From 22f35ab249790cb2bb416605ad4f0cdc337b7081 Mon Sep 17 00:00:00 2001 From: David Capello Date: Tue, 10 Feb 2015 12:59:43 -0300 Subject: [PATCH] Independent scroll/zoom in Preview window (part of issue #407) --- data/skins/default/sheet.png | Bin 12524 -> 12645 bytes data/skins/default/skin.xml | 21 ++- src/app/CMakeLists.txt | 2 + src/app/ui/document_view.cpp | 33 +++- src/app/ui/document_view.h | 4 +- src/app/ui/editor/navigate_state.cpp | 75 ++++++++ src/app/ui/editor/navigate_state.h | 39 ++++ src/app/ui/editor/standby_state.cpp | 134 +------------- src/app/ui/editor/standby_state.h | 7 +- .../ui/editor/state_with_wheel_behavior.cpp | 167 ++++++++++++++++++ src/app/ui/editor/state_with_wheel_behavior.h | 34 ++++ src/app/ui/preview_editor.cpp | 84 ++++++++- src/app/ui/preview_editor.h | 4 + src/app/ui/skin/skin_parts.h | 6 +- src/app/ui/skin/skin_theme.cpp | 5 +- 15 files changed, 452 insertions(+), 163 deletions(-) create mode 100644 src/app/ui/editor/navigate_state.cpp create mode 100644 src/app/ui/editor/navigate_state.h create mode 100644 src/app/ui/editor/state_with_wheel_behavior.cpp create mode 100644 src/app/ui/editor/state_with_wheel_behavior.h diff --git a/data/skins/default/sheet.png b/data/skins/default/sheet.png index fbac858be54f75523072a23e72c97487cd74e4ed..8863dce759dab788d157d9544ba0ffa2e56d69cd 100644 GIT binary patch literal 12645 zcmXYXcQ~8>_kO6oXYATLVvnNKrba0uHnD5Ac578_rDkkO6(v;6+I!R}p(twC-aGa; z@6Ye|M{?zQt~}T4dCqyg?sK2}KC$|G8l*&wL;wJQR7+F!B>;d0!h8S(c$h1M)Y>ut z02@F{RmmtIcRz0|p2Y;d`GV#Of20Wi6^cn(+%d|7iNyWOiq(M*<}bSuLp9G~7U^ar4LQ#P*b#Ui79M?I7^>ZhEPSUp zJQ@FyDR8a7P5R(_%n!=LAhyAbpy=LoR~vM0n7fMI-*I zeZV|R&uTZB{fwu{CXmjL?GZqR2E;H$ymYbbSjzy)(9Rs&B+w8pN80eMn#>e|*f^*` z4$V^OiG9hzezA(Q6B23*!FrQ4C-NruTc-AE9Euc*MCtlh9FIB+p~tIz&w6+IfPHbv zmK~(=#B!LdAHTG{#>9g?*udRtk-vQli!!IPW=yKvhFL+^5C}#w2gxur|1f5Za!}H; zlA6)eB;bJpG>W*X1@WkbEXCtu;jz#@A`XZK+(Ct|^aYyE{Je?OAPDXK@PQLr5M@1f&*pboprm`|7GJiiE+Z=~slbbRTF@#i+kvEw(qr++*I) zRG}as08kADF)m;U0Ux83MY>jn1k;_5;pxxo0)}6GEc&|p#T-jVwMppX!Mk;Tmuv{^ z^Q)AvE^#i|j5Mg`ZL@Txx{_MZBRKD_9VhCIlaMNhnt_Csjw<3@Fe?HpOkLdT|)HZ#+3(>3rRUkB`xu6E96L+d8=a*3j;xv_r>BQib zP$S()_Pt{uf|XT~%*m`BKTO1Sl?K5z=KcD9Y-MkbtE&MkDt2X_%k5@y>#Ok1$0XNq z$R^5>Z%DC{ufoW*4# zCQ>(qdQxs`_odTo7qhQeA)G0&$3KG<2576R{2>iJj1SoVjXB3k5xmBM$Z(w{U0FpOF>purDQ9y(f~CBqqfA zIVJk!;YmJj?emEf!Wr7~Hz|uhY-rT5)C@XH{S`#WSbMu+(+M&zMh!u#%sZPsB1kIU zgq`dU(tg5SSHl~rSf}#BYptFvp`oE2luH!uUr%Urzdy_zB37IGML*k`I=6dk3F9cZ zT*IAC;OV1c;*d@E?(bO4;8*u!kqpB z@*ma@;(-q*-#vq1ve1NAaaHOhIhh}HgZ5Rc=X!|%A05Nybr|d2ig4q{9?LAXc+7sU z#sXLY;Z8wRmD^r*VaLusW-hqLuyYKKyszl^i>Iopc4ypH-By)K(hR4tp+|;KsF8Fm zL;cbmQXLLxJL-T2w{C;MsjajQO{{DRqNGWz`mk)neAnL^s;Z0RQ&ZL+j{uz;7f+1u zXm2=!Z+PS=-ynWbC#JI z`>pLP*f!29frs?+CK&`I9;_jmUEO_iX7Tog>B3)}XHw4_n}W#>_7`+g+H!)^XS20H zqqeZ~MyI9msGF$^t$-W7$ug1P6?dTBX^{h`6?I?nEZhFzI*??t2KXr8J*@j{kMd{z zc2~Mk`u3E62iA*w5EeNIEG6Zn##I(I(j%sS!Jdn8~HUe5#vYK>? zf7#qbc-wAH2rRTNVT`TIFM6mb>SbKIBcx+wz*ur;1j0b^+O7pW;}uHOT0|>XN|}@#v@C z1k@T|*c`6Jhr^@-3MdV({M)lFuYXg92&g>3%hX4YBrKj_wi*x6c_^y+qbpu`=Il|} z2D1?OV}0BEFB)LSXQo zX6VyQ^fG&;!+P(lH`R`8JsOA@8KlKe%CyhnlH)bG<=cf+T%rg9SC2YfqV%ht)yU`v zkklm?+*rtx^-@g7%W^HczmZ{3+`y8RMIiZ&h2pNx_}3>jr&6{S1l#1p#Ra{;S%K0$ zZL*~`2ptI4mRIb&L4p4M9QIy{?kfi}?7`3^hhgu`@uOWrhRX{NsqSIm<)sh=U@H*e z_g#AW(1t2%G$6y^7b*pQIbM)H`YqMUr#NXbF9S_0oee7i5C_6?-XM*~=Z)@&)% zNnC#uJK}v1q)@s!#4bg6W1rw~+chd& zaJs3hP&(tmu5wGlNLLy2hfi9tB_MJ5JJ4D^yJX_D8J+#+LeGE(mBtOIZ-y~KZe1zp zCL}6%o?gz8c(i!%QMEv?glrLZjHK6=QxG`y&DfVJcw^VdtoFy;;iN=g9}KmX&G&t_ z$zo)bj8eb4x1k-eFDw=4plkEG-!GzlAYseAF0QC71QlP@X*ZCF)wwdKaNP1ZZc^mn z@zb~e#7t=^4G`L9$P*EPwn{LMfZIx=8&#hbJGPhCr%rK`WKIeJa zd@sxM(vDUzip?xf;oq#A-^t#$o}0ejxUPG}cdzgrYfWczO7UnbiueSyEu^oYc*Mf@ z=@Au@$A$N~jANCRu^A2wi0|KfuCJRjoLzdKU!8b)f2W$lqmhq^{@@bDvK8w^^2l{& zSau}hp3lX{Sc7Q^%abbVu!V}8-hdU(RcqRl|Y>EAAUE` zpM7#LTfRy^^KMkm$Y8Xm8Tn4jg<;`OTX9=Tq5o(s6ZoAy0Fbm9I5B-I z#)seWFEP(%QUuWH=Fc!qhvyX_1Z=@8JZcn(lJGLsH=uDV5%dz@Hg-sM6oPB<=EkJ( z8=HwMrT)QCm`d8$j^4y7ktmB7G(b2yi>1c%_gE(lCKXuN3eXgxPeC%+k)rhh&@Wu0!r z&)_Og3aYwGW9a1MbEVdmiQHKBwv6}gLGGB1$Y@9xc2focVY%Y16xjt+jZ3+)Ghs(MeHXL0|%CUyQ3c8Cy)YKYZ3$Fp7040mEw8;t!vII*Wr=`qJM zGc)zCXMYI^fgJ^ir$4g_p4}}0f)$PDFL5;R=i@|C+irBO1{8A$b^{7~4~Lk}v?|+= zWLZoMOK7Uzi(uh96C6=ro-ZY$H$4I?lLaHeyfF&jB;$R`vX!z?a-2STS0GU#4d+lO zj?!80r%Y&J^?|nhFYAz{KST@w3vfn)Sp4P?igTL+;S?0k_SPmLHvPRKXkWke*Hu1A z-h-dEKqzEY%6fI$+H1m9g4e{ zb^O!$E+NrY_w^xezFX(?ui6aVA5N@z0ZEyE{d>REM+g|exUdU{+*I6iglAR1&$_A0 z9VDi^1L&RaWUMnR;6oH1XTeLebp(Ar1X*88>+bF0`2pavMm&zk7&MDW=e}{^6|A7^ z{U&kS6 z@})$fo`;S#{Lou>SHeRK!J}DZE?yUXQaWrd-{@y|NyVjw9Ye6W`1VCsU<#L8LyLi} z32n%G@tl_ahkf~nc~fqPzd!JZ$R5GE8&YHUZEV~qo0Ru*8hLX z-QD0qEA*HMPa~IW=u}ZLsF8^C3kEf~3>YwM^jJE%(REZYEDtxR=Fz2f7vhkg3^h#) zixfQu3dsEkXz%?;u5CtE*tWE-$?kk>d;X-a>o-1?(x2r!!9mr{hx>WEihzghv3y*> zL*E$too!QZ#%JbZp~^pCA@Y-GHJxmm@b%{eo}@gBJU^;Qk;e(bO1>}3vQ&M@YMpg& zYRw!gH2S!3h;3-@s|kv{0}6I|?q{qQ-;!qO9~bZrOIrsg?&)_$Q?BI%+_+JvGPPvr z%XeFE*D1MOi2wYx{foK>*249CqoZxK^k&@Xv^tGNSSaWQO$-18?99@oaXQz|5*y1T zV?q&)Q8S`Q1t7cLbPaJtQn>2OLyh7845#Rk9yn2Zy>Sm(DziVc_|>A}mJD zea{@4&lY7vx~z|A55C1^mJf2y>pZ6B6+ljSe)$R%N{1p3G5wlcuokrTBCGVC1ORBi zzgPkQ#=kTT0X`Pje< zfJNwK=ntMqoih6+B@GOd7bu$gP3KTR6t?t~Z8Jttha0*n+(EvIm*#l;5Z0F^6>MrI z+T9xm-|@jW&$gS}4#8|Du?D@%>_>`|3!egwMq5P<4if*$T)wW6)_Knp#Rf6xpsJwV@wEI$K4GXfr=_f+i zIhwCs#d2h1E4rWF{f#%Q45;@INmoQv0iVrF?e~`CdIm)~iF^?>`9x~bulVdaI7HP2B@NltQ`CS;FB^Wd7kQ!FAVZlZ`-1t2f1X4t_MwAJ-jvV@M zLzfipvGYR?)HWqz;tFqVEsqJuaN^IMj#mdRUn5UdM$&lAvRZ8_v6x3y-fZ{8q35DF z_?>FCJ9b5u1Z}`(6JD+B>0HFmM!@mY^m2y=df{vYo>lbulX<*RYU@Q>kD>eha%QhQ z!rhxNAxrd*FEG{}@@&7(B~K+-s$cxvkgS&VP;v71BZzVKJjbKC>+w;Nqr@u#2W8!h zbfrBX;W7Rjnm#@MFv^cKV)$>t0Kj1;dB*V9Gm7r1<-D73i47;597p&qk42yYJ=Psi zM{12QP(fix76rg{z*gzi0L3~-)cb+}*P5#VPlX%1bA^YET19nh6Dq!?Ci1Fwk9Dh! z{sV5A%jtKWvb(;VA2CWokU})(30rN2L=9v@R#n$OY2PAht22EgVxphUt=ByBVC{oE z><+I}U0hze@?z@jY=6xh+AX5~_HWBqV`?rd@g`VOx|&X8_PZdtCF--6$2Wf*(c#_d*6gcO+i4BoY9Yo&}ILsjlQAC zySrc~BuoSadk`l^WbklK_P(z(s3%KO^ckgDLO1)kU8tWWyztSUTC$rDjf|)+GeRwbp*(@x-E~B8a66mCMBNRA zPLa8~5EKwybhRI}Zq%7j6kJ*Q+ch6fJ|8i`xT^6!y#w76Ae#$!_ z*vBlJ33;|%!}g)o*Vf&78oGmQ_`6yc)xbKkRVvwu146JOZBsZ_ zrZl1PvHOV`A&jObiq@vAJ0@n4T4R7LR2cn$_4)O8*_vt?Oq1BvSZ+bCzM4l6s#9kl zy^S~*EqXin*JNVs15JaSvsn+Dj{vmeYVXrvVhFf2Z%1w7T;&^%>sI#wQH#c^(&a~j zkLjI_Z8M^TsYI%(+vDvAe4BD=p|4dq;(!anMUM~&6f!>ja&@zCm{ra`flAfJtx|9q zflwln7t=%#aF9$`rm{?UMfvu!$_GJ(0uo=p;a8&Qsl@|8#Qz2kVkt!);7#aq#5^-P zaByo}eY<0N1-GioY)*}(&DtUt+Vb>pX9IM8zkHnJTty)E{R?(|Gux@G8L_+%H!#Mr zM9%we9~EXMBgXeLk+BhLP&jJw1Oyt=|4FU z9JwZVYZ+->@uXwl8(x^j8$Z=;bH00fs8kd;cGAeLYxu9P^w#Td#HLp`$GH;#66|Cn#2? zxsgluPP=$p760$#We_l4b+ba7rq=p)k2m&LcpTC&#H%Y?${5|L6W_#|wV64!zfmwu*F@&p4G6in%nXWguD-TK?&rrKS%-hp z0mm7I!(*`4{4tG91<>f@W6hcNtDV!i*wTV`NXZlmeBHI5tD!G%71sg;Fx4$@_3Mm> zQpmASMhDy8dyPv$H43|8sn>Px_)cLxmbnEX9#+(Om|H0^62WrT>}e%Kh-DDr3&qPK zzPA9tQP2BX#2iL=&Sp)qmM7h=H?RItZAX)Vq2>D^pC~r*j$o%IYSj@VT9#%{Wk`5m zys-hz5CKM9#E^S#GabZ#=0!_Li=+wuip6XuH9{p9fTmbh zyfq1MypV4VI+kE7GEmb=!8vR@1_oIMndaS~C!bcJS-V)ioXF}^SBNRPqTYJD_P7ux z{#Zd$-w2xDuAC!X4Pmpi=WWtfTT7pDwTlBM0096M}?_ z^tPI> z2lb=VF{qn^;QuBw$7|-{=7J_uv_M6#DTGkQx^Rb*(Pt2_)n^LI)QR;MG4A^@ScN?7 zluVctUF<^i*Lu?WdMF##K7bxGWd0T$xLf}`3`615te9BUF(>I`QY0-QGQi21^Q_zT z{Z8K-3c;`vN!(U1T(GOrmTL5a9*Hy$5}U0nF7A(7g&p$Mve?q|>Jr9H+i+cFYE*LU z^q*d$ua_*<+%8D|P9}@bs^)NZ4p+3aU*<#fDQ>R@)U6;ICZ6 z{p6PGmlQMrqvK+>*U^c0sIBztvkFCHm+B`kq>h^cUly`j*sVGTP6#Mw%RKk_`JaYI zujabHXcBs&*Q<_zqMaPa9#OM|sjQ^BO|Wsd`Bl6=7}SjQEf!yx14WOcb7P%5VCzB|1sxt;@6flP| zTtvmeIH7Njv30V|uFHA2WfxTR9nibO9%nc&Uztg7Q4IlDI*0%zrn5XI3W|3E8e_HZ zAZwldVyls{eN3rPtR$QB@R3gqqhgiUH7s}7_IFgQIX~{eKHwRW>?ntuLrNPSvm%jW zZ)880nZ)Zl-akC$?#kR|8byHf`qNqvYkZKy{eAswZKRl4r)w?CP5EbPmUQU1`%ert z)f^F{?_Qc}7h1Mu{<<>QxBJN>BuSAqv($RL5X-$=1odEkq+#9oAh(X3d$n z>YzeS$P0=HcG5y@d?faGeByWKbIK0YR*$sY)IQNj99K1VYEhDyYsb%`JVoQvpfp`W z5f{Cv!4}oM537@;qA8Ns?eyXFDN&K@Fw4k@#Gbb3}$qiI;7=;wgfeuS!@ItO3Oilk!u+)En@~S-PIP;!~B5ta^t5C{lt&oY>uy+ zw7+!Pb5#rF2W0lMQq8=nn4naoX09aWC0)Dj)yVqfN1gdd!KC9%Sn-nXXn#$3`TPBK zAbNRc*X#b|M*SFLAccE-w&6eAzOe2#9BY53t8i7@$Z%|k+AOm*XDmBK^l^HKq zUH&7tEE&!cWjLi{n@q1}V*`X>Z!JNTDY4WY$y!E-KgW$08S}HAV#K8RO3FWp(j2w3 z2;)6^MQIwT@aj(Ex-@vIe=Las^kwWeSib_NDT6Rx#&+W3T{k%$YL&N9mM~(o=t4@E z7zaO)nG~OcBdtY2TP}H0!U619ayI5ZpzFVxQWx&cf+(uASt*l=GZ9Vjx?dmQARZb`yPF&pG-?z_Py5CPoF147^8~Q)} zt=OWiTn$rqO_84Bh4LS0mT-s4<5VsKj}wexOtu6jyk(ZOylxKQ zD8UfO(_+D6=f4mt!6#hM`=gGeu$Z|Iktk!$Ea$8kT2^ZsA!_8RuqF+r{!iR3aZjNi z&?}Wg#x)|982Ltp+sqWspYy>K&d`##qBg9KK%-6JN(M9#SfBOy^|dSjfKiW`;*IC8 zz?n(TltM;%2jy4BV(s8|w_L%v?tl=8FK!Fc?j%CbXB-l0m^o4RnStOZdLkjAI&SOLP^|5U> z8KVrq$C&AnCA52Oqj5D#aO}47@I6Ha8%&vB#wEMv$_GFd>gQ&rH(Yk~*|+@-&{2P! zXr;SLIwZRU@Ni7nlJc;7X&e&cyf+the2Q^wWpu>zJVbLwoq68KZ%x~0%d;xv?s#Wh zMHl6{g<{Rd8#mXJJRv=W2 zH~6WCx~YO)ntJ_zD&n*S`iUG#P4L%A@G@Io^)S{^|L$EF>5QnU_97WKp*DzK_ zCg4&bM2tGT;`@}Z#!Wl&BAo+2$y_0jb}-r|XVRxbbPIfitvvu zJSC+6DEWi2qC#;y#L;=X63x9qJ3V)`7Q_F{5eK zC>IEXTOLm>{aK^-OR|Y9q!L;Pl9=9Jl*;Iv_D@HMsPrFFrxWDFiL>gRHx1v)@$_n1 z8NoRu34026ABk+Murce$hF3;%Nv&I~io31i0~~-&yE~K&*=O(QYO^C9R(oG;w0^Q( z?G=V>2CErBg+>j=AzE5x*qA`VcxoylxufVuN!|F$M7!UX~?s3f8u7Ba^JjmO4t9;-&~zz~S;S z_K}2@TQypyy0%)y*qS}USa~}IS3w?fH0HJKsqcXfuf_>sI_tSq;P9RuU85efLQLgL z!!Ki!R;;Sxm0iy;YaH|Y)7xAQ#*jtclMi{Oi zxuPcbF$3(yq{ORu&M;rDewJG2?GR@7U5hlKN3V+gq@Ty|1-z%h!=Ibj7+$~4&4f0Q z)Se1=9A5W>k3qa}muLB#TG=IoqsxgG+1#4DIh#0R;E6Ms4tcR)GX-ejgOrvzD0R{s zGrwcrMJ1G;i5m|96#l}cfmcoVa%3BHV#)$T-(te%0 zfdXX?Xb&a;6R`h@5RQE+I{vtw{e)*}TQ8!pHkxU*@3@|Eh@aD-J3h5yIi^VRB@*^~ zheOwu&3^nl>RCi}qCLjxTg*SAWd63y(9f+Nj`%gHa)4#MtNBq*5{3PuE3WeKKs7p$ zN`K&=NZO=O>t=j z3R?Vm%IvlV2FCjXmKUI^+BAZGzf|fda)ud-eoQAaC?n7knsqztD_N=wHgpKx$XUFN&rDIzg1xK^~(Uot#?su1=!#5oS~=p~j|(vkvzI1Ux{eeM4M@ z1Y4~2Wn$L0{1zf|rNU`e5Rco0kT{rv$+waud zg+J*A87(swC~h(?;hDC#U$wydlB2%j5D^bcFkAa$nF%#6zNTfS0zE+~9wn7o1!PEA zSOu^msZQT$X#-20x^}Q>-fQlFF|a%-Qb`%T;8HAXk@LCzepBV^N-8ENoNSc5`N~|r z88{V80w^nF;^wF0GVg-t{OE18C>K*tdDA8SOqE<-q9$X? zq|R+M`VY$>Z)MWVi#o&8X&D;^g7Bl#UDm;_&@gI%v^5lPa9@r7Awt?U5qnQlHHLHi z_;;20UIYZnK1Ub+wGe5ePn*$KPDOaIuQA zYfx<*7bMY{VX9d`b(l{pMU^6tVtN6p07(4W+)YF=c3gpQc&Ydf+H?TZT$MLwUe26CS zmVcarMx;!*#Km>ukmVH>UPP>@o%3W9Z{4WihmD!><5Ha%*H1h5$u_vktBDP=tjcxp z;jboFaYaXQFDOKxh0{jOA(nxt8mXC#VeXMlZzq&M95!Z-GZu(~9IA`f=mtX<#PoIG^D?2m)`KRb zK$*cMTk6;T;o%GjaTQcGqVJ%T99eG`18m=uvn?1Y&*$J6sUcRdb|h^hfuN0RVc$nJ&lTN+i#FvJZ*CpOkc}Bmpv6n^(br zfEiwPb1Z=w%KWpR-a7i1lqk^@T)@OLQq)S{FD?a=CsT!>WjttR#QVgA$6#SRpUW^d zHBNi(6^)Rf$@kA(D36!xU$Nm$r*L)s&m}`I3c&pCVxN~CL5RG995YUpuzqec zW3hRUDs}|OMiRyVrAJ7Xtz43{2cD2t$tP+dB-nFwz~nYtw{pCgabTU5DU*9#g?pbd zz6s0_1A6PAKqZCw6>i8SKKkF!j`tnnBWH~OubmdfXD9zKhM9f-)hDZJK;rb)iItJX zgx4NTWkmUq1sG}oS&boZS!u?I?^f;y={#;_y99cYug@@yyqw31Nh@VpLs{_P5P(=M zp!$`5#T5G@h3i}9gVA!taLI&G_@<46mImB@Q@&CfM&FD7Gv5}Qk~ozpdwcO|P^5uz z;#`u?*eLQn}=2R(uQdh^d|Zqh^e?0}lM*CG#3 zoJ>Is>sHK89|^&s7EY%Qq9_uCIPfwR=(-V-W;sv2qw2R|NQfK{mbD}(7_D_5W~D7q zSzqGEC=YCY;kBny<&KXGyQeA2woP5o36dA{vdze<@{_tT_tv2PnF z0c9Wr>H}NnG_#|vC>&l;JLR*#w-ooe?_$RoJSC4h z^l~Ue+xZErR6z+iuv>KoA=Z_XT*dzCOAGbO=HK^6_?V`3Sj^Zd6yt@^F7D zsu@jcDLurIrqUu?kp3Qzd{0T0#9+X3(j|T%^gA)rj%@QYN89b+=?@2S5@8#aYaQ{X zeL_k~6y-fIxa^5?A#}tI^cH4HGEC`!%Y92x$#XH|9G^$gULkNCw(aor1>) z`HSYYYN)xGpmyCzYyOMDjIOCUda+Pz^hxxu0#kj&%fX35v4^CXJ7bg2v&lhfAC1%$ z{t;b1&}yAR8A6Mzt%YZai*9~#=SnGLL}ija@7_AO44G9SjB=HAKh~)X&be**;kb0m zeQ51ES9L{>l|VALCJ5z=@ZPqOP7vI1FjIGh(SVjR8Y^mcCJ3`S;xz{@^iFk^al$NT zB8G^)6BS{q(jv6Zf3|<^;Lt5L04f8kKRcky1XhyR8l*qDO%fYRnP$7M6LXtYU0o8I znuH97wCPr6=pmR@2D>NzQHzBx`SjcG`{H`q2J$=U49QW5NsEZ>3O3wudDE0-UyHm# z%MO_vvV#PRSO?p5p!VtQRANdr_O?-PUD8I)SflRM4vGS4#2%^`WJ6)CMtQ4`r0#Ue zB%PwcBStaEKzVyvg(O8p$g*^Xmu17GBr-jkjZwd)&6+XT;zOD;`BD&WOzp=n9K{Yb rajDL+whY?duAp@;jLsB;M*BxbR7RH^3z%RUV1SmIo@$k{P5A!-p3`9L literal 12524 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 diff --git a/data/skins/default/skin.xml b/data/skins/default/skin.xml index 85044f10e..5965d3886 100644 --- a/data/skins/default/skin.xml +++ b/data/skins/default/skin.xml @@ -171,15 +171,18 @@ - - - - - - - - - + + + + + + + + + + + + diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index a589ecb0d..0051ab76c 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -280,10 +280,12 @@ add_library(app-lib ui/editor/editor_view.cpp ui/editor/moving_cel_state.cpp ui/editor/moving_pixels_state.cpp + ui/editor/navigate_state.cpp ui/editor/pixels_movement.cpp ui/editor/scrolling_state.cpp ui/editor/select_box_state.cpp ui/editor/standby_state.cpp + ui/editor/state_with_wheel_behavior.cpp ui/editor/tool_loop_impl.cpp ui/editor/transform_handles.cpp ui/editor/zooming_state.cpp diff --git a/src/app/ui/document_view.cpp b/src/app/ui/document_view.cpp index 16be26f4b..a5c6d9860 100644 --- a/src/app/ui/document_view.cpp +++ b/src/app/ui/document_view.cpp @@ -1,5 +1,5 @@ /* Aseprite - * Copyright (C) 2001-2013 David Capello + * Copyright (C) 2001-2015 David Capello * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -47,8 +47,7 @@ using namespace ui; class AppEditor : public Editor, public EditorObserver, - public EditorCustomizationDelegate -{ + public EditorCustomizationDelegate { public: AppEditor(Document* document) : Editor(document) { addObserver(this); @@ -150,14 +149,36 @@ private: }; +class PreviewEditor : public Editor, + public EditorObserver { +public: + PreviewEditor(Document* document) + : Editor(document, Editor::kShowOutside) // Don't show grid/mask in preview preview + { + addObserver(this); + } + + ~PreviewEditor() { + removeObserver(this); + } + +private: + void onScrollChanged(Editor* editor) override { + if (hasCapture()) { + // TODO create a signal + App::instance()->getMainWindow()->getPreviewEditor()->uncheckCenterButton(); + } + } +}; + DocumentView::DocumentView(Document* document, Type type) : Box(JI_VERTICAL) , m_document(document) , m_view(new EditorView(type == Normal ? EditorView::CurrentEditorMode: EditorView::AlwaysSelected)) - , m_editor(type == Normal ? - new AppEditor(document): - new Editor(document, Editor::kShowOutside)) // Don't show grid/mask in preview preview + , m_editor((type == Normal ? + (Editor*)new AppEditor(document): + (Editor*)new PreviewEditor(document))) { addChild(m_view); diff --git a/src/app/ui/document_view.h b/src/app/ui/document_view.h index a3a3552c8..7b2b18389 100644 --- a/src/app/ui/document_view.h +++ b/src/app/ui/document_view.h @@ -1,5 +1,5 @@ /* Aseprite - * Copyright (C) 2001-2013 David Capello + * Copyright (C) 2001-2015 David Capello * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -41,7 +41,7 @@ namespace app { public: enum Type { Normal, - Mini + Preview }; DocumentView(Document* document, Type type); diff --git a/src/app/ui/editor/navigate_state.cpp b/src/app/ui/editor/navigate_state.cpp new file mode 100644 index 000000000..99968a4ac --- /dev/null +++ b/src/app/ui/editor/navigate_state.cpp @@ -0,0 +1,75 @@ +/* Aseprite + * Copyright (C) 2001-2015 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "app/ui/editor/navigate_state.h" + +#include "app/ui/editor/editor.h" +#include "app/ui/editor/scrolling_state.h" + +namespace app { + +using namespace ui; + +NavigateState::NavigateState() +{ +} + +bool NavigateState::onMouseDown(Editor* editor, MouseMessage* msg) +{ + if (editor->hasCapture()) + return true; + + // UIContext* context = UIContext::instance(); + // // When an editor is clicked the current view is changed. + // context->setActiveView(editor->getDocumentView()); + + // Start scroll loop + EditorStatePtr newState(new ScrollingState()); + editor->setState(newState); + newState->onMouseDown(editor, msg); + return true; +} + +bool NavigateState::onMouseUp(Editor* editor, MouseMessage* msg) +{ + editor->releaseMouse(); + return true; +} + +bool NavigateState::onMouseMove(Editor* editor, MouseMessage* msg) +{ + editor->moveDrawingCursor(); + editor->updateStatusBar(); + return true; +} + +bool NavigateState::onKeyDown(Editor* editor, KeyMessage* msg) +{ + return false; +} + +bool NavigateState::onKeyUp(Editor* editor, KeyMessage* msg) +{ + return false; +} + +} // namespace app diff --git a/src/app/ui/editor/navigate_state.h b/src/app/ui/editor/navigate_state.h new file mode 100644 index 000000000..5327a3075 --- /dev/null +++ b/src/app/ui/editor/navigate_state.h @@ -0,0 +1,39 @@ +/* Aseprite + * Copyright (C) 2001-2015 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef APP_UI_EDITOR_NAVIGATE_STATE_H_INCLUDED +#define APP_UI_EDITOR_NAVIGATE_STATE_H_INCLUDED +#pragma once + +#include "app/ui/editor/state_with_wheel_behavior.h" + +namespace app { + + class NavigateState : public StateWithWheelBehavior { + public: + NavigateState(); + virtual bool onMouseDown(Editor* editor, ui::MouseMessage* msg) override; + virtual bool onMouseUp(Editor* editor, ui::MouseMessage* msg) override; + virtual bool onMouseMove(Editor* editor, ui::MouseMessage* msg) override; + virtual bool onKeyDown(Editor* editor, ui::KeyMessage* msg) override; + virtual bool onKeyUp(Editor* editor, ui::KeyMessage* msg) override; + }; + +} // namespace app + +#endif diff --git a/src/app/ui/editor/standby_state.cpp b/src/app/ui/editor/standby_state.cpp index dea32ca87..49a9866a6 100644 --- a/src/app/ui/editor/standby_state.cpp +++ b/src/app/ui/editor/standby_state.cpp @@ -1,5 +1,5 @@ /* Aseprite - * Copyright (C) 2001-2013 David Capello + * Copyright (C) 2001-2015 David Capello * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -32,7 +32,6 @@ #include "app/tools/ink.h" #include "app/tools/pick_ink.h" #include "app/tools/tool.h" -#include "app/ui/color_bar.h" #include "app/ui/editor/drawing_state.h" #include "app/ui/editor/editor.h" #include "app/ui/editor/editor_customization_delegate.h" @@ -61,14 +60,6 @@ namespace app { using namespace ui; -enum WHEEL_ACTION { WHEEL_NONE, - WHEEL_ZOOM, - WHEEL_VSCROLL, - WHEEL_HSCROLL, - WHEEL_FG, - WHEEL_BG, - WHEEL_FRAME }; - static CursorType rotated_size_cursors[] = { kSizeECursor, kSizeNECursor, @@ -302,129 +293,6 @@ bool StandbyState::onMouseMove(Editor* editor, MouseMessage* msg) return true; } -bool StandbyState::onMouseWheel(Editor* editor, MouseMessage* msg) -{ - int dz = msg->wheelDelta().x + msg->wheelDelta().y; - WHEEL_ACTION wheelAction = WHEEL_NONE; - bool scrollBigSteps = false; - - // Alt+mouse wheel changes the fg/bg colors - if (msg->altPressed()) { - if (msg->shiftPressed()) - wheelAction = WHEEL_BG; - else - wheelAction = WHEEL_FG; - } - // Normal behavior: mouse wheel zooms - else if (UIContext::instance()->settings()->getZoomWithScrollWheel()) { - if (msg->ctrlPressed()) - wheelAction = WHEEL_FRAME; - else if (msg->wheelDelta().x != 0 || msg->shiftPressed()) - wheelAction = WHEEL_HSCROLL; - else - wheelAction = WHEEL_ZOOM; - } - // For laptops, it's convenient to that Ctrl+wheel zoom (because - // it's the "pinch" gesture). - else { - if (msg->ctrlPressed()) - wheelAction = WHEEL_ZOOM; - else if (msg->wheelDelta().x != 0 || msg->shiftPressed()) - wheelAction = WHEEL_HSCROLL; - else - wheelAction = WHEEL_VSCROLL; - } - - switch (wheelAction) { - - case WHEEL_NONE: - // Do nothing - break; - - case WHEEL_FG: - { - int newIndex = 0; - if (ColorBar::instance()->getFgColor().getType() == app::Color::IndexType) { - newIndex = ColorBar::instance()->getFgColor().getIndex() + dz; - newIndex = MID(0, newIndex, 255); - } - ColorBar::instance()->setFgColor(app::Color::fromIndex(newIndex)); - } - break; - - case WHEEL_BG: - { - int newIndex = 0; - if (ColorBar::instance()->getBgColor().getType() == app::Color::IndexType) { - newIndex = ColorBar::instance()->getBgColor().getIndex() + dz; - newIndex = MID(0, newIndex, 255); - } - ColorBar::instance()->setBgColor(app::Color::fromIndex(newIndex)); - } - break; - - case WHEEL_FRAME: - { - Command* command = CommandsModule::instance()->getCommandByName - ((dz < 0) ? CommandId::GotoNextFrame: - CommandId::GotoPreviousFrame); - if (command) - UIContext::instance()->executeCommand(command, NULL); - } - break; - - case WHEEL_ZOOM: { - MouseMessage* mouseMsg = static_cast(msg); - render::Zoom zoom = editor->zoom(); - if (dz < 0) { - while (dz++ < 0) - zoom.in(); - } - else { - while (dz-- > 0) - zoom.out(); - } - - if (editor->zoom() != zoom) { - editor->setZoomAndCenterInMouse(zoom, - mouseMsg->position(), Editor::kDontCenterOnZoom); - } - break; - } - - case WHEEL_HSCROLL: - case WHEEL_VSCROLL: { - View* view = View::getView(editor); - gfx::Rect vp = view->getViewportBounds(); - gfx::Point delta(0, 0); - - if (wheelAction == WHEEL_HSCROLL) { - delta.x = dz * vp.w; - } - else { - delta.y = dz * vp.h; - } - - if (scrollBigSteps) { - delta /= 2; - } - else { - delta /= 10; - } - - gfx::Point scroll = view->getViewScroll(); - - editor->hideDrawingCursor(); - editor->setEditorScroll(scroll+delta, true); - editor->showDrawingCursor(); - break; - } - - } - - return true; -} - bool StandbyState::onSetCursor(Editor* editor) { tools::Ink* ink = editor->getCurrentEditorInk(); diff --git a/src/app/ui/editor/standby_state.h b/src/app/ui/editor/standby_state.h index b4e7fdd9b..b46a78390 100644 --- a/src/app/ui/editor/standby_state.h +++ b/src/app/ui/editor/standby_state.h @@ -1,5 +1,5 @@ /* Aseprite - * Copyright (C) 2001-2013 David Capello + * Copyright (C) 2001-2015 David Capello * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,14 +21,14 @@ #pragma once #include "app/ui/editor/editor_decorator.h" -#include "app/ui/editor/editor_state.h" #include "app/ui/editor/handle_type.h" +#include "app/ui/editor/state_with_wheel_behavior.h" #include "gfx/transformation.h" namespace app { class TransformHandles; - class StandbyState : public EditorState { + class StandbyState : public StateWithWheelBehavior { public: StandbyState(); virtual ~StandbyState(); @@ -38,7 +38,6 @@ namespace app { virtual bool onMouseDown(Editor* editor, ui::MouseMessage* msg) override; virtual bool onMouseUp(Editor* editor, ui::MouseMessage* msg) override; virtual bool onMouseMove(Editor* editor, ui::MouseMessage* msg) override; - virtual bool onMouseWheel(Editor* editor, ui::MouseMessage* msg) override; virtual bool onSetCursor(Editor* editor) override; virtual bool onKeyDown(Editor* editor, ui::KeyMessage* msg) override; virtual bool onKeyUp(Editor* editor, ui::KeyMessage* msg) override; diff --git a/src/app/ui/editor/state_with_wheel_behavior.cpp b/src/app/ui/editor/state_with_wheel_behavior.cpp new file mode 100644 index 000000000..71e597c1e --- /dev/null +++ b/src/app/ui/editor/state_with_wheel_behavior.cpp @@ -0,0 +1,167 @@ +/* Aseprite + * Copyright (C) 2001-2015 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "app/ui/editor/state_with_wheel_behavior.h" + +#include "app/commands/commands.h" +#include "app/settings/settings.h" +#include "app/ui/color_bar.h" +#include "app/ui/editor/editor.h" +#include "app/ui_context.h" +#include "ui/message.h" + +namespace app { + +using namespace ui; + +enum WHEEL_ACTION { WHEEL_NONE, + WHEEL_ZOOM, + WHEEL_VSCROLL, + WHEEL_HSCROLL, + WHEEL_FG, + WHEEL_BG, + WHEEL_FRAME }; + +bool StateWithWheelBehavior::onMouseWheel(Editor* editor, MouseMessage* msg) +{ + int dz = msg->wheelDelta().x + msg->wheelDelta().y; + WHEEL_ACTION wheelAction = WHEEL_NONE; + bool scrollBigSteps = false; + + // Alt+mouse wheel changes the fg/bg colors + if (msg->altPressed()) { + if (msg->shiftPressed()) + wheelAction = WHEEL_BG; + else + wheelAction = WHEEL_FG; + } + // Normal behavior: mouse wheel zooms + else if (UIContext::instance()->settings()->getZoomWithScrollWheel()) { + if (msg->ctrlPressed()) + wheelAction = WHEEL_FRAME; + else if (msg->wheelDelta().x != 0 || msg->shiftPressed()) + wheelAction = WHEEL_HSCROLL; + else + wheelAction = WHEEL_ZOOM; + } + // For laptops, it's convenient to that Ctrl+wheel zoom (because + // it's the "pinch" gesture). + else { + if (msg->ctrlPressed()) + wheelAction = WHEEL_ZOOM; + else if (msg->wheelDelta().x != 0 || msg->shiftPressed()) + wheelAction = WHEEL_HSCROLL; + else + wheelAction = WHEEL_VSCROLL; + } + + switch (wheelAction) { + + case WHEEL_NONE: + // Do nothing + break; + + case WHEEL_FG: + { + int newIndex = 0; + if (ColorBar::instance()->getFgColor().getType() == app::Color::IndexType) { + newIndex = ColorBar::instance()->getFgColor().getIndex() + dz; + newIndex = MID(0, newIndex, 255); + } + ColorBar::instance()->setFgColor(app::Color::fromIndex(newIndex)); + } + break; + + case WHEEL_BG: + { + int newIndex = 0; + if (ColorBar::instance()->getBgColor().getType() == app::Color::IndexType) { + newIndex = ColorBar::instance()->getBgColor().getIndex() + dz; + newIndex = MID(0, newIndex, 255); + } + ColorBar::instance()->setBgColor(app::Color::fromIndex(newIndex)); + } + break; + + case WHEEL_FRAME: + { + Command* command = CommandsModule::instance()->getCommandByName + ((dz < 0) ? CommandId::GotoNextFrame: + CommandId::GotoPreviousFrame); + if (command) + UIContext::instance()->executeCommand(command, NULL); + } + break; + + case WHEEL_ZOOM: { + MouseMessage* mouseMsg = static_cast(msg); + render::Zoom zoom = editor->zoom(); + if (dz < 0) { + while (dz++ < 0) + zoom.in(); + } + else { + while (dz-- > 0) + zoom.out(); + } + + if (editor->zoom() != zoom) { + editor->setZoomAndCenterInMouse(zoom, + mouseMsg->position(), Editor::kDontCenterOnZoom); + } + break; + } + + case WHEEL_HSCROLL: + case WHEEL_VSCROLL: { + View* view = View::getView(editor); + gfx::Rect vp = view->getViewportBounds(); + gfx::Point delta(0, 0); + + if (wheelAction == WHEEL_HSCROLL) { + delta.x = dz * vp.w; + } + else { + delta.y = dz * vp.h; + } + + if (scrollBigSteps) { + delta /= 2; + } + else { + delta /= 10; + } + + gfx::Point scroll = view->getViewScroll(); + + editor->hideDrawingCursor(); + editor->setEditorScroll(scroll+delta, true); + editor->showDrawingCursor(); + break; + } + + } + + return true; +} + +} // namespace app diff --git a/src/app/ui/editor/state_with_wheel_behavior.h b/src/app/ui/editor/state_with_wheel_behavior.h new file mode 100644 index 000000000..750660bb2 --- /dev/null +++ b/src/app/ui/editor/state_with_wheel_behavior.h @@ -0,0 +1,34 @@ +/* Aseprite + * Copyright (C) 2001-2015 David Capello + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef APP_UI_STATE_WITH_WHEEL_BEHAVIOR_H_INCLUDED +#define APP_UI_STATE_WITH_WHEEL_BEHAVIOR_H_INCLUDED +#pragma once + +#include "app/ui/editor/editor_state.h" + +namespace app { + + class StateWithWheelBehavior : public EditorState { + public: + virtual bool onMouseWheel(Editor* editor, ui::MouseMessage* msg) override; + }; + +} // namespace app + +#endif diff --git a/src/app/ui/preview_editor.cpp b/src/app/ui/preview_editor.cpp index 7f3af45db..dd2e542cf 100644 --- a/src/app/ui/preview_editor.cpp +++ b/src/app/ui/preview_editor.cpp @@ -31,14 +31,15 @@ #include "app/settings/settings.h" #include "app/ui/editor/editor.h" #include "app/ui/editor/editor_view.h" +#include "app/ui/editor/navigate_state.h" #include "app/ui/skin/skin_button.h" #include "app/ui/skin/skin_theme.h" #include "app/ui/status_bar.h" #include "app/ui/toolbar.h" #include "app/ui_context.h" #include "base/bind.h" -#include "gfx/rect.h" #include "doc/sprite.h" +#include "gfx/rect.h" #include "ui/base.h" #include "ui/button.h" #include "ui/close_event.h" @@ -50,6 +51,52 @@ namespace app { using namespace app::skin; using namespace ui; +class MiniCenterButton : public SkinButton { +public: + MiniCenterButton() + : SkinButton( + PART_WINDOW_CENTER_BUTTON_NORMAL, + PART_WINDOW_CENTER_BUTTON_HOT, + PART_WINDOW_CENTER_BUTTON_SELECTED) + { + setup_bevels(this, 0, 0, 0, 0); + setDecorative(true); + setSelected(true); + } + +protected: + void onSetDecorativeWidgetBounds() override + { + SkinTheme* theme = static_cast(getTheme()); + Widget* window = getParent(); + gfx::Rect rect(0, 0, 0, 0); + gfx::Size iconSize = theme->get_part_size(PART_WINDOW_PLAY_BUTTON_NORMAL); + gfx::Size closeSize = theme->get_part_size(PART_WINDOW_CLOSE_BUTTON_NORMAL); + + rect.w = iconSize.w; + rect.h = iconSize.h; + + rect.offset(window->getBounds().x2() - 3*guiscale() + - iconSize.w - 1*guiscale() + - iconSize.w - 1*guiscale() - closeSize.w, + window->getBounds().y + 3*guiscale()); + + setBounds(rect); + } + + bool onProcessMessage(Message* msg) override + { + switch (msg->type()) { + + case kSetCursorMessage: + ui::set_mouse_cursor(kArrowCursor); + return true; + } + + return SkinButton::onProcessMessage(msg); + } +}; + class MiniPlayButton : public SkinButton