From 87ef48b50b3daa51efd5c6c79bd7fdc9acd81027 Mon Sep 17 00:00:00 2001 From: David Capello Date: Tue, 19 Apr 2016 13:45:23 -0300 Subject: [PATCH] Improve status bar with icons/automatically generated and re-used parts (fix #752) --- data/skins/default/sheet.png | Bin 13776 -> 14090 bytes data/skins/default/skin.xml | 9 + src/app/tools/controllers.h | 10 +- src/app/ui/editor/moving_cel_state.cpp | 4 +- src/app/ui/editor/moving_pixels_state.cpp | 4 +- src/app/ui/editor/standby_state.cpp | 20 +- src/app/ui/status_bar.cpp | 473 +++++++++++++++------- src/app/ui/status_bar.h | 18 +- src/app/ui/timeline.cpp | 4 +- 9 files changed, 371 insertions(+), 171 deletions(-) diff --git a/data/skins/default/sheet.png b/data/skins/default/sheet.png index b2628d8756de5e89135f3240a6a0683db080925a..150ff3d5183223b4cac9f482aa6cd42965870e04 100644 GIT binary patch literal 14090 zcmXwA1yEZ}v<}i1Elz>x*QB)6yWV@(z|s7kQ=%LhnT z*t}1oL0S1{Fbb%nt7_B|N5}PFq2s7k$Otmk#L<;Ez)j05il!HT{{a_SxBFhA8$;sp z4eCdnALY7+hT4WRhEI0ezU*W?KiX7uK&m$$`vYZ~0CB#itj%S5>qSHtk^K5|;0WbV zC$#eo%2=M`n>QxomxE@txww;a9B+yoA0G4eUIA!m9?zfFbd0j7L>`IIr~%@PZO~eX z33qzZBuA=}{pZianEL74een*yd+~CLP+*(On|IYm`*(22h{=$Wm@0t}jk6szqd0AR zr`WgS!ab?q+u>8)57IoB#(NPsTimz!IYyQ&`(v$J!1*GDhuYo&BDyeA8K8y}0OzFd@2_U6ff(4s0##q=9C+}r7*r$^z8mr zoA4(pauHET_<8f)t$k<5yw+CMyhr$p#gZ3omS7!rH>`e;_uWwyrr>{%+EpicN9|(k z6l#j|XBrep3KU4&#?`7VwcQWxUJ^%%LeNWUO<)L1amxQE7$67@VS<eP0V&0RH zBYezvRJ=Exbyv1A%UuYKSg_xw7iO4upMv0*wmL&(@Khs-ae;clT(rD`dGBS&J~-R};=xqOM7PwU9rF zYc4wMbR%2%h-JkrDY7C<7SM(rr<9joHlJ#qd=XosP;!dPq z=)JxF!E9wh$H%cuc-ddy(=~rmi}EG;o@(5D7O908K%?;TWd=6Xq69cDYh~8c z#U8m0&RG)zbs{H(NB_Czt8*Nb06Z(IOM}Dj8@hC-Qb@(> zIhsW$msyF{V-XjhN;=?647E_(wYbdYkK}IlTmT;{Z275%(DLKhsUa$6lre z-iHy8`o=SC%Ep9%Eu-U5UB_n*<$L3cqpU7&8gD$3oOGT-F{D_A;S6|xUL=5sSz`;5kFjHdn!9xBZIaOhsG1N_K8yL!}KQY9O-+&>95G~ zSs;??=$8T+h@rrQM!({{Ps=|;q>xbdhL-kUY2>bzH~OYzA$8*^Mh>s{LA~mH=%Ji^ z)`JygHtBuC>6962L)*ERCmVlQjZh79;(XKzii|Qs-i!0322d-HlA_o#=z(jUJ+D%$ z5D{uzE_;g=#fp>UWbKbvOWrqu_kcb`xPL$Tr7qg}uHw)vBcp(4c01Q0$g^LjT(Ke$ zSnus$V^T@%COc3d90NCvcX)>E^Vs_2&cru!$&$Z1q|T+c4SmFrK$yPA$?D2`F9$~O z-Bgi?7`{gctz5!s|tc-&`ZY6 zXYJ0LpIjyc`%6ICPaJL1V&FZhpC#(@`}TmkKlHkkwVVdb5^DciF(ZtKhxM(am}Pql zj-!~&oW~mZIAdO62~Je!-fHn##bQ+G*7{E;&dV%P?gpi` zYvmVIw$=64kL58)*D>xiF95&1!LWj8`7uKpol*IFaKAi{m|HvZY!gluM`H|(!v#+A z3t;)wg3Ktbb4tu${34#|)W`<$O02Q<9J!)?&B+(4{Qc6qOLtq_(ICDkT=dMAk!8TF z_5-Pqhl`5~>stBXw(T&KN4&2ks90UHrFx2i8gJq~2hi?F9@ynVrrLE1Kk6l+a{q8V zou&Lc>+WFK?_idVT+r#mi?JcAlu&BpWAU9MgU{%IEvvu{2{oXT#_R#<`pHkvaL?xO zQoC1!r-V+yrWQiT-_n^`@R}hO@0#-Yv7>cu2j+Z?uW)%&vlbvNUF1Acckqz(h;hx3 zK*x3LvG8elL1<*lnbR^{eBJ0wfu&3AYNnT1Az>4md}GAuwcJ*XaySs<`)kpp7NSNi zU1zYQy25NVe-O;po{_73GdO{q><2N=N=bxONi63+Tpt~@p%sPd#A@kUR-?%g=CJ0R zSOaq~Ee)mC-&0Fs5J1-pXUyHW(AGaJEH4u})V8!R{^)mi2w0f@}YIsN9RpH3$=DT#ggn1d+$H*Cd8-u|yBZ#XkY$-*nK z>U*UPf+XAW6kkv*t1YKeOMUD^y`6A^tL*efwz#W>5t&{>V>#^MIyuHojl2LdY%9#@ zC#1_~_8%>{g)TQYeCCuKF@|4qd>=^|5*3!lzN`1!wiv)i;kg8ZNbjDscS+uO^+7>!BgR_%*< z0a4I^4u;&tP`+Obc}P!@4jUt#UhDhGQmQ~dEJO@oBX9P(VgHW!X?BB-$!p<2mD-F^ zt0wy6=$-h_^pa>TXu&$v33N=$I(4MBb}?f+E_q>jYE6?bz(~`a2N3MbEpvSI5LCwAmvJHma-FZRFc<^f4$ z;4nBG%W{T1M?SR4c=3!*9ZG zN*JV>ic+ORAlbpsH%mi^h)9JoY6p$pqkD5<;HmsLXUJsy@1-W(>fbt*6va^CzDAM` z)CSuLyrA419Rtk9+I~hi^nl zVva;8OhAjaEeMeHk7kJ_8f=YnnQ}V8ft2*RHYC-fgtEnD9Y|NHm1otWy_`N3QOs|J zD8V7#&&e&vSX1=DR`HnnJcC@`JHafB#veMj!YFVeP19m-0|{9s8SM9$hIp(y?5IV> zBm48UtYF6c-WKG64mRVQ%5UuDYvB>0+I)m37@gLVAu=)Il;euV+e*gw2SqFb%Duxa z9mm?$98Y{c+i5NkJvPn$GdGEdPsW%G7>df>HyJEDxH&}xHMa3p6QxF-DZoA(l^EJr6&%h1EQ!STD?uPty_1>UV||8 z0zS@OiP@_AQp|Er`$4Vy{@k3-%h8IIIFPikXL-Ay0jisoHo z1M5y5S0Va*`?f6n7^^oiWHF6VWwQN^6`#+dBH}eY_LWl0fhepHE~Y2Jp_j%vFsc-J zCPgbVx4Iyl;`ehGvlZ@uRW_^NqSVdnDWuLP9k|KxO)(5#n{&%&s#B6G1&Z&a&tg&` zOk8W5m>G)_>PKxQK-rc>EOUV2bTy9^dr~>QJTy(-$Wmxa!%C3z=in&AlQsTHKJ-UU zK0IT_o}a*bmvjm^bhRSTAAdMt@O`O)Ls5j)igVeQTu@rB_Q&NT(INVr`rkA2mGESY zNNtb#jIT`xYjntg4wU&RjtbKTE^k3Jr6)^*h+|F?4Hxgb-@3Nlwj|o#k&*UTqiptH zR@mJ1-0VeH*0!13e^a7Peu4<})s8WgVpw!V4fp=+gs>3^Bei^f(VTk%Gr#{ho<+3d zp`xknTO5J*s-xgjIQ((HQsg$sI(B$TQ7_8e)dQav1Ajp)*C1-&7xIL(q%Ps&fgmU!LwBB;5U- zUwQ!@HDoV{7gTcoWY3?usCoPa5pzUF5!=WzRm}&S0G9V{K8`^re>9DB*y1KXq$@ud zJfuIX_YYro#V~`5U*0HLI@Wd&=sF|2PkdnulS04@>6F2@h}&4qJ_0L5H}OfcToY!f z6mRxPs;o@B%=Hg7#FD<||5A7KBYY}O#tspg%VSsl-*~M0wGFkfmyWQMA(##$fYXGP zAi{-Udq>tW;RwW53H(r}`|wBL_zl4KbYce}j-65Nd|tdCDr3`vGom9ORP%5UG~GZ_ zZ0D?c^U1MmWu9r;!=a1%{I|;s(Enx7BVf+>uG&piMx#`D;7@{0a2STVBKw4GBriw- z+g~GbHaLfry~QM3#D%ztECF-Lm9kh_hp&>Fraz)&zhMBeJ&3TV{b}*)MZ4;xQ%JP^ zXi>*JA}M+rP%^=72rbUFChDc+aiTel?dz-Dh8dz0_(} z#Gaq~nH7wMt6QTSj|INO5Hi}$#ru>_8Lr#giq^|v-c;EN;rct#{gqRu zR!G#1o*}=C->W~p(-9+(@Aj{2Z!u@hyc-o*zP?JKD;blxd^H_eu;AzuN~DeDKP^Qu zi;3aPAgYd+x6fBUo*j-{IECEglrp&;5{&rKi_-9l?xHI&vX<9EOGGro4|FD4oyxer zi2nFKy8yVx(D^=cI3O;jlN0tEyVtX#-?!xS9h_fG5bT5c9rFK2YR z_p!^7^?g54aaqt!w^{ECVnk0UmGYhzevcYDZ+Z^_4lkBp5tE&*?cb| zqqIGhYLhH&Tm6Am?_h-RxgZFKMA{DH@7E?w-PC9VXbuef57)g8P8I5M(Ys<1_Uyu4 zYn1V6HV!-S>%0+3U4CE4IJoso`J{X}!L0{R9K`9Mp{cx2aQ14@yIu`}?a>0_vN$+tx`dXnuhJG@fq@S(0w&02`iZPYfnov-950Tokcy8xkyJ z$aA2~ZEcxlw6{GGRvlan10AKilXjR`_7C<)Ae*%+^=Lj+?_ZkkW!^8$z#4&tEH6mt z#E<9BMP-DnsT~Zwzg#@1)0Eqy^lAb`C%pU~K8SX~I6Y^`9kjUCe8~9Y(u^~UvyF|4vZgNs;Z=MXubvu_E&Qj`h7kY%9M(v?p^Au zcIe!r$4Xq}S|?^hfvN;MsqZIb8y)nUq;@CTd_(m_aNIv+#0Yq z2Ns<*F4Hd={8#vuN4GMxqFf~7OW*BSoM4qPGgHif+!nJ&B_Vl579m%aZr z7Zn~A3jtm9`6(w~s7|Qf1QOBEZ2al88+pvWU3bZiBsS(Ke%0QOaf)BT6e5y(`Z%`d zTl%#3&Ip@(8v^-kkySfig@sjs>#B-QeeFZ{&|su4Oe5<_`s?jn1qs7jTP4RfddlSljHf85^r&4uPb zd{$e~0?$C;xuS6wIgM)-=3w9eXZ&Evw(sThCy9_X&)bQnciI4_>X562>`%=I{YRmJ3nyn0gtXX43P}=_*iCT-rc|)8~|m; z;XuD#+XtHUdc*dn$WVs<&VIEAVKnOVO2_YOKzRiJ^EI_;xS-rnDAGx7yEP-e-Fdf_@HTKe?qe(1{c4R#DY`VaRxS;p=H`Iq1$FRvrX92 zfCKz_*cI^Y76B9HwcI?TMh-NtvI;2FeV^S`TPJb$^;{BbM1vFxeS?Q*8X}M2YV=^P z`v$tIw;sghjLNkh(e|0cC6ZxFl3`Cxl~V~m-GMXg^b_Y2*L?ki5v{i=^a}Vn8=(G> zerDhgmL`dwKt6E`mvII{VD?Vlo%WVy@*0AkW|&Bj)ZQA7TZfa@K)3*p-*7Y9P4uZI z6vhnm4^Ci`3xpKapdZvU{}Ikh&jPnRf-md)L3ZL2LUN4RP+vrl2Sdh>27H+B3b z-`d>>DmoNtU=5`1je2#pVBaQNi~(i`k8Dlaa;7WSKv=cZKahSHFIkg&Jvk*k62z>x zN;3S;Ody(0PdZ|XaV86ObXiIz<2qerw1PcY4!FEUOlUxt1!dDa#hSI{$mG$W_T~HU5E(8UL#qp zpJf`Ef1lmJZ*AJ)Z2e;gM&e^N_39e_H-l+7CO{r&LR#>?RFXotZh{9v^H16HvmE{| z&ej4l!grhdKYkCmMKh$zPo_g3wc`2Ov5SN3qOcvYQmb@LMgU!yHyuY_{XcTzgf zqh~VHTUvV9+b?*ob9kNz^zp+FP-;GX@9#pW9)2aprB!Z#v%cw-G|TP<8g-K%v)so^ zb_l;#?S31pA*X9?f-AKix9zvA{lwz3YRFb2lT2>z%k_Wn2Q9(g<)VMfR%%w^V<{GA z2XlK%b(iL9R|F)xapd(bscPRnltIsLDBZsmAZB5w<~?d_C~e0$K?)BOJ=3Fo`A#%} zF;xC15wJ<~>h1-O$eWoA)?fssPI#@I4-5!GQrq*yR6x-C9jl3I65YA~lcyN{K}udE zc*IOQKc*`goXLDNFlbAtjT#m+I0-+IyD`9S!cnqrF%T9#HDBTjur~#7UwBz2N~?(b z?G0mF|81XNw=`fUtYdYEOeT(Yb;Z$C4KnzcSw3K6bGSiQvKb^CW2Nb8K?+89C%637 z&G>N9cXb1V8pyoGV+qgl@I)8}#fr>DH!t5Cl6CB#6?D9_z=~*LGlFlO=SN{bAxM!# zJRh8EhmGX4r^rB5vuJpVawj&Q(X6goIvH~aH}Mu@T)kC}Dab{Dz1lQ|YWJt~HaKhL64rS%ZIWxY<{fe+I zjqh71(umKZ`JZA1F>A>YtYiDMXb6KBl-AanG)7K@H()RkN`j;vk=C?%n2rt zYufwQXn1fIIp-c1#34dynwL_`!ZDQ(q-VCXv0d9bECO+oXxg z5u?7GEmm<-q~;eG~G9O*VNbA}TE4BDGm z;I<~e@6~sC1`U=$FFKPJWp~u`*1I{WSP#nl_dZj=Cj@ozm5|bYnvkWNodnd+@XKo- z1DsKe8c?T`8ok$X@+HJngbAIaVnO?iKgE%RZ*2?5#Ct26WZGV0s@LgHiliW#{6e63CakKax z(r~cN%!TsH)sasq_W8Ryr`N~1S_d;#1RVTY>|+rL`Frn^GhHY4SXuoKp;`6hJoWpv zpZ%*x#ITCg6+|%eybsnni+wp|?>sv#Sl-mfhRaeq&}Iiek7PWh>@(JLK8{-qdO{H4 z_P-?KbmYeWg!i_m*I45I-txC9g-(|VA^}^a=flka0Eqkls|6T=B7|=QpnPj8v^(#klyVy#7-tRcM77rbGboebR(RbazRk$^R+#3y;4uyuPN@u^ef$jmsF`{qh~8lP5W7( z^*(hM1Q8?rXZAQddNZ{I;s^C>i+*y~;$$q-?_6 zh8e|o#m6Vg4(77y~bXurc4S)xt1SJ0wgnx$^{KCX3|CQ`4UgqnP!m5kpI$5nIlrbcoTy zPJaOa1kH^CG$SHn0=E~wD@gEYU3x56_O0>#(cp;Cf*y1bUv>OnG{%hMFR)Ago$qJS z&+;5~b9%2b#&`0o*aF&JI){Yz6WCHP^e<9$Rh@h85638cPsjaYa&n%k#geWKpBMC- zuS$;J8m2x){N?d(s*{focUzvW*dm+rrlrdL29Qiu5<>lJh3fNNX^=DO-F~k-=b!81 zYk#%}gxwG6FuEe#;5EQ8k89y2vm$4E{P}0K5bNE5|GXV>y$P4H2i8B+5y?JOm-FAc z6Vsj0FcM+}*Amycp?>9%V;J&{?@-DvN%_-!@#yU{?v=wDy|yOowHT2+z%%G^tb@UhN4@LxCv z2eecextN9`BW&i}xOu_e>S@xl%P_!(kMaxraN6lZKRm={563Rs6ViDNi#^Bwob+dw z*Y&q$WftZq!U?k;Ta{@~$i5fL^9>8hes~JI26g_-7ZFzVGd-ELYX_QX2VhQ{@MthD z^00x9+j}flNN?YDfVbFft9)=+3Mk80x*RIPBKjSi+`&GaN3-$+HlT(6=P#;as1%)m zoMFO{9i*ALFKUEi)H-P9x&{~TE-1Vf#A(Eys(qIjRg)VTgFimJ(9W|}dC0ObGH&iu zneXVsfJIy(xS79oE|-{ntli0)S6i+eyf;P3D5qy*YZp0fLSSnA1w6H|`mi`R)MaTF zwTTTc9t8dLY`zEh-s6H1bqgtupu?FL(7ZHt10t{6+MidFJfsybCi7ZZpk*N6IWhQ+ zfjA64_!a+!;UjKR*sDJb*uNETLrPl}bo5H6_0;6qh6Xy1$Wkh3<|-^jyP*BLW!&pA{%35KaEG2z1jE# zSsKG2L)wws?ls;}4qL;Nmfgdnkv)QN%9aD6$-Mq!XXgK(3s{R(93FuVWyG;1a7+d- z#n%daQOM{C^UXkCzviq}W zK<1);O?LfoXO-bcte(mq*RSmyV^5L>f81g3#KTOy5ZF_Tc?W?|bDZxzp*&y8GzsF^ z0gbi?-&xFlSUE~MCf|ea_ZQuIaF@w0iy>-LhX`_{`8oEhLWRMDn@xA3f=*m+WI1+I zoMqR$d^0^Tznb|GO2SVQAMMwT?P3ML+m5YC$)s>u8(-uN!v`WCf^WYQmW_w|xgZFg zNP|wsQUP`XB5gq6tCBtDrJ|pVVv75c%|J2md73XM0aY^Wrx!PKrdv|YtJ?snSuAk9K)p7O)~&cKDQI-Bv7a2O{H&?6IO}FMn`z8I zU0L@|_cxpuRDK9ri#+qwBo~3va&1D1;uk-0;!fy!FlPn@wCL^%mlTlhP926#X3+$z z=`Wy8WY8E{t85J`a1rj;OguuXm9yolD zFkVfTnj6d2Aky_EHJK4t*uD{u)|!&`TG^_c_LUxUlZY7R?EXK)UhkdblXFnHX}X`p zdst6~&CG)dHmcI%8w~Ku8$M?09NjKiP_=HXblZ&{(3-XxXXG2A^3MB`gNpgk=fD2W zbT2z|+9bgy@tLqlBznUvI4G2wnSF;rK=j@wGYBJEk71@MvQD-bK0c&lqxB`iU2Gum z)d-4V1^gQ2OXqT4*epWEB}>i&T`tBipRfpC+!>@vF7RUK&lAv3B=~7j3$stznXR@# zxO}wuO{a@YM1qFKzwKnN`I*>1cU&ytoZpCS6;ss}zlXlO zDd0tk#x#veZf*Uf)v;YtaX%*o*owLF@O${`*zh`J4`m4^x_`=DOd<~3TnQ3;bNY1n zR1J7!pY$^SP`&q|^DyN@(h2RASu`1Xg1J7a4Zm1z=9R+$?G8+zN+3)>xYR83Kd81XkQr? zW-apPcPVqNdnDM337eKQ-nwtCU)yt-pY&ig!h{qOQt?W_0*&plLn)T^T)QzNgK_7! z_gVLTQ*KUo=%jBXX?E67bDUd-)wNeiw)Dz;s$>505>+hoOWwVZ`$+PQuKwsrvE)(5 zWofCbv5CK4r5E@_21F;x)5o}MKUs+|p*=3xQZ0m*D9so5>= ztFRPD#&iwi=+J19V#m%MY$jvFec#o%4eCuZZQ*pOhRfO5jZLGy#h_Osv8tjs{Z_2` zjbroog=QW1n;dNvS!Z(wE|{=yk5?4ing6|lv^?9S`e`^*#%_LI_Q9+JOcOlBd&A-S zIgdW%)6DLy%`4&x(I(c+P1XR9h9moTuk3{HTFPu*Df?FKPn{lVRSO&OkR zjFaWqJ@aJAlJk>gwE1S^E;npJ%HLH*{f)ya#H#_fv3!Td#F8R9Q_q&veJ;CeV$kw` zw>KtKut$o3sgS4O{T6qWJ8|)+8GWsII6Zq_{!s?Wg!yS-!tAgVNGpS2B`p}w&g zi}6b>^)f9@=8N9^oRR`>vjQY~#Anr=wOX&b8N!7^N^k#Fg1=WFKy)o~!T#F0wDxkO z)LaZTCnjpCCYEq@tf`*Sqh?7Kjefs++N9HoLAc|=w36U{SH{@VB(2tr3_I$MOpkcF z=Kb&;3!Zof1S02sh9~n`5&?sZqVqnIdUSq?heY3(S+th+nPNDdur)Qk7SD$)cQK#Oy2!q@Yn*PQa z#Cokm1vc$la67>x5}tB+s_nQoJ=@&5W&{O-KT2hC1{bxs9e@$1U`q>h^bh#kKeAbG zQ$!^p+%6n$W#bn` zb}d&XB+B%lEnjQ&FTN^($=17ZRSMPa{C-ZmZvb&=bVRKO&i~TsyNFU0gXVinwAvD) z%QMH*$ZFU-|E=`BaU_xFGsh2|*M44-A(d*XDI=x-42(=TxJVbmmQ1U)UUi zXmy{dr$2{i5ffLqGm5YtFoR)yvEV!?UG)lXh6P9a=}(i4&}BON(4VPr-+_Z7J>phd zZ>%zC;TS5^M=yh=T6iF2T4a+9{3&hQtrk)#Sk=PyUwwP$ZT_6sWk#7}qVl%mh#i8b z9Wnj%zY_~2%6a^5I8gkzm6pmvClP{!r$v;;Rp?c^<2bCu50i>fxc^M)oXE)@Of|py zG2(4fRfb$`rmSI7`AGY(MG?Au>0d2p5!OYEfDiY#0_)f5*a1O|3fD#*M=qH__Ow?T zNNt=Xw7DUZ)~lcqJleH>vv|k6t+4nmBVs_~Fh1sI{9k#ePhUoDV}Wu>_mra=BjSYB zUh{M>^P|1M!OWnKG4@hu62K)y6;Tnv6ZvV=OH1Ad-RJOet6_ge1WisI)#5e(23h=Q zXdI!mAn|5AV)14^VqJ=*#+A;ujG6T(g-rzg6ADqpz5jkRfCwh1TtOsO6gGu}d_*hI zDIGauz_*AoLFe0hE_(aV*oE!*0nkB(q8dgNEZ}uvhu%1;M#@`i?x>J!!_r#r$co8Q4oX0x{Co^fkG$}K zq?@M8F|wHeTfIW`MCj0cUQ#1w2D?Gr!zEv>W1JWdHyk|bw2IoPViPfhGAwj;gQy_? z^kZU8?s?fQK4+j6KYVMR+3cYTCg$H$91a_OOpnjI(E+Iw!^=J=y+7g7e$F8~rb_Ja z)=d7)slAC6I48ggxd~%{h%WG;$eqyIOgoBe`A8P-lc_lq#32`rg;1$c5yy8_54+hD zaXqJ?`aUlk8BW*#1a|%Etp09k`Z`RQFBEV%EvoKbGSm1Hu_X%l8$J+2wuTdAAa}Jj z7FOyp{3KQm=b;YxS_=iqr!7wveFL`nckRnMNn}ntY!(A z5uom*mmj=m%;E9uo=vdd`{tCv)XGR%6W7P$L9fmaGWJ~e-3U}mG&gpRm;5R$kT0t0 z?7DFOHElttvDLkvp$xM7LX4R&4X*(FpR6dTl_h4oplkj0>ny}g4X~wHilXAiEkUsD z*n+Jp5SmZ)ofNy+4gD%3+0TAaMLqwF79dtn{=gM5XYfmUv*Dej;F056r(sPO?7_Xq zPdHonXh0GCzHY|zl5Dn3aq-F4fr)@-gU-7#WTvM1w|sbG+e4Fj(#M^V5Cu4x4q&=zw-9lk7OKo z!cRL3Qkn+QbTPnzvSniWdr+}IuD}2RI@K$oh^A9w@Y^ZwU%j!|hoI){@Kk`4z7U|g@KyORLJ{I~&KJ*gMc#=q9YvwJfgrYMI;qOiWiE-k#k1=A z(SAUyj`3-TtrrqQw3V=#D6t4jg}B$UNqAC@@idY!ll)$q_x5lN&b8yVBhn zU3cr|{^xKwplFNmoe~K064XOfT^~tdL@C&mTZ?p}wh|Q-s^a}@vHDbJ#LH;?f^w((* zHC2-OHOxx`oW#4|3wBfF&Z&^RT+W*O)Mh7>7Bhxo4-B`oD@C`SjLy^k%@v*hAmXFj z_>1=7f2CBRazi!Hba#3ldW&d)0I}64+Go$XHUucFRuy_^q9RiKc-uB8ExE8`-nCUb zuGfqF8?n$zHrWfd2W7E3azEVe7W?|yu{5hbXFE^qZo3@6dnSN*=l+ur67StBA8c%c zH{3dri`VHnGmFjajL(|-r4u?91n)s727Ih5nX3$p(SLmV&!5XHV&Bdaz%|c1mN|k1 zr)9lnld+dCe3;HuZx_U#1bla1kY4tYB4J0`?q)pMDl&;>T>n`%6ZdPRdw#r*ko-7b z{mvob730M0odqwy(rntBwK_x6 z`(pi0^`GeDP}ePqv9Ct`3e+wrj`U-Sx@38nPBij;6u#tMxrVK%mvskWcSZf0);8NA zx>_EXJnqM)1b}M)#EUN8R91H8+llaZw@}jF5&2J(+g$MQ&9m-vy&W0ur}G!2yup-m V#hjsa#DClX3Nk9vRgxxw{{u1)^JM@4 literal 13776 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 VZu*0d`ll8^NlsO^T-qe){{i^#Wyt^l diff --git a/data/skins/default/skin.xml b/data/skins/default/skin.xml index 617269e4d..5ab0a8869 100644 --- a/data/skins/default/skin.xml +++ b/data/skins/default/skin.xml @@ -400,6 +400,15 @@ + + + + + + + + + diff --git a/src/app/tools/controllers.h b/src/app/tools/controllers.h index 35bab4bed..4cbca8a75 100644 --- a/src/app/tools/controllers.h +++ b/src/app/tools/controllers.h @@ -81,7 +81,7 @@ public: return; char buf[1024]; - sprintf(buf, "Start %3d %3d End %3d %3d", + sprintf(buf, ":start: %3d %3d :end: %3d %3d", stroke.firstPoint().x, stroke.firstPoint().y, stroke.lastPoint().x, @@ -202,7 +202,7 @@ public: return; char buf[1024]; - sprintf(buf, "Start %3d %3d End %3d %3d (Size %3d %3d) Angle %.1f", + sprintf(buf, ":start: %3d %3d :end: %3d %3d :size: %3d %3d :angle: %.1f", stroke[0].x, stroke[0].y, stroke[1].x, stroke[1].y, ABS(stroke[1].x-stroke[0].x)+1, @@ -264,7 +264,7 @@ public: return; char buf[1024]; - sprintf(buf, "Start %3d %3d End %3d %3d", + sprintf(buf, ":start: %3d %3d :end: %3d %3d", stroke.firstPoint().x, stroke.firstPoint().y, stroke.lastPoint().x, @@ -303,7 +303,7 @@ public: return; char buf[1024]; - sprintf(buf, "Pos %3d %3d", stroke[0].x, stroke[0].y); + sprintf(buf, ":pos: %3d %3d", stroke[0].x, stroke[0].y); text = buf; } @@ -358,7 +358,7 @@ public: return; char buf[1024]; - sprintf(buf, "Start %3d %3d End %3d %3d (%3d %3d - %3d %3d)", + sprintf(buf, ":start: %3d %3d :end: %3d %3d (%3d %3d - %3d %3d)", stroke[0].x, stroke[0].y, stroke[3].x, stroke[3].y, stroke[1].x, stroke[1].y, diff --git a/src/app/ui/editor/moving_cel_state.cpp b/src/app/ui/editor/moving_cel_state.cpp index 65cbf8edf..ffbc33e25 100644 --- a/src/app/ui/editor/moving_cel_state.cpp +++ b/src/app/ui/editor/moving_cel_state.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2001-2015 David Capello +// Copyright (C) 2001-2016 David Capello // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as @@ -163,7 +163,7 @@ bool MovingCelState::onUpdateStatusBar(Editor* editor) { StatusBar::instance()->setStatusText (0, - "Pos %3d %3d Offset %3d %3d", + ":pos: %3d %3d :offset: %3d %3d", (int)m_cursorStart.x, (int)m_cursorStart.y, (int)m_celOffset.x, diff --git a/src/app/ui/editor/moving_pixels_state.cpp b/src/app/ui/editor/moving_pixels_state.cpp index 0be8360c2..c214e96b9 100644 --- a/src/app/ui/editor/moving_pixels_state.cpp +++ b/src/app/ui/editor/moving_pixels_state.cpp @@ -437,10 +437,10 @@ bool MovingPixelsState::onUpdateStatusBar(Editor* editor) gfx::Size imageSize = m_pixelsMovement->getInitialImageSize(); StatusBar::instance()->setStatusText - (100, "Moving Pixels - Pos %d %d, Size %d %d, Orig: %3d %3d (%.02f%% %.02f%%), Angle %.1f", + (100, "Moving Pixels: :pos: %d %d :size: %3d %3d :selsize: %d %d [%.02f%% %.02f%%] :angle: %.1f", transform.bounds().x, transform.bounds().y, - transform.bounds().w, transform.bounds().h, imageSize.w, imageSize.h, + transform.bounds().w, transform.bounds().h, (double)transform.bounds().w*100.0/imageSize.w, (double)transform.bounds().h*100.0/imageSize.h, 180.0 * transform.angle() / PI); diff --git a/src/app/ui/editor/standby_state.cpp b/src/app/ui/editor/standby_state.cpp index 1244198f1..4f4b348d8 100644 --- a/src/app/ui/editor/standby_state.cpp +++ b/src/app/ui/editor/standby_state.cpp @@ -445,7 +445,7 @@ bool StandbyState::onUpdateStatusBar(Editor* editor) cmd.pickSample(editor->getSite(), spritePos, color); char buf[256]; - sprintf(buf, "- Pos %d %d", spritePos.x, spritePos.y); + sprintf(buf, " :pos: %d %d", spritePos.x, spritePos.y); StatusBar::instance()->showColor(0, buf, color); } @@ -454,13 +454,21 @@ bool StandbyState::onUpdateStatusBar(Editor* editor) (editor->document()->isMaskVisible() ? editor->document()->mask(): NULL); - StatusBar::instance()->setStatusText(0, - "Pos %d %d, Size %d %d, Frame %d [%d msecs]", + char buf[1024]; + sprintf( + buf, ":pos: %d %d :%s: %d %d", spritePos.x, spritePos.y, + (mask ? "selsize": "size"), (mask ? mask->bounds().w: sprite->width()), - (mask ? mask->bounds().h: sprite->height()), - editor->frame()+1, - sprite->frameDuration(editor->frame())); + (mask ? mask->bounds().h: sprite->height())); + if (sprite->totalFrames() > 1) { + sprintf( + buf+strlen(buf), " :frame: %d :clock: %d", + editor->frame()+1, + sprite->frameDuration(editor->frame())); + } + + StatusBar::instance()->setStatusText(0, buf); } return true; diff --git a/src/app/ui/status_bar.cpp b/src/app/ui/status_bar.cpp index 62951eed9..bf836f67d 100644 --- a/src/app/ui/status_bar.cpp +++ b/src/app/ui/status_bar.cpp @@ -45,9 +45,11 @@ #include "ui/ui.h" #include +#include #include #include #include +#include namespace app { @@ -56,6 +58,313 @@ using namespace gfx; using namespace ui; using namespace doc; +class StatusBar::Indicators : public HBox { + + class Indicator : public Widget { + public: + enum IndicatorType { + kText, + kIcon, + kColor + }; + Indicator(IndicatorType type) : m_type(type) { } + IndicatorType indicatorType() const { return m_type; } + private: + IndicatorType m_type; + }; + + class TextIndicator : public Indicator { + public: + TextIndicator(const char* text) : Indicator(kText) { + updateIndicator(text); + } + + void updateIndicator(const char* text) { + if (this->text() == text) + return; + + setText(text); + + if (minSize().w > textSize().w*2) + setMinSize(textSize()); + else + setMinSize(minSize().createUnion(textSize())); + } + + private: + void onPaint(ui::PaintEvent& ev) override { + SkinTheme* theme = static_cast(this->theme()); + gfx::Color textColor = theme->colors.statusBarText(); + Rect rc = clientBounds(); + Graphics* g = ev.graphics(); + + g->fillRect(bgColor(), rc); + if (textLength() > 0) { + g->drawString(text(), textColor, ColorNone, + Point(rc.x, rc.y + rc.h/2 - font()->height()/2)); + } + } + }; + + class IconIndicator : public Indicator { + public: + IconIndicator(she::Surface* icon, bool colored) + : Indicator(kIcon) + , m_icon(nullptr) + , m_colored(colored) { + updateIndicator(icon, colored); + } + + void updateIndicator(she::Surface* icon, bool colored) { + if (m_icon == icon && m_colored == colored) + return; + + ASSERT(icon); + + m_icon = icon; + m_colored = colored; + setMinSize(minSize().createUnion(Size(m_icon->width(), + m_icon->height()))); + } + + private: + void onPaint(ui::PaintEvent& ev) override { + SkinTheme* theme = static_cast(this->theme()); + gfx::Color textColor = theme->colors.statusBarText(); + Rect rc = clientBounds(); + Graphics* g = ev.graphics(); + + g->fillRect(bgColor(), rc); + if (m_colored) + g->drawColoredRgbaSurface( + m_icon, textColor, + rc.x, rc.y + rc.h/2 - m_icon->height()/2); + else + g->drawRgbaSurface( + m_icon, + rc.x, rc.y + rc.h/2 - m_icon->height()/2); + } + + she::Surface* m_icon; + bool m_colored; + }; + + class ColorIndicator : public Indicator { + public: + ColorIndicator(const app::Color& color) + : Indicator(kColor) + , m_color(Color::fromMask()) { + updateIndicator(color, true); + } + + void updateIndicator(const app::Color& color, bool first = false) { + if (m_color == color && !first) + return; + + m_color = color; + setMinSize(minSize().createUnion(Size(32*guiscale(), 1))); + } + + private: + void onPaint(ui::PaintEvent& ev) override { + SkinTheme* theme = static_cast(this->theme()); + Rect rc = clientBounds(); + Graphics* g = ev.graphics(); + + g->fillRect(bgColor(), rc); + draw_color_button( + g, Rect(rc.x, rc.y, 32*guiscale(), rc.h), + m_color, + (doc::ColorMode)app_get_current_pixel_format(), false, false); + } + + app::Color m_color; + }; + +public: + + Indicators() { + } + + void startIndicators() { + m_iterator = m_indicators.begin(); + } + + void endIndicators() { + removeAllNextIndicators(); + layout(); + } + + void addTextIndicator(const char* text) { + // Re-use indicator + if (m_iterator != m_indicators.end()) { + if ((*m_iterator)->indicatorType() == Indicator::kText) { + static_cast(*m_iterator) + ->updateIndicator(text); + ++m_iterator; + return; + } + else + removeAllNextIndicators(); + } + + auto indicator = new TextIndicator(text); + m_indicators.push_back(indicator); + m_iterator = m_indicators.end(); + addChild(indicator); + } + + void addIconIndicator(she::Surface* icon, bool colored) { + if (m_iterator != m_indicators.end()) { + if ((*m_iterator)->indicatorType() == Indicator::kIcon) { + static_cast(*m_iterator) + ->updateIndicator(icon, colored); + ++m_iterator; + return; + } + else + removeAllNextIndicators(); + } + + auto indicator = new IconIndicator(icon, colored); + m_indicators.push_back(indicator); + m_iterator = m_indicators.end(); + addChild(indicator); + } + + void addColorIndicator(const app::Color& color) { + if (m_iterator != m_indicators.end()) { + if ((*m_iterator)->indicatorType() == Indicator::kColor) { + static_cast(*m_iterator) + ->updateIndicator(color); + ++m_iterator; + return; + } + else + removeAllNextIndicators(); + } + + auto indicator = new ColorIndicator(color); + m_indicators.push_back(indicator); + m_iterator = m_indicators.end(); + addChild(indicator); + } + +private: + void removeAllNextIndicators() { + auto it = m_iterator; + auto end = m_indicators.end(); + for (; it != end; ++it) { + auto indicator = *it; + removeChild(indicator); + delete indicator; + } + m_indicators.erase(m_iterator, end); + } + + std::vector m_indicators; + std::vector::iterator m_iterator; +}; + +class StatusBar::IndicatorsGeneration { +public: + IndicatorsGeneration(StatusBar::Indicators* indicators) + : m_indicators(indicators) { + m_indicators->startIndicators(); + } + + ~IndicatorsGeneration() { + m_indicators->endIndicators(); + } + + IndicatorsGeneration& add(const char* text) { + auto theme = SkinTheme::instance(); + + for (auto i = text; *i; ) { + // Icon + if (*i == ':' && (i == text || *(i-1) == ' ')) { + const char* j = i+1; + for (; *j; ++j) { + if (*j == ':') + break; + } + + if (*(j+1) == 0 || *(j+1) == ' ') { + if (i != text) { + // Here i is ':' and i-1 is a whitespace ' ' + m_indicators->addTextIndicator(std::string(text, i-1).c_str()); + } + + auto part = theme->getPartById("icon_" + std::string(i+1, j)); + if (part) + add(part.get(), true); + + text = i = (*(j+1) == ' ' ? j+2: j+1); + } + } + else + ++i; + } + + if (*text != 0) + m_indicators->addTextIndicator(text); + + return *this; + } + + IndicatorsGeneration& add(she::Surface* icon, bool colored) { + if (icon) + m_indicators->addIconIndicator(icon, colored); + return *this; + } + + IndicatorsGeneration& add(const skin::SkinPart* part, bool colored) { + return add(part->bitmap(0), colored); + } + + IndicatorsGeneration& add(const app::Color& color) { + auto theme = SkinTheme::instance(); + + // Eyedropper icon + add(theme->getToolIcon("eyedropper"), false); + + // Color + m_indicators->addColorIndicator(color); + + // Color description + std::string str = color.toHumanReadableString( + app_get_current_pixel_format(), + app::Color::LongHumanReadableString); + if (color.getAlpha() < 255) { + char buf[256]; + sprintf(buf, " \xCE\xB1%d", color.getAlpha()); + str += buf; + } + m_indicators->addTextIndicator(str.c_str()); + + return *this; + } + + IndicatorsGeneration& add(tools::Tool* tool) { + auto theme = SkinTheme::instance(); + + // Tool icon + text + add(theme->getToolIcon(tool->getId().c_str()), false); + m_indicators->addTextIndicator(tool->getText().c_str()); + + // Tool shortcut + Key* key = KeyboardShortcuts::instance()->tool(tool); + if (key && !key->accels().empty()) { + add(theme->parts.iconKey()->bitmap(0), true); + m_indicators->addTextIndicator(key->accels().front().toString().c_str()); + } + return *this; + } + +private: + StatusBar::Indicators* m_indicators; +}; + class StatusBar::CustomizedTipWindow : public ui::TipWindow { public: CustomizedTipWindow(const std::string& text) @@ -77,7 +386,14 @@ public: } protected: - bool onProcessMessage(Message* msg); + bool onProcessMessage(Message* msg) override { + switch (msg->type()) { + case kTimerMessage: + closeWindow(NULL); + break; + } + return ui::TipWindow::onProcessMessage(msg); + } private: base::UniquePtr m_timer; @@ -112,14 +428,6 @@ private: ui::Button m_button; }; -static WidgetType statusbar_type() -{ - static WidgetType type = kGenericWidget; - if (type == kGenericWidget) - type = register_widget_type(); - return type; -} - // This widget is used to show the current frame. class GotoFrameEntry : public Entry { public: @@ -164,10 +472,8 @@ public: StatusBar* StatusBar::m_instance = NULL; StatusBar::StatusBar() - : Widget(statusbar_type()) - , m_timeout(0) - , m_state(SHOW_TEXT) - , m_color(app::Color::fromMask()) + : m_timeout(0) + , m_indicators(new Indicators) , m_docControls(new HBox) , m_doc(nullptr) , m_tipwindow(nullptr) @@ -180,14 +486,15 @@ StatusBar::StatusBar() SkinTheme* theme = static_cast(this->theme()); setBgColor(theme->colors.statusBarFace()); - this->setFocusStop(true); + setFocusStop(true); + setBorder(gfx::Border(6*guiscale(), 0, 6*guiscale(), 0)); - // The extra pixel in left and right borders are necessary so - // m_commandsBox and m_movePixelsBox do not overlap the upper-left - // and upper-right pixels drawn in onPaint() event (see putpixels) - setBorder(gfx::Border(1*guiscale(), 0, 1*guiscale(), 0)); + setMinSize(Size(0, textHeight()+8*guiscale())); + setMaxSize(Size(INT_MAX, textHeight()+8*guiscale())); + m_indicators->setExpansive(true); m_docControls->setVisible(false); + addChild(m_indicators); addChild(m_docControls); // Construct the commands box @@ -271,12 +578,8 @@ bool StatusBar::setStatusText(int msecs, const char *format, ...) vsprintf(buf, format, ap); va_end(ap); + IndicatorsGeneration(m_indicators).add(buf); m_timeout = base::current_tick() + msecs; - m_state = SHOW_TEXT; - - setText(buf); - invalidate(); - return true; } else @@ -315,39 +618,21 @@ void StatusBar::showTip(int msecs, const char *format, ...) m_tipwindow->startTimer(); // Set the text in status-bar (with inmediate timeout) + IndicatorsGeneration(m_indicators).add(buf); m_timeout = base::current_tick(); - setText(buf); - invalidate(); } void StatusBar::showColor(int msecs, const char* text, const app::Color& color) { if (setStatusText(msecs, text)) { - m_state = SHOW_COLOR; - m_color = color; + IndicatorsGeneration(m_indicators).add(color); } } void StatusBar::showTool(int msecs, tools::Tool* tool) { ASSERT(tool != NULL); - - // Tool name - std::string text = tool->getText(); - - // Tool shortcut - Key* key = KeyboardShortcuts::instance()->tool(tool); - if (key && !key->accels().empty()) { - text += ", Shortcut: "; - text += key->accels().front().toString(); - } - - // Set text - if (setStatusText(msecs, text.c_str())) { - // Show tool - m_state = SHOW_TOOL; - m_tool = tool; - } + IndicatorsGeneration(m_indicators).add(tool); } void StatusBar::showSnapToGridWarning(bool state) @@ -387,106 +672,10 @@ void StatusBar::showSnapToGridWarning(bool state) void StatusBar::onResize(ResizeEvent& ev) { - setBoundsQuietly(ev.bounds()); - - Border border = this->border(); Rect rc = ev.bounds(); - bool docControls = (rc.w > 300*ui::guiscale()); - if (docControls) { - int prefWidth = m_docControls->sizeHint().w; - int toolBarWidth = ToolBar::instance()->sizeHint().w; + m_docControls->setVisible(m_doc && rc.w > 300*ui::guiscale()); - rc.x += rc.w - prefWidth - border.right() - toolBarWidth; - rc.w = prefWidth; - - m_docControls->setVisible(m_doc != nullptr); - m_docControls->setBounds(rc); - } - else - m_docControls->setVisible(false); -} - -void StatusBar::onSizeHint(SizeHintEvent& ev) -{ - int s = 4*guiscale() + textHeight() + 4*guiscale(); - ev.setSizeHint(Size(s, s)); -} - -void StatusBar::onPaint(ui::PaintEvent& ev) -{ - SkinTheme* theme = static_cast(this->theme()); - gfx::Color textColor = theme->colors.statusBarText(); - Rect rc = clientBounds(); - Graphics* g = ev.graphics(); - - g->fillRect(bgColor(), rc); - - rc.shrink(Border(2, 1, 2, 2)*guiscale()); - - int x = rc.x + 4*guiscale(); - - // Color - if (m_state == SHOW_COLOR) { - // Draw eyedropper icon - she::Surface* icon = theme->getToolIcon("eyedropper"); - if (icon) { - g->drawRgbaSurface(icon, x, rc.y + rc.h/2 - icon->height()/2); - x += icon->width() + 4*guiscale(); - } - - // Draw color - draw_color_button( - g, gfx::Rect(x, rc.y, 32*guiscale(), rc.h), - m_color, - (doc::ColorMode)app_get_current_pixel_format(), false, false); - - x += (32+4)*guiscale(); - - // Draw color description - std::string str = m_color.toHumanReadableString( - app_get_current_pixel_format(), - app::Color::LongHumanReadableString); - if (m_color.getAlpha() < 255) { - char buf[256]; - sprintf(buf, " \xCE\xB1%d", m_color.getAlpha()); - str += buf; - } - - g->drawString(str, textColor, ColorNone, - gfx::Point(x, rc.y + rc.h/2 - font()->height()/2)); - - x += font()->textLength(str.c_str()) + 4*guiscale(); - } - - // Show tool - if (m_state == SHOW_TOOL) { - // Draw eyedropper icon - she::Surface* icon = theme->getToolIcon(m_tool->getId().c_str()); - if (icon) { - g->drawRgbaSurface(icon, x, rc.y + rc.h/2 - icon->height()/2); - x += icon->width() + 4*guiscale(); - } - } - - // Status bar text - if (textLength() > 0) { - g->drawString(text(), textColor, ColorNone, - gfx::Point(x, rc.y + rc.h/2 - font()->height()/2)); - - x += font()->textLength(text().c_str()) + 4*guiscale(); - } -} - -bool StatusBar::CustomizedTipWindow::onProcessMessage(Message* msg) -{ - switch (msg->type()) { - - case kTimerMessage: - closeWindow(NULL); - break; - } - - return ui::TipWindow::onProcessMessage(msg); + HBox::onResize(ev); } void StatusBar::onActiveSiteChange(const doc::Site& site) diff --git a/src/app/ui/status_bar.h b/src/app/ui/status_bar.h index 1a53a3167..06a3bdd00 100644 --- a/src/app/ui/status_bar.h +++ b/src/app/ui/status_bar.h @@ -17,7 +17,7 @@ #include "doc/documents_observer.h" #include "doc/layer_index.h" #include "ui/base.h" -#include "ui/widget.h" +#include "ui/box.h" #include #include @@ -43,7 +43,7 @@ namespace app { class Tool; } - class StatusBar : public ui::Widget + class StatusBar : public ui::HBox , public doc::ContextObserver , public doc::DocumentsObserver , public doc::DocumentObserver { @@ -67,8 +67,6 @@ namespace app { protected: void onResize(ui::ResizeEvent& ev) override; - void onSizeHint(ui::SizeHintEvent& ev) override; - void onPaint(ui::PaintEvent& ev) override; // ContextObserver impl void onActiveSiteChange(const doc::Site& site) override; @@ -85,16 +83,12 @@ namespace app { void newFrame(); void onChangeZoom(const render::Zoom& zoom); - enum State { SHOW_TEXT, SHOW_COLOR, SHOW_TOOL }; - base::tick_t m_timeout; - State m_state; - // Showing a tool - tools::Tool* m_tool; - - // Showing a color - Color m_color; + // Indicators + class Indicators; + class IndicatorsGeneration; + Indicators* m_indicators; // Box of main commands ui::Widget* m_docControls; diff --git a/src/app/ui/timeline.cpp b/src/app/ui/timeline.cpp index 8b4260f99..790875621 100644 --- a/src/app/ui/timeline.cpp +++ b/src/app/ui/timeline.cpp @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2001-2015 David Capello +// Copyright (C) 2001-2016 David Capello // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as @@ -2181,7 +2181,7 @@ void Timeline::updateStatusBar(ui::Message* msg) case PART_HEADER_FRAME: if (validFrame(m_hot.frame)) { sb->setStatusText(0, - "Frame %d [%d msecs]", + ":frame: %d :clock: %d", (int)m_hot.frame+1, m_sprite->frameDuration(m_hot.frame)); return;