From 74442af421b6a3f2aa42b425f64c8b29caea4904 Mon Sep 17 00:00:00 2001 From: lizj0505 Date: Thu, 18 Jul 2013 14:29:05 +0800 Subject: [PATCH] create project function done, not yet with paremeter exception considered --- .../Images/MLTableAlertBackground.png | Bin 0 -> 7310 bytes .../Images/MLTableAlertBackground@2x.png | Bin 0 -> 7954 bytes .../Images/MLTableAlertButton.png | Bin 0 -> 606 bytes .../Images/MLTableAlertButton@2x.png | Bin 0 -> 1377 bytes .../Images/MLTableAlertButtonPressed.png | Bin 0 -> 603 bytes .../Images/MLTableAlertButtonPressed@2x.png | Bin 0 -> 1536 bytes .../Images/MLTableAlertShadowMask.png | Bin 0 -> 400 bytes .../Images/MLTableAlertShadowMask@2x.png | Bin 0 -> 1013 bytes .../Libs/MLTableAlert/MLTableAlert.h | 47 +++ .../Libs/MLTableAlert/MLTableAlert.m | 339 ++++++++++++++++++ .../RedmineMobile.xcodeproj/project.pbxproj | 58 +++ .../RedmineMobile/Models/OZLModelProject.h | 2 + .../RedmineMobile/Models/OZLModelProject.m | 6 +- .../RedmineMobile/Utils/OZLNetwork.m | 3 +- .../OZLProjectCreateViewController.h | 8 + .../OZLProjectCreateViewController.m | 106 +++++- .../OZLProjectCreateViewController.storyboard | 12 +- .../OZLProjectListViewController.m | 1 + 18 files changed, 577 insertions(+), 5 deletions(-) create mode 100755 RedmineMobile/Libs/MLTableAlert/Images/MLTableAlertBackground.png create mode 100755 RedmineMobile/Libs/MLTableAlert/Images/MLTableAlertBackground@2x.png create mode 100755 RedmineMobile/Libs/MLTableAlert/Images/MLTableAlertButton.png create mode 100755 RedmineMobile/Libs/MLTableAlert/Images/MLTableAlertButton@2x.png create mode 100755 RedmineMobile/Libs/MLTableAlert/Images/MLTableAlertButtonPressed.png create mode 100755 RedmineMobile/Libs/MLTableAlert/Images/MLTableAlertButtonPressed@2x.png create mode 100755 RedmineMobile/Libs/MLTableAlert/Images/MLTableAlertShadowMask.png create mode 100755 RedmineMobile/Libs/MLTableAlert/Images/MLTableAlertShadowMask@2x.png create mode 100755 RedmineMobile/Libs/MLTableAlert/MLTableAlert.h create mode 100755 RedmineMobile/Libs/MLTableAlert/MLTableAlert.m diff --git a/RedmineMobile/Libs/MLTableAlert/Images/MLTableAlertBackground.png b/RedmineMobile/Libs/MLTableAlert/Images/MLTableAlertBackground.png new file mode 100755 index 0000000000000000000000000000000000000000..57d8cc9bf3a2c9b5e304e5a68bd683e1b41d3f11 GIT binary patch literal 7310 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 literal 0 HcmV?d00001 diff --git a/RedmineMobile/Libs/MLTableAlert/Images/MLTableAlertBackground@2x.png b/RedmineMobile/Libs/MLTableAlert/Images/MLTableAlertBackground@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..c2b7c66407376b8af06cfc9dab415362256ead47 GIT binary patch literal 7954 zcmdsbi91yP`#y%Tj3H#-Dk7o?8M_Eclxz_p$=FBs-B^}$x*cPy26pX>Jz{LXdGoVjM^^(^;uKlk%G6MRoi2~5UBhKGj-R=#!fJ{}$c1oz&9 z1c-Zm!qJkByOF|f>DuGr(Oo>e@Rjd#F5^CAF~50N6L%-TU5AG>?z(hx$GtxT`M#xL zg}W0f-@KvefdV~`!3w}+O>?#A0f5;9;RK+&4#W}y#JD1{a*xik0Eq7{RE`JDs{ITbGSRK23Bqh`JK^=#nRP(~z)dSm*M{iH{4tLZO^ zjjz9U#$$z?7sZ!6(Hl~$o+DzJ1HFdcL;M2{b3F@?_LW2$DQj#YS1FcHx5%L`5Nvyvp1yjof!=VpHLT@q zw=DT{{6m|vy-)DyQKZ*x1~-*h@O4m(kDXEHVWbFxjvB#mXKlR+-ZrmS)r_gvxn0zL zB4%pJ^L~b++uIMCTVgKjM8AHWcQE@tKWDP_>OxZ_Q#;iT!XqyWh)ej$dO06p@pqsQ zz)_%u8dy3AFb{4o?B1WP>s!ZMZ`;*bI^_a%QT#R2IaOua`nu9%b9r>b!s2BDhtuYV z_62Nako5svzQp$6#!lL{j}}ih{20{d@GGr&SA1x&KnOvej}VpuLU;v^vtMX}Wr8Su zxR}}OJAO5MumJD5aq6mMXn*KcUfu*l1B1%Kj0~=ABryeB(X1zNZnj0WmgeGzpD!#f zkL(05@Z{hB3%3CRAAu)|qJj}2@SSCy4uL5}2|n&ciNPpY(waHMRH<1WVf>_4fb=e8 zZfnykYChxUnVhVNV1=8EprC9IdsuCJGD{t&h9`04n< z;-svPks*RU0PJtDNbYh$4DM>feODv@)6m<4`z1B$$ERAM(T}~4++#*l zJ$GcnCNT_;c!xiI(f+($!vCO1`)`vxhtmoAs9?`_bj9R%)`-9;1_8vu287%-s!aM3 zopD$Jk#%dzFXgm{ejC@2sA5j;}1|h+vS#RT;+9jc-m5JS?iA#`!l}X?9Zf~>f$GmCv{D)x_gB?lMe#tIz@rXLTZw`ox+}W|0ZA}o zcU~U;(rVj2EBndHoYOF0ApesQ_7!;!Wc5$@ct8{Pcs`tY$xCkc^UpC@y-TDt4#mQv*#4>H>GKtKMEcT+s#;IR+Ne^BsONA&aX9w=BS@A z(_UXaIp=cAfeNix6HkTXk#7Zyi0Y404c|Hpg}kJhOVv2zLVP?AgtAQ!`j10aUm>BR zEJ-^xJLF8NJwvgGnd-Tvt>h_s{cH~Yz+GW+$^<^#AR##<*5)JQ@poVL~@ma4WNP>REe)q=J5BluAs{;7*grY2`hq z4D<~uXgKN$7~SASKH*053pK`qYUNnOcb2r zdAJyF`40oiL!vin8w{Ql(IDPdv{<*6ywc~12nXbL?KVH-N zhB)V_5c~s9{S^m;7E7K5LsqL46<&kn6)Qbo{sWjlK5h!uD8Q%(IW23xe@^e~sa{>u zEMG702$yg#e%o*Rd7Tx~{4;3S#4q0)6*#n65S9Q@IW1wwL-l0hmnoHpV7bJoScbEz z);=#km8dwd?pbPScKW{TzA&p!`Te6w#y}IP5bfU`BE8wEUF+=Xi{+i`^oZpfv;B!< zTu$2i{2w`FbVf`7`EM=cm82O|-NVXUGyVbs4{yWkR9;(HTiF`!6{40Oi2!u{0IKd8 zRL~&;_n*`344&Ovsl0l*cojHg981@w=1GK~V)VC~$OT5E?Ni?1ss!mbRm||@tF~GB z?UPj$mmy($9o*}z^lc4qC5&FJGhe${RC~F4L*sJUsBwkOeCjC^F$_rC^axYJKvR)d{n%k*bayO=TDS zO=5UB8ZY(gnspP%lhu>Wlbu6gEg)Z_}8((TW zJd8Y!c2w4}1}l-WrECPcP(Nz>2Mkrya|ZekR^>+I*yRoDvOu19&7xmV?yBO}g48ss z$>|>Bo1Qt(_hx)AevU<8SDG2tw%1|okaJV#c;_cO^~9$n@p@88lJvRIGD17^R)q@H zh4%i|aZbp>O;`fp=F8;HRW7}J727a6cLRvavtpq&cBgzQ?GKcUg12FS*fvXX@Y3ch>_@bG%Up;aNGXZ33ld*jmYqTKjr|WpiGP~@V3xPtUL2HGp zE9?M?loLp1&3sB;U5_deDo(xe0BR!d{-$-cLbz*kuFCd_vTtWIQRc-0A?H@LmJ1e6 z52)3$nn)8KWHq8yA1Ku~zd33%cz8XYwGQ+Pv=cf|OFAuAp~QUaVb(g|$Srx5?dTG> za6%>DP76?nFGI&Un3q51mO#)QsASnWJresimV~UMQBdrU-~SSmSdbn@x}Xa6hKAH; zy||ff^5V7%k+LsGjk!pTIgh{OlK*h3M%cYGoJ?HQXoa(!!41ym$!QJkhBOa3!WxSI zYp8(zgK8|zudRZEOc0qhz*^zDby(tnBc~G1%8X_h(dsZ?A81sMn{NVS45p@k21-`{ zQLjA{+{04$>^{v7{T@S3N8632Pvf!NxV?*;jVO96W?b9>SpSPP+7sd;K5u@1a7 z&E4VMl}mA{OqNXZomUcGQfFeaKJ>k`EJ!1ce;h6&`Q~>8A&JDV1DS?D+nO||3$B%t zuXh%Ta65z}Abj-3oIX+dlNUZaU6B^bS5{5XkY`g_5UP$avDtBs+p2szy!h2DLAB^Z zr@N!nr&rkGFKE>yr7x9q|*ab-vy762;-|LBD8 z&B%UKfYLCfckl{>7Ub$M*Mz~=CfNCQ`lhL$-X!8kz~PCh0szB>?w|{1d?==Ir|bfY z04%!P>Arhf=YC|k$z&Yvi>@|&z!#Jt%t4m;@I*RMFhFh_NW7bKIy<)S@+9}r(t?B$ zmH`3`KeB>bg2o3Zy|d*0s3g9?J_C6g9*?s#Bq6L7oK`J0$mc+wGUs9WN) z?wSw%uP3WB<;r~^mw>6Y)y4+6J1=fyb7yaJe=QqC+0AO4)WN~1TI`>nKQ$Xw7|pA$ z+}%d^I(cFASKiSN7L7PTIV~}c?#0PR)IkD>0|CWKq$~-i{h(_>b*0`bUu{b&e>GOW zx%|juNDuJEqW74U_^f@l6d1NPlyVe?OZaxG7WB0-F*=7&QYL46*psrVz@#^*jW&O1 zdERT_eCsyqlBFTHA@?z%BOQExU4qM>Uig)7cMCTD*%g%NHlBMRth4*Aq}2TjYiUzc z;h^I&S!Ib82k{g9{W8T0U??+_KUcCUG+OaJhOZa|mTx8BjDyIqus_J+{z~ehxtq7s>v7O9 z8_?K(;HqTX8{ME7{v+=MD{+Cx6c{F9rT8bw3T!UWJ?;Lqj!VV2?;;JLad*iPGrH4j z1?O@Sq&>GYbeyX;Y+MO!Vn<5s>YbXhr3JG4dz*WekIH4l$%+)oUbqp0;Vf28Rfp0h zm^Psp-x#tnWwFyG&~5g02N>(REGGwv?x${ZUakIVvs5e;%PjV~;-oXDQPR#njmI|9 zlzXn@NS2H%12v?WT(xsUwb6u$@;3HPiwT|dMUN|d;P>2W3B@z%*0xm!o+hcqEJ0S}YIld0tzTsdTkm68w-iJoO_3lX@3wXm4nLtX~PfCC~*hlRurg zFsZd%D&~)bwfUgLBxNMUS=iOc%mQ3T6HxTClI2eqI0hajtwmg2oR`}AOsg2K5q+X> zNI+6QzMgLebb-9z4`^OYqAK?WbE%lDO|AkX03Zmm*BX~|hVZh`Z}!pBFCo}BD>Ov| zcElwlk~UXp?p625-bsUcUH|y}TucrI;A} z4VV34AK(fS;FN3(WlYEr^V0w$I95Sb0-4;f74%?%z`Z-A0geU+26v^aX5v|MBkN3B zLh>~i6W!u%9U6a2=QQdi1%^zx&gjE+VWQj{_87J>V6p;~8dsem&v=Sgn>9;!Z?sld?jmf1+2gWlTCqNvC*KgR!4|N z5#}q*&4~B;<8tvFk`Zu(f0C#9%D3uW^SQY_X#u^ z!L>nFuQOiXJo}7s|1a*Lt-VL8=2#7L;8$OpjK%$K%|uq@c_`^2U5?_%unCj!%NsO(ngl^(?-Db{ICOq=YMM=W#W#Gquo2ItN4rSo@no)Wc{P|O;``4wiN)cn z9~<5a8>R0()Hilh#HGU{j&4Nc$q?D)oP4Cczzb%kWm1ETi{P%_a@k;Ol869y z;OxAe9re{IbfWxKZxSWca8rJMR!DC=M_)5e5bG(OphRl z=+b#<8%G!H?31dSncN8KNq|p=q3bTHM&mp}=y!!eV+_Cf zG5yR3h$Mm%^!q3xX`#T=h#uvJ>!{`qxZ*o6VUGxST^9ui#%8HMO)(D0%+By@ix1u((2k&IAcCg0a( zytup+gPD&op?{Jup<>2PN8R?sW10dd$KM#Cu}=rdNf5Uu3Ir7D-(^#a(LD3Me<`v~vm+iJ;&p`_ zR5u1wFyhDu-4QAr9U-|)5CFUkkl+f3pUjM|0sP_B)*YGuaHPIg_PB0>97k<;e=JbZ z96gK?(At*DB2Q$0lrXj%zk zfW4wd#D59tCU$Rls&z*i{70QI(qIYA0S!)8T9>t4J$56E1i_ft|6Gf#{T{zhEMKF`e zcsoTGqXb~;ZyFz+k)M}3@rvpyrDU3*F|)bdI&TNe{B-Z2i6^2J=kP5J75Hp1G)($D z>iiqb@^vNO{HSw+`c3kWi8Ylb3)xR_B<ditJQi*9|vd1M!TKM%3`hXxuy32Y!UE`NH ztmQ=u|HqHSEov?mJK|hlY738*nt`8!{5wfH$FJ@MX-b6WN8`NAgOM(nBn#!qBOgN* a-~h15Z(H@M`V|`T$$?5$m&57bJu30pn-tdVgPDsL0X2z8?n{^3U1+tL3%e_lA4_y+2BCnE5C?!T6~D zfwZo0Af67y^Bd2K*fZ*{5joGOfA-0_yOm)!M=$w&WVzwJv;moq;(0K$eg@5P$w3Fu8(r zP1*6{16NnSyK${_@8yEaCejJrXTqnYia+?e`I3q4Wx?-jwmx6A>f3?Y$1R@E>-(YH z_qg%>@8c?-eyNdi9}Z1Ze?O<#KYfFNYhcM|8+kTIgHJa4N0c6&w0?f)vgH}}D~`2a gI``!RRauv_R+PNkoXB+h70~w#p00i_>zopr0J%;Iy8r+H literal 0 HcmV?d00001 diff --git a/RedmineMobile/Libs/MLTableAlert/Images/MLTableAlertButton@2x.png b/RedmineMobile/Libs/MLTableAlert/Images/MLTableAlertButton@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..a1d3d2a2b181aa6bf1999176a1ae741a29d303e3 GIT binary patch literal 1377 zcmV-n1)lneP)4ntHu% z1X@z5R9hqxITZ?p&KYAafvcdKW5zhg9MrZ5_2#gYNhiYL@EHiYtcbFs=wdEw4!@vL z+?q@#PeO7r5P6~<}la3prcVvF+aZzlkH4!9A~Ifsr*E24}1pO-~-sSaLgFz_L$2W zD{n{4-*<|!P5z$xD@EdW#CE|Jcn>y?fOE{*Wlga1Xf%2jv9QVK^W4`?zOhg!a3wo{ zt6Td|n7hMTyXsEg8IQ+LGvK=JVZ%z_L#6{ zn-03H(_H35xm^B;$#t;OBT1|(^5Q` zIHPXYEXkNUelT%X-F~(tYwGw&(sfIYrYg><+b@>nOdTWMu*4`nmh`J7$EJ=?B>iT| z$yCLs>h`-Or>2hck|r(5o5Tf4H!UgLCEk+Q2BY{)(rru5OdX#~nzH2FB)*Vz$C3+^ z_)^jzmRy>|SCam;T;Xtd&G9^Mk()xHz!yEg z)O!<>#eu8uY_(c%bhAyMR;%%S;R=>y99(K~;OaXim{aRZ1mp2|S|1_@mvQ7SHPqt3 zh11d7te97Dod>S#X4>sGXJ!7EFu{FzCa j&M3rqM$WKHjfcMf1ndhq7@2mq00000NkvXXu0mjfn^A^I literal 0 HcmV?d00001 diff --git a/RedmineMobile/Libs/MLTableAlert/Images/MLTableAlertButtonPressed.png b/RedmineMobile/Libs/MLTableAlert/Images/MLTableAlertButtonPressed.png new file mode 100755 index 0000000000000000000000000000000000000000..5094083813e9d0260eb4b21fbf00c8574ca7c633 GIT binary patch literal 603 zcmV-h0;K(kP)dj zBuQR&g?G3Oj^nuJB0QVTp1BBzVfe&FI0%AAF2cU=KX4KDJnx>1uE+Y literal 0 HcmV?d00001 diff --git a/RedmineMobile/Libs/MLTableAlert/Images/MLTableAlertButtonPressed@2x.png b/RedmineMobile/Libs/MLTableAlert/Images/MLTableAlertButtonPressed@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..8ae06dc888e0cc9df3039584b381ef6e8fee306d GIT binary patch literal 1536 zcmXX_3pmqj7}u=H*g|NrgKF3#_e)lCtGVo%Y_!a&Iw zpeA5GJ0QT!pS?f^KrzDo*C-&aFSBhpZ`1-1M227qBmhBx$;JV|(ElUg%agnsPgVn{ zhr>FPd=-m^_;_tEb;yDj$8>gI>Y8a|s4eV#pdYFo3JuY4R&~}lDtOxIPE1NQQ@>q> z#g;R1VFd;Sd8HLY?QY2&laYIuC&te8?G9$fdY9@<+{lmX`!UiT6HaPqZuWVO3XY7d zaVinock}sig=l8>V!dNBANTc!H@G+mE97FB=Thd+@{ne zbNMe97ni<3BQlvRCR_Ow{c&?_-my#AD-h^x5s2wJ-#7%SAn(P%3FY@)kts(D@#>xg zg6@dnw6mGA@1ENFdhzuKY&N@2Y?s*;g%wHH!1mM0+we9y*;QY zG1Q|Y=|N78MtR=jygYY%)PHH0JUdWy=Bb4v;e3M=~b)&OJ*olYm*X$e^9>FLQHp4&tN+fy;p`T4QCV8{(AvFMDc zs1jw4@L)_<*VSEdQ$r|st_=%?ckcn)Zf1t^9v27%u`w|*?m&TJ7P5-Nxn>B+z7ieXZmh{qkui^s z>Xen2OR{9lj^8SnOy*M{9L7Cm3%swqOhxnlo(oY<07E#1!YuGG;K?rO@1V-+uQvtA zgkBj4<&+p)fVpp#$PKEbB+{oBw*C&Z%+}WYqwy}FmCnj~WiA(gNzF_BdI=~gb;ra; z2B=0QYr(*jGn8XdUKYsebe!O5AD8665mTt;;+X;y9z%l%>SI`et!!!}gJ5Atmn81X zp)n-}ET@!q#|_~@DMKi^M%oh`dQHJ0|E_cOUlwC21Wc|Su$kc8J|COAB)1i|@e zQxAzWI%6Y|2dwa2YU}$3=upi4j?9m5(eRT+gUr>pDvtfLm)8zzD=xQ9RO{>jL&{X3 z$&i7E;ib87+~sXSVz@ zKS<#=s`oy*RJ*!UM5VD+vnE@fE?@%7m%W8O&K#?YPEbg@9-nTDj@ z)}s9F-LPrkD)60s1KVpL(LA`_LD~cukn}HCrOf&O literal 0 HcmV?d00001 diff --git a/RedmineMobile/Libs/MLTableAlert/Images/MLTableAlertShadowMask.png b/RedmineMobile/Libs/MLTableAlert/Images/MLTableAlertShadowMask.png new file mode 100755 index 0000000000000000000000000000000000000000..d0e3c5da481c4de4f2090a89c2c4d26a5c78e5b0 GIT binary patch literal 400 zcmeAS@N?(olHy`uVBq!ia0vp^+(697!3HFMCO(@Aq+~K({6l~=6A*&{I}mF?X%PE@ zH}8sIAU(&^#W6%fROh@cA7h|M+r!D7FI1Go45S357tEaGvUrJkYm=Ym#lWl*tBs7- zGViO4yVCbr+J8?|Q+m|SA6N09EqmG4+UM`49-qDEag#FN%xmA~PJgPef3M(}ob(!_ zwQsG<_2*e6cB?*{krs9Pdqefp-(^pjgnJCnZ28tu{D1MBsL94X7u@wP-`ZE4-!I0S z#S>5(>+UkO)YmHiKhSyq|F7nXS_5RXgWNgwj3L*d00GyFo)b)j1U8E0x@=-}-4L>2 z;}x@nmDU^lU#e}o@P4m>v`3-Dz1ctQl@=Z6%svx1HAo^bbzAxU`fc93ze-%0EyAYoumdKI;Vst0PZKBssI20 literal 0 HcmV?d00001 diff --git a/RedmineMobile/Libs/MLTableAlert/Images/MLTableAlertShadowMask@2x.png b/RedmineMobile/Libs/MLTableAlert/Images/MLTableAlertShadowMask@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..ca2d8ecfc384dcabfc7804bd7f6d30993fe442fd GIT binary patch literal 1013 zcmeAS@N?(olHy`uVBq!ia0vp^Vn8gz!3HE#_5EXk6lZ})WHC@&6@(c*gH%3%RAjpN zhX83NAO-*K_xs;9f8QAM9R8ra z@A&l}GQl6s;*Nc;km`SYu_NkyPg|K*Me2!3mVf%>7yi_|cYJk)n3LSGzdOtqT{B+1 z@ae;;AB|J|>gIe>wPRV>JLCPavpb~1-L6!nnQXDyW0d0CwD#?il?oL?+ja|1e^fK4 z*I4=0=R`N>(}%4^H>rhxT>B__58wK7^_+4&zoVTNQtj?=ttaQi{F*(FZTsV-Iem`{ zHNG96cf%HDr{d{$nR~6(MOux%eJr2P-H?$^J`8s3wD#~eotcNbKP=U6zr6R;y&F=m zlS|k1JXOxJHI|B!i<8`x;-~j7%>R3-PR>TvYe%~xgt-4Z0(}Y6xJKR3hC_XBPxD6Q zoWnabo*mya!y0JgXECr>PR{uwum9zX;~1H=>U6UvZkD`!`SRiWFM6RaT6gpb|GPZC zBikaRy$`QG*Y}@w_Qeb9IDu|m_lJ>z;s5_$EhY#R%HvXkpYoOIMugIqQXq%J(8qoZQBN!eRfx=ifbXYsiA*G*ojZA$#O>-(MJdCx!B zzS~*eV;EMXf8A()^30R#a_0J|JuaV zZPqY3x^vFClRp|aYy-QcD)q##Ngr+Jf7a7qeBko*NADN^O#1T*=$2=%S3|-iS@-@Y yO+K4a(|31N%8Rts4&Rz*Y?}4;#Z<-Yx9nHn%B=J +#import + +@class MLTableAlert; + + +// Blocks definition for table view management +typedef NSInteger (^MLTableAlertNumberOfRowsBlock)(NSInteger section); +typedef UITableViewCell* (^MLTableAlertTableCellsBlock)(MLTableAlert *alert, NSIndexPath *indexPath); +typedef void (^MLTableAlertRowSelectionBlock)(NSIndexPath *selectedIndex); +typedef void (^MLTableAlertCompletionBlock)(void); + + +@interface MLTableAlert : UIView + +@property (nonatomic, strong) UITableView *table; + +@property (nonatomic, assign) CGFloat height; + +@property (nonatomic, strong) MLTableAlertCompletionBlock completionBlock; // Called when Cancel button pressed +@property (nonatomic, strong) MLTableAlertRowSelectionBlock selectionBlock; // Called when a row in table view is pressed + + +// Classe method; rowsBlock and cellsBlock MUST NOT be nil ++(MLTableAlert *)tableAlertWithTitle:(NSString *)title cancelButtonTitle:(NSString *)cancelBtnTitle numberOfRows:(MLTableAlertNumberOfRowsBlock)rowsBlock andCells:(MLTableAlertTableCellsBlock)cellsBlock; + +// Initialization method; rowsBlock and cellsBlock MUST NOT be nil +-(id)initWithTitle:(NSString *)title cancelButtonTitle:(NSString *)cancelBtnTitle numberOfRows:(MLTableAlertNumberOfRowsBlock)rowsBlock andCells:(MLTableAlertTableCellsBlock)cellsBlock; + +// Allows you to perform custom actions when a row is selected or the cancel button is pressed +-(void)configureSelectionBlock:(MLTableAlertRowSelectionBlock)selBlock andCompletionBlock:(MLTableAlertCompletionBlock)comBlock; + +// Show the alert +-(void)show; + +@end + diff --git a/RedmineMobile/Libs/MLTableAlert/MLTableAlert.m b/RedmineMobile/Libs/MLTableAlert/MLTableAlert.m new file mode 100755 index 0000000..75e1050 --- /dev/null +++ b/RedmineMobile/Libs/MLTableAlert/MLTableAlert.m @@ -0,0 +1,339 @@ +// +// MLTableAlert.m +// +// Version 1.0 +// +// Created by Matteo Del Vecchio on 11/12/12. +// Copyright (c) 2012 Matthew Labs. All rights reserved. +// For the complete copyright notice, read Source Code License. +// + +#import "MLTableAlert.h" + + +#define kTableAlertWidth 284.0 +#define kLateralInset 12.0 +#define kVerticalInset 8.0 +#define kMinAlertHeight 264.0 +#define kCancelButtonHeight 44.0 +#define kCancelButtonMargin 5.0 +#define kTitleLabelMargin 12.0 + + +// Since orientation is managed by view controllers, +// MLTableAlertController is used under the MLTableAlert +// to provide support for orientation and rotation +@interface MLTableAlertController : UIViewController +@end + +@implementation MLTableAlertController + +// Orientation support +-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation +{ + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) + return YES; + else + return (toInterfaceOrientation == UIInterfaceOrientationPortrait); +} + +-(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration +{ + MLTableAlert *ta = [self.view.subviews lastObject]; + if (ta != nil && [ta isKindOfClass:[MLTableAlert class]]) + { + // Rotate the MLTableAlert if orientation changes + // when it is visible on screen + [UIView animateWithDuration:duration animations:^{ + [ta sizeToFit]; + + CGFloat x = CGRectGetMidX(self.view.bounds); + CGFloat y = CGRectGetMidY(self.view.bounds); + ta.center = CGPointMake(x, y); + ta.frame = CGRectIntegral(ta.frame); + }]; + } + else + return; +} + +@end + + +@interface MLTableAlert () +@property (nonatomic, strong) UIView *alertBg; +@property (nonatomic, strong) UILabel *titleLabel; +@property (nonatomic, strong) UIButton *cancelButton; +@property (nonatomic, strong) UIWindow *appWindow; + +@property (nonatomic, strong) NSString *title; +@property (nonatomic, strong) NSString *cancelButtonTitle; + +@property (nonatomic) BOOL cellSelected; + +@property (nonatomic, strong) MLTableAlertNumberOfRowsBlock numberOfRows; +@property (nonatomic, strong) MLTableAlertTableCellsBlock cells; + +-(void)createBackgroundView; // Draws and manages the view behind the alert +-(void)animateIn; // Animates the alert when it has to be shown +-(void)animateOut; // Animates the alert when it has to be dismissed +-(void)dismissTableAlert; // Dismisses the alert +@end + + + +@implementation MLTableAlert + +#pragma mark - MLTableAlert Class Method + ++(MLTableAlert *)tableAlertWithTitle:(NSString *)title cancelButtonTitle:(NSString *)cancelBtnTitle numberOfRows:(MLTableAlertNumberOfRowsBlock)rowsBlock andCells:(MLTableAlertTableCellsBlock)cellsBlock +{ + return [[self alloc] initWithTitle:title cancelButtonTitle:cancelBtnTitle numberOfRows:rowsBlock andCells:cellsBlock]; +} + +#pragma mark - MLTableAlert Initialization + +-(id)initWithTitle:(NSString *)title cancelButtonTitle:(NSString *)cancelButtonTitle numberOfRows:(MLTableAlertNumberOfRowsBlock)rowsBlock andCells:(MLTableAlertTableCellsBlock)cellsBlock +{ + // Throw exception if rowsBlock or cellsBlock is nil + if (rowsBlock == nil || cellsBlock == nil) + { + [[NSException exceptionWithName:@"rowsBlock and cellsBlock Error" reason:@"These blocks MUST NOT be nil" userInfo:nil] raise]; + return nil; + } + + self = [super init]; + if (self) + { + _numberOfRows = rowsBlock; + _cells = cellsBlock; + _title = title; + _cancelButtonTitle = cancelButtonTitle; + _height = kMinAlertHeight; // Defining default (and minimum) alert height + } + + return self; +} + +#pragma mark - Actions + +-(void)configureSelectionBlock:(MLTableAlertRowSelectionBlock)selBlock andCompletionBlock:(MLTableAlertCompletionBlock)comBlock +{ + self.selectionBlock = selBlock; + self.completionBlock = comBlock; +} + +-(void)createBackgroundView +{ + // reset cellSelected value + self.cellSelected = NO; + + // Allocating controller for presenting MLTableAlert + MLTableAlertController *controller = [[MLTableAlertController alloc] init]; + controller.view.backgroundColor = [UIColor clearColor]; + + // Creating new UIWindow to manage MLTableAlert and MLTableAlertController + self.appWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; + self.appWindow.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.4]; + self.appWindow.rootViewController = controller; + self.appWindow.alpha = 0.0; + self.appWindow.windowLevel = UIWindowLevelStatusBar; + self.appWindow.hidden = NO; + [self.appWindow makeKeyAndVisible]; + + // Adding MLTableAlert as subview of MLTableAlertController (controller) + [controller.view addSubview:self]; + + // setting options to MLTableAlert + self.frame = self.superview.bounds; + self.opaque = NO; + + // get background color darker + [UIView animateWithDuration:0.2 animations:^{ + self.appWindow.alpha = 1.0; + }]; +} + +-(void)animateIn +{ + // UIAlertView-like pop in animation + self.alertBg.transform = CGAffineTransformMakeScale(0.6, 0.6); + [UIView animateWithDuration:0.2 animations:^{ + self.alertBg.transform = CGAffineTransformMakeScale(1.1, 1.1); + } completion:^(BOOL finished){ + [UIView animateWithDuration:1.0/15.0 animations:^{ + self.alertBg.transform = CGAffineTransformMakeScale(0.9, 0.9); + } completion:^(BOOL finished){ + [UIView animateWithDuration:1.0/7.5 animations:^{ + self.alertBg.transform = CGAffineTransformIdentity; + }]; + }]; + }]; +} + +-(void)animateOut +{ + [UIView animateWithDuration:1.0/7.5 animations:^{ + self.alertBg.transform = CGAffineTransformMakeScale(0.9, 0.9); + } completion:^(BOOL finished) { + [UIView animateWithDuration:1.0/15.0 animations:^{ + self.alertBg.transform = CGAffineTransformMakeScale(1.1, 1.1); + } completion:^(BOOL finished) { + [UIView animateWithDuration:0.3 animations:^{ + self.alertBg.transform = CGAffineTransformMakeScale(0.01, 0.01); + self.appWindow.alpha = 0.3; + } completion:^(BOOL finished){ + // table alert not shown anymore + [self removeFromSuperview]; + self.appWindow.hidden = YES; + [self.appWindow resignKeyWindow]; + }]; + }]; + }]; +} + +-(void)show +{ + [self createBackgroundView]; + + // alert view creation + self.alertBg = [[UIView alloc] initWithFrame:CGRectZero]; + [self addSubview:self.alertBg]; + + // setting alert background image + UIImageView *alertBgImage = [[UIImageView alloc] initWithImage:[[UIImage imageNamed:@"MLTableAlertBackground.png"] stretchableImageWithLeftCapWidth:15 topCapHeight:30]]; + [self.alertBg addSubview:alertBgImage]; + + // alert title creation + self.titleLabel = [[UILabel alloc] initWithFrame:CGRectZero]; + self.titleLabel.backgroundColor = [UIColor clearColor]; + self.titleLabel.textColor = [UIColor whiteColor]; + self.titleLabel.shadowColor = [[UIColor blackColor] colorWithAlphaComponent:0.75]; + self.titleLabel.shadowOffset = CGSizeMake(0, -1); + self.titleLabel.font = [UIFont boldSystemFontOfSize:18.0]; + self.titleLabel.frame = CGRectMake(kLateralInset, 15, kTableAlertWidth - kLateralInset * 2, 22); + self.titleLabel.text = self.title; + self.titleLabel.textAlignment = NSTextAlignmentCenter; + [self.alertBg addSubview:self.titleLabel]; + + // table view creation + self.table = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain]; + self.table.frame = CGRectMake(kLateralInset, self.titleLabel.frame.origin.y + self.titleLabel.frame.size.height + kTitleLabelMargin, kTableAlertWidth - kLateralInset * 2, (self.height - kVerticalInset * 2) - self.titleLabel.frame.origin.y - self.titleLabel.frame.size.height - kTitleLabelMargin - kCancelButtonMargin - kCancelButtonHeight); + self.table.layer.cornerRadius = 6.0; + self.table.layer.masksToBounds = YES; + self.table.delegate = self; + self.table.dataSource = self; + self.table.separatorStyle = UITableViewCellSeparatorStyleNone; + self.table.backgroundView = [[UIView alloc] init]; + [self.alertBg addSubview:self.table]; + + // setting white-to-gray gradient as table view's background + CAGradientLayer *tableGradient = [CAGradientLayer layer]; + tableGradient.frame = CGRectMake(0, 0, self.table.frame.size.width, self.table.frame.size.height); + tableGradient.colors = [NSArray arrayWithObjects:(id)[[UIColor colorWithRed:240.0/255.0 green:240.0/255.0 blue:240.0/255.0 alpha:1.0] CGColor], (id)[[UIColor colorWithRed:174.0/255.0 green:174.0/255.0 blue:174.0/255.0 alpha:1.0] CGColor], nil]; + [self.table.backgroundView.layer insertSublayer:tableGradient atIndex:0]; + + // adding inner shadow mask on table view + UIImageView *maskShadow = [[UIImageView alloc] initWithImage:[[UIImage imageNamed:@"MLTableAlertShadowMask.png"] stretchableImageWithLeftCapWidth:6 topCapHeight:7]]; + maskShadow.userInteractionEnabled = NO; + maskShadow.layer.masksToBounds = YES; + maskShadow.layer.cornerRadius = 5.0; + maskShadow.frame = self.table.frame; + [self.alertBg addSubview:maskShadow]; + + // cancel button creation + self.cancelButton = [UIButton buttonWithType:UIButtonTypeCustom]; + self.cancelButton.frame = CGRectMake(kLateralInset, self.table.frame.origin.y + self.table.frame.size.height + kCancelButtonMargin, kTableAlertWidth - kLateralInset * 2, kCancelButtonHeight); + self.cancelButton.titleLabel.textAlignment = NSTextAlignmentCenter; + self.cancelButton.titleLabel.font = [UIFont boldSystemFontOfSize:17.0]; + self.cancelButton.titleLabel.shadowOffset = CGSizeMake(0, -1); + self.cancelButton.titleLabel.shadowColor = [[UIColor blackColor] colorWithAlphaComponent:0.75]; + [self.cancelButton setTitle:self.cancelButtonTitle forState:UIControlStateNormal]; + [self.cancelButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + [self.cancelButton setBackgroundColor:[UIColor clearColor]]; + [self.cancelButton setBackgroundImage:[[UIImage imageNamed:@"MLTableAlertButton.png"] stretchableImageWithLeftCapWidth:5 topCapHeight:0] forState:UIControlStateNormal]; + [self.cancelButton setBackgroundImage:[[UIImage imageNamed:@"MLTableAlertButtonPressed.png"] stretchableImageWithLeftCapWidth:5 topCapHeight:0] forState:UIControlStateHighlighted]; + self.cancelButton.opaque = NO; + self.cancelButton.layer.cornerRadius = 5.0; + [self.cancelButton addTarget:self action:@selector(dismissTableAlert) forControlEvents:UIControlEventTouchUpInside]; + [self.alertBg addSubview:self.cancelButton]; + + // setting alert and alert background image frames + self.alertBg.frame = CGRectMake((self.frame.size.width - kTableAlertWidth) / 2, (self.frame.size.height - self.height) / 2, kTableAlertWidth, self.height - kVerticalInset * 2); + alertBgImage.frame = CGRectMake(0.0, 0.0, kTableAlertWidth, self.height); + + // the alert will be the first responder so any other controls, + // like the keyboard, will be dismissed before the alert + [self becomeFirstResponder]; + + // show the alert with animation + [self animateIn]; +} + +-(void)dismissTableAlert +{ + // dismiss the alert with its animation + [self animateOut]; + + // perform actions contained in completionBlock if the + // cancel button of the alert has been pressed + // if completionBlock == nil, nothing is performed + if (self.completionBlock != nil) + if (!self.cellSelected) + self.completionBlock(); +} + +// Allows the alert to be first responder +-(BOOL)canBecomeFirstResponder +{ + return YES; +} + +// Alert height setter +-(void)setHeight:(CGFloat)height +{ + if (height > kMinAlertHeight) + _height = height; + else + _height = kMinAlertHeight; +} + +#pragma mark - UITableViewDataSource + +-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView +{ + // TODO: Allow multiple sections + return 1; +} + +-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section +{ + // according to the numberOfRows block code + return self.numberOfRows(section); +} + +-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath +{ + // according to the cells block code + return self.cells(self, indexPath); +} + +#pragma mark - UITableViewDelegate + +-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath +{ + [tableView deselectRowAtIndexPath:indexPath animated:YES]; + + // set cellSelected to YES so the completionBlock won't be + // executed because a cell has been pressed instead of the cancel button + self.cellSelected = YES; + // dismiss the alert + [self dismissTableAlert]; + + // perform actions contained in the selectionBlock if it isn't nil + // add pass the selected indexPath + if (self.selectionBlock != nil) + self.selectionBlock(indexPath); +} + +@end diff --git a/RedmineMobile/RedmineMobile.xcodeproj/project.pbxproj b/RedmineMobile/RedmineMobile.xcodeproj/project.pbxproj index f7a22d2..35f7bba 100644 --- a/RedmineMobile/RedmineMobile.xcodeproj/project.pbxproj +++ b/RedmineMobile/RedmineMobile.xcodeproj/project.pbxproj @@ -12,6 +12,16 @@ 2B62D0E31796A15C00AC3C19 /* OZLProjectCreateViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2B62D0E21796A15C00AC3C19 /* OZLProjectCreateViewController.storyboard */; }; 2B62D0E51796A8C800AC3C19 /* OZLIssueFilterViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2B62D0E41796A8C800AC3C19 /* OZLIssueFilterViewController.storyboard */; }; 2B62D0E81796A8D800AC3C19 /* OZLIssueFilterViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2B62D0E71796A8D800AC3C19 /* OZLIssueFilterViewController.m */; }; + 2B6F382F1797A00A00D06F51 /* MLTableAlertBackground.png in Resources */ = {isa = PBXBuildFile; fileRef = 2B6F38251797A00A00D06F51 /* MLTableAlertBackground.png */; }; + 2B6F38301797A00A00D06F51 /* MLTableAlertBackground@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 2B6F38261797A00A00D06F51 /* MLTableAlertBackground@2x.png */; }; + 2B6F38311797A00A00D06F51 /* MLTableAlertButton.png in Resources */ = {isa = PBXBuildFile; fileRef = 2B6F38271797A00A00D06F51 /* MLTableAlertButton.png */; }; + 2B6F38321797A00A00D06F51 /* MLTableAlertButton@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 2B6F38281797A00A00D06F51 /* MLTableAlertButton@2x.png */; }; + 2B6F38331797A00A00D06F51 /* MLTableAlertButtonPressed.png in Resources */ = {isa = PBXBuildFile; fileRef = 2B6F38291797A00A00D06F51 /* MLTableAlertButtonPressed.png */; }; + 2B6F38341797A00A00D06F51 /* MLTableAlertButtonPressed@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 2B6F382A1797A00A00D06F51 /* MLTableAlertButtonPressed@2x.png */; }; + 2B6F38351797A00A00D06F51 /* MLTableAlertShadowMask.png in Resources */ = {isa = PBXBuildFile; fileRef = 2B6F382B1797A00A00D06F51 /* MLTableAlertShadowMask.png */; }; + 2B6F38361797A00A00D06F51 /* MLTableAlertShadowMask@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 2B6F382C1797A00A00D06F51 /* MLTableAlertShadowMask@2x.png */; }; + 2B6F38371797A00A00D06F51 /* MLTableAlert.m in Sources */ = {isa = PBXBuildFile; fileRef = 2B6F382E1797A00A00D06F51 /* MLTableAlert.m */; }; + 2B6F38391797BEBA00D06F51 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2B6F38381797BEBA00D06F51 /* QuartzCore.framework */; }; 2B8A11E217963CE500906D34 /* OZLIssueDetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2B8A11E117963CE500906D34 /* OZLIssueDetailViewController.m */; }; 2B9968AB1794F71B0086F115 /* OZLModelIssueCategory.m in Sources */ = {isa = PBXBuildFile; fileRef = 2B9968AA1794F71B0086F115 /* OZLModelIssueCategory.m */; }; 2B9968AF1794FC0A0086F115 /* OZLProjectCreateViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2B9968AD1794FC0A0086F115 /* OZLProjectCreateViewController.m */; }; @@ -69,6 +79,17 @@ 2B62D0E41796A8C800AC3C19 /* OZLIssueFilterViewController.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = OZLIssueFilterViewController.storyboard; path = ViewControllers/OZLIssueFilterViewController.storyboard; sourceTree = ""; }; 2B62D0E61796A8D800AC3C19 /* OZLIssueFilterViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OZLIssueFilterViewController.h; path = ViewControllers/OZLIssueFilterViewController.h; sourceTree = ""; }; 2B62D0E71796A8D800AC3C19 /* OZLIssueFilterViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OZLIssueFilterViewController.m; path = ViewControllers/OZLIssueFilterViewController.m; sourceTree = ""; }; + 2B6F38251797A00A00D06F51 /* MLTableAlertBackground.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = MLTableAlertBackground.png; sourceTree = ""; }; + 2B6F38261797A00A00D06F51 /* MLTableAlertBackground@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "MLTableAlertBackground@2x.png"; sourceTree = ""; }; + 2B6F38271797A00A00D06F51 /* MLTableAlertButton.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = MLTableAlertButton.png; sourceTree = ""; }; + 2B6F38281797A00A00D06F51 /* MLTableAlertButton@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "MLTableAlertButton@2x.png"; sourceTree = ""; }; + 2B6F38291797A00A00D06F51 /* MLTableAlertButtonPressed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = MLTableAlertButtonPressed.png; sourceTree = ""; }; + 2B6F382A1797A00A00D06F51 /* MLTableAlertButtonPressed@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "MLTableAlertButtonPressed@2x.png"; sourceTree = ""; }; + 2B6F382B1797A00A00D06F51 /* MLTableAlertShadowMask.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = MLTableAlertShadowMask.png; sourceTree = ""; }; + 2B6F382C1797A00A00D06F51 /* MLTableAlertShadowMask@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "MLTableAlertShadowMask@2x.png"; sourceTree = ""; }; + 2B6F382D1797A00A00D06F51 /* MLTableAlert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLTableAlert.h; sourceTree = ""; }; + 2B6F382E1797A00A00D06F51 /* MLTableAlert.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLTableAlert.m; sourceTree = ""; }; + 2B6F38381797BEBA00D06F51 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 2B8A11E017963CE500906D34 /* OZLIssueDetailViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OZLIssueDetailViewController.h; path = ViewControllers/OZLIssueDetailViewController.h; sourceTree = ""; }; 2B8A11E117963CE500906D34 /* OZLIssueDetailViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OZLIssueDetailViewController.m; path = ViewControllers/OZLIssueDetailViewController.m; sourceTree = ""; }; 2B9968A91794F71B0086F115 /* OZLModelIssueCategory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OZLModelIssueCategory.h; path = Models/OZLModelIssueCategory.h; sourceTree = ""; }; @@ -162,6 +183,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 2B6F38391797BEBA00D06F51 /* QuartzCore.framework in Frameworks */, 2BCF88141793CB94006FC859 /* SystemConfiguration.framework in Frameworks */, 2BCF88121793CB4F006FC859 /* CFNetwork.framework in Frameworks */, D5DB805A1792F2BF0081662A /* UIKit.framework in Frameworks */, @@ -173,6 +195,31 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 2B6F38231797A00A00D06F51 /* MLTableAlert */ = { + isa = PBXGroup; + children = ( + 2B6F38241797A00A00D06F51 /* Images */, + 2B6F382D1797A00A00D06F51 /* MLTableAlert.h */, + 2B6F382E1797A00A00D06F51 /* MLTableAlert.m */, + ); + path = MLTableAlert; + sourceTree = ""; + }; + 2B6F38241797A00A00D06F51 /* Images */ = { + isa = PBXGroup; + children = ( + 2B6F38251797A00A00D06F51 /* MLTableAlertBackground.png */, + 2B6F38261797A00A00D06F51 /* MLTableAlertBackground@2x.png */, + 2B6F38271797A00A00D06F51 /* MLTableAlertButton.png */, + 2B6F38281797A00A00D06F51 /* MLTableAlertButton@2x.png */, + 2B6F38291797A00A00D06F51 /* MLTableAlertButtonPressed.png */, + 2B6F382A1797A00A00D06F51 /* MLTableAlertButtonPressed@2x.png */, + 2B6F382B1797A00A00D06F51 /* MLTableAlertShadowMask.png */, + 2B6F382C1797A00A00D06F51 /* MLTableAlertShadowMask@2x.png */, + ); + path = Images; + sourceTree = ""; + }; 2BCB50FD1796370F006845AC /* Views */ = { isa = PBXGroup; children = ( @@ -254,6 +301,7 @@ D5DB80581792F2BF0081662A /* Frameworks */ = { isa = PBXGroup; children = ( + 2B6F38381797BEBA00D06F51 /* QuartzCore.framework */, 2BCF88131793CB94006FC859 /* SystemConfiguration.framework */, 2BCF88111793CB4F006FC859 /* CFNetwork.framework */, D5DB80591792F2BF0081662A /* UIKit.framework */, @@ -294,6 +342,7 @@ D5DB80761792F3EE0081662A /* Libs */ = { isa = PBXGroup; children = ( + 2B6F38231797A00A00D06F51 /* MLTableAlert */, 2BCF880D1793ABA0006FC859 /* Reachability */, 2BCF88091793A26A006FC859 /* MBProgressHUD */, D5DB80771792F3EE0081662A /* AFNetworking */, @@ -471,6 +520,14 @@ 2B62D0E1179649A800AC3C19 /* OZLIssueDetailViewController.storyboard in Resources */, 2B62D0E31796A15C00AC3C19 /* OZLProjectCreateViewController.storyboard in Resources */, 2B62D0E51796A8C800AC3C19 /* OZLIssueFilterViewController.storyboard in Resources */, + 2B6F382F1797A00A00D06F51 /* MLTableAlertBackground.png in Resources */, + 2B6F38301797A00A00D06F51 /* MLTableAlertBackground@2x.png in Resources */, + 2B6F38311797A00A00D06F51 /* MLTableAlertButton.png in Resources */, + 2B6F38321797A00A00D06F51 /* MLTableAlertButton@2x.png in Resources */, + 2B6F38331797A00A00D06F51 /* MLTableAlertButtonPressed.png in Resources */, + 2B6F38341797A00A00D06F51 /* MLTableAlertButtonPressed@2x.png in Resources */, + 2B6F38351797A00A00D06F51 /* MLTableAlertShadowMask.png in Resources */, + 2B6F38361797A00A00D06F51 /* MLTableAlertShadowMask@2x.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -517,6 +574,7 @@ 2BCCA0541795312E00FA8B1A /* OZLConstants.m in Sources */, 2B8A11E217963CE500906D34 /* OZLIssueDetailViewController.m in Sources */, 2B62D0E81796A8D800AC3C19 /* OZLIssueFilterViewController.m in Sources */, + 2B6F38371797A00A00D06F51 /* MLTableAlert.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/RedmineMobile/RedmineMobile/Models/OZLModelProject.h b/RedmineMobile/RedmineMobile/Models/OZLModelProject.h index 4c5281f..a9a5fe6 100644 --- a/RedmineMobile/RedmineMobile/Models/OZLModelProject.h +++ b/RedmineMobile/RedmineMobile/Models/OZLModelProject.h @@ -35,6 +35,8 @@ @property(nonatomic,strong) NSString* description; @property(nonatomic,strong) NSString* name; @property(nonatomic) int parentId; +@property(nonatomic) BOOL isPublic; +@property(nonatomic,strong) NSString* homepage; @property(nonatomic,strong) NSString* createdOn; @property(nonatomic,strong) NSString* updatedOn; diff --git a/RedmineMobile/RedmineMobile/Models/OZLModelProject.m b/RedmineMobile/RedmineMobile/Models/OZLModelProject.m index 23d4dd0..6f72fae 100644 --- a/RedmineMobile/RedmineMobile/Models/OZLModelProject.m +++ b/RedmineMobile/RedmineMobile/Models/OZLModelProject.m @@ -41,6 +41,7 @@ _identifier = [dic objectForKey:@"identifier"]; _name = [dic objectForKey:@"name"]; _description = [dic objectForKey:@"description"]; + _homepage = [dic objectForKey:@"homepage"]; _createdOn = [dic objectForKey:@"created_on"]; _updatedOn = [dic objectForKey:@"updated_on"]; NSDictionary* parent = [dic objectForKey:@"parent"]; @@ -61,7 +62,10 @@ [projectDic setObject:_description forKey:@"description"]; } if (_parentId > 0) { - [projectDic setObject:[NSNumber numberWithInt:_parentId] forKey:@"parent"]; + [projectDic setObject:[NSNumber numberWithInt:_parentId] forKey:@"parent_id"]; + } + if (_homepage.length > 0) { + [projectDic setObject:_homepage forKey:@"homepage"]; } return [[NSMutableDictionary alloc] initWithObjectsAndKeys:projectDic,@"project",nil]; diff --git a/RedmineMobile/RedmineMobile/Utils/OZLNetwork.m b/RedmineMobile/RedmineMobile/Utils/OZLNetwork.m index beeab35..96e41d8 100644 --- a/RedmineMobile/RedmineMobile/Utils/OZLNetwork.m +++ b/RedmineMobile/RedmineMobile/Utils/OZLNetwork.m @@ -114,8 +114,7 @@ if (block) { NSLog(@"the repsonse:%@",responseObject); - int repondNumber = [responseObject intValue]; - block(repondNumber == 201,nil); + block(YES,nil); } } failure:^(AFHTTPRequestOperation *operation, NSError *error) { diff --git a/RedmineMobile/RedmineMobile/ViewControllers/OZLProjectCreateViewController.h b/RedmineMobile/RedmineMobile/ViewControllers/OZLProjectCreateViewController.h index 502a4fc..13da6cc 100644 --- a/RedmineMobile/RedmineMobile/ViewControllers/OZLProjectCreateViewController.h +++ b/RedmineMobile/RedmineMobile/ViewControllers/OZLProjectCreateViewController.h @@ -7,9 +7,17 @@ // #import +#import "OZLModelProject.h" @interface OZLProjectCreateViewController : UITableViewController - (IBAction)onCancel:(id)sender; - (IBAction)onSave:(id)sender; +@property (weak, nonatomic) IBOutlet UITextField *name; +@property (weak, nonatomic) IBOutlet UITextField *identifier; +@property (weak, nonatomic) IBOutlet UITextField *homepageUrl; +@property (weak, nonatomic) IBOutlet UITextView *description; +@property (nonatomic) BOOL isPublic; +@property (nonatomic,strong) OZLModelProject* parentProject; +@property (nonatomic,strong) NSArray* projectList; @end diff --git a/RedmineMobile/RedmineMobile/ViewControllers/OZLProjectCreateViewController.m b/RedmineMobile/RedmineMobile/ViewControllers/OZLProjectCreateViewController.m index 313c2e8..cd2b951 100644 --- a/RedmineMobile/RedmineMobile/ViewControllers/OZLProjectCreateViewController.m +++ b/RedmineMobile/RedmineMobile/ViewControllers/OZLProjectCreateViewController.m @@ -7,8 +7,14 @@ // #import "OZLProjectCreateViewController.h" +#import "MBProgressHUD.h" +#import "OZLNetwork.h" +#import "MLTableAlert.h" -@interface OZLProjectCreateViewController () +@interface OZLProjectCreateViewController () { + MBProgressHUD * _HUD; + +} @end @@ -31,6 +37,11 @@ [self.navigationItem setLeftBarButtonItem:cancelBtn]; UIBarButtonItem* saveBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:self action:@selector(onSave:)]; [self.navigationItem setRightBarButtonItem:saveBtn]; + + + _HUD = [[MBProgressHUD alloc] initWithView:self.view]; + [self.view addSubview:_HUD]; + _HUD.labelText = @"Loading..."; } - (void)didReceiveMemoryWarning @@ -45,6 +56,99 @@ } - (IBAction)onSave:(id)sender { + + if (_name.text.length == 0) { + _HUD.mode = MBProgressHUDModeText; + _HUD.labelText = @"Project name can not be empty."; + [_HUD show:YES]; + [_HUD hide:YES afterDelay:1]; + + return; + } + if (_identifier.text.length == 0) { + _HUD.mode = MBProgressHUDModeText; + _HUD.labelText = @"Project identifier can not be empty."; + [_HUD show:YES]; + [_HUD hide:YES afterDelay:1]; + return; + } + + + OZLModelProject* projectData = [[OZLModelProject alloc] init]; + projectData.name = _name.text; + projectData.identifier = _identifier.text; + //TODO: is_public is not processed yet + + projectData.description = _description.text; + projectData.homepage = _homepageUrl.text; + if (_parentProject) { + projectData.parentId = _parentProject.index; + } + + _HUD.mode = MBProgressHUDModeIndeterminate; + _HUD.labelText = @"Creating Project..."; + [_HUD show:YES]; + [OZLNetwork createProject:projectData withParams:nil andBlock:^(BOOL success, NSError *error) { + if (error) { + NSLog(@"create project error: %@",error.description); + }else { + + } + [_HUD hide:YES]; + }]; } +- (void)viewDidUnload { + [self setName:nil]; + [self setIdentifier:nil]; + [self setHomepageUrl:nil]; + [self setDescription:nil]; + [super viewDidUnload]; +} + +-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath +{ + if (indexPath.section ==0 && indexPath.row == 4) {//parent project + // create the alert + MLTableAlert* tableAlert = [MLTableAlert tableAlertWithTitle:@"Parent Project" cancelButtonTitle:@"Cancel" numberOfRows:^NSInteger (NSInteger section) + { + return _projectList.count; + } + andCells:^UITableViewCell* (MLTableAlert *anAlert, NSIndexPath *indexPath) + { + static NSString *CellIdentifier = @"CellIdentifier"; + UITableViewCell *cell = [anAlert.table dequeueReusableCellWithIdentifier:CellIdentifier]; + if (cell == nil) + cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; + + if (indexPath.row == 0) { + cell.textLabel.text = @"None"; + }else { + cell.textLabel.text = [[_projectList objectAtIndex:indexPath.row - 1] name]; + } + return cell; + }]; + + // Setting custom alert height + tableAlert.height = 350; + + // configure actions to perform + [tableAlert configureSelectionBlock:^(NSIndexPath *selectedIndex){ + UITableViewCell* parentCell = [self.tableView cellForRowAtIndexPath:indexPath]; + if (selectedIndex.row == 0) { + _parentProject = nil; + parentCell.detailTextLabel.text = @"None"; + }else { + _parentProject = [_projectList objectAtIndex:selectedIndex.row - 1]; + parentCell.detailTextLabel.text = _parentProject.name; + } + [parentCell.detailTextLabel sizeToFit]; + } andCompletionBlock:^{ + + }]; + + // show the alert + [tableAlert show]; + } +} @end diff --git a/RedmineMobile/RedmineMobile/ViewControllers/OZLProjectCreateViewController.storyboard b/RedmineMobile/RedmineMobile/ViewControllers/OZLProjectCreateViewController.storyboard index 338fe56..cdfb4ff 100644 --- a/RedmineMobile/RedmineMobile/ViewControllers/OZLProjectCreateViewController.storyboard +++ b/RedmineMobile/RedmineMobile/ViewControllers/OZLProjectCreateViewController.storyboard @@ -112,7 +112,7 @@ -