Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d39bcfb7bd | ||
|
|
c7770c37d0 | ||
|
|
ca2fb81247 | ||
|
|
6a1543cb82 | ||
|
|
a2c0b47908 | ||
|
|
f2528b5e9a | ||
|
|
02f301dae0 | ||
|
|
6c47fc9023 | ||
|
|
f03adf727b | ||
|
|
77684dfe31 | ||
|
|
ee688d9ae4 | ||
|
|
9b16d3624e | ||
|
|
2fc75be3dd | ||
|
|
eb883bc51e | ||
|
|
fdc5ed93fc | ||
|
|
148960eecd | ||
|
|
0265fc36fa | ||
|
|
f4c2a0a7f8 | ||
|
|
de3eb861ed | ||
|
|
f5b64b4958 | ||
|
|
20eb59d9b6 | ||
|
|
ca1bb8e634 | ||
|
|
6213c098ce | ||
|
|
31023a1a71 | ||
|
|
b963b9547b | ||
|
|
fa4c0af78d | ||
|
|
ef0e0432a7 | ||
|
|
d16f2b54fe | ||
|
|
a3a3da309c | ||
|
|
fa7b71cabe | ||
|
|
d3490f6a2e | ||
|
|
82dc126952 | ||
|
|
6f90e765d4 | ||
|
|
b1382e8e89 | ||
|
|
0fb739935f | ||
|
|
e49a9f1f06 | ||
|
|
0f5dd99167 | ||
|
|
2f9f3db198 | ||
|
|
00ebc265d8 | ||
|
|
5995b42872 | ||
|
|
9edb0abda0 | ||
|
|
eaa966e72b | ||
|
|
a48df23252 | ||
|
|
3aa8eb9533 | ||
|
|
e407eeea40 | ||
|
|
873232d560 | ||
|
|
47cced540e | ||
|
|
5b4bddc2e0 | ||
|
|
cd511da678 | ||
|
|
c4fbef2dd3 | ||
|
|
92b997fb78 | ||
|
|
05d602c313 | ||
|
|
e1d92bd630 | ||
|
|
373951a75e | ||
|
|
f17898d43d | ||
|
|
129eef79a3 | ||
|
|
e3988e7b84 | ||
|
|
9174338140 | ||
|
|
642dc36c41 | ||
|
|
1016c3e22f | ||
|
|
b74d49b0bf | ||
|
|
8b29369b7e | ||
|
|
cb5fe06e58 | ||
|
|
4ebb2baf06 | ||
|
|
0f4a938dfc | ||
|
|
2a16fb5e09 | ||
|
|
c22cf71099 | ||
|
|
c739718710 | ||
|
|
2db9fd9657 | ||
|
|
56b613ff8a | ||
|
|
cd2e9e29d4 | ||
|
|
d1917db47e | ||
|
|
8024f6a804 | ||
|
|
46a0ce8e98 | ||
|
|
c7ccff914f | ||
|
|
8efb6f8808 | ||
|
|
006bf72c17 | ||
|
|
ec3af04f29 | ||
|
|
b45399a045 | ||
|
|
12ed70fec2 | ||
|
|
c3ce0a61b6 | ||
|
|
526e0725d8 | ||
|
|
7e4e0567ef | ||
|
|
ee13978115 | ||
|
|
f5d847f320 | ||
|
|
1df0da7509 | ||
|
|
e4bfd0ef5e | ||
|
|
2e66601c19 | ||
|
|
2484fb85e9 | ||
|
|
b2557c38dd | ||
|
|
56acbfc85c | ||
|
|
77f962eed4 | ||
|
|
18a6ecc79a | ||
|
|
c3fc6a087a | ||
|
|
02a47dc7b9 | ||
|
|
30413e6f8f | ||
|
|
6ed7354884 | ||
|
|
94f89acc84 | ||
|
|
392a6cfbca | ||
|
|
e03b6b3824 | ||
|
|
51940cea3d | ||
|
|
5ab346e5d1 | ||
|
|
243024e232 | ||
|
|
e62fd4dc00 | ||
|
|
547522a0a4 | ||
|
|
4fd3ce606a | ||
|
|
ad364b6184 | ||
|
|
3269ba10ec | ||
|
|
b0a7fe4079 | ||
|
|
31afae71d1 | ||
|
|
e7ae969c8e | ||
|
|
fc5bb7417f | ||
|
|
81e6c5c2fa | ||
|
|
e9f73cbb45 | ||
|
|
b36cc8f1e9 | ||
|
|
6f6938deb7 | ||
|
|
b63bddacb0 | ||
|
|
b1d56924e6 | ||
|
|
85d80e7ca0 | ||
|
|
d481d9cca5 | ||
|
|
fe25dbd872 | ||
|
|
0dcc645f22 | ||
|
|
f3090e7827 | ||
|
|
37b9895878 | ||
|
|
d5b4d66272 | ||
|
|
653f706f1b | ||
|
|
d106e6485b | ||
|
|
460a60440a | ||
|
|
9e66c699e1 | ||
|
|
86d2431925 | ||
|
|
d30659c37c | ||
|
|
1402133c32 | ||
|
|
5a99e18d7c | ||
|
|
afe326c1c1 | ||
|
|
e40612a032 | ||
|
|
9c6cca7db6 | ||
|
|
a5283a26ab | ||
|
|
e2020fa7f2 | ||
|
|
de3f6d3e82 | ||
|
|
e7cde2ca5f | ||
|
|
0c7b2ae702 | ||
|
|
1c822901e2 | ||
|
|
0cafb3fac5 | ||
|
|
d8718cc20f | ||
|
|
c484e4afe5 | ||
|
|
e155cca65e | ||
|
|
5cad5b095a | ||
|
|
2dff805d40 | ||
|
|
0afd65539f | ||
|
|
664d5777fd | ||
|
|
9a307269ca | ||
|
|
ab2657b795 | ||
|
|
57d435b6db | ||
|
|
de2e77cc86 | ||
|
|
ee5e22c574 | ||
|
|
1ce6a630d2 | ||
|
|
aee89b1f63 | ||
|
|
0f791be195 | ||
|
|
45248bcb65 | ||
|
|
3c092f36cb | ||
|
|
9a5afb70b5 | ||
|
|
f9275a70af | ||
|
|
8ee443a43c | ||
|
|
26223bb383 | ||
|
|
ea0c5e291f | ||
|
|
8ef7cacdda | ||
|
|
6d956c6138 | ||
|
|
b028e62731 | ||
|
|
fc43ec8185 | ||
|
|
491b5dcd6f | ||
|
|
02bbe0e6f5 | ||
|
|
b827b7ffce | ||
|
|
459374db1c | ||
|
|
97a65059e5 | ||
|
|
d629f4b501 | ||
|
|
f486c02b5e | ||
|
|
d63669ac22 | ||
|
|
ad82b0064a | ||
|
|
58f2d7117a | ||
|
|
735b0f8593 | ||
|
|
2bf012100a | ||
|
|
7abcc42a42 | ||
|
|
4d77e7dd6b | ||
|
|
5678fe3b83 | ||
|
|
f74888419c | ||
|
|
f21dcb8265 | ||
|
|
5bd07716eb | ||
|
|
c37f0cfaa9 | ||
|
|
9621d76faa | ||
|
|
32c252393a | ||
|
|
ef5d1d6e58 | ||
|
|
660d36e001 | ||
|
|
2cc67f23ab | ||
|
|
6fe3054738 | ||
|
|
7811521c08 | ||
|
|
96135c9875 | ||
|
|
0038eab6ab | ||
|
|
a34e8fbc9a | ||
|
|
0399b3daed | ||
|
|
64a15db791 | ||
|
|
49cb446f8b | ||
|
|
82c32d7dee | ||
|
|
bfd0ceac53 | ||
|
|
ba20936c17 | ||
|
|
4b058a8c56 | ||
|
|
49ba0cab27 | ||
|
|
b9c4f888b9 | ||
|
|
09e3c5ecfc | ||
|
|
b180f06c2a | ||
|
|
90345addce | ||
|
|
328172cfeb | ||
|
|
a75e5d914c | ||
|
|
a783479306 | ||
|
|
ecb557daa5 | ||
|
|
d5e811f9f1 | ||
|
|
3e5a6986f9 | ||
|
|
8e346f18bf | ||
|
|
34c7dededf | ||
|
|
e56cc85e96 | ||
|
|
8d660ff386 | ||
|
|
2e3c658bc8 | ||
|
|
7af50c3951 | ||
|
|
0bbada27f3 | ||
|
|
fcd2b778ea | ||
|
|
cbef08eeff | ||
|
|
6d3f430b24 | ||
|
|
e4516c19d3 | ||
|
|
8eb52f9a88 | ||
|
|
f2956670cd | ||
|
|
5b7afd72e3 | ||
|
|
643566bbfd | ||
|
|
5e0e61b7e5 | ||
|
|
608480c1d2 | ||
|
|
5979baa874 | ||
|
|
73a2823d0b | ||
|
|
804ffb826d | ||
|
|
4bcbe577c6 | ||
|
|
2b1b858776 | ||
|
|
8089f52744 | ||
|
|
3aaa887d68 | ||
|
|
b617d60b60 | ||
|
|
321a5533df | ||
|
|
921fcbdcd0 | ||
|
|
06d0357f74 | ||
|
|
2f7681f881 | ||
|
|
a822ec729a | ||
|
|
38370c7f2e | ||
|
|
37f65eb3dd | ||
|
|
9347ce2ede | ||
|
|
c4a839f47a | ||
|
|
43f7dcd08f | ||
|
|
71bfe4dd44 | ||
|
|
5bc44e7190 | ||
|
|
84c1b92fdf | ||
|
|
be6e222d8d | ||
|
|
7db488cdfb | ||
|
|
ca8a70a1ee | ||
|
|
903cc8ee83 | ||
|
|
13fe318110 | ||
|
|
b9b396a279 | ||
|
|
a2755221d0 | ||
|
|
83ec89fa20 | ||
|
|
68b193a782 | ||
|
|
fa5fd1e71c | ||
|
|
e051d02ad3 | ||
|
|
a3796fe128 | ||
|
|
c1e89bd1c3 | ||
|
|
aded1dd4da | ||
|
|
1e39281423 | ||
|
|
d92cc0f365 | ||
|
|
a5e39d1db3 | ||
|
|
7052ce9e63 | ||
|
|
8d036ab1d4 | ||
|
|
48276f989f | ||
|
|
57f2d3e26a | ||
|
|
c4924e4005 | ||
|
|
5c193f49df | ||
|
|
5b2ef77c2c | ||
|
|
371b660b33 | ||
|
|
228a95f776 | ||
|
|
cf93b72edd | ||
|
|
90c60cc5e4 | ||
|
|
e79ab4f47a | ||
|
|
4e946cbb27 | ||
|
|
d5c5070e59 | ||
|
|
50b3aabb76 | ||
|
|
b2fd84192b | ||
|
|
1a7f7cb197 | ||
|
|
ecab61929e | ||
|
|
ab4f0f87ca | ||
|
|
ae5b3c4c2d | ||
|
|
06240d1183 | ||
|
|
f3b3d8d759 | ||
|
|
8420f6ccfe | ||
|
|
f007ecf6c5 | ||
|
|
758a023267 | ||
|
|
fe6a576d84 | ||
|
|
d4f2d99a6b | ||
|
|
cb390325a6 | ||
|
|
1922ef974b | ||
|
|
de495aa1c5 | ||
|
|
cf0b4c8f03 | ||
|
|
aa4a4b07d8 | ||
|
|
75a4d8a2b9 | ||
|
|
b92214461e | ||
|
|
3f4ba87079 | ||
|
|
f1cfa14750 | ||
|
|
b24f5b6ad6 | ||
|
|
3dbce0e800 | ||
|
|
872fd126f4 | ||
|
|
efca50c6ac | ||
|
|
3cf013b25b | ||
|
|
92a5fa19fb | ||
|
|
1fcf13d149 | ||
|
|
bd20050db8 | ||
|
|
ce0233d0a2 | ||
|
|
0479e9b3f3 | ||
|
|
abdf1156d4 | ||
|
|
9ed30f563a | ||
|
|
d1985bad3b | ||
|
|
c83a4dc8e4 | ||
|
|
5484bbf8bf | ||
|
|
62e8d70d74 | ||
|
|
b2f1477b45 | ||
|
|
7323a5e393 | ||
|
|
f8205cc376 | ||
|
|
1b639ab978 | ||
|
|
4828f7478e | ||
|
|
9646f7039a | ||
|
|
6f921028de | ||
|
|
2508db0550 | ||
|
|
775141b7f7 | ||
|
|
a2d9c1aa72 | ||
|
|
4b639843ec | ||
|
|
464389a862 | ||
|
|
48b3eb259d | ||
|
|
4cebfbcd13 | ||
|
|
1767cf8ad4 | ||
|
|
b1981bb70c | ||
|
|
3dc581efbb | ||
|
|
655cc3256c | ||
|
|
bf5b660cb5 | ||
|
|
712dc493ca | ||
|
|
f4fba64ffb | ||
|
|
02430916cb | ||
|
|
e3ad115698 | ||
|
|
c078bb04b2 | ||
|
|
d95e133792 | ||
|
|
a04f1045bc | ||
|
|
db6975e07a | ||
|
|
93127489e7 | ||
|
|
83064294ac | ||
|
|
0b64758360 | ||
|
|
4e1a2c04a5 | ||
|
|
8412c1db21 | ||
|
|
18a7a9fdce | ||
|
|
fc90d00354 | ||
|
|
55861a8f44 | ||
|
|
4fbd307163 | ||
|
|
3e4c03852d | ||
|
|
c8a04b998b | ||
|
|
568a652fb4 | ||
|
|
a2c9b5c042 | ||
|
|
fd3a4b069d | ||
|
|
4aaafa6de7 | ||
|
|
97475fb27b | ||
|
|
26e29df657 | ||
|
|
269ab3884a | ||
|
|
d15a853bf7 | ||
|
|
b3f7f440c8 | ||
|
|
c298c968f5 | ||
|
|
5feac3a7ff | ||
|
|
215c1c53f5 | ||
|
|
7890085c6c | ||
|
|
12c427a9cf | ||
|
|
d686a0dadf | ||
|
|
eb186f550c | ||
|
|
01b631aea6 | ||
|
|
293114f1a0 | ||
|
|
20b92c03cb | ||
|
|
b6d76eb84e | ||
|
|
25bb51f4a3 | ||
|
|
4a3f51e550 | ||
|
|
d629a13499 | ||
|
|
07c0de71ec | ||
|
|
7470f4ffcf | ||
|
|
81f9748313 | ||
|
|
58928a5000 | ||
|
|
4c44ede945 | ||
|
|
d3c4105429 | ||
|
|
ed307adb22 | ||
|
|
8001688daf | ||
|
|
4c0687b9a5 | ||
|
|
33043dd8af | ||
|
|
1848f96efa | ||
|
|
51440cc7f7 | ||
|
|
09f100c0c2 | ||
|
|
a8b66abe15 | ||
|
|
03c45a78a9 | ||
|
|
6574d4450f | ||
|
|
d7f0ff84d6 | ||
|
|
5ef4c8e83e | ||
|
|
5ab48c6015 | ||
|
|
9119e08342 | ||
|
|
ce82ce1444 | ||
|
|
bbffd3d113 | ||
|
|
85cff2c0f3 | ||
|
|
9a0c621ad6 | ||
|
|
5c66104d25 | ||
|
|
c642d76e91 | ||
|
|
6d78ed3462 | ||
|
|
437142ed7b | ||
|
|
634c6dd455 | ||
|
|
3652931be8 | ||
|
|
7de3022a4a | ||
|
|
f82e52b7a2 | ||
|
|
c274f27810 | ||
|
|
88954b9bf6 | ||
|
|
f418f9de4c | ||
|
|
57f6ee7f78 | ||
|
|
f8457bd918 | ||
|
|
71c1369365 | ||
|
|
b015a6ea6c | ||
|
|
34072f3947 | ||
|
|
036b82afd9 | ||
|
|
52b5b3f741 | ||
|
|
c2f7f2ad27 | ||
|
|
bc9c78acfe | ||
|
|
7bd27ebd52 | ||
|
|
43ed8be114 | ||
|
|
a896fe7425 | ||
|
|
6c52e4936f | ||
|
|
32657793c8 | ||
|
|
63eb88c6ae | ||
|
|
28520cc493 | ||
|
|
8be05b404c | ||
|
|
96b791b5f9 | ||
|
|
ba9eac3ea4 | ||
|
|
717841877f | ||
|
|
cf06686d67 | ||
|
|
8d7594c96a | ||
|
|
ed36869f1d | ||
|
|
ea3adc44fd | ||
|
|
5fafc97bc0 | ||
|
|
fba900707a | ||
|
|
175a455d75 | ||
|
|
ffcef907b3 | ||
|
|
33317782ea | ||
|
|
3b9a0124fa | ||
|
|
5d5d03fd4c | ||
|
|
148f3172e6 | ||
|
|
972c14225b | ||
|
|
ce86c757cd | ||
|
|
cd6ffba9ac | ||
|
|
ab7209ceba | ||
|
|
63cca6190f | ||
|
|
0f2ec90064 | ||
|
|
4568dfabb9 | ||
|
|
2a78da6d07 | ||
|
|
c3505f865e | ||
|
|
3364e6c63b | ||
|
|
a129f2c5c5 | ||
|
|
770b0c7022 | ||
|
|
15a7a0459a | ||
|
|
6490858f43 | ||
|
|
aac6f75025 | ||
|
|
86945218de | ||
|
|
4632ba3ae5 | ||
|
|
38d63c3dc9 | ||
|
|
c64e5a5799 | ||
|
|
7c6ef51cb2 | ||
|
|
1e1297378c | ||
|
|
ac53b30f25 | ||
|
|
a5448549b1 | ||
|
|
a83b9109bf | ||
|
|
fdb079548e | ||
|
|
effd837cd0 | ||
|
|
089d564934 | ||
|
|
90c65c2927 | ||
|
|
7958775c6a | ||
|
|
ff99812c4d | ||
|
|
741ac31ba6 | ||
|
|
f953b4dc0f | ||
|
|
76ce921778 | ||
|
|
4819f3ca15 | ||
|
|
48dd722db9 | ||
|
|
57c2613d37 | ||
|
|
804927f893 | ||
|
|
f151920404 | ||
|
|
02f36a1abe | ||
|
|
c04041f110 | ||
|
|
a4702d48b4 | ||
|
|
ba27a4cc4a | ||
|
|
c28da78294 | ||
|
|
61f6ef4c19 | ||
|
|
d46b9b5aad | ||
|
|
7fc014f5d9 | ||
|
|
b28e0d15d8 | ||
|
|
0cc1679f64 | ||
|
|
e7a0e9ac70 | ||
|
|
025a43ea4e | ||
|
|
050fcf2ab8 | ||
|
|
c9642fcf35 | ||
|
|
79c257642c | ||
|
|
4f9d9d7a1d | ||
|
|
f14ac355f0 | ||
|
|
e0217477ce | ||
|
|
5e3bad2a36 | ||
|
|
26d6450f0a | ||
|
|
5923f7d859 | ||
|
|
57f6a5ca8c | ||
|
|
dd30ffa7ce | ||
|
|
8f5aa0ea16 | ||
|
|
1ddf21a256 | ||
|
|
9d8796c703 | ||
|
|
59a97272bb | ||
|
|
e9d328a309 | ||
|
|
448f2913eb | ||
|
|
d92b630069 | ||
|
|
584955caa8 | ||
|
|
951e81158c | ||
|
|
2a88e598ff | ||
|
|
3e5e88b369 | ||
|
|
4806c52ba6 | ||
|
|
86d186e279 | ||
|
|
5bf5388552 | ||
|
|
c19ed471ca | ||
|
|
9d694a1589 | ||
|
|
4dadf0cb95 | ||
|
|
de4bc67159 | ||
|
|
af37616e48 | ||
|
|
07f7ad0a05 | ||
|
|
fd355636d0 | ||
|
|
e8528271ee | ||
|
|
41ed80e0c4 | ||
|
|
e8fef8104d | ||
|
|
30c48df1f0 | ||
|
|
f14add2791 | ||
|
|
14cb6d21a9 | ||
|
|
eaa607b48d | ||
|
|
0bd2a032bb | ||
|
|
d6961889fb | ||
|
|
51ffd0d64a | ||
|
|
120ac31394 | ||
|
|
4284b97b43 | ||
|
|
d1615567e2 | ||
|
|
9ad3e50511 | ||
|
|
372372a0aa | ||
|
|
7f35ff5fe5 | ||
|
|
c28cd8a270 | ||
|
|
973940fcb2 | ||
|
|
a740f60734 | ||
|
|
2b557a0f8d | ||
|
|
cd19fc7c81 | ||
|
|
b5f9501001 | ||
|
|
8c0cd28f64 | ||
|
|
e8e10d4224 | ||
|
|
3e187df75b | ||
|
|
88d2ed9e93 | ||
|
|
ab5674aa4e | ||
|
|
81e4b6b37b | ||
|
|
b1507952df | ||
|
|
c4ac7cf375 | ||
|
|
c23292db8a | ||
|
|
a350ffeaa1 | ||
|
|
0efb7e67c9 | ||
|
|
a61e0f6cec | ||
|
|
0f5b36e9c5 | ||
|
|
93e7133076 | ||
|
|
2411edd461 | ||
|
|
af83065df5 | ||
|
|
1557c567d4 | ||
|
|
8bdaeab998 | ||
|
|
6825e3f7ce | ||
|
|
4602549ec8 | ||
|
|
a7b2df2450 | ||
|
|
3c0f6d3631 | ||
|
|
7ac37b75f3 | ||
|
|
b1e6d57bf1 | ||
|
|
f19c6a0a5b | ||
|
|
789279fe76 | ||
|
|
39a8d8803a | ||
|
|
f4ce73fc0d | ||
|
|
cac9d9266c | ||
|
|
7e94d02fb7 | ||
|
|
f3913b1dd2 | ||
|
|
50fc716c15 | ||
|
|
50412392f8 | ||
|
|
1b80859022 | ||
|
|
c6bd758793 | ||
|
|
cd4d657815 | ||
|
|
a4852b7a21 | ||
|
|
0b3c06abc0 | ||
|
|
1b351ad5bb | ||
|
|
1a1fc3ef21 | ||
|
|
fa3f18c88b | ||
|
|
904454d737 | ||
|
|
c1fb54ecad | ||
|
|
bd88b28310 | ||
|
|
de2397fa05 | ||
|
|
2513cf0969 | ||
|
|
15e16d86e4 | ||
|
|
26118ee881 | ||
|
|
232cf69006 | ||
|
|
9d2fba308d | ||
|
|
1171c9a0b2 | ||
|
|
9b397245f8 | ||
|
|
59b80ab8f6 | ||
|
|
18258877a8 | ||
|
|
e2b12c730e | ||
|
|
0a85b4b383 | ||
|
|
d5af9806ea | ||
|
|
104761d064 | ||
|
|
59065418ac | ||
|
|
7ccdc50637 | ||
|
|
f8ae61058e | ||
|
|
cc9d896cf8 | ||
|
|
c5637ea29b | ||
|
|
be3c4abbce | ||
|
|
d5c48567b3 | ||
|
|
5b4e7df856 | ||
|
|
23f04b3d09 | ||
|
|
050e3e86e3 | ||
|
|
c21d0c64a0 | ||
|
|
970b176fbf | ||
|
|
9e918cc717 | ||
|
|
4a31467afb | ||
|
|
86f07245d4 | ||
|
|
d51f179c2d | ||
|
|
974942a736 | ||
|
|
31d17cada7 | ||
|
|
647686e68e | ||
|
|
959212a95f | ||
|
|
45df8c0f74 | ||
|
|
1dbd41a746 | ||
|
|
8c43f4f628 | ||
|
|
633445883e | ||
|
|
e6acc3c336 | ||
|
|
90b947a7da | ||
|
|
b6b4015a82 | ||
|
|
2fd8940c02 | ||
|
|
7408710761 | ||
|
|
e4a4dd3219 | ||
|
|
745ad7cc34 | ||
|
|
821f8fea6f | ||
|
|
b0d90bb612 | ||
|
|
b439e0cfa0 | ||
|
|
68952b273b | ||
|
|
df148e4946 | ||
|
|
8b2f2fe24d | ||
|
|
ee668df440 | ||
|
|
6cae917058 | ||
|
|
cf99a7bf18 | ||
|
|
727b519750 | ||
|
|
861d093d80 | ||
|
|
c3d2decdec | ||
|
|
d862d701f3 | ||
|
|
883c4a185d | ||
|
|
7eb35ef33d | ||
|
|
1563b0bf55 | ||
|
|
bad731c86f | ||
|
|
5309cc5916 | ||
|
|
f8ef6ab397 | ||
|
|
9e61991ad2 | ||
|
|
c644e8a30f | ||
|
|
45a237af16 | ||
|
|
0450fdb542 | ||
|
|
7d304fbd51 | ||
|
|
33df895709 | ||
|
|
22ef6ca56a | ||
|
|
2e015c9816 | ||
|
|
1d40b5010e | ||
|
|
9d25f1c073 | ||
|
|
2a8de9cb28 | ||
|
|
67767ede17 | ||
|
|
03db4d73ad | ||
|
|
fcb1f4665f | ||
|
|
77ea0d3ea6 | ||
|
|
23ff035eb3 | ||
|
|
9906173a3f | ||
|
|
c6dd18ce40 | ||
|
|
a31ad2c367 | ||
|
|
7e20422e20 | ||
|
|
bd2f63c232 | ||
|
|
532a874ba6 | ||
|
|
48fa46e0d5 | ||
|
|
f72119f1b6 | ||
|
|
3063d53a2b | ||
|
|
e4163c5da4 | ||
|
|
a34ae45b05 | ||
|
|
d8e4f1150e | ||
|
|
c2534ae6da | ||
|
|
342ea97406 | ||
|
|
6f66c06111 | ||
|
|
aaeffe61a6 | ||
|
|
f5daa96c8e | ||
|
|
67fed5f3d7 | ||
|
|
4531b017b3 | ||
|
|
101a03c38d | ||
|
|
8147f648a1 | ||
|
|
30b1fa9c5b | ||
|
|
fa66c2692f | ||
|
|
1814f6b545 | ||
|
|
9d04ad5097 | ||
|
|
93b48ba973 | ||
|
|
047983d7bf | ||
|
|
ebccbf28a7 | ||
|
|
1dc84f9b58 | ||
|
|
35f3987803 | ||
|
|
b6bd132066 | ||
|
|
3ce2f28303 | ||
|
|
0d9cda8a85 | ||
|
|
f2decc09a5 | ||
|
|
b1c55b23ee | ||
|
|
4622600ab0 | ||
|
|
396358d4e5 | ||
|
|
8b975f50dd | ||
|
|
a1ea371c73 | ||
|
|
acd5442246 | ||
|
|
d176dd0623 | ||
|
|
68310bb479 | ||
|
|
e822966464 | ||
|
|
febce68bc8 | ||
|
|
fadffeedca | ||
|
|
2fc501fe59 | ||
|
|
21aac76ba2 | ||
|
|
fa3ebf2ca7 | ||
|
|
d2bf2539b5 | ||
|
|
8a0acedc94 | ||
|
|
11e5cd4f84 | ||
|
|
27fdb3116c | ||
|
|
b9c0c89a24 | ||
|
|
8078889a09 | ||
|
|
5dd4266ccc | ||
|
|
7d14676bce | ||
|
|
db113da121 | ||
|
|
5b2bfcef7d | ||
|
|
4d266f4ad2 | ||
|
|
b81a325b28 | ||
|
|
09eca10eb6 | ||
|
|
7b86465d7b | ||
|
|
40da5a849d | ||
|
|
ad170ed854 | ||
|
|
8d7c47a5e4 | ||
|
|
d7b5382c32 |
@@ -5,6 +5,7 @@ Demos
|
||||
./Aristo
|
||||
WebSite
|
||||
.push-package
|
||||
*.xcodeproj*
|
||||
*.xcodeproj/*.pbxuser
|
||||
*.xcodeproj/*.perspectivev3
|
||||
xcuserdata/
|
||||
@@ -15,3 +16,4 @@ xcuserdata/
|
||||
Tests/Manual/**/*.xcodeproj
|
||||
*.sublime-project
|
||||
*.sublime-workspace
|
||||
*.tm_properties
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- 0.8
|
||||
install: ./bootstrap.sh --quiet --noprompt --directory ./narwhal
|
||||
install: ./bootstrap.sh --noprompt --directory ./narwhal
|
||||
script: jake test
|
||||
env: PATH="$TRAVIS_BUILD_DIR/narwhal/bin:$PATH" CAPP_BUILD="$TRAVIS_BUILD_DIR/Build" NARWHAL_ENGINE=rhino
|
||||
|
||||
@@ -41,6 +41,10 @@
|
||||
|
||||
@global CPApp
|
||||
|
||||
var CPAlertDelegate_alertShowHelp_ = 1 << 0,
|
||||
CPAlertDelegate_alertDidEnd_returnCode_ = 1 << 1;
|
||||
|
||||
@typedef CPAlertStyle
|
||||
/*
|
||||
@global
|
||||
@group CPAlertStyle
|
||||
@@ -59,6 +63,62 @@ CPCriticalAlertStyle = 2;
|
||||
|
||||
var bottomHeight = 71;
|
||||
|
||||
@protocol CPAlertDelegate <CPObject>
|
||||
|
||||
@optional
|
||||
- (BOOL)alertShowHelp:(CPAlert)alert;
|
||||
- (void)alertDidEnd:(CPAlert)theAlert returnCode:(int)returnCode;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation _CPAlertThemeView : CPView
|
||||
|
||||
+ (CPString)defaultThemeClass
|
||||
{
|
||||
return @"alert";
|
||||
}
|
||||
|
||||
+ (CPDictionary)themeAttributes
|
||||
{
|
||||
return @{
|
||||
@"size": CGSizeMake(400.0, 110.0),
|
||||
@"content-inset": CGInsetMake(15, 15, 15, 50),
|
||||
@"informative-offset": 6,
|
||||
@"button-offset": 10,
|
||||
@"message-text-alignment": CPJustifiedTextAlignment,
|
||||
@"message-text-color": [CPColor blackColor],
|
||||
@"message-text-font": [CPFont boldSystemFontOfSize:13.0],
|
||||
@"message-text-shadow-color": [CPNull null],
|
||||
@"message-text-shadow-offset": CGSizeMakeZero(),
|
||||
@"informative-text-alignment": CPJustifiedTextAlignment,
|
||||
@"informative-text-color": [CPColor blackColor],
|
||||
@"informative-text-font": [CPFont systemFontOfSize:12.0],
|
||||
@"informative-text-shadow-color": [CPNull null],
|
||||
@"informative-text-shadow-offset": CGSizeMakeZero(),
|
||||
@"image-offset": CGPointMake(15, 12),
|
||||
@"information-image": [CPNull null],
|
||||
@"warning-image": [CPNull null],
|
||||
@"error-image": [CPNull null],
|
||||
@"help-image": [CPNull null],
|
||||
@"help-image-left-offset": 15,
|
||||
@"help-image-pressed": [CPNull null],
|
||||
@"suppression-button-y-offset": 0.0,
|
||||
@"suppression-button-x-offset": 0.0,
|
||||
@"default-elements-margin": 3.0,
|
||||
@"suppression-button-text-color": [CPColor blackColor],
|
||||
@"suppression-button-text-font": [CPFont systemFontOfSize:12.0],
|
||||
@"suppression-button-text-shadow-color": [CPNull null],
|
||||
@"suppression-button-text-shadow-offset": 0.0,
|
||||
@"modal-window-button-margin-y": 0.0,
|
||||
@"modal-window-button-margin-x": 0.0,
|
||||
@"standard-window-button-margin-y": 0.0,
|
||||
@"standard-window-button-margin-x": 0.0,
|
||||
};
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
/*!
|
||||
@ingroup appkit
|
||||
|
||||
@@ -83,32 +143,33 @@ var bottomHeight = 71;
|
||||
*/
|
||||
@implementation CPAlert : CPObject
|
||||
{
|
||||
BOOL _showHelp @accessors(property=showsHelp);
|
||||
BOOL _showSuppressionButton @accessors(property=showsSuppressionButton);
|
||||
BOOL _showHelp @accessors(property=showsHelp);
|
||||
BOOL _showSuppressionButton @accessors(property=showsSuppressionButton);
|
||||
|
||||
CPAlertStyle _alertStyle @accessors(property=alertStyle);
|
||||
CPString _title @accessors(property=title);
|
||||
CPView _accessoryView @accessors(property=accessoryView);
|
||||
CPImage _icon @accessors(property=icon);
|
||||
CPAlertStyle _alertStyle @accessors(property=alertStyle);
|
||||
CPString _title @accessors(property=title);
|
||||
CPView _accessoryView @accessors(property=accessoryView);
|
||||
CPImage _icon @accessors(property=icon);
|
||||
|
||||
CPArray _buttons @accessors(property=buttons, readonly);
|
||||
CPCheckBox _suppressionButton @accessors(property=suppressionButton, readonly);
|
||||
CPArray _buttons @accessors(property=buttons, readonly);
|
||||
CPCheckBox _suppressionButton @accessors(property=suppressionButton, readonly);
|
||||
|
||||
id _delegate @accessors(property=delegate);
|
||||
id _modalDelegate;
|
||||
SEL _didEndSelector @accessors(property=didEndSelector);
|
||||
Function _didEndBlock;
|
||||
id <CPAlertDelegate> _delegate @accessors(property=delegate);
|
||||
id _modalDelegate;
|
||||
SEL _didEndSelector @accessors(property=didEndSelector);
|
||||
Function _didEndBlock;
|
||||
unsigned _implementedDelegateMethods;
|
||||
|
||||
_CPAlertThemeView _themeView @accessors(property=themeView, readonly);
|
||||
CPWindow _window @accessors(property=window, readonly);
|
||||
int _defaultWindowStyle;
|
||||
_CPAlertThemeView _themeView @accessors(property=themeView, readonly);
|
||||
CPWindow _window @accessors(property=window, readonly);
|
||||
int _defaultWindowStyle;
|
||||
|
||||
CPImageView _alertImageView;
|
||||
CPTextField _informativeLabel;
|
||||
CPTextField _messageLabel;
|
||||
CPButton _alertHelpButton;
|
||||
CPImageView _alertImageView;
|
||||
CPTextField _informativeLabel;
|
||||
CPTextField _messageLabel;
|
||||
CPButton _alertHelpButton;
|
||||
|
||||
BOOL _needsLayout;
|
||||
BOOL _needsLayout;
|
||||
}
|
||||
|
||||
#pragma mark Creating Alerts
|
||||
@@ -187,6 +248,30 @@ var bottomHeight = 71;
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Delegate
|
||||
|
||||
/*!
|
||||
Set the delegate of the receiver
|
||||
@param aDelegate the delegate object for the alert.
|
||||
*/
|
||||
- (void)setDelegate:(id <CPAlertDelegate>)aDelegate
|
||||
{
|
||||
if (_delegate === aDelegate)
|
||||
return;
|
||||
|
||||
_delegate = aDelegate;
|
||||
_implementedDelegateMethods = 0;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(alertShowHelp:)])
|
||||
_implementedDelegateMethods |= CPAlertDelegate_alertShowHelp_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(alertDidEnd:returnCode:)])
|
||||
_implementedDelegateMethods |= CPAlertDelegate_alertDidEnd_returnCode_;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark Accessors
|
||||
|
||||
- (CPTheme)theme
|
||||
@@ -219,7 +304,7 @@ var bottomHeight = 71;
|
||||
[_themeView setValue:aValue forThemeAttribute:aName];
|
||||
}
|
||||
|
||||
- (void)setValue:(id)aValue forThemeAttribute:(CPString)aName inState:(CPThemeState)aState
|
||||
- (void)setValue:(id)aValue forThemeAttribute:(CPString)aName inState:(ThemeState)aState
|
||||
{
|
||||
[_themeView setValue:aValue forThemeAttribute:aName inState:aState];
|
||||
}
|
||||
@@ -696,8 +781,7 @@ var bottomHeight = 71;
|
||||
*/
|
||||
- (@action)_showHelp:(id)aSender
|
||||
{
|
||||
if ([_delegate respondsToSelector:@selector(alertShowHelp:)])
|
||||
[_delegate alertShowHelp:self];
|
||||
[self _sendDelegateAlertShowHelp];
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -743,56 +827,38 @@ var bottomHeight = 71;
|
||||
{
|
||||
if (_didEndSelector)
|
||||
objj_msgSend(_delegate, _didEndSelector, self, returnCode);
|
||||
else if ([_delegate respondsToSelector:@selector(alertDidEnd:returnCode:)])
|
||||
[_delegate alertDidEnd:self returnCode:returnCode];
|
||||
else
|
||||
[self _sendDelegateAlertDidEndReturnCode:returnCode];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation _CPAlertThemeView : CPView
|
||||
|
||||
+ (CPString)defaultThemeClass
|
||||
@implementation CPAlert (CPAlertDelegate)
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call the delegate alertDidEnd:returnCode
|
||||
*/
|
||||
- (void)_sendDelegateAlertDidEndReturnCode:(int)returnCode
|
||||
{
|
||||
return @"alert";
|
||||
if (!(_implementedDelegateMethods & CPAlertDelegate_alertDidEnd_returnCode_))
|
||||
return;
|
||||
|
||||
[_delegate alertDidEnd:self returnCode:returnCode];
|
||||
}
|
||||
|
||||
+ (CPDictionary)themeAttributes
|
||||
/*!
|
||||
@ignore
|
||||
Call the delegate alertShowHelp:
|
||||
*/
|
||||
- (BOOL)_sendDelegateAlertShowHelp
|
||||
{
|
||||
return @{
|
||||
@"size": CGSizeMake(400.0, 110.0),
|
||||
@"content-inset": CGInsetMake(15, 15, 15, 50),
|
||||
@"informative-offset": 6,
|
||||
@"button-offset": 10,
|
||||
@"message-text-alignment": CPJustifiedTextAlignment,
|
||||
@"message-text-color": [CPColor blackColor],
|
||||
@"message-text-font": [CPFont boldSystemFontOfSize:13.0],
|
||||
@"message-text-shadow-color": [CPNull null],
|
||||
@"message-text-shadow-offset": CGSizeMakeZero(),
|
||||
@"informative-text-alignment": CPJustifiedTextAlignment,
|
||||
@"informative-text-color": [CPColor blackColor],
|
||||
@"informative-text-font": [CPFont systemFontOfSize:12.0],
|
||||
@"informative-text-shadow-color": [CPNull null],
|
||||
@"informative-text-shadow-offset": CGSizeMakeZero(),
|
||||
@"image-offset": CGPointMake(15, 12),
|
||||
@"information-image": [CPNull null],
|
||||
@"warning-image": [CPNull null],
|
||||
@"error-image": [CPNull null],
|
||||
@"help-image": [CPNull null],
|
||||
@"help-image-left-offset": 15,
|
||||
@"help-image-pressed": [CPNull null],
|
||||
@"suppression-button-y-offset": 0.0,
|
||||
@"suppression-button-x-offset": 0.0,
|
||||
@"default-elements-margin": 3.0,
|
||||
@"suppression-button-text-color": [CPColor blackColor],
|
||||
@"suppression-button-text-font": [CPFont systemFontOfSize:12.0],
|
||||
@"suppression-button-text-shadow-color": [CPNull null],
|
||||
@"suppression-button-text-shadow-offset": 0.0,
|
||||
@"modal-window-button-margin-y": 0.0,
|
||||
@"modal-window-button-margin-x": 0.0,
|
||||
@"standard-window-button-margin-y": 0.0,
|
||||
@"standard-window-button-margin-x": 0.0,
|
||||
};
|
||||
if (!(_implementedDelegateMethods & CPAlertDelegate_alertShowHelp_))
|
||||
return YES;
|
||||
|
||||
return [_delegate alertShowHelp:self];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -26,25 +26,26 @@
|
||||
@import "CAMediaTimingFunction.j"
|
||||
|
||||
|
||||
/*
|
||||
@global
|
||||
@group CPAnimationCurve
|
||||
*/
|
||||
@protocol CPAnimationDelegate <CPObject>
|
||||
|
||||
@optional
|
||||
- (BOOL)animationShouldStart:(CPAnimation)animation;
|
||||
- (float)animation:(CPAnimation)animation valueForProgress:(float)progress;
|
||||
- (void)animationDidEnd:(CPAnimation)animation;
|
||||
- (void)animationDidStop:(CPAnimation)animation;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
var CPAnimationDelegate_animationShouldStart_ = 1 << 1,
|
||||
CPAnimationDelegate_animation_valueForProgress_ = 1 << 2,
|
||||
CPAnimationDelegate_animationDidEnd_ = 1 << 3,
|
||||
CPAnimationDelegate_animationDidStop_ = 1 << 4;
|
||||
|
||||
@typedef CPAnimationCurve
|
||||
CPAnimationEaseInOut = 0;
|
||||
/*
|
||||
@global
|
||||
@group CPAnimationCurve
|
||||
*/
|
||||
CPAnimationEaseIn = 1;
|
||||
/*
|
||||
@global
|
||||
@group CPAnimationCurve
|
||||
*/
|
||||
CPAnimationEaseOut = 2;
|
||||
/*
|
||||
@global
|
||||
@group CPAnimationCurve
|
||||
*/
|
||||
CPAnimationLinear = 3;
|
||||
|
||||
ACTUAL_FRAME_RATE = 0;
|
||||
@@ -80,17 +81,18 @@ ACTUAL_FRAME_RATE = 0;
|
||||
*/
|
||||
@implementation CPAnimation : CPObject
|
||||
{
|
||||
CPTimeInterval _lastTime;
|
||||
CPTimeInterval _duration;
|
||||
CPTimeInterval _lastTime;
|
||||
CPTimeInterval _duration;
|
||||
|
||||
CPAnimationCurve _animationCurve;
|
||||
CAMediaTimingFunction _timingFunction;
|
||||
CPAnimationCurve _animationCurve;
|
||||
CAMediaTimingFunction _timingFunction;
|
||||
|
||||
float _frameRate;
|
||||
float _progress;
|
||||
float _frameRate;
|
||||
float _progress;
|
||||
|
||||
id _delegate;
|
||||
CPTimer _timer;
|
||||
id <CPAnimationDelegate> _delegate;
|
||||
CPTimer _timer;
|
||||
unsigned _implementedDelegateMethods;
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -214,9 +216,25 @@ ACTUAL_FRAME_RATE = 0;
|
||||
Sets the animation's delegate.
|
||||
@param aDelegate the new delegate
|
||||
*/
|
||||
- (void)setDelegate:(id)aDelegate
|
||||
- (void)setDelegate:(id <CPAnimationDelegate>)aDelegate
|
||||
{
|
||||
if (_delegate === aDelegate)
|
||||
return;
|
||||
|
||||
_delegate = aDelegate;
|
||||
_implementedDelegateMethods = 0;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(animationShouldStart:)])
|
||||
_implementedDelegateMethods |= CPAnimationDelegate_animationShouldStart_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(animationDidEnd:)])
|
||||
_implementedDelegateMethods |= CPAnimationDelegate_animationDidEnd_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(animationDidStop:)])
|
||||
_implementedDelegateMethods |= CPAnimationDelegate_animationDidStop_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(animation:valueForProgress:)])
|
||||
_implementedDelegateMethods |= CPAnimationDelegate_animation_valueForProgress_;
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -227,7 +245,7 @@ ACTUAL_FRAME_RATE = 0;
|
||||
- (void)startAnimation
|
||||
{
|
||||
// If we're already animating, or our delegate stops us, animate.
|
||||
if (_timer || _delegate && [_delegate respondsToSelector:@selector(animationShouldStart:)] && ![_delegate animationShouldStart:self])
|
||||
if (_timer || ![self _sendDelegateAnimationShouldStart])
|
||||
return;
|
||||
|
||||
if (_progress === 1.0)
|
||||
@@ -236,7 +254,7 @@ ACTUAL_FRAME_RATE = 0;
|
||||
ACTUAL_FRAME_RATE = 0;
|
||||
_lastTime = new Date();
|
||||
|
||||
var timerInterval = _frameRate <= 0.0 ? 0.0001 : 1.0/_frameRate;
|
||||
var timerInterval = _frameRate <= 0.0 ? 0.0001 : 1.0 / _frameRate;
|
||||
|
||||
_timer = [CPTimer scheduledTimerWithTimeInterval:timerInterval target:self selector:@selector(animationTimerDidFire:) userInfo:nil repeats:YES];
|
||||
}
|
||||
@@ -260,8 +278,7 @@ ACTUAL_FRAME_RATE = 0;
|
||||
[_timer invalidate];
|
||||
_timer = nil;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(animationDidEnd:)])
|
||||
[_delegate animationDidEnd:self];
|
||||
[self _sendDelegateAnimationDidEnd];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,8 +293,7 @@ ACTUAL_FRAME_RATE = 0;
|
||||
[_timer invalidate];
|
||||
_timer = nil;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(animationDidStop:)])
|
||||
[_delegate animationDidStop:self];
|
||||
[self _sendDelegateAnimationDidStop];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -313,8 +329,8 @@ ACTUAL_FRAME_RATE = 0;
|
||||
{
|
||||
var t = [self currentProgress];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(animation:valueForProgress:)])
|
||||
return [_delegate animation:self valueForProgress:t];
|
||||
if ([self _delegateRespondsToAnimationValueForProgress])
|
||||
return [self _sendDelegateAnimationValueForProgress:t];
|
||||
|
||||
if (_animationCurve == CPAnimationLinear)
|
||||
return t;
|
||||
@@ -330,6 +346,68 @@ ACTUAL_FRAME_RATE = 0;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation CPAnimation (CPAnimationDelegate)
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Check if the delegate responds to animation:valueForProgress:
|
||||
*/
|
||||
- (BOOL)_delegateRespondsToAnimationValueForProgress
|
||||
{
|
||||
return _implementedDelegateMethods & CPAnimationDelegate_animation_valueForProgress_;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call delegate animationShouldStart:
|
||||
*/
|
||||
- (BOOL)_sendDelegateAnimationShouldStart
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPAnimationDelegate_animationShouldStart_))
|
||||
return YES;
|
||||
|
||||
return [_delegate animationShouldStart:self];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call delegate animation:valueForProgress:
|
||||
*/
|
||||
- (float)_sendDelegateAnimationValueForProgress:(float)aProgress
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPAnimationDelegate_animation_valueForProgress_))
|
||||
return aProgress;
|
||||
|
||||
return [_delegate animation:self valueForProgress:aProgress];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call delegate animationDidEnd:
|
||||
*/
|
||||
- (void)_sendDelegateAnimationDidEnd
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPAnimationDelegate_animationDidEnd_))
|
||||
return;
|
||||
|
||||
[_delegate animationDidEnd:self];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call delegate animationDidStop:
|
||||
*/
|
||||
- (void)_sendDelegateAnimationDidStop
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPAnimationDelegate_animationDidStop_))
|
||||
return;
|
||||
|
||||
[_delegate animationDidStop:self];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
// currently used function to determine time
|
||||
// 1:1 conversion to js from webkit source files
|
||||
// UnitBezier.h, WebCore_animation_AnimationBase.cpp
|
||||
|
||||
@@ -37,10 +37,27 @@
|
||||
@import "CPWindowController.j"
|
||||
@import "_CPPopoverWindow.j"
|
||||
|
||||
@typedef CPModalSession
|
||||
|
||||
var CPMainCibFile = @"CPMainCibFile",
|
||||
CPMainCibFileHumanFriendly = @"Main cib file base name",
|
||||
CPEventModifierFlags = 0;
|
||||
|
||||
|
||||
@protocol CPApplicationDelegate <CPObject>
|
||||
|
||||
@optional
|
||||
- (void)applicationDidBecomeActive:(CPNotification)aNotification;
|
||||
- (void)applicationDidChangeScreenParameters:(CPNotification)aNotification;
|
||||
- (void)applicationDidFinishLaunching:(CPNotification)aNotification;
|
||||
- (void)applicationDidResignActive:(CPNotification)aNotification;
|
||||
- (void)applicationWillBecomeActive:(CPNotification)aNotification;
|
||||
- (void)applicationWillFinishLaunching:(CPNotification)aNotification;
|
||||
- (void)applicationWillResignActive:(CPNotification)aNotification;
|
||||
- (void)applicationWillTerminate:(CPNotification)aNotification;
|
||||
|
||||
@end
|
||||
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@class CPApplication
|
||||
@@ -68,36 +85,36 @@ var CPMainCibFile = @"CPMainCibFile",
|
||||
*/
|
||||
@implementation CPApplication : CPResponder
|
||||
{
|
||||
CPArray _eventListeners;
|
||||
int _eventListenerInsertionIndex;
|
||||
CPArray _eventListeners;
|
||||
int _eventListenerInsertionIndex;
|
||||
|
||||
CPEvent _currentEvent;
|
||||
CPWindow _lastMouseMoveWindow;
|
||||
CPEvent _currentEvent;
|
||||
CPWindow _lastMouseMoveWindow;
|
||||
|
||||
CPArray _windows;
|
||||
CPWindow _keyWindow;
|
||||
CPWindow _mainWindow;
|
||||
CPWindow _previousKeyWindow;
|
||||
CPWindow _previousMainWindow;
|
||||
CPArray _windows;
|
||||
CPWindow _keyWindow;
|
||||
CPWindow _mainWindow;
|
||||
CPWindow _previousKeyWindow;
|
||||
CPWindow _previousMainWindow;
|
||||
|
||||
CPDocumentController _documentController;
|
||||
CPDocumentController _documentController;
|
||||
|
||||
CPModalSession _currentSession;
|
||||
CPModalSession _currentSession;
|
||||
|
||||
//
|
||||
id _delegate;
|
||||
BOOL _finishedLaunching;
|
||||
BOOL _isActive;
|
||||
id <CPApplicationDelegate> _delegate;
|
||||
BOOL _finishedLaunching;
|
||||
BOOL _isActive;
|
||||
|
||||
CPDictionary _namedArgs;
|
||||
CPArray _args;
|
||||
CPString _fullArgsString;
|
||||
CPDictionary _namedArgs;
|
||||
CPArray _args;
|
||||
CPString _fullArgsString;
|
||||
|
||||
CPImage _applicationIconImage;
|
||||
CPImage _applicationIconImage;
|
||||
|
||||
CPPanel _aboutPanel;
|
||||
CPPanel _aboutPanel;
|
||||
|
||||
CPThemeBlend _themeBlend @accessors(property=themeBlend);
|
||||
CPThemeBlend _themeBlend @accessors(property=themeBlend);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -143,7 +160,7 @@ var CPMainCibFile = @"CPMainCibFile",
|
||||
react to these events.
|
||||
@param aDelegate the delegate object
|
||||
*/
|
||||
- (void)setDelegate:(id)aDelegate
|
||||
- (void)setDelegate:(id <CPApplicationDelegate>)aDelegate
|
||||
{
|
||||
if (_delegate == aDelegate)
|
||||
return;
|
||||
@@ -433,7 +450,7 @@ var CPMainCibFile = @"CPMainCibFile",
|
||||
[CPPlatform activateIgnoringOtherApps:shouldIgnoreOtherApps];
|
||||
_isActive = YES;
|
||||
|
||||
[self _willResignActive];
|
||||
[self _didBecomeActive];
|
||||
}
|
||||
|
||||
- (void)deactivate
|
||||
@@ -971,7 +988,9 @@ var CPMainCibFile = @"CPMainCibFile",
|
||||
return;
|
||||
}
|
||||
|
||||
[aSheet._windowView _enableSheet:YES inWindow:aWindow];
|
||||
if (![aWindow attachedSheet])
|
||||
[aSheet._windowView _enableSheet:YES inWindow:aWindow];
|
||||
|
||||
[aWindow _attachSheet:aSheet modalDelegate:aModalDelegate didEndSelector:didEndSelector contextInfo:contextInfo];
|
||||
}
|
||||
|
||||
@@ -1158,7 +1177,7 @@ var CPMainCibFile = @"CPMainCibFile",
|
||||
[[self keyWindow] orderFront:self];
|
||||
else if ([self mainWindow])
|
||||
[[self mainWindow] makeKeyAndOrderFront:self];
|
||||
else
|
||||
else if ([self mainMenu])
|
||||
[[self mainMenu]._menuWindow makeKeyWindow]; //FIXME this may not actually work
|
||||
|
||||
_previousKeyWindow = nil;
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
*/
|
||||
|
||||
@import <Foundation/CPIndexSet.j>
|
||||
|
||||
@import <Foundation/CPPredicate.j>
|
||||
@import "CPObjectController.j"
|
||||
@import "CPKeyValueBinding.j"
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
@import "CPView.j"
|
||||
|
||||
// CPBoxType
|
||||
@typedef CPBoxType
|
||||
CPBoxPrimary = 0;
|
||||
CPBoxSecondary = 1;
|
||||
CPBoxSeparator = 2;
|
||||
@@ -31,12 +32,14 @@ CPBoxOldStyle = 3;
|
||||
CPBoxCustom = 4;
|
||||
|
||||
// CPBorderType
|
||||
@typedef CPBorderType
|
||||
CPNoBorder = 0;
|
||||
CPLineBorder = 1;
|
||||
CPBezelBorder = 2;
|
||||
CPGrooveBorder = 3;
|
||||
|
||||
// CPTitlePosition
|
||||
@typedef CPTitlePosition
|
||||
CPNoTitle = 0;
|
||||
CPAboveTop = 1;
|
||||
CPAtTop = 2;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
@import <Foundation/CPObject.j>
|
||||
@import <Foundation/CPIndexSet.j>
|
||||
|
||||
@import "CPControl.j"
|
||||
@@ -30,40 +31,86 @@
|
||||
|
||||
@global CPApp
|
||||
|
||||
@protocol CPBrowserDelegate <CPObject>
|
||||
|
||||
@optional
|
||||
- (BOOL)browser:(CPBrowser)browser acceptDrop:(id)info atRow:(CPInteger)row column:(CPInteger)column dropOperation:(CPTableViewDropOperation)dropOperation;
|
||||
- (BOOL)browser:(CPBrowser)browser canDragRowsWithIndexes:(CPIndexSet)rowIndexes inColumn:(CPInteger)column withEvent:(CPEvent )event;
|
||||
- (BOOL)browser:(CPBrowser)browser isLeafItem:(id)item;
|
||||
- (BOOL)browser:(CPBrowser)browser shouldSelectRowIndexes:(CPIndexSet)anIndexSet inColumn:(CPInteger)column;
|
||||
- (BOOL)browser:(CPBrowser)browser writeRowsWithIndexes:(CPIndexSet)rowIndexes inColumn:(CPInteger)column toPasteboard:(CPPasteboard)pasteboard;
|
||||
- (CPDragOperation)browser:(CPBrowser)browser validateDrop:(id)info proposedRow:(CPInteger)row column:(CPInteger)column dropOperation:(CPTableViewDropOperation)dropOperation;
|
||||
- (CPImage)browser:(CPBrowser)browser imageValueForItem:(id)anItem;
|
||||
- (CPImage)browser:(CPBrowser)browser draggingImageForRowsWithIndexes:(CPIndexSet)rowIndexes inColumn:(CPInteger)column withEvent:(CPEvent)event offset:(CGPoint)dragImageOffset;
|
||||
- (CPImage)browser:(CPBrowser)browser imageValueForItem:(id)item;
|
||||
- (CPIndexSet)browser:(CPBrowser)browser selectionIndexesForProposedSelection:(CPIndexSet)proposedSelectionIndexes inColumn:(CPInteger)column;
|
||||
- (CPInteger)browser:(CPBrowser)browser numberOfChildrenOfItem:(id)item;
|
||||
- (CPView)browser:(CPBrowser)browser draggingViewForRowsWithIndexes:(CPIndexSet)rowIndexes inColumn:(CPInteger)column withEvent:(CPEvent)event offset:(CGPoint)dragImageOffset;
|
||||
- (id)browser:(CPBrowser)browser child:(CPInteger)index ofItem:(id)item;
|
||||
- (id)browser:(CPBrowser)browser objectValueForItem:(id)item;
|
||||
- (id)rootItemForBrowser:(CPBrowser)browser;
|
||||
- (void)browser:(CPBrowser)browser didChangeLastColumn:(CPInteger)oldLastColumn toColumn:(CPInteger)column;
|
||||
- (void)browser:(CPBrowser)browser didResizeColumn:(CPInteger)column;
|
||||
- (void)browserSelectionIsChanging:(CPBrowser)browser;
|
||||
- (void)browserSelectionDidChange:(CPBrowser)browser;
|
||||
|
||||
@end
|
||||
|
||||
var CPBrowserDelegate_browser_acceptDrop_atRow_column_dropOperation_ = 1 << 1,
|
||||
CPBrowserDelegate_browser_canDragRowsWithIndexes_inColumn_withEvent_ = 1 << 2,
|
||||
CPBrowserDelegate_browser_isLeafItem_ = 1 << 3,
|
||||
CPBrowserDelegate_browser_shouldSelectRowIndexes_inColumn_ = 1 << 4,
|
||||
CPBrowserDelegate_browser_writeRowsWithIndexes_inColumn_toPasteboard_ = 1 << 5,
|
||||
CPBrowserDelegate_browser_validateDrop_proposedRow_column_dropOperation_ = 1 << 6,
|
||||
CPBrowserDelegate_browser_imageValueForItem_ = 1 << 7,
|
||||
CPBrowserDelegate_browser_draggingImageForRowsWithIndexes_inColumn_withEvent_offset_ = 1 << 8,
|
||||
CPBrowserDelegate_browser_imageValueForItem_ = 1 << 9,
|
||||
CPBrowserDelegate_browser_selectionIndexesForProposedSelection_inColumn_ = 1 << 10,
|
||||
CPBrowserDelegate_browser_numberOfChildrenOfItem_ = 1 << 11,
|
||||
CPBrowserDelegate_browser_draggingViewForRowsWithIndexes_inColumn_withEvent_offset_ = 1 << 12,
|
||||
CPBrowserDelegate_browser_child_ofItem_ = 1 << 13,
|
||||
CPBrowserDelegate_browser_objectValueForItem_ = 1 << 14,
|
||||
CPBrowserDelegate_rootItemForBrowser_ = 1 << 15,
|
||||
CPBrowserDelegate_browser_didChangeLastColumn_toColumn_ = 1 << 16,
|
||||
CPBrowserDelegate_browser_didResizeColumn_ = 1 << 17,
|
||||
CPBrowserDelegate_browserSelectionIsChanging_ = 1 << 18,
|
||||
CPBrowserDelegate_browserSelectionDidChange_ = 1 << 19;
|
||||
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@class CPBrowser
|
||||
*/
|
||||
@implementation CPBrowser : CPControl
|
||||
{
|
||||
id _delegate;
|
||||
CPString _pathSeparator;
|
||||
id <CPBrowserDelegate> _delegate;
|
||||
CPString _pathSeparator;
|
||||
unsigned _implementedDelegateMethods;
|
||||
|
||||
CPView _contentView;
|
||||
CPScrollView _horizontalScrollView;
|
||||
CPView _prototypeView;
|
||||
CPView _contentView;
|
||||
CPScrollView _horizontalScrollView;
|
||||
CPView _prototypeView;
|
||||
|
||||
CPArray _tableViews;
|
||||
CPArray _tableDelegates;
|
||||
CPArray _tableViews;
|
||||
CPArray _tableDelegates;
|
||||
|
||||
id _rootItem;
|
||||
id _rootItem;
|
||||
|
||||
BOOL _delegateSupportsImages;
|
||||
BOOL _delegateSupportsImages;
|
||||
|
||||
SEL _doubleAction @accessors(property=doubleAction);
|
||||
SEL _doubleAction @accessors(property=doubleAction);
|
||||
|
||||
BOOL _allowsMultipleSelection;
|
||||
BOOL _allowsEmptySelection;
|
||||
BOOL _allowsMultipleSelection;
|
||||
BOOL _allowsEmptySelection;
|
||||
|
||||
Class _tableViewClass @accessors(property=tableViewClass);
|
||||
Class _tableViewClass @accessors(property=tableViewClass);
|
||||
|
||||
float _rowHeight;
|
||||
float _imageWidth;
|
||||
float _leafWidth;
|
||||
float _minColumnWidth;
|
||||
float _defaultColumnWidth @accessors(property=defaultColumnWidth);
|
||||
float _rowHeight;
|
||||
float _imageWidth;
|
||||
float _leafWidth;
|
||||
float _minColumnWidth;
|
||||
float _defaultColumnWidth @accessors(property=defaultColumnWidth);
|
||||
|
||||
CPArray _columnWidths;
|
||||
CPArray _columnWidths;
|
||||
}
|
||||
|
||||
+ (CPString)defaultThemeClass
|
||||
@@ -137,10 +184,74 @@
|
||||
[CPKeyedArchiver archivedDataWithRootObject:_prototypeView]];
|
||||
}
|
||||
|
||||
- (void)setDelegate:(id)anObject
|
||||
- (void)setDelegate:(id <CPBrowserDelegate>)anObject
|
||||
{
|
||||
if (_delegate === anObject)
|
||||
return;
|
||||
|
||||
_delegate = anObject;
|
||||
_delegateSupportsImages = [_delegate respondsToSelector:@selector(browser:imageValueForItem:)];
|
||||
_implementedDelegateMethods = 0;
|
||||
_delegateSupportsImages = NO;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(browser:acceptDrop:atRow:column:dropOperation:)])
|
||||
_implementedDelegateMethods |= CPBrowserDelegate_browser_acceptDrop_atRow_column_dropOperation_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(browser:canDragRowsWithIndexes:inColumn:withEvent:)])
|
||||
_implementedDelegateMethods |= CPBrowserDelegate_browser_canDragRowsWithIndexes_inColumn_withEvent_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(browser:isLeafItem:)])
|
||||
_implementedDelegateMethods |= CPBrowserDelegate_browser_isLeafItem_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(browser:shouldSelectRowIndexes:inColumn:)])
|
||||
_implementedDelegateMethods |= CPBrowserDelegate_browser_shouldSelectRowIndexes_inColumn_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(browser:writeRowsWithIndexes:inColumn:toPasteboard:)])
|
||||
_implementedDelegateMethods |= CPBrowserDelegate_browser_writeRowsWithIndexes_inColumn_toPasteboard_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(browser:validateDrop:proposedRow:column:dropOperation:)])
|
||||
_implementedDelegateMethods |= CPBrowserDelegate_browser_validateDrop_proposedRow_column_dropOperation_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(browser:imageValueForItem:)])
|
||||
_implementedDelegateMethods |= CPBrowserDelegate_browser_imageValueForItem_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(browser:draggingImageForRowsWithIndexes:inColumn:withEvent:offset:)])
|
||||
_implementedDelegateMethods |= CPBrowserDelegate_browser_draggingImageForRowsWithIndexes_inColumn_withEvent_offset_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(browser:imageValueForItem:)])
|
||||
{
|
||||
_delegateSupportsImages = YES;
|
||||
_implementedDelegateMethods |= CPBrowserDelegate_browser_imageValueForItem_;
|
||||
}
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(browser:selectionIndexesForProposedSelection:inColumn:)])
|
||||
_implementedDelegateMethods |= CPBrowserDelegate_browser_selectionIndexesForProposedSelection_inColumn_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(browser:numberOfChildrenOfItem:)])
|
||||
_implementedDelegateMethods |= CPBrowserDelegate_browser_numberOfChildrenOfItem_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(browser:draggingViewForRowsWithIndexes:inColumn:withEvent:offset:)])
|
||||
_implementedDelegateMethods |= CPBrowserDelegate_browser_draggingViewForRowsWithIndexes_inColumn_withEvent_offset_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(browser:child:ofItem:)])
|
||||
_implementedDelegateMethods |= CPBrowserDelegate_browser_child_ofItem_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(browser:objectValueForItem:)])
|
||||
_implementedDelegateMethods |= CPBrowserDelegate_browser_objectValueForItem_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(rootItemForBrowser:)])
|
||||
_implementedDelegateMethods |= CPBrowserDelegate_rootItemForBrowser_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(browser:didChangeLastColumn:toColumn:)])
|
||||
_implementedDelegateMethods |= CPBrowserDelegate_browser_didChangeLastColumn_toColumn_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(browser:didChangeLastColumn:)])
|
||||
_implementedDelegateMethods |= CPBrowserDelegate_browser_didResizeColumn_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(browserSelectionIsChanging:)])
|
||||
_implementedDelegateMethods |= CPBrowserDelegate_browserSelectionIsChanging_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(browserSelectionDidChange:)])
|
||||
_implementedDelegateMethods |= CPBrowserDelegate_browserSelectionDidChange_;
|
||||
|
||||
[self loadColumnZero];
|
||||
}
|
||||
@@ -162,10 +273,7 @@
|
||||
|
||||
- (void)loadColumnZero
|
||||
{
|
||||
if ([_delegate respondsToSelector:@selector(rootItemForBrowser:)])
|
||||
_rootItem = [_delegate rootItemForBrowser:self];
|
||||
else
|
||||
_rootItem = nil;
|
||||
_rootItem = [self _sendDelegateRootItemForBrowser];
|
||||
|
||||
[self setLastColumn:-1];
|
||||
[self addColumn];
|
||||
@@ -190,8 +298,7 @@
|
||||
_tableViews = _tableViews.slice(0, indexPlusOne);
|
||||
_tableDelegates = _tableDelegates.slice(0, indexPlusOne);
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(browser:didChangeLastColumn:toColumn:)])
|
||||
[_delegate browser:self didChangeLastColumn:oldValue toColumn:columnIndex];
|
||||
[self _sendDelegateBrowserDidChangeLastColumn:oldValue toColumn:columnIndex];
|
||||
|
||||
[self tile];
|
||||
}
|
||||
@@ -366,7 +473,7 @@
|
||||
|
||||
- (BOOL)isLeafItem:(id)item
|
||||
{
|
||||
return [_delegate respondsToSelector:@selector(browser:isLeafItem:)] && [_delegate browser:self isLeafItem:item];
|
||||
return (_implementedDelegateMethods & CPBrowserDelegate_browser_isLeafItem_) && [_delegate browser:self isLeafItem:item];
|
||||
}
|
||||
|
||||
- (id)parentForItemsInColumn:(CPInteger)column
|
||||
@@ -493,9 +600,7 @@
|
||||
{
|
||||
_columnWidths[column] = aWidth;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(browser:didResizeColumn:)])
|
||||
[_delegate browser:self didResizeColumn:column];
|
||||
|
||||
[self _sendDelegateBrowserDidResizeColumn:column];
|
||||
[self tile];
|
||||
}
|
||||
|
||||
@@ -610,15 +715,12 @@
|
||||
if (column < 0 || column > [self lastColumn] + 1)
|
||||
return;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(browser:selectionIndexesForProposedSelection:inColumn:)])
|
||||
indexSet = [_delegate browser:self selectionIndexesForProposedSelection:indexSet inColumn:column];
|
||||
indexSet = [self _sendDelegateBrowserSelectionIndexesForProposedSelection:indexSet inColumn:column];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(browser:shouldSelectRowIndexes:inColumn:)] &&
|
||||
![_delegate browser:self shouldSelectRowIndexes:indexSet inColumn:column])
|
||||
if (![self _sendDelegateBrowserShouldSelectRowIndexes:indexSet inColumn:column])
|
||||
return;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(browserSelectionIsChanging:)])
|
||||
[_delegate browserSelectionIsChanging:self];
|
||||
[self _sendDelegateBrowserSelectionIsChanging];
|
||||
|
||||
if (column > [self lastColumn])
|
||||
[self addColumn];
|
||||
@@ -629,8 +731,7 @@
|
||||
|
||||
[self scrollColumnToVisible:column];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(browserSelectionDidChange:)])
|
||||
[_delegate browserSelectionDidChange:self];
|
||||
[self _sendDelegateBrowserSelectionDidChange];
|
||||
}
|
||||
|
||||
- (void)setBackgroundColor:(CPColor)aColor
|
||||
@@ -652,30 +753,6 @@
|
||||
[_tableViews makeObjectsPerformSelector:@selector(registerForDraggedTypes:) withObject:types];
|
||||
}
|
||||
|
||||
- (BOOL)canDragRowsWithIndexes:(CPIndexSet)rowIndexes inColumn:(CPInteger)columnIndex withEvent:(CPEvent)dragEvent
|
||||
{
|
||||
if ([_delegate respondsToSelector:@selector(browser:canDragRowsWithIndexes:inColumn:withEvent:)])
|
||||
return [_delegate browser:self canDragRowsWithIndexes:rowIndexes inColumn:columnIndex withEvent:dragEvent];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (CPImage)draggingImageForRowsWithIndexes:(CPIndexSet)rowIndexes inColumn:(CPInteger)columnIndex withEvent:(CPEvent)dragEvent offset:(CGPoint)dragImageOffset
|
||||
{
|
||||
if ([_delegate respondsToSelector:@selector(browser:draggingImageForRowsWithIndexes:inColumn:withEvent:offset:)])
|
||||
return [_delegate browser:self draggingImageForRowsWithIndexes:rowIndexes inColumn:columnIndex withEvent:dragEvent offset:dragImageOffset];
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (CPView)draggingViewForRowsWithIndexes:(CPIndexSet)rowIndexes inColumn:(CPInteger)columnIndex withEvent:(CPEvent)dragEvent offset:(CGPoint)dragImageOffset
|
||||
{
|
||||
if ([_delegate respondsToSelector:@selector(browser:draggingViewForRowsWithIndexes:inColumn:withEvent:offset:)])
|
||||
return [_delegate browser:self draggingViewForRowsWithIndexes:rowIndexes inColumn:columnIndex withEvent:dragEvent offset:dragImageOffset];
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPBrowser (CPCoding)
|
||||
@@ -860,8 +937,6 @@
|
||||
|
||||
@end
|
||||
|
||||
@import <Foundation/CPObject.j>
|
||||
|
||||
@implementation _CPBrowserTableDelegate : CPObject
|
||||
{
|
||||
CPBrowser _browser @accessors;
|
||||
@@ -909,7 +984,7 @@
|
||||
|
||||
- (BOOL)tableView:(CPTableView)aTableView acceptDrop:(id)info row:(CPInteger)row dropOperation:(CPTableViewDropOperation)operation
|
||||
{
|
||||
if ([_delegate respondsToSelector:@selector(browser:acceptDrop:atRow:column:dropOperation:)])
|
||||
if (_browser._implementedDelegateMethods & CPBrowserDelegate_browser_acceptDrop_atRow_column_dropOperation_)
|
||||
return [_delegate browser:_browser acceptDrop:info atRow:row column:_index dropOperation:operation];
|
||||
else
|
||||
return NO;
|
||||
@@ -917,7 +992,7 @@
|
||||
|
||||
- (CPDragOperation)tableView:(CPTableView)aTableView validateDrop:(id)info proposedRow:(CPInteger)row proposedDropOperation:(CPTableViewDropOperation)operation
|
||||
{
|
||||
if ([_delegate respondsToSelector:@selector(browser:validateDrop:proposedRow:column:dropOperation:)])
|
||||
if (_browser._implementedDelegateMethods & CPBrowserDelegate_browser_validateDrop_proposedRow_column_dropOperation_)
|
||||
return [_delegate browser:_browser validateDrop:info proposedRow:row column:_index dropOperation:operation];
|
||||
else
|
||||
return CPDragOperationNone;
|
||||
@@ -925,7 +1000,7 @@
|
||||
|
||||
- (BOOL)tableView:(CPTableView)aTableView writeRowsWithIndexes:(CPIndexSet)rowIndexes toPasteboard:(CPPasteboard)pboard
|
||||
{
|
||||
if ([_delegate respondsToSelector:@selector(browser:writeRowsWithIndexes:inColumn:toPasteboard:)])
|
||||
if (_browser._implementedDelegateMethods & CPBrowserDelegate_browser_writeRowsWithIndexes_inColumn_toPasteboard_)
|
||||
return [_delegate browser:_browser writeRowsWithIndexes:rowIndexes inColumn:_index toPasteboard:pboard];
|
||||
else
|
||||
return NO;
|
||||
@@ -980,7 +1055,7 @@
|
||||
var imageView = [self layoutEphemeralSubviewNamed:@"image-view"
|
||||
positioned:CPWindowAbove
|
||||
relativeToEphemeralSubviewNamed:nil],
|
||||
isHighlighted = [self themeState] & CPThemeStateSelectedDataView;
|
||||
isHighlighted = [self hasThemeState:CPThemeStateSelectedDataView];
|
||||
|
||||
[imageView setImage: _isLeaf ? (isHighlighted ? _highlightedBranchImage : _branchImage) : nil];
|
||||
[imageView setImageScaling:CPImageScaleNone];
|
||||
@@ -1008,3 +1083,115 @@
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPBrowser (CPBrowserDelegate)
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call delegate rootItemForBrowser:
|
||||
*/
|
||||
- (id)_sendDelegateRootItemForBrowser
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPBrowserDelegate_rootItemForBrowser_))
|
||||
return nil;
|
||||
|
||||
return [_delegate rootItemForBrowser:self];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call delegate browser:didChangeLastColumn:toColumn:
|
||||
*/
|
||||
- (void)_sendDelegateBrowserDidChangeLastColumn:(CPInteger)lastColumn toColumn:(CPInteger)newColumn
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPBrowserDelegate_browser_didChangeLastColumn_toColumn_))
|
||||
return;
|
||||
|
||||
[_delegate browser:self didChangeLastColumn:lastColumn toColumn:newColumn];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call delegate browser:didResizeColumn:
|
||||
*/
|
||||
- (void)_sendDelegateBrowserDidResizeColumn:(CPInteger)column
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPBrowserDelegate_browser_didResizeColumn_))
|
||||
return;
|
||||
|
||||
[_delegate browser:self didResizeColumn:column];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call delegate browserSelectionIsChanging:
|
||||
*/
|
||||
- (void)_sendDelegateBrowserSelectionIsChanging
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPBrowserDelegate_browserSelectionIsChanging_))
|
||||
return;
|
||||
|
||||
[_delegate browserSelectionIsChanging:self];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call delegate browser:shouldSelectRowIndexes:inColumn:
|
||||
*/
|
||||
- (BOOL)_sendDelegateBrowserShouldSelectRowIndexes:(CPIndexSet)anIndexSet inColumn:(CPInteger)aColumn
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPBrowserDelegate_browser_shouldSelectRowIndexes_inColumn_))
|
||||
return YES;
|
||||
|
||||
return [_delegate browser:self shouldSelectRowIndexes:anIndexSet inColumn:aColumn];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call delegate browser:selectionIndexesForProposedSelection:inColumn:
|
||||
*/
|
||||
- (CPIndexSet)_sendDelegateBrowserSelectionIndexesForProposedSelection:(CPIndexSet)anIndexSet inColumn:(CPInteger)aColumn
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPBrowserDelegate_browser_selectionIndexesForProposedSelection_inColumn_))
|
||||
return anIndexSet;
|
||||
|
||||
return [_delegate browser:self selectionIndexesForProposedSelection:anIndexSet inColumn:aColumn];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call delegate browserSelectionDidChange
|
||||
*/
|
||||
- (void)_sendDelegateBrowserSelectionDidChange
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPBrowserDelegate_browserSelectionDidChange_))
|
||||
return;
|
||||
|
||||
[_delegate browserSelectionDidChange:self];
|
||||
}
|
||||
|
||||
- (BOOL)canDragRowsWithIndexes:(CPIndexSet)rowIndexes inColumn:(CPInteger)columnIndex withEvent:(CPEvent)dragEvent
|
||||
{
|
||||
if (_implementedDelegateMethods & CPBrowserDelegate_browser_canDragRowsWithIndexes_inColumn_withEvent_)
|
||||
return [_delegate browser:self canDragRowsWithIndexes:rowIndexes inColumn:columnIndex withEvent:dragEvent];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (CPImage)draggingImageForRowsWithIndexes:(CPIndexSet)rowIndexes inColumn:(CPInteger)columnIndex withEvent:(CPEvent)dragEvent offset:(CGPoint)dragImageOffset
|
||||
{
|
||||
if (_implementedDelegateMethods & CPBrowserDelegate_browser_draggingImageForRowsWithIndexes_inColumn_withEvent_offset_)
|
||||
return [_delegate browser:self draggingImageForRowsWithIndexes:rowIndexes inColumn:columnIndex withEvent:dragEvent offset:dragImageOffset];
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (CPView)draggingViewForRowsWithIndexes:(CPIndexSet)rowIndexes inColumn:(CPInteger)columnIndex withEvent:(CPEvent)dragEvent offset:(CGPoint)dragImageOffset
|
||||
{
|
||||
if (_implementedDelegateMethods & CPBrowserDelegate_browser_draggingViewForRowsWithIndexes_inColumn_withEvent_offset_)
|
||||
return [_delegate browser:self draggingViewForRowsWithIndexes:rowIndexes inColumn:columnIndex withEvent:dragEvent offset:dragImageOffset];
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -29,8 +29,7 @@
|
||||
@import "CPWindow_Constants.j"
|
||||
|
||||
/* @group CPBezelStyle */
|
||||
|
||||
// IB style
|
||||
@typedef CPBezelStyle
|
||||
CPRoundedBezelStyle = 1; // Push
|
||||
CPRegularSquareBezelStyle = 2; // Bevel
|
||||
CPThickSquareBezelStyle = 3;
|
||||
@@ -49,6 +48,7 @@ CPHUDBezelStyle = -1;
|
||||
|
||||
|
||||
/* @group CPButtonType */
|
||||
@typedef CPButtonType
|
||||
CPMomentaryLightButton = 0;
|
||||
CPPushOnPushOffButton = 1;
|
||||
CPToggleButton = 2;
|
||||
@@ -72,13 +72,14 @@ CPPushInCellMask = CPPushInButtonMask;
|
||||
CPChangeGrayCellMask = CPGrayButtonMask;
|
||||
CPChangeBackgroundCellMask = CPBackgroundButtonMask;
|
||||
|
||||
CPButtonStateMixed = CPThemeState("mixed");
|
||||
CPButtonStateBezelStyleRounded = CPThemeState("rounded");
|
||||
CPButtonStateMixed = CPThemeState("mixed");
|
||||
CPButtonStateBezelStyleRounded = CPThemeState("rounded");
|
||||
CPButtonStateBezelStyleRoundRect = CPThemeState("roundRect");
|
||||
|
||||
// add all future correspondance between bezel styles and theme state here.
|
||||
var CPButtonBezelStyleStateMap = @{
|
||||
CPRoundedBezelStyle: CPButtonStateBezelStyleRounded,
|
||||
CPRoundRectBezelStyle: [CPNull null],
|
||||
CPRoundRectBezelStyle: CPButtonStateBezelStyleRoundRect,
|
||||
};
|
||||
|
||||
/// @cond IGNORE
|
||||
@@ -107,7 +108,6 @@ CPButtonImageOffset = 3.0;
|
||||
|
||||
// NS-style Display Properties
|
||||
CPBezelStyle _bezelStyle;
|
||||
CPControlSize _controlSize;
|
||||
|
||||
CPString _keyEquivalent;
|
||||
unsigned _keyEquivalentModifierMask;
|
||||
@@ -188,8 +188,6 @@ CPButtonImageOffset = 3.0;
|
||||
|
||||
- (void)_init
|
||||
{
|
||||
_controlSize = CPRegularControlSize;
|
||||
|
||||
_keyEquivalent = @"";
|
||||
_keyEquivalentModifierMask = 0;
|
||||
|
||||
@@ -200,6 +198,20 @@ CPButtonImageOffset = 3.0;
|
||||
[self setButtonType:CPMomentaryPushInButton];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Control Size
|
||||
|
||||
- (void)setControlSize:(CPControlSize)aControlSize
|
||||
{
|
||||
[super setControlSize:aControlSize];
|
||||
|
||||
if ([self isBordered])
|
||||
[self _sizeToControlSize];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
|
||||
// Setting the state
|
||||
/*!
|
||||
Returns a Boolean value indicating whether the button allows a mixed state.
|
||||
@@ -268,7 +280,7 @@ CPButtonImageOffset = 3.0;
|
||||
break;
|
||||
|
||||
case CPOffState:
|
||||
[self unsetThemeState:CPThemeStateSelected | CPButtonStateMixed | CPThemeStateHighlighted];
|
||||
[self unsetThemeState:[CPThemeStateSelected, CPButtonStateMixed, CPThemeStateHighlighted]];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -653,10 +665,10 @@ CPButtonImageOffset = 3.0;
|
||||
*/
|
||||
- (void)sizeToFit
|
||||
{
|
||||
[self layoutSubviews];
|
||||
|
||||
[self setFrameSize:[self _minimumFrameSize]];
|
||||
|
||||
[self layoutSubviews];
|
||||
|
||||
if ([self ephemeralSubviewNamed:@"content-view"])
|
||||
[self layoutSubviews];
|
||||
}
|
||||
|
||||
@@ -26,7 +26,10 @@
|
||||
@class CPSplitView
|
||||
|
||||
@global CPPopUpButtonStatePullsDown
|
||||
|
||||
@global CPKeyValueChangeOldKey
|
||||
@global CPKeyValueChangeNewKey
|
||||
@global CPKeyValueObservingOptionNew
|
||||
@global CPKeyValueObservingOptionOld
|
||||
|
||||
@implementation CPButtonBar : CPView
|
||||
{
|
||||
@@ -129,10 +132,20 @@
|
||||
|
||||
- (void)setButtons:(CPArray)buttons
|
||||
{
|
||||
for (var i = [_buttons count] - 1; i >= 0; i--)
|
||||
{
|
||||
[_buttons[i] removeFromSuperview];
|
||||
[_buttons[i] removeObserver:self forKeyPath:@"hidden"];
|
||||
}
|
||||
|
||||
|
||||
_buttons = [CPArray arrayWithArray:buttons];
|
||||
|
||||
for (var i = 0, count = [_buttons count]; i < count; i++)
|
||||
for (var i = [_buttons count] - 1; i >= 0; i--)
|
||||
{
|
||||
[_buttons[i] addObserver:self forKeyPath:@"hidden" options:CPKeyValueObservingOptionNew | CPKeyValueObservingOptionOld context:nil];
|
||||
[_buttons[i] setBordered:YES];
|
||||
}
|
||||
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
@@ -218,8 +231,15 @@
|
||||
count = [buttonsNotHidden count];
|
||||
|
||||
while (count--)
|
||||
if ([buttonsNotHidden[count] isHidden])
|
||||
[buttonsNotHidden removeObject:buttonsNotHidden[count]];
|
||||
{
|
||||
var button = buttonsNotHidden[count];
|
||||
|
||||
if ([button isHidden])
|
||||
{
|
||||
[button removeFromSuperview];
|
||||
[buttonsNotHidden removeObject:button];
|
||||
}
|
||||
}
|
||||
|
||||
var currentButtonOffset = _resizeControlIsLeftAligned ? CGRectGetMaxX([self bounds]) + 1 : -1,
|
||||
bounds = [self bounds],
|
||||
@@ -250,15 +270,15 @@
|
||||
currentButtonOffset += width - 1;
|
||||
}
|
||||
|
||||
[button setValue:normalColor forThemeAttribute:@"bezel-color" inState:CPThemeStateNormal | CPThemeStateBordered];
|
||||
[button setValue:highlightedColor forThemeAttribute:@"bezel-color" inState:CPThemeStateHighlighted | CPThemeStateBordered];
|
||||
[button setValue:disabledColor forThemeAttribute:@"bezel-color" inState:CPThemeStateDisabled | CPThemeStateBordered];
|
||||
[button setValue:normalColor forThemeAttribute:@"bezel-color" inState:[CPThemeStateNormal, CPThemeStateBordered]];
|
||||
[button setValue:highlightedColor forThemeAttribute:@"bezel-color" inState:[CPThemeStateHighlighted, CPThemeStateBordered, ]];
|
||||
[button setValue:disabledColor forThemeAttribute:@"bezel-color" inState:[CPThemeStateDisabled, CPThemeStateBordered]];
|
||||
[button setValue:textColor forThemeAttribute:@"text-color" inState:CPThemeStateBordered];
|
||||
|
||||
// FIXME shouldn't need this
|
||||
[button setValue:normalColor forThemeAttribute:@"bezel-color" inState:CPThemeStateNormal | CPThemeStateBordered | CPPopUpButtonStatePullsDown];
|
||||
[button setValue:highlightedColor forThemeAttribute:@"bezel-color" inState:CPThemeStateHighlighted | CPThemeStateBordered | CPPopUpButtonStatePullsDown];
|
||||
[button setValue:disabledColor forThemeAttribute:@"bezel-color" inState:CPThemeStateDisabled | CPThemeStateBordered | CPPopUpButtonStatePullsDown];
|
||||
[button setValue:normalColor forThemeAttribute:@"bezel-color" inState:[CPThemeStateNormal, CPThemeStateBordered, CPPopUpButtonStatePullsDown]];
|
||||
[button setValue:highlightedColor forThemeAttribute:@"bezel-color" inState:[CPThemeStateHighlighted, CPThemeStateBordered, CPPopUpButtonStatePullsDown]];
|
||||
[button setValue:disabledColor forThemeAttribute:@"bezel-color" inState:[CPThemeStateDisabled, CPThemeStateBordered, CPPopUpButtonStatePullsDown]];
|
||||
|
||||
[self addSubview:button];
|
||||
}
|
||||
@@ -274,6 +294,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(CPString)keyPath ofObject:(id)object change:(CPDictionary)change context:(id)context
|
||||
{
|
||||
if ([change objectForKey:CPKeyValueChangeOldKey] == [change objectForKey:CPKeyValueChangeNewKey])
|
||||
return;
|
||||
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (void)setFrameSize:(CGSize)aSize
|
||||
{
|
||||
[super setFrameSize:aSize];
|
||||
|
||||
@@ -111,6 +111,30 @@ CPCheckBoxImageOffset = 4.0;
|
||||
return startedTracking;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Override methods from CPButton
|
||||
|
||||
- (CGSize)_minimumFrameSize
|
||||
{
|
||||
var size = [super _minimumFrameSize],
|
||||
contentView = [self ephemeralSubviewNamed:@"content-view"];
|
||||
|
||||
if (!contentView && [[self title] length])
|
||||
{
|
||||
var minSize = [self currentValueForThemeAttribute:@"min-size"],
|
||||
maxSize = [self currentValueForThemeAttribute:@"max-size"];
|
||||
|
||||
// Here we always add the min size to the control which is the size of the view of the checkBox
|
||||
size.width += minSize.width + CPCheckBoxImageOffset;
|
||||
|
||||
if (maxSize.width >= 0.0)
|
||||
size.width = MIN(size.width, maxSize.width);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation _CPCheckBoxValueBinder : CPBinder
|
||||
|
||||
@@ -46,49 +46,12 @@
|
||||
return;
|
||||
|
||||
if (_documentView)
|
||||
{
|
||||
var defaultCenter = [CPNotificationCenter defaultCenter];
|
||||
|
||||
[defaultCenter
|
||||
removeObserver:self
|
||||
name:CPViewFrameDidChangeNotification
|
||||
object:_documentView];
|
||||
|
||||
[defaultCenter
|
||||
removeObserver:self
|
||||
name:CPViewBoundsDidChangeNotification
|
||||
object:_documentView];
|
||||
|
||||
[_documentView removeFromSuperview];
|
||||
}
|
||||
|
||||
_documentView = aView;
|
||||
|
||||
if (_documentView)
|
||||
{
|
||||
[self addSubview:_documentView];
|
||||
[self _observeDocumentView];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_observeDocumentView
|
||||
{
|
||||
var defaultCenter = [CPNotificationCenter defaultCenter];
|
||||
|
||||
[_documentView setPostsFrameChangedNotifications:YES];
|
||||
[_documentView setPostsBoundsChangedNotifications:YES];
|
||||
|
||||
[defaultCenter
|
||||
addObserver:self
|
||||
selector:@selector(viewFrameChanged:)
|
||||
name:CPViewFrameDidChangeNotification
|
||||
object:_documentView];
|
||||
|
||||
[defaultCenter
|
||||
addObserver:self
|
||||
selector:@selector(viewBoundsChanged:)
|
||||
name:CPViewBoundsDidChangeNotification
|
||||
object:_documentView];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -230,6 +193,11 @@
|
||||
return [self scrollToPoint:CGPointMake(bounds.origin.x - deltaX, bounds.origin.y - deltaY)];
|
||||
}
|
||||
|
||||
- (CGRect)documentVisibleRect
|
||||
{
|
||||
return [self convertRect:[self bounds] fromView:_documentView];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -244,7 +212,6 @@ var CPClipViewDocumentViewKey = @"CPScrollViewDocumentView";
|
||||
// Don't call setDocumentView: here. It calls addSubview:, but it's A) not necessary since the
|
||||
// view hierarchy is fully encoded and B) dangerous if the subview is not fully decoded.
|
||||
_documentView = [aCoder decodeObjectForKey:CPClipViewDocumentViewKey];
|
||||
[self _observeDocumentView];
|
||||
}
|
||||
|
||||
return self;
|
||||
|
||||
@@ -32,6 +32,34 @@
|
||||
@import "CPPasteboard.j"
|
||||
@import "CPView.j"
|
||||
|
||||
@class _CPCollectionViewDropIndicator
|
||||
|
||||
var CPCollectionViewDelegate_collectionView_acceptDrop_index_dropOperation_ = 1 << 0,
|
||||
CPCollectionViewDelegate_collectionView_canDragItemsAtIndexes_withEvent_ = 1 << 1,
|
||||
CPCollectionViewDelegate_collectionView_writeItemsAtIndexes_toPasteboard_ = 1 << 2,
|
||||
CPCollectionViewDelegate_collectionView_dragTypesForItemsAtIndexes_ = 1 << 3,
|
||||
CPCollectionViewDelegate_collectionView_dataForItemsAtIndexes_forType_ = 1 << 4,
|
||||
CPCollectionViewDelegate_collectionView_validateDrop_proposedIndex_dropOperation_ = 1 << 5,
|
||||
CPCollectionViewDelegate_collectionView_didDoubleClickOnItemAtIndex_ = 1 << 6,
|
||||
CPCollectionViewDelegate_collectionView_menuForItemAtIndex_ = 1 << 7,
|
||||
CPCollectionViewDelegate_collectionView_draggingViewForItemsAtIndexes_withEvent_offset = 1 << 8;
|
||||
|
||||
|
||||
@protocol CPCollectionViewDelegate <CPObject>
|
||||
|
||||
@optional
|
||||
- (BOOL)collectionView:(CPCollectionView)collectionView acceptDrop:(id)draggingInfo index:(CPInteger)index dropOperation:(CPCollectionViewDropOperation)dropOperation;
|
||||
- (BOOL)collectionView:(CPCollectionView)collectionView canDragItemsAtIndexes:(CPIndexSet)indexes withEvent:(CPEvent)event;
|
||||
- (BOOL)collectionView:(CPCollectionView)collectionView writeItemsAtIndexes:(CPIndexSet)indexes toPasteboard:(CPPasteboard)pasteboard;
|
||||
- (CPArray)collectionView:(CPCollectionView)collectionView dragTypesForItemsAtIndexes:(CPIndexSet)indexes;
|
||||
- (CPData)collectionView:(CPCollectionView)collectionView dataForItemsAtIndexes:(CPIndexSet)indices forType:(CPString)aType;
|
||||
- (CPDragOperation)collectionView:(CPCollectionView)collectionView validateDrop:(id)draggingInfo proposedIndex:(CPInteger)proposedDropIndex dropOperation:(CPCollectionViewDropOperation)proposedDropOperation;
|
||||
- (CPMenu)collectionView:(CPCollectionView)collectionView menuForItemAtIndex:(CPInteger)anIndex;
|
||||
- (CPView)collectionView:(CPCollectionView)collectionView dragginViewForItemsAtIndexes:(CPIndexSet)indexes withEvent:(CPEvent)event offset:(CGPoint)dragImageOffset;
|
||||
- (void)collectionView:(CPCollectionView)collectionView didDoubleClickOnItemAtIndex:(int)index;
|
||||
|
||||
@end
|
||||
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@class CPCollectionView
|
||||
@@ -42,10 +70,6 @@
|
||||
|
||||
@par Delegate Methods
|
||||
|
||||
@delegate - (void)collectionViewDidChangeSelection:(CPCollectionView)collectionView;
|
||||
DEPRECATED: Please do not use.
|
||||
@param collectionView the collection view who's selection changed
|
||||
|
||||
@delegate - (void)collectionView:(CPCollectionView)collectionView didDoubleClickOnItemAtIndex:(int)index;
|
||||
Called when the user double-clicks on an item in the collection view.
|
||||
@param collectionView the collection view that received the double-click
|
||||
@@ -69,51 +93,52 @@ var HORIZONTAL_MARGIN = 2;
|
||||
|
||||
@implementation CPCollectionView : CPView
|
||||
{
|
||||
CPArray _content;
|
||||
CPArray _items;
|
||||
CPArray _content;
|
||||
CPArray _items;
|
||||
|
||||
CPData _itemData;
|
||||
CPCollectionViewItem _itemPrototype;
|
||||
CPCollectionViewItem _itemForDragging;
|
||||
CPMutableArray _cachedItems;
|
||||
CPData _itemData;
|
||||
CPCollectionViewItem _itemPrototype;
|
||||
CPCollectionViewItem _itemForDragging;
|
||||
CPMutableArray _cachedItems;
|
||||
|
||||
unsigned _maxNumberOfRows;
|
||||
unsigned _maxNumberOfColumns;
|
||||
unsigned _maxNumberOfRows;
|
||||
unsigned _maxNumberOfColumns;
|
||||
|
||||
CGSize _minItemSize;
|
||||
CGSize _maxItemSize;
|
||||
CGSize _minItemSize;
|
||||
CGSize _maxItemSize;
|
||||
|
||||
CPArray _backgroundColors;
|
||||
CPArray _backgroundColors;
|
||||
|
||||
float _tileWidth;
|
||||
float _tileWidth;
|
||||
|
||||
BOOL _isSelectable;
|
||||
BOOL _allowsMultipleSelection;
|
||||
BOOL _allowsEmptySelection;
|
||||
CPIndexSet _selectionIndexes;
|
||||
BOOL _isSelectable;
|
||||
BOOL _allowsMultipleSelection;
|
||||
BOOL _allowsEmptySelection;
|
||||
CPIndexSet _selectionIndexes;
|
||||
|
||||
CGSize _itemSize;
|
||||
CGSize _itemSize;
|
||||
|
||||
float _horizontalMargin;
|
||||
float _verticalMargin;
|
||||
float _horizontalMargin;
|
||||
float _verticalMargin;
|
||||
|
||||
unsigned _numberOfRows;
|
||||
unsigned _numberOfColumns;
|
||||
unsigned _numberOfRows;
|
||||
unsigned _numberOfColumns;
|
||||
|
||||
id _delegate;
|
||||
id <CPCollectionViewDelegate> _delegate;
|
||||
unsigned _implementedDelegateMethods;
|
||||
|
||||
CPEvent _mouseDownEvent;
|
||||
CPEvent _mouseDownEvent;
|
||||
|
||||
BOOL _needsMinMaxItemSizeUpdate;
|
||||
CGSize _storedFrameSize;
|
||||
BOOL _needsMinMaxItemSizeUpdate;
|
||||
CGSize _storedFrameSize;
|
||||
|
||||
BOOL _uniformSubviewsResizing @accessors(property=uniformSubviewsResizing);
|
||||
BOOL _lockResizing;
|
||||
BOOL _uniformSubviewsResizing @accessors(property=uniformSubviewsResizing);
|
||||
BOOL _lockResizing;
|
||||
|
||||
CPInteger _currentDropIndex;
|
||||
CPDragOperation _currentDragOperation;
|
||||
CPInteger _currentDropIndex;
|
||||
CPDragOperation _currentDragOperation;
|
||||
|
||||
_CPCollectionViewDropIndicator _dropView;
|
||||
_CPCollectionViewDropIndicator _dropView;
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)aFrame
|
||||
@@ -168,6 +193,51 @@ var HORIZONTAL_MARGIN = 2;
|
||||
[self setAutoresizingMask:0];
|
||||
}
|
||||
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Delegate
|
||||
|
||||
/*!
|
||||
Set the delegate of the receiver
|
||||
@param aDelegate the delegate object for the collectionView.
|
||||
*/
|
||||
- (void)setDelegate:(id <CPCollectionViewDelegate>)aDelegate
|
||||
{
|
||||
if (_delegate === aDelegate)
|
||||
return;
|
||||
|
||||
_delegate = aDelegate;
|
||||
_implementedDelegateMethods = 0;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(collectionView:acceptDrop:index:dropOperation:)])
|
||||
_implementedDelegateMethods |= CPCollectionViewDelegate_collectionView_acceptDrop_index_dropOperation_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(collectionView:canDragItemsAtIndexes:withEvent:)])
|
||||
_implementedDelegateMethods |= CPCollectionViewDelegate_collectionView_canDragItemsAtIndexes_withEvent_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(collectionView:writeItemsAtIndexes:toPasteboard:)])
|
||||
_implementedDelegateMethods |= CPCollectionViewDelegate_collectionView_writeItemsAtIndexes_toPasteboard_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(collectionView:dragTypesForItemsAtIndexes:)])
|
||||
_implementedDelegateMethods |= CPCollectionViewDelegate_collectionView_dragTypesForItemsAtIndexes_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(collectionView:dataForItemsAtIndexes:forType:)])
|
||||
_implementedDelegateMethods |= CPCollectionViewDelegate_collectionView_dataForItemsAtIndexes_forType_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(collectionView:validateDrop:proposedIndex:dropOperation:)])
|
||||
_implementedDelegateMethods |= CPCollectionViewDelegate_collectionView_validateDrop_proposedIndex_dropOperation_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(collectionView:didDoubleClickOnItemAtIndex:)])
|
||||
_implementedDelegateMethods |= CPCollectionViewDelegate_collectionView_didDoubleClickOnItemAtIndex_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(collectionView:menuForItemAtIndex:)])
|
||||
_implementedDelegateMethods |= CPCollectionViewDelegate_collectionView_menuForItemAtIndex_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(collectionView:draggingViewForItemsAtIndexes:withEvent:offset:)])
|
||||
_implementedDelegateMethods |= CPCollectionViewDelegate_collectionView_draggingViewForItemsAtIndexes_withEvent_offset;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the item prototype to \c anItem
|
||||
@param anItem the new item prototype.
|
||||
@@ -395,12 +465,6 @@ var HORIZONTAL_MARGIN = 2;
|
||||
|
||||
var binderClass = [[self class] _binderClassForBinding:@"selectionIndexes"];
|
||||
[[binderClass getBinding:@"selectionIndexes" forObject:self] reverseSetValueFor:@"selectionIndexes"];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(collectionViewDidChangeSelection:)])
|
||||
{
|
||||
CPLog.warn("The delegate method collectionViewDidChangeSelection: is deprecated and will be removed in a future version, please bind to selectionIndexes instead.");
|
||||
[_delegate collectionViewDidChangeSelection:self];
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -545,7 +609,7 @@ var HORIZONTAL_MARGIN = 2;
|
||||
|
||||
height = MAX(height, numberOfRows * (_minItemSize.height + _verticalMargin));
|
||||
|
||||
var itemSizeHeight = FLOOR(height / numberOfRows);
|
||||
var itemSizeHeight = FLOOR(height / numberOfRows) - _verticalMargin;
|
||||
|
||||
if (maxItemSizeHeight > 0)
|
||||
itemSizeHeight = MIN(itemSizeHeight, maxItemSizeHeight);
|
||||
@@ -755,8 +819,8 @@ var HORIZONTAL_MARGIN = 2;
|
||||
|
||||
- (void)mouseUp:(CPEvent)anEvent
|
||||
{
|
||||
if ([_selectionIndexes count] && [anEvent clickCount] == 2 && [_delegate respondsToSelector:@selector(collectionView:didDoubleClickOnItemAtIndex:)])
|
||||
[_delegate collectionView:self didDoubleClickOnItemAtIndex:[_selectionIndexes firstIndex]];
|
||||
if ([_selectionIndexes count] && [anEvent clickCount] == 2)
|
||||
[self _sendDelegateDidDoubleClickOnItemAtIndex:[_selectionIndexes firstIndex]];
|
||||
}
|
||||
|
||||
- (void)mouseDown:(CPEvent)anEvent
|
||||
@@ -846,15 +910,6 @@ var HORIZONTAL_MARGIN = 2;
|
||||
return _verticalMargin;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the collection view's delegate
|
||||
@param aDelegate the new delegate
|
||||
*/
|
||||
- (void)setDelegate:(id)aDelegate
|
||||
{
|
||||
_delegate = aDelegate;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the collection view's delegate
|
||||
*/
|
||||
@@ -868,13 +923,13 @@ var HORIZONTAL_MARGIN = 2;
|
||||
*/
|
||||
- (CPMenu)menuForEvent:(CPEvent)theEvent
|
||||
{
|
||||
if (![[self delegate] respondsToSelector:@selector(collectionView:menuForItemAtIndex:)])
|
||||
if (![self _delegateRespondsToCollectionViewMenuForItemAtIndex])
|
||||
return [super menuForEvent:theEvent];
|
||||
|
||||
var location = [self convertPoint:[theEvent locationInWindow] fromView:nil],
|
||||
index = [self _indexAtPoint:location];
|
||||
|
||||
return [_delegate collectionView:self menuForItemAtIndex:index];
|
||||
return [self _sendDelegateMenuForItemAtIndex:index];
|
||||
}
|
||||
|
||||
- (int)_indexAtPoint:(CGPoint)thePoint
|
||||
@@ -932,7 +987,7 @@ var HORIZONTAL_MARGIN = 2;
|
||||
*/
|
||||
- (void)pasteboard:(CPPasteboard)aPasteboard provideDataForType:(CPString)aType
|
||||
{
|
||||
[aPasteboard setData:[_delegate collectionView:self dataForItemsAtIndexes:_selectionIndexes forType:aType] forType:aType];
|
||||
[aPasteboard setData:[self _sendDelegateDataForItemsAtIndexes:_selectionIndexes forType:aType] forType:aType];
|
||||
}
|
||||
|
||||
- (void)_createDropIndicatorIfNeeded
|
||||
@@ -962,24 +1017,23 @@ var HORIZONTAL_MARGIN = 2;
|
||||
(ABS(locationInWindow.y - mouseDownLocationInWindow.y) < 3))
|
||||
return;
|
||||
|
||||
if (![_delegate respondsToSelector:@selector(collectionView:dragTypesForItemsAtIndexes:)])
|
||||
if (![self _delegateRespondsToCollectionViewDragTypesForItemsAtIndexes])
|
||||
return;
|
||||
|
||||
// If we don't have any selected items, we've clicked away, and thus the drag is meaningless.
|
||||
if (![_selectionIndexes count])
|
||||
return;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(collectionView:canDragItemsAtIndexes:withEvent:)] &&
|
||||
![_delegate collectionView:self canDragItemsAtIndexes:_selectionIndexes withEvent:_mouseDownEvent])
|
||||
if (![self _sendDelegateCanDragItemsAtIndexes:_selectionIndexes withEvent:_mouseDownEvent])
|
||||
return;
|
||||
|
||||
// Set up the pasteboard
|
||||
var dragTypes = [_delegate collectionView:self dragTypesForItemsAtIndexes:_selectionIndexes];
|
||||
var dragTypes = [self _sendDelegateDragTypesForItemsAtIndexes:_selectionIndexes];
|
||||
|
||||
[[CPPasteboard pasteboardWithName:CPDragPboard] declareTypes:dragTypes owner:self];
|
||||
|
||||
var dragImageOffset = CGSizeMakeZero(),
|
||||
view = [self _draggingViewForItemsAtIndexes:_selectionIndexes withEvent:_mouseDownEvent offset:dragImageOffset];
|
||||
view = [self _sendDelegateDraggingViewForItemsAtIndexes:_selectionIndexes withEvent:_mouseDownEvent offset:dragImageOffset];
|
||||
|
||||
[view setFrameSize:_itemSize];
|
||||
[view setAlphaValue:0.7];
|
||||
@@ -996,14 +1050,6 @@ var HORIZONTAL_MARGIN = 2;
|
||||
slideBack:YES];
|
||||
}
|
||||
|
||||
- (CPView)_draggingViewForItemsAtIndexes:(CPIndexSet)indexes withEvent:(CPEvent)anEvent offset:(CGPoint)offset
|
||||
{
|
||||
if ([_delegate respondsToSelector:@selector(collectionView:draggingViewForItemsAtIndexes:withEvent:offset:)])
|
||||
return [_delegate collectionView:self draggingViewForItemsAtIndexes:indexes withEvent:anEvent offset:offset];
|
||||
|
||||
return [self draggingViewForItemsAtIndexes:indexes withEvent:anEvent offset:offset];
|
||||
}
|
||||
|
||||
- (CPView)draggingViewForItemsAtIndexes:(CPIndexSet)indexes withEvent:(CPEvent)event offset:(CGPoint)dragImageOffset
|
||||
{
|
||||
var idx = _content[[indexes firstIndex]];
|
||||
@@ -1016,14 +1062,6 @@ var HORIZONTAL_MARGIN = 2;
|
||||
return [_itemForDragging view];
|
||||
}
|
||||
|
||||
- (BOOL)_canDragItemsAtIndexes:(CPIndexSet)indexes withEvent:(CPEvent)anEvent
|
||||
{
|
||||
if ([self respondsToSelector:@selector(collectionView:canDragItemsAtIndexes:withEvent:)])
|
||||
return [_delegate collectionView:self canDragItemsAtIndexes:indexes withEvent:anEvent];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (CPDragOperation)draggingEntered:(id)draggingInfo
|
||||
{
|
||||
var dropIndex = -1,
|
||||
@@ -1061,16 +1099,14 @@ var HORIZONTAL_MARGIN = 2;
|
||||
var result = CPDragOperationMove,
|
||||
dropIndex = [self _dropIndexForDraggingInfo:draggingInfo proposedDropOperation:dropOperation];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(collectionView:validateDrop:proposedIndex:dropOperation:)])
|
||||
if ([self _delegateRespondsToCollectionViewValidateDropProposedIndexDropOperation])
|
||||
{
|
||||
var dropIndexRef2 = @ref(dropIndex);
|
||||
|
||||
result = [_delegate collectionView:self validateDrop:draggingInfo proposedIndex:dropIndexRef2 dropOperation:dropOperation];
|
||||
result = [self _sendDelegateValidateDrop:draggingInfo proposedIndex:dropIndexRef2 dropOperation:dropOperation];
|
||||
|
||||
if (result !== CPDragOperationNone)
|
||||
{
|
||||
dropIndex = dropIndexRef2();
|
||||
}
|
||||
}
|
||||
|
||||
dropIndexRef(dropIndex);
|
||||
@@ -1104,7 +1140,7 @@ Not supported. Use -collectionView:dataForItemsAtIndexes:fortype:
|
||||
var result = NO;
|
||||
|
||||
if (_currentDragOperation && _currentDropIndex !== -1)
|
||||
result = [_delegate collectionView:self acceptDrop:draggingInfo index:_currentDropIndex dropOperation:1];
|
||||
result = [self _sendDelegateAcceptDrop:draggingInfo index:_currentDropIndex dropOperation:1];
|
||||
|
||||
[self draggingEnded:draggingInfo]; // Is this correct ?
|
||||
|
||||
@@ -1329,6 +1365,7 @@ Not supported. Use -collectionView:dataForItemsAtIndexes:fortype:
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation CPCollectionView (Deprecated)
|
||||
|
||||
- (CGRect)rectForItemAtIndex:(int)anIndex
|
||||
@@ -1349,6 +1386,148 @@ Not supported. Use -collectionView:dataForItemsAtIndexes:fortype:
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation CPCollectionView (CPCollectionViewDelegate)
|
||||
|
||||
/*
|
||||
@ignore
|
||||
Return YES if the delegate implements collectionView:validateDrop:proposedIndex:dropOperation:
|
||||
*/
|
||||
- (BOOL)_delegateRespondsToCollectionViewValidateDropProposedIndexDropOperation
|
||||
{
|
||||
return _implementedDelegateMethods & CPCollectionViewDelegate_collectionView_validateDrop_proposedIndex_dropOperation_;
|
||||
}
|
||||
|
||||
/*
|
||||
@ignore
|
||||
Return YES if the delegate implements collectionView:menuForItemAtIndex:
|
||||
*/
|
||||
- (BOOL)_delegateRespondsToCollectionViewMenuForItemAtIndex
|
||||
{
|
||||
return _implementedDelegateMethods & CPCollectionViewDelegate_collectionView_menuForItemAtIndex_;
|
||||
}
|
||||
|
||||
/*
|
||||
@ignore
|
||||
Return YES if the delegate implements collectionView:dragTypesForItemsAtIndexes:
|
||||
*/
|
||||
- (BOOL)_delegateRespondsToCollectionViewDragTypesForItemsAtIndexes
|
||||
{
|
||||
return _implementedDelegateMethods & CPCollectionViewDelegate_collectionView_dragTypesForItemsAtIndexes_;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call delegate collectionView:acceptDrop:index:dropOperation:
|
||||
*/
|
||||
- (BOOL)_sendDelegateAcceptDrop:(id)draggingInfo index:(CPInteger)index dropOperation:(CPCollectionViewDropOperation)dropOperation
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPCollectionViewDelegate_collectionView_acceptDrop_index_dropOperation_))
|
||||
return NO;
|
||||
|
||||
return [_delegate collectionView:self acceptDrop:draggingInfo index:index dropOperation:dropOperation];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call delegate collectionView:canDragItemsAtIndexes:withEvent:
|
||||
*/
|
||||
- (BOOL)_sendDelegateCanDragItemsAtIndexes:(CPIndexSet)indexes withEvent:(CPEvent)anEvent
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPCollectionViewDelegate_collectionView_canDragItemsAtIndexes_withEvent_))
|
||||
return YES;
|
||||
|
||||
return [_delegate collectionView:self canDragItemsAtIndexes:indexes withEvent:anEvent];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call delegate collectionView:writeItemsAtIndexes:toPasteboard:
|
||||
*/
|
||||
- (BOOL)_sendDelegateWriteItemsAtIndexes:(CPIndexSet)indexes toPasteboard:(CPPasteboard)pasteboard
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPCollectionViewDelegate_collectionView_writeItemsAtIndexes_toPasteboard_))
|
||||
return NO;
|
||||
|
||||
return [_delegate collectionView:self writeItemsAtIndexes:indexes toPasteboard:pasteboard];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call delegate collectionView:dragTypesForItemsAtIndexes:
|
||||
*/
|
||||
- (CPArray)_sendDelegateDragTypesForItemsAtIndexes:(CPIndexSet)indexes
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPCollectionViewDelegate_collectionView_dragTypesForItemsAtIndexes_))
|
||||
return [];
|
||||
|
||||
return [_delegate collectionView:self dragTypesForItemsAtIndexes:indexes];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call delegate collectionView:dataForItemsAtIndexes:forType:
|
||||
*/
|
||||
- (CPData)_sendDelegateDataForItemsAtIndexes:(CPIndexSet)indexes forType:(CPString)aType
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPCollectionViewDelegate_collectionView_dataForItemsAtIndexes_forType_))
|
||||
return nil;
|
||||
|
||||
return [_delegate collectionView:self dataForItemsAtIndexes:indexes forType:aType];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call delegate collectionView:validateDrop:proposedIndex:dropOperation:
|
||||
*/
|
||||
- (CPDragOperation)_sendDelegateValidateDrop:(id)draggingInfo proposedIndex:(CPInteger)proposedDropIndex dropOperation:(CPCollectionViewDropOperation)proposedDropOperation
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPCollectionViewDelegate_collectionView_validateDrop_proposedIndex_dropOperation_))
|
||||
return CPDragOperationNone;
|
||||
|
||||
return [_delegate collectionView:self validateDrop:draggingInfo proposedIndex:proposedDropIndex dropOperation:proposedDropOperation];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call delegate collectionView:didDoubleClickOnItemAtIndex:
|
||||
*/
|
||||
- (void)_sendDelegateDidDoubleClickOnItemAtIndex:(int)index
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPCollectionViewDelegate_collectionView_didDoubleClickOnItemAtIndex_))
|
||||
return;
|
||||
|
||||
return [_delegate collectionView:self didDoubleClickOnItemAtIndex:index];
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call delegate collectionView:menuForItemAtIndex:
|
||||
*/
|
||||
- (void)_sendDelegateMenuForItemAtIndex:(CPInteger)anIndex
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPCollectionViewDelegate_collectionView_menuForItemAtIndex_))
|
||||
return nil;
|
||||
|
||||
return [_delegate collectionView:self menuForItemAtIndex:anIndex];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call delegate draggingViewForItemsAtIndexes:withEvent:offset:
|
||||
*/
|
||||
- (CPView)_sendDelegateDraggingViewForItemsAtIndexes:(CPIndexSet)indexes withEvent:(CPEvent)anEvent offset:(CGPoint)dragImageOffset
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPCollectionViewDelegate_collectionView_draggingViewForItemsAtIndexes_withEvent_offset))
|
||||
return [self draggingViewForItemsAtIndexes:indexes withEvent:anEvent offset:dragImageOffset];
|
||||
|
||||
return [_delegate collectionView:self draggingViewForItemsAtIndexes:indexes withEvent:anEvent offset:dragImageOffset];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
var CPCollectionViewMinItemSizeKey = @"CPCollectionViewMinItemSizeKey",
|
||||
CPCollectionViewMaxItemSizeKey = @"CPCollectionViewMaxItemSizeKey",
|
||||
CPCollectionViewVerticalMarginKey = @"CPCollectionViewVerticalMarginKey",
|
||||
|
||||
@@ -813,6 +813,12 @@ url("data:image/png;base64,BASE64ENCODEDDATA") // if there is a pattern image
|
||||
return [CPColor colorWithRed:RAND() green:RAND() blue:RAND() alpha:1.0];
|
||||
}
|
||||
|
||||
+ (CPColor)checkerBoardColor
|
||||
{
|
||||
// Thanks to cocco http://stackoverflow.com/a/18368212/76900.
|
||||
return [CPColor colorWithPatternImage:[[CPImage alloc] initWithContentsOfFile:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEX////MzMw46qqDAAAAEElEQVQImWNg+M+AFeEQBgB+vw/xfUUZkgAAAABJRU5ErkJggg=="]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
/// @cond IGNORE
|
||||
|
||||
@@ -27,6 +27,9 @@
|
||||
@import "CPView.j"
|
||||
|
||||
@class CPSlider
|
||||
@class _CPColorPanelToolbar
|
||||
@class _CPColorPanelSwatches
|
||||
@class _CPColorPanelPreview
|
||||
|
||||
@global CPApp
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
@import "CPView.j"
|
||||
|
||||
@class CPSlider
|
||||
@class CPColorPanel
|
||||
@class __CPColorWheel
|
||||
|
||||
@global CPColorPickerViewWidth
|
||||
@global CPColorPickerViewHeight
|
||||
|
||||
@@ -86,14 +86,12 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
|
||||
_active = NO;
|
||||
_color = [CPColor whiteColor];
|
||||
[self setBordered:YES];
|
||||
|
||||
[self _registerForNotifications];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)_registerForNotifications
|
||||
- (void)_registerNotifications
|
||||
{
|
||||
var defaultCenter = [CPNotificationCenter defaultCenter];
|
||||
|
||||
@@ -110,6 +108,22 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
|
||||
object:[CPColorPanel sharedColorPanel]];
|
||||
}
|
||||
|
||||
- (void)_removeNotifications
|
||||
{
|
||||
var defaultCenter = [CPNotificationCenter defaultCenter];
|
||||
|
||||
[defaultCenter
|
||||
removeObserver:self
|
||||
name:_CPColorWellDidBecomeExclusiveNotification
|
||||
object:nil];
|
||||
|
||||
[defaultCenter
|
||||
removeObserver:self
|
||||
name:CPWindowWillCloseNotification
|
||||
object:[CPColorPanel sharedColorPanel]];
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets whether the color well is bordered.
|
||||
*/
|
||||
@@ -312,6 +326,28 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv
|
||||
[contentBorderView setBackgroundColor:[self currentValueForThemeAttribute:@"content-border-color"]];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Observers method
|
||||
|
||||
- (void)_addObservers
|
||||
{
|
||||
if (_isObserving)
|
||||
return;
|
||||
|
||||
[super _addObservers];
|
||||
[self _registerNotifications];
|
||||
}
|
||||
|
||||
- (void)_removeObservers
|
||||
{
|
||||
if (!_isObserving)
|
||||
return;
|
||||
|
||||
[super _removeObservers];
|
||||
[self _removeNotifications];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPColorWellValueBinder : CPBinder
|
||||
@@ -363,8 +399,6 @@ var CPColorWellColorKey = "CPColorWellColorKey",
|
||||
_active = NO;
|
||||
_color = [aCoder decodeObjectForKey:CPColorWellColorKey];
|
||||
[self setBordered:[aCoder decodeBoolForKey:CPColorWellBorderedKey]];
|
||||
|
||||
[self _registerForNotifications];
|
||||
}
|
||||
|
||||
return self;
|
||||
|
||||
@@ -25,6 +25,27 @@
|
||||
@import "_CPPopUpList.j"
|
||||
|
||||
|
||||
// TODO : should conform to protocol CPTextFieldDelegate
|
||||
@protocol CPComboBoxDelegate <CPObject>
|
||||
|
||||
@optional
|
||||
- (void)comboBoxSelectionIsChanging:(CPNotification)aNotification;
|
||||
- (void)comboBoxSelectionDidChange:(CPNotification)aNotification;
|
||||
- (void)comboBoxWillPopUp:(CPNotification)aNotification;
|
||||
- (void)comboBoxWillDismiss:(CPNotification)aNotification;
|
||||
|
||||
@end
|
||||
|
||||
@protocol CPComboBoxDataSource <CPObject>
|
||||
|
||||
@optional
|
||||
- (CPString)comboBox:(CPComboBox)aComboBox completedString:(CPString)uncompletedString;
|
||||
- (id)comboBox:(CPComboBox)aComboBox objectValueForItemAtIndex:(int)index;
|
||||
- (int)comboBox:(CPComboBox)aComboBox indexOfItemWithStringValue:(CPString)stringValue;
|
||||
- (int)numberOfItemsInComboBox:(CPComboBox)aComboBox;
|
||||
|
||||
@end
|
||||
|
||||
CPComboBoxSelectionDidChangeNotification = @"CPComboBoxSelectionDidChangeNotification";
|
||||
CPComboBoxSelectionIsChangingNotification = @"CPComboBoxSelectionIsChangingNotification";
|
||||
CPComboBoxWillDismissNotification = @"CPComboBoxWillDismissNotification";
|
||||
@@ -32,6 +53,11 @@ CPComboBoxWillPopUpNotification = @"CPComboBoxWillPopUpNotification";
|
||||
|
||||
CPComboBoxStateButtonBordered = CPThemeState("button-bordered");
|
||||
|
||||
var CPComboBoxDelegate_comboBoxSelectionIsChanging_ = 1 << 0,
|
||||
CPComboBoxDelegate_comboBoxSelectionDidChange_ = 1 << 1,
|
||||
CPComboBoxDelegate_comboBoxWillPopUp_ = 1 << 2,
|
||||
CPComboBoxDelegate_comboBoxWillDismiss_ = 1 << 3;
|
||||
|
||||
var CPComboBoxTextSubview = @"text",
|
||||
CPComboBoxButtonSubview = @"button",
|
||||
CPComboBoxDefaultNumberOfVisibleItems = 5,
|
||||
@@ -40,17 +66,20 @@ var CPComboBoxTextSubview = @"text",
|
||||
|
||||
@implementation CPComboBox : CPTextField
|
||||
{
|
||||
CPArray _items;
|
||||
_CPPopUpList _listDelegate;
|
||||
CPComboBoxDataSource _dataSource;
|
||||
BOOL _usesDataSource;
|
||||
BOOL _completes;
|
||||
BOOL _canComplete;
|
||||
int _numberOfVisibleItems;
|
||||
BOOL _forceSelection;
|
||||
BOOL _hasVerticalScroller;
|
||||
CPString _selectedStringValue;
|
||||
BOOL _popUpButtonCausedResign;
|
||||
BOOL _canComplete;
|
||||
BOOL _completes;
|
||||
BOOL _forceSelection;
|
||||
BOOL _hasVerticalScroller;
|
||||
BOOL _popUpButtonCausedResign;
|
||||
BOOL _usesDataSource;
|
||||
CGSize _intercellSpacing;
|
||||
CPArray _items;
|
||||
id<CPComboBoxDataSource> _dataSource;
|
||||
CPInteger _implementedDelegateComboBoxMethods;
|
||||
CPString _selectedStringValue;
|
||||
float _itemHeight;
|
||||
int _numberOfVisibleItems;
|
||||
_CPPopUpList _listDelegate;
|
||||
}
|
||||
|
||||
+ (CPString)defaultThemeClass
|
||||
@@ -119,7 +148,9 @@ var CPComboBoxTextSubview = @"text",
|
||||
return;
|
||||
|
||||
_hasVerticalScroller = flag;
|
||||
[[_listDelegate scrollView] setHasVerticalScroller:flag];
|
||||
|
||||
if (_listDelegate)
|
||||
[[_listDelegate scrollView] setHasVerticalScroller:_hasVerticalScroller];
|
||||
}
|
||||
|
||||
- (CGSize)intercellSpacing
|
||||
@@ -129,7 +160,13 @@ var CPComboBoxTextSubview = @"text",
|
||||
|
||||
- (void)setIntercellSpacing:(CGSize)aSize
|
||||
{
|
||||
[[_listDelegate tableView] setIntercellSpacing:aSize];
|
||||
if (_intercellSpacing && CGSizeEqualToSize(aSize, _intercellSpacing))
|
||||
return;
|
||||
|
||||
_intercellSpacing = aSize;
|
||||
|
||||
if (_listDelegate)
|
||||
[[_listDelegate tableView] setIntercellSpacing:_intercellSpacing];
|
||||
}
|
||||
|
||||
- (BOOL)isButtonBordered
|
||||
@@ -152,10 +189,18 @@ var CPComboBoxTextSubview = @"text",
|
||||
|
||||
- (void)setItemHeight:(float)itemHeight
|
||||
{
|
||||
[[_listDelegate tableView] setRowHeight:itemHeight];
|
||||
if (itemHeight === _itemHeight)
|
||||
return;
|
||||
|
||||
// FIXME: This shouldn't be necessary, but CPTableView does not tile after setRowHeight
|
||||
[[_listDelegate tableView] reloadData];
|
||||
_itemHeight = itemHeight;
|
||||
|
||||
if (_listDelegate)
|
||||
{
|
||||
[[_listDelegate tableView] setRowHeight:_itemHeight];
|
||||
|
||||
// FIXME: This shouldn't be necessary, but CPTableView does not tile after setRowHeight
|
||||
[[_listDelegate tableView] reloadData];
|
||||
}
|
||||
}
|
||||
|
||||
- (int)numberOfVisibleItems
|
||||
@@ -171,7 +216,7 @@ var CPComboBoxTextSubview = @"text",
|
||||
|
||||
#pragma mark Setting a Delegate
|
||||
|
||||
- (id /*< CPComboBoxDelegate >*/)delegate
|
||||
- (id <CPComboBoxDelegate>)delegate
|
||||
{
|
||||
return [super delegate];
|
||||
}
|
||||
@@ -182,48 +227,28 @@ var CPComboBoxTextSubview = @"text",
|
||||
protocol, in actual fact it doesn't. Also note that the same
|
||||
delegate may conform to the NSTextFieldDelegate protocol.
|
||||
*/
|
||||
- (void)setDelegate:(id /*< CPComboBoxDelegate >*/)aDelegate
|
||||
- (void)setDelegate:(id <CPComboBoxDelegate>)aDelegate
|
||||
{
|
||||
var delegate = [self delegate];
|
||||
|
||||
if (aDelegate === delegate)
|
||||
return;
|
||||
|
||||
var defaultCenter = [CPNotificationCenter defaultCenter];
|
||||
|
||||
if (delegate)
|
||||
{
|
||||
[defaultCenter removeObserver:delegate name:CPComboBoxSelectionIsChangingNotification object:self];
|
||||
[defaultCenter removeObserver:delegate name:CPComboBoxSelectionDidChangeNotification object:self];
|
||||
[defaultCenter removeObserver:delegate name:CPComboBoxWillDismissNotification object:self];
|
||||
[defaultCenter removeObserver:delegate name:CPComboBoxWillPopUpNotification object:self];
|
||||
}
|
||||
_implementedDelegateComboBoxMethods = 0;
|
||||
|
||||
if (aDelegate)
|
||||
{
|
||||
if ([aDelegate respondsToSelector:@selector(comboBoxSelectionIsChanging:)])
|
||||
[defaultCenter addObserver:delegate
|
||||
selector:@selector(comboBoxSelectionIsChanging:)
|
||||
name:CPComboBoxSelectionIsChangingNotification
|
||||
object:self];
|
||||
_implementedDelegateComboBoxMethods |= CPComboBoxDelegate_comboBoxSelectionIsChanging_;
|
||||
|
||||
if ([aDelegate respondsToSelector:@selector(comboBoxSelectionDidChange:)])
|
||||
[defaultCenter addObserver:delegate
|
||||
selector:@selector(comboBoxSelectionDidChange:)
|
||||
name:CPComboBoxSelectionDidChangeNotification
|
||||
object:self];
|
||||
_implementedDelegateComboBoxMethods |= CPComboBoxDelegate_comboBoxSelectionDidChange_;
|
||||
|
||||
if ([aDelegate respondsToSelector:@selector(comboBoxWillPopUp:)])
|
||||
[defaultCenter addObserver:delegate
|
||||
selector:@selector(comboBoxWillPopUp:)
|
||||
name:CPComboBoxWillPopUpNotification
|
||||
object:self];
|
||||
_implementedDelegateComboBoxMethods |= CPComboBoxDelegate_comboBoxWillPopUp_;
|
||||
|
||||
if ([aDelegate respondsToSelector:@selector(comboBoxWillDismiss:)])
|
||||
[defaultCenter addObserver:delegate
|
||||
selector:@selector(comboBoxWillDissmis:)
|
||||
name:CPComboBoxWillDismissNotification
|
||||
object:self];
|
||||
_implementedDelegateComboBoxMethods |= CPComboBoxDelegate_comboBoxWillDismiss_;
|
||||
}
|
||||
|
||||
[super setDelegate:aDelegate];
|
||||
@@ -231,7 +256,7 @@ var CPComboBoxTextSubview = @"text",
|
||||
|
||||
#pragma mark Setting a Data Source
|
||||
|
||||
- (id /*< CPComboBoxDataSource >*/)dataSource
|
||||
- (id <CPComboBoxDataSource>)dataSource
|
||||
{
|
||||
if (!_usesDataSource)
|
||||
[self _dataSourceWarningForMethod:_cmd condition:NO];
|
||||
@@ -239,10 +264,12 @@ var CPComboBoxTextSubview = @"text",
|
||||
return _dataSource;
|
||||
}
|
||||
|
||||
- (void)setDataSource:(id /*< CPComboBoxDataSource >*/)aSource
|
||||
- (void)setDataSource:(id <CPComboBoxDataSource>)aSource
|
||||
{
|
||||
if (!_usesDataSource)
|
||||
{
|
||||
[self _dataSourceWarningForMethod:_cmd condition:NO];
|
||||
}
|
||||
else if (_dataSource !== aSource)
|
||||
{
|
||||
if (![aSource respondsToSelector:@selector(numberOfItemsInComboBox:)] ||
|
||||
@@ -251,7 +278,9 @@ var CPComboBoxTextSubview = @"text",
|
||||
CPLog.warn("Illegal %s data source (%s). Must implement numberOfItemsInComboBox: and comboBox:objectValueForItemAtIndex:", [self className], [aSource description]);
|
||||
}
|
||||
else
|
||||
{
|
||||
_dataSource = aSource;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -369,49 +398,57 @@ var CPComboBoxTextSubview = @"text",
|
||||
if (_listDelegate === aDelegate)
|
||||
return;
|
||||
|
||||
var defaultCenter = [CPNotificationCenter defaultCenter];
|
||||
|
||||
if (_listDelegate)
|
||||
{
|
||||
[defaultCenter removeObserver:self name:_CPPopUpListWillPopUpNotification object:_listDelegate];
|
||||
[defaultCenter removeObserver:self name:_CPPopUpListWillDismissNotification object:_listDelegate];
|
||||
[defaultCenter removeObserver:self name:_CPPopUpListDidDismissNotification object:_listDelegate];
|
||||
[defaultCenter removeObserver:self name:_CPPopUpListItemWasClickedNotification object:_listDelegate];
|
||||
|
||||
var oldTableView = [_listDelegate tableView];
|
||||
|
||||
if (oldTableView)
|
||||
{
|
||||
[defaultCenter removeObserver:self name:CPTableViewSelectionIsChangingNotification object:oldTableView];
|
||||
[defaultCenter removeObserver:self name:CPTableViewSelectionDidChangeNotification object:oldTableView];
|
||||
}
|
||||
}
|
||||
[self _removeObserversForListDelegate:_listDelegate];
|
||||
|
||||
_listDelegate = aDelegate;
|
||||
|
||||
// We only add the observers if the CPComboBox is displayed
|
||||
if ([self window])
|
||||
[self _addObserversForListDelegate:_listDelegate]
|
||||
|
||||
// Apply our text style to the list
|
||||
[_listDelegate setFont:[self font]];
|
||||
[_listDelegate setAlignment:[self alignment]];
|
||||
|
||||
[[_listDelegate scrollView] setHasVerticalScroller:_hasVerticalScroller];
|
||||
|
||||
if (_intercellSpacing)
|
||||
[[_listDelegate tableView] setIntercellSpacing:_intercellSpacing];
|
||||
|
||||
if (_itemHeight)
|
||||
[[_listDelegate tableView] setRowHeight:_itemHeight];
|
||||
}
|
||||
|
||||
- (void)_addObserversForListDelegate:(_CPPopUpList)aDelegate
|
||||
{
|
||||
if (!aDelegate)
|
||||
return;
|
||||
|
||||
var defaultCenter = [CPNotificationCenter defaultCenter];
|
||||
|
||||
[defaultCenter addObserver:self
|
||||
selector:@selector(comboBoxWillPopUp:)
|
||||
name:_CPPopUpListWillPopUpNotification
|
||||
object:_listDelegate];
|
||||
object:aDelegate];
|
||||
|
||||
[defaultCenter addObserver:self
|
||||
selector:@selector(comboBoxWillDismiss:)
|
||||
name:_CPPopUpListWillDismissNotification
|
||||
object:_listDelegate];
|
||||
object:aDelegate];
|
||||
|
||||
[defaultCenter addObserver:self
|
||||
selector:@selector(listDidDismiss:)
|
||||
name:_CPPopUpListDidDismissNotification
|
||||
object:_listDelegate];
|
||||
object:aDelegate];
|
||||
|
||||
[defaultCenter addObserver:self
|
||||
selector:@selector(itemWasClicked:)
|
||||
name:_CPPopUpListItemWasClickedNotification
|
||||
object:_listDelegate];
|
||||
object:aDelegate];
|
||||
|
||||
[[_listDelegate scrollView] setHasVerticalScroller:_hasVerticalScroller];
|
||||
[[aDelegate scrollView] setHasVerticalScroller:_hasVerticalScroller];
|
||||
|
||||
var tableView = [_listDelegate tableView];
|
||||
var tableView = [aDelegate tableView];
|
||||
|
||||
[defaultCenter addObserver:self
|
||||
selector:@selector(comboBoxSelectionIsChanging:)
|
||||
@@ -422,10 +459,27 @@ var CPComboBoxTextSubview = @"text",
|
||||
selector:@selector(comboBoxSelectionDidChange:)
|
||||
name:CPTableViewSelectionDidChangeNotification
|
||||
object:tableView];
|
||||
}
|
||||
|
||||
// Apply our text style to the list
|
||||
[_listDelegate setFont:[self font]];
|
||||
[_listDelegate setAlignment:[self alignment]];
|
||||
- (void)_removeObserversForListDelegate:(_CPPopUpList)aDelegate
|
||||
{
|
||||
if (!aDelegate)
|
||||
return;
|
||||
|
||||
var defaultCenter = [CPNotificationCenter defaultCenter];
|
||||
|
||||
[defaultCenter removeObserver:self name:_CPPopUpListWillPopUpNotification object:aDelegate];
|
||||
[defaultCenter removeObserver:self name:_CPPopUpListWillDismissNotification object:aDelegate];
|
||||
[defaultCenter removeObserver:self name:_CPPopUpListDidDismissNotification object:aDelegate];
|
||||
[defaultCenter removeObserver:self name:_CPPopUpListItemWasClickedNotification object:aDelegate];
|
||||
|
||||
var oldTableView = [aDelegate tableView];
|
||||
|
||||
if (oldTableView)
|
||||
{
|
||||
[defaultCenter removeObserver:self name:CPTableViewSelectionIsChangingNotification object:oldTableView];
|
||||
[defaultCenter removeObserver:self name:CPTableViewSelectionDidChangeNotification object:oldTableView];
|
||||
}
|
||||
}
|
||||
|
||||
- (int)indexOfItemWithObjectValue:(id)anObject
|
||||
@@ -470,8 +524,6 @@ var CPComboBoxTextSubview = @"text",
|
||||
if (!_listDelegate)
|
||||
[self setListDelegate:[[_CPPopUpList alloc] initWithDataSource:self]];
|
||||
|
||||
[self _selectMatchingItem];
|
||||
|
||||
// Note the offset here is 1 less than the focus ring width because the outer edge
|
||||
// of the focus ring is very transparent and it looks better if the list is closer.
|
||||
if (CPComboBoxFocusRingWidth < 0)
|
||||
@@ -482,6 +534,7 @@ var CPComboBoxTextSubview = @"text",
|
||||
}
|
||||
|
||||
[_listDelegate popUpRelativeToRect:[self _borderFrame] view:self offset:CPComboBoxFocusRingWidth - 1];
|
||||
[self _selectMatchingItem];
|
||||
}
|
||||
|
||||
/*! @ignore */
|
||||
@@ -817,13 +870,17 @@ var CPComboBoxTextSubview = @"text",
|
||||
- (void)setFont:(CPFont)aFont
|
||||
{
|
||||
[super setFont:aFont];
|
||||
[_listDelegate setFont:aFont];
|
||||
|
||||
if (_listDelegate)
|
||||
[_listDelegate setFont:aFont];
|
||||
}
|
||||
|
||||
- (void)setAlignment:(CPTextAlignment)alignment
|
||||
{
|
||||
[super setAlignment:alignment];
|
||||
[_listDelegate setAlignment:alignment];
|
||||
|
||||
if (_listDelegate)
|
||||
[_listDelegate setAlignment:alignment];
|
||||
}
|
||||
|
||||
#pragma mark Pop Up Button Layout
|
||||
@@ -894,7 +951,9 @@ var CPComboBoxTextSubview = @"text",
|
||||
index = [_dataSource comboBox:self indexOfItemWithStringValue:stringValue]
|
||||
}
|
||||
else
|
||||
{
|
||||
index = [self indexOfItemWithObjectValue:stringValue];
|
||||
}
|
||||
|
||||
[_listDelegate selectRow:index];
|
||||
|
||||
@@ -946,6 +1005,28 @@ var CPComboBoxTextSubview = @"text",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Observers method
|
||||
|
||||
- (void)_addObservers
|
||||
{
|
||||
if (_isObserving)
|
||||
return;
|
||||
|
||||
[super _addObservers];
|
||||
[self _addObserversForListDelegate:_listDelegate];
|
||||
}
|
||||
|
||||
- (void)_removeObservers
|
||||
{
|
||||
if (!_isObserving)
|
||||
return;
|
||||
|
||||
[super _removeObservers];
|
||||
[self _removeObserversForListDelegate:_listDelegate];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPComboBox (CPComboBoxDelegate)
|
||||
@@ -953,24 +1034,36 @@ var CPComboBoxTextSubview = @"text",
|
||||
/*! @ignore */
|
||||
- (void)comboBoxSelectionIsChanging:(CPNotification)aNotification
|
||||
{
|
||||
if (_implementedDelegateComboBoxMethods & CPComboBoxDelegate_comboBoxSelectionIsChanging_)
|
||||
[_delegate comboBoxSelectionIsChanging:[[CPNotification alloc] initWithName:CPComboBoxSelectionIsChangingNotification object:self userInfo:nil]];
|
||||
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPComboBoxSelectionIsChangingNotification object:self];
|
||||
}
|
||||
|
||||
/*! @ignore */
|
||||
- (void)comboBoxSelectionDidChange:(CPNotification)aNotification
|
||||
{
|
||||
if (_implementedDelegateComboBoxMethods & CPComboBoxDelegate_comboBoxSelectionDidChange_)
|
||||
[_delegate comboBoxSelectionDidChange:[[CPNotification alloc] initWithName:CPComboBoxSelectionDidChangeNotification object:self userInfo:nil]];
|
||||
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPComboBoxSelectionDidChangeNotification object:self];
|
||||
}
|
||||
|
||||
/*! @ignore */
|
||||
- (void)comboBoxWillPopUp:(CPNotification)aNotification
|
||||
{
|
||||
if (_implementedDelegateComboBoxMethods & CPComboBoxDelegate_comboBoxWillPopUp_)
|
||||
[_delegate comboBoxWillPopUp:[[CPNotification alloc] initWithName:CPComboBoxWillPopUpNotification object:self userInfo:nil]];
|
||||
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPComboBoxWillPopUpNotification object:self];
|
||||
}
|
||||
|
||||
/*! @ignore */
|
||||
- (void)comboBoxWillDismiss:(CPNotification)aNotification
|
||||
{
|
||||
if (_implementedDelegateComboBoxMethods & CPComboBoxDelegate_comboBoxWillDismiss_)
|
||||
[_delegate comboBoxWillDismiss:[[CPNotification alloc] initWithName:CPComboBoxWillDismissNotification object:self userInfo:nil]];
|
||||
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPComboBoxWillDismissNotification object:self];
|
||||
}
|
||||
|
||||
|
||||
@@ -78,6 +78,8 @@ CPInputOnInputEventFeature = 30;
|
||||
|
||||
CPFileAPIFeature = 31;
|
||||
|
||||
CPAltEnterTextAreaFeature = 32;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
@@ -100,6 +102,7 @@ var USER_AGENT = "",
|
||||
// default these features to true
|
||||
PLATFORM_FEATURES[CPInputTypeCanBeChangedFeature] = YES;
|
||||
PLATFORM_FEATURES[CPInputSetFontOutsideOfDOM] = YES;
|
||||
PLATFORM_FEATURES[CPAltEnterTextAreaFeature] = YES;
|
||||
|
||||
if (typeof window !== "undefined" && typeof window.navigator !== "undefined")
|
||||
USER_AGENT = window.navigator.userAgent;
|
||||
@@ -208,6 +211,7 @@ else if (USER_AGENT.indexOf("Gecko") !== -1) // Must follow KHTML check.
|
||||
// Some day this might be fixed and should be version prefixed. No known fixed version yet.
|
||||
PLATFORM_FEATURES[CPInput1PxLeftPadding] = YES;
|
||||
|
||||
PLATFORM_FEATURES[CPAltEnterTextAreaFeature] = NO;
|
||||
// This was supposed to be added in Firefox 22, but when testing with the latest beta as of 2013-06-14
|
||||
// it does not seem to work. It seems to exhibit the CPJavaScriptPasteRequiresEditableTarget problem,
|
||||
// and in addition doesn't seem to work with our native copy code either.
|
||||
|
||||
@@ -30,16 +30,31 @@
|
||||
|
||||
@global CPApp
|
||||
|
||||
@protocol CPControlTextEditingDelegate <CPObject>
|
||||
|
||||
@optional
|
||||
- (void)controlTextDidBeginEditing:(CPNotification)aNotification;
|
||||
- (void)controlTextDidChange:(CPNotification)aNotification;
|
||||
- (void)controlTextDidEndEditing:(CPNotification)aNotification;
|
||||
- (void)controlTextDidFocus:(CPNotification)aNotification;
|
||||
- (void)controlTextDidBlur:(CPNotification)aNotification;
|
||||
- (BOOL)control:(CPControl)control didFailToFormatString:(CPString)string errorDescription:(CPString)error;
|
||||
|
||||
@end
|
||||
|
||||
@typedef CPTextAlignment
|
||||
CPLeftTextAlignment = 0;
|
||||
CPRightTextAlignment = 1;
|
||||
CPCenterTextAlignment = 2;
|
||||
CPJustifiedTextAlignment = 3;
|
||||
CPNaturalTextAlignment = 4;
|
||||
|
||||
@typedef CPControlSize
|
||||
CPRegularControlSize = 0;
|
||||
CPSmallControlSize = 1;
|
||||
CPMiniControlSize = 2;
|
||||
|
||||
@typedef CPLineBreakMode
|
||||
CPLineBreakByWordWrapping = 0;
|
||||
CPLineBreakByCharWrapping = 1;
|
||||
CPLineBreakByClipping = 2;
|
||||
@@ -47,11 +62,13 @@ CPLineBreakByTruncatingHead = 3;
|
||||
CPLineBreakByTruncatingTail = 4;
|
||||
CPLineBreakByTruncatingMiddle = 5;
|
||||
|
||||
@typedef CPVerticalTextAlignment
|
||||
CPTopVerticalTextAlignment = 1;
|
||||
CPCenterVerticalTextAlignment = 2;
|
||||
CPBottomVerticalTextAlignment = 3;
|
||||
|
||||
// Deprecated for use with images, use the CPImageScale constants
|
||||
@typedef CPImageScaling
|
||||
CPScaleProportionally = 0;
|
||||
CPScaleToFit = 1;
|
||||
CPScaleNone = 2;
|
||||
@@ -61,6 +78,7 @@ CPImageScaleAxesIndependently = 1;
|
||||
CPImageScaleNone = 2;
|
||||
CPImageScaleProportionallyUpOrDown = 3;
|
||||
|
||||
@typedef CPCellImagePosition
|
||||
CPNoImage = 0;
|
||||
CPImageOnly = 1;
|
||||
CPImageLeft = 2;
|
||||
@@ -106,6 +124,8 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
BOOL _trackingWasWithinFrame;
|
||||
unsigned _trackingMouseDownFlags;
|
||||
CGPoint _previousTrackingLocation;
|
||||
|
||||
CPControlSize _controlSize;
|
||||
}
|
||||
|
||||
+ (CPDictionary)themeAttributes
|
||||
@@ -122,6 +142,7 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
@"image-scaling": CPScaleToFit,
|
||||
@"min-size": CGSizeMakeZero(),
|
||||
@"max-size": CGSizeMake(-1.0, -1.0),
|
||||
@"nib2cib-adjustment-frame": CGRectMakeZero()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -177,13 +198,95 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
|
||||
if (self)
|
||||
{
|
||||
_sendActionOn = CPLeftMouseUpMask;
|
||||
_sendActionOn = CPLeftMouseUpMask;
|
||||
_trackingMouseDownFlags = 0;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Control Size
|
||||
|
||||
/*!
|
||||
Returns the control's control size
|
||||
*/
|
||||
- (CPControlSize)controlSize
|
||||
{
|
||||
return _controlSize;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the control's size.
|
||||
@param aControlSize the control's size
|
||||
*/
|
||||
- (void)setControlSize:(CPControlSize)aControlSize
|
||||
{
|
||||
if (_controlSize === aControlSize)
|
||||
return;
|
||||
|
||||
[self unsetThemeState:[self _controlSizeThemeState]];
|
||||
_controlSize = aControlSize;
|
||||
[self setThemeState:[self _controlSizeThemeState]];
|
||||
|
||||
[self setNeedsLayout];
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
/*!
|
||||
Gets the current theme state according to the current controlSize.
|
||||
@return a CPThemeState
|
||||
*/
|
||||
- (ThemeState)_controlSizeThemeState
|
||||
{
|
||||
switch(_controlSize)
|
||||
{
|
||||
case CPSmallControlSize:
|
||||
return CPThemeStateControlSizeSmall;
|
||||
|
||||
case CPMiniControlSize:
|
||||
return CPThemeStateControlSizeMini;
|
||||
|
||||
case CPRegularControlSize:
|
||||
default:
|
||||
return CPThemeStateControlSizeRegular;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Change frame size according to the theme control size theme constraints
|
||||
Basically for height to min-size.
|
||||
*/
|
||||
- (void)_sizeToControlSize
|
||||
{
|
||||
var frameSize = [self frameSize],
|
||||
minSize = [self currentValueForThemeAttribute:@"min-size"],
|
||||
maxSize = [self currentValueForThemeAttribute:@"max-size"];
|
||||
|
||||
if (minSize.width > 0)
|
||||
{
|
||||
frameSize.width = MAX(minSize.width, frameSize.width);
|
||||
|
||||
if (maxSize.width > 0)
|
||||
frameSize.width = MIN(maxSize.width, frameSize.width);
|
||||
}
|
||||
|
||||
if (minSize.height > 0)
|
||||
{
|
||||
frameSize.height = MAX(minSize.height, frameSize.height);
|
||||
|
||||
if (maxSize.height > 0)
|
||||
frameSize.height = MIN(maxSize.height, frameSize.height);
|
||||
}
|
||||
|
||||
[self setFrameSize:frameSize];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
|
||||
/*!
|
||||
Sets the receiver's target action.
|
||||
|
||||
@@ -915,14 +1018,15 @@ var CPControlBlackColor = [CPColor blackColor];
|
||||
|
||||
@end
|
||||
|
||||
var CPControlValueKey = @"CPControlValueKey",
|
||||
var CPControlActionKey = @"CPControlActionKey",
|
||||
CPControlControlSizeKey = @"CPControlControlSizeKey",
|
||||
CPControlControlStateKey = @"CPControlControlStateKey",
|
||||
CPControlIsEnabledKey = @"CPControlIsEnabledKey",
|
||||
CPControlTargetKey = @"CPControlTargetKey",
|
||||
CPControlActionKey = @"CPControlActionKey",
|
||||
CPControlSendActionOnKey = @"CPControlSendActionOnKey",
|
||||
CPControlFormatterKey = @"CPControlFormatterKey",
|
||||
CPControlIsEnabledKey = @"CPControlIsEnabledKey",
|
||||
CPControlSendActionOnKey = @"CPControlSendActionOnKey",
|
||||
CPControlSendsActionOnEndEditingKey = @"CPControlSendsActionOnEndEditingKey",
|
||||
CPControlTargetKey = @"CPControlTargetKey",
|
||||
CPControlValueKey = @"CPControlValueKey",
|
||||
|
||||
__Deprecated__CPImageViewImageKey = @"CPImageViewImageKey";
|
||||
|
||||
@@ -949,6 +1053,8 @@ var CPControlValueKey = @"CPControlValueKey",
|
||||
[self setSendsActionOnEndEditing:[aCoder decodeBoolForKey:CPControlSendsActionOnEndEditingKey]];
|
||||
|
||||
[self setFormatter:[aCoder decodeObjectForKey:CPControlFormatterKey]];
|
||||
|
||||
[self setControlSize:[aCoder decodeIntForKey:CPControlControlSizeKey]];
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -981,6 +1087,8 @@ var CPControlValueKey = @"CPControlValueKey",
|
||||
|
||||
if (_formatter !== nil)
|
||||
[aCoder encodeObject:_formatter forKey:CPControlFormatterKey];
|
||||
|
||||
[aCoder encodeInt:_controlSize forKey:CPControlControlSizeKey];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -22,6 +22,7 @@ Cursor support by browser:
|
||||
*/
|
||||
|
||||
@import <Foundation/CPObject.j>
|
||||
@import "CPImage.j"
|
||||
|
||||
@global CPApp
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
@import <Foundation/CPArray.j>
|
||||
@import <Foundation/CPObject.j>
|
||||
@import <Foundation/CPDate.j>
|
||||
@import <Foundation/CPDateFormatter.j>
|
||||
@import <Foundation/CPLocale.j>
|
||||
@import <Foundation/CPTimeZone.j>
|
||||
|
||||
@@ -76,6 +75,7 @@ CPEraDatePickerElementFlag = 0x0100;
|
||||
CPInteger _datePickerStyle @accessors(property=datePickerStyle);
|
||||
CPInteger _timeInterval @accessors(property=timeInterval);
|
||||
|
||||
BOOL _invokedByUserEvent;
|
||||
_CPDatePickerTextField _datePickerTextfield;
|
||||
_CPDatePickerCalendar _datePickerCalendar;
|
||||
unsigned _implementedCDatePickerDelegateMethods;
|
||||
@@ -206,24 +206,32 @@ CPEraDatePickerElementFlag = 0x0100;
|
||||
if (!_locale)
|
||||
_locale = [CPLocale currentLocale];
|
||||
|
||||
if (!_timeZone)
|
||||
_timeZone = [CPTimeZone systemTimeZone];
|
||||
|
||||
_datePickerTextfield = [[_CPDatePickerTextField alloc] initWithFrame:[self bounds] withDatePicker:self];
|
||||
|
||||
[_datePickerTextfield setDateValue:_dateValue];
|
||||
[self addSubview:_datePickerTextfield];
|
||||
|
||||
_datePickerCalendar = [[_CPDatePickerCalendar alloc] initWithFrame:[self bounds] withDatePicker:self];
|
||||
[_datePickerCalendar setDateValue:_dateValue];
|
||||
[_datePickerCalendar setHidden:YES];
|
||||
[self addSubview:_datePickerCalendar];
|
||||
|
||||
// We might have been unarchived in a disabled state.
|
||||
[_datePickerTextfield setEnabled:[self isEnabled]];
|
||||
|
||||
[self setNeedsDisplay:YES];
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Control Size
|
||||
|
||||
- (void)setControlSize:(CPControlSize)aControlSize
|
||||
{
|
||||
[super setControlSize:aControlSize];
|
||||
|
||||
if ([self datePickerStyle] == CPTextFieldAndStepperDatePickerStyle || [self datePickerStyle] == CPTextFieldDatePickerStyle)
|
||||
[self _sizeToControlSize];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Delegate methods
|
||||
|
||||
@@ -252,15 +260,26 @@ CPEraDatePickerElementFlag = 0x0100;
|
||||
|
||||
if (_datePickerStyle == CPTextFieldAndStepperDatePickerStyle || _datePickerStyle == CPTextFieldDatePickerStyle)
|
||||
{
|
||||
[_datePickerTextfield setHidden:NO];
|
||||
[_datePickerCalendar setHidden:YES];
|
||||
if (![_datePickerTextfield superview])
|
||||
[self addSubview:_datePickerTextfield];
|
||||
|
||||
if ([_datePickerCalendar superview])
|
||||
[_datePickerCalendar removeFromSuperview];
|
||||
|
||||
[_datePickerTextfield setControlSize:[self controlSize]];
|
||||
[_datePickerTextfield setNeedsLayout];
|
||||
[_datePickerTextfield setNeedsDisplay:YES];
|
||||
}
|
||||
else
|
||||
{
|
||||
[_datePickerCalendar setHidden:NO];
|
||||
[_datePickerTextfield setHidden:YES];
|
||||
if (![_datePickerCalendar superview])
|
||||
[self addSubview:_datePickerCalendar];
|
||||
|
||||
if ([_datePickerTextfield superview])
|
||||
[_datePickerTextfield removeFromSuperview];
|
||||
|
||||
[_datePickerCalendar setNeedsLayout];
|
||||
[_datePickerCalendar setNeedsDisplay:YES];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,11 +294,14 @@ CPEraDatePickerElementFlag = 0x0100;
|
||||
return _dateValue
|
||||
}
|
||||
|
||||
/*! Set the objectValue ofhe datePier. It has to be a CPDate
|
||||
/*! Set the objectValue of the datePicker. It has to be a CPDate
|
||||
@param aDateValue the dateValue
|
||||
*/
|
||||
- (void)setObjectValue:(CPDate)aValue
|
||||
{
|
||||
if (![aValue isKindOfClass:[CPDate class]])
|
||||
return;
|
||||
|
||||
[self setDateValue:aValue];
|
||||
}
|
||||
|
||||
@@ -291,6 +313,7 @@ CPEraDatePickerElementFlag = 0x0100;
|
||||
if (aDateValue == nil)
|
||||
return;
|
||||
|
||||
_invokedByUserEvent = NO;
|
||||
[self _setDateValue:aDateValue timeInterval:_timeInterval];
|
||||
}
|
||||
|
||||
@@ -309,7 +332,14 @@ CPEraDatePickerElementFlag = 0x0100;
|
||||
aTimeInterval = MAX(MIN(aTimeInterval, [_maxDate timeIntervalSinceDate:aDateValue]), [_minDate timeIntervalSinceDate:aDateValue]);
|
||||
|
||||
if ([aDateValue isEqualToDate:_dateValue] && aTimeInterval == _timeInterval)
|
||||
{
|
||||
if (_datePickerStyle == CPTextFieldAndStepperDatePickerStyle || _datePickerStyle == CPTextFieldDatePickerStyle)
|
||||
[_datePickerTextfield setDateValue:_dateValue];
|
||||
else
|
||||
[_datePickerCalendar setDateValue:_dateValue];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (_implementedCDatePickerDelegateMethods & CPDatePicker_validateProposedDateValue_timeInterval)
|
||||
{
|
||||
@@ -331,7 +361,8 @@ CPEraDatePickerElementFlag = 0x0100;
|
||||
_timeInterval = (_datePickerMode == CPSingleDateMode)? 0 : aTimeInterval;
|
||||
[self didChangeValueForKey:@"timeInterval"];
|
||||
|
||||
[self sendAction:[self action] to:[self target]];
|
||||
if (_invokedByUserEvent)
|
||||
[self sendAction:[self action] to:[self target]];
|
||||
|
||||
if (_datePickerStyle == CPTextFieldAndStepperDatePickerStyle || _datePickerStyle == CPTextFieldDatePickerStyle)
|
||||
[_datePickerTextfield setDateValue:_dateValue];
|
||||
@@ -370,6 +401,8 @@ CPEraDatePickerElementFlag = 0x0100;
|
||||
{
|
||||
_datePickerStyle = aDatePickerStyle;
|
||||
|
||||
[self setControlSize:[self controlSize]];
|
||||
|
||||
[self setNeedsDisplay:YES];
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
@@ -509,6 +542,11 @@ CPEraDatePickerElementFlag = 0x0100;
|
||||
[self didChangeValueForKey:@"timeZone"];
|
||||
|
||||
[self setNeedsLayout];
|
||||
|
||||
if (_datePickerStyle == CPTextFieldAndStepperDatePickerStyle || _datePickerStyle == CPTextFieldDatePickerStyle)
|
||||
[_datePickerTextfield setDateValue:_dateValue];
|
||||
else
|
||||
[_datePickerCalendar setDateValue:_dateValue];
|
||||
}
|
||||
|
||||
|
||||
@@ -520,11 +558,16 @@ CPEraDatePickerElementFlag = 0x0100;
|
||||
- (BOOL)becomeFirstResponder
|
||||
{
|
||||
if (_datePickerStyle == CPTextFieldAndStepperDatePickerStyle || _datePickerStyle == CPTextFieldDatePickerStyle)
|
||||
[_datePickerTextfield _selecteTextFieldWithFlags:[[CPApp currentEvent] modifierFlags]];
|
||||
else
|
||||
return NO;
|
||||
{
|
||||
if (![super becomeFirstResponder])
|
||||
return NO;
|
||||
|
||||
return YES;
|
||||
[_datePickerTextfield _selectTextFieldWithFlags:[[CPApp currentEvent] modifierFlags]];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
/*! Return YES
|
||||
@@ -628,12 +671,13 @@ var CPDatePickerModeKey = @"CPDatePickerModeKey",
|
||||
_timeInterval = [aCoder decodeDoubleForKey:CPIntervalKey];
|
||||
_datePickerMode = [aCoder decodeIntForKey:CPDatePickerModeKey];
|
||||
_datePickerElements = [aCoder decodeIntForKey:CPDatePickerElementsKey];
|
||||
_datePickerStyle = [aCoder decodeIntForKey:CPDatePickerStyleKey];
|
||||
[self setDatePickerStyle:[aCoder decodeIntForKey:CPDatePickerStyleKey]];
|
||||
_locale = [aCoder decodeObjectForKey:CPLocaleKey];
|
||||
_dateValue = [aCoder decodeObjectForKey:CPDateValueKey];
|
||||
_backgroundColor = [aCoder decodeObjectForKey:CPBackgroundColorKey];
|
||||
_drawsBackground = [aCoder decodeBoolForKey:CPDrawsBackgroundKey];
|
||||
_isBordered = [aCoder decodeBoolForKey:CPBorderedKey];
|
||||
|
||||
[self _init];
|
||||
}
|
||||
|
||||
@@ -642,7 +686,9 @@ var CPDatePickerModeKey = @"CPDatePickerModeKey",
|
||||
|
||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
// FIXME Do we need to encode _datePickerTextfield and _datePickerCalendar? As subviews they'll be encoded, but when we decode we recreate them anyhow.
|
||||
[super encodeWithCoder:aCoder];
|
||||
|
||||
[aCoder encodeDouble:_timeInterval forKey:CPIntervalKey];
|
||||
[aCoder encodeInt:_datePickerMode forKey:CPDatePickerModeKey];
|
||||
[aCoder encodeInt:_datePickerStyle forKey:CPDatePickerStyleKey];
|
||||
@@ -655,6 +701,7 @@ var CPDatePickerModeKey = @"CPDatePickerModeKey",
|
||||
[aCoder encodeObject:_backgroundColor forKey:CPBackgroundColorKey];
|
||||
[aCoder encodeObject:_drawsBackground forKey:CPDrawsBackgroundKey];
|
||||
[aCoder encodeObject:_isBordered forKey:CPBorderedKey];
|
||||
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -29,7 +29,11 @@
|
||||
@import <Foundation/Foundation.j>
|
||||
|
||||
@class CPDatePicker
|
||||
@class _CPDatePickerMonthView
|
||||
@class _CPDatePickerHeaderView
|
||||
@class _CPDatePickerBox
|
||||
|
||||
@global CPApp
|
||||
@global CPSingleDateMode
|
||||
@global CPRangeDateMode
|
||||
|
||||
@@ -43,6 +47,10 @@
|
||||
@global CPYearMonthDayDatePickerElementFlag
|
||||
@global CPEraDatePickerElementFlag
|
||||
|
||||
@global CPAlternateKeyMask
|
||||
@global CPCommandKeyMask
|
||||
@global CPControlKeyMask
|
||||
|
||||
var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"],
|
||||
CPShortWeekDayNameArrayUS = [@"Su", @"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa"],
|
||||
CPShortWeekDayNameArrayFr = [@"L", @"M", @"M", @"J", @"V", @"S", @"D"],
|
||||
@@ -58,7 +66,7 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
||||
_CPDatePickerMonthView _monthView;
|
||||
_CPDatePickerHeaderView _headerView;
|
||||
_CPDatePickerClock _datePickerClock;
|
||||
CPBox _box;
|
||||
_CPDatePickerBox _box;
|
||||
CPDatePicker _datePicker;
|
||||
CPInteger _startSelectionIndex;
|
||||
CPInteger _currentSelectionIndex;
|
||||
@@ -80,6 +88,7 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
||||
_datePicker = aDatePicker
|
||||
[self _init];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -91,7 +100,7 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
||||
sizeCalendar = [_datePicker valueForThemeAttribute:@"size-calendar"],
|
||||
sizeClock = [_datePicker valueForThemeAttribute:@"size-clock"];
|
||||
|
||||
_box = [[_DatePickerBox alloc] initWithFrame:CGRectMake(0, 0, sizeCalendar.width, sizeHeader.height + sizeCalendar.height)];
|
||||
_box = [[_CPDatePickerBox alloc] initWithFrame:CGRectMake(0, 0, sizeCalendar.width, sizeHeader.height + sizeCalendar.height)];
|
||||
[_box setDatePicker:_datePicker];
|
||||
|
||||
_headerView = [[_CPDatePickerHeaderView alloc] initWithFrame:CGRectMake(0, 0, sizeHeader.width, sizeHeader.height) datePicker:_datePicker delegate:self];
|
||||
@@ -113,11 +122,6 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
||||
#pragma mark -
|
||||
#pragma mark Responder methods
|
||||
|
||||
- (BOOL)becomeFirstResponder
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)acceptsFirstResponder
|
||||
{
|
||||
return YES;
|
||||
@@ -215,6 +219,8 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
||||
[_headerView setHidden:YES];
|
||||
[_monthView setHidden:YES];
|
||||
}
|
||||
|
||||
[self setFrameSize:[_datePicker frameSize]];
|
||||
}
|
||||
|
||||
|
||||
@@ -223,16 +229,62 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
||||
|
||||
/*! Move to the nextMonth without changing the dateValue of the datePicker
|
||||
*/
|
||||
- (void)_nextMonth:(id)sender
|
||||
- (void)_clickArrowNext:(id)sender
|
||||
{
|
||||
[self setDateValue:[_monthView nextMonth]];
|
||||
var currentEvent = [CPApp currentEvent],
|
||||
modifierFlags = [currentEvent modifierFlags];
|
||||
|
||||
if (modifierFlags & (CPCommandKeyMask | CPControlKeyMask | CPAlternateKeyMask))
|
||||
{
|
||||
var date = [[_monthView monthDate] copy];
|
||||
date.setDate(1);
|
||||
|
||||
if (modifierFlags & CPAlternateKeyMask)
|
||||
date.setUTCFullYear(date.getUTCFullYear() + 10);
|
||||
else
|
||||
date.setUTCFullYear(date.getUTCFullYear() + 1);
|
||||
|
||||
[self setDateValue:date];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self _displayNextMonth];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_displayNextMonth
|
||||
{
|
||||
[self setDateValue:[_monthView nextMonth]];
|
||||
}
|
||||
|
||||
- (void)_displayPreviousMonth
|
||||
{
|
||||
[self setDateValue:[_monthView previousMonth]];
|
||||
}
|
||||
|
||||
/*! Move to the previous month without changing the dateValue of the datePicker
|
||||
*/
|
||||
- (void)_previousMonth:(id)sender
|
||||
- (void)_clickArrowPrevious:(id)sender
|
||||
{
|
||||
[self setDateValue:[_monthView previousMonth]];
|
||||
var currentEvent = [CPApp currentEvent],
|
||||
modifierFlags = [currentEvent modifierFlags];
|
||||
|
||||
if (modifierFlags & (CPCommandKeyMask | CPControlKeyMask | CPAlternateKeyMask))
|
||||
{
|
||||
var date = [[_monthView monthDate] copy];
|
||||
date.setDate(1);
|
||||
|
||||
if (modifierFlags & CPAlternateKeyMask)
|
||||
date.setUTCFullYear(date.getUTCFullYear() - 10);
|
||||
else
|
||||
date.setUTCFullYear(date.getUTCFullYear() - 1);
|
||||
|
||||
[self setDateValue:date];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self _displayPreviousMonth];
|
||||
}
|
||||
}
|
||||
|
||||
/*! Move to the current selected day
|
||||
@@ -334,10 +386,12 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
||||
[self addSubview:_currentButton];
|
||||
|
||||
[_previousButton setTarget:aDelegate];
|
||||
[_previousButton setAction:@selector(_previousMonth:)];
|
||||
[_previousButton setAction:@selector(_clickArrowPrevious:)];
|
||||
[_previousButton setContinuous:YES];
|
||||
|
||||
[_nextButton setTarget:aDelegate];
|
||||
[_nextButton setAction:@selector(_nextMonth:)];
|
||||
[_nextButton setAction:@selector(_clickArrowNext:)];
|
||||
[_nextButton setContinuous:YES];
|
||||
|
||||
[_currentButton setTarget:aDelegate];
|
||||
[_currentButton setAction:@selector(_currentMonth:)];
|
||||
@@ -683,7 +737,7 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
||||
|
||||
[dayTile setDate:[currentDate copy]];
|
||||
[dayTile setStringValue:currentDate.getDate()];
|
||||
[dayTile setDisabled:![self isEnabled] || currentDate.getMonth() !== currentMonth.getMonth()];
|
||||
[dayTile setDisabled:![self isEnabled] || currentDate.getMonth() !== currentMonth.getMonth() || currentDate < [_datePicker minDate] || currentDate > [_datePicker maxDate]];
|
||||
[dayTile setHighlighted:isPresentMonth && currentDate.getDate() == now.getDate()];
|
||||
}
|
||||
|
||||
@@ -845,26 +899,62 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
||||
_indexDayTile = -1;
|
||||
_eventDragged = nil
|
||||
|
||||
_datePicker._invokedByUserEvent = YES;
|
||||
|
||||
// Check if we have to change or not the month of the component
|
||||
if ([dayTile date].getMonth() == _date.getMonth())
|
||||
{
|
||||
var minDate = [[_datePicker minDate] copy],
|
||||
maxDate = [[_datePicker maxDate] copy];
|
||||
if ([_datePicker datePickerMode] == CPRangeDateMode && [anEvent modifierFlags] & CPShiftKeyMask)
|
||||
{
|
||||
var dateValueAtMidnight = [[_datePicker dateValue] copy];
|
||||
|
||||
[minDate _resetToMidnight];
|
||||
[maxDate _resetToLastSeconds];
|
||||
[dateValueAtMidnight _resetToMidnight];
|
||||
|
||||
if (dateTile >= minDate && dateTile <= maxDate)
|
||||
[_datePicker _setDateValue:[self _hoursMinutesSecondsFromDatePickerForDate:dateTile] timeInterval:0];
|
||||
if (dateTile < dateValueAtMidnight)
|
||||
{
|
||||
var interval;
|
||||
|
||||
if (dateTile == dateValueAtMidnight)
|
||||
interval = [_datePicker timeInterval];
|
||||
else
|
||||
interval = ([dateValueAtMidnight timeIntervalSinceDate:dateTile] + [_datePicker timeInterval]);
|
||||
|
||||
[_datePicker _setDateValue:[self _hoursMinutesSecondsFromDatePickerForDate:dateTile] timeInterval:interval];
|
||||
}
|
||||
else if ([[dayTile date] isEqualToDate:dateValueAtMidnight])
|
||||
{
|
||||
[_datePicker _setDateValue:[self _hoursMinutesSecondsFromDatePickerForDate:dateTile] timeInterval:0];
|
||||
}
|
||||
else
|
||||
{
|
||||
[_datePicker _setDateValue:[self _hoursMinutesSecondsFromDatePickerForDate:[dateValueAtMidnight copy]] timeInterval:([dateTile timeIntervalSinceDate:dateValueAtMidnight])];
|
||||
}
|
||||
|
||||
// Be sure to display the good month
|
||||
[_delegate setDateValue:dateTile];
|
||||
}
|
||||
else
|
||||
{
|
||||
var minDate = [[_datePicker minDate] copy],
|
||||
maxDate = [[_datePicker maxDate] copy];
|
||||
|
||||
[minDate _resetToMidnight];
|
||||
[maxDate _resetToLastSeconds];
|
||||
|
||||
if (dateTile >= minDate && dateTile <= maxDate)
|
||||
[_datePicker _setDateValue:[self _hoursMinutesSecondsFromDatePickerForDate:dateTile] timeInterval:0];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check the year and the month. The year is usefull when changing from Jan to Dec.
|
||||
if (_date.getMonth() - [dayTile date].getMonth() == 1 || _date.getFullYear() - [dayTile date].getFullYear() == 1)
|
||||
[_delegate _previousMonth:self];
|
||||
[_delegate _displayPreviousMonth];
|
||||
else
|
||||
[_delegate _nextMonth:self];
|
||||
[_delegate _displayNextMonth];
|
||||
}
|
||||
|
||||
_datePicker._invokedByUserEvent = NO;
|
||||
}
|
||||
|
||||
/*! Mouse dragged event
|
||||
@@ -882,6 +972,8 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
||||
_indexDayTile = [self indexOfTileForEvent:anEvent];
|
||||
_eventDragged = anEvent;
|
||||
|
||||
_datePicker._invokedByUserEvent = YES;
|
||||
|
||||
if ([_datePicker datePickerMode] == CPSingleDateMode)
|
||||
{
|
||||
// Check if we have to change or not the month of the component
|
||||
@@ -899,9 +991,9 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
||||
|
||||
// Check the year and the month. The year is usefull when changing from Jan to Dec.
|
||||
if (_date.getMonth() - [dayTile date].getMonth() == 1 || _date.getFullYear() - [dayTile date].getFullYear() == 1)
|
||||
[_delegate _previousMonth:self];
|
||||
[_delegate _displayPreviousMonth];
|
||||
else
|
||||
[_delegate _nextMonth:self];
|
||||
[_delegate _displayNextMonth];
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -923,6 +1015,8 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
||||
[_datePicker _setDateValue:[self _hoursMinutesSecondsFromDatePickerForDate:_clickDate] timeInterval:[dateTile timeIntervalSinceDate:dateValueAtMidnight]];
|
||||
}
|
||||
}
|
||||
|
||||
_datePicker._invokedByUserEvent = NO;
|
||||
}
|
||||
|
||||
- (void)mouseUp:(CPEvent)anEvent
|
||||
@@ -944,7 +1038,7 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
||||
if (_isMonthJustChanged)
|
||||
{
|
||||
_dragDate.setMonth(_date.getMonth() + 1);
|
||||
[_delegate _nextMonth:self];
|
||||
[_delegate _displayNextMonth];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -953,7 +1047,7 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
||||
if (_isMonthJustChanged)
|
||||
{
|
||||
_dragDate.setMonth(_date.getMonth() - 1);
|
||||
[_delegate _previousMonth:self];
|
||||
[_delegate _displayPreviousMonth];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1020,30 +1114,30 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-color" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateDisabled];
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-offset" inState:CPThemeStateDisabled] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateDisabled];
|
||||
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-font" inState:CPThemeStateDisabled | CPThemeStateSelected] forThemeAttribute:@"font" inState:CPThemeStateDisabled | CPThemeStateSelected];
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-color" inState:CPThemeStateDisabled | CPThemeStateSelected] forThemeAttribute:@"text-color" inState:CPThemeStateDisabled | CPThemeStateSelected];
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-color" inState:CPThemeStateDisabled | CPThemeStateSelected] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateDisabled | CPThemeStateSelected];
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-offset" inState:CPThemeStateDisabled | CPThemeStateSelected] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateDisabled | CPThemeStateSelected];
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-font" inState:[CPThemeStateDisabled, CPThemeStateSelected]] forThemeAttribute:@"font" inState:[CPThemeStateDisabled, CPThemeStateSelected]];
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-color" inState:[CPThemeStateDisabled, CPThemeStateSelected]]forThemeAttribute:@"text-color" inState:[CPThemeStateDisabled, CPThemeStateSelected]];
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-color" inState:[CPThemeStateDisabled, CPThemeStateSelected]] forThemeAttribute:@"text-shadow-color" inState:[CPThemeStateDisabled, CPThemeStateSelected]];
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-offset" inState:[CPThemeStateDisabled, CPThemeStateSelected]] forThemeAttribute:@"text-shadow-offset" inState:[CPThemeStateDisabled, CPThemeStateSelected]];
|
||||
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-font" inState:CPThemeStateHighlighted] forThemeAttribute:@"font" inState:CPThemeStateHighlighted];
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-color" inState:CPThemeStateHighlighted] forThemeAttribute:@"text-color" inState:CPThemeStateHighlighted];
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-color" inState:CPThemeStateHighlighted] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateHighlighted];
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-offset" inState:CPThemeStateHighlighted] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateHighlighted];
|
||||
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-font" inState:CPThemeStateHighlighted | CPThemeStateSelected] forThemeAttribute:@"font" inState:CPThemeStateHighlighted | CPThemeStateSelected];
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-color" inState:CPThemeStateHighlighted | CPThemeStateSelected] forThemeAttribute:@"text-color" inState:CPThemeStateHighlighted | CPThemeStateSelected];
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-color" inState:CPThemeStateHighlighted | CPThemeStateSelected] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateHighlighted | CPThemeStateSelected];
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-offset" inState:CPThemeStateHighlighted | CPThemeStateSelected] forThemeAttribute:@"text-shadow-offset" inState:CPThemeStateHighlighted | CPThemeStateSelected];
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-font" inState:[CPThemeStateHighlighted, CPThemeStateSelected]] forThemeAttribute:@"font" inState:[CPThemeStateHighlighted, CPThemeStateSelected]];
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-color" inState:[CPThemeStateHighlighted, CPThemeStateSelected]] forThemeAttribute:@"text-color" inState:[CPThemeStateHighlighted, CPThemeStateSelected]];
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-color" inState:[CPThemeStateHighlighted, CPThemeStateSelected]] forThemeAttribute:@"text-shadow-color" inState:[CPThemeStateHighlighted, CPThemeStateSelected]];
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-offset" inState:[CPThemeStateHighlighted, CPThemeStateSelected]] forThemeAttribute:@"text-shadow-offset" inState:[CPThemeStateHighlighted, CPThemeStateSelected]];
|
||||
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-font" inState: CPThemeStateDisabled | CPThemeStateHighlighted | CPThemeStateSelected] forThemeAttribute:@"font" inState: CPThemeStateDisabled | CPThemeStateHighlighted | CPThemeStateSelected];
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-color" inState: CPThemeStateDisabled | CPThemeStateHighlighted | CPThemeStateSelected] forThemeAttribute:@"text-color" inState: CPThemeStateDisabled | CPThemeStateHighlighted | CPThemeStateSelected];
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-color" inState: CPThemeStateDisabled | CPThemeStateHighlighted | CPThemeStateSelected] forThemeAttribute:@"text-shadow-color" inState: CPThemeStateDisabled | CPThemeStateHighlighted | CPThemeStateSelected];
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-offset" inState: CPThemeStateDisabled | CPThemeStateHighlighted | CPThemeStateSelected] forThemeAttribute:@"text-shadow-offset" inState: CPThemeStateDisabled | CPThemeStateHighlighted | CPThemeStateSelected];
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-font" inState:[CPThemeStateDisabled, CPThemeStateHighlighted, CPThemeStateSelected]] forThemeAttribute:@"font" inState:[CPThemeStateDisabled, CPThemeStateHighlighted, CPThemeStateSelected]];
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-color" inState:[CPThemeStateDisabled, CPThemeStateHighlighted, CPThemeStateSelected]] forThemeAttribute:@"text-color" inState:[CPThemeStateDisabled, CPThemeStateHighlighted, CPThemeStateSelected]];
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-color" inState:[CPThemeStateDisabled, CPThemeStateHighlighted, CPThemeStateSelected]] forThemeAttribute:@"text-shadow-color" inState:[CPThemeStateDisabled, CPThemeStateHighlighted, CPThemeStateSelected]];
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-offset" inState:[CPThemeStateDisabled, CPThemeStateHighlighted, CPThemeStateSelected]] forThemeAttribute:@"text-shadow-offset" inState:[CPThemeStateDisabled, CPThemeStateHighlighted, CPThemeStateSelected]];
|
||||
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-font" inState: CPThemeStateDisabled | CPThemeStateHighlighted ] forThemeAttribute:@"font" inState: CPThemeStateDisabled | CPThemeStateHighlighted ];
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-color" inState: CPThemeStateDisabled | CPThemeStateHighlighted ] forThemeAttribute:@"text-color" inState: CPThemeStateDisabled | CPThemeStateHighlighted ];
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-color" inState: CPThemeStateDisabled | CPThemeStateHighlighted ] forThemeAttribute:@"text-shadow-color" inState: CPThemeStateDisabled | CPThemeStateHighlighted ];
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-offset" inState: CPThemeStateDisabled | CPThemeStateHighlighted ] forThemeAttribute:@"text-shadow-offset" inState: CPThemeStateDisabled | CPThemeStateHighlighted];
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-font" inState:[CPThemeStateDisabled, CPThemeStateHighlighted]] forThemeAttribute:@"font" inState:[CPThemeStateDisabled, CPThemeStateHighlighted]];
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-color" inState:[CPThemeStateDisabled, CPThemeStateHighlighted]] forThemeAttribute:@"text-color" inState:[CPThemeStateDisabled, CPThemeStateHighlighted]];
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-color" inState:[CPThemeStateDisabled, CPThemeStateHighlighted]] forThemeAttribute:@"text-shadow-color" inState:[CPThemeStateDisabled, CPThemeStateHighlighted]];
|
||||
[_textField setValue:[_datePicker valueForThemeAttribute:@"tile-text-shadow-offset" inState:[CPThemeStateDisabled, CPThemeStateHighlighted]] forThemeAttribute:@"text-shadow-offset" inState:[CPThemeStateDisabled, CPThemeStateHighlighted]];
|
||||
|
||||
[self addSubview:_textField];
|
||||
|
||||
@@ -1059,7 +1153,7 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
||||
|
||||
/*! Set a theme
|
||||
*/
|
||||
- (BOOL)setThemeState:(CPThemeState)aState
|
||||
- (BOOL)setThemeState:(ThemeState)aState
|
||||
{
|
||||
[_textField setThemeState:aState];
|
||||
[super setThemeState:aState];
|
||||
@@ -1067,7 +1161,7 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
||||
|
||||
/*! Unset a theme
|
||||
*/
|
||||
- (BOOL)unsetThemeState:(CPThemeState)aState
|
||||
- (BOOL)unsetThemeState:(ThemeState)aState
|
||||
{
|
||||
[_textField unsetThemeState:aState];
|
||||
[super unsetThemeState:aState];
|
||||
@@ -1156,7 +1250,7 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
||||
var themeState = [self themeState],
|
||||
context = [[CPGraphicsContext currentContext] graphicsPort];
|
||||
|
||||
if (themeState & CPThemeStateSelected)
|
||||
if (themeState.hasThemeState(CPThemeStateSelected))
|
||||
{
|
||||
[self setBackgroundColor:[_datePicker valueForThemeAttribute:@"bezel-color-calendar" inState:themeState]];
|
||||
CGContextSetLineWidth(context, [_datePicker valueForThemeAttribute:@"border-width"]);
|
||||
@@ -1175,19 +1269,11 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
||||
@end
|
||||
|
||||
|
||||
@implementation _DatePickerBox : CPView
|
||||
@implementation _CPDatePickerBox : CPView
|
||||
{
|
||||
CPDatePicker _datePicker @accessors(property=datePicker);
|
||||
}
|
||||
|
||||
- (id)init
|
||||
{
|
||||
if (self = [super init])
|
||||
{
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)drawRect:(CGRect)aRect
|
||||
{
|
||||
[super drawRect:aRect];
|
||||
@@ -1201,10 +1287,10 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
||||
CGContextSetStrokeColor(context, [_datePicker valueForThemeAttribute:@"border-color" inState:[_datePicker themeState]]);
|
||||
CGContextSetLineWidth(context, [_datePicker valueForThemeAttribute:@"border-width"]);
|
||||
|
||||
CGContextMoveToPoint(context, borderWidth,borderWidth);
|
||||
CGContextAddLineToPoint(context, aRect.size.width - borderWidth,borderWidth);
|
||||
CGContextAddLineToPoint(context, aRect.size.width - borderWidth,aRect.size.height - borderWidth);
|
||||
CGContextAddLineToPoint(context, borderWidth,aRect.size.height - borderWidth);
|
||||
CGContextMoveToPoint(context, borderWidth, borderWidth);
|
||||
CGContextAddLineToPoint(context, aRect.size.width - borderWidth, borderWidth);
|
||||
CGContextAddLineToPoint(context, aRect.size.width - borderWidth, aRect.size.height - borderWidth);
|
||||
CGContextAddLineToPoint(context, borderWidth, aRect.size.height - borderWidth);
|
||||
CGContextAddLineToPoint(context, borderWidth,borderWidth);
|
||||
|
||||
CGContextStrokePath(context);
|
||||
@@ -1223,5 +1309,4 @@ var CPShortWeekDayNameArrayEn = [@"Mo", @"Tu", @"We", @"Th", @"Fr", @"Sa", @"Su"
|
||||
[self setBackgroundColor:[CPColor clearColor]];
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
@import "CPImageView.j"
|
||||
@import "CALayer.j"
|
||||
|
||||
|
||||
@class _CPCibCustomResource
|
||||
@class CPDatePicker
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
@typedef CPDragOperation
|
||||
CPDragOperationNone = 0;
|
||||
CPDragOperationCopy = 1 << 1;
|
||||
CPDragOperationLink = 1 << 1;
|
||||
|
||||
@@ -31,9 +31,15 @@
|
||||
@import "CPText.j"
|
||||
|
||||
@class CPTextField
|
||||
@class CPWindow
|
||||
@class CPGraphicsContext
|
||||
|
||||
@global CPApp
|
||||
|
||||
@typedef DOMEvent
|
||||
@typedef CPEventType
|
||||
|
||||
|
||||
var _CPEventPeriodicEventPeriod = 0,
|
||||
_CPEventPeriodicEventTimer = nil,
|
||||
_CPEventUpperCaseRegex = new RegExp("[A-Z]"),
|
||||
@@ -68,6 +74,9 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
float _deltaX;
|
||||
float _deltaY;
|
||||
float _deltaZ;
|
||||
float _scrollingDeltaX;
|
||||
float _scrollingDeltaY;
|
||||
BOOL _hasPreciseScrollingDeltas;
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
BOOL _suppressCappuccinoCut;
|
||||
@@ -163,7 +172,9 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
|
||||
// Make sure these are 0 rather than nil.
|
||||
_deltaX = 0;
|
||||
_scrollingDeltaX = 0;
|
||||
_deltaY = 0;
|
||||
_scrollingDeltaY = 0;
|
||||
_deltaZ = 0;
|
||||
}
|
||||
|
||||
@@ -417,6 +428,31 @@ var _CPEventPeriodicEventPeriod = 0,
|
||||
return _deltaZ;
|
||||
}
|
||||
|
||||
- (BOOL)hasPreciseScrollingDeltas
|
||||
{
|
||||
return !!_hasPreciseScrollingDeltas;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the change in points on the x-axis for a mouse movement, unless hasPreciseScrollingDeltas is NO,
|
||||
in which case the change is measured in number of "lines" or "rows" and needs to be multiplied as appropriate
|
||||
to get change in pixels.
|
||||
*/
|
||||
- (float)scrollingDeltaX
|
||||
{
|
||||
return _scrollingDeltaX;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the change in points on the y-axis for a mouse movement, unless hasPreciseScrollingDeltas is NO,
|
||||
in which case the change is measured in number of "lines" or "columns" and needs to be multiplied as appropriate
|
||||
to get change in pixels.
|
||||
*/
|
||||
- (float)scrollingDeltaY
|
||||
{
|
||||
return _scrollingDeltaY;
|
||||
}
|
||||
|
||||
- (BOOL)_triggersKeyEquivalent:(CPString)aKeyEquivalent withModifierMask:aKeyEquivalentModifierMask
|
||||
{
|
||||
if (!aKeyEquivalent)
|
||||
|
||||
@@ -174,20 +174,20 @@ following:
|
||||
return _CPFontSystemFontSize;
|
||||
}
|
||||
|
||||
+ (float)systemFontSizeForControlSize:(CPControlSize)aSize
|
||||
+ (CPFont)systemFontForControlSize:(CPControlSize)aSize
|
||||
{
|
||||
// TODO These sizes should be themable or made less arbitrary in some other way.
|
||||
switch (aSize)
|
||||
{
|
||||
case CPSmallControlSize:
|
||||
return _CPFontSystemFontSize - 1;
|
||||
return [self systemFontOfSize:_CPFontSystemFontSize - 1];
|
||||
|
||||
case CPMiniControlSize:
|
||||
return _CPFontSystemFontSize - 2;
|
||||
return [self systemFontOfSize:_CPFontSystemFontSize - 2];
|
||||
|
||||
case CPRegularControlSize:
|
||||
default:
|
||||
return _CPFontSystemFontSize;
|
||||
return [self systemFontOfSize:_CPFontSystemFontSize];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,20 @@
|
||||
@import "CGGeometry.j"
|
||||
@import "CPCompatibility.j"
|
||||
|
||||
|
||||
@protocol CPImageDelegate <CPObject>
|
||||
|
||||
@optional
|
||||
- (void)imageDidLoad:(CPImage)anImage;
|
||||
- (void)imageDidError:(CPImage)anImage;
|
||||
- (void)imageDidAbort:(CPImage)anImage;
|
||||
|
||||
@end
|
||||
|
||||
var CPImageDelegate_imageDidLoad_ = 1 << 1,
|
||||
CPImageDelegate_imageDidError_ = 1 << 2,
|
||||
CPImageDelegate_imageDidAbort_ = 1 << 3;
|
||||
|
||||
CPImageLoadStatusInitialized = 0;
|
||||
CPImageLoadStatusLoading = 1;
|
||||
CPImageLoadStatusCompleted = 2;
|
||||
@@ -119,14 +133,15 @@ function CPAppKitImage(aFilename, aSize)
|
||||
*/
|
||||
@implementation CPImage : CPObject
|
||||
{
|
||||
CGSize _size;
|
||||
CPString _filename;
|
||||
CPString _name;
|
||||
CGSize _size;
|
||||
CPString _filename;
|
||||
CPString _name;
|
||||
|
||||
id _delegate;
|
||||
unsigned _loadStatus;
|
||||
id <CPImageDelegate> _delegate;
|
||||
unsigned _loadStatus;
|
||||
unsigned _implementedDelegateMethods;
|
||||
|
||||
Image _image;
|
||||
Image _image;
|
||||
}
|
||||
|
||||
- (id)init
|
||||
@@ -319,9 +334,22 @@ function CPAppKitImage(aFilename, aSize)
|
||||
Sets the receiver's delegate.
|
||||
@param the delegate
|
||||
*/
|
||||
- (void)setDelegate:(id)aDelegate
|
||||
- (void)setDelegate:(id <CPImageDelegate>)aDelegate
|
||||
{
|
||||
if (_delegate === aDelegate)
|
||||
return;
|
||||
|
||||
_delegate = aDelegate;
|
||||
_implementedDelegateMethods = 0;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(imageDidLoad:)])
|
||||
_implementedDelegateMethods |= CPImageDelegate_imageDidLoad_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(imageDidError:)])
|
||||
_implementedDelegateMethods |= CPImageDelegate_imageDidError_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(imageDidAbort:)])
|
||||
_implementedDelegateMethods |= CPImageDelegate_imageDidAbort_;
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -457,7 +485,7 @@ function CPAppKitImage(aFilename, aSize)
|
||||
postNotificationName:CPImageDidLoadNotification
|
||||
object:self];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(imageDidLoad:)])
|
||||
if (_implementedDelegateMethods & CPImageDelegate_imageDidLoad_)
|
||||
[_delegate imageDidLoad:self];
|
||||
}
|
||||
|
||||
@@ -466,7 +494,7 @@ function CPAppKitImage(aFilename, aSize)
|
||||
{
|
||||
_loadStatus = CPImageLoadStatusReadError;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(imageDidError:)])
|
||||
if (_implementedDelegateMethods & CPImageDelegate_imageDidError_)
|
||||
[_delegate imageDidError:self];
|
||||
}
|
||||
|
||||
@@ -475,7 +503,7 @@ function CPAppKitImage(aFilename, aSize)
|
||||
{
|
||||
_loadStatus = CPImageLoadStatusCancelled;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(imageDidAbort:)])
|
||||
if (_implementedDelegateMethods & CPImageDelegate_imageDidAbort_)
|
||||
[_delegate imageDidAbort:self];
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
@global CPImagesPboardType
|
||||
@global appkit_tag_dom_elements
|
||||
|
||||
@typedef CPImageAlignment
|
||||
CPImageAlignCenter = 0;
|
||||
CPImageAlignTop = 1;
|
||||
CPImageAlignTopLeft = 2;
|
||||
@@ -178,6 +179,7 @@ var CPImageViewEmptyPlaceholderImage = nil;
|
||||
|
||||
- (void)imageDidLoad:(CPNotification)aNotification
|
||||
{
|
||||
[[CPNotificationCenter defaultCenter] removeObserver:self name:CPImageDidLoadNotification object:[self objectValue]];
|
||||
[self hideOrDisplayContents];
|
||||
|
||||
[self setNeedsLayout];
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
var exposedBindingsMap = @{},
|
||||
bindingsMap = @{};
|
||||
|
||||
@typedef CPBindingOperationKind
|
||||
var CPBindingOperationAnd = 0,
|
||||
CPBindingOperationOr = 1;
|
||||
|
||||
@@ -70,6 +71,20 @@ var CPBindingOperationAnd = 0,
|
||||
return [[bindingsMap objectForKey:[anObject UID]] objectForKey:aBinding];
|
||||
}
|
||||
|
||||
+ (void)_reverseSetValueFromExclusiveBinderForObject:(id)anObject
|
||||
{
|
||||
var bindersByBindingName = [bindingsMap objectForKey:[anObject UID]];
|
||||
|
||||
[bindersByBindingName enumerateKeysAndObjectsUsingBlock:function(binding, binder, stop)
|
||||
{
|
||||
if ([binder isKindOfClass:[self class]])
|
||||
{
|
||||
[binder reverseSetValueFor:binding];
|
||||
stop(YES);
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
+ (CPDictionary)infoForBinding:(CPString)aBinding forObject:(id)anObject
|
||||
{
|
||||
var theBinding = [self getBinding:aBinding forObject:anObject];
|
||||
@@ -116,7 +131,7 @@ var CPBindingOperationAnd = 0,
|
||||
count = allKeys.length;
|
||||
|
||||
while (count--)
|
||||
[anObject unbind:[bindings objectForKey:allKeys[count]]];
|
||||
[anObject unbind:allKeys[count]];
|
||||
|
||||
[bindingsMap removeObjectForKey:[anObject UID]];
|
||||
}
|
||||
@@ -142,7 +157,7 @@ var CPBindingOperationAnd = 0,
|
||||
|
||||
[self _updatePlaceholdersWithOptions:options forBinding:aName];
|
||||
|
||||
[aDestination addObserver:self forKeyPath:aKeyPath options:CPKeyValueObservingOptionNew context:aBinding];
|
||||
[aDestination addObserver:self forKeyPath:aKeyPath options:0 context:aBinding];
|
||||
|
||||
var bindings = [bindingsMap objectForKey:[_source UID]];
|
||||
|
||||
@@ -159,6 +174,24 @@ var CPBindingOperationAnd = 0,
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (BOOL)isBindingAllowed:(CPString)aBinding forObject:(id)anObject
|
||||
{
|
||||
if ([[anObject class] isBindingExclusive:aBinding])
|
||||
{
|
||||
var bindingsForObject = [bindingsMap objectForKey:[anObject UID]],
|
||||
allBindings = [bindingsForObject allKeys],
|
||||
count = [allBindings count];
|
||||
|
||||
while(count--)
|
||||
{
|
||||
if ([[anObject class] isBindingExclusive:allBindings[count]])
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)raiseIfNotApplicable:(id)aValue forKeyPath:(CPString)keyPath options:(CPDictionary)options
|
||||
{
|
||||
if (aValue === CPNotApplicableMarker && [options objectForKey:CPRaisesForNotApplicableKeysBindingOption])
|
||||
@@ -387,6 +420,11 @@ var CPBindingOperationAnd = 0,
|
||||
return [CPBinder class];
|
||||
}
|
||||
|
||||
+ (BOOL)isBindingExclusive:(CPString)aBinding
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (CPArray)exposedBindings
|
||||
{
|
||||
var exposedBindings = [],
|
||||
@@ -415,6 +453,11 @@ var CPBindingOperationAnd = 0,
|
||||
if (!anObject || !aKeyPath)
|
||||
return CPLog.error("Invalid object or path on " + self + " for " + aBinding);
|
||||
|
||||
if (![CPBinder isBindingAllowed:aBinding forObject:self])
|
||||
{
|
||||
CPLog.warn([self description] + " : cannot bind " + aBinding + " because another binding with the same functionality is already in use.");
|
||||
return;
|
||||
}
|
||||
//if (![[self exposedBindings] containsObject:aBinding])
|
||||
// CPLog.warn("No binding exposed on " + self + " for " + aBinding);
|
||||
|
||||
|
||||
@@ -25,11 +25,13 @@
|
||||
|
||||
@global CPApp
|
||||
|
||||
@typedef CPTickMarkPosition
|
||||
CPTickMarkBelow = 0;
|
||||
CPTickMarkAbove = 1;
|
||||
CPTickMarkLeft = CPTickMarkAbove;
|
||||
CPTickMarkRight = CPTickMarkBelow;
|
||||
|
||||
@typedef CPLevelIndicatorStyle
|
||||
CPRelevancyLevelIndicatorStyle = 0;
|
||||
CPContinuousCapacityLevelIndicatorStyle = 1;
|
||||
CPDiscreteCapacityLevelIndicatorStyle = 2;
|
||||
@@ -105,10 +107,21 @@ CPRatingLevelIndicatorStyle = 3;
|
||||
var filledColor = [self valueForThemeAttribute:@"color-normal"],
|
||||
value = [self doubleValue];
|
||||
|
||||
if (value <= _criticalValue)
|
||||
filledColor = [self valueForThemeAttribute:@"color-critical"];
|
||||
else if (value <= _warningValue)
|
||||
filledColor = [self valueForThemeAttribute:@"color-warning"];
|
||||
if (_warningValue < _criticalValue)
|
||||
{
|
||||
if (value >= _criticalValue)
|
||||
filledColor = [self valueForThemeAttribute:@"color-critical"];
|
||||
else if (value >= _warningValue)
|
||||
filledColor = [self valueForThemeAttribute:@"color-warning"];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (value <= _criticalValue)
|
||||
filledColor = [self valueForThemeAttribute:@"color-critical"];
|
||||
else if (value <= _warningValue)
|
||||
filledColor = [self valueForThemeAttribute:@"color-warning"];
|
||||
}
|
||||
|
||||
|
||||
for (var i = 0; i < segmentCount; i++)
|
||||
{
|
||||
|
||||
@@ -30,6 +30,17 @@
|
||||
|
||||
@global CPApp
|
||||
|
||||
@protocol CPMenuDelegate <CPObject>
|
||||
|
||||
@optional
|
||||
- (void)menuWillOpen:(CPMenu)aMenu;
|
||||
- (void)menuDidClose:(CPMenu)aMenu;
|
||||
|
||||
@end
|
||||
|
||||
var CPMenuDelegate_menuWillOpen_ = 1 << 1,
|
||||
CPMenuDelegate_menuDidClose_ = 1 << 2;
|
||||
|
||||
CPMenuDidAddItemNotification = @"CPMenuDidAddItemNotification";
|
||||
CPMenuDidChangeItemNotification = @"CPMenuDidChangeItemNotification";
|
||||
CPMenuDidRemoveItemNotification = @"CPMenuDidRemoveItemNotification";
|
||||
@@ -50,26 +61,27 @@ var _CPMenuBarVisible = NO,
|
||||
*/
|
||||
@implementation CPMenu : CPObject
|
||||
{
|
||||
CPMenu _supermenu;
|
||||
CPMenu _supermenu;
|
||||
|
||||
CPString _title;
|
||||
CPString _name;
|
||||
CPString _title;
|
||||
CPString _name;
|
||||
|
||||
CPFont _font;
|
||||
CPFont _font;
|
||||
|
||||
float _minimumWidth;
|
||||
float _minimumWidth;
|
||||
|
||||
CPMutableArray _items;
|
||||
CPMutableArray _items;
|
||||
|
||||
BOOL _autoenablesItems;
|
||||
BOOL _showsStateColumn;
|
||||
BOOL _autoenablesItems;
|
||||
BOOL _showsStateColumn;
|
||||
|
||||
id _delegate;
|
||||
id <CPMenuDelegate> _delegate;
|
||||
unsigned _implementedDelegateMethods;
|
||||
|
||||
int _highlightedIndex;
|
||||
_CPMenuWindow _menuWindow;
|
||||
int _highlightedIndex;
|
||||
_CPMenuWindow _menuWindow;
|
||||
|
||||
CPEvent _lastCloseEvent;
|
||||
CPEvent _lastCloseEvent;
|
||||
}
|
||||
|
||||
// Managing the Menu Bar
|
||||
@@ -639,6 +651,7 @@ var _CPMenuBarVisible = NO,
|
||||
if (binder)
|
||||
{
|
||||
[binder setValueFor:CPEnabledBinding];
|
||||
[[_menuWindow _menuView] tile];
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -941,9 +954,19 @@ var _CPMenuBarVisible = NO,
|
||||
|
||||
// Managing the Delegate
|
||||
|
||||
- (void)setDelegate:(id)aDelegate
|
||||
- (void)setDelegate:(id <CPMenuDelegate>)aDelegate
|
||||
{
|
||||
if (_delegate === aDelegate)
|
||||
return;
|
||||
|
||||
_delegate = aDelegate;
|
||||
_implementedDelegateMethods = 0;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(menuWillOpen:)])
|
||||
_implementedDelegateMethods |= CPMenuDelegate_menuWillOpen_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(menuDidClose:)])
|
||||
_implementedDelegateMethods |= CPMenuDelegate_menuDidClose_;
|
||||
}
|
||||
|
||||
- (id)delegate
|
||||
@@ -953,10 +976,7 @@ var _CPMenuBarVisible = NO,
|
||||
|
||||
- (void)_menuWillOpen
|
||||
{
|
||||
var delegate = [self delegate];
|
||||
|
||||
if ([delegate respondsToSelector:@selector(menuWillOpen:)])
|
||||
[delegate menuWillOpen:self];
|
||||
[self _sendDelegateMenuWillOpen];
|
||||
}
|
||||
|
||||
- (void)_menuDidClose
|
||||
@@ -965,10 +985,7 @@ var _CPMenuBarVisible = NO,
|
||||
// when a click on the button itself caused the menu to close.
|
||||
_lastCloseEvent = [CPApp currentEvent];
|
||||
|
||||
var delegate = [self delegate];
|
||||
|
||||
if ([delegate respondsToSelector:@selector(menuDidClose:)])
|
||||
[delegate menuDidClose:self];
|
||||
[self _sendDelegateMenuDidClose];
|
||||
}
|
||||
|
||||
// Handling Tracking
|
||||
@@ -1132,6 +1149,36 @@ var _CPMenuBarVisible = NO,
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation CPMenu (CPMenuDelegate)
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call delegate menuWillOpen
|
||||
*/
|
||||
- (void)_sendDelegateMenuWillOpen
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPMenuDelegate_menuWillOpen_))
|
||||
return;
|
||||
|
||||
[_delegate menuWillOpen:self];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call delegate menuDidClose
|
||||
*/
|
||||
- (void)_sendDelegateMenuDidClose
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPMenuDelegate_menuDidClose_))
|
||||
return;
|
||||
|
||||
[_delegate menuDidClose:self];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation CPMenu (CPKeyValueCoding)
|
||||
|
||||
- (CPUInteger)countOfItems
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
@import "_CPMenuManager.j"
|
||||
|
||||
@class _CPMenuView
|
||||
@class CPMenu
|
||||
|
||||
@global CPMenuDidAddItemNotification
|
||||
@global CPMenuDidChangeItemNotification
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
@import "CPWindow.j"
|
||||
@import "_CPMenuManager.j"
|
||||
|
||||
@class _CPMenuView
|
||||
|
||||
var _CPMenuWindowPool = [],
|
||||
_CPMenuWindowPoolCapacity = 5,
|
||||
|
||||
@@ -410,7 +412,7 @@ _CPMenuWindowAttachedMenuBackgroundStyle = 2;
|
||||
{
|
||||
// Don't return indexes of items that aren't visible.
|
||||
if (!CGRectContainsPoint([_menuClipView bounds], [_menuClipView convertPoint:aPoint fromView:nil]))
|
||||
return NO;
|
||||
return CPNotFound;
|
||||
|
||||
return [_menuView itemIndexAtPoint:[_menuView convertPoint:aPoint fromView:nil]];
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
@class _CPMenuBarWindow
|
||||
@class _CPMenuView
|
||||
@class CPMenuItem
|
||||
|
||||
@implementation _CPMenuItemMenuBarView : CPView
|
||||
{
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
@import "CPImageView.j"
|
||||
@import "_CPImageAndTextView.j"
|
||||
|
||||
@class CPMenuItem
|
||||
|
||||
|
||||
@implementation _CPMenuItemStandardView : CPView
|
||||
{
|
||||
CPMenuItem _menuItem @accessors(property=menuItem);
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
@import "_CPMenuItemStandardView.j"
|
||||
@import "_CPMenuItemMenuBarView.j"
|
||||
|
||||
@class CPMenuItem
|
||||
@global CPApp
|
||||
|
||||
/*
|
||||
|
||||
@@ -459,13 +459,13 @@ var CPObjectControllerContentKey = @"CPObjectControllerCo
|
||||
|
||||
- (BOOL)isEqual:(id)anObject
|
||||
{
|
||||
if ([anObject class] === [self class])
|
||||
{
|
||||
if (anObject._observer === _observer && [anObject._keyPath isEqual:_keyPath] && [anObject._object isEqual:_object])
|
||||
return YES;
|
||||
}
|
||||
if (self === anObject)
|
||||
return YES;
|
||||
|
||||
return NO;
|
||||
if (!anObject || [anObject class] !== [self class] || anObject._observer !== _observer || anObject._keyPath !== _keyPath || anObject._object !== _object)
|
||||
return NO;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObject change:(CPDictionary)change context:(id)context
|
||||
@@ -808,15 +808,20 @@ var CPObjectControllerContentKey = @"CPObjectControllerCo
|
||||
|
||||
- (void)removeObserver:(id)anObject forKeyPath:(CPString)aKeyPath
|
||||
{
|
||||
var proxy = [[_CPObservationProxy alloc] initWithKeyPath:aKeyPath observer:anObject object:self],
|
||||
index = [_observationProxies indexOfObject:proxy];
|
||||
[_observationProxies enumerateObjectsUsingBlock:function(aProxy, idx, stop)
|
||||
{
|
||||
if (aProxy._object === self && aProxy._keyPath == aKeyPath && aProxy._observer === anObject)
|
||||
{
|
||||
var observedObjects = _observedObjectsByKeyPath[aKeyPath];
|
||||
|
||||
var observedObjects = _observedObjectsByKeyPath[aKeyPath];
|
||||
[observedObjects removeObserver:[_observationProxies objectAtIndex:index] forKeyPath:aKeyPath];
|
||||
[observedObjects removeObserver:aProxy forKeyPath:aKeyPath];
|
||||
[_observationProxies removeObjectAtIndex:idx];
|
||||
|
||||
[_observationProxies removeObjectAtIndex:index];
|
||||
_observedObjectsByKeyPath[aKeyPath] = nil;
|
||||
|
||||
_observedObjectsByKeyPath[aKeyPath] = nil;
|
||||
stop(YES);
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -52,7 +52,6 @@ var CPOutlineViewDataSource_outlineView_objectValue_forTableColumn_byItem_
|
||||
CPOutlineViewDataSource_outlineView_sortDescriptorsDidChange_ = 1 << 11;
|
||||
|
||||
var CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_ = 1 << 1,
|
||||
CPOutlineViewDelegate_outlineView_viewForTableColumn_item_ = 1 << 26,
|
||||
CPOutlineViewDelegate_outlineView_didClickTableColumn_ = 1 << 2,
|
||||
CPOutlineViewDelegate_outlineView_didDragTableColumn_ = 1 << 3,
|
||||
CPOutlineViewDelegate_outlineView_heightOfRowByItem_ = 1 << 4,
|
||||
@@ -75,8 +74,10 @@ var CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_
|
||||
CPOutlineViewDelegate_outlineView_typeSelectStringForTableColumn_item_ = 1 << 21,
|
||||
CPOutlineViewDelegate_outlineView_willDisplayOutlineView_forTableColumn_item_ = 1 << 22,
|
||||
CPOutlineViewDelegate_outlineView_willDisplayView_forTableColumn_item_ = 1 << 23,
|
||||
CPOutlineViewDelegate_selectionShouldChangeInOutlineView_ = 1 << 24,
|
||||
CPOutlineViewDelegate_outlineView_menuForTableColumn_item_ = 1 << 25;
|
||||
CPOutlineViewDelegate_outlineView_willRemoveView_forTableColumn_item_ = 1 << 24,
|
||||
CPOutlineViewDelegate_selectionShouldChangeInOutlineView_ = 1 << 25,
|
||||
CPOutlineViewDelegate_outlineView_menuForTableColumn_item_ = 1 << 26,
|
||||
CPOutlineViewDelegate_outlineView_viewForTableColumn_item_ = 1 << 27;
|
||||
|
||||
CPOutlineViewDropOnItemIndex = -1;
|
||||
|
||||
@@ -88,6 +89,58 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
|
||||
|
||||
#define SHOULD_SELECT_ITEM(anOutlineView, anItem) (!((anOutlineView)._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_shouldSelectItem_) || [(anOutlineView)._outlineViewDelegate outlineView:(anOutlineView) shouldSelectItem:(anItem)])
|
||||
|
||||
|
||||
@protocol CPOutlineViewDelegate <CPObject>
|
||||
|
||||
@optional
|
||||
- (BOOL)outlineView:(CPOutlineView)anOutlineView isGroupItem:(id)anItem;
|
||||
- (BOOL)outlineView:(CPOutlineView)anOutlineView shouldCollapseItem:(id)anItem;
|
||||
- (BOOL)outlineView:(CPOutlineView)anOutlineView shouldEditTableColumn:(CPTableColumn)aTableColumn item:(id)anItem;
|
||||
- (BOOL)outlineView:(CPOutlineView)anOutlineView shouldExpandItem:(id)anItem;
|
||||
- (BOOL)outlineView:(CPOutlineView)anOutlineView shouldReorderColumn:(CPInteger)columnIndex toColumn:(CPInteger)newColumnIndex;
|
||||
- (BOOL)outlineView:(CPOutlineView)anOutlineView shouldSelectItem:(id)anItem;
|
||||
- (BOOL)outlineView:(CPOutlineView)anOutlineView shouldSelectTableColumn:(CPTableColumn)aTableColumn;
|
||||
- (BOOL)outlineView:(CPOutlineView)anOutlineView shouldShowOutlineDisclosureControlForItem:(id)anItem;
|
||||
- (BOOL)outlineView:(CPOutlineView)anOutlineView shouldShowViewExpansionForTableColumn:(CPTableColumn)aTableColumn item:(id)anItem;
|
||||
- (BOOL)outlineView:(CPOutlineView)anOutlineView shouldTrackView:(CPView)aView forTableColumn:(CPTableColumn)aTableColumn item:(id)anItem;
|
||||
- (BOOL)outlineView:(CPOutlineView)anOutlineView shouldTypeSelectForEvent:(CPEvent)anEvent withCurrentSearchString:(CPString)searchString;
|
||||
- (BOOL)selectionShouldChangeInOutlineView:(CPOutlineView)anOutlineView;
|
||||
- (CPIndexSet)outlineView:(CPOutlineView)anOutlineView selectionIndexesForProposedSelection:(CPIndexSet)proposedSelectionIndexes;
|
||||
- (CPMenu)outlineView:(CPOutlineView)anOutlineView menuForTableColumn:(CPTableColumn)aTableColumn item:(id)anItem;
|
||||
- (CPString)outlineView:(CPOutlineView)anOutlineView toolTipForView:(CPView)aView rect:(CGRect)aRect tableColumn:(CPTableColumn)aTableColumn item:(id)anItem mouseLocation:(CGPoint)mouseLocation;
|
||||
- (CPString)outlineView:(CPOutlineView)anOutlineView typeSelectStringForTableColumn:(CPTableColumn)aTableColumn item:(id)anItem;
|
||||
- (CPView)outlineView:(CPOutlineView)anOutlineView dataViewForTableColumn:(CPTableColumn)aTableColumn item:(id)anItem;
|
||||
- (CPView)outlineView:(CPOutlineView)anOutlineView viewForTableColumn:(CPTableColumn)aTableColumn item:(id)anItem;
|
||||
- (float)outlineView:(CPOutlineView)anOutlineView heightOfRowByItem:(id)anItem;
|
||||
- (float)outlineView:(CPOutlineView)anOutlineView sizeToFitWidthOfColumn:(CPTableColumn)aTableColumn;
|
||||
- (id)outlineView:(CPOutlineView)anOutlineView nextTypeSelectMatchFromItem:(id)startItem toItem:(id)endItem forString:(CPString)searchString;
|
||||
- (void)outlineView:(CPOutlineView)anOutlineView didClickTableColumn:(CPTableColumn)aTableColumn;
|
||||
- (void)outlineView:(CPOutlineView)anOutlineView didDragTableColumn:(CPTableColumn)aTableColumn;
|
||||
- (void)outlineView:(CPOutlineView)anOutlineView mouseDownInHeaderOfTableColumn:(CPTableColumn)aTableColumn;
|
||||
- (void)outlineView:(CPOutlineView)anOutlineView willDisplayOutlineView:(CPView)aView forTableColumn:(CPTableColumn)aTableColumn item:(id)anItem;
|
||||
- (void)outlineView:(CPOutlineView)anOutlineView willDisplayView:(CPView)aView forTableColumn:(CPTableColumn)aTableColumn item:(id)anItem;
|
||||
- (void)outlineView:(CPOutlineView)anOutlineView willRemoveView:(CPView)aView forTableColumn:(CPTableColumn)aTableColumn item:(id)anItem;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@protocol CPOutlineViewDataSource <CPObject>
|
||||
|
||||
@optional
|
||||
- (BOOL)outlineView:(CPOutlineView)anOutlineView acceptDrop:(id /*<CPDraggingInfo>*/)info item:(id)anItem childIndex:(CPInteger)anIndex;
|
||||
- (BOOL)outlineView:(CPOutlineView)anOutlineView shouldDeferDisplayingChildrenOfItem:(id)anItem;
|
||||
- (BOOL)outlineView:(CPOutlineView)anOutlineView writeItems:(CPArray)items toPasteboard:(CPPasteboard)pboard;
|
||||
- (CPArray)outlineView:(CPOutlineView)anOutlineView namesOfPromisedFilesDroppedAtDestination:(CPURL)dropDestination forDraggedItems:(CPArray)items;
|
||||
- (CPDragOperation)outlineView:(CPOutlineView)anOutlineView validateDrop:(id /*<CPDraggingInfo>*/)info proposedItem:(id)anItem proposedChildIndex:(CPInteger)anIndex;
|
||||
- (CPDragOperation)outlineView:(CPOutlineView)anOutlineView validateDrop:(id /*<CPDraggingInfo>*/)info proposedRow:(int)theRow proposedDropOperation:(CPTableViewDropOperation)theOperation;
|
||||
- (id)outlineView:(CPOutlineView)anOutlineView itemForPersistentObject:(id)anObject;
|
||||
- (id)outlineView:(CPOutlineView)anOutlineView objectValueforTableColumn:(CPTableColumn)aTableColumn byItem:(id)anItem;
|
||||
- (id)outlineView:(CPOutlineView)anOutlineView persistentObjectForItem:(id)anItem;
|
||||
- (void)outlineView:(CPOutlineView)anOutlineView setObjectValue:(id)anObject forTableColumn:(CPTableColumn)aTableColumn byItem:(id)anItem;
|
||||
- (void)outlineView:(CPOutlineView)anOutlineView sortDescriptorsDidChange:(CPArray)oldDescriptors;
|
||||
|
||||
@end
|
||||
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@class CPOutlineView
|
||||
@@ -105,34 +158,37 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
|
||||
*/
|
||||
@implementation CPOutlineView : CPTableView
|
||||
{
|
||||
id _outlineViewDataSource;
|
||||
id _outlineViewDelegate;
|
||||
CPTableColumn _outlineTableColumn;
|
||||
id <CPOutlineViewDataSource> _outlineViewDataSource;
|
||||
id <CPOutlineViewDelegate> _outlineViewDelegate;
|
||||
CPTableColumn _outlineTableColumn;
|
||||
|
||||
float _indentationPerLevel;
|
||||
BOOL _indentationMarkerFollowsDataView;
|
||||
float _indentationPerLevel;
|
||||
BOOL _indentationMarkerFollowsDataView;
|
||||
|
||||
CPInteger _implementedOutlineViewDataSourceMethods;
|
||||
CPInteger _implementedOutlineViewDelegateMethods;
|
||||
CPInteger _implementedOutlineViewDataSourceMethods;
|
||||
CPInteger _implementedOutlineViewDelegateMethods;
|
||||
|
||||
Object _rootItemInfo;
|
||||
CPMutableArray _itemsForRows;
|
||||
Object _itemInfosForItems;
|
||||
Object _rootItemInfo;
|
||||
CPMutableArray _itemsForRows;
|
||||
Object _itemInfosForItems;
|
||||
|
||||
CPControl _disclosureControlPrototype;
|
||||
CPArray _disclosureControlsForRows;
|
||||
CPData _disclosureControlData;
|
||||
CPArray _disclosureControlQueue;
|
||||
CPControl _disclosureControlPrototype;
|
||||
CPArray _disclosureControlsForRows;
|
||||
CPData _disclosureControlData;
|
||||
CPArray _disclosureControlQueue;
|
||||
|
||||
BOOL _shouldRetargetItem;
|
||||
id _retargetedItem;
|
||||
BOOL _shouldRetargetItem;
|
||||
id _retargetedItem;
|
||||
|
||||
BOOL _shouldRetargetChildIndex;
|
||||
CPInteger _retargedChildIndex;
|
||||
CPTimer _dragHoverTimer;
|
||||
id _dropItem;
|
||||
BOOL _shouldRetargetChildIndex;
|
||||
CPInteger _retargedChildIndex;
|
||||
CPTimer _dragHoverTimer;
|
||||
id _dropItem;
|
||||
|
||||
BOOL _coalesceSelectionNotificationState;
|
||||
BOOL _coalesceSelectionNotificationState;
|
||||
|
||||
CPArray _pendingItemToClean;
|
||||
CPArray _itemAddedDuringLastLoading;
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)aFrame
|
||||
@@ -218,7 +274,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
|
||||
If you want the drag to begin you should return YES and place the drag data on the pboard.
|
||||
@code - (BOOL)outlineView:(CPOutlineView)outlineView writeItems:(CPArray)items toPasteboard:(CPPasteboard)pboard; @endcode
|
||||
*/
|
||||
- (void)setDataSource:(id)aDataSource
|
||||
- (void)setDataSource:(id <CPOutlineViewDataSource>)aDataSource
|
||||
{
|
||||
if (_outlineViewDataSource === aDataSource)
|
||||
return;
|
||||
@@ -293,7 +349,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
|
||||
if (!anItem)
|
||||
return YES;
|
||||
|
||||
var itemInfo = _itemInfosForItems[[anItem UID]];
|
||||
var itemInfo = [self _itemInfosForItem:anItem];
|
||||
|
||||
if (!itemInfo)
|
||||
return NO;
|
||||
@@ -326,7 +382,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
|
||||
if (!anItem)
|
||||
return YES;
|
||||
|
||||
var itemInfo = _itemInfosForItems[[anItem UID]];
|
||||
var itemInfo = [self _itemInfosForItem:anItem];
|
||||
|
||||
if (!itemInfo)
|
||||
return NO;
|
||||
@@ -334,6 +390,107 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
|
||||
return itemInfo.isExpanded;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the item at a given row index. If no item exists nil is returned.
|
||||
|
||||
@param aRow - The row index you want to find the item at.
|
||||
@return id - The item at a given index.
|
||||
*/
|
||||
- (id)itemAtRow:(CPInteger)aRow
|
||||
{
|
||||
return _itemsForRows[aRow] || nil;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the row of a given item
|
||||
|
||||
@param anItem - The item you want to find the row of.
|
||||
@return int - The row index of a given item.
|
||||
*/
|
||||
- (CPInteger)rowForItem:(id)anItem
|
||||
{
|
||||
if (!anItem)
|
||||
return _rootItemInfo.row;
|
||||
|
||||
var itemInfo = [self _itemInfosForItem:anItem];
|
||||
|
||||
if (!itemInfo)
|
||||
return CPNotFound;
|
||||
|
||||
return itemInfo.row;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the indentation level of a given item. If the item is nil (the top
|
||||
level root item) CPNotFound is returned. Indentation levels are zero
|
||||
based, thus items that are not indented return 0.
|
||||
|
||||
@param anItem - The item you want the indentation level for.
|
||||
@return int - the indentation level of anItem.
|
||||
*/
|
||||
- (CPInteger)levelForItem:(id)anItem
|
||||
{
|
||||
if (!anItem)
|
||||
return _rootItemInfo.level;
|
||||
|
||||
var itemInfo = [self _itemInfosForItem:anItem];
|
||||
|
||||
if (!itemInfo)
|
||||
return CPNotFound;
|
||||
|
||||
return itemInfo.level;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the indentation level for a given row. If the row is invalid
|
||||
CPNotFound is returned. Rows that are not indented return 0.
|
||||
|
||||
@param aRow - the row of the receiver
|
||||
@return int - the indentation level of aRow.
|
||||
*/
|
||||
- (CPInteger)levelForRow:(CPInteger)aRow
|
||||
{
|
||||
var item = [self itemAtRow:aRow];
|
||||
|
||||
if (!item && aRow >= 0)
|
||||
item = [CPObject new];
|
||||
|
||||
return [self levelForItem:item];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Return the itemInfos for the given item.
|
||||
The method returns only itemInfo for displayed items
|
||||
*/
|
||||
- (Object)_itemInfosForItem:(id)anItem
|
||||
{
|
||||
var itemInfo = _itemInfosForItems[[anItem UID]];
|
||||
|
||||
if (!itemInfo || [self _parentIsCollapsed:[self parentForItem:anItem]])
|
||||
return nil;
|
||||
|
||||
return itemInfo;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Return a boolean to know if one parent of the given item is collapsed or not
|
||||
*/
|
||||
- (BOOL)_parentIsCollapsed:(id)anItem
|
||||
{
|
||||
var parentItem = [self parentForItem:anItem],
|
||||
itemInfo = _itemInfosForItems[[anItem UID]];
|
||||
|
||||
if (!itemInfo)
|
||||
return NO;
|
||||
|
||||
if (!itemInfo.isExpanded)
|
||||
return YES;
|
||||
|
||||
return [self _parentIsCollapsed:parentItem];
|
||||
}
|
||||
|
||||
/*!
|
||||
Expands a given item.
|
||||
|
||||
@@ -370,6 +527,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
|
||||
// selection notifications so that exactly one IsChanging and one
|
||||
// DidChange is sent as needed, for the totality of the operation.
|
||||
var isTopLevel = NO;
|
||||
|
||||
if (!_coalesceSelectionNotificationState)
|
||||
{
|
||||
isTopLevel = YES;
|
||||
@@ -389,6 +547,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
|
||||
|
||||
// Shift selection indexes below so that the same items remain selected.
|
||||
var rowCountDelta = [self numberOfRows] - previousRowCount;
|
||||
|
||||
if (rowCountDelta)
|
||||
{
|
||||
var selection = [self selectedRowIndexes],
|
||||
@@ -478,6 +637,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
|
||||
[self _setSelectedRowIndexes:selection]; // _noteSelectionDidChange will be suppressed.
|
||||
}
|
||||
}
|
||||
|
||||
itemInfo.isExpanded = NO;
|
||||
|
||||
[self reloadItem:anItem reloadChildren:YES];
|
||||
@@ -509,42 +669,205 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
|
||||
*/
|
||||
- (void)reloadItem:(id)anItem reloadChildren:(BOOL)shouldReloadChildren
|
||||
{
|
||||
_pendingItemToClean = [];
|
||||
_itemAddedDuringLastLoading = [];
|
||||
|
||||
if (!!shouldReloadChildren || !anItem)
|
||||
_loadItemInfoForItem(self, anItem);
|
||||
[self _loadItemInfoForItem:anItem intermediate:NO];
|
||||
else
|
||||
_reloadItem(self, anItem);
|
||||
[self _reloadItem:anItem];
|
||||
|
||||
[self _cleanPendingItem];
|
||||
|
||||
[super reloadData];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the item at a given row index. If no item exists nil is returned.
|
||||
|
||||
@param aRow - The row index you want to find the item at.
|
||||
@return id - The item at a given index.
|
||||
*/
|
||||
- (id)itemAtRow:(CPInteger)aRow
|
||||
{
|
||||
return _itemsForRows[aRow] || nil;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the row of a given item
|
||||
|
||||
@param anItem - The item you want to find the row of.
|
||||
@return int - The row index of a given item.
|
||||
*/
|
||||
- (CPInteger)rowForItem:(id)anItem
|
||||
- (void)_reloadItem:(id)anItem
|
||||
{
|
||||
if (!anItem)
|
||||
return _rootItemInfo.row;
|
||||
return;
|
||||
|
||||
// Get the existing info if it exists.
|
||||
var itemUID = [anItem UID],
|
||||
itemInfo = _itemInfosForItems[itemUID];
|
||||
|
||||
// If we're not in the tree, then just bail.
|
||||
if (!itemInfo)
|
||||
return [];
|
||||
|
||||
// See if the item itself can be swapped out.
|
||||
var parent = itemInfo.parent,
|
||||
parentItemInfo = parent ? _itemInfosForItems[[parent UID]] : _rootItemInfo,
|
||||
parentChildren = parentItemInfo.children,
|
||||
index = [parentChildren indexOfObjectIdenticalTo:anItem],
|
||||
newItem = [_outlineViewDataSource outlineView:self child:index ofItem:parent];
|
||||
|
||||
if (anItem !== newItem)
|
||||
{
|
||||
_itemInfosForItems[[anItem UID]] = nil;
|
||||
_itemInfosForItems[[newItem UID]] = itemInfo;
|
||||
|
||||
parentChildren[index] = newItem;
|
||||
_itemsForRows[itemInfo.row] = newItem;
|
||||
}
|
||||
|
||||
itemInfo.isExpandable = [_outlineViewDataSource outlineView:self isItemExpandable:newItem];
|
||||
itemInfo.isExpanded = itemInfo.isExpandable && itemInfo.isExpanded;
|
||||
itemInfo.shouldShowOutlineDisclosureControl = [self _sendDelegateShouldShowOutlineDisclosureControlForItem:newItem];
|
||||
}
|
||||
|
||||
- (void)_addPendingItemsFromPreviousItems:(CPArray)previousItems forItemInfo:(Object)itemInfo
|
||||
{
|
||||
if (!itemInfo)
|
||||
return;
|
||||
|
||||
var children = itemInfo.children;
|
||||
|
||||
for (var i = [previousItems count] - 1; i >= 0; i--)
|
||||
{
|
||||
var item = previousItems[i];
|
||||
|
||||
if (![children containsObject:item])
|
||||
[self _addPendingItem:item];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_addPendingItem:(id)anItem
|
||||
{
|
||||
var itemInfo = _itemInfosForItems[[anItem UID]];
|
||||
|
||||
if (!itemInfo)
|
||||
return CPNotFound;
|
||||
return;
|
||||
|
||||
return itemInfo.row;
|
||||
var children = itemInfo.children;
|
||||
|
||||
for (var i = [children count]; i >= 0; i--)
|
||||
{
|
||||
var child = children[i];
|
||||
[self _addPendingItem:child];
|
||||
}
|
||||
|
||||
[_pendingItemToClean addObject:anItem];
|
||||
}
|
||||
|
||||
- (void)_cleanPendingItem
|
||||
{
|
||||
for (var i = [_pendingItemToClean count]; i >= 0; i--)
|
||||
{
|
||||
var item = _pendingItemToClean[i];
|
||||
|
||||
if (![_itemAddedDuringLastLoading containsObject:item])
|
||||
delete _itemInfosForItems[[item UID]];
|
||||
}
|
||||
|
||||
_pendingItemToClean = [];
|
||||
_itemAddedDuringLastLoading = [];
|
||||
}
|
||||
|
||||
- (CPArray)_loadItemInfoForItem:(id)anItem intermediate:(BOOL)isIntermediate
|
||||
{
|
||||
if (!anItem)
|
||||
{
|
||||
var itemInfo = _rootItemInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get the existing info if it exists.
|
||||
var itemUID = [anItem UID],
|
||||
itemInfo = _itemInfosForItems[itemUID];
|
||||
|
||||
// If we're not in the tree, then just bail.
|
||||
if (!itemInfo)
|
||||
return [];
|
||||
|
||||
itemInfo.isExpandable = [_outlineViewDataSource outlineView:self isItemExpandable:anItem];
|
||||
itemInfo.shouldShowOutlineDisclosureControl = [self _sendDelegateShouldShowOutlineDisclosureControlForItem:anItem];
|
||||
|
||||
// If we were previously expanded, but now no longer expandable, "de-expand".
|
||||
// NOTE: we are *not* collapsing, thus no notification is posted.
|
||||
if (!itemInfo.isExpandable && itemInfo.isExpanded)
|
||||
{
|
||||
itemInfo.isExpanded = NO;
|
||||
itemInfo.children = [];
|
||||
}
|
||||
}
|
||||
|
||||
// The root item does not count as a descendant.
|
||||
var weight = itemInfo.weight,
|
||||
descendants = anItem ? [anItem] : [];
|
||||
|
||||
[_itemAddedDuringLastLoading addObject:anItem];
|
||||
|
||||
if (itemInfo.isExpanded && [self _sendDataSourceShouldDeferDisplayingChildrenOfItem:anItem])
|
||||
{
|
||||
var index = 0,
|
||||
count = [_outlineViewDataSource outlineView:self numberOfChildrenOfItem:anItem],
|
||||
level = itemInfo.level + 1,
|
||||
previousChildren = itemInfo.children;
|
||||
|
||||
itemInfo.children = [];
|
||||
|
||||
for (; index < count; ++index)
|
||||
{
|
||||
var childItem = [_outlineViewDataSource outlineView:self child:index ofItem:anItem],
|
||||
childItemInfo = _itemInfosForItems[[childItem UID]];
|
||||
|
||||
if (!childItemInfo)
|
||||
{
|
||||
childItemInfo = { isExpanded:NO, isExpandable:NO, shouldShowOutlineDisclosureControl:YES, children:[], weight:1 };
|
||||
_itemInfosForItems[[childItem UID]] = childItemInfo;
|
||||
}
|
||||
|
||||
itemInfo.children[index] = childItem;
|
||||
|
||||
var childDescendants = [self _loadItemInfoForItem:childItem intermediate:YES];
|
||||
|
||||
childItemInfo.parent = anItem;
|
||||
childItemInfo.level = level;
|
||||
descendants = descendants.concat(childDescendants);
|
||||
}
|
||||
|
||||
// Here we clean the itemInfos dictionary
|
||||
// Some items could have been removed at this point, we don't need to keep a ref of them anymore
|
||||
[self _addPendingItemsFromPreviousItems:previousChildren forItemInfo:itemInfo];
|
||||
}
|
||||
|
||||
itemInfo.weight = descendants.length;
|
||||
|
||||
if (!isIntermediate)
|
||||
{
|
||||
// row = -1 is the root item, so just go to row 0 since it is ignored.
|
||||
var index = MAX(itemInfo.row, 0);
|
||||
|
||||
descendants.unshift(index, weight);
|
||||
|
||||
_itemsForRows.splice.apply(_itemsForRows, descendants);
|
||||
|
||||
var count = _itemsForRows.length;
|
||||
|
||||
for (; index < count; ++index)
|
||||
_itemInfosForItems[[_itemsForRows[index] UID]].row = index;
|
||||
|
||||
var deltaWeight = itemInfo.weight - weight;
|
||||
|
||||
if (deltaWeight !== 0)
|
||||
{
|
||||
var parent = itemInfo.parent;
|
||||
|
||||
while (parent)
|
||||
{
|
||||
var parentItemInfo = _itemInfosForItems[[parent UID]];
|
||||
|
||||
parentItemInfo.weight += deltaWeight;
|
||||
parent = parentItemInfo.parent;
|
||||
}
|
||||
|
||||
if (anItem)
|
||||
_rootItemInfo.weight += deltaWeight;
|
||||
}
|
||||
}
|
||||
|
||||
return descendants;
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -574,39 +897,6 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
|
||||
return _outlineTableColumn;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the indentation level of a given item. If the item is nil (the top
|
||||
level root item) CPNotFound is returned. Indentation levels are zero
|
||||
based, thus items that are not indented return 0.
|
||||
|
||||
@param anItem - The item you want the indentation level for.
|
||||
@return int - the indentation level of anItem.
|
||||
*/
|
||||
- (CPInteger)levelForItem:(id)anItem
|
||||
{
|
||||
if (!anItem)
|
||||
return _rootItemInfo.level;
|
||||
|
||||
var itemInfo = _itemInfosForItems[[anItem UID]];
|
||||
|
||||
if (!itemInfo)
|
||||
return CPNotFound;
|
||||
|
||||
return itemInfo.level;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the indentation level for a given row. If the row is invalid
|
||||
CPNotFound is returned. Rows that are not indented return 0.
|
||||
|
||||
@param aRow - the row of the receiver
|
||||
@return int - the indentation level of aRow.
|
||||
*/
|
||||
- (CPInteger)levelForRow:(CPInteger)aRow
|
||||
{
|
||||
return [self levelForItem:[self itemAtRow:aRow]];
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the number of pixels to indent an item at each indentation level.
|
||||
|
||||
@@ -717,6 +1007,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
|
||||
- (CGRect)frameOfOutlineDisclosureControlAtRow:(CPInteger)aRow
|
||||
{
|
||||
var theItem = [self itemAtRow:aRow];
|
||||
|
||||
if (![self isExpandable:theItem] || ![self _shouldShowOutlineDisclosureControlForItem:theItem])
|
||||
return CGRectMakeZero();
|
||||
|
||||
@@ -826,7 +1117,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
|
||||
@code - (int)outlineView:(CPOutlineView)outlineView heightOfRowByItem:(id)anItem; @endcode
|
||||
|
||||
*/
|
||||
- (void)setDelegate:(id)aDelegate
|
||||
- (void)setDelegate:(id <CPOutlineViewDelegate>)aDelegate
|
||||
{
|
||||
if (_outlineViewDelegate === aDelegate)
|
||||
return;
|
||||
@@ -912,6 +1203,7 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
|
||||
CPOutlineViewDelegate_outlineView_typeSelectStringForTableColumn_item_ , @selector(outlineView:typeSelectStringForTableColumn:item:),
|
||||
CPOutlineViewDelegate_outlineView_willDisplayOutlineView_forTableColumn_item_ , @selector(outlineView:willDisplayOutlineView:forTableColumn:item:),
|
||||
CPOutlineViewDelegate_outlineView_willDisplayView_forTableColumn_item_ , @selector(outlineView:willDisplayView:forTableColumn:item:),
|
||||
CPOutlineViewDelegate_outlineView_willRemoveView_forTableColumn_item_ , @selector(outlineView:willRemoveView:forTableColumn:item:),
|
||||
CPOutlineViewDelegate_selectionShouldChangeInOutlineView_ , @selector(selectionShouldChangeInOutlineView:),
|
||||
CPOutlineViewDelegate_outlineView_menuForTableColumn_item_ , @selector(outlineView:menuForTableColumn:item:)
|
||||
],
|
||||
@@ -988,17 +1280,6 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
|
||||
CPLog.warn("outlineView:dataViewForTableColumn:item: is deprecated. You should use -outlineView:viewForTableColumn:item: where you can request the view with -makeViewWithIdentifier:owner:");
|
||||
}
|
||||
|
||||
- (BOOL)_sendDelegateDeleteKeyPressed
|
||||
{
|
||||
if ([[self delegate] respondsToSelector: @selector(outlineViewDeleteKeyPressed:)])
|
||||
{
|
||||
[[self delegate] outlineViewDeleteKeyPressed:self];
|
||||
return YES;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the delegate object for the outlineview.
|
||||
*/
|
||||
@@ -1557,6 +1838,33 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
|
||||
[super keyDown:anEvent];
|
||||
}
|
||||
|
||||
- (BOOL)_sendDelegateDeleteKeyPressed
|
||||
{
|
||||
if ([[self delegate] respondsToSelector: @selector(outlineViewDeleteKeyPressed:)])
|
||||
{
|
||||
[[self delegate] outlineViewDeleteKeyPressed:self];
|
||||
return YES;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)_sendDelegateShouldShowOutlineDisclosureControlForItem:(id)anItem
|
||||
{
|
||||
if (!(_implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_shouldShowOutlineDisclosureControlForItem_))
|
||||
return YES;
|
||||
|
||||
return [_outlineViewDelegate outlineView:self shouldShowOutlineDisclosureControlForItem:anItem];
|
||||
}
|
||||
|
||||
- (BOOL)_sendDataSourceShouldDeferDisplayingChildrenOfItem:(id)anItem
|
||||
{
|
||||
if (!(_implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_shouldDeferDisplayingChildrenOfItem_))
|
||||
return YES;
|
||||
|
||||
return [_outlineViewDataSource outlineView:self shouldDeferDisplayingChildrenOfItem:anItem];
|
||||
}
|
||||
|
||||
- (CPView)_sendDelegateViewForTableColumn:(CPTableColumn)aTableColumn row:(CPInteger)aRow
|
||||
{
|
||||
return [_outlineViewDelegate outlineView:self viewForTableColumn:aTableColumn item:[self itemAtRow:aRow]];
|
||||
@@ -1612,152 +1920,6 @@ var CPOutlineViewCoalesceSelectionNotificationStateOff = 0,
|
||||
|
||||
@end
|
||||
|
||||
// FIX ME: We're using with() here because Safari fails if we use anOutlineView._itemInfosForItems or whatever...
|
||||
var _reloadItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anItem)
|
||||
{
|
||||
if (!anItem)
|
||||
return;
|
||||
|
||||
with (anOutlineView)
|
||||
{
|
||||
// Get the existing info if it exists.
|
||||
var itemInfosForItems = _itemInfosForItems,
|
||||
dataSource = _outlineViewDataSource,
|
||||
itemUID = [anItem UID],
|
||||
itemInfo = itemInfosForItems[itemUID];
|
||||
|
||||
// If we're not in the tree, then just bail.
|
||||
if (!itemInfo)
|
||||
return [];
|
||||
|
||||
// See if the item itself can be swapped out.
|
||||
var parent = itemInfo.parent,
|
||||
parentItemInfo = parent ? itemInfosForItems[[parent UID]] : _rootItemInfo,
|
||||
parentChildren = parentItemInfo.children,
|
||||
index = [parentChildren indexOfObjectIdenticalTo:anItem],
|
||||
newItem = [dataSource outlineView:anOutlineView child:index ofItem:parent];
|
||||
|
||||
if (anItem !== newItem)
|
||||
{
|
||||
itemInfosForItems[[anItem UID]] = nil;
|
||||
itemInfosForItems[[newItem UID]] = itemInfo;
|
||||
|
||||
parentChildren[index] = newItem;
|
||||
_itemsForRows[itemInfo.row] = newItem;
|
||||
}
|
||||
|
||||
itemInfo.isExpandable = [dataSource outlineView:anOutlineView isItemExpandable:newItem];
|
||||
itemInfo.isExpanded = itemInfo.isExpandable && itemInfo.isExpanded;
|
||||
itemInfo.shouldShowOutlineDisclosureControl = !(_implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_shouldShowOutlineDisclosureControlForItem_) || [_outlineViewDelegate outlineView:self shouldShowOutlineDisclosureControlForItem:newItem];
|
||||
}
|
||||
};
|
||||
|
||||
// FIX ME: We're using with() here because Safari fails if we use anOutlineView._itemInfosForItems or whatever...
|
||||
var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anItem, /*BOOL*/ isIntermediate)
|
||||
{
|
||||
with (anOutlineView)
|
||||
{
|
||||
var itemInfosForItems = _itemInfosForItems,
|
||||
dataSource = _outlineViewDataSource;
|
||||
|
||||
if (!anItem)
|
||||
var itemInfo = _rootItemInfo;
|
||||
|
||||
else
|
||||
{
|
||||
// Get the existing info if it exists.
|
||||
var itemUID = [anItem UID],
|
||||
itemInfo = itemInfosForItems[itemUID];
|
||||
|
||||
// If we're not in the tree, then just bail.
|
||||
if (!itemInfo)
|
||||
return [];
|
||||
|
||||
itemInfo.isExpandable = [dataSource outlineView:anOutlineView isItemExpandable:anItem];
|
||||
itemInfo.shouldShowOutlineDisclosureControl = !(_implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_shouldShowOutlineDisclosureControlForItem_) || [_outlineViewDelegate outlineView:self shouldShowOutlineDisclosureControlForItem:anItem];
|
||||
|
||||
// If we were previously expanded, but now no longer expandable, "de-expand".
|
||||
// NOTE: we are *not* collapsing, thus no notification is posted.
|
||||
if (!itemInfo.isExpandable && itemInfo.isExpanded)
|
||||
{
|
||||
itemInfo.isExpanded = NO;
|
||||
itemInfo.children = [];
|
||||
}
|
||||
}
|
||||
|
||||
// The root item does not count as a descendant.
|
||||
var weight = itemInfo.weight,
|
||||
descendants = anItem ? [anItem] : [];
|
||||
|
||||
if (itemInfo.isExpanded && (!(_implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_shouldDeferDisplayingChildrenOfItem_) ||
|
||||
![dataSource outlineView:anOutlineView shouldDeferDisplayingChildrenOfItem:anItem]))
|
||||
{
|
||||
var index = 0,
|
||||
count = [dataSource outlineView:anOutlineView numberOfChildrenOfItem:anItem],
|
||||
level = itemInfo.level + 1;
|
||||
|
||||
itemInfo.children = [];
|
||||
|
||||
for (; index < count; ++index)
|
||||
{
|
||||
var childItem = [dataSource outlineView:anOutlineView child:index ofItem:anItem],
|
||||
childItemInfo = itemInfosForItems[[childItem UID]];
|
||||
|
||||
if (!childItemInfo)
|
||||
{
|
||||
childItemInfo = { isExpanded:NO, isExpandable:NO, shouldShowOutlineDisclosureControl:YES, children:[], weight:1 };
|
||||
itemInfosForItems[[childItem UID]] = childItemInfo;
|
||||
}
|
||||
|
||||
itemInfo.children[index] = childItem;
|
||||
|
||||
var childDescendants = _loadItemInfoForItem(anOutlineView, childItem, YES);
|
||||
|
||||
childItemInfo.parent = anItem;
|
||||
childItemInfo.level = level;
|
||||
descendants = descendants.concat(childDescendants);
|
||||
}
|
||||
}
|
||||
|
||||
itemInfo.weight = descendants.length;
|
||||
|
||||
if (!isIntermediate)
|
||||
{
|
||||
// row = -1 is the root item, so just go to row 0 since it is ignored.
|
||||
var index = MAX(itemInfo.row, 0),
|
||||
itemsForRows = _itemsForRows;
|
||||
|
||||
descendants.unshift(index, weight);
|
||||
|
||||
itemsForRows.splice.apply(itemsForRows, descendants);
|
||||
|
||||
var count = itemsForRows.length;
|
||||
|
||||
for (; index < count; ++index)
|
||||
itemInfosForItems[[itemsForRows[index] UID]].row = index;
|
||||
|
||||
var deltaWeight = itemInfo.weight - weight;
|
||||
|
||||
if (deltaWeight !== 0)
|
||||
{
|
||||
var parent = itemInfo.parent;
|
||||
|
||||
while (parent)
|
||||
{
|
||||
var parentItemInfo = itemInfosForItems[[parent UID]];
|
||||
|
||||
parentItemInfo.weight += deltaWeight;
|
||||
parent = parentItemInfo.parent;
|
||||
}
|
||||
|
||||
if (anItem)
|
||||
_rootItemInfo.weight += deltaWeight;
|
||||
}
|
||||
}
|
||||
}//end of with
|
||||
return descendants;
|
||||
};
|
||||
|
||||
@implementation _CPOutlineViewTableViewDataSource : CPObject
|
||||
{
|
||||
CPObject _outlineView;
|
||||
@@ -1938,6 +2100,15 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt
|
||||
}
|
||||
}
|
||||
|
||||
- (void)tableView:(CPTableView)aTableView willRemoveView:(id)aView forTableColumn:(CPTableColumn)aTableColumn row:(CPInteger)aRowIndex
|
||||
{
|
||||
if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_willRemoveView_forTableColumn_item_))
|
||||
{
|
||||
var item = [_outlineView itemAtRow:aRowIndex];
|
||||
[_outlineView._outlineViewDelegate outlineView:_outlineView willRemoveView:aView forTableColumn:aTableColumn item:item];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)tableView:(CPTableView)aTableView isGroupRow:(CPInteger)aRow
|
||||
{
|
||||
if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_isGroupItem_))
|
||||
|
||||
@@ -119,4 +119,24 @@ CPDocModalWindowMask = 1 << 6;
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Overrides
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (void)cancelOperation:(id)sender
|
||||
{
|
||||
if ([[CPApp currentEvent] _couldBeKeyEquivalent] && [self performKeyEquivalent:[CPApp currentEvent]])
|
||||
return;
|
||||
|
||||
[[self firstResponder] tryToPerform:@selector(cancel:) with:self];
|
||||
}
|
||||
|
||||
- (void)cancel:(id)sender
|
||||
{
|
||||
[self performClose:sender];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -26,6 +26,9 @@
|
||||
@import <Foundation/CPDictionary.j>
|
||||
@import <Foundation/CPPropertyListSerialization.j>
|
||||
|
||||
@class CPWebScriptObject
|
||||
|
||||
@typedef DataTransfer
|
||||
|
||||
CPGeneralPboard = @"CPGeneralPboard";
|
||||
CPFontPboard = @"CPFontPboard";
|
||||
@@ -66,7 +69,7 @@ var CPPasteboards = nil,
|
||||
unsigned _changeCount;
|
||||
CPString _stateUID;
|
||||
|
||||
WebScriptObject _nativePasteboard;
|
||||
CPWebScriptObject _nativePasteboard;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -26,8 +26,6 @@
|
||||
@import "CPMenu.j"
|
||||
@import "CPMenuItem.j"
|
||||
|
||||
var VISIBLE_MARGIN = 7.0;
|
||||
|
||||
CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
|
||||
/*!
|
||||
@@ -773,13 +771,6 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
[[self selectedItem] setState:CPOffState];
|
||||
}
|
||||
|
||||
- (void)_reverseSetBinding
|
||||
{
|
||||
[_CPPopUpButtonSelectionBinder reverseSetValueForObject:self];
|
||||
|
||||
[super _reverseSetBinding];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPPopUpButton (BindingSupport)
|
||||
@@ -802,6 +793,20 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
return [super _binderClassForBinding:aBinding];
|
||||
}
|
||||
|
||||
+ (BOOL)isBindingExclusive:(CPString)aBinding
|
||||
{
|
||||
return (aBinding == CPSelectedIndexBinding ||
|
||||
aBinding == CPSelectedTagBinding ||
|
||||
aBinding == CPSelectedValueBinding);
|
||||
}
|
||||
|
||||
- (void)_reverseSetBinding
|
||||
{
|
||||
[_CPPopUpButtonSelectionBinder _reverseSetValueFromExclusiveBinderForObject:self];
|
||||
|
||||
[super _reverseSetBinding];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation _CPPopUpButtonContentBinder : CPBinder
|
||||
@@ -931,30 +936,8 @@ CPPopUpButtonStatePullsDown = CPThemeState("pulls-down");
|
||||
|
||||
@end
|
||||
|
||||
var binderForObject = {};
|
||||
|
||||
@implementation _CPPopUpButtonSelectionBinder : CPBinder
|
||||
{
|
||||
CPString _selectionBinding @accessors;
|
||||
}
|
||||
|
||||
- (id)initWithBinding:(CPString)aBinding name:(CPString)aName to:(id)aDestination keyPath:(CPString)aKeyPath options:(CPDictionary)options from:(id)aSource
|
||||
{
|
||||
self = [super initWithBinding:aBinding name:aName to:aDestination keyPath:aKeyPath options:options from:aSource];
|
||||
|
||||
if (self)
|
||||
{
|
||||
binderForObject[[aSource UID]] = self;
|
||||
_selectionBinding = aName;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (void)reverseSetValueForObject:(id)aSource
|
||||
{
|
||||
var binder = binderForObject[[aSource UID]];
|
||||
[binder reverseSetValueFor:[binder _selectionBinding]];
|
||||
}
|
||||
|
||||
- (void)setPlaceholderValue:(id)aValue withMarker:(CPString)aMarker forBinding:(CPString)aBinding
|
||||
|
||||
@@ -28,8 +28,19 @@
|
||||
@import "CPImageView.j"
|
||||
@import "CPResponder.j"
|
||||
@import "CPView.j"
|
||||
@import "CPViewController.j"
|
||||
@import "_CPPopoverWindow.j"
|
||||
|
||||
@protocol CPPopoverDelegate <CPObject>
|
||||
|
||||
@optional
|
||||
- (BOOL)popoverShouldClose:(CPPopover)aPopover;
|
||||
- (void)popoverWillClose:(CPPopover)aPopover;
|
||||
- (void)popoverDidClose:(CPPopover)aPopover;
|
||||
- (void)popoverWillShow:(CPPopover)aPopover;
|
||||
- (void)popoverDidShow:(CPPopover)aPopover;
|
||||
|
||||
@end
|
||||
|
||||
CPPopoverBehaviorApplicationDefined = 0;
|
||||
CPPopoverBehaviorTransient = 1;
|
||||
@@ -60,15 +71,16 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
|
||||
*/
|
||||
@implementation CPPopover : CPResponder
|
||||
{
|
||||
@outlet CPViewController _contentViewController @accessors(property=contentViewController);
|
||||
@outlet id _delegate @accessors(getter=delegate);
|
||||
@outlet CPViewController _contentViewController @accessors(property=contentViewController);
|
||||
@outlet id <CPPopoverDelegate> _delegate @accessors(getter=delegate);
|
||||
|
||||
BOOL _animates @accessors(getter=animates);
|
||||
int _appearance @accessors(property=appearance);
|
||||
int _behavior @accessors(getter=behavior);
|
||||
BOOL _animates @accessors(getter=animates);
|
||||
int _appearance @accessors(property=appearance);
|
||||
int _behavior @accessors(getter=behavior);
|
||||
|
||||
_CPPopoverWindow _popoverWindow;
|
||||
int _implementedDelegateMethods;
|
||||
_CPPopoverWindow _popoverWindow;
|
||||
CPView _positioningView;
|
||||
int _implementedDelegateMethods;
|
||||
}
|
||||
|
||||
|
||||
@@ -127,9 +139,6 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
|
||||
*/
|
||||
- (CGSize)contentSize
|
||||
{
|
||||
if (![_popoverWindow isVisible])
|
||||
return CGRectMakeZero();
|
||||
|
||||
return [[_contentViewController view] frameSize];
|
||||
}
|
||||
|
||||
@@ -140,7 +149,10 @@ var CPPopoverDelegate_popover_willShow_ = 1 << 0,
|
||||
*/
|
||||
- (void)setContentSize:(CGSize)aSize
|
||||
{
|
||||
[[_contentViewController view] setFrameSize:aSize];
|
||||
if (!_popoverWindow)
|
||||
[[_contentViewController view] setFrameSize:aSize];
|
||||
else
|
||||
[_popoverWindow updateFrameWithSize:aSize];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -181,10 +193,10 @@ Set the behavior of the CPPopover. It can be:
|
||||
return;
|
||||
|
||||
_behavior = aBehavior;
|
||||
[_popoverWindow setStyleMask:[self styleMaskForBehavior]];
|
||||
[_popoverWindow setStyleMask:[self _styleMaskForBehavior]];
|
||||
}
|
||||
|
||||
- (void)setDelegate:(id)aDelegate
|
||||
- (void)setDelegate:(id <CPPopoverDelegate>)aDelegate
|
||||
{
|
||||
if (_delegate === aDelegate)
|
||||
return;
|
||||
@@ -226,17 +238,14 @@ Set the behavior of the CPPopover. It can be:
|
||||
if (!_contentViewController)
|
||||
[CPException raise:CPInternalInconsistencyException reason:@"contentViewController must not be nil"];
|
||||
|
||||
// If the popover is currently closing, do nothing. That is what Cocoa does.
|
||||
if ([_popoverWindow isClosing])
|
||||
// If the popover is currently closing or opening, do nothing. That is what Cocoa does.
|
||||
if ([_popoverWindow isClosing] || [_popoverWindow isOpening])
|
||||
return;
|
||||
|
||||
if (_implementedDelegateMethods & CPPopoverDelegate_popover_willShow_)
|
||||
[_delegate popoverWillShow:self];
|
||||
_positioningView = positioningView;
|
||||
|
||||
if (!_popoverWindow)
|
||||
{
|
||||
_popoverWindow = [[_CPPopoverWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:[self styleMaskForBehavior]];
|
||||
}
|
||||
_popoverWindow = [[_CPPopoverWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:[self _styleMaskForBehavior]];
|
||||
|
||||
[_popoverWindow setPlatformWindow:[[positioningView window] platformWindow]];
|
||||
[_popoverWindow setAppearance:_appearance];
|
||||
@@ -245,15 +254,22 @@ Set the behavior of the CPPopover. It can be:
|
||||
[_popoverWindow setMovableByWindowBackground:NO];
|
||||
[_popoverWindow setFrame:[_popoverWindow frameRectForContentRect:[[_contentViewController view] frame]]];
|
||||
[_popoverWindow setContentView:[_contentViewController view]];
|
||||
|
||||
if (![self isShown])
|
||||
[self _popoverWillShow];
|
||||
|
||||
[_popoverWindow positionRelativeToRect:positioningRect ofView:positioningView preferredEdge:preferredEdge];
|
||||
|
||||
if (!_animates && _implementedDelegateMethods & CPPopoverDelegate_popover_didShow_)
|
||||
[_delegate popoverDidShow:self];
|
||||
if (![self isShown])
|
||||
[self _popoverWindowDidShow];
|
||||
}
|
||||
|
||||
- (unsigned)styleMaskForBehavior
|
||||
- (unsigned)_styleMaskForBehavior
|
||||
{
|
||||
return (_behavior == CPPopoverBehaviorTransient) ? CPClosableOnBlurWindowMask : 0;
|
||||
if (_behavior == CPPopoverBehaviorApplicationDefined)
|
||||
return 0;
|
||||
|
||||
return CPClosableOnBlurWindowMask
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -272,9 +288,9 @@ Set the behavior of the CPPopover. It can be:
|
||||
if ([_popoverWindow isClosing] || ![self isShown])
|
||||
return;
|
||||
|
||||
if (_implementedDelegateMethods & CPPopoverDelegate_popover_willClose_)
|
||||
[_delegate popoverWillClose:self];
|
||||
[self _popoverWillClose];
|
||||
|
||||
_positioningView = nil;
|
||||
[_popoverWindow close];
|
||||
|
||||
// popoverDidClose will be sent from popoverWindowDidClose, since
|
||||
@@ -295,9 +311,8 @@ Set the behavior of the CPPopover. It can be:
|
||||
if ([_popoverWindow isClosing])
|
||||
return;
|
||||
|
||||
if (_implementedDelegateMethods & CPPopoverDelegate_popover_shouldClose_)
|
||||
if (![_delegate popoverShouldClose:self])
|
||||
return;
|
||||
if (![self _popoverShouldClose])
|
||||
return;
|
||||
|
||||
[self _close];
|
||||
}
|
||||
@@ -307,7 +322,7 @@ Set the behavior of the CPPopover. It can be:
|
||||
#pragma mark Delegates
|
||||
|
||||
/*! @ignore */
|
||||
- (BOOL)popoverWindowShouldClose:(_CPPopoverWindow)aPopoverWindow
|
||||
- (BOOL)_popoverWindowShouldClose
|
||||
{
|
||||
[self performClose:self];
|
||||
|
||||
@@ -318,19 +333,42 @@ Set the behavior of the CPPopover. It can be:
|
||||
}
|
||||
|
||||
/*! @ignore */
|
||||
- (void)popoverWindowDidClose:(_CPPopoverWindow)aPopoverWindow
|
||||
- (void)_popoverWindowDidClose
|
||||
{
|
||||
if (_implementedDelegateMethods & CPPopoverDelegate_popover_didClose_)
|
||||
[_delegate popoverDidClose:self];
|
||||
}
|
||||
|
||||
/*! @ignore */
|
||||
- (void)popoverWindowDidShow:(_CPPopoverWindow)aPopoverWindow
|
||||
- (void)_popoverWindowDidShow
|
||||
{
|
||||
if (_implementedDelegateMethods & CPPopoverDelegate_popover_didShow_)
|
||||
[_delegate popoverDidShow:self];
|
||||
}
|
||||
|
||||
/*! @ignore */
|
||||
- (BOOL)_popoverShouldClose
|
||||
{
|
||||
if (_implementedDelegateMethods & CPPopoverDelegate_popover_shouldClose_)
|
||||
return [_delegate popoverShouldClose:self];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
/*! @ignore */
|
||||
- (void)_popoverWillClose
|
||||
{
|
||||
if (_implementedDelegateMethods & CPPopoverDelegate_popover_willClose_)
|
||||
[_delegate popoverWillClose:self];
|
||||
}
|
||||
|
||||
/*! @ignore */
|
||||
- (void)_popoverWillShow
|
||||
{
|
||||
if (_implementedDelegateMethods & CPPopoverDelegate_popover_willShow_)
|
||||
[_delegate popoverWillShow:self];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPPopover (Deprecated)
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
@import "CPWindow_Constants.j"
|
||||
|
||||
|
||||
@typedef CPProgressIndicatorStyle
|
||||
/*
|
||||
@global
|
||||
@group CPProgressIndicatorStyle
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
@import "CPButton.j"
|
||||
|
||||
@class CPRadioGroup
|
||||
|
||||
@global CPApp
|
||||
|
||||
|
||||
@@ -356,7 +358,7 @@ var CPRadioRadioGroupKey = @"CPRadioRadioGroupKey";
|
||||
[_selectedRadio setState:CPOffState];
|
||||
|
||||
_selectedRadio = aRadio;
|
||||
[_CPRadioGroupSelectionBinder reverseSetValueForObject:self];
|
||||
[_CPRadioGroupSelectionBinder _reverseSetValueFromExclusiveBinderForObject:self];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -407,32 +409,17 @@ var CPRadioGroupRadiosKey = @"CPRadioGroupRadiosKey",
|
||||
return [super _binderClassForBinding:aBinding];
|
||||
}
|
||||
|
||||
@end
|
||||
+ (BOOL)isBindingExclusive:(CPString)aBinding
|
||||
{
|
||||
return (aBinding == CPSelectedIndexBinding ||
|
||||
aBinding == CPSelectedTagBinding ||
|
||||
aBinding == CPSelectedValueBinding);
|
||||
}
|
||||
|
||||
var binderForObject = {};
|
||||
@end
|
||||
|
||||
@implementation _CPRadioGroupSelectionBinder : CPBinder
|
||||
{
|
||||
CPString _selectionBinding @accessors;
|
||||
}
|
||||
|
||||
- (id)initWithBinding:(CPString)aBinding name:(CPString)aName to:(id)aDestination keyPath:(CPString)aKeyPath options:(CPDictionary)options from:(id)aSource
|
||||
{
|
||||
self = [super initWithBinding:aBinding name:aName to:aDestination keyPath:aKeyPath options:options from:aSource];
|
||||
|
||||
if (self)
|
||||
{
|
||||
binderForObject[[aSource UID]] = self;
|
||||
_selectionBinding = aName;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (void)reverseSetValueForObject:(id)aSource
|
||||
{
|
||||
var binder = binderForObject[[aSource UID]];
|
||||
[binder reverseSetValueFor:[binder _selectionBinding]];
|
||||
}
|
||||
|
||||
- (void)setPlaceholderValue:(id)aValue withMarker:(CPString)aMarker forBinding:(CPString)aBinding
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
@import "CPEvent.j"
|
||||
|
||||
@class CPKeyBinding
|
||||
@class CPMenu
|
||||
|
||||
CPDeleteKeyCode = 8;
|
||||
CPTabKeyCode = 9;
|
||||
|
||||
@@ -27,8 +27,7 @@
|
||||
@import "CPMenuItem.j"
|
||||
@import "CPTextField.j"
|
||||
|
||||
// NOTE: CPDatePicker is not implemented yet
|
||||
@class CPDatePicker
|
||||
@import "CPDatePicker.j"
|
||||
|
||||
|
||||
CPUndefinedAttributeType = 0;
|
||||
@@ -488,7 +487,36 @@ CPTransformableAttributeType = 1800;
|
||||
|
||||
- (id)copy
|
||||
{
|
||||
return [CPKeyedUnarchiver unarchiveObjectWithData:[CPKeyedArchiver archivedDataWithRootObject:self]];
|
||||
var views = [CPArray array];
|
||||
|
||||
var copy = [[[self class] alloc] init];
|
||||
[copy _setTemplateType:_templateType];
|
||||
[copy _setOptions:_predicateOptions];
|
||||
[copy _setModifier:_predicateModifier];
|
||||
[copy _setLeftAttributeType:_leftAttributeType];
|
||||
[copy _setRightAttributeType:_rightAttributeType];
|
||||
[copy setLeftIsWildcard:_leftIsWildcard];
|
||||
[copy setRightIsWildcard:_rightIsWildcard];
|
||||
|
||||
[_views enumerateObjectsUsingBlock:function(aView, idx, stop)
|
||||
{
|
||||
var vcopy;
|
||||
|
||||
if ([aView implementsSelector:@selector(copy)])
|
||||
{
|
||||
vcopy = [aView copy];
|
||||
}
|
||||
else
|
||||
{
|
||||
vcopy = [CPKeyedUnarchiver unarchiveObjectWithData:[CPKeyedArchiver archivedDataWithRootObject:aView]];
|
||||
}
|
||||
|
||||
[views addObject:vcopy];
|
||||
}];
|
||||
|
||||
[copy setTemplateViews:views];
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
+ (id)_operatorsForAttributeType:(CPAttributeType)attributeType
|
||||
@@ -680,7 +708,10 @@ CPTransformableAttributeType = 1800;
|
||||
view = [[CPCheckBox alloc] initWithFrame:CGRectMake(0, 0, 50, 26)];
|
||||
}
|
||||
else if (attributeType == CPDateAttributeType)
|
||||
view = [[CPDatePicker alloc] initWithFrame:CGRectMake(0, 0, 150, 26)];
|
||||
{
|
||||
view = [[CPDatePicker alloc] initWithFrame:CGRectMake(0, 0, 180, 26)];
|
||||
[view setDatePickerElements:CPYearMonthDayDatePickerElementFlag];
|
||||
}
|
||||
else
|
||||
return nil;
|
||||
|
||||
@@ -797,5 +828,31 @@ var CPPredicateTemplateTypeKey = @"CPPredicateTemplateType",
|
||||
[coder encodeObject:_views forKey:CPPredicateTemplateViewsKey];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
// Copy support for built-in types
|
||||
@implementation CPDatePicker (CPCopying)
|
||||
|
||||
- (id)copy
|
||||
{
|
||||
var ret = [[[self class] alloc] initWithFrame:[self frame]];
|
||||
|
||||
[ret setTextFont:[self textFont]];
|
||||
[ret setMinDate:[self minDate]];
|
||||
[ret setMaxDate:[self maxDate]];
|
||||
[ret setTimeInterval:[self timeInterval]];
|
||||
[ret setDatePickerMode:[self datePickerMode]];
|
||||
[ret setDatePickerElements:[self datePickerElements]];
|
||||
[ret setDatePickerStyle:[self datePickerStyle]];
|
||||
[ret setLocale:[self locale]];
|
||||
[ret setDateValue:[self dateValue]];
|
||||
[ret setBackgroundColor:[self backgroundColor]];
|
||||
[ret setDrawsBackground:[self drawsBackground]];
|
||||
[ret setBordered:[self isBordered]];
|
||||
[ret _init];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@end
|
||||
/*! @endcond */
|
||||
|
||||
@@ -41,6 +41,21 @@
|
||||
@global CPCaseInsensitivePredicateOption
|
||||
@global CPOrPredicateType
|
||||
|
||||
@protocol CPRuleEditorDelegate <CPObject>
|
||||
|
||||
@required
|
||||
- (id)ruleEditor:(CPRuleEditor)editor child:(CPInteger)index forCriterion:(id)criterion withRowType:(CPRuleEditorRowType)rowType;
|
||||
- (id)ruleEditor:(CPRuleEditor)editor displayValueForCriterion:(id)criterion inRow:(CPInteger)row;
|
||||
- (CPInteger)ruleEditor:(CPRuleEditor)editor numberOfChildrenForCriterion:(id)criterion withRowType:(CPRuleEditorRowType)rowType;
|
||||
|
||||
@optional
|
||||
- (CPDictionary)ruleEditor:(CPRuleEditor)editor predicatePartsForCriterion:(id)criterion withDisplayValue:(id)value inRow:(CPInteger)row;
|
||||
- (void)ruleEditorRowsDidChange:(CPNotification)notification;
|
||||
|
||||
@end
|
||||
|
||||
var CPRuleEditorDelegate_ruleEditor_predicatePartsForCriterion_withDisplayValue_inRow_ = 1 << 1;
|
||||
|
||||
var CPRuleEditorItemPBoardType = @"CPRuleEditorItemPBoardType",
|
||||
itemsContext = "items",
|
||||
valuesContext = "values",
|
||||
@@ -69,50 +84,51 @@ var CPRuleEditorItemPBoardType = @"CPRuleEditorItemPBoardType",
|
||||
|
||||
@implementation CPRuleEditor : CPControl
|
||||
{
|
||||
BOOL _suppressKeyDownHandling;
|
||||
BOOL _allowsEmptyCompoundRows;
|
||||
BOOL _disallowEmpty;
|
||||
BOOL _delegateWantsValidation;
|
||||
BOOL _editable;
|
||||
BOOL _sendAction;
|
||||
BOOL _suppressKeyDownHandling;
|
||||
BOOL _allowsEmptyCompoundRows;
|
||||
BOOL _disallowEmpty;
|
||||
BOOL _delegateWantsValidation;
|
||||
BOOL _editable;
|
||||
BOOL _sendAction;
|
||||
|
||||
Class _rowClass;
|
||||
Class _rowClass;
|
||||
|
||||
CPIndexSet _draggingRows;
|
||||
CPInteger _subviewIndexOfDropLine;
|
||||
CPView _dropLineView;
|
||||
CPIndexSet _draggingRows;
|
||||
CPInteger _subviewIndexOfDropLine;
|
||||
CPView _dropLineView;
|
||||
|
||||
CPMutableArray _rowCache;
|
||||
CPMutableArray _slices;
|
||||
CPMutableArray _rowCache;
|
||||
CPMutableArray _slices;
|
||||
|
||||
CPPredicate _predicate;
|
||||
CPPredicate _predicate;
|
||||
|
||||
CPString _itemsKeyPath;
|
||||
CPString _subrowsArrayKeyPath;
|
||||
CPString _typeKeyPath;
|
||||
CPString _valuesKeyPath;
|
||||
CPString _boundArrayKeyPath @accessors(property=boundArrayKeyPath);
|
||||
CPString _itemsKeyPath;
|
||||
CPString _subrowsArrayKeyPath;
|
||||
CPString _typeKeyPath;
|
||||
CPString _valuesKeyPath;
|
||||
CPString _boundArrayKeyPath @accessors(property=boundArrayKeyPath);
|
||||
|
||||
CPView _slicesHolder;
|
||||
CPViewAnimation _currentAnimation;
|
||||
CPView _slicesHolder;
|
||||
CPViewAnimation _currentAnimation;
|
||||
|
||||
CPInteger _lastRow;
|
||||
CPInteger _nestingMode;
|
||||
CPInteger _lastRow;
|
||||
CPInteger _nestingMode;
|
||||
|
||||
float _alignmentGridWidth;
|
||||
float _sliceHeight;
|
||||
float _alignmentGridWidth;
|
||||
float _sliceHeight;
|
||||
|
||||
id _ruleDataSource;
|
||||
id _ruleDelegate;
|
||||
id _boundArrayOwner;
|
||||
id _ruleDataSource;
|
||||
id <CPRuleEditorDelegate> _ruleDelegate;
|
||||
id _boundArrayOwner;
|
||||
unsigned _implementedDelegateMethods;
|
||||
|
||||
CPString _stringsFilename;
|
||||
CPString _stringsFilename;
|
||||
|
||||
BOOL _isKeyDown;
|
||||
BOOL _nestingModeDidChange;
|
||||
BOOL _isKeyDown;
|
||||
BOOL _nestingModeDidChange;
|
||||
|
||||
_CPRuleEditorLocalizer _standardLocalizer @accessors(property=standardLocalizer);
|
||||
CPDictionary _itemsAndValuesToAddForRowType;
|
||||
_CPRuleEditorLocalizer _standardLocalizer @accessors(property=standardLocalizer);
|
||||
CPDictionary _itemsAndValuesToAddForRowType;
|
||||
}
|
||||
|
||||
/*! @cond */
|
||||
@@ -131,8 +147,10 @@ var CPRuleEditorItemPBoardType = @"CPRuleEditorItemPBoardType",
|
||||
@"slice-bottom-border-color": [CPNull null],
|
||||
@"slice-last-bottom-border-color": [CPNull null],
|
||||
@"font": [CPNull null],
|
||||
@"font-color": [CPNull null],
|
||||
@"add-image": [CPNull null],
|
||||
@"remove-image": [CPNull null],
|
||||
@"vertical-alignment": [CPNull null]
|
||||
};
|
||||
}
|
||||
|
||||
@@ -143,7 +161,7 @@ var CPRuleEditorItemPBoardType = @"CPRuleEditorItemPBoardType",
|
||||
{
|
||||
_slices = [[CPMutableArray alloc] init];
|
||||
|
||||
_sliceHeight = 26.;
|
||||
_sliceHeight = 26.0;
|
||||
_nestingMode = CPRuleEditorNestingModeSimple; // 10.5 default is CPRuleEditorNestingModeCompound
|
||||
_editable = YES;
|
||||
_allowsEmptyCompoundRows = NO;
|
||||
@@ -213,19 +231,24 @@ var CPRuleEditorItemPBoardType = @"CPRuleEditorItemPBoardType",
|
||||
@discussion CPRuleEditor requires a delegate that implements the required delegate methods to function.
|
||||
@see delegate
|
||||
*/
|
||||
- (void)setDelegate:(id)aDelegate
|
||||
- (void)setDelegate:(id <CPRuleEditorDelegate>)aDelegate
|
||||
{
|
||||
if (_ruleDelegate === aDelegate)
|
||||
return;
|
||||
|
||||
var nc = [CPNotificationCenter defaultCenter];
|
||||
|
||||
if (_ruleDelegate)
|
||||
[nc removeObserver:_ruleDelegate name:nil object:self];
|
||||
|
||||
_ruleDelegate = aDelegate;
|
||||
_implementedDelegateMethods = 0;
|
||||
|
||||
if ([_ruleDelegate respondsToSelector:@selector(ruleEditorRowsDidChange:)])
|
||||
[nc addObserver:_ruleDelegate selector:@selector(ruleEditorRowsDidChange:) name:CPRuleEditorRowsDidChangeNotification object:nil];
|
||||
|
||||
if ([_ruleDelegate respondsToSelector:@selector(ruleEditor:predicatePartsForCriterion:withDisplayValue:inRow:)])
|
||||
_implementedDelegateMethods |= CPRuleEditorDelegate_ruleEditor_predicatePartsForCriterion_withDisplayValue_inRow_;
|
||||
}
|
||||
/*!
|
||||
@brief Returns a Boolean value that indicates whether the receiver is editable.
|
||||
@@ -810,7 +833,7 @@ TODO: implement
|
||||
var item = [items objectAtIndex:i],
|
||||
//var displayValue = [self _queryValueForItem:item inRow:aRow]; Ask the delegate or get cached value ?.
|
||||
displayValue = [[self displayValuesForRow:aRow] objectAtIndex:i],
|
||||
predpart = [_ruleDelegate ruleEditor:self predicatePartsForCriterion:item withDisplayValue:displayValue inRow:aRow];
|
||||
predpart = [self _sendDelegateRuleEditorPredicatePartsForCriterion:item withDisplayValue:displayValue inRow:aRow];
|
||||
|
||||
if (predpart)
|
||||
[predicateParts addEntriesFromDictionary:predpart];
|
||||
@@ -1716,8 +1739,7 @@ TODO: implement
|
||||
{
|
||||
if (_delegateWantsValidation)
|
||||
{
|
||||
var selector = @selector(ruleEditor:predicatePartsForCriterion:withDisplayValue:inRow:);
|
||||
if (![_ruleDelegate respondsToSelector:selector])
|
||||
if (![self _delegateRespondsToRuleEditorPredicatePartsForCriterionWithDisplayValueInRow])
|
||||
return;
|
||||
|
||||
_delegateWantsValidation = NO;
|
||||
@@ -1865,14 +1887,34 @@ TODO: implement
|
||||
return [self valueForThemeAttribute:@"font"];
|
||||
}
|
||||
|
||||
- (CPImage)_addImage
|
||||
- (CPColor)_fontColor
|
||||
{
|
||||
return [self valueForThemeAttribute:@"add-image"];
|
||||
return [self valueForThemeAttribute:@"font-color"];
|
||||
}
|
||||
|
||||
- (CPImage)_removeImage
|
||||
- (CPImage)_imageAdd
|
||||
{
|
||||
return [self valueForThemeAttribute:@"remove-image"];
|
||||
return [self valueForThemeAttribute:@"add-image" inState:CPThemeStateNormal];
|
||||
}
|
||||
|
||||
- (CPImage)_imageAddHighlighted
|
||||
{
|
||||
return [self valueForThemeAttribute:@"add-image" inState:CPThemeStateHighlighted];
|
||||
}
|
||||
|
||||
- (CPImage)_imageRemove
|
||||
{
|
||||
return [self valueForThemeAttribute:@"remove-image" inState:CPThemeStateNormal];
|
||||
}
|
||||
|
||||
- (CPImage)_imageRemoveHighlighted
|
||||
{
|
||||
return [self valueForThemeAttribute:@"remove-image" inState:CPThemeStateHighlighted];
|
||||
}
|
||||
|
||||
- (CPVerticalTextAlignment)_verticalAlignment
|
||||
{
|
||||
return [self valueForThemeAttribute:@"vertical-alignment"];
|
||||
}
|
||||
|
||||
- (CPString)_toolTipForAddCompoundRowButton
|
||||
@@ -2165,7 +2207,7 @@ TODO: implement
|
||||
indexOfDropLine = FLOOR(y / _sliceHeight),
|
||||
numberOfRows = [self numberOfRows];
|
||||
|
||||
if (indexOfDropLine < 0 || indexOfDropLine > numberOfRows || (indexOfDropLine >= [_draggingRows firstIndex] && indexOfDropLine <= [_draggingRows lastIndex] + 1))
|
||||
if (indexOfDropLine <= 0 || indexOfDropLine > numberOfRows || (indexOfDropLine >= [_draggingRows firstIndex] && indexOfDropLine <= [_draggingRows lastIndex] + 1))
|
||||
{
|
||||
if (_subviewIndexOfDropLine !== CPNotFound && indexOfDropLine !== _subviewIndexOfDropLine)
|
||||
[self _clearDropLine];
|
||||
@@ -2377,6 +2419,33 @@ TODO: implement
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation CPRuleEditor (CPRuleEditorDelegate)
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Check if the delegate responds to ruleEditor:predicatePartsForCriterion:withDisplayValue:inRow:
|
||||
*/
|
||||
- (BOOL)_delegateRespondsToRuleEditorPredicatePartsForCriterionWithDisplayValueInRow
|
||||
{
|
||||
return _implementedDelegateMethods & CPRuleEditorDelegate_ruleEditor_predicatePartsForCriterion_withDisplayValue_inRow_;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call delegate ruleEditor:predicatePartsForCriterion:withDisplayValue:inRow:
|
||||
*/
|
||||
- (CPDictionary)_sendDelegateRuleEditorPredicatePartsForCriterion:(id)criterion withDisplayValue:(id)value inRow:(CPInteger)row
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPRuleEditorDelegate_ruleEditor_predicatePartsForCriterion_withDisplayValue_inRow_))
|
||||
return @{};
|
||||
|
||||
return [_ruleDelegate ruleEditor:self predicatePartsForCriterion:criterion withDisplayValue:value inRow:row];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
var CPRuleEditorAlignmentGridWidthKey = @"CPRuleEditorAlignmentGridWidth",
|
||||
CPRuleEditorSliceHeightKey = @"CPRuleEditorSliceHeight",
|
||||
CPRuleEditorStringsFilenameKey = @"CPRuleEditorStringsFilename",
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
CPRuleEditorPredicateLeftExpression = "CPRuleEditorPredicateLeftExpression";
|
||||
CPRuleEditorPredicateRightExpression = "CPRuleEditorPredicateRightExpression";
|
||||
CPRuleEditorPredicateComparisonModifier = "CPRuleEditorPredicateComparisonModifier";
|
||||
@@ -36,5 +37,6 @@ CPRuleEditorNestingModeList = 1; // Allows a single list, with no nes
|
||||
CPRuleEditorNestingModeCompound = 2; // Unlimited nesting and compound rows; this is the default
|
||||
CPRuleEditorNestingModeSimple = 3; // One compound row at the top with subrows beneath it, and no further nesting allowed
|
||||
|
||||
@typedef CPRuleEditorRowType
|
||||
CPRuleEditorRowTypeSimple = 0;
|
||||
CPRuleEditorRowTypeCompound = 1;
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
@import <Foundation/CPObject.j>
|
||||
@import <Foundation/CPString.j>
|
||||
|
||||
@class CPPredicateEditorRowTemplate
|
||||
|
||||
@implementation _CPPredicateEditorTree : CPObject
|
||||
{
|
||||
CPPredicateEditorRowTemplate template @accessors;
|
||||
|
||||
@@ -1,203 +0,0 @@
|
||||
/*
|
||||
* Created by cacaodev@gmail.com.
|
||||
* Copyright (c) 2011 Pear, Inc. All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
@import "CPBezierPath.j"
|
||||
@import "CPPopUpButton.j"
|
||||
|
||||
@class _CPRuleEditorViewSlice
|
||||
|
||||
var GRADIENT_START_COLOR = "#fcfcfc",
|
||||
GRADIENT_END_COLOR = "#dfdfdf",
|
||||
BORDER_COLOR = "#BDBDBD";
|
||||
|
||||
var GRADIENT_NORMAL,
|
||||
GRADIENT_HIGHLIGHTED,
|
||||
GRADIENT_PROPERTY;
|
||||
|
||||
if (CPBrowserIsEngine(CPWebKitBrowserEngine))
|
||||
{
|
||||
GRADIENT_NORMAL = "-webkit-gradient(linear, left top, left bottom, from(" + GRADIENT_START_COLOR + "), to(" + GRADIENT_END_COLOR + "))",
|
||||
GRADIENT_HIGHLIGHTED = "-webkit-gradient(linear, left top, left bottom, from(" + GRADIENT_END_COLOR + "), to(" + GRADIENT_START_COLOR + "))";
|
||||
GRADIENT_PROPERTY = "background";
|
||||
}
|
||||
else if (CPBrowserIsEngine(CPGeckoBrowserEngine))
|
||||
{
|
||||
GRADIENT_NORMAL = "-moz-linear-gradient(top, " + GRADIENT_START_COLOR + ", " + GRADIENT_END_COLOR + ")",
|
||||
GRADIENT_HIGHLIGHTED = "-moz-linear-gradient(top, " + GRADIENT_END_COLOR + ", " + GRADIENT_START_COLOR + ")";
|
||||
GRADIENT_PROPERTY = "background";
|
||||
}
|
||||
else if (CPBrowserIsEngine(CPInternetExplorerBrowserEngine))
|
||||
{
|
||||
GRADIENT_NORMAL = "progid:DXImageTransform.Microsoft.gradient(startColorstr='" + GRADIENT_START_COLOR + "', endColorstr='" + GRADIENT_END_COLOR + "')";
|
||||
GRADIENT_HIGHLIGHTED = "progid:DXImageTransform.Microsoft.gradient(startColorstr='" + GRADIENT_END_COLOR + "', endColorstr='" + GRADIENT_START_COLOR + "')";
|
||||
GRADIENT_PROPERTY = "filter";
|
||||
}else
|
||||
{
|
||||
GRADIENT_NORMAL = GRADIENT_START_COLOR;
|
||||
GRADIENT_HIGHLIGHTED = GRADIENT_END_COLOR;
|
||||
GRADIENT_PROPERTY = "background";
|
||||
}
|
||||
|
||||
@implementation _CPRuleEditorPopUpButton : CPPopUpButton
|
||||
{
|
||||
CPInteger radius;
|
||||
}
|
||||
|
||||
- (void)_sharedInit
|
||||
{
|
||||
[self setBordered:NO];
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
var style = _DOMElement.style;
|
||||
style.border = "1px solid " + BORDER_COLOR;
|
||||
style[GRADIENT_PROPERTY] = GRADIENT_NORMAL;
|
||||
#endif
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)aFrame
|
||||
{
|
||||
if (self = [super initWithFrame:aFrame])
|
||||
[self _sharedInit];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
self = [super initWithCoder:aCoder];
|
||||
[self _sharedInit];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (CPView)hitTest:(CGPoint)point
|
||||
{
|
||||
if (!CGRectContainsPoint([self frame], point) || ![self sliceIsEditable])
|
||||
return nil;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)sliceIsEditable
|
||||
{
|
||||
var superview = [self superview];
|
||||
return ![superview isKindOfClass:[_CPRuleEditorViewSlice]] || [superview isEditable];
|
||||
}
|
||||
|
||||
- (void)trackMouse:(CPEvent)theEvent
|
||||
{
|
||||
if (![self sliceIsEditable])
|
||||
return;
|
||||
|
||||
[super trackMouse:theEvent];
|
||||
}
|
||||
|
||||
- (CGRect)contentRectForBounds:(CGRect)bounds
|
||||
{
|
||||
var contentRect = [super contentRectForBounds:bounds];
|
||||
contentRect.origin.x += radius;
|
||||
contentRect.size.width -= 2 * radius;
|
||||
|
||||
return contentRect;
|
||||
}
|
||||
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
#if PLATFORM(DOM)
|
||||
radius = FLOOR(CGRectGetHeight([self bounds]) / 2);
|
||||
var style = _DOMElement.style,
|
||||
radiusCSS = radius + "px";
|
||||
|
||||
style.borderRadius = radiusCSS;
|
||||
#endif
|
||||
|
||||
[super layoutSubviews];
|
||||
}
|
||||
|
||||
- (void)drawRect:(CGRect)aRect
|
||||
{
|
||||
var context = [[CPGraphicsContext currentContext] graphicsPort],
|
||||
bounds = [self bounds],
|
||||
arrow_width = FLOOR(CGRectGetHeight(bounds) / 3.5);
|
||||
|
||||
CGContextTranslateCTM(context, CGRectGetWidth(bounds) - radius - arrow_width, CGRectGetHeight(bounds) / 2);
|
||||
|
||||
var arrowsPath = [CPBezierPath bezierPath];
|
||||
[arrowsPath moveToPoint:CGPointMake(0, 1)];
|
||||
[arrowsPath lineToPoint:CGPointMake(arrow_width, 1)];
|
||||
[arrowsPath lineToPoint:CGPointMake(arrow_width / 2, arrow_width + 1)];
|
||||
[arrowsPath closePath];
|
||||
|
||||
CGContextSetFillColor(context, [CPColor colorWithWhite:101 / 255 alpha:1]);
|
||||
[arrowsPath fill];
|
||||
|
||||
CGContextScaleCTM(context, 1 , -1);
|
||||
[arrowsPath fill];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation _CPRuleEditorButton : CPButton
|
||||
{
|
||||
CPInteger radius;
|
||||
}
|
||||
|
||||
- (void)_sharedInit
|
||||
{
|
||||
[self setBordered:NO];
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
var style = _DOMElement.style;
|
||||
style.border = "1px solid " + BORDER_COLOR;
|
||||
style[GRADIENT_PROPERTY] = GRADIENT_NORMAL;
|
||||
#endif
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)aFrame
|
||||
{
|
||||
if (self = [super initWithFrame:aFrame])
|
||||
[self _sharedInit];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
self = [super initWithCoder:aCoder];
|
||||
[self _sharedInit];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
#if PLATFORM(DOM)
|
||||
radius = FLOOR(CGRectGetHeight([self bounds]) / 2);
|
||||
|
||||
var style = _DOMElement.style,
|
||||
radiusCSS = radius + "px";
|
||||
|
||||
style.borderRadius = radiusCSS;
|
||||
style[GRADIENT_PROPERTY] = ([self isHighlighted]) ? GRADIENT_HIGHLIGHTED : GRADIENT_NORMAL;
|
||||
#endif
|
||||
|
||||
[super layoutSubviews];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
@import "CPView.j"
|
||||
|
||||
@class CPRuleEditor
|
||||
|
||||
@implementation _CPRuleEditorViewSlice : CPView
|
||||
{
|
||||
CPRuleEditor _ruleEditor;
|
||||
@@ -61,9 +63,9 @@
|
||||
- (void)drawRect:(CGRect)rect
|
||||
{
|
||||
var context = [[CPGraphicsContext currentContext] graphicsPort],
|
||||
bounds = [self bounds],
|
||||
maxX = CGRectGetWidth(bounds),
|
||||
maxY = CGRectGetHeight(bounds);
|
||||
bounds = [self bounds],
|
||||
maxX = CGRectGetWidth(bounds),
|
||||
maxY = CGRectGetHeight(bounds);
|
||||
|
||||
// Draw background
|
||||
if ([self _isSelected])
|
||||
|
||||
@@ -19,24 +19,27 @@
|
||||
|
||||
@import "CPRuleEditor_Constants.j"
|
||||
@import "_CPRuleEditorViewSlice.j"
|
||||
@import "_CPRuleEditorPopUpButton.j"
|
||||
|
||||
@import "CPButton.j"
|
||||
@import "CPDatePicker.j"
|
||||
@import "CPPopUpButton.j"
|
||||
|
||||
@global CPApp
|
||||
|
||||
var CONTROL_HEIGHT = 16.,
|
||||
BUTTON_HEIGHT = 16.;
|
||||
@global CPMiniControlSize
|
||||
@global CPSmallControlSize
|
||||
|
||||
@implementation _CPRuleEditorViewSliceRow : _CPRuleEditorViewSlice
|
||||
{
|
||||
CPMutableArray _ruleOptionViews;
|
||||
CPMutableArray _ruleOptionFrames;
|
||||
CPMutableArray _correspondingRuleItems;
|
||||
CPMutableArray _ruleOptionInitialViewFrames;
|
||||
CPButton _addButton;
|
||||
CPButton _subtractButton;
|
||||
CPButton _addButton;
|
||||
CPButton _subtractButton;
|
||||
CPMutableArray _correspondingRuleItems;
|
||||
CPMutableArray _ruleOptionFrames;
|
||||
CPMutableArray _ruleOptionInitialViewFrames;
|
||||
CPMutableArray _ruleOptionViews;
|
||||
|
||||
CPRuleEditorRowType _rowType @accessors;
|
||||
CPRuleEditorRowType _plusButtonRowType;
|
||||
|
||||
CPRuleEditorRowType _rowType @accessors;
|
||||
CPRuleEditorRowType _plusButtonRowType;
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)frame ruleEditorView:(id)editor
|
||||
@@ -49,34 +52,33 @@ var CONTROL_HEIGHT = 16.,
|
||||
|
||||
- (void)_initShared
|
||||
{
|
||||
_correspondingRuleItems = [[CPMutableArray alloc] init];
|
||||
_ruleOptionFrames = [[CPMutableArray alloc] init];
|
||||
_ruleOptionInitialViewFrames = [[CPMutableArray alloc] init];
|
||||
_ruleOptionViews = [[CPMutableArray alloc] init];
|
||||
_editable = [_ruleEditor isEditable];
|
||||
_correspondingRuleItems = [[CPMutableArray alloc] init];
|
||||
_ruleOptionFrames = [[CPMutableArray alloc] init];
|
||||
_ruleOptionInitialViewFrames = [[CPMutableArray alloc] init];
|
||||
_ruleOptionViews = [[CPMutableArray alloc] init];
|
||||
_editable = [_ruleEditor isEditable];
|
||||
|
||||
_addButton = [self _createAddRowButton];
|
||||
_subtractButton = [self _createDeleteRowButton];
|
||||
|
||||
_addButton = [self _createAddRowButton];
|
||||
_subtractButton = [self _createDeleteRowButton];
|
||||
[_addButton setToolTip:[_ruleEditor _toolTipForAddSimpleRowButton]];
|
||||
[_subtractButton setToolTip:[_ruleEditor _toolTipForDeleteRowButton]];
|
||||
[_addButton setHidden:!_editable];
|
||||
[_subtractButton setHidden:!_editable];
|
||||
[self addSubview:_addButton];
|
||||
[self addSubview:_subtractButton];
|
||||
|
||||
[self setAutoresizingMask:CPViewWidthSizable];
|
||||
|
||||
var center = [CPNotificationCenter defaultCenter];
|
||||
[center addObserver:self selector:@selector(_textDidChange:) name:CPControlTextDidChangeNotification object:nil];
|
||||
}
|
||||
|
||||
- (CPButton)_createRowButton
|
||||
{
|
||||
var button = [[_CPRuleEditorButton alloc] initWithFrame:CGRectMakeZero()];
|
||||
[button setFont:[CPFont boldFontWithName:@"Apple Symbol" size:12.0]];
|
||||
[button setTextColor:[CPColor colorWithWhite:150 / 255 alpha:1]];
|
||||
var button = [[CPButton alloc] initWithFrame:CGRectMakeZero()];
|
||||
|
||||
[button setFont:[_ruleEditor font]];
|
||||
[button setTextColor:[_ruleEditor _fontColor]];
|
||||
|
||||
[button setAlignment:CPCenterTextAlignment];
|
||||
[button setAutoresizingMask:CPViewMinXMargin];
|
||||
[button setButtonType:CPMomentaryChangeButton];
|
||||
[button setBordered:NO];
|
||||
[button setHidden:!_editable];
|
||||
[button setImagePosition:CPImageOnly];
|
||||
|
||||
return button;
|
||||
@@ -86,7 +88,10 @@ var CONTROL_HEIGHT = 16.,
|
||||
{
|
||||
var button = [self _createRowButton];
|
||||
|
||||
[button setImage:[_ruleEditor _addImage]];
|
||||
[button setToolTip:[_ruleEditor _toolTipForAddSimpleRowButton]];
|
||||
[button setValue:[_ruleEditor _imageAdd] forThemeAttribute:@"image" inState:CPThemeStateNormal];
|
||||
[button setValue:[_ruleEditor _imageAddHighlighted] forThemeAttribute:@"image" inState:CPThemeStateHighlighted];
|
||||
|
||||
[button setAction:@selector(_addOption:)];
|
||||
[button setTarget:self];
|
||||
|
||||
@@ -97,7 +102,10 @@ var CONTROL_HEIGHT = 16.,
|
||||
{
|
||||
var button = [self _createRowButton];
|
||||
|
||||
[button setImage:[_ruleEditor _removeImage]];
|
||||
[button setToolTip:[_ruleEditor _toolTipForDeleteRowButton]];
|
||||
[button setValue:[_ruleEditor _imageRemove] forThemeAttribute:@"image" inState:CPThemeStateNormal];
|
||||
[button setValue:[_ruleEditor _imageRemoveHighlighted] forThemeAttribute:@"image" inState:CPThemeStateHighlighted];
|
||||
|
||||
[button setAction:@selector(_deleteOption:)];
|
||||
[button setTarget:self];
|
||||
|
||||
@@ -107,20 +115,17 @@ var CONTROL_HEIGHT = 16.,
|
||||
- (CPMenuItem)_createMenuItemWithTitle:(CPString )title
|
||||
{
|
||||
title = [[_ruleEditor standardLocalizer] localizedStringForString:title];
|
||||
var mItem = [[CPMenuItem alloc] initWithTitle:title action:nil keyEquivalent:@""];
|
||||
return mItem;
|
||||
return [[CPMenuItem alloc] initWithTitle:title action:nil keyEquivalent:@""];
|
||||
}
|
||||
|
||||
- (CPPopUpButton)_createPopUpButtonWithItems:(CPArray)itemsArray selectedItemIndex:(int)index
|
||||
{
|
||||
var title = [[itemsArray objectAtIndex:index] title],
|
||||
font = [_ruleEditor font],
|
||||
width = [title sizeWithFont:font].width + 20,
|
||||
rect = CGRectMake(0, 0, (width - width % 40) + 80, CONTROL_HEIGHT),
|
||||
var title = [[itemsArray objectAtIndex:index] title],
|
||||
font = [_ruleEditor font],
|
||||
width = [title sizeWithFont:font].width + 35, // 35 for right arrows + margins
|
||||
rect = CGRectMake(0, 0, width, [_ruleEditor rowHeight]),
|
||||
popup = [[CPPopUpButton alloc] initWithFrame:rect];
|
||||
|
||||
popup = [[_CPRuleEditorPopUpButton alloc] initWithFrame:rect];
|
||||
|
||||
[popup setTextColor:[CPColor colorWithWhite:101 / 255 alpha:1]];
|
||||
[popup setValue:font forThemeAttribute:@"font"];
|
||||
|
||||
var count = [itemsArray count];
|
||||
@@ -137,17 +142,17 @@ var CONTROL_HEIGHT = 16.,
|
||||
return [CPMenuItem separatorItem];
|
||||
}
|
||||
|
||||
- (_CPRuleEditorTextField)_createStaticTextFieldWithStringValue:(CPString)text
|
||||
- (CPTextField)_createStaticTextFieldWithStringValue:(CPString)text
|
||||
{
|
||||
var textField = [[_CPRuleEditorTextField alloc] initWithFrame:CGRectMakeZero()],
|
||||
ruleEditorFont = [_ruleEditor font],
|
||||
font = [CPFont fontWithName:[ruleEditorFont familyName] size:[ruleEditorFont size] + 2],
|
||||
localizedText = [[_ruleEditor standardLocalizer] localizedStringForString:text],
|
||||
size = [localizedText sizeWithFont:font];
|
||||
|
||||
[textField setFrameSize:CGSizeMake(size.width + 4, CONTROL_HEIGHT + 2)];
|
||||
var textField = [[CPTextField alloc] initWithFrame:CGRectMakeZero()],
|
||||
ruleEditorFont = [_ruleEditor font],
|
||||
font = [CPFont fontWithName:[ruleEditorFont familyName] size:[ruleEditorFont size] + 2],
|
||||
localizedText = [[_ruleEditor standardLocalizer] localizedStringForString:text],
|
||||
size = [localizedText sizeWithFont:font];
|
||||
|
||||
[textField setFrameSize:CGSizeMake(size.width + 4, [_ruleEditor rowHeight])];
|
||||
[textField setValue:font forThemeAttribute:@"font"];
|
||||
[textField setValue:[_ruleEditor _verticalAlignment] forThemeAttribute:@"vertical-alignment"];
|
||||
[textField setStringValue:localizedText];
|
||||
|
||||
return textField;
|
||||
@@ -159,6 +164,7 @@ var CONTROL_HEIGHT = 16.,
|
||||
[self setNeedsDisplay:YES];
|
||||
|
||||
var type = _plusButtonRowType;
|
||||
|
||||
if ([_ruleEditor nestingMode] == CPRuleEditorNestingModeCompound && ([[CPApp currentEvent] modifierFlags] & CPAlternateKeyMask))
|
||||
type = CPRuleEditorRowTypeCompound;
|
||||
|
||||
@@ -170,12 +176,12 @@ var CONTROL_HEIGHT = 16.,
|
||||
[_ruleEditor _deleteSlice:self];
|
||||
}
|
||||
|
||||
- (void)_ruleOptionPopupChangedAction:(CPMenuItem )sender
|
||||
- (void)_ruleOptionPopupChangedAction:(CPMenuItem)sender
|
||||
{
|
||||
var layoutdict = [sender representedObject],
|
||||
newItem = [layoutdict objectForKey:@"item"],
|
||||
var layoutdict = [sender representedObject],
|
||||
newItem = [layoutdict objectForKey:@"item"],
|
||||
indexInCriteria = [layoutdict objectForKey:@"indexInCriteria"],
|
||||
oldItem = [_correspondingRuleItems objectAtIndex:indexInCriteria];
|
||||
oldItem = [_correspondingRuleItems objectAtIndex:indexInCriteria];
|
||||
|
||||
if (![newItem isEqual:oldItem])
|
||||
{
|
||||
@@ -307,8 +313,16 @@ var CONTROL_HEIGHT = 16.,
|
||||
|
||||
if (ruleView != nil)
|
||||
{
|
||||
[ruleView setControlSize:CPSmallControlSize];
|
||||
|
||||
var minSize = [ruleView currentValueForThemeAttribute:@"min-size"],
|
||||
frame = [ruleView frame];
|
||||
|
||||
// Force controls to their minimum size
|
||||
frame.size.height = minSize.height;
|
||||
[ruleView setFrame:frame];
|
||||
|
||||
[_ruleOptionViews addObject:ruleView];
|
||||
var frame = [ruleView frame];
|
||||
[_ruleOptionInitialViewFrames addObject:frame];
|
||||
[_ruleOptionFrames addObject:frame];
|
||||
|
||||
@@ -331,8 +345,6 @@ var CONTROL_HEIGHT = 16.,
|
||||
var aView = [_ruleOptionViews objectAtIndex:firstResponderIndex];
|
||||
[[self window] makeFirstResponder:aView]; // This is not working. bug in CPPopUpButton firstResponder ?
|
||||
}
|
||||
|
||||
//[self setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
- (void)_updateEnabledStateForSubviews
|
||||
@@ -350,14 +362,15 @@ var CONTROL_HEIGHT = 16.,
|
||||
var optionViewOriginX,
|
||||
leftHorizontalPadding,
|
||||
leftButtonMinX,
|
||||
rowHeight = [_ruleEditor rowHeight],
|
||||
count = [_ruleOptionViews count],
|
||||
sliceFrame = [self frame],
|
||||
rowHeight = [_ruleEditor rowHeight],
|
||||
count = [_ruleOptionViews count],
|
||||
sliceFrame = [self frame],
|
||||
image = [_ruleEditor _imageAdd],
|
||||
|
||||
buttonFrame = CGRectMake(CGRectGetWidth(sliceFrame) - BUTTON_HEIGHT - [self _rowButtonsRightHorizontalPadding], ([_ruleEditor rowHeight] - BUTTON_HEIGHT) / 2 - 2, BUTTON_HEIGHT, BUTTON_HEIGHT);
|
||||
buttonFrame = CGRectMake(CGRectGetWidth(sliceFrame) - [image size].width - [self _rowButtonsRightHorizontalPadding], ([_ruleEditor rowHeight] - [image size].height) / 2 - 1, [image size].width, [image size].height);
|
||||
|
||||
[_addButton setFrame:buttonFrame];
|
||||
buttonFrame.origin.x -= BUTTON_HEIGHT + [self _rowButtonsInterviewHorizontalPadding];
|
||||
buttonFrame.origin.x -= [image size].width + [self _rowButtonsInterviewHorizontalPadding];
|
||||
[_subtractButton setFrame:buttonFrame];
|
||||
|
||||
if (widthChanged)
|
||||
@@ -372,7 +385,8 @@ var CONTROL_HEIGHT = 16.,
|
||||
var ruleOptionView = _ruleOptionViews[i],
|
||||
optionFrame = _ruleOptionFrames[i];
|
||||
|
||||
optionFrame.origin.y = (rowHeight - CGRectGetHeight(optionFrame)) / 2 - 2;
|
||||
// Use a pixel correction to align controls
|
||||
optionFrame.origin.y = (rowHeight - CGRectGetHeight(optionFrame)) / 2;
|
||||
|
||||
if (widthChanged)
|
||||
{
|
||||
@@ -481,6 +495,26 @@ var CONTROL_HEIGHT = 16.,
|
||||
[self layoutSubviews];
|
||||
}
|
||||
|
||||
- (void)_addObservers
|
||||
{
|
||||
if (_isObserving)
|
||||
return;
|
||||
|
||||
[super _addObservers];
|
||||
|
||||
[[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_textDidChange:) name:CPControlTextDidChangeNotification object:nil];
|
||||
}
|
||||
|
||||
- (void)_removeObservers
|
||||
{
|
||||
if (!_isObserving)
|
||||
return;
|
||||
|
||||
[super _removeObservers];
|
||||
|
||||
[[CPNotificationCenter defaultCenter] removeObserver:self name:CPControlTextDidChangeNotification object:nil];
|
||||
}
|
||||
|
||||
- (void)drawRect:(CGRect)rect
|
||||
{
|
||||
[super drawRect:rect];
|
||||
@@ -488,8 +522,9 @@ var CONTROL_HEIGHT = 16.,
|
||||
|
||||
- (BOOL)_isRulePopup:(CPView)view
|
||||
{
|
||||
if ([view isKindOfClass:[_CPRuleEditorPopUpButton class]])
|
||||
if ([view isKindOfClass:[CPPopUpButton class]])
|
||||
return YES;
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
@@ -506,28 +541,3 @@ var CONTROL_HEIGHT = 16.,
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation _CPRuleEditorTextField : CPTextField
|
||||
{
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)frame
|
||||
{
|
||||
self = [super initWithFrame:frame];
|
||||
if (self)
|
||||
{
|
||||
[self setDrawsBackground:NO];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (CPView)hitTest:(CGPoint)point
|
||||
{
|
||||
if (!CGRectContainsPoint([self frame], point))
|
||||
return nil;
|
||||
|
||||
return [self superview];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -264,11 +264,6 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay,
|
||||
_delegate = nil;
|
||||
_scrollTimer = nil;
|
||||
_implementedDelegateMethods = 0;
|
||||
|
||||
[[CPNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(_didReceiveDefaultStyleChange:)
|
||||
name:CPScrollerStyleGlobalChangeNotification
|
||||
object:nil];
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -1262,10 +1257,45 @@ Notifies the delegate when the scroll view has finished scrolling.
|
||||
[self reflectScrolledClipView:_contentView];
|
||||
}
|
||||
|
||||
- (CGRect)documentVisibleRect
|
||||
{
|
||||
return [_contentView documentVisibleRect];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Overrides
|
||||
|
||||
|
||||
- (void)_removeObservers
|
||||
{
|
||||
if (!_isObserving)
|
||||
return;
|
||||
|
||||
[[CPNotificationCenter defaultCenter] removeObserver:self
|
||||
name:CPScrollerStyleGlobalChangeNotification
|
||||
object:nil];
|
||||
|
||||
[super _removeObservers];
|
||||
}
|
||||
|
||||
- (void)_addObservers
|
||||
{
|
||||
if (_isObserving)
|
||||
return;
|
||||
|
||||
//Make sure to have the last global style for the scroller
|
||||
[self _didReceiveDefaultStyleChange:nil];
|
||||
|
||||
[[CPNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(_didReceiveDefaultStyleChange:)
|
||||
name:CPScrollerStyleGlobalChangeNotification
|
||||
object:nil];
|
||||
|
||||
[super _addObservers];
|
||||
}
|
||||
|
||||
|
||||
|
||||
- (void)drawRect:(CGRect)aRect
|
||||
{
|
||||
[super drawRect:aRect];
|
||||
@@ -1399,7 +1429,16 @@ Notifies the delegate when the scroll view has finished scrolling.
|
||||
if (![_horizontalScroller isHidden] || ![_verticalScroller isHidden])
|
||||
_timerScrollersHide = [CPTimer scheduledTimerWithTimeInterval:CPScrollViewFadeOutTime target:self selector:@selector(_hideScrollers:) userInfo:nil repeats:NO];
|
||||
|
||||
[self _respondToScrollWheelEventWithDeltaX:[anEvent deltaX] deltaY:[anEvent deltaY]];
|
||||
var deltaX = [anEvent scrollingDeltaX],
|
||||
deltaY = [anEvent scrollingDeltaY];
|
||||
|
||||
if (![anEvent hasPreciseScrollingDeltas])
|
||||
{
|
||||
deltaX *= (_horizontalLineScroll || 1.0);
|
||||
deltaY *= (_verticalLineScroll || 1.0);
|
||||
}
|
||||
|
||||
[self _respondToScrollWheelEventWithDeltaX:deltaX deltaY:deltaY];
|
||||
}
|
||||
|
||||
- (void)scrollPageUp:(id)sender
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
@global CPApp
|
||||
|
||||
// CPScroller Constants
|
||||
@typedef CPScrollerPart
|
||||
CPScrollerNoPart = 0;
|
||||
CPScrollerDecrementPage = 1;
|
||||
CPScrollerKnob = 2;
|
||||
@@ -44,6 +45,7 @@ CPScrollerKnobSlot = 6;
|
||||
CPScrollerIncrementArrow = 0;
|
||||
CPScrollerDecrementArrow = 1;
|
||||
|
||||
@typedef CPUsableScrollerParts
|
||||
CPNoScrollerParts = 0;
|
||||
CPOnlyScrollerArrows = 1;
|
||||
CPAllScrollerParts = 2;
|
||||
@@ -78,7 +80,6 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
|
||||
|
||||
@implementation CPScroller : CPControl
|
||||
{
|
||||
CPControlSize _controlSize;
|
||||
CPUsableScrollerParts _usableParts;
|
||||
CPArray _partRects;
|
||||
|
||||
@@ -172,7 +173,6 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
|
||||
{
|
||||
if (self = [super initWithFrame:aFrame])
|
||||
{
|
||||
_controlSize = CPRegularControlSize;
|
||||
_partRects = [];
|
||||
|
||||
[self setFloatValue:0.0];
|
||||
@@ -243,29 +243,6 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
|
||||
[super setObjectValue:MIN(1.0, MAX(0.0, +aValue))];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the scroller's control size
|
||||
*/
|
||||
- (CPControlSize)controlSize
|
||||
{
|
||||
return _controlSize;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the scroller's size.
|
||||
@param aControlSize the scroller's size
|
||||
*/
|
||||
- (void)setControlSize:(CPControlSize)aControlSize
|
||||
{
|
||||
if (_controlSize == aControlSize)
|
||||
return;
|
||||
|
||||
_controlSize = aControlSize;
|
||||
|
||||
[self setNeedsLayout];
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
/*!
|
||||
Return's the knob's proportion
|
||||
*/
|
||||
@@ -733,7 +710,7 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
|
||||
var themeState = _themeState;
|
||||
|
||||
if (NAMES_FOR_PARTS[_hitPart] + "-color" !== anAttributeName)
|
||||
themeState &= ~CPThemeStateHighlighted;
|
||||
themeState = themeState.without(CPThemeStateHighlighted);
|
||||
|
||||
return [self valueForThemeAttribute:anAttributeName inState:themeState];
|
||||
}
|
||||
@@ -802,8 +779,7 @@ CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
|
||||
|
||||
@end
|
||||
|
||||
var CPScrollerControlSizeKey = @"CPScrollerControlSize",
|
||||
CPScrollerIsVerticalKey = @"CPScrollerIsVerticalKey",
|
||||
var CPScrollerIsVerticalKey = @"CPScrollerIsVerticalKey",
|
||||
CPScrollerKnobProportionKey = @"CPScrollerKnobProportion",
|
||||
CPScrollerStyleKey = @"CPScrollerStyleKey";
|
||||
|
||||
@@ -813,10 +789,6 @@ var CPScrollerControlSizeKey = @"CPScrollerControlSize",
|
||||
{
|
||||
if (self = [super initWithCoder:aCoder])
|
||||
{
|
||||
_controlSize = CPRegularControlSize;
|
||||
if ([aCoder containsValueForKey:CPScrollerControlSizeKey])
|
||||
_controlSize = [aCoder decodeIntForKey:CPScrollerControlSizeKey];
|
||||
|
||||
_knobProportion = 1.0;
|
||||
|
||||
if ([aCoder containsValueForKey:CPScrollerKnobProportionKey])
|
||||
@@ -851,7 +823,6 @@ var CPScrollerControlSizeKey = @"CPScrollerControlSize",
|
||||
{
|
||||
[super encodeWithCoder:aCoder];
|
||||
|
||||
[aCoder encodeInt:_controlSize forKey:CPScrollerControlSizeKey];
|
||||
[aCoder encodeInt:_isVertical forKey:CPScrollerIsVerticalKey];
|
||||
[aCoder encodeFloat:_knobProportion forKey:CPScrollerKnobProportionKey];
|
||||
[aCoder encodeInt:_style forKey:CPScrollerStyleKey];
|
||||
|
||||
@@ -119,16 +119,28 @@ var RECENT_SEARCH_PREFIX = @" ";
|
||||
_canResignFirstResponder = YES;
|
||||
}
|
||||
|
||||
- (void)viewWillMoveToSuperview:(CPView)aView
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Override observers
|
||||
|
||||
- (void)_removeObservers
|
||||
{
|
||||
[super viewWillMoveToSuperview:aView];
|
||||
if (!_isObserving)
|
||||
return;
|
||||
|
||||
[super _removeObservers];
|
||||
|
||||
// First we remove any observer that may have been in place to avoid memory leakage.
|
||||
[[CPNotificationCenter defaultCenter] removeObserver:self name:CPControlTextDidChangeNotification object:self];
|
||||
}
|
||||
|
||||
// Register the observe here if we need to.
|
||||
if (aView)
|
||||
[[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_searchFieldTextDidChange:) name:CPControlTextDidChangeNotification object:self];
|
||||
- (void)_addObservers
|
||||
{
|
||||
if (_isObserving)
|
||||
return;
|
||||
|
||||
[super _addObservers];
|
||||
|
||||
[[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_searchFieldTextDidChange:) name:CPControlTextDidChangeNotification object:self];
|
||||
}
|
||||
|
||||
// Managing Buttons
|
||||
|
||||
@@ -25,9 +25,11 @@
|
||||
@import "CPControl.j"
|
||||
@import "CPWindow_Constants.j"
|
||||
@import "_CPImageAndTextView.j"
|
||||
@import "CPMenu.j"
|
||||
|
||||
@global CPApp
|
||||
|
||||
@typedef CPSegmentSwitchTracking
|
||||
CPSegmentSwitchTrackingSelectOne = 0;
|
||||
CPSegmentSwitchTrackingSelectAny = 1;
|
||||
CPSegmentSwitchTrackingMomentary = 2;
|
||||
@@ -70,23 +72,9 @@ CPSegmentSwitchTrackingMomentary = 2;
|
||||
@"center-segment-bezel-color": [CPNull null],
|
||||
@"divider-bezel-color": [CPNull null],
|
||||
@"divider-thickness": 1.0,
|
||||
@"default-height": 24.0,
|
||||
};
|
||||
}
|
||||
|
||||
+ (Class)_binderClassForBinding:(CPString)aBinding
|
||||
{
|
||||
if ([self _isSelectionBinding:aBinding])
|
||||
return [_CPSegmentedControlBinder class];
|
||||
|
||||
return [super _binderClassForBinding:aBinding];
|
||||
}
|
||||
|
||||
+ (BOOL)_isSelectionBinding:(CPString)aBinding
|
||||
{
|
||||
return (aBinding === CPSelectedIndexBinding || aBinding === CPSelectedLabelBinding || aBinding === CPSelectedTagBinding);
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)aRect
|
||||
{
|
||||
_segments = [];
|
||||
@@ -104,17 +92,14 @@ CPSegmentSwitchTrackingMomentary = 2;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)bind:(CPString)aBinding toObject:(id)anObject withKeyPath:(CPString)aKeyPath options:(CPDictionary)options
|
||||
/*!
|
||||
Sets the control's size.
|
||||
@param aControlSize the control's size
|
||||
*/
|
||||
- (void)setControlSize:(CPControlSize)aControlSize
|
||||
{
|
||||
if ([[self class] _isSelectionBinding:aBinding] && _trackingMode !== CPSegmentSwitchTrackingSelectOne)
|
||||
CPLog.warn("Binding " + aBinding + " needs CPSegmentSwitchTrackingSelectOne tracking mode");
|
||||
else
|
||||
[super bind:aBinding toObject:anObject withKeyPath:aKeyPath options:options];
|
||||
}
|
||||
|
||||
- (void)_reverseSetBinding
|
||||
{
|
||||
[_CPSegmentedControlBinder reverseSetValueForObject:self];
|
||||
[super setControlSize:aControlSize];
|
||||
[self _sizeToControlSize];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -285,7 +270,6 @@ CPSegmentSwitchTrackingMomentary = 2;
|
||||
- (void)setWidth:(float)aWidth forSegment:(unsigned)aSegment
|
||||
{
|
||||
[_segments[aSegment] setWidth:aWidth];
|
||||
|
||||
[self tileWithChangedSegment:aSegment];
|
||||
}
|
||||
|
||||
@@ -432,9 +416,9 @@ CPSegmentSwitchTrackingMomentary = 2;
|
||||
[_segments[aSegment] setEnabled:shouldBeEnabled];
|
||||
|
||||
if (shouldBeEnabled)
|
||||
_themeStates[aSegment] &= ~CPThemeStateDisabled;
|
||||
_themeStates[aSegment] = _themeStates[aSegment].without(CPThemeStateDisabled);
|
||||
else
|
||||
_themeStates[aSegment] |= CPThemeStateDisabled;
|
||||
_themeStates[aSegment] = _themeStates[aSegment].and(CPThemeStateDisabled);
|
||||
|
||||
[self setNeedsLayout];
|
||||
[self setNeedsDisplay:YES];
|
||||
@@ -477,10 +461,13 @@ CPSegmentSwitchTrackingMomentary = 2;
|
||||
*/
|
||||
- (void)drawSegmentBezel:(int)aSegment highlight:(BOOL)shouldHighlight
|
||||
{
|
||||
if (shouldHighlight)
|
||||
_themeStates[aSegment] |= CPThemeStateHighlighted;
|
||||
else
|
||||
_themeStates[aSegment] &= ~CPThemeStateHighlighted;
|
||||
if(aSegment < _themeStates.length)
|
||||
{
|
||||
if (shouldHighlight)
|
||||
_themeStates[aSegment] = _themeStates[aSegment].and(CPThemeStateHighlighted);
|
||||
else
|
||||
_themeStates[aSegment] = _themeStates[aSegment].without(CPThemeStateHighlighted);
|
||||
}
|
||||
|
||||
[self setNeedsLayout];
|
||||
[self setNeedsDisplay:YES];
|
||||
@@ -510,7 +497,7 @@ CPSegmentSwitchTrackingMomentary = 2;
|
||||
|
||||
- (CGRect)rectForEphemeralSubviewNamed:(CPString)aName
|
||||
{
|
||||
var height = [self currentValueForThemeAttribute:@"default-height"],
|
||||
var height = [self currentValueForThemeAttribute:@"min-size"].height,
|
||||
contentInset = [self currentValueForThemeAttribute:@"content-inset"],
|
||||
bezelInset = [self currentValueForThemeAttribute:@"bezel-inset"],
|
||||
bounds = [self bounds];
|
||||
@@ -574,9 +561,17 @@ CPSegmentSwitchTrackingMomentary = 2;
|
||||
if (_segments.length <= 0)
|
||||
return;
|
||||
|
||||
var themeState = _themeStates[0];
|
||||
var themeState = _themeStates[0],
|
||||
isDisabled = [self hasThemeState:CPThemeStateDisabled],
|
||||
isControlSizeSmall = [self hasThemeState:CPThemeStateControlSizeSmall],
|
||||
isControlSizeMini = [self hasThemeState:CPThemeStateControlSizeMini];
|
||||
|
||||
themeState |= _themeState & CPThemeStateDisabled;
|
||||
themeState = isDisabled ? themeState.and(CPThemeStateDisabled) : themeState;
|
||||
|
||||
if (isControlSizeSmall)
|
||||
themeState = themeState.and(CPThemeStateControlSizeSmall);
|
||||
else if (isControlSizeMini)
|
||||
themeState = themeState.and(CPThemeStateControlSizeMini);
|
||||
|
||||
var leftCapColor = [self valueForThemeAttribute:@"left-segment-bezel-color"
|
||||
inState:themeState],
|
||||
@@ -589,7 +584,12 @@ CPSegmentSwitchTrackingMomentary = 2;
|
||||
|
||||
var themeState = _themeStates[_themeStates.length - 1];
|
||||
|
||||
themeState |= _themeState & CPThemeStateDisabled;
|
||||
themeState = isDisabled ? themeState.and(CPThemeStateDisabled) : themeState;
|
||||
|
||||
if (isControlSizeSmall)
|
||||
themeState = themeState.and(CPThemeStateControlSizeSmall);
|
||||
else if (isControlSizeMini)
|
||||
themeState = themeState.and(CPThemeStateControlSizeMini);
|
||||
|
||||
var rightCapColor = [self valueForThemeAttribute:@"right-segment-bezel-color"
|
||||
inState:themeState],
|
||||
@@ -604,7 +604,12 @@ CPSegmentSwitchTrackingMomentary = 2;
|
||||
{
|
||||
var themeState = _themeStates[i];
|
||||
|
||||
themeState |= _themeState & CPThemeStateDisabled;
|
||||
themeState = isDisabled ? themeState.and(CPThemeStateDisabled) : themeState;
|
||||
|
||||
if (isControlSizeSmall)
|
||||
themeState = themeState.and(CPThemeStateControlSizeSmall);
|
||||
else if (isControlSizeMini)
|
||||
themeState = themeState.and(CPThemeStateControlSizeMini);
|
||||
|
||||
var bezelColor = [self valueForThemeAttribute:@"center-segment-bezel-color"
|
||||
inState:themeState],
|
||||
@@ -615,7 +620,6 @@ CPSegmentSwitchTrackingMomentary = 2;
|
||||
|
||||
[bezelView setBackgroundColor:bezelColor];
|
||||
|
||||
|
||||
// layout image/title views
|
||||
var segment = _segments[i],
|
||||
contentView = [self layoutEphemeralSubviewNamed:@"segment-content-" + i
|
||||
@@ -642,11 +646,16 @@ CPSegmentSwitchTrackingMomentary = 2;
|
||||
if (i == count - 1)
|
||||
continue;
|
||||
|
||||
var borderState = _themeStates[i] | _themeStates[i + 1];
|
||||
var borderState = _themeStates[i].and(_themeStates[i + 1]);
|
||||
|
||||
borderState = (borderState & CPThemeStateSelected & ~CPThemeStateHighlighted) ? CPThemeStateSelected : CPThemeStateNormal;
|
||||
borderState = (borderState.hasThemeState(CPThemeStateSelected) && !borderState.hasThemeState(CPThemeStateHighlighted)) ? CPThemeStateSelected : CPThemeStateNormal;
|
||||
|
||||
borderState |= _themeState & CPThemeStateDisabled;
|
||||
borderState = isDisabled ? borderState.and(CPThemeStateDisabled) : borderState;
|
||||
|
||||
if (isControlSizeSmall)
|
||||
borderState = borderState.and(CPThemeStateControlSizeSmall);
|
||||
else if (isControlSizeMini)
|
||||
borderState = borderState.and(CPThemeStateControlSizeMini);
|
||||
|
||||
var borderColor = [self valueForThemeAttribute:@"divider-bezel-color"
|
||||
inState:borderState],
|
||||
@@ -676,7 +685,7 @@ CPSegmentSwitchTrackingMomentary = 2;
|
||||
|
||||
var segment = _segments[aSegment],
|
||||
segmentWidth = [segment width],
|
||||
themeState = _themeStates[aSegment] | (_themeState & CPThemeStateDisabled),
|
||||
themeState = _themeState.hasThemeState(CPThemeStateDisabled) ? _themeStates[aSegment].and(CPThemeStateDisabled) : _themeStates[aSegment],
|
||||
contentInset = [self valueForThemeAttribute:@"content-inset" inState:themeState],
|
||||
font = [self font];
|
||||
|
||||
@@ -704,7 +713,6 @@ CPSegmentSwitchTrackingMomentary = 2;
|
||||
|
||||
// Update control size
|
||||
var frame = [self frame];
|
||||
|
||||
[self setFrameSize:CGSizeMake(CGRectGetWidth(frame) + delta, CGRectGetHeight(frame))];
|
||||
|
||||
// Update segment width
|
||||
@@ -740,7 +748,7 @@ CPSegmentSwitchTrackingMomentary = 2;
|
||||
|
||||
- (CGRect)bezelFrameForSegment:(unsigned)aSegment
|
||||
{
|
||||
var height = [self currentValueForThemeAttribute:@"default-height"],
|
||||
var height = [self currentValueForThemeAttribute:@"min-size"].height,
|
||||
bezelInset = [self currentValueForThemeAttribute:@"bezel-inset"],
|
||||
width = [self widthForSegment:aSegment],
|
||||
left = [self _leftOffsetForSegment:aSegment];
|
||||
@@ -750,7 +758,7 @@ CPSegmentSwitchTrackingMomentary = 2;
|
||||
|
||||
- (CGRect)contentFrameForSegment:(unsigned)aSegment
|
||||
{
|
||||
var height = [self currentValueForThemeAttribute:@"default-height"],
|
||||
var height = [self currentValueForThemeAttribute:@"min-size"].height,
|
||||
contentInset = [self currentValueForThemeAttribute:@"content-inset"],
|
||||
width = [self widthForSegment:aSegment],
|
||||
left = [self _leftOffsetForSegment:aSegment];
|
||||
@@ -912,20 +920,40 @@ var CPSegmentedControlSegmentsKey = "CPSegmentedControlSegmentsKey",
|
||||
else
|
||||
_trackingMode = CPSegmentSwitchTrackingSelectOne;
|
||||
|
||||
// HACK
|
||||
// Here we update the themeStates array for each segments to know if there are selected or not
|
||||
for (var i = 0; i < _segments.length; i++)
|
||||
_themeStates[i] = [_segments[i] selected] ? CPThemeStateSelected : CPThemeStateNormal;
|
||||
|
||||
// We do this in a second loop because it relies on all the themeStates being set first
|
||||
for (var i = 0; i < _segments.length; i++)
|
||||
[self tileWithChangedSegment:i];
|
||||
|
||||
var thickness = [self currentValueForThemeAttribute:@"divider-thickness"],
|
||||
dividerExtraSpace = ([_segments count] - 1) * thickness,
|
||||
difference = MAX(originalWidth - [self frame].size.width - dividerExtraSpace, 0.0),
|
||||
remainingWidth = FLOOR(difference / _segments.length),
|
||||
widthOfAllSegments = 0;
|
||||
|
||||
for (var i = 0; i < _segments.length; i++)
|
||||
{
|
||||
_themeStates[i] = [_segments[i] selected] ? CPThemeStateSelected : CPThemeStateNormal;
|
||||
[self tileWithChangedSegment:i];
|
||||
[self setWidth:[_segments[i] width] + remainingWidth forSegment:i];
|
||||
widthOfAllSegments += [_segments[i] width];
|
||||
}
|
||||
|
||||
var difference = MAX(originalWidth - [self frame].size.width, 0.0),
|
||||
remainingWidth = FLOOR(difference / _segments.length);
|
||||
// Here we handle the leftovers pixel, and we will add one pixel to each segment cell till we have the same size as the originalSize.
|
||||
// This is needed to have a perfect/same alignment between our application and xCode.
|
||||
var leftOversPixel = originalWidth - (widthOfAllSegments + dividerExtraSpace);
|
||||
|
||||
for (var i = 0; i < _segments.length; i++)
|
||||
[self setWidth:[_segments[i] width] + remainingWidth forSegment:i];
|
||||
// Make sure we don't make an out of range
|
||||
if (leftOversPixel < _segments.length - 1)
|
||||
{
|
||||
for (var i = 0; i < leftOversPixel; i++)
|
||||
{
|
||||
[self setWidth:[_segments[i] width] + 1 forSegment:i];
|
||||
}
|
||||
}
|
||||
|
||||
[self setFrameSize:CGSizeMake(originalWidth, [self frame].size.height)];
|
||||
[self tileWithChangedSegment:0];
|
||||
}
|
||||
|
||||
@@ -944,31 +972,48 @@ var CPSegmentedControlSegmentsKey = "CPSegmentedControlSegmentsKey",
|
||||
|
||||
@end
|
||||
|
||||
var CPSegmentedControlBindersMap = {},
|
||||
CPSegmentedControlNoSelectionPlaceholder = "CPSegmentedControlNoSelectionPlaceholder";
|
||||
@implementation CPSegmentedControl (BindingSupport)
|
||||
|
||||
+ (Class)_binderClassForBinding:(CPString)aBinding
|
||||
{
|
||||
if ([self _isSelectionBinding:aBinding])
|
||||
return [_CPSegmentedControlBinder class];
|
||||
|
||||
return [super _binderClassForBinding:aBinding];
|
||||
}
|
||||
|
||||
+ (BOOL)_isSelectionBinding:(CPString)aBinding
|
||||
{
|
||||
return (aBinding === CPSelectedIndexBinding || aBinding === CPSelectedLabelBinding || aBinding === CPSelectedTagBinding);
|
||||
}
|
||||
|
||||
+ (BOOL)isBindingExclusive:(CPString)aBinding
|
||||
{
|
||||
return [self _isSelectionBinding:aBinding];
|
||||
}
|
||||
|
||||
- (void)bind:(CPString)aBinding toObject:(id)anObject withKeyPath:(CPString)aKeyPath options:(CPDictionary)options
|
||||
{
|
||||
if ([[self class] _isSelectionBinding:aBinding] && _trackingMode !== CPSegmentSwitchTrackingSelectOne)
|
||||
{
|
||||
CPLog.warn("Binding " + aBinding + " needs CPSegmentSwitchTrackingSelectOne tracking mode");
|
||||
return;
|
||||
}
|
||||
|
||||
[super bind:aBinding toObject:anObject withKeyPath:aKeyPath options:options];
|
||||
}
|
||||
|
||||
- (void)_reverseSetBinding
|
||||
{
|
||||
[_CPSegmentedControlBinder _reverseSetValueFromExclusiveBinderForObject:self];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
var CPSegmentedControlNoSelectionPlaceholder = "CPSegmentedControlNoSelectionPlaceholder";
|
||||
|
||||
@implementation _CPSegmentedControlBinder : CPBinder
|
||||
{
|
||||
CPString _selectionBinding @accessors(readonly, getter=selectionBinding);
|
||||
}
|
||||
|
||||
+ (void)reverseSetValueForObject:(id)aSource
|
||||
{
|
||||
var binder = CPSegmentedControlBindersMap[[aSource UID]];
|
||||
[binder reverseSetValueFor:[binder selectionBinding]];
|
||||
}
|
||||
|
||||
- (id)initWithBinding:(CPString)aBinding name:(CPString)aName to:(id)aDestination keyPath:(CPString)aKeyPath options:(CPDictionary)options from:(id)aSource
|
||||
{
|
||||
self = [super initWithBinding:aBinding name:aName to:aDestination keyPath:aKeyPath options:options from:aSource];
|
||||
|
||||
if (self)
|
||||
{
|
||||
CPSegmentedControlBindersMap[[aSource UID]] = self;
|
||||
_selectionBinding = aName;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)_updatePlaceholdersWithOptions:(CPDictionary)options
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
|
||||
@import <Foundation/CPObject.j>
|
||||
|
||||
@import "CGGeometry.j"
|
||||
@import "CPColor.j"
|
||||
@import "CPGraphicsContext.j"
|
||||
|
||||
/*!
|
||||
@deprecated
|
||||
@@ -31,9 +34,9 @@
|
||||
*/
|
||||
@implementation CPShadow : CPObject
|
||||
{
|
||||
CGSize _offset @accessors(property=shadowOffset);
|
||||
CGSize _offset @accessors(property=shadowOffset);
|
||||
float _blurRadius @accessors(property=shadowBlurRadius);
|
||||
CPColor _color @accessors(property=shadowColor);
|
||||
CPColor _color @accessors(property=shadowColor);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
@import "CPImage.j"
|
||||
@import "CPView.j"
|
||||
|
||||
|
||||
@typedef CPShadowWeight
|
||||
CPLightShadow = 0;
|
||||
CPHeavyShadow = 1;
|
||||
|
||||
|
||||
@@ -23,6 +23,18 @@
|
||||
@import <Foundation/CPObject.j>
|
||||
@import <Foundation/CPRunLoop.j>
|
||||
|
||||
@typedef HTMLAudioElement
|
||||
|
||||
@protocol CPSoundDelegate <CPObject>
|
||||
|
||||
@optional
|
||||
- (void)sound:(CPSound)aSound didFinishPlaying:(BOOL)finishedLoading;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
var CPSoundDelegate_sound_didFinishPlaying_ = 1 << 1;
|
||||
|
||||
CPSoundLoadStateEmpty = 0;
|
||||
CPSoundLoadStateLoading = 1;
|
||||
CPSoundLoadStateCanBePlayed = 2;
|
||||
@@ -50,6 +62,7 @@ CPSoundPlayBackStatePause = 2;
|
||||
HTMLAudioElement _audioTag;
|
||||
int _loadStatus;
|
||||
int _playBackStatus;
|
||||
unsigned _implementedDelegateMethods;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
@@ -133,6 +146,25 @@ CPSoundPlayBackStatePause = 2;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Delegate methods
|
||||
|
||||
/*!
|
||||
Sets the sound's delegate.
|
||||
@param aDelegate the new delegate
|
||||
*/
|
||||
- (void)setDelegate:(id)aDelegate
|
||||
{
|
||||
if (_delegate === aDelegate)
|
||||
return;
|
||||
|
||||
_delegate = aDelegate;
|
||||
_implementedDelegateMethods = 0;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(sound:didFinishPlaying:)])
|
||||
_implementedDelegateMethods |= CPSoundDelegate_sound_didFinishPlaying_;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Events listener
|
||||
|
||||
@@ -207,8 +239,7 @@ CPSoundPlayBackStatePause = 2;
|
||||
_audioTag.currentTime = 0.0;
|
||||
_playBackStatus = CPSoundPlayBackStateStop;
|
||||
|
||||
if (_delegate && [_delegate respondsToSelector:@selector(sound:didFinishPlaying:)])
|
||||
[_delegate sound:self didFinishPlaying:YES];
|
||||
[self _sendDelegateSoundDidFinishPlaying:YES];
|
||||
|
||||
return YES;
|
||||
}
|
||||
@@ -316,3 +347,20 @@ CPSoundPlayBackStatePause = 2;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation CPSound (CPSoundDelegate)
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call delegate sound:didFinishPlaying:
|
||||
*/
|
||||
- (void)_sendDelegateSoundDidFinishPlaying:(BOOL)finishedPlaying
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPSoundDelegate_sound_didFinishPlaying_))
|
||||
return;
|
||||
|
||||
[_delegate sound:self didFinishPlaying:finishedPlaying];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -30,6 +30,33 @@
|
||||
@class CPUserDefaults
|
||||
@global CPApp
|
||||
|
||||
@protocol CPSplitViewDelegate <CPObject>
|
||||
|
||||
@optional
|
||||
- (BOOL)splitView:(CPSplitView)splitView canCollapseSubview:(CPView)subview;
|
||||
- (BOOL)splitView:(CPSplitView)splitView shouldAdjustSizeOfSubview:(CPView)subview;
|
||||
- (BOOL)splitView:(CPSplitView)splitView shouldCollapseSubview:(CPView)subview forDoubleClickOnDividerAtIndex:(CPInteger)dividerIndex;
|
||||
- (CGRect)splitView:(CPSplitView)splitView additionalEffectiveRectOfDividerAtIndex:(CPInteger)dividerIndex;
|
||||
- (CGRect)splitView:(CPSplitView)splitView effectiveRect:(CGRect)proposedEffectiveRect forDrawnRect:(CGRect)drawnRect ofDividerAtIndex:(CPInteger)dividerIndex;
|
||||
- (float)splitView:(CPSplitView)splitView constrainMaxCoordinate:(float)proposedMax ofSubviewAt:(CPInteger)dividerIndex;
|
||||
- (float)splitView:(CPSplitView)splitView constrainMinCoordinate:(float)proposedMin ofSubviewAt:(CPInteger)dividerIndex;
|
||||
- (float)splitView:(CPSplitView)splitView constrainSplitPosition:(float)proposedPosition ofSubviewAt:(CPInteger)dividerIndex;
|
||||
- (void)splitView:(CPSplitView)splitView resizeSubviewsWithOldSize:(CGSize)oldSize;
|
||||
- (void)splitViewDidResizeSubviews:(CPNotification)aNotification;
|
||||
- (void)splitViewWillResizeSubviews:(CPNotification)aNotification;
|
||||
|
||||
@end
|
||||
|
||||
var CPSplitViewDelegate_splitView_canCollapseSubview_ = 1 << 0,
|
||||
CPSplitViewDelegate_splitView_shouldAdjustSizeOfSubview_ = 1 << 1,
|
||||
CPSplitViewDelegate_splitView_shouldCollapseSubview_forDoubleClickOnDividerAtIndex_ = 1 << 2,
|
||||
CPSplitViewDelegate_splitView_additionalEffectiveRectOfDividerAtIndex_ = 1 << 3,
|
||||
CPSplitViewDelegate_splitView_effectiveRect_forDrawnRect_ofDividerAtIndex_ = 1 << 4,
|
||||
CPSplitViewDelegate_splitView_constrainMaxCoordinate_ofSubviewAt_ = 1 << 5,
|
||||
CPSplitViewDelegate_splitView_constrainMinCoordinate_ofSubviewAt_ = 1 << 6,
|
||||
CPSplitViewDelegate_splitView_constrainSplitPosition_ofSubviewAt_ = 1 << 7,
|
||||
CPSplitViewDelegate_splitView_resizeSubviewsWithOldSize_ = 1 << 8;
|
||||
|
||||
#define SPLIT_VIEW_MAYBE_POST_WILL_RESIZE() \
|
||||
if ((_suppressResizeNotificationsMask & DidPostWillResizeNotification) === 0) \
|
||||
{ \
|
||||
@@ -73,29 +100,31 @@ var ShouldSuppressResizeNotifications = 1,
|
||||
|
||||
@implementation CPSplitView : CPView
|
||||
{
|
||||
id _delegate;
|
||||
BOOL _isVertical;
|
||||
BOOL _isPaneSplitter;
|
||||
id <CPSplitViewDelegate> _delegate;
|
||||
BOOL _isVertical;
|
||||
BOOL _isPaneSplitter;
|
||||
|
||||
int _currentDivider;
|
||||
float _initialOffset;
|
||||
CPDictionary _preCollapsePositions;
|
||||
int _currentDivider;
|
||||
float _initialOffset;
|
||||
CPDictionary _preCollapsePositions;
|
||||
|
||||
CPString _originComponent;
|
||||
CPString _sizeComponent;
|
||||
CPString _originComponent;
|
||||
CPString _sizeComponent;
|
||||
|
||||
CPArray _DOMDividerElements;
|
||||
CPString _dividerImagePath;
|
||||
int _drawingDivider;
|
||||
CPArray _DOMDividerElements;
|
||||
CPString _dividerImagePath;
|
||||
int _drawingDivider;
|
||||
|
||||
CPString _autosaveName;
|
||||
BOOL _shouldAutosave;
|
||||
CGSize _shouldRestoreFromAutosaveUnlessFrameSize;
|
||||
CPString _autosaveName;
|
||||
BOOL _shouldAutosave;
|
||||
CGSize _shouldRestoreFromAutosaveUnlessFrameSize;
|
||||
|
||||
BOOL _needsResizeSubviews;
|
||||
int _suppressResizeNotificationsMask;
|
||||
BOOL _needsResizeSubviews;
|
||||
int _suppressResizeNotificationsMask;
|
||||
|
||||
CPArray _buttonBars;
|
||||
CPArray _buttonBars;
|
||||
|
||||
unsigned _implementedDelegateMethods;
|
||||
}
|
||||
|
||||
+ (CPString)defaultThemeClass
|
||||
@@ -406,11 +435,8 @@ var ShouldSuppressResizeNotifications = 1,
|
||||
buttonBarRect.origin = [self convertPoint:buttonBarRect.origin fromView:buttonBar];
|
||||
}
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(splitView:effectiveRect:forDrawnRect:ofDividerAtIndex:)])
|
||||
effectiveRect = [_delegate splitView:self effectiveRect:effectiveRect forDrawnRect:effectiveRect ofDividerAtIndex:anIndex];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(splitView:additionalEffectiveRectOfDividerAtIndex:)])
|
||||
additionalRect = [_delegate splitView:self additionalEffectiveRectOfDividerAtIndex:anIndex];
|
||||
effectiveRect = [self _sendDelegateSplitViewEffectiveRect:effectiveRect forDrawnRect:effectiveRect ofDividerAtIndex:anIndex];
|
||||
additionalRect = [self _sendDelegateSplitViewAdditionalEffectiveRectOfDividerAtIndex:anIndex];
|
||||
|
||||
return CGRectContainsPoint(effectiveRect, aPoint) ||
|
||||
(additionalRect && CGRectContainsPoint(additionalRect, aPoint)) ||
|
||||
@@ -472,21 +498,21 @@ var ShouldSuppressResizeNotifications = 1,
|
||||
if ([self cursorAtPoint:point hitDividerAtIndex:i])
|
||||
{
|
||||
if ([anEvent clickCount] == 2 &&
|
||||
[_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)] &&
|
||||
[_delegate respondsToSelector:@selector(splitView:shouldCollapseSubview:forDoubleClickOnDividerAtIndex:)])
|
||||
[self _delegateRespondsToSplitViewCanCollapseSubview] &&
|
||||
[self _delegateRespondsToSplitViewshouldCollapseSubviewForDoubleClickOnDividerAtIndex])
|
||||
{
|
||||
var minPosition = [self minPossiblePositionOfDividerAtIndex:i],
|
||||
maxPosition = [self maxPossiblePositionOfDividerAtIndex:i],
|
||||
preCollapsePosition = [_preCollapsePositions objectForKey:"" + i] || 0;
|
||||
|
||||
if ([_delegate splitView:self canCollapseSubview:_subviews[i]] && [_delegate splitView:self shouldCollapseSubview:_subviews[i] forDoubleClickOnDividerAtIndex:i])
|
||||
if ([self _sendDelegateSplitViewCanCollapseSubview:_subviews[i]] && [self _sendDelegateSplitViewShouldCollapseSubview:_subviews[i] forDoubleClickOnDividerAtIndex:i])
|
||||
{
|
||||
if ([self isSubviewCollapsed:_subviews[i]])
|
||||
[self setPosition:preCollapsePosition ? preCollapsePosition : (minPosition + (maxPosition - minPosition) / 2) ofDividerAtIndex:i];
|
||||
else
|
||||
[self setPosition:minPosition ofDividerAtIndex:i];
|
||||
}
|
||||
else if ([_delegate splitView:self canCollapseSubview:_subviews[i + 1]] && [_delegate splitView:self shouldCollapseSubview:_subviews[i + 1] forDoubleClickOnDividerAtIndex:i])
|
||||
else if ([self _sendDelegateSplitViewCanCollapseSubview:_subviews[i + 1]] && [self _sendDelegateSplitViewShouldCollapseSubview:_subviews[i + 1] forDoubleClickOnDividerAtIndex:i])
|
||||
{
|
||||
if ([self isSubviewCollapsed:_subviews[i + 1]])
|
||||
[self setPosition:preCollapsePosition ? preCollapsePosition : (minPosition + (maxPosition - minPosition) / 2) ofDividerAtIndex:i];
|
||||
@@ -580,12 +606,8 @@ var ShouldSuppressResizeNotifications = 1,
|
||||
|
||||
if (sizeA === 0)
|
||||
canGrow = YES; // Subview is collapsed.
|
||||
else if (!canShrink &&
|
||||
[_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)] &&
|
||||
[_delegate splitView:self canCollapseSubview:_subviews[i]])
|
||||
{
|
||||
else if (!canShrink && [self _sendDelegateSplitViewCanCollapseSubview:_subviews[i]])
|
||||
canShrink = YES; // Subview is collapsible.
|
||||
}
|
||||
|
||||
if (sizeB === 0)
|
||||
{
|
||||
@@ -594,9 +616,7 @@ var ShouldSuppressResizeNotifications = 1,
|
||||
// It's safe to assume it can always be uncollapsed.
|
||||
canShrink = YES;
|
||||
}
|
||||
else if (!canGrow &&
|
||||
[_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)] &&
|
||||
[_delegate splitView:self canCollapseSubview:_subviews[i + 1]])
|
||||
else if (!canGrow && [self _sendDelegateSplitViewCanCollapseSubview:_subviews[i + 1]])
|
||||
{
|
||||
canGrow = YES; // Right/lower subview is collapsible.
|
||||
}
|
||||
@@ -657,53 +677,38 @@ var ShouldSuppressResizeNotifications = 1,
|
||||
- (int)_realPositionForPosition:(float)position ofDividerAtIndex:(int)dividerIndex
|
||||
{
|
||||
// not sure where this should override other positions?
|
||||
if ([_delegate respondsToSelector:@selector(splitView:constrainSplitPosition:ofSubviewAt:)])
|
||||
{
|
||||
var proposedPosition = [_delegate splitView:self constrainSplitPosition:position ofSubviewAt:dividerIndex];
|
||||
var proposedPosition = [self _sendDelegateSplitViewConstrainSplitPosition:position ofSubviewAt:dividerIndex];
|
||||
|
||||
// Silently ignore bad positions which could result from odd delegate responses. We don't want these
|
||||
// bad results to go into the system and cause havoc with frame sizes as the split view tries to resize
|
||||
// its subviews.
|
||||
if (_IS_NUMERIC(proposedPosition))
|
||||
position = proposedPosition;
|
||||
}
|
||||
// Silently ignore bad positions which could result from odd delegate responses. We don't want these
|
||||
// bad results to go into the system and cause havoc with frame sizes as the split view tries to resize
|
||||
// its subviews.
|
||||
if (_IS_NUMERIC(proposedPosition))
|
||||
position = proposedPosition;
|
||||
|
||||
var proposedMax = [self maxPossiblePositionOfDividerAtIndex:dividerIndex],
|
||||
proposedMin = [self minPossiblePositionOfDividerAtIndex:dividerIndex],
|
||||
actualMax = proposedMax,
|
||||
actualMin = proposedMin;
|
||||
actualMin = proposedMin,
|
||||
proposedActualMin = [self _sendDelegateSplitViewConstrainMinCoordinate:proposedMin ofSubviewAt:dividerIndex],
|
||||
proposedActualMax = [self _sendDelegateSplitViewConstrainMaxCoordinate:proposedMax ofSubviewAt:dividerIndex];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(splitView:constrainMinCoordinate:ofSubviewAt:)])
|
||||
{
|
||||
var proposedActualMin = [_delegate splitView:self constrainMinCoordinate:proposedMin ofSubviewAt:dividerIndex];
|
||||
if (_IS_NUMERIC(proposedActualMin))
|
||||
actualMin = proposedActualMin;
|
||||
|
||||
if (_IS_NUMERIC(proposedActualMin))
|
||||
actualMin = proposedActualMin;
|
||||
}
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(splitView:constrainMaxCoordinate:ofSubviewAt:)])
|
||||
{
|
||||
var proposedActualMax = [_delegate splitView:self constrainMaxCoordinate:proposedMax ofSubviewAt:dividerIndex];
|
||||
|
||||
if (_IS_NUMERIC(proposedActualMax))
|
||||
actualMax = proposedActualMax;
|
||||
}
|
||||
if (_IS_NUMERIC(proposedActualMax))
|
||||
actualMax = proposedActualMax;
|
||||
|
||||
var viewA = _subviews[dividerIndex],
|
||||
viewB = _subviews[dividerIndex + 1],
|
||||
realPosition = MAX(MIN(position, actualMax), actualMin);
|
||||
|
||||
// Is this position past the halfway point to collapse?
|
||||
if (position < proposedMin + (actualMin - proposedMin) / 2)
|
||||
if ([_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)])
|
||||
if ([_delegate splitView:self canCollapseSubview:viewA])
|
||||
realPosition = proposedMin;
|
||||
if ((position < proposedMin + (actualMin - proposedMin) / 2) && [self _sendDelegateSplitViewCanCollapseSubview:viewA])
|
||||
realPosition = proposedMin;
|
||||
|
||||
// We can also collapse to the right.
|
||||
if (position > proposedMax - (proposedMax - actualMax) / 2)
|
||||
if ([_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)])
|
||||
if ([_delegate splitView:self canCollapseSubview:viewB])
|
||||
realPosition = proposedMax;
|
||||
if ((position > proposedMax - (proposedMax - actualMax) / 2) && [self _sendDelegateSplitViewCanCollapseSubview:viewB])
|
||||
realPosition = proposedMax;
|
||||
|
||||
return realPosition;
|
||||
}
|
||||
@@ -787,9 +792,9 @@ var ShouldSuppressResizeNotifications = 1,
|
||||
|
||||
- (void)resizeSubviewsWithOldSize:(CGSize)oldSize
|
||||
{
|
||||
if ([_delegate respondsToSelector:@selector(splitView:resizeSubviewsWithOldSize:)])
|
||||
if ([self _delegateRespondsToSplitViewResizeSubviewsWithOldSize])
|
||||
{
|
||||
[_delegate splitView:self resizeSubviewsWithOldSize:oldSize];
|
||||
[self _sendDelegateSplitViewResizeSubviewsWithOldSize:oldSize];
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -815,8 +820,7 @@ var ShouldSuppressResizeNotifications = 1,
|
||||
oldFlexibleSpace = 0,
|
||||
totalSizablePanes = 0,
|
||||
isSizableMap = {},
|
||||
viewSizes = [],
|
||||
delegateRespondsToShouldAdjust = [_delegate respondsToSelector:@selector(splitView:shouldAdjustSizeOfSubview:)];
|
||||
viewSizes = [];
|
||||
|
||||
// What we want to do is to preserve non resizable sizes first, and then to preserve the ratio of size to available
|
||||
// non fixed space for every other subview. E.g. assume fixed space was 20 pixels initially, view 1 was 20 and
|
||||
@@ -832,7 +836,7 @@ var ShouldSuppressResizeNotifications = 1,
|
||||
for (index = 0; index < count; ++index)
|
||||
{
|
||||
var view = _subviews[index],
|
||||
isSizable = !delegateRespondsToShouldAdjust || [_delegate splitView:self shouldAdjustSizeOfSubview:view],
|
||||
isSizable = [self _sendDelegateSplitViewShouldAdjustSizeOfSubview:view],
|
||||
size = [view frame].size[_sizeComponent];
|
||||
|
||||
isSizableMap[index] = isSizable;
|
||||
@@ -958,25 +962,59 @@ The sum of the views and the sum of the dividers should be equal to the size of
|
||||
|
||||
@param delegate - The delegate of the splitview.
|
||||
*/
|
||||
- (void)setDelegate:(id)delegate
|
||||
- (void)setDelegate:(id <CPSplitViewDelegate>)aDelegate
|
||||
{
|
||||
if (_delegate === aDelegate)
|
||||
return;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(splitViewDidResizeSubviews:)])
|
||||
[[CPNotificationCenter defaultCenter] removeObserver:_delegate name:CPSplitViewDidResizeSubviewsNotification object:self];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(splitViewWillResizeSubviews:)])
|
||||
[[CPNotificationCenter defaultCenter] removeObserver:_delegate name:CPSplitViewWillResizeSubviewsNotification object:self];
|
||||
|
||||
_delegate = delegate;
|
||||
_delegate = aDelegate;
|
||||
_implementedDelegateMethods = 0;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(splitViewDidResizeSubviews:)])
|
||||
[[CPNotificationCenter defaultCenter] addObserver:_delegate
|
||||
selector:@selector(splitViewDidResizeSubviews:)
|
||||
name:CPSplitViewDidResizeSubviewsNotification
|
||||
object:self];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(splitViewWillResizeSubviews:)])
|
||||
[[CPNotificationCenter defaultCenter] addObserver:_delegate
|
||||
selector:@selector(splitViewWillResizeSubviews:)
|
||||
name:CPSplitViewWillResizeSubviewsNotification
|
||||
object:self];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(splitView:canCollapseSubview:)])
|
||||
_implementedDelegateMethods |= CPSplitViewDelegate_splitView_canCollapseSubview_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(splitView:shouldAdjustSizeOfSubview:)])
|
||||
_implementedDelegateMethods |= CPSplitViewDelegate_splitView_shouldAdjustSizeOfSubview_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(splitView:shouldCollapseSubview:forDoubleClickOnDividerAtIndex:)])
|
||||
_implementedDelegateMethods |= CPSplitViewDelegate_splitView_shouldCollapseSubview_forDoubleClickOnDividerAtIndex_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(splitView:additionalEffectiveRectOfDividerAtIndex:)])
|
||||
_implementedDelegateMethods |= CPSplitViewDelegate_splitView_additionalEffectiveRectOfDividerAtIndex_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(splitView:effectiveRect:forDrawnRect:ofDividerAtIndex:)])
|
||||
_implementedDelegateMethods |= CPSplitViewDelegate_splitView_effectiveRect_forDrawnRect_ofDividerAtIndex_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(splitView:constrainMaxCoordinate:ofSubviewAt:)])
|
||||
_implementedDelegateMethods |= CPSplitViewDelegate_splitView_constrainMaxCoordinate_ofSubviewAt_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(splitView:constrainMinCoordinate:ofSubviewAt:)])
|
||||
_implementedDelegateMethods |= CPSplitViewDelegate_splitView_constrainMinCoordinate_ofSubviewAt_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(splitView:constrainSplitPosition:ofSubviewAt:)])
|
||||
_implementedDelegateMethods |= CPSplitViewDelegate_splitView_constrainSplitPosition_ofSubviewAt_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(splitView:resizeSubviewsWithOldSize:)])
|
||||
_implementedDelegateMethods |= CPSplitViewDelegate_splitView_resizeSubviewsWithOldSize_;
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -1192,6 +1230,148 @@ The sum of the views and the sum of the dividers should be equal to the size of
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation CPSplitView (CPSplitViewDelegate)
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Return YES if the delegate implements splitView:resizeSubviewsWithOldSize:
|
||||
*/
|
||||
- (BOOL)_delegateRespondsToSplitViewResizeSubviewsWithOldSize
|
||||
{
|
||||
return _implementedDelegateMethods & CPSplitViewDelegate_splitView_resizeSubviewsWithOldSize_;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Return YES if the delegate implements splitView:canCollapseSubview:
|
||||
*/
|
||||
- (BOOL)_delegateRespondsToSplitViewCanCollapseSubview
|
||||
{
|
||||
return _implementedDelegateMethods & CPSplitViewDelegate_splitView_canCollapseSubview_;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Return YES if the delegate implements splitView:shouldCollapseSubview:forDoubleClickOnDividerAtIndex
|
||||
*/
|
||||
- (BOOL)_delegateRespondsToSplitViewshouldCollapseSubviewForDoubleClickOnDividerAtIndex
|
||||
{
|
||||
return _implementedDelegateMethods & CPSplitViewDelegate_splitView_shouldCollapseSubview_forDoubleClickOnDividerAtIndex_;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call the delegate splitView:canCollapseSubview:
|
||||
*/
|
||||
- (BOOL)_sendDelegateSplitViewCanCollapseSubview:(CPView)aView
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPSplitViewDelegate_splitView_canCollapseSubview_))
|
||||
return NO;
|
||||
|
||||
return [_delegate splitView:self canCollapseSubview:aView];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call the delegate splitView:shouldAdjustSizeOfSubview:
|
||||
*/
|
||||
- (BOOL)_sendDelegateSplitViewShouldAdjustSizeOfSubview:(CPView)aView
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPSplitViewDelegate_splitView_shouldAdjustSizeOfSubview_))
|
||||
return YES;
|
||||
|
||||
return [_delegate splitView:self shouldAdjustSizeOfSubview:aView];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call the delegate splitView:shouldCollapseSubview:forDoubleClickOnDividerAtIndex:
|
||||
*/
|
||||
- (BOOL)_sendDelegateSplitViewShouldCollapseSubview:(CPView)aView forDoubleClickOnDividerAtIndex:(int)anIndex
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPSplitViewDelegate_splitView_shouldCollapseSubview_forDoubleClickOnDividerAtIndex_))
|
||||
return NO;
|
||||
|
||||
return [_delegate splitView:self shouldCollapseSubview:aView forDoubleClickOnDividerAtIndex:anIndex];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call the delegate splitView:additionalEffectiveRectOfDividerAtIndex:
|
||||
*/
|
||||
- (CGRect)_sendDelegateSplitViewAdditionalEffectiveRectOfDividerAtIndex:(int)anIndex
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPSplitViewDelegate_splitView_additionalEffectiveRectOfDividerAtIndex_))
|
||||
return nil;
|
||||
|
||||
return [_delegate splitView:self additionalEffectiveRectOfDividerAtIndex:anIndex];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call the delegate splitView:effectiveRect:forDrawnRect:ofDividerAtIndex:
|
||||
*/
|
||||
- (CGRect)_sendDelegateSplitViewEffectiveRect:(CGRect)proposedEffectiveRect forDrawnRect:(CGRect)drawnRect ofDividerAtIndex:(CPInteger)dividerIndex
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPSplitViewDelegate_splitView_effectiveRect_forDrawnRect_ofDividerAtIndex_))
|
||||
return proposedEffectiveRect;
|
||||
|
||||
return [_delegate splitView:self effectiveRect:proposedEffectiveRect forDrawnRect:drawnRect ofDividerAtIndex:dividerIndex];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call the delegate splitView:constrainMaxCoordinate:ofSubviewAt:
|
||||
*/
|
||||
- (float)_sendDelegateSplitViewConstrainMaxCoordinate:(float)proposedMax ofSubviewAt:(CPInteger)dividerIndex
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPSplitViewDelegate_splitView_constrainMaxCoordinate_ofSubviewAt_))
|
||||
return nil;
|
||||
|
||||
return [_delegate splitView:self constrainMaxCoordinate:proposedMax ofSubviewAt:dividerIndex];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call the delegate splitView:constrainMinCoordinate:ofSubviewAt:
|
||||
*/
|
||||
- (float)_sendDelegateSplitViewConstrainMinCoordinate:(float)proposedMin ofSubviewAt:(CPInteger)dividerIndex
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPSplitViewDelegate_splitView_constrainMinCoordinate_ofSubviewAt_))
|
||||
return nil;
|
||||
|
||||
return [_delegate splitView:self constrainMinCoordinate:proposedMin ofSubviewAt:dividerIndex];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call the delegate splitView:constrainSplitPosition:ofSubviewAt:
|
||||
*/
|
||||
- (float)_sendDelegateSplitViewConstrainSplitPosition:(float)proposedMax ofSubviewAt:(CPInteger)dividerIndex
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPSplitViewDelegate_splitView_constrainSplitPosition_ofSubviewAt_))
|
||||
return nil;
|
||||
|
||||
return [_delegate splitView:self constrainSplitPosition:proposedMax ofSubviewAt:dividerIndex];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call the delegate splitView:resizeSubviewsWithOldSize:
|
||||
*/
|
||||
- (void)_sendDelegateSplitViewResizeSubviewsWithOldSize:(CGSize)oldSize
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPSplitViewDelegate_splitView_resizeSubviewsWithOldSize_))
|
||||
return;
|
||||
|
||||
[_delegate splitView:self resizeSubviewsWithOldSize:oldSize];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
var CPSplitViewDelegateKey = "CPSplitViewDelegateKey",
|
||||
CPSplitViewIsVerticalKey = "CPSplitViewIsVerticalKey",
|
||||
CPSplitViewIsPaneSplitterKey = "CPSplitViewIsPaneSplitterKey",
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
@import "CPTextField.j"
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
CPStepper is an implementation of Cocoa NSStepper.
|
||||
|
||||
@@ -53,9 +52,9 @@
|
||||
@param maxValue the maximal acceptable value of the stepper
|
||||
@return Initialized CPStepper
|
||||
*/
|
||||
+ (CPStepper)stepperWithInitialValue:(float)aValue minValue:(float)aMinValue maxValue:(float)aMaxValue
|
||||
+ (id)stepperWithInitialValue:(float)aValue minValue:(float)aMinValue maxValue:(float)aMaxValue
|
||||
{
|
||||
var stepper = [[CPStepper alloc] initWithFrame:CGRectMakeZero()];
|
||||
var stepper = [[self alloc] initWithFrame:CGRectMakeZero()];
|
||||
|
||||
[stepper setDoubleValue:aValue];
|
||||
[stepper setMinValue:aMinValue];
|
||||
@@ -75,14 +74,14 @@
|
||||
|
||||
@return Initialized CPStepper
|
||||
*/
|
||||
+ (CPStepper)stepper
|
||||
+ (id)stepper
|
||||
{
|
||||
return [CPStepper stepperWithInitialValue:0.0 minValue:0.0 maxValue:59.0];
|
||||
}
|
||||
|
||||
+ (Class)_binderClassForBinding:(CPString)aBinding
|
||||
{
|
||||
if (aBinding == CPValueBinding || aBinding == CPMinValueBinding || aBinding == CPMaxValueBinding)
|
||||
if (aBinding === CPValueBinding || aBinding === CPMinValueBinding || aBinding === CPMaxValueBinding)
|
||||
return [_CPStepperValueBinder class];
|
||||
|
||||
return [super _binderClassForBinding:aBinding];
|
||||
@@ -90,7 +89,7 @@
|
||||
|
||||
- (CPString)_replacementKeyPathForBinding:(CPString)aBinding
|
||||
{
|
||||
if (aBinding == CPValueBinding)
|
||||
if (aBinding === CPValueBinding)
|
||||
return @"doubleValue";
|
||||
|
||||
return [super _replacementKeyPathForBinding:aBinding];
|
||||
@@ -138,9 +137,16 @@
|
||||
[self setContinuous:_autorepeat];
|
||||
[self addSubview:_buttonDown];
|
||||
|
||||
[self _sizeToFit];
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (void)setControlSize:(CPControlSize)aControlSize
|
||||
{
|
||||
[super setControlSize:aControlSize];
|
||||
[self _sizeToFit];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Superclass overrides
|
||||
|
||||
@@ -159,8 +165,8 @@
|
||||
|
||||
- (void)setFrame:(CGRect)aFrame
|
||||
{
|
||||
var upSize = [self valueForThemeAttribute:@"up-button-size"],
|
||||
downSize = [self valueForThemeAttribute:@"down-button-size"],
|
||||
var upSize = [self currentValueForThemeAttribute:@"up-button-size"],
|
||||
downSize = [self currentValueForThemeAttribute:@"down-button-size"],
|
||||
minSize = CGSizeMake(upSize.width, upSize.height + downSize.height),
|
||||
frame = CGRectMakeCopy(aFrame);
|
||||
|
||||
@@ -172,21 +178,22 @@
|
||||
/*! @ignore */
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
var aFrame = [self frame],
|
||||
upSize = [self valueForThemeAttribute:@"up-button-size"],
|
||||
downSize = [self valueForThemeAttribute:@"down-button-size"],
|
||||
upFrame = CGRectMake(aFrame.size.width - upSize.width, 0, upSize.width, upSize.height),
|
||||
downFrame = CGRectMake(aFrame.size.width - downSize.width, upSize.height, downSize.width, downSize.height);
|
||||
var controlSizeThemeState = [self _controlSizeThemeState],
|
||||
aFrame = [self frame],
|
||||
upSize = [self valueForThemeAttribute:@"up-button-size" inState:controlSizeThemeState],
|
||||
downSize = [self valueForThemeAttribute:@"down-button-size" inState:controlSizeThemeState],
|
||||
upFrame = CGRectMake(0, 0, upSize.width, upSize.height),
|
||||
downFrame = CGRectMake(0, upSize.height, downSize.width, downSize.height);
|
||||
|
||||
[_buttonUp setFrame:upFrame];
|
||||
[_buttonDown setFrame:downFrame];
|
||||
|
||||
[_buttonUp setValue:[self valueForThemeAttribute:@"bezel-color-up-button" inState:CPThemeStateBordered] forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered];
|
||||
[_buttonUp setValue:[self valueForThemeAttribute:@"bezel-color-up-button" inState:CPThemeStateBordered | CPThemeStateDisabled] forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered | CPThemeStateDisabled];
|
||||
[_buttonUp setValue:[self valueForThemeAttribute:@"bezel-color-up-button" inState:CPThemeStateBordered | CPThemeStateHighlighted] forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered | CPThemeStateHighlighted];
|
||||
[_buttonDown setValue:[self valueForThemeAttribute:@"bezel-color-down-button" inState:CPThemeStateBordered] forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered];
|
||||
[_buttonDown setValue:[self valueForThemeAttribute:@"bezel-color-down-button" inState:CPThemeStateBordered | CPThemeStateDisabled] forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered | CPThemeStateDisabled];
|
||||
[_buttonDown setValue:[self valueForThemeAttribute:@"bezel-color-down-button" inState:CPThemeStateBordered | CPThemeStateHighlighted] forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered | CPThemeStateHighlighted];
|
||||
[_buttonUp setValue:[self valueForThemeAttribute:@"bezel-color-up-button" inState:[controlSizeThemeState, CPThemeStateBordered]] forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered];
|
||||
[_buttonUp setValue:[self valueForThemeAttribute:@"bezel-color-up-button" inState:[controlSizeThemeState, CPThemeStateBordered, CPThemeStateDisabled]] forThemeAttribute:@"bezel-color" inState:[CPThemeStateBordered, CPThemeStateDisabled]];
|
||||
[_buttonUp setValue:[self valueForThemeAttribute:@"bezel-color-up-button" inState:[controlSizeThemeState, CPThemeStateBordered, CPThemeStateHighlighted]] forThemeAttribute:@"bezel-color" inState:[CPThemeStateBordered, CPThemeStateHighlighted]];
|
||||
[_buttonDown setValue:[self valueForThemeAttribute:@"bezel-color-down-button" inState:[controlSizeThemeState, CPThemeStateBordered]] forThemeAttribute:@"bezel-color" inState:CPThemeStateBordered];
|
||||
[_buttonDown setValue:[self valueForThemeAttribute:@"bezel-color-down-button" inState:[controlSizeThemeState, CPThemeStateBordered, CPThemeStateDisabled]] forThemeAttribute:@"bezel-color" inState:[CPThemeStateBordered, CPThemeStateDisabled]];
|
||||
[_buttonDown setValue:[self valueForThemeAttribute:@"bezel-color-down-button" inState:[controlSizeThemeState, CPThemeStateBordered, CPThemeStateHighlighted]] forThemeAttribute:@"bezel-color" inState:[CPThemeStateBordered, CPThemeStateHighlighted]];
|
||||
}
|
||||
|
||||
- (void)_sizeToFit
|
||||
@@ -232,7 +239,7 @@
|
||||
if (![self isEnabled])
|
||||
return;
|
||||
|
||||
if (aSender == _buttonUp)
|
||||
if (aSender === _buttonUp)
|
||||
[self setDoubleValue:([self doubleValue] + _increment)];
|
||||
else
|
||||
[self setDoubleValue:([self doubleValue] - _increment)];
|
||||
@@ -285,7 +292,7 @@
|
||||
|
||||
- (void)_updatePlaceholdersWithOptions:(CPDictionary)options forBinding:(CPString)aBinding
|
||||
{
|
||||
var placeholder = (aBinding == CPMaxValueBinding) ? [_source maxValue] : [_source minValue];
|
||||
var placeholder = (aBinding === CPMaxValueBinding) ? [_source maxValue] : [_source minValue];
|
||||
|
||||
[super _updatePlaceholdersWithOptions:options];
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
@import "CPTabViewItem.j"
|
||||
@import "CPView.j"
|
||||
|
||||
@typedef CPTabViewType
|
||||
CPTopTabsBezelBorder = 0;
|
||||
//CPLeftTabsBezelBorder = 1;
|
||||
CPBottomTabsBezelBorder = 2;
|
||||
@@ -33,10 +34,22 @@ CPNoTabsBezelBorder = 4; //Displays no tabs and has a bezeled border.
|
||||
CPNoTabsLineBorder = 5; //Has no tabs and displays a line border.
|
||||
CPNoTabsNoBorder = 6; //Displays no tabs and no border.
|
||||
|
||||
var CPTabViewDidSelectTabViewItemSelector = 1,
|
||||
CPTabViewShouldSelectTabViewItemSelector = 2,
|
||||
CPTabViewWillSelectTabViewItemSelector = 4,
|
||||
CPTabViewDidChangeNumberOfTabViewItemsSelector = 8;
|
||||
var CPTabViewDidSelectTabViewItemSelector = 1 << 1,
|
||||
CPTabViewShouldSelectTabViewItemSelector = 1 << 2,
|
||||
CPTabViewWillSelectTabViewItemSelector = 1 << 3,
|
||||
CPTabViewDidChangeNumberOfTabViewItemsSelector = 1 << 4;
|
||||
|
||||
|
||||
@protocol CPTabViewDelegate <CPObject>
|
||||
|
||||
@optional
|
||||
- (BOOL)tabView:(CPTabView)tabView shouldSelectTabViewItem:(CPTabViewItem)tabViewItem;
|
||||
- (void)tabView:(CPTabView)tabView didSelectTabViewItem:(CPTabViewItem)tabViewItem;
|
||||
- (void)tabView:(CPTabView)tabView willSelectTabViewItem:(CPTabViewItem)tabViewItem;
|
||||
- (void)tabViewDidChangeNumberOfTabViewItems:(CPTabView)tabView;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@@ -48,18 +61,18 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
|
||||
*/
|
||||
@implementation CPTabView : CPView
|
||||
{
|
||||
CPArray _items;
|
||||
CPArray _items;
|
||||
|
||||
CPSegmentedControl _tabs;
|
||||
CPBox _box;
|
||||
CPSegmentedControl _tabs;
|
||||
CPBox _box;
|
||||
|
||||
CPNumber _selectedIndex;
|
||||
CPNumber _selectedIndex;
|
||||
|
||||
CPTabViewType _type;
|
||||
CPFont _font;
|
||||
CPTabViewType _type;
|
||||
CPFont _font;
|
||||
|
||||
id _delegate;
|
||||
unsigned _delegateSelectors;
|
||||
id <CPTabViewDelegate> _delegate;
|
||||
unsigned _delegateSelectors;
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)aFrame
|
||||
@@ -82,7 +95,7 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
|
||||
_tabs = [[CPSegmentedControl alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
|
||||
[_tabs setHitTests:NO];
|
||||
|
||||
var height = [_tabs valueForThemeAttribute:@"default-height"];
|
||||
var height = [_tabs valueForThemeAttribute:@"min-size"].height;
|
||||
[_tabs setFrameSize:CGSizeMake(0, height)];
|
||||
|
||||
_box = [[CPBox alloc] initWithFrame:[self bounds]];
|
||||
@@ -379,6 +392,7 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
|
||||
[_box setFrame:CGRectMake(0, origin, CGRectGetWidth(aFrame),
|
||||
CGRectGetHeight(aFrame) - segmentedHeight / 2)];
|
||||
|
||||
[self _updateItems];
|
||||
[self _repositionTabs];
|
||||
}
|
||||
}
|
||||
@@ -405,7 +419,7 @@ var CPTabViewDidSelectTabViewItemSelector = 1,
|
||||
Sets the delegate for this tab view.
|
||||
@param aDelegate the tab view's delegate
|
||||
*/
|
||||
- (void)setDelegate:(id)aDelegate
|
||||
- (void)setDelegate:(id <CPTabViewDelegate>)aDelegate
|
||||
{
|
||||
if (_delegate == aDelegate)
|
||||
return;
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
@import <Foundation/CPObject.j>
|
||||
|
||||
@import "CPView.j"
|
||||
|
||||
@class CPTabView
|
||||
|
||||
/*
|
||||
The tab is currently selected.
|
||||
@@ -90,6 +90,7 @@ CPPressedTab = 2;
|
||||
- (void)setLabel:(CPString)aLabel
|
||||
{
|
||||
_label = aLabel;
|
||||
[_tabView setNeedsLayout];
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -28,9 +28,8 @@
|
||||
|
||||
@import "CPTextField.j"
|
||||
|
||||
@global CPTableViewColumnDidResizeNotification
|
||||
|
||||
@class _CPTableColumnHeaderView
|
||||
@class CPTableView
|
||||
|
||||
CPTableColumnNoResizing = 0;
|
||||
CPTableColumnAutoresizingMask = 1 << 0;
|
||||
@@ -185,7 +184,7 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
[tableView tile];
|
||||
|
||||
if (!_disableResizingPosting)
|
||||
[self _postDidResizeNotificationWithOldWidth:oldWidth];
|
||||
[[self tableView] _didResizeTableColumn:self oldWidth:oldWidth];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -538,19 +537,6 @@ CPTableColumnUserResizingMask = 1 << 1;
|
||||
return _headerToolTip;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (void)_postDidResizeNotificationWithOldWidth:(float)oldWidth
|
||||
{
|
||||
[[self tableView] _didResizeTableColumn:self];
|
||||
|
||||
[[CPNotificationCenter defaultCenter]
|
||||
postNotificationName:CPTableViewColumnDidResizeNotification
|
||||
object:[self tableView]
|
||||
userInfo:@{ @"CPTableColumn": self, @"CPOldWidth": oldWidth }];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPTableColumnValueBinder : CPBinder
|
||||
|
||||
@@ -625,7 +625,7 @@ var _CPTableColumnHeaderViewStringValueKey = @"_CPTableColumnHeaderViewStringVal
|
||||
- (void)stopResizingTableColumn:(CPInteger)aColumnIndex at:(CGPoint)aPoint
|
||||
{
|
||||
var tableColumn = [[_tableView tableColumns] objectAtIndex:aColumnIndex];
|
||||
[tableColumn _postDidResizeNotificationWithOldWidth:_columnOldWidth];
|
||||
[_tableView _didResizeTableColumn:tableColumn oldWidth:_columnOldWidth];
|
||||
[tableColumn setDisableResizingPosting:NO];
|
||||
[_tableView setDisableAutomaticResizing:NO];
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
@class CPTableHeaderView
|
||||
@class CPClipView
|
||||
@class CPButton
|
||||
@class _CPDropOperationDrawingView
|
||||
|
||||
@global CPApp
|
||||
|
||||
@@ -58,7 +59,6 @@ var CPTableViewDataSource_numberOfRowsInTableView_
|
||||
CPTableViewDataSource_tableView_namesOfPromisedFilesDroppedAtDestination_forDraggedRowsWithIndexes_ = 1 << 4,
|
||||
CPTableViewDataSource_tableView_validateDrop_proposedRow_proposedDropOperation_ = 1 << 5,
|
||||
CPTableViewDataSource_tableView_writeRowsWithIndexes_toPasteboard_ = 1 << 6,
|
||||
|
||||
CPTableViewDataSource_tableView_sortDescriptorsDidChange_ = 1 << 7;
|
||||
|
||||
var CPTableViewDelegate_selectionShouldChangeInTableView_ = 1 << 0,
|
||||
@@ -80,10 +80,13 @@ var CPTableViewDelegate_selectionShouldChangeInTableView_
|
||||
CPTableViewDelegate_tableView_toolTipForView_rect_tableColumn_row_mouseLocation_ = 1 << 16,
|
||||
CPTableViewDelegate_tableView_typeSelectStringForTableColumn_row_ = 1 << 17,
|
||||
CPTableViewDelegate_tableView_willDisplayView_forTableColumn_row_ = 1 << 18,
|
||||
CPTableViewDelegate_tableViewSelectionDidChange_ = 1 << 19,
|
||||
CPTableViewDelegate_tableViewSelectionIsChanging_ = 1 << 20,
|
||||
CPTableViewDelegate_tableViewMenuForTableColumn_row_ = 1 << 21,
|
||||
CPTableViewDelegate_tableView_shouldReorderColumn_toColumn_ = 1 << 22;
|
||||
CPTableViewDelegate_tableView_willRemoveView_forTableColumn_row_ = 1 << 19,
|
||||
CPTableViewDelegate_tableViewColumnDidMove_ = 1 << 20,
|
||||
CPTableViewDelegate_tableViewColumnDidResize_ = 1 << 21,
|
||||
CPTableViewDelegate_tableViewSelectionDidChange_ = 1 << 22,
|
||||
CPTableViewDelegate_tableViewSelectionIsChanging_ = 1 << 23,
|
||||
CPTableViewDelegate_tableViewMenuForTableColumn_row_ = 1 << 24,
|
||||
CPTableViewDelegate_tableView_shouldReorderColumn_toColumn_ = 1 << 25;
|
||||
|
||||
//CPTableViewDraggingDestinationFeedbackStyles
|
||||
CPTableViewDraggingDestinationFeedbackStyleNone = -1;
|
||||
@@ -116,14 +119,61 @@ CPTableViewLastColumnOnlyAutoresizingStyle = 4;
|
||||
CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
|
||||
#define NUMBER_OF_COLUMNS() (_tableColumns.length)
|
||||
#define UPDATE_COLUMN_RANGES_IF_NECESSARY() if (_dirtyTableColumnRangeIndex !== CPNotFound) [self _recalculateTableColumnRanges];
|
||||
#define UPDATE_COLUMN_RANGES_IF_NECESSARY() \
|
||||
if (_dirtyTableColumnRangeIndex !== CPNotFound) \
|
||||
[self _recalculateTableColumnRanges];
|
||||
#define FULL_ROW_HEIGHT() (_rowHeight + _intercellSpacing.height)
|
||||
#define ROW_BOTTOM(__heightInfo) (__heightInfo.y + __heightInfo.height + _intercellSpacing.height)
|
||||
#define HAS_VARIABLE_ROW_HEIGHTS() (_implementedDelegateMethods & CPTableViewDelegate_tableView_heightOfRow_)
|
||||
|
||||
|
||||
@protocol CPTableViewDataSource <CPObject>
|
||||
|
||||
@optional
|
||||
- (BOOL)tableView:(CPTableView)aTableView acceptDrop:(id <CPDraggingInfo>)info row:(CPInteger)aRowIndex dropOperation:(CPTableViewDropOperation)operation;
|
||||
- (BOOL)tableView:(CPTableView)aTableView writeRowsWithIndexes:(CPIndexSet)rowIndexes toPasteboard:(CPPasteboard)pboard;
|
||||
- (CPArray)tableView:(CPTableView)aTableView namesOfPromisedFilesDroppedAtDestination:(CPURL)dropDestination forDraggedRowsWithIndexes:(CPIndexSet)anIndexSet;
|
||||
- (CPDragOperation)tableView:(CPTableView)aTableView validateDrop:(id <CPDraggingInfo>)info proposedRow:(CPInteger)aRowIndex proposedDropOperation:(CPTableViewDropOperation)anOperation;
|
||||
- (CPInteger)numberOfRowsInTableView:(CPTableView)aTableView;
|
||||
- (id)tableView:(CPTableView)aTableView objectValueForTableColumn:(CPTableColumn)aTableColumn row:(CPInteger)aRowIndex;
|
||||
- (void)tableView:(CPTableView)aTableView setObjectValue:(id)anObjectValue forTableColumn:(CPTableColumn)aTableColumn row:(CPInteger)aRowIndex;
|
||||
- (void)tableView:(CPTableView)aTableView sortDescriptorsDidChange:(CPArray)oldDescriptors;
|
||||
|
||||
@end
|
||||
|
||||
@protocol CPTableViewDelegate <CPObject>
|
||||
|
||||
@optional
|
||||
- (BOOL)selectionShouldChangeInTableView:(CPTableView)aTableView;
|
||||
- (BOOL)tableView:(CPTableView)aTableView isGroupRow:(CPInteger)aRowIndex;
|
||||
- (BOOL)tableView:(CPTableView)aTableView shouldEditTableColumn:(CPTableColumn)aTableView row:(CPInteger)aRowIndex;
|
||||
- (BOOL)tableView:(CPTableView)aTableView shouldReorderColumn:(CPInteger)columnIndex toColumn:(NSInteger)newColumnIndex;
|
||||
- (BOOL)tableView:(CPTableView)aTableView shouldSelectRow:(CPInteger)aRowIndex;
|
||||
- (BOOL)tableView:(CPTableView)aTableView shouldSelectTableColumn:(CPTableColumn)aTableColumn;
|
||||
- (BOOL)tableView:(CPTableView)aTableView shouldShowViewExpansionForTableColumn:(CPTableColumn)aTableColumn row:(CPInteger)aRowIndex;
|
||||
- (BOOL)tableView:(CPTableView)aTableView shouldTrackView:(CPView)aView forTableColumn:(CPTableColumn)aTableColumn row:(CPInteger)aRowIndex;
|
||||
- (BOOL)tableView:(CPTableView)aTableView shouldTypeSelectForEvent:(CPEvent)anEvent withCurrentSearchString:(CPString)searchString;
|
||||
- (CPIndexSet)tableView:(CPTableView)aTableView selectionIndexesForProposedSelection:(CPIndexSet)proposedSelectionIndexes;
|
||||
- (CPInteger)tableView:(CPTableView)aTableView nextTypeSelectMatchFromRow:(CPInteger)startRow toRow:(CPInteger)endRow forString:(CPString)searchString;
|
||||
- (CPMenu)tableViewMenuForTableColumn:(CPTableColumn)aTableColumn row:(CPInteger)aRowIndex;
|
||||
- (CPString)tableView:(CPTableView)aTableView toolTipForView:(CPView)aView rect:(CGRect)aRect tableColumn:(CPTableColumn)aTableColumn row:(CPInteger)aRowIndex mouseLocation:(CGPoint)mouseLocation;
|
||||
- (CPString)tableView:(CPTableView)aTableView typeSelectStringForTableColumn:(CPTableColumn)aTableColumn row:(CPInteger)aRowIndex;
|
||||
- (CPView)tableView:(CPTableView)aTableView dataViewForTableColumn:(CPTableColumn)aTableColumn row:(CPInteger)aRowIndex;
|
||||
- (CPView)tableView:(CPTableView)aTableView viewForTableColumn:(CPTableColumn)aTableColumn row:(CPInteger)aRowIndex;
|
||||
- (float)tableView:(CPTableView)aTableView heightOfRow:(CPInteger)aRowIndex;
|
||||
- (void)tableView:(CPTableView)aTableView didClickTableColumn:(CPTableColumn)aTableColumn;
|
||||
- (void)tableView:(CPTableView)aTableView didDragTableColumn:(CPTableColumn)aTableColumn;
|
||||
- (void)tableView:(CPTableView)aTableView mouseDownInHeaderOfTableColumn:(CPTableColumn)aTableColumn;
|
||||
- (void)tableView:(CPTableView)aTableView willDisplayView:(CPView)aView forTableColumn:(CPTableColumn)aTableColumn row:(CPInteger)aRowIndex;
|
||||
- (void)tableView:(CPTableView)aTableView willRemoveView:(CPView)aView forTableColumn:(CPTableColumn)aTableColumn row:(CPInteger)aRowIndex;
|
||||
- (void)tableViewSelectionDidChange:(CPNotification)aNotification;
|
||||
- (void)tableViewSelectionIsChanging:(CPNotification)aNotification;
|
||||
|
||||
@end
|
||||
|
||||
@implementation _CPTableDrawView : CPView
|
||||
{
|
||||
CPTableView _tableView;
|
||||
id _tableView;
|
||||
}
|
||||
|
||||
- (id)initWithTableView:(CPTableView)aTableView
|
||||
@@ -173,106 +223,108 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
*/
|
||||
@implementation CPTableView : CPControl
|
||||
{
|
||||
id _dataSource;
|
||||
CPInteger _implementedDataSourceMethods;
|
||||
id <CPTableViewDataSource> _dataSource;
|
||||
CPInteger _implementedDataSourceMethods;
|
||||
|
||||
id _delegate;
|
||||
CPInteger _implementedDelegateMethods;
|
||||
id <CPTableViewDelegate> _delegate;
|
||||
CPInteger _implementedDelegateMethods;
|
||||
|
||||
CPArray _tableColumns;
|
||||
CPArray _tableColumnRanges;
|
||||
CPInteger _dirtyTableColumnRangeIndex;
|
||||
CPInteger _numberOfHiddenColumns;
|
||||
CPArray _tableColumns;
|
||||
CPArray _tableColumnRanges;
|
||||
CPInteger _dirtyTableColumnRangeIndex;
|
||||
CPInteger _numberOfHiddenColumns;
|
||||
|
||||
BOOL _reloadAllRows;
|
||||
Object _objectValues;
|
||||
BOOL _reloadAllRows;
|
||||
Object _objectValues;
|
||||
|
||||
CGRect _exposedRect;
|
||||
CPIndexSet _exposedRows;
|
||||
CPIndexSet _exposedColumns;
|
||||
CGRect _exposedRect;
|
||||
CPIndexSet _exposedRows;
|
||||
CPIndexSet _exposedColumns;
|
||||
|
||||
Object _dataViewsForTableColumns;
|
||||
Object _cachedDataViews;
|
||||
CPDictionary _archivedDataViews;
|
||||
Object _unavailable_custom_cibs;
|
||||
Object _dataViewsForTableColumns;
|
||||
Object _cachedDataViews;
|
||||
CPDictionary _archivedDataViews;
|
||||
Object _unavailable_custom_cibs;
|
||||
|
||||
//Configuring Behavior
|
||||
BOOL _allowsColumnReordering;
|
||||
BOOL _allowsColumnResizing;
|
||||
BOOL _allowsColumnSelection;
|
||||
BOOL _allowsMultipleSelection;
|
||||
BOOL _allowsEmptySelection;
|
||||
BOOL _allowsColumnReordering;
|
||||
BOOL _allowsColumnResizing;
|
||||
BOOL _allowsColumnSelection;
|
||||
BOOL _allowsMultipleSelection;
|
||||
BOOL _allowsEmptySelection;
|
||||
|
||||
CPArray _sortDescriptors;
|
||||
CPArray _sortDescriptors;
|
||||
|
||||
//Setting Display Attributes
|
||||
CGSize _intercellSpacing;
|
||||
float _rowHeight;
|
||||
CGSize _intercellSpacing;
|
||||
float _rowHeight;
|
||||
|
||||
BOOL _usesAlternatingRowBackgroundColors;
|
||||
CPArray _alternatingRowBackgroundColors;
|
||||
BOOL _usesAlternatingRowBackgroundColors;
|
||||
CPArray _alternatingRowBackgroundColors;
|
||||
|
||||
unsigned _selectionHighlightStyle;
|
||||
CPColor _unfocusedSelectionHighlightColor;
|
||||
CPDictionary _unfocusedSourceListSelectionColor;
|
||||
CPTableColumn _currentHighlightedTableColumn;
|
||||
unsigned _gridStyleMask;
|
||||
unsigned _selectionHighlightStyle;
|
||||
CPColor _unfocusedSelectionHighlightColor;
|
||||
CPDictionary _unfocusedSourceListSelectionColor;
|
||||
CPTableColumn _currentHighlightedTableColumn;
|
||||
unsigned _gridStyleMask;
|
||||
|
||||
unsigned _numberOfRows;
|
||||
CPIndexSet _groupRows;
|
||||
unsigned _numberOfRows;
|
||||
CPIndexSet _groupRows;
|
||||
|
||||
CPArray _cachedRowHeights;
|
||||
CPArray _cachedRowHeights;
|
||||
|
||||
// Persistence
|
||||
CPString _autosaveName;
|
||||
BOOL _autosaveTableColumns;
|
||||
CPString _autosaveName;
|
||||
BOOL _autosaveTableColumns;
|
||||
|
||||
CPTableHeaderView _headerView;
|
||||
_CPCornerView _cornerView;
|
||||
CPTableHeaderView _headerView;
|
||||
_CPCornerView _cornerView;
|
||||
|
||||
CPIndexSet _selectedColumnIndexes;
|
||||
CPIndexSet _selectedRowIndexes;
|
||||
CPInteger _selectionAnchorRow;
|
||||
CPInteger _lastSelectedRow;
|
||||
CPIndexSet _previouslySelectedRowIndexes;
|
||||
CGPoint _startTrackingPoint;
|
||||
CPDate _startTrackingTimestamp;
|
||||
BOOL _trackingPointMovedOutOfClickSlop;
|
||||
CGPoint _editingCellIndex;
|
||||
CPInteger _editingRow;
|
||||
CPInteger _editingColumn;
|
||||
CPIndexSet _selectedColumnIndexes;
|
||||
CPIndexSet _selectedRowIndexes;
|
||||
CPInteger _selectionAnchorRow;
|
||||
CPInteger _lastSelectedRow;
|
||||
CPIndexSet _previouslySelectedRowIndexes;
|
||||
CGPoint _startTrackingPoint;
|
||||
CPDate _startTrackingTimestamp;
|
||||
BOOL _trackingPointMovedOutOfClickSlop;
|
||||
CGPoint _editingCellIndex;
|
||||
CPInteger _editingRow;
|
||||
CPInteger _editingColumn;
|
||||
|
||||
_CPTableDrawView _tableDrawView;
|
||||
_CPTableDrawView _tableDrawView;
|
||||
|
||||
SEL _doubleAction;
|
||||
CPInteger _clickedRow;
|
||||
CPInteger _clickedColumn;
|
||||
unsigned _columnAutoResizingStyle;
|
||||
SEL _doubleAction;
|
||||
CPInteger _clickedRow;
|
||||
CPInteger _clickedColumn;
|
||||
unsigned _columnAutoResizingStyle;
|
||||
|
||||
int _lastTrackedRowIndex;
|
||||
CGPoint _originalMouseDownPoint;
|
||||
BOOL _verticalMotionCanDrag;
|
||||
unsigned _destinationDragStyle;
|
||||
BOOL _isSelectingSession;
|
||||
CPIndexSet _draggedRowIndexes;
|
||||
BOOL _wasSelectionBroken;
|
||||
int _lastTrackedRowIndex;
|
||||
CGPoint _originalMouseDownPoint;
|
||||
BOOL _verticalMotionCanDrag;
|
||||
unsigned _destinationDragStyle;
|
||||
BOOL _isSelectingSession;
|
||||
CPIndexSet _draggedRowIndexes;
|
||||
BOOL _wasSelectionBroken;
|
||||
|
||||
_CPDropOperationDrawingView _dropOperationFeedbackView;
|
||||
CPDragOperation _dragOperationDefaultMask;
|
||||
int _retargetedDropRow;
|
||||
CPDragOperation _retargetedDropOperation;
|
||||
CPArray _draggingViews;
|
||||
CPDragOperation _dragOperationDefaultMask;
|
||||
int _retargetedDropRow;
|
||||
CPDragOperation _retargetedDropOperation;
|
||||
CPArray _draggingViews;
|
||||
|
||||
BOOL _disableAutomaticResizing @accessors(property=disableAutomaticResizing);
|
||||
BOOL _lastColumnShouldSnap;
|
||||
BOOL _implementsCustomDrawRow;
|
||||
BOOL _isViewBased;
|
||||
BOOL _contentBindingExplicitlySet;
|
||||
BOOL _disableAutomaticResizing @accessors(property=disableAutomaticResizing);
|
||||
BOOL _lastColumnShouldSnap;
|
||||
BOOL _implementsCustomDrawRow;
|
||||
BOOL _isViewBased;
|
||||
BOOL _contentBindingExplicitlySet;
|
||||
|
||||
SEL _viewForTableColumnRowSelector;
|
||||
SEL _viewForTableColumnRowSelector;
|
||||
|
||||
CPTableColumn _draggedColumn;
|
||||
CPArray _differedColumnDataToRemove;
|
||||
CPTableColumn _draggedColumn;
|
||||
CPArray _differedColumnDataToRemove;
|
||||
|
||||
CPView _observedClipView;
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -426,8 +478,6 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5;
|
||||
|
||||
if (!_sortDescriptors)
|
||||
_sortDescriptors = [];
|
||||
|
||||
[self _startObservingFirstResponder];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -495,7 +545,7 @@ NOT YET IMPLEMENTED
|
||||
- (CPArray)tableView:(CPTableView)aTableView namesOfPromisedFilesDroppedAtDestination:(CPURL)dropDestination forDraggedRowsWithIndexes:(CPIndexSet)indexSet;
|
||||
@endcode
|
||||
*/
|
||||
- (void)setDataSource:(id)aDataSource
|
||||
- (void)setDataSource:(id <CPTableViewDataSource>)aDataSource
|
||||
{
|
||||
if (_dataSource === aDataSource)
|
||||
return;
|
||||
@@ -917,7 +967,7 @@ NOT YET IMPLEMENTED
|
||||
</pre>
|
||||
*/
|
||||
|
||||
- (void)unfocusedSelectionGradientColors
|
||||
- (CPColor)unfocusedSelectionGradientColors
|
||||
{
|
||||
if (!_unfocusedSourceListSelectionColor)
|
||||
{
|
||||
@@ -1121,6 +1171,9 @@ NOT YET IMPLEMENTED
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPTableViewColumnDidMoveNotification
|
||||
object:self
|
||||
userInfo:@{ @"CPOldColumn": fromIndex, @"CPNewColumn": toIndex }];
|
||||
|
||||
if (_implementedDelegateMethods & CPTableViewDelegate_tableViewColumnDidMove_)
|
||||
[_delegate tableViewColumnDidMove:[[CPNotification alloc] initWithName:CPTableViewColumnDidMoveNotification object:self userInfo:@{ @"CPOldColumn": fromIndex, @"CPNewColumn": toIndex }]];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -1199,9 +1252,17 @@ NOT YET IMPLEMENTED
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (void)_didResizeTableColumn:(CPTableColumn)theColumn
|
||||
- (void)_didResizeTableColumn:(CPTableColumn)theColumn oldWidth:(int)oldWidth
|
||||
{
|
||||
[self _autosave];
|
||||
|
||||
[[CPNotificationCenter defaultCenter]
|
||||
postNotificationName:CPTableViewColumnDidResizeNotification
|
||||
object:self
|
||||
userInfo:@{ @"CPTableColumn": theColumn, @"CPOldWidth": oldWidth }];
|
||||
|
||||
if (_implementedDelegateMethods & CPTableViewDelegate_tableViewColumnDidResize_)
|
||||
[_delegate tableViewColumnDidResize:[[CPNotification alloc] initWithName:CPTableViewColumnDidResizeNotification object:self userInfo:@{ @"CPTableColumn": theColumn, @"CPOldWidth": oldWidth }]];
|
||||
}
|
||||
|
||||
//Selecting Columns and Rows
|
||||
@@ -1298,6 +1359,38 @@ NOT YET IMPLEMENTED
|
||||
[self _setSelectedRowIndexes:newSelectedIndexes];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
cleanup a an indexset from the indexes that cannot be selected
|
||||
according to the table view delegate.
|
||||
*/
|
||||
- (CPIndexSet)_cleanUpSelectionRowIndexes:(CPIndexSet)anIndexSet
|
||||
{
|
||||
if ([self _delegateRespondsToSelectionIndexesForProposedSelection])
|
||||
{
|
||||
return [self _sendDelegateSelectionIndexesForProposedSelection:anIndexSet];
|
||||
}
|
||||
else if ([self _delegateRespondsToShouldSelectRow])
|
||||
{
|
||||
var indexesToRemove = [CPIndexSet new],
|
||||
currentIndex = [anIndexSet firstIndex];
|
||||
|
||||
while (currentIndex != CPNotFound)
|
||||
{
|
||||
if (![self _sendDelegateShouldSelectRow:currentIndex])
|
||||
[indexesToRemove addIndex:currentIndex];
|
||||
|
||||
currentIndex = [anIndexSet indexGreaterThanIndex:currentIndex];
|
||||
}
|
||||
|
||||
[anIndexSet removeIndexes:indexesToRemove];
|
||||
|
||||
return anIndexSet;
|
||||
}
|
||||
else
|
||||
return anIndexSet;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
@@ -1522,7 +1615,10 @@ NOT YET IMPLEMENTED
|
||||
if ([[self selectedColumnIndexes] count])
|
||||
[self selectColumnIndexes:[CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [self numberOfColumns])] byExtendingSelection:NO];
|
||||
else
|
||||
[self selectRowIndexes:[CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [self numberOfRows])] byExtendingSelection:NO];
|
||||
{
|
||||
var range = [self _cleanUpSelectionRowIndexes:[CPIndexSet indexSetWithIndexesInRange:CPMakeRange(0, [self numberOfRows])]];
|
||||
[self selectRowIndexes:range byExtendingSelection:NO];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2014,7 +2110,7 @@ NOT YET IMPLEMENTED
|
||||
// search the (potentially large number of) rows for nothing.
|
||||
var heightInfo = [_cachedRowHeights lastObject];
|
||||
|
||||
if (aPoint.y >= ROW_BOTTOM(heightInfo))
|
||||
if (!heightInfo || aPoint.y >= ROW_BOTTOM(heightInfo))
|
||||
return -1;
|
||||
|
||||
return [_cachedRowHeights indexOfObject:aPoint
|
||||
@@ -2774,40 +2870,11 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
|
||||
- (void)tableViewDeleteKeyPressed:(CPTableView)aTableView;
|
||||
@endcode
|
||||
*/
|
||||
- (void)setDelegate:(id)aDelegate
|
||||
- (void)setDelegate:(id <CPTableViewDelegate>)aDelegate
|
||||
{
|
||||
if (_delegate === aDelegate)
|
||||
return;
|
||||
|
||||
var defaultCenter = [CPNotificationCenter defaultCenter];
|
||||
|
||||
if (_delegate)
|
||||
{
|
||||
if ([_delegate respondsToSelector:@selector(tableViewColumnDidMove:)])
|
||||
[defaultCenter
|
||||
removeObserver:_delegate
|
||||
name:CPTableViewColumnDidMoveNotification
|
||||
object:self];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(tableViewColumnDidResize:)])
|
||||
[defaultCenter
|
||||
removeObserver:_delegate
|
||||
name:CPTableViewColumnDidResizeNotification
|
||||
object:self];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(tableViewSelectionDidChange:)])
|
||||
[defaultCenter
|
||||
removeObserver:_delegate
|
||||
name:CPTableViewSelectionDidChangeNotification
|
||||
object:self];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(tableViewSelectionIsChanging:)])
|
||||
[defaultCenter
|
||||
removeObserver:_delegate
|
||||
name:CPTableViewSelectionIsChangingNotification
|
||||
object:self];
|
||||
}
|
||||
|
||||
_delegate = aDelegate;
|
||||
_implementedDelegateMethods = 0;
|
||||
|
||||
@@ -2872,6 +2939,9 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
|
||||
if ([_delegate respondsToSelector:@selector(tableView:willDisplayView:forTableColumn:row:)])
|
||||
_implementedDelegateMethods |= CPTableViewDelegate_tableView_willDisplayView_forTableColumn_row_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(tableView:willRemoveView:forTableColumn:row:)])
|
||||
_implementedDelegateMethods |= CPTableViewDelegate_tableView_willRemoveView_forTableColumn_row_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(tableView:menuForTableColumn:row:)])
|
||||
_implementedDelegateMethods |= CPTableViewDelegate_tableViewMenuForTableColumn_row_;
|
||||
|
||||
@@ -2879,32 +2949,16 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
|
||||
_implementedDelegateMethods |= CPTableViewDelegate_tableView_shouldReorderColumn_toColumn_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(tableViewColumnDidMove:)])
|
||||
[defaultCenter
|
||||
addObserver:_delegate
|
||||
selector:@selector(tableViewColumnDidMove:)
|
||||
name:CPTableViewColumnDidMoveNotification
|
||||
object:self];
|
||||
_implementedDelegateMethods |= CPTableViewDelegate_tableViewColumnDidMove_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(tableViewColumnDidResize:)])
|
||||
[defaultCenter
|
||||
addObserver:_delegate
|
||||
selector:@selector(tableViewColumnDidResize:)
|
||||
name:CPTableViewColumnDidResizeNotification
|
||||
object:self];
|
||||
_implementedDelegateMethods |= CPTableViewDelegate_tableViewColumnDidResize_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(tableViewSelectionDidChange:)])
|
||||
[defaultCenter
|
||||
addObserver:_delegate
|
||||
selector:@selector(tableViewSelectionDidChange:)
|
||||
name:CPTableViewSelectionDidChangeNotification
|
||||
object:self];
|
||||
_implementedDelegateMethods |= CPTableViewDelegate_tableViewSelectionDidChange_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(tableViewSelectionIsChanging:)])
|
||||
[defaultCenter
|
||||
addObserver:_delegate
|
||||
selector:@selector(tableViewSelectionIsChanging:)
|
||||
name:CPTableViewSelectionIsChangingNotification
|
||||
object:self];
|
||||
_implementedDelegateMethods |= CPTableViewDelegate_tableViewSelectionIsChanging_;
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -3507,6 +3561,8 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
|
||||
|
||||
var dataView = [dataViews objectAtIndex:row];
|
||||
|
||||
[self _sendDelegateWillRemoveView:dataView forTableColumn:tableColumn row:row];
|
||||
|
||||
[dataViews replaceObjectAtIndex:row withObject:nil];
|
||||
|
||||
[self _enqueueReusableDataView:dataView];
|
||||
@@ -3863,6 +3919,9 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
|
||||
// FIXME: yuck!
|
||||
var identifier = [aDataView identifier];
|
||||
|
||||
if ([aDataView hasThemeState:CPThemeStateSelectedDataView])
|
||||
[aDataView unsetThemeState:CPThemeStateSelectedDataView];
|
||||
|
||||
if (!_cachedDataViews[identifier])
|
||||
_cachedDataViews[identifier] = [aDataView];
|
||||
else
|
||||
@@ -4366,39 +4425,15 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
|
||||
*/
|
||||
- (void)viewWillMoveToSuperview:(CPView)aView
|
||||
{
|
||||
var superview = [self superview],
|
||||
defaultCenter = [CPNotificationCenter defaultCenter];
|
||||
|
||||
if (superview)
|
||||
{
|
||||
[defaultCenter
|
||||
removeObserver:self
|
||||
name:CPViewFrameDidChangeNotification
|
||||
object:superview];
|
||||
|
||||
[defaultCenter
|
||||
removeObserver:self
|
||||
name:CPViewBoundsDidChangeNotification
|
||||
object:superview];
|
||||
}
|
||||
|
||||
if ([aView isKindOfClass:[CPClipView class]])
|
||||
_observedClipView = aView;
|
||||
else
|
||||
{
|
||||
[aView setPostsFrameChangedNotifications:YES];
|
||||
[aView setPostsBoundsChangedNotifications:YES];
|
||||
|
||||
[defaultCenter
|
||||
addObserver:self
|
||||
selector:@selector(superviewFrameChanged:)
|
||||
name:CPViewFrameDidChangeNotification
|
||||
object:aView];
|
||||
|
||||
[defaultCenter
|
||||
addObserver:self
|
||||
selector:@selector(superviewBoundsChanged:)
|
||||
name:CPViewBoundsDidChangeNotification
|
||||
object:aView];
|
||||
[self _stopObservingClipView];
|
||||
_observedClipView = nil;
|
||||
}
|
||||
|
||||
[super viewWillMoveToSuperview:aView];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -4980,6 +5015,9 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
|
||||
postNotificationName:CPTableViewSelectionIsChangingNotification
|
||||
object:self
|
||||
userInfo:nil];
|
||||
|
||||
if (_implementedDelegateMethods & CPTableViewDelegate_tableViewSelectionIsChanging_)
|
||||
[_delegate tableViewSelectionIsChanging:[[CPNotification alloc] initWithName:CPTableViewSelectionIsChangingNotification object:self userInfo:nil]];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -4991,6 +5029,9 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
|
||||
postNotificationName:CPTableViewSelectionDidChangeNotification
|
||||
object:self
|
||||
userInfo:nil];
|
||||
|
||||
if (_implementedDelegateMethods & CPTableViewDelegate_tableViewSelectionDidChange_)
|
||||
[_delegate tableViewSelectionDidChange:[[CPNotification alloc] initWithName:CPTableViewSelectionDidChangeNotification object:self userInfo:nil]];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -5009,24 +5050,6 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (BOOL)becomeFirstResponder
|
||||
{
|
||||
[self setNeedsDisplay:YES];
|
||||
return YES;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
- (BOOL)resignFirstResponder
|
||||
{
|
||||
[self setNeedsDisplay:YES];
|
||||
return YES;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
*/
|
||||
@@ -5051,14 +5074,88 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
|
||||
var hit = [super hitTest:aPoint];
|
||||
|
||||
if ([[CPApp currentEvent] type] == CPLeftMouseDown && [hit acceptsFirstResponder] && ![self isRowSelected:[self rowForView:hit]])
|
||||
{
|
||||
if (_selectionHighlightStyle == CPTableViewSelectionHighlightStyleNone)
|
||||
return hit;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
return hit;
|
||||
}
|
||||
|
||||
- (void)_startObservingFirstResponder
|
||||
- (void)_removeObservers
|
||||
{
|
||||
[[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_firstResponderDidChange:) name:_CPWindowDidChangeFirstResponderNotification object:[self window]];
|
||||
if (!_isObserving)
|
||||
return;
|
||||
|
||||
[self _stopObservingClipView];
|
||||
[super _removeObservers];
|
||||
}
|
||||
|
||||
- (void)_addObservers
|
||||
{
|
||||
if (_isObserving)
|
||||
return;
|
||||
|
||||
[self _startObservingClipView];
|
||||
[super _addObservers];
|
||||
}
|
||||
|
||||
/*!
|
||||
Called when the receiver is about to be moved to a new window.
|
||||
@param aWindow the window to which the receiver will be moved.
|
||||
*/
|
||||
- (void)viewWillMoveToWindow:(CPWindow)aWindow
|
||||
{
|
||||
[super viewWillMoveToWindow:aWindow];
|
||||
|
||||
[self _stopObservingFirstResponder];
|
||||
|
||||
if (aWindow)
|
||||
[self _startObservingFirstResponderForWindow:aWindow];
|
||||
}
|
||||
|
||||
- (void)_startObservingClipView
|
||||
{
|
||||
if (!_observedClipView)
|
||||
return;
|
||||
|
||||
var defaultCenter = [CPNotificationCenter defaultCenter];
|
||||
|
||||
[_observedClipView setPostsFrameChangedNotifications:YES];
|
||||
[_observedClipView setPostsBoundsChangedNotifications:YES];
|
||||
|
||||
[defaultCenter addObserver:self
|
||||
selector:@selector(superviewFrameChanged:)
|
||||
name:CPViewFrameDidChangeNotification
|
||||
object:_observedClipView];
|
||||
|
||||
[defaultCenter addObserver:self
|
||||
selector:@selector(superviewBoundsChanged:)
|
||||
name:CPViewBoundsDidChangeNotification
|
||||
object:_observedClipView];
|
||||
}
|
||||
|
||||
- (void)_stopObservingClipView
|
||||
{
|
||||
if (!_observedClipView)
|
||||
return;
|
||||
|
||||
var defaultCenter = [CPNotificationCenter defaultCenter];
|
||||
|
||||
[defaultCenter removeObserver:self
|
||||
name:CPViewFrameDidChangeNotification
|
||||
object:_observedClipView];
|
||||
|
||||
[defaultCenter removeObserver:self
|
||||
name:CPViewBoundsDidChangeNotification
|
||||
object:_observedClipView];
|
||||
}
|
||||
|
||||
- (void)_startObservingFirstResponderForWindow:(CPWindow)aWindow
|
||||
{
|
||||
[[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_firstResponderDidChange:) name:_CPWindowDidChangeFirstResponderNotification object:aWindow];
|
||||
}
|
||||
|
||||
- (void)_stopObservingFirstResponder
|
||||
@@ -5074,13 +5171,20 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
|
||||
{
|
||||
_editingRow = CPNotFound;
|
||||
_editingColumn = CPNotFound;
|
||||
|
||||
// This is needed to unset the themeState firstResponder of the tableView
|
||||
[self _notifyViewDidResignFirstResponder];
|
||||
return;
|
||||
}
|
||||
|
||||
_editingRow = [self rowForView:responder];
|
||||
_editingColumn = [self columnForView:responder];
|
||||
|
||||
if (_editingRow !== CPNotFound && [responder isKindOfClass:[CPTextField class]] && ![responder isBezeled])
|
||||
// We want to keep the 'First Responder' theme state for the table view as a whole, even when a subview is being edited.
|
||||
// This makes sure the theming effects of a focused table remain in effect even as cells are being edited in it.
|
||||
[self _notifyViewDidBecomeFirstResponder];
|
||||
|
||||
if (_editingRow !== CPNotFound && [responder isKindOfClass:[CPTextField class]] && ![responder isBezeled] && [responder isEditable])
|
||||
{
|
||||
[responder setBezeled:YES];
|
||||
[self _registerForEndEditingNote:responder];
|
||||
@@ -5210,9 +5314,9 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
|
||||
if (i >= [self numberOfRows] || i < 0)
|
||||
return;
|
||||
|
||||
if (![self _delegateRespondsToSelectionIndexesForProposedSelection] && [self _delegateRespondsToShouldSelectRow])
|
||||
if ([self _delegateRespondsToSelectionIndexesForProposedSelection] || [self _delegateRespondsToShouldSelectRow])
|
||||
{
|
||||
var shouldSelect = [self _sendDelegateShouldSelectRow:i];
|
||||
var shouldSelect = !![[self _cleanUpSelectionRowIndexes:[CPIndexSet indexSetWithIndex:i]] count];
|
||||
|
||||
/* If shouldSelect returns NO it means this row cannot be selected.
|
||||
The proper behaviour is to then try to see if the next/previous
|
||||
@@ -5221,7 +5325,7 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
|
||||
while (!shouldSelect && (i < [self numberOfRows] && i > 0))
|
||||
{
|
||||
shouldGoUpward ? --i : ++i; //check to see if the row can be selected. If it can't be then see if the next row can be selected.
|
||||
shouldSelect = [self _sendDelegateShouldSelectRow:i];
|
||||
shouldSelect = !![[self _cleanUpSelectionRowIndexes:[CPIndexSet indexSetWithIndex:i]] count];
|
||||
}
|
||||
|
||||
if (!shouldSelect)
|
||||
@@ -5583,6 +5687,18 @@ Your delegate can implement this method to avoid subclassing the tableview to ad
|
||||
[_delegate tableView:self willDisplayView:aCell forTableColumn:aTableColumn row:aRowIndex];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call the delegate tableView:willRemoveView:forTableColumn:row:
|
||||
*/
|
||||
- (void)_sendDelegateWillRemoveView:(id)aCell forTableColumn:(CPTableColumn)aTableColumn row:(CPInteger)aRowIndex
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPTableViewDelegate_tableView_willRemoveView_forTableColumn_row_))
|
||||
return;
|
||||
|
||||
[_delegate tableView:self willRemoveView:aCell forTableColumn:aTableColumn row:aRowIndex];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Return a CPMenu for the given tableColumn and row. By default return the menu of super.
|
||||
@@ -5916,6 +6032,11 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey",
|
||||
{
|
||||
[super encodeWithCoder:aCoder];
|
||||
|
||||
// We do this in order to avoid encoding the _tableDrawView, which
|
||||
// should just automatically be created programmatically as needed.
|
||||
if (_tableDrawView)
|
||||
[_tableDrawView removeFromSuperview];
|
||||
|
||||
[aCoder encodeObject:_dataSource forKey:CPTableViewDataSourceKey];
|
||||
[aCoder encodeObject:_delegate forKey:CPTableViewDelegateKey];
|
||||
|
||||
@@ -6143,14 +6264,20 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey",
|
||||
[self setThemeState:CPThemeStateTableDataView];
|
||||
}
|
||||
|
||||
- (BOOL)setThemeState:(CPThemeState)aState
|
||||
- (BOOL)setThemeState:(ThemeState)aState
|
||||
{
|
||||
if (aState.isa && [aState isKindOfClass:CPArray])
|
||||
aState = CPThemeState.apply(null, aState);
|
||||
|
||||
[super setThemeState:aState];
|
||||
[self recursivelyPerformSelector:@selector(setThemeState:) withObject:aState startingFrom:self];
|
||||
}
|
||||
|
||||
- (BOOL)unsetThemeState:(CPThemeState)aState
|
||||
- (BOOL)unsetThemeState:(ThemeState)aState
|
||||
{
|
||||
if (aState.isa && [aState isKindOfClass:CPArray])
|
||||
aState = CPThemeState.apply(null, aState);
|
||||
|
||||
[super unsetThemeState:aState];
|
||||
[self recursivelyPerformSelector:@selector(unsetThemeState:) withObject:aState startingFrom:self];
|
||||
}
|
||||
|
||||
@@ -31,16 +31,32 @@
|
||||
|
||||
@global CPApp
|
||||
@global CPStringPboardType
|
||||
@global CPCursor
|
||||
|
||||
|
||||
@protocol CPTextFieldDelegate <CPControlTextEditingDelegate>
|
||||
|
||||
@end
|
||||
|
||||
var CPTextFieldDelegate_control_didFailToFormatString_errorDescription_ = 1 << 1,
|
||||
CPTextFieldDelegate_controlTextDidBeginEditing_ = 1 << 2,
|
||||
CPTextFieldDelegate_controlTextDidChange_ = 1 << 3,
|
||||
CPTextFieldDelegate_controlTextDidEndEditing_ = 1 << 4,
|
||||
CPTextFieldDelegate_controlTextDidFocus_ = 1 << 5,
|
||||
CPTextFieldDelegate_controlTextDidBlur_ = 1 << 6;
|
||||
|
||||
|
||||
@typedef CPTextFieldBezelStyle
|
||||
CPTextFieldSquareBezel = 0; /*! A textfield bezel with squared corners. */
|
||||
CPTextFieldRoundedBezel = 1; /*! A textfield bezel with rounded corners. */
|
||||
|
||||
CPTextFieldDidFocusNotification = @"CPTextFieldDidFocusNotification";
|
||||
CPTextFieldDidBlurNotification = @"CPTextFieldDidBlurNotification";
|
||||
|
||||
var CPTextFieldDOMInputElement = nil,
|
||||
CPTextFieldDOMPasswordInputElement = nil,
|
||||
var CPTextFieldDOMCurrentElement = nil,
|
||||
CPTextFieldDOMTextAreaElement = nil,
|
||||
CPTextFieldDOMStandardInputElement = nil,
|
||||
CPTextFieldDOMPasswordInputElement = nil,
|
||||
CPTextFieldInputOwner = nil,
|
||||
CPTextFieldTextDidChangeValue = nil,
|
||||
CPTextFieldInputResigning = NO,
|
||||
@@ -112,26 +128,30 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
*/
|
||||
@implementation CPTextField : CPControl
|
||||
{
|
||||
BOOL _isEditing;
|
||||
BOOL _isEditing;
|
||||
|
||||
BOOL _isEditable;
|
||||
BOOL _isSelectable;
|
||||
BOOL _isSecure;
|
||||
BOOL _willBecomeFirstResponderByClick;
|
||||
BOOL _isEditable;
|
||||
BOOL _isSelectable;
|
||||
BOOL _isSecure;
|
||||
BOOL _willBecomeFirstResponderByClick;
|
||||
BOOL _invokedByUserEvent;
|
||||
|
||||
BOOL _drawsBackground;
|
||||
BOOL _drawsBackground;
|
||||
|
||||
CPColor _textFieldBackgroundColor;
|
||||
CPColor _textFieldBackgroundColor;
|
||||
|
||||
CPString _placeholderString;
|
||||
CPString _stringValue;
|
||||
CPString _placeholderString;
|
||||
CPString _stringValue;
|
||||
|
||||
id _delegate;
|
||||
id <CPTextFieldDelegate> _delegate;
|
||||
unsigned _implementedDelegateMethods;
|
||||
|
||||
// NS-style Display Properties
|
||||
CPTextFieldBezelStyle _bezelStyle;
|
||||
BOOL _isBordered;
|
||||
CPControlSize _controlSize;
|
||||
CPTextFieldBezelStyle _bezelStyle;
|
||||
BOOL _isBordered;
|
||||
BOOL _usesSingleLineMode;
|
||||
BOOL _wraps;
|
||||
BOOL _scrolls;
|
||||
}
|
||||
|
||||
+ (Class)_binderClassForBinding:(CPString)aBinding
|
||||
@@ -218,98 +238,124 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Control Size
|
||||
|
||||
- (void)setControlSize:(CPControlSize)aControlSize
|
||||
{
|
||||
[super setControlSize:aControlSize];
|
||||
|
||||
if ([self isBezeled])
|
||||
[self _sizeToControlSize];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
- (DOMElement)_inputElement
|
||||
{
|
||||
if (!CPTextFieldDOMInputElement)
|
||||
if (!CPTextFieldDOMTextAreaElement)
|
||||
{
|
||||
CPTextFieldDOMInputElement = document.createElement("input");
|
||||
CPTextFieldDOMInputElement.style.position = "absolute";
|
||||
CPTextFieldDOMInputElement.style.border = "0px";
|
||||
CPTextFieldDOMInputElement.style.padding = "0px";
|
||||
CPTextFieldDOMInputElement.style.margin = "0px";
|
||||
CPTextFieldDOMInputElement.style.whiteSpace = "pre";
|
||||
CPTextFieldDOMInputElement.style.background = "transparent";
|
||||
CPTextFieldDOMInputElement.style.outline = "none";
|
||||
CPTextFieldDOMTextAreaElement = document.createElement("textarea");
|
||||
CPTextFieldDOMTextAreaElement.style.position = "absolute";
|
||||
CPTextFieldDOMTextAreaElement.style.border = "0px";
|
||||
CPTextFieldDOMTextAreaElement.style.padding = "0px";
|
||||
CPTextFieldDOMTextAreaElement.style.margin = "0px";
|
||||
CPTextFieldDOMTextAreaElement.style.background = "transparent";
|
||||
CPTextFieldDOMTextAreaElement.style.outline = "none";
|
||||
CPTextFieldDOMTextAreaElement.style.resize = "none";
|
||||
CPTextFieldDOMTextAreaElement.style.overflow = "hidden";
|
||||
CPTextFieldDOMTextAreaElement.spellcheck = NO;
|
||||
}
|
||||
|
||||
if (!CPTextFieldDOMStandardInputElement)
|
||||
{
|
||||
CPTextFieldDOMStandardInputElement = document.createElement("input");
|
||||
CPTextFieldDOMStandardInputElement.style.position = "absolute";
|
||||
CPTextFieldDOMStandardInputElement.style.border = "0px";
|
||||
CPTextFieldDOMStandardInputElement.style.padding = "0px";
|
||||
CPTextFieldDOMStandardInputElement.style.margin = "0px";
|
||||
CPTextFieldDOMStandardInputElement.style.whiteSpace = "pre";
|
||||
CPTextFieldDOMStandardInputElement.style.background = "transparent";
|
||||
CPTextFieldDOMStandardInputElement.style.outline = "none";
|
||||
CPTextFieldDOMStandardInputElement.spellcheck = NO;
|
||||
}
|
||||
|
||||
if (!CPTextFieldDOMPasswordInputElement)
|
||||
{
|
||||
CPTextFieldDOMPasswordInputElement = document.createElement("input");
|
||||
CPTextFieldDOMPasswordInputElement.style.position = "absolute";
|
||||
CPTextFieldDOMPasswordInputElement.style.border = "0px";
|
||||
CPTextFieldDOMPasswordInputElement.style.padding = "0px";
|
||||
CPTextFieldDOMPasswordInputElement.style.margin = "0px";
|
||||
CPTextFieldDOMPasswordInputElement.style.whiteSpace = "pre";
|
||||
CPTextFieldDOMPasswordInputElement.style.background = "transparent";
|
||||
CPTextFieldDOMPasswordInputElement.style.outline = "none";
|
||||
CPTextFieldDOMPasswordInputElement.type = "password";
|
||||
CPTextFieldDOMPasswordInputElement.spellcheck = NO;
|
||||
}
|
||||
|
||||
if (!CPTextFieldBlurHandler)
|
||||
{
|
||||
CPTextFieldBlurHandler = function(anEvent)
|
||||
{
|
||||
return CPTextFieldBlurFunction(
|
||||
anEvent,
|
||||
CPTextFieldInputOwner,
|
||||
CPTextFieldInputOwner ? CPTextFieldInputOwner._DOMElement : nil,
|
||||
CPTextFieldDOMInputElement,
|
||||
CPTextFieldDOMCurrentElement,
|
||||
CPTextFieldInputResigning,
|
||||
@ref(CPTextFieldInputDidBlur));
|
||||
};
|
||||
}
|
||||
|
||||
if (CPFeatureIsCompatible(CPInputOnInputEventFeature))
|
||||
if (!CPTextFieldInputFunction)
|
||||
{
|
||||
if (!CPFeatureIsCompatible(CPInputOnInputEventFeature))
|
||||
return;
|
||||
|
||||
CPTextFieldInputFunction = function(anEvent)
|
||||
{
|
||||
CPTextFieldInputFunction = function(anEvent)
|
||||
{
|
||||
if (!CPTextFieldInputOwner)
|
||||
return;
|
||||
if (!CPTextFieldInputOwner)
|
||||
return;
|
||||
|
||||
var cappEvent = [CPEvent keyEventWithType:CPKeyUp
|
||||
location:CGPointMakeZero()
|
||||
modifierFlags:0
|
||||
timestamp:[CPEvent currentTimestamp]
|
||||
windowNumber:[[CPApp keyWindow] windowNumber]
|
||||
context:nil
|
||||
characters:nil
|
||||
charactersIgnoringModifiers:nil
|
||||
isARepeat:NO
|
||||
keyCode:nil];
|
||||
var cappEvent = [CPEvent keyEventWithType:CPKeyUp
|
||||
location:CGPointMakeZero()
|
||||
modifierFlags:0
|
||||
timestamp:[CPEvent currentTimestamp]
|
||||
windowNumber:[[CPApp keyWindow] windowNumber]
|
||||
context:nil
|
||||
characters:nil
|
||||
charactersIgnoringModifiers:nil
|
||||
isARepeat:NO
|
||||
keyCode:nil];
|
||||
|
||||
[CPTextFieldInputOwner keyUp:cappEvent];
|
||||
[CPTextFieldInputOwner keyUp:cappEvent];
|
||||
|
||||
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
|
||||
}
|
||||
|
||||
CPTextFieldDOMInputElement.oninput = CPTextFieldInputFunction;
|
||||
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
|
||||
}
|
||||
|
||||
// FIXME make this not onblur
|
||||
CPTextFieldDOMInputElement.onblur = CPTextFieldBlurHandler;
|
||||
CPTextFieldDOMPasswordInputElement.oninput = CPTextFieldInputFunction;
|
||||
CPTextFieldDOMPasswordInputElement.onblur = CPTextFieldBlurHandler;
|
||||
|
||||
CPTextFieldDOMStandardInputElement = CPTextFieldDOMInputElement;
|
||||
CPTextFieldDOMStandardInputElement.oninput = CPTextFieldInputFunction;
|
||||
CPTextFieldDOMPasswordInputElement.onblur = CPTextFieldBlurHandler;
|
||||
|
||||
CPTextFieldDOMTextAreaElement.oninput = CPTextFieldInputFunction;
|
||||
CPTextFieldDOMTextAreaElement.onblur = CPTextFieldBlurHandler;
|
||||
}
|
||||
|
||||
if (CPFeatureIsCompatible(CPInputTypeCanBeChangedFeature))
|
||||
{
|
||||
if ([self isSecure])
|
||||
CPTextFieldDOMInputElement.type = "password";
|
||||
else
|
||||
CPTextFieldDOMInputElement.type = "text";
|
||||
|
||||
return CPTextFieldDOMInputElement;
|
||||
}
|
||||
|
||||
if ([self isSecure])
|
||||
{
|
||||
if (!CPTextFieldDOMPasswordInputElement)
|
||||
{
|
||||
CPTextFieldDOMPasswordInputElement = document.createElement("input");
|
||||
CPTextFieldDOMPasswordInputElement.style.position = "absolute";
|
||||
CPTextFieldDOMPasswordInputElement.style.border = "0px";
|
||||
CPTextFieldDOMPasswordInputElement.style.padding = "0px";
|
||||
CPTextFieldDOMPasswordInputElement.style.margin = "0px";
|
||||
CPTextFieldDOMPasswordInputElement.style.whiteSpace = "pre";
|
||||
CPTextFieldDOMPasswordInputElement.style.background = "transparent";
|
||||
CPTextFieldDOMPasswordInputElement.style.outline = "none";
|
||||
CPTextFieldDOMPasswordInputElement.type = "password";
|
||||
|
||||
CPTextFieldDOMPasswordInputElement.onblur = CPTextFieldBlurHandler;
|
||||
}
|
||||
|
||||
CPTextFieldDOMInputElement = CPTextFieldDOMPasswordInputElement;
|
||||
}
|
||||
CPTextFieldDOMCurrentElement = CPTextFieldDOMPasswordInputElement;
|
||||
else if (_usesSingleLineMode)
|
||||
CPTextFieldDOMCurrentElement = CPTextFieldDOMStandardInputElement;
|
||||
else
|
||||
{
|
||||
CPTextFieldDOMInputElement = CPTextFieldDOMStandardInputElement;
|
||||
}
|
||||
CPTextFieldDOMCurrentElement = CPTextFieldDOMTextAreaElement;
|
||||
|
||||
return CPTextFieldDOMInputElement;
|
||||
return CPTextFieldDOMCurrentElement;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -528,6 +574,24 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
return _textFieldBackgroundColor;
|
||||
}
|
||||
|
||||
/*! @ignore */
|
||||
- (void)_setUsesSingleLineMode:(BOOL)aFlag
|
||||
{
|
||||
_usesSingleLineMode = aFlag;
|
||||
}
|
||||
|
||||
/*! @ignore */
|
||||
- (void)_setWraps:(BOOL)aFlag
|
||||
{
|
||||
_wraps = aFlag;
|
||||
}
|
||||
|
||||
/*! @ignore */
|
||||
- (void)_setScrolls:(BOOL)aFlag
|
||||
{
|
||||
_scrolls = aFlag;
|
||||
}
|
||||
|
||||
/*! @ignore */
|
||||
- (BOOL)acceptsFirstResponder
|
||||
{
|
||||
@@ -537,7 +601,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
/*! @ignore */
|
||||
- (BOOL)becomeFirstResponder
|
||||
{
|
||||
if (![self isEnabled])
|
||||
if (![self isEnabled] || ![super becomeFirstResponder])
|
||||
return NO;
|
||||
|
||||
// As long as we are the first responder we need to monitor the key status of our window.
|
||||
@@ -581,75 +645,12 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
|
||||
var element = [self _inputElement],
|
||||
font = [self currentValueForThemeAttribute:@"font"],
|
||||
lineHeight = [font defaultLineHeightForFont];
|
||||
[self _setCSSStyleForInputElement];
|
||||
|
||||
var element = [self _inputElement];
|
||||
element.value = _stringValue;
|
||||
element.style.color = [[self currentValueForThemeAttribute:@"text-color"] cssString];
|
||||
|
||||
if (CPFeatureIsCompatible(CPInputSetFontOutsideOfDOM))
|
||||
element.style.font = [font cssString];
|
||||
|
||||
element.style.zIndex = 1000;
|
||||
|
||||
switch ([self alignment])
|
||||
{
|
||||
case CPCenterTextAlignment:
|
||||
element.style.textAlign = "center";
|
||||
break;
|
||||
|
||||
case CPRightTextAlignment:
|
||||
element.style.textAlign = "right";
|
||||
break;
|
||||
|
||||
default:
|
||||
element.style.textAlign = "left";
|
||||
}
|
||||
|
||||
var contentRect = [self contentRectForBounds:[self bounds]],
|
||||
verticalAlign = [self currentValueForThemeAttribute:"vertical-alignment"];
|
||||
|
||||
switch (verticalAlign)
|
||||
{
|
||||
case CPTopVerticalTextAlignment:
|
||||
var topPoint = CGRectGetMinY(contentRect) + "px";
|
||||
break;
|
||||
|
||||
case CPCenterVerticalTextAlignment:
|
||||
var topPoint = (CGRectGetMidY(contentRect) - (lineHeight / 2)) + "px";
|
||||
break;
|
||||
|
||||
case CPBottomVerticalTextAlignment:
|
||||
var topPoint = (CGRectGetMaxY(contentRect) - lineHeight) + "px";
|
||||
break;
|
||||
|
||||
default:
|
||||
var topPoint = CGRectGetMinY(contentRect) + "px";
|
||||
break;
|
||||
}
|
||||
|
||||
element.style.top = topPoint;
|
||||
|
||||
var left = CGRectGetMinX(contentRect);
|
||||
|
||||
// If the browser has a built in left padding, compensate for it. We need the input text to be exactly on top of the original text.
|
||||
if (CPFeatureIsCompatible(CPInput1PxLeftPadding))
|
||||
left -= 1;
|
||||
|
||||
element.style.left = left + "px";
|
||||
element.style.width = CGRectGetWidth(contentRect) + "px";
|
||||
element.style.height = ROUND(lineHeight) + "px";
|
||||
element.style.lineHeight = ROUND(lineHeight) + "px";
|
||||
element.style.verticalAlign = "top";
|
||||
element.style.cursor = "auto";
|
||||
|
||||
_DOMElement.appendChild(element);
|
||||
|
||||
// The font change above doesn't work for some browsers if the element isn't already appendChild'ed.
|
||||
if (!CPFeatureIsCompatible(CPInputSetFontOutsideOfDOM))
|
||||
element.style.font = [font cssString];
|
||||
|
||||
CPTextFieldInputIsActive = YES;
|
||||
|
||||
if (document.attachEvent)
|
||||
@@ -687,6 +688,81 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
return YES;
|
||||
}
|
||||
|
||||
/*!
|
||||
Set the css style for the input element of the textField
|
||||
@ignore
|
||||
*/
|
||||
- (void)_setCSSStyleForInputElement
|
||||
{
|
||||
#if PLATFORM(DOM)
|
||||
|
||||
var element = [self _inputElement],
|
||||
font = [self currentValueForThemeAttribute:@"font"],
|
||||
lineHeight = [font defaultLineHeightForFont],
|
||||
contentRect = [self contentRectForBounds:[self bounds]],
|
||||
verticalAlign = [self currentValueForThemeAttribute:"vertical-alignment"],
|
||||
left = CGRectGetMinX(contentRect);
|
||||
|
||||
// If the browser has a built in left padding, compensate for it. We need the input text to be exactly on top of the original text.
|
||||
if (CPFeatureIsCompatible(CPInput1PxLeftPadding))
|
||||
left -= 1;
|
||||
|
||||
switch (verticalAlign)
|
||||
{
|
||||
case CPTopVerticalTextAlignment:
|
||||
var topPoint = CGRectGetMinY(contentRect) + "px";
|
||||
break;
|
||||
|
||||
case CPCenterVerticalTextAlignment:
|
||||
var topPoint = (CGRectGetMidY(contentRect) - (lineHeight / 2)) + "px";
|
||||
break;
|
||||
|
||||
case CPBottomVerticalTextAlignment:
|
||||
var topPoint = (CGRectGetMaxY(contentRect) - lineHeight) + "px";
|
||||
break;
|
||||
|
||||
default:
|
||||
var topPoint = CGRectGetMinY(contentRect) + "px";
|
||||
break;
|
||||
}
|
||||
|
||||
if ([self hasThemeState:CPTextFieldStatePlaceholder])
|
||||
element.style.color = [[self valueForThemeAttribute:@"text-color" inState:CPTextFieldStatePlaceholder] cssString];
|
||||
else
|
||||
element.style.color = [[self valueForThemeAttribute:@"text-color" inState:CPThemeStateEditing] cssString];
|
||||
|
||||
switch ([self alignment])
|
||||
{
|
||||
case CPCenterTextAlignment:
|
||||
element.style.textAlign = "center";
|
||||
break;
|
||||
|
||||
case CPRightTextAlignment:
|
||||
element.style.textAlign = "right";
|
||||
break;
|
||||
|
||||
default:
|
||||
element.style.textAlign = "left";
|
||||
}
|
||||
|
||||
var isTextArea = element.nodeName.toUpperCase() == "TEXTAREA";
|
||||
|
||||
element.style.zIndex = 1000;
|
||||
element.style.top = topPoint;
|
||||
element.style.lineHeight = ROUND(lineHeight) + "px";
|
||||
element.style.height = isTextArea ? CGRectGetHeight(contentRect) + "px" : ROUND(lineHeight) + "px";;
|
||||
element.style.width = CGRectGetWidth(contentRect) + "px";
|
||||
element.style.left = left + "px";
|
||||
element.style.verticalAlign = "top";
|
||||
element.style.cursor = "auto";
|
||||
element.style.font = [font cssString];
|
||||
|
||||
if (isTextArea)
|
||||
element.style.whiteSpace = _wraps ? "pre" : "nowrap";
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/*! @ignore */
|
||||
- (BOOL)resignFirstResponder
|
||||
{
|
||||
@@ -790,6 +866,26 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_removeObservers
|
||||
{
|
||||
if (!_isObserving)
|
||||
return;
|
||||
|
||||
[super _removeObservers];
|
||||
[self _setObserveWindowKeyNotifications:NO];
|
||||
}
|
||||
|
||||
- (void)_addObservers
|
||||
{
|
||||
if (_isObserving)
|
||||
return;
|
||||
|
||||
[super _addObservers];
|
||||
|
||||
if ([[self window] firstResponder] === self)
|
||||
[self _setObserveWindowKeyNotifications:YES];
|
||||
}
|
||||
|
||||
- (void)_windowDidResignKey:(CPNotification)aNotification
|
||||
{
|
||||
if (![[self window] isKeyWindow])
|
||||
@@ -818,7 +914,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
{
|
||||
var acceptInvalidValue = NO;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(control:didFailToFormatString:errorDescription:)])
|
||||
if (_implementedDelegateMethods & CPTextFieldDelegate_control_didFailToFormatString_errorDescription_)
|
||||
acceptInvalidValue = [_delegate control:self didFailToFormatString:aValue errorDescription:error];
|
||||
|
||||
if (acceptInvalidValue === NO)
|
||||
@@ -858,6 +954,12 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
[self textDidChange:[CPNotification notificationWithName:CPControlTextDidChangeNotification object:self userInfo:nil]];
|
||||
}
|
||||
|
||||
- (void)mouseMoved:(CPEvent)anEvent
|
||||
{
|
||||
[super mouseMoved:anEvent];
|
||||
[self _updateCursorForEvent:anEvent];
|
||||
}
|
||||
|
||||
- (void)mouseDown:(CPEvent)anEvent
|
||||
{
|
||||
// Don't track! (ever?)
|
||||
@@ -928,7 +1030,6 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
if (newValue !== _stringValue)
|
||||
{
|
||||
[self _setStringValue:newValue];
|
||||
|
||||
[self _didEdit];
|
||||
}
|
||||
|
||||
@@ -938,13 +1039,20 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
|
||||
- (void)keyDown:(CPEvent)anEvent
|
||||
{
|
||||
if (!([self isEnabled] && [self isEditable]))
|
||||
return;
|
||||
|
||||
// CPTextField uses an HTML input element to take the input so we need to
|
||||
// propagate the dom event so the element is updated. This has to be done
|
||||
// before interpretKeyEvents: though so individual commands have a chance
|
||||
// to override this (escape to clear the text in a search field for example).
|
||||
[[[self window] platformWindow] _propagateCurrentDOMEvent:YES];
|
||||
|
||||
// Set a flag so that key handling methods (such as deleteBackward:)
|
||||
// know they were invoked from a user event.
|
||||
_invokedByUserEvent = !!anEvent._DOMEvent;
|
||||
[self interpretKeyEvents:[anEvent]];
|
||||
_invokedByUserEvent = NO;
|
||||
|
||||
[[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
|
||||
}
|
||||
@@ -1022,7 +1130,11 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
range = [self selectedRange],
|
||||
element = [self _inputElement];
|
||||
|
||||
element.value = [element.value stringByReplacingCharactersInRange:[self selectedRange] withString:aCharacter];
|
||||
// we don't need to do this in case of textarea
|
||||
// or we will end up with 2 carriage returns
|
||||
if (aCharacter != CPNewlineCharacter || element.nodeName.toUpperCase() != "TEXTAREA" || !CPFeatureIsCompatible(CPAltEnterTextAreaFeature))
|
||||
element.value = [element.value stringByReplacingCharactersInRange:[self selectedRange] withString:aCharacter];
|
||||
|
||||
[self _setStringValue:element.value];
|
||||
|
||||
// NOTE: _stringValue is now the current input element value
|
||||
@@ -1040,6 +1152,9 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
if ([note object] != self)
|
||||
return;
|
||||
|
||||
if (_implementedDelegateMethods & CPTextFieldDelegate_controlTextDidBlur_)
|
||||
[_delegate controlTextDidBlur:note];
|
||||
|
||||
[[CPNotificationCenter defaultCenter] postNotification:note];
|
||||
}
|
||||
|
||||
@@ -1049,6 +1164,9 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
if ([note object] != self)
|
||||
return;
|
||||
|
||||
if (_implementedDelegateMethods & CPTextFieldDelegate_controlTextDidFocus_)
|
||||
[_delegate controlTextDidFocus:note];
|
||||
|
||||
[[CPNotificationCenter defaultCenter] postNotification:note];
|
||||
}
|
||||
|
||||
@@ -1059,9 +1177,57 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
|
||||
[self _continuouslyReverseSetBinding];
|
||||
|
||||
if (_implementedDelegateMethods & CPTextFieldDelegate_controlTextDidChange_)
|
||||
[_delegate controlTextDidChange:note];
|
||||
|
||||
[super textDidChange:note];
|
||||
}
|
||||
|
||||
- (void)textDidBeginEditing:(CPNotification)note
|
||||
{
|
||||
//this looks to prevent false propagation of notifications for other objects
|
||||
if ([note object] != self)
|
||||
return;
|
||||
|
||||
if (_implementedDelegateMethods & CPTextFieldDelegate_controlTextDidBeginEditing_)
|
||||
[_delegate controlTextDidBeginEditing:[[CPNotification alloc] initWithName:CPControlTextDidBeginEditingNotification object:self userInfo:@{"CPFieldEditor": [note object]}]]
|
||||
|
||||
[super textDidBeginEditing:note];
|
||||
}
|
||||
|
||||
- (void)textDidEndEditing:(CPNotification)note
|
||||
{
|
||||
//this looks to prevent false propagation of notifications for other objects
|
||||
if ([note object] != self)
|
||||
return;
|
||||
|
||||
[super textDidEndEditing:note];
|
||||
|
||||
if (_implementedDelegateMethods & CPTextFieldDelegate_controlTextDidEndEditing_)
|
||||
[_delegate controlTextDidEndEditing:note];
|
||||
}
|
||||
|
||||
- (void)_updateCursorForEvent:(CPEvent)anEvent
|
||||
{
|
||||
var frame = CGRectMakeCopy([self frame]),
|
||||
contentInset = [self currentValueForThemeAttribute:@"content-inset"];
|
||||
|
||||
frame = [[self superview] convertRectToBase:CGRectInsetByInset(frame, contentInset)];
|
||||
|
||||
if ([self isEnabled] && ([self isSelectable] || [self isEditable]) && CGRectContainsPoint(frame, [anEvent locationInWindow]))
|
||||
{
|
||||
#if PLATFORM(DOM)
|
||||
self._DOMElement.style.cursor = "text";
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if PLATFORM(DOM)
|
||||
self._DOMElement.style.cursor = "default";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the string in the text field.
|
||||
*/
|
||||
@@ -1118,12 +1284,17 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
}
|
||||
|
||||
- (void)setObjectValue:(id)aValue
|
||||
{
|
||||
[self _setObjectValue:aValue useFormatter:YES];
|
||||
}
|
||||
|
||||
- (void)_setObjectValue:(id)aValue useFormatter:(BOOL)useFormatter
|
||||
{
|
||||
[super setObjectValue:aValue];
|
||||
|
||||
var formatter = [self formatter];
|
||||
|
||||
if (formatter)
|
||||
if (useFormatter && formatter)
|
||||
{
|
||||
// If there is a formatter, make sure the object value can be formatted successfully
|
||||
var formattedString = [self hasThemeState:CPThemeStateEditing] ? [formatter editingStringForObjectValue:aValue] : [formatter stringForObjectValue:aValue];
|
||||
@@ -1148,7 +1319,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
|
||||
if (CPTextFieldInputOwner === self || [[self window] firstResponder] === self)
|
||||
if ((CPTextFieldInputOwner === self || [[self window] firstResponder] === self) && [[self window] isKeyWindow])
|
||||
[self _inputElement].value = _stringValue;
|
||||
|
||||
#endif
|
||||
@@ -1158,7 +1329,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
|
||||
- (void)_updatePlaceholderState
|
||||
{
|
||||
if ((!_stringValue || _stringValue.length === 0) && ![self hasThemeState:CPThemeStateEditing])
|
||||
if (!_stringValue || _stringValue.length === 0)
|
||||
[self setThemeState:CPTextFieldStatePlaceholder];
|
||||
else
|
||||
[self unsetThemeState:CPTextFieldStatePlaceholder];
|
||||
@@ -1508,7 +1679,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
|
||||
var selectedRange = [self selectedRange];
|
||||
|
||||
if (selectedRange.length < 1)
|
||||
if (selectedRange.length === 0)
|
||||
{
|
||||
if (selectedRange.location < 1)
|
||||
return;
|
||||
@@ -1518,19 +1689,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
selectedRange.length += 1;
|
||||
}
|
||||
|
||||
var newValue = [_stringValue stringByReplacingCharactersInRange:selectedRange withString:""];
|
||||
|
||||
[self setStringValue:newValue];
|
||||
[self setSelectedRange:CPMakeRange(selectedRange.location, 0)];
|
||||
[self _didEdit];
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
// Since we just performed the deletion manually, we don't need the browser to do anything else.
|
||||
// (Previously we would allow the event to propagate for the browser to delete 1 character only,
|
||||
// and we'd delete the rest manually. But this meant that if deleteBackward: was called without
|
||||
// it being a browser backspace event, 1 character would be left behind.)
|
||||
[[[self window] platformWindow] _propagateCurrentDOMEvent:NO];
|
||||
#endif
|
||||
[self _replaceCharactersInRange:selectedRange withCharacters:@""];
|
||||
}
|
||||
|
||||
- (void)delete:(id)sender
|
||||
@@ -1544,16 +1703,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
if (selectedRange.length < 1)
|
||||
return;
|
||||
|
||||
var newValue = [_stringValue stringByReplacingCharactersInRange:selectedRange withString:""];
|
||||
|
||||
[self setStringValue:newValue];
|
||||
[self setSelectedRange:CPMakeRange(selectedRange.location, 0)];
|
||||
[self _didEdit];
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
// Since we just performed the deletion manually, we don't need the browser to do anything else.
|
||||
[[[self window] platformWindow] _propagateCurrentDOMEvent:NO];
|
||||
#endif
|
||||
[self _replaceCharactersInRange:selectedRange withCharacters:@""];
|
||||
}
|
||||
|
||||
- (void)deleteForward:(id)sender
|
||||
@@ -1563,79 +1713,67 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
|
||||
var selectedRange = [self selectedRange];
|
||||
|
||||
if (selectedRange.length < 1)
|
||||
if (selectedRange.length === 0)
|
||||
{
|
||||
if (selectedRange.location + 1 >= _stringValue.length)
|
||||
if (selectedRange.location >= _stringValue.length)
|
||||
return;
|
||||
|
||||
// Delete a single element forward from the insertion point if there's no selection.
|
||||
selectedRange.length += 1;
|
||||
}
|
||||
|
||||
var newValue = [_stringValue stringByReplacingCharactersInRange:selectedRange withString:""];
|
||||
[self _replaceCharactersInRange:selectedRange withCharacters:@""];
|
||||
}
|
||||
|
||||
[self setStringValue:newValue];
|
||||
[self setSelectedRange:CPMakeRange(selectedRange.location, 0)];
|
||||
[self _didEdit];
|
||||
- (void)_replaceCharactersInRange:(CPRange)range withCharacters:(CPString)characters
|
||||
{
|
||||
var newValue = [_stringValue stringByReplacingCharactersInRange:range withString:characters];
|
||||
|
||||
if (_invokedByUserEvent)
|
||||
{
|
||||
[self _setStringValue:newValue];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self _setObjectValue:newValue useFormatter:NO];
|
||||
[self setSelectedRange:CPMakeRange(range.location, 0)];
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
// Since we just performed the deletion manually, we don't need the browser to do anything else.
|
||||
[[[self window] platformWindow] _propagateCurrentDOMEvent:NO];
|
||||
// Since we just performed the deletion manually, we don't need the browser to do anything else.
|
||||
[[[self window] platformWindow] _propagateCurrentDOMEvent:NO];
|
||||
#endif
|
||||
}
|
||||
|
||||
[self _didEdit];
|
||||
}
|
||||
|
||||
#pragma mark Setting the Delegate
|
||||
|
||||
- (void)setDelegate:(id)aDelegate
|
||||
- (void)setDelegate:(id <CPTextFieldDelegate>)aDelegate
|
||||
{
|
||||
var defaultCenter = [CPNotificationCenter defaultCenter];
|
||||
|
||||
//unsubscribe the existing delegate if it exists
|
||||
if (_delegate)
|
||||
{
|
||||
[defaultCenter removeObserver:_delegate name:CPControlTextDidBeginEditingNotification object:self];
|
||||
[defaultCenter removeObserver:_delegate name:CPControlTextDidChangeNotification object:self];
|
||||
[defaultCenter removeObserver:_delegate name:CPControlTextDidEndEditingNotification object:self];
|
||||
[defaultCenter removeObserver:_delegate name:CPTextFieldDidFocusNotification object:self];
|
||||
[defaultCenter removeObserver:_delegate name:CPTextFieldDidBlurNotification object:self];
|
||||
}
|
||||
if (_delegate === aDelegate)
|
||||
return;
|
||||
|
||||
_delegate = aDelegate;
|
||||
_implementedDelegateMethods = 0;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(control:didFailToFormatString:errorDescription:)])
|
||||
_implementedDelegateMethods |= CPTextFieldDelegate_control_didFailToFormatString_errorDescription_
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(controlTextDidBeginEditing:)])
|
||||
[defaultCenter
|
||||
addObserver:_delegate
|
||||
selector:@selector(controlTextDidBeginEditing:)
|
||||
name:CPControlTextDidBeginEditingNotification
|
||||
object:self];
|
||||
_implementedDelegateMethods |= CPTextFieldDelegate_controlTextDidBeginEditing_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(controlTextDidChange:)])
|
||||
[defaultCenter
|
||||
addObserver:_delegate
|
||||
selector:@selector(controlTextDidChange:)
|
||||
name:CPControlTextDidChangeNotification
|
||||
object:self];
|
||||
|
||||
_implementedDelegateMethods |= CPTextFieldDelegate_controlTextDidChange_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(controlTextDidEndEditing:)])
|
||||
[defaultCenter
|
||||
addObserver:_delegate
|
||||
selector:@selector(controlTextDidEndEditing:)
|
||||
name:CPControlTextDidEndEditingNotification
|
||||
object:self];
|
||||
_implementedDelegateMethods |= CPTextFieldDelegate_controlTextDidEndEditing_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(controlTextDidFocus:)])
|
||||
[defaultCenter
|
||||
addObserver:_delegate
|
||||
selector:@selector(controlTextDidFocus:)
|
||||
name:CPTextFieldDidFocusNotification
|
||||
object:self];
|
||||
_implementedDelegateMethods |= CPTextFieldDelegate_controlTextDidFocus_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(controlTextDidBlur:)])
|
||||
[defaultCenter
|
||||
addObserver:_delegate
|
||||
selector:@selector(controlTextDidBlur:)
|
||||
name:CPTextFieldDidBlurNotification
|
||||
object:self];
|
||||
_implementedDelegateMethods |= CPTextFieldDelegate_controlTextDidBlur_;
|
||||
}
|
||||
|
||||
- (id)delegate
|
||||
@@ -1705,7 +1843,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
|
||||
if (contentView)
|
||||
{
|
||||
[contentView setHidden:[self hasThemeState:CPThemeStateEditing]];
|
||||
[contentView setHidden:(_stringValue && _stringValue.length > 0) && [self hasThemeState:CPThemeStateEditing]];
|
||||
|
||||
var string = "";
|
||||
|
||||
@@ -1729,6 +1867,9 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
[contentView setTextShadowColor:[self currentValueForThemeAttribute:@"text-shadow-color"]];
|
||||
[contentView setTextShadowOffset:[self currentValueForThemeAttribute:@"text-shadow-offset"]];
|
||||
}
|
||||
|
||||
if (_isEditing)
|
||||
[self _setCSSStyleForInputElement];
|
||||
}
|
||||
|
||||
- (void)takeValueFromKeyPath:(CPString)aKeyPath ofObjects:(CPArray)objects
|
||||
@@ -1749,6 +1890,20 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
|
||||
#pragma mark Overrides
|
||||
|
||||
/*!
|
||||
Sets the text color of the receiver.
|
||||
|
||||
@param aColor - A CPColor object.
|
||||
*/
|
||||
- (void)setTextColor:(CPColor)aColor
|
||||
{
|
||||
// We don't want to change the text-color of the placeHolder of the textField
|
||||
var placeholderColor = [self valueForThemeAttribute:@"text-color" inState:CPTextFieldStatePlaceholder];
|
||||
|
||||
[super setTextColor:aColor];
|
||||
[self setValue:placeholderColor forThemeAttribute:@"text-color" inState:CPTextFieldStatePlaceholder];
|
||||
}
|
||||
|
||||
- (void)viewDidHide
|
||||
{
|
||||
[super viewDidHide];
|
||||
@@ -1795,7 +1950,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder");
|
||||
if (!wind)
|
||||
return NO;
|
||||
|
||||
var frame = [self convertRectToBase:[self bounds]],
|
||||
var frame = [self convertRectToBase:[self contentRectForBounds:[self bounds]]],
|
||||
usableRect = [[wind platformWindow] usableContentFrame];
|
||||
|
||||
frame.origin = [wind convertBaseToGlobal:frame.origin];
|
||||
@@ -1827,7 +1982,11 @@ var CPTextFieldIsEditableKey = "CPTextFieldIsEditableKey",
|
||||
CPTextFieldLineBreakModeKey = "CPTextFieldLineBreakModeKey",
|
||||
CPTextFieldAlignmentKey = "CPTextFieldAlignmentKey",
|
||||
CPTextFieldBackgroundColorKey = "CPTextFieldBackgroundColorKey",
|
||||
CPTextFieldPlaceholderStringKey = "CPTextFieldPlaceholderStringKey";
|
||||
CPTextFieldPlaceholderStringKey = "CPTextFieldPlaceholderStringKey",
|
||||
CPTextFieldUsesSingleLineMode = "CPTextFieldUsesSingleLineMode",
|
||||
CPTextFieldWraps = "CPTextFieldWraps",
|
||||
CPTextFieldScrolls = "CPTextFieldScrolls";
|
||||
|
||||
|
||||
@implementation CPTextField (CPCoding)
|
||||
|
||||
@@ -1853,6 +2012,10 @@ var CPTextFieldIsEditableKey = "CPTextFieldIsEditableKey",
|
||||
[self setAlignment:[aCoder decodeIntForKey:CPTextFieldAlignmentKey]];
|
||||
|
||||
[self setPlaceholderString:[aCoder decodeObjectForKey:CPTextFieldPlaceholderStringKey]];
|
||||
|
||||
[self _setUsesSingleLineMode:[aCoder decodeBoolForKey:CPTextFieldUsesSingleLineMode]];
|
||||
[self _setWraps:[aCoder decodeBoolForKey:CPTextFieldWraps]];
|
||||
[self _setScrolls:[aCoder decodeBoolForKey:CPTextFieldScrolls]];
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -1877,6 +2040,10 @@ var CPTextFieldIsEditableKey = "CPTextFieldIsEditableKey",
|
||||
[aCoder encodeInt:[self alignment] forKey:CPTextFieldAlignmentKey];
|
||||
|
||||
[aCoder encodeObject:_placeholderString forKey:CPTextFieldPlaceholderStringKey];
|
||||
|
||||
[aCoder encodeBool:_usesSingleLineMode forKey:CPTextFieldUsesSingleLineMode];
|
||||
[aCoder encodeBool:_wraps forKey:CPTextFieldWraps];
|
||||
[aCoder encodeBool:_scrolls forKey:CPTextFieldScrolls];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1907,6 +2074,23 @@ var CPTextFieldIsEditableKey = "CPTextFieldIsEditableKey",
|
||||
[_source setObjectValue:aValue];
|
||||
}
|
||||
|
||||
- (void)reverseSetValueFor:(CPString)aBinding
|
||||
{
|
||||
var destination = [_info objectForKey:CPObservedObjectKey],
|
||||
keyPath = [_info objectForKey:CPObservedKeyPathKey],
|
||||
options = [_info objectForKey:CPOptionsKey],
|
||||
newValue = [self valueForBinding:aBinding],
|
||||
value = [destination valueForKeyPath:keyPath];
|
||||
|
||||
if (CPIsControllerMarker(value) && newValue === nil) return;
|
||||
|
||||
newValue = [self reverseTransformValue:newValue withOptions:options];
|
||||
|
||||
[self suppressSpecificNotificationFromObject:destination keyPath:keyPath];
|
||||
[destination setValue:newValue forKeyPath:keyPath];
|
||||
[self unsuppressSpecificNotificationFromObject:destination keyPath:keyPath];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation _CPTextFieldPatternValueBinder : CPValueWithPatternBinding
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
@import <Foundation/CPKeyedUnarchiver.j>
|
||||
|
||||
@class CPView
|
||||
@class _CPThemeAttribute
|
||||
|
||||
var CPThemesByName = { },
|
||||
CPThemeDefaultTheme = nil,
|
||||
@@ -240,7 +241,7 @@ var CPThemesByName = { },
|
||||
@param aClass The themed class in which to look for the attribute
|
||||
@return A value or nil
|
||||
*/
|
||||
- (id)valueForAttributeWithName:(CPString)aName inState:(CPThemeState)aState forClass:(id)aClass
|
||||
- (id)valueForAttributeWithName:(CPString)aName inState:(ThemeState)aState forClass:(id)aClass
|
||||
{
|
||||
var attribute = [self attributeWithName:aName forClass:aClass];
|
||||
|
||||
@@ -314,6 +315,164 @@ var CPThemeNameKey = @"CPThemeNameKey",
|
||||
|
||||
@end
|
||||
|
||||
/*!
|
||||
* ThemeStates are immutable objects representing a particular ThemeState. Applications should never be creating
|
||||
* ThemeStates directly but should instead use the CPThemeState function.
|
||||
*/
|
||||
function ThemeState(stateNames)
|
||||
{
|
||||
var stateNameKeys = [];
|
||||
this._stateNames = {};
|
||||
|
||||
for (key in stateNames)
|
||||
{
|
||||
if (!stateNames.hasOwnProperty(key))
|
||||
continue;
|
||||
if (key !== 'normal')
|
||||
{
|
||||
this._stateNames[key] = true;
|
||||
stateNameKeys.push(key);
|
||||
}
|
||||
}
|
||||
|
||||
if (stateNameKeys.length === 0)
|
||||
{
|
||||
stateNameKeys.push('normal');
|
||||
this._stateNames['normal'] = true;
|
||||
}
|
||||
|
||||
stateNameKeys.sort();
|
||||
this._stateNameString = stateNameKeys[0];
|
||||
|
||||
var stateNameLength = stateNameKeys.length;
|
||||
for (var stateIndex = 1; stateIndex < stateNameLength; stateIndex++)
|
||||
this._stateNameString = this._stateNameString + "+" + stateNameKeys[stateIndex];
|
||||
this._stateNameCount = stateNameLength;
|
||||
}
|
||||
|
||||
ThemeState.prototype.toString = function()
|
||||
{
|
||||
return this._stateNameString;
|
||||
}
|
||||
|
||||
ThemeState.prototype.hasThemeState = function(aState)
|
||||
{
|
||||
if (!aState || !aState._stateNames)
|
||||
return false;
|
||||
|
||||
// We can do this in O(n) because both states have their stateNames already sorted.
|
||||
for (var stateName in aState._stateNames)
|
||||
{
|
||||
if (!aState._stateNames.hasOwnProperty(stateName))
|
||||
continue;
|
||||
|
||||
if (!this._stateNames[stateName])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ThemeState.prototype.isSubsetOf = function(aState)
|
||||
{
|
||||
if (aState._stateNameCount < this._stateNameCount)
|
||||
return false;
|
||||
|
||||
for (var key in this._stateNames)
|
||||
{
|
||||
if (!this._stateNames.hasOwnProperty(key))
|
||||
continue;
|
||||
|
||||
if (!aState._stateNames[key])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ThemeState.prototype.without = function(aState)
|
||||
{
|
||||
if (!aState || aState === [CPNull null])
|
||||
return this;
|
||||
|
||||
var newStates = {};
|
||||
for (var stateName in this._stateNames)
|
||||
{
|
||||
if (!this._stateNames.hasOwnProperty(stateName))
|
||||
continue;
|
||||
|
||||
if (!aState._stateNames[stateName])
|
||||
newStates[stateName] = true;
|
||||
}
|
||||
|
||||
return ThemeState._cacheThemeState(new ThemeState(newStates));
|
||||
}
|
||||
|
||||
ThemeState.prototype.and = function(aState)
|
||||
{
|
||||
return CPThemeState(this, aState);
|
||||
}
|
||||
|
||||
var CPThemeStates = {};
|
||||
|
||||
ThemeState._cacheThemeState = function(aState)
|
||||
{
|
||||
// We do this caching so themeState equality works. Basically, doing CPThemeState('foo+bar') === CPThemeState('bar', 'foo') will return true.
|
||||
var themeState = CPThemeStates[String(aState)];
|
||||
if (themeState === undefined)
|
||||
{
|
||||
themeState = aState;
|
||||
CPThemeStates[String(themeState)] = themeState;
|
||||
}
|
||||
return themeState;
|
||||
}
|
||||
|
||||
/*!
|
||||
* This method can be called in multiple ways:
|
||||
* CPThemeState('state1') - creates a new CPThemeState that corresponds to the string 'state1'
|
||||
* CPThemeState('state1', 'state2') - creates a new composite CPThemeState made up of both 'state1' or 'state2'
|
||||
* CPThemeState('state1+state2') - The same as CPThemeState('state1', 'state2')
|
||||
* CPThemeState(state1, state2) - creates a new composite CPThemeState made up of state1 and state2
|
||||
* where state1 and state2 are not strings but are themselves CPThemeStates.
|
||||
*/
|
||||
function CPThemeState()
|
||||
{
|
||||
if (arguments.length < 1)
|
||||
throw "CPThemeState() must be called with at least one string argument";
|
||||
|
||||
var themeState;
|
||||
if (arguments.length === 1 && typeof arguments[0] === 'string')
|
||||
{
|
||||
themeState = CPThemeStates[arguments[0]];
|
||||
if (themeState !== undefined)
|
||||
return themeState;
|
||||
}
|
||||
|
||||
var stateNames = {};
|
||||
for (var argIndex = 0; argIndex < arguments.length; argIndex++)
|
||||
{
|
||||
if (arguments[argIndex] === [CPNull null] || !arguments[argIndex])
|
||||
continue;
|
||||
|
||||
if (typeof arguments[argIndex] === 'object')
|
||||
{
|
||||
for (var stateName in arguments[argIndex]._stateNames)
|
||||
{
|
||||
if (!arguments[argIndex]._stateNames.hasOwnProperty(stateName))
|
||||
continue;
|
||||
stateNames[stateName] = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var allNames = arguments[argIndex].split('+');
|
||||
for (var nameIndex = 0; nameIndex < allNames.length; nameIndex++)
|
||||
stateNames[allNames[nameIndex]] = true;
|
||||
}
|
||||
}
|
||||
|
||||
themeState = ThemeState._cacheThemeState(new ThemeState(stateNames));
|
||||
return themeState;
|
||||
}
|
||||
|
||||
@implementation _CPThemeKeyedUnarchiver : CPKeyedUnarchiver
|
||||
{
|
||||
CPBundle _bundle;
|
||||
@@ -341,88 +500,28 @@ var CPThemeNameKey = @"CPThemeNameKey",
|
||||
|
||||
@end
|
||||
|
||||
var CPThemeStates = {},
|
||||
CPThemeStateNames = {},
|
||||
CPThemeStateCount = 0;
|
||||
|
||||
function CPThemeState(aStateName)
|
||||
{
|
||||
var state = CPThemeStates[aStateName];
|
||||
|
||||
if (state === undefined)
|
||||
{
|
||||
if (aStateName.indexOf('+') === -1)
|
||||
state = 1 << CPThemeStateCount++;
|
||||
else
|
||||
{
|
||||
var state = 0,
|
||||
states = aStateName.split('+'),
|
||||
count = states.length;
|
||||
|
||||
while (count--)
|
||||
{
|
||||
var stateName = states[count],
|
||||
individualState = CPThemeStates[stateName];
|
||||
|
||||
if (individualState === undefined)
|
||||
{
|
||||
individualState = 1 << CPThemeStateCount++;
|
||||
CPThemeStates[stateName] = individualState;
|
||||
CPThemeStateNames[individualState] = stateName;
|
||||
}
|
||||
|
||||
state |= individualState;
|
||||
}
|
||||
}
|
||||
|
||||
CPThemeStates[aStateName] = state;
|
||||
CPThemeStateNames[state] = aStateName;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
function CPThemeStateName(aState)
|
||||
{
|
||||
var name = CPThemeStateNames[aState];
|
||||
|
||||
if (name !== undefined)
|
||||
return name;
|
||||
|
||||
if (!(aState & (aState - 1)))
|
||||
return "";
|
||||
|
||||
var state = 1,
|
||||
name = "";
|
||||
|
||||
for (; state < aState; state <<= 1)
|
||||
if (aState & state)
|
||||
name += (name.length === 0 ? '' : '+') + CPThemeStateNames[state];
|
||||
|
||||
CPThemeStateNames[aState] = name;
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
CPThemeStateNames[0] = "normal";
|
||||
CPThemeStateNormal = CPThemeStates["normal"] = 0;
|
||||
CPThemeStateDisabled = CPThemeState("disabled");
|
||||
CPThemeStateHovered = CPThemeState("hovered");
|
||||
CPThemeStateHighlighted = CPThemeState("highlighted");
|
||||
CPThemeStateSelected = CPThemeState("selected");
|
||||
CPThemeStateTableDataView = CPThemeState("tableDataView");
|
||||
CPThemeStateSelectedDataView = CPThemeState("selectedTableDataView");
|
||||
CPThemeStateGroupRow = CPThemeState("CPThemeStateGroupRow");
|
||||
CPThemeStateBezeled = CPThemeState("bezeled");
|
||||
CPThemeStateBordered = CPThemeState("bordered");
|
||||
CPThemeStateEditable = CPThemeState("editable");
|
||||
CPThemeStateEditing = CPThemeState("editing");
|
||||
CPThemeStateVertical = CPThemeState("vertical");
|
||||
CPThemeStateDefault = CPThemeState("default");
|
||||
CPThemeStateCircular = CPThemeState("circular");
|
||||
CPThemeStateAutocompleting = CPThemeState("autocompleting");
|
||||
CPThemeStateMainWindow = CPThemeState("mainWindow");
|
||||
CPThemeStateKeyWindow = CPThemeState("keyWindow");
|
||||
CPThemeStateNormal = CPThemeState("normal");
|
||||
CPThemeStateDisabled = CPThemeState("disabled");
|
||||
CPThemeStateHovered = CPThemeState("hovered");
|
||||
CPThemeStateHighlighted = CPThemeState("highlighted");
|
||||
CPThemeStateSelected = CPThemeState("selected");
|
||||
CPThemeStateTableDataView = CPThemeState("tableDataView");
|
||||
CPThemeStateSelectedDataView = CPThemeState("selectedTableDataView");
|
||||
CPThemeStateGroupRow = CPThemeState("CPThemeStateGroupRow");
|
||||
CPThemeStateBezeled = CPThemeState("bezeled");
|
||||
CPThemeStateBordered = CPThemeState("bordered");
|
||||
CPThemeStateEditable = CPThemeState("editable");
|
||||
CPThemeStateEditing = CPThemeState("editing");
|
||||
CPThemeStateVertical = CPThemeState("vertical");
|
||||
CPThemeStateDefault = CPThemeState("default");
|
||||
CPThemeStateCircular = CPThemeState("circular");
|
||||
CPThemeStateAutocompleting = CPThemeState("autocompleting");
|
||||
CPThemeStateFirstResponder = CPThemeState("firstResponder");
|
||||
CPThemeStateMainWindow = CPThemeState("mainWindow");
|
||||
CPThemeStateKeyWindow = CPThemeState("keyWindow");
|
||||
CPThemeStateControlSizeRegular = CPThemeState("controlSizeRegular");
|
||||
CPThemeStateControlSizeSmall = CPThemeState("controlSizeSmall");
|
||||
CPThemeStateControlSizeMini = CPThemeState("controlSizeMini");
|
||||
|
||||
@implementation _CPThemeAttribute : CPObject
|
||||
{
|
||||
@@ -464,11 +563,6 @@ CPThemeStateKeyWindow = CPThemeState("keyWindow");
|
||||
return [_values count] > 0;
|
||||
}
|
||||
|
||||
- (BOOL)isTrivial
|
||||
{
|
||||
return ([_values count] === 1) && (Number([_values allKeys][0]) === CPThemeStateNormal);
|
||||
}
|
||||
|
||||
- (void)setValue:(id)aValue
|
||||
{
|
||||
_cache = {};
|
||||
@@ -479,7 +573,7 @@ CPThemeStateKeyWindow = CPThemeState("keyWindow");
|
||||
_values = @{ String(CPThemeStateNormal): aValue };
|
||||
}
|
||||
|
||||
- (void)setValue:(id)aValue forState:(CPThemeState)aState
|
||||
- (void)setValue:(id)aValue forState:(ThemeState)aState
|
||||
{
|
||||
_cache = { };
|
||||
|
||||
@@ -494,44 +588,34 @@ CPThemeStateKeyWindow = CPThemeState("keyWindow");
|
||||
return [self valueForState:CPThemeStateNormal];
|
||||
}
|
||||
|
||||
- (id)valueForState:(CPThemeState)aState
|
||||
- (id)valueForState:(ThemeState)aState
|
||||
{
|
||||
var value = _cache[aState];
|
||||
var stateName = String(aState),
|
||||
value = _cache[stateName];
|
||||
|
||||
// This can be nil.
|
||||
if (value !== undefined)
|
||||
return value;
|
||||
|
||||
value = [_values objectForKey:String(aState)];
|
||||
value = [_values objectForKey:stateName];
|
||||
|
||||
// If we don't have a value, and we have a non-normal state...
|
||||
if ((value === undefined || value === nil) && aState !== CPThemeStateNormal)
|
||||
if (value === undefined || value === nil)
|
||||
{
|
||||
// If this is a composite state (not a power of 2), find the closest partial subset match.
|
||||
if (aState & (aState - 1))
|
||||
// If this is a composite state, find the closest partial subset match.
|
||||
if (aState._stateNameCount > 1)
|
||||
{
|
||||
var highestOneCount = 0,
|
||||
states = [_values allKeys],
|
||||
count = states.length;
|
||||
var states = [_values allKeys],
|
||||
count = states.length,
|
||||
largestThemeState = 0;
|
||||
|
||||
while (count--)
|
||||
{
|
||||
// states[count] is a string!
|
||||
var state = Number(states[count]);
|
||||
var stateObject = CPThemeState(states[count]);
|
||||
|
||||
// A & B = A iff A < B
|
||||
if ((state & aState) === state)
|
||||
if (stateObject.isSubsetOf(aState) && stateObject._stateNameCount > largestThemeState)
|
||||
{
|
||||
var oneCount = cachedNumberOfOnes[state];
|
||||
|
||||
if (oneCount === undefined)
|
||||
oneCount = numberOfOnes(state);
|
||||
|
||||
if (oneCount > highestOneCount)
|
||||
{
|
||||
highestOneCount = oneCount;
|
||||
value = [_values objectForKey:String(state)];
|
||||
}
|
||||
value = [_values objectForKey:states[count]];
|
||||
largestThemeState = stateObject._stateNameCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -554,7 +638,7 @@ CPThemeStateKeyWindow = CPThemeState("keyWindow");
|
||||
value = nil;
|
||||
}
|
||||
|
||||
_cache[aState] = value;
|
||||
_cache[stateName] = value;
|
||||
|
||||
return value;
|
||||
}
|
||||
@@ -596,10 +680,10 @@ CPThemeStateKeyWindow = CPThemeState("keyWindow");
|
||||
|
||||
if ([aCoder containsValueForKey:@"value"])
|
||||
{
|
||||
var state = CPThemeStateNormal;
|
||||
var state = String(CPThemeStateNormal);
|
||||
|
||||
if ([aCoder containsValueForKey:@"state"])
|
||||
state = CPThemeState([aCoder decodeObjectForKey:@"state"]);
|
||||
state = [aCoder decodeObjectForKey:@"state"];
|
||||
|
||||
[_values setObject:[aCoder decodeObjectForKey:"value"] forKey:state];
|
||||
}
|
||||
@@ -613,7 +697,7 @@ CPThemeStateKeyWindow = CPThemeState("keyWindow");
|
||||
{
|
||||
var key = keys[count];
|
||||
|
||||
[_values setObject:[encodedValues objectForKey:key] forKey:CPThemeState(key)];
|
||||
[_values setObject:[encodedValues objectForKey:key] forKey:key];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -633,8 +717,8 @@ CPThemeStateKeyWindow = CPThemeState("keyWindow");
|
||||
{
|
||||
var onlyKey = keys[0];
|
||||
|
||||
if (Number(onlyKey) !== CPThemeStateNormal)
|
||||
[aCoder encodeObject:CPThemeStateName(Number(onlyKey)) forKey:@"state"];
|
||||
if (onlyKey !== String(CPThemeStateNormal))
|
||||
[aCoder encodeObject:onlyKey forKey:@"state"];
|
||||
|
||||
[aCoder encodeObject:[_values objectForKey:onlyKey] forKey:@"value"];
|
||||
}
|
||||
@@ -646,7 +730,7 @@ CPThemeStateKeyWindow = CPThemeState("keyWindow");
|
||||
{
|
||||
var key = keys[count];
|
||||
|
||||
[encodedValues setObject:[_values objectForKey:key] forKey:CPThemeStateName(Number(key))];
|
||||
[encodedValues setObject:[_values objectForKey:key] forKey:key];
|
||||
}
|
||||
|
||||
[aCoder encodeObject:encodedValues forKey:@"values"];
|
||||
@@ -655,35 +739,6 @@ CPThemeStateKeyWindow = CPThemeState("keyWindow");
|
||||
|
||||
@end
|
||||
|
||||
var cachedNumberOfOnes = [ 0 /*000000*/, 1 /*000001*/, 1 /*000010*/, 2 /*000011*/, 1 /*000100*/, 2 /*000101*/, 2 /*000110*/,
|
||||
3 /*000111*/, 1 /*001000*/, 2 /*001001*/, 2 /*001010*/, 3 /*001011*/, 2 /*001100*/, 3 /*001101*/,
|
||||
3 /*001110*/, 4 /*001111*/, 1 /*010000*/, 2 /*010001*/, 2 /*010010*/, 3 /*010011*/, 2 /*010100*/,
|
||||
3 /*010101*/, 3 /*010110*/, 4 /*010111*/, 2 /*011000*/, 3 /*011001*/, 3 /*011010*/, 4 /*011011*/,
|
||||
3 /*011100*/, 4 /*011101*/, 4 /*011110*/, 5 /*011111*/, 1 /*100000*/, 2 /*100001*/, 2 /*100010*/,
|
||||
3 /*100011*/, 2 /*100100*/, 3 /*100101*/, 3 /*100110*/, 4 /*100111*/, 2 /*101000*/, 3 /*101001*/,
|
||||
3 /*101010*/, 4 /*101011*/, 3 /*101100*/, 4 /*101101*/, 4 /*101110*/, 5 /*101111*/, 2 /*110000*/,
|
||||
3 /*110001*/, 3 /*110010*/, 4 /*110011*/, 3 /*110100*/, 4 /*110101*/, 4 /*110110*/, 5 /*110111*/,
|
||||
3 /*111000*/, 4 /*111001*/, 4 /*111010*/, 5 /*111011*/, 4 /*111100*/, 5 /*111101*/, 5 /*111110*/,
|
||||
6 /*111111*/ ];
|
||||
|
||||
var numberOfOnes = function(aNumber)
|
||||
{
|
||||
var count = 0,
|
||||
slot = aNumber;
|
||||
|
||||
while (aNumber)
|
||||
{
|
||||
++count;
|
||||
aNumber &= (aNumber - 1);
|
||||
}
|
||||
|
||||
cachedNumberOfOnes[slot] = count;
|
||||
|
||||
return count;
|
||||
};
|
||||
|
||||
numberOfOnes.displayName = "numberOfOnes";
|
||||
|
||||
function CPThemeAttributeEncode(aCoder, aThemeAttribute)
|
||||
{
|
||||
var values = aThemeAttribute._values,
|
||||
@@ -694,7 +749,7 @@ function CPThemeAttributeEncode(aCoder, aThemeAttribute)
|
||||
{
|
||||
var state = [values allKeys][0];
|
||||
|
||||
if (Number(state) === 0)
|
||||
if (state === String(CPThemeStateNormal))
|
||||
{
|
||||
[aCoder encodeObject:[values objectForKey:state] forKey:key];
|
||||
|
||||
@@ -723,7 +778,7 @@ function CPThemeAttributeDecode(aCoder, anAttributeName, aDefaultValue, aTheme,
|
||||
{
|
||||
var attribute = [aCoder decodeObjectForKey:key];
|
||||
|
||||
if (!attribute.isa || ![attribute isKindOfClass:[_CPThemeAttribute class]])
|
||||
if (!attribute || !attribute.isa || ![attribute isKindOfClass:[_CPThemeAttribute class]])
|
||||
{
|
||||
var themeAttribute = [[_CPThemeAttribute alloc] initWithName:anAttributeName defaultValue:aDefaultValue];
|
||||
|
||||
|
||||
@@ -33,10 +33,35 @@
|
||||
@import "CPTextField.j"
|
||||
@import "CPWindow_Constants.j"
|
||||
|
||||
@class _CPTokenFieldTokenCloseButton
|
||||
@class _CPTokenFieldTokenDisclosureButton
|
||||
|
||||
@global CPApp
|
||||
@global CPTextFieldDidFocusNotification
|
||||
@global CPTextFieldDidBlurNotification
|
||||
|
||||
|
||||
// TODO: should be conform to protocol CPTextFieldDelegate
|
||||
@protocol CPTokenFieldDelegate <CPObject>
|
||||
|
||||
@optional
|
||||
- (BOOL)tokenField:(CPTokenField)tokenField hasMenuForRepresentedObject:(id)representedObject;
|
||||
- (CPArray)tokenField:(CPTokenField)tokenField completionsForSubstring:(CPString)substring indexOfToken:(CPInteger)tokenIndex indexOfSelectedItem:(CPInteger)selectedIndex;
|
||||
- (CPArray)tokenField:(CPTokenField)tokenField shouldAddObjects:(CPArray)tokens atIndex:(CPUInteger)index;
|
||||
- (CPMenu)tokenField:(CPTokenField)tokenField menuForRepresentedObject:(id)representedObject;
|
||||
- (CPString )tokenField:(CPTokenField)tokenField displayStringForRepresentedObject:(id)representedObject;
|
||||
- (id)tokenField:(CPTokenField)tokenField representedObjectForEditingString:(CPString)editingString;
|
||||
|
||||
@end
|
||||
|
||||
var CPTokenFieldDelegate_tokenField_hasMenuForRepresentedObject_ = 1 << 1,
|
||||
CPTokenFieldDelegate_tokenField_completionsForSubstring_indexOfToken_indexOfSelectedItem_ = 1 << 2,
|
||||
CPTokenFieldDelegate_tokenField_shouldAddObjects_atIndex_ = 1 << 3,
|
||||
CPTokenFieldDelegate_tokenField_menuForRepresentedObject_ = 1 << 4,
|
||||
CPTokenFieldDelegate_tokenField_displayStringForRepresentedObject_ = 1 << 5,
|
||||
CPTokenFieldDelegate_tokenField_representedObjectForEditingString_ = 1 << 6;
|
||||
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
|
||||
var CPTokenFieldDOMInputElement = nil,
|
||||
@@ -64,23 +89,26 @@ CPTokenFieldDeleteButtonType = 1;
|
||||
|
||||
@implementation CPTokenField : CPTextField
|
||||
{
|
||||
CPScrollView _tokenScrollView;
|
||||
int _shouldScrollTo;
|
||||
CPScrollView _tokenScrollView;
|
||||
int _shouldScrollTo;
|
||||
|
||||
CPRange _selectedRange;
|
||||
CPRange _selectedRange;
|
||||
|
||||
_CPAutocompleteMenu _autocompleteMenu;
|
||||
CGRect _inputFrame;
|
||||
_CPAutocompleteMenu _autocompleteMenu;
|
||||
CGRect _inputFrame;
|
||||
|
||||
CPTimeInterval _completionDelay;
|
||||
CPTimeInterval _completionDelay;
|
||||
|
||||
CPCharacterSet _tokenizingCharacterSet @accessors(property=tokenizingCharacterSet);
|
||||
CPCharacterSet _tokenizingCharacterSet @accessors(property=tokenizingCharacterSet);
|
||||
|
||||
CPEvent _mouseDownEvent;
|
||||
CPEvent _mouseDownEvent;
|
||||
|
||||
BOOL _shouldNotifyTarget;
|
||||
BOOL _shouldNotifyTarget;
|
||||
|
||||
int _buttonType @accessors(property=buttonType);
|
||||
int _buttonType @accessors(property=buttonType);
|
||||
|
||||
id <CPTokenFieldDelegate> _tokenFieldDelegate;
|
||||
unsigned _implementedTokenFieldDelegateMethods;
|
||||
}
|
||||
|
||||
+ (CPCharacterSet)defaultTokenizingCharacterSet
|
||||
@@ -140,6 +168,41 @@ CPTokenFieldDeleteButtonType = 1;
|
||||
[self addSubview:_tokenScrollView];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Delegate methods
|
||||
|
||||
/*!
|
||||
Set the delegate of the receiver
|
||||
*/
|
||||
- (void)setDelegate:(id <CPTokenFieldDelegate>)aDelegate
|
||||
{
|
||||
if (_tokenFieldDelegate === aDelegate)
|
||||
return;
|
||||
|
||||
_tokenFieldDelegate = aDelegate;
|
||||
_implementedTokenFieldDelegateMethods = 0;
|
||||
|
||||
if ([_tokenFieldDelegate respondsToSelector:@selector(tokenField:hasMenuForRepresentedObject:)])
|
||||
_implementedTokenFieldDelegateMethods |= CPTokenFieldDelegate_tokenField_hasMenuForRepresentedObject_;
|
||||
|
||||
if ([_tokenFieldDelegate respondsToSelector:@selector(tokenField:completionsForSubstring:indexOfToken:indexOfSelectedItem:)])
|
||||
_implementedTokenFieldDelegateMethods |= CPTokenFieldDelegate_tokenField_completionsForSubstring_indexOfToken_indexOfSelectedItem_;
|
||||
|
||||
if ([_tokenFieldDelegate respondsToSelector:@selector(tokenField:shouldAddObjects:atIndex:)])
|
||||
_implementedTokenFieldDelegateMethods |= CPTokenFieldDelegate_tokenField_shouldAddObjects_atIndex_;
|
||||
|
||||
if ([_tokenFieldDelegate respondsToSelector:@selector(tokenField:menuForRepresentedObject:)])
|
||||
_implementedTokenFieldDelegateMethods |= CPTokenFieldDelegate_tokenField_menuForRepresentedObject_;
|
||||
|
||||
if ([_tokenFieldDelegate respondsToSelector:@selector(tokenField:displayStringForRepresentedObject:)])
|
||||
_implementedTokenFieldDelegateMethods |= CPTokenFieldDelegate_tokenField_displayStringForRepresentedObject_;
|
||||
|
||||
if ([_tokenFieldDelegate respondsToSelector:@selector(tokenField:representedObjectForEditingString:)])
|
||||
_implementedTokenFieldDelegateMethods |= CPTokenFieldDelegate_tokenField_representedObjectForEditingString_;
|
||||
|
||||
[super setDelegate:_tokenFieldDelegate];
|
||||
}
|
||||
|
||||
- (_CPAutocompleteMenu)_autocompleteMenu
|
||||
{
|
||||
if (!_autocompleteMenu)
|
||||
@@ -321,6 +384,9 @@ CPTokenFieldDeleteButtonType = 1;
|
||||
|
||||
- (BOOL)becomeFirstResponder
|
||||
{
|
||||
if (![super becomeFirstResponder])
|
||||
return NO;
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
if (CPTokenFieldInputOwner && [CPTokenFieldInputOwner window] !== [self window])
|
||||
[[CPTokenFieldInputOwner window] makeFirstResponder:nil];
|
||||
@@ -1185,12 +1251,10 @@ CPTokenFieldDeleteButtonType = 1;
|
||||
*/
|
||||
- (CPArray)_completionsForSubstring:(CPString)substring indexOfToken:(int)tokenIndex indexOfSelectedItem:(int)selectedIndex
|
||||
{
|
||||
if ([[self delegate] respondsToSelector:@selector(tokenField:completionsForSubstring:indexOfToken:indexOfSelectedItem:)])
|
||||
{
|
||||
return [[self delegate] tokenField:self completionsForSubstring:substring indexOfToken:tokenIndex indexOfSelectedItem:selectedIndex];
|
||||
}
|
||||
if (!(_implementedTokenFieldDelegateMethods & CPTokenFieldDelegate_tokenField_completionsForSubstring_indexOfToken_indexOfSelectedItem_))
|
||||
return [];
|
||||
|
||||
return [];
|
||||
return [_tokenFieldDelegate tokenField:self completionsForSubstring:substring indexOfToken:tokenIndex indexOfSelectedItem:selectedIndex];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -1199,6 +1263,7 @@ CPTokenFieldDeleteButtonType = 1;
|
||||
- (CGPoint)_completionOrigin:(_CPAutocompleteMenu)anAutocompleteMenu
|
||||
{
|
||||
var relativeFrame = _inputFrame ? [[_tokenScrollView documentView] convertRect:_inputFrame toView:self ] : [self bounds];
|
||||
|
||||
return CGPointMake(CGRectGetMinX(relativeFrame), CGRectGetMaxY(relativeFrame));
|
||||
}
|
||||
|
||||
@@ -1212,13 +1277,12 @@ CPTokenFieldDeleteButtonType = 1;
|
||||
*/
|
||||
- (CPString)_displayStringForRepresentedObject:(id)representedObject
|
||||
{
|
||||
if ([[self delegate] respondsToSelector:@selector(tokenField:displayStringForRepresentedObject:)])
|
||||
if (_implementedTokenFieldDelegateMethods & CPTokenFieldDelegate_tokenField_displayStringForRepresentedObject_)
|
||||
{
|
||||
var stringForRepresentedObject = [[self delegate] tokenField:self displayStringForRepresentedObject:representedObject];
|
||||
var stringForRepresentedObject = [_tokenFieldDelegate tokenField:self displayStringForRepresentedObject:representedObject];
|
||||
|
||||
if (stringForRepresentedObject !== nil)
|
||||
{
|
||||
return stringForRepresentedObject;
|
||||
}
|
||||
}
|
||||
|
||||
return representedObject;
|
||||
@@ -1235,10 +1299,10 @@ CPTokenFieldDeleteButtonType = 1;
|
||||
*/
|
||||
- (CPArray)_shouldAddObjects:(CPArray)tokens atIndex:(int)index
|
||||
{
|
||||
var delegate = [self delegate];
|
||||
if ([delegate respondsToSelector:@selector(tokenField:shouldAddObjects:atIndex:)])
|
||||
if (_implementedTokenFieldDelegateMethods & CPTokenFieldDelegate_tokenField_shouldAddObjects_atIndex_)
|
||||
{
|
||||
var approvedObjects = [delegate tokenField:self shouldAddObjects:tokens atIndex:index];
|
||||
var approvedObjects = [_tokenFieldDelegate tokenField:self shouldAddObjects:tokens atIndex:index];
|
||||
|
||||
if (approvedObjects !== nil)
|
||||
return approvedObjects;
|
||||
}
|
||||
@@ -1257,10 +1321,10 @@ CPTokenFieldDeleteButtonType = 1;
|
||||
*/
|
||||
- (id)_representedObjectForEditingString:(CPString)aString
|
||||
{
|
||||
var delegate = [self delegate];
|
||||
if ([delegate respondsToSelector:@selector(tokenField:representedObjectForEditingString:)])
|
||||
if (_implementedTokenFieldDelegateMethods & CPTokenFieldDelegate_tokenField_representedObjectForEditingString_)
|
||||
{
|
||||
var token = [delegate tokenField:self representedObjectForEditingString:aString];
|
||||
var token = [_tokenFieldDelegate tokenField:self representedObjectForEditingString:aString];
|
||||
|
||||
if (token !== nil && token !== undefined)
|
||||
return token;
|
||||
// If nil was returned, assume the string is the represented object. The alternative would have been
|
||||
@@ -1272,23 +1336,22 @@ CPTokenFieldDeleteButtonType = 1;
|
||||
|
||||
- (BOOL)_hasMenuForRepresentedObject:(id)aRepresentedObject
|
||||
{
|
||||
var delegate = [self delegate];
|
||||
if ([delegate respondsToSelector:@selector(tokenField:hasMenuForRepresentedObject:)] &&
|
||||
[delegate respondsToSelector:@selector(tokenField:menuForRepresentedObject:)])
|
||||
return [delegate tokenField:self hasMenuForRepresentedObject:aRepresentedObject];
|
||||
if ((_implementedTokenFieldDelegateMethods & CPTokenFieldDelegate_tokenField_hasMenuForRepresentedObject_) &&
|
||||
(_implementedTokenFieldDelegateMethods & CPTokenFieldDelegate_tokenField_menuForRepresentedObject_))
|
||||
return [_tokenFieldDelegate tokenField:self hasMenuForRepresentedObject:aRepresentedObject];
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (CPMenu)_menuForRepresentedObject:(id)aRepresentedObject
|
||||
{
|
||||
var delegate = [self delegate];
|
||||
if ([delegate respondsToSelector:@selector(tokenField:hasMenuForRepresentedObject:)] &&
|
||||
[delegate respondsToSelector:@selector(tokenField:menuForRepresentedObject:)])
|
||||
if ((_implementedTokenFieldDelegateMethods & CPTokenFieldDelegate_tokenField_hasMenuForRepresentedObject_) &&
|
||||
(_implementedTokenFieldDelegateMethods & CPTokenFieldDelegate_tokenField_menuForRepresentedObject_))
|
||||
{
|
||||
var hasMenu = [delegate tokenField:self hasMenuForRepresentedObject:aRepresentedObject];
|
||||
var hasMenu = [_tokenFieldDelegate tokenField:self hasMenuForRepresentedObject:aRepresentedObject];
|
||||
|
||||
if (hasMenu)
|
||||
return [delegate tokenField:self menuForRepresentedObject:aRepresentedObject] || nil;
|
||||
return [_tokenFieldDelegate tokenField:self menuForRepresentedObject:aRepresentedObject] || nil;
|
||||
}
|
||||
|
||||
return nil;
|
||||
@@ -1389,12 +1452,15 @@ CPTokenFieldDeleteButtonType = 1;
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (BOOL)setThemeState:(CPThemeState)aState
|
||||
- (BOOL)setThemeState:(ThemeState)aState
|
||||
{
|
||||
if (aState.isa && [aState isKindOfClass:CPArray])
|
||||
aState = CPThemeState.apply(null, aState);
|
||||
|
||||
var r = [super setThemeState:aState];
|
||||
|
||||
// Share hover state with the disclosure and delete buttons.
|
||||
if (aState & CPThemeStateHovered)
|
||||
if (aState.hasThemeState(CPThemeStateHovered))
|
||||
{
|
||||
[_disclosureButton setThemeState:CPThemeStateHovered];
|
||||
[_deleteButton setThemeState:CPThemeStateHovered];
|
||||
@@ -1403,12 +1469,15 @@ CPTokenFieldDeleteButtonType = 1;
|
||||
return r;
|
||||
}
|
||||
|
||||
- (BOOL)unsetThemeState:(CPThemeState)aState
|
||||
- (BOOL)unsetThemeState:(ThemeState)aState
|
||||
{
|
||||
if (aState.isa && [aState isKindOfClass:CPArray])
|
||||
aState = CPThemeState.apply(null, aState);
|
||||
|
||||
var r = [super unsetThemeState:aState];
|
||||
|
||||
// Share hover state with the disclosure and delete button.
|
||||
if (aState & CPThemeStateHovered)
|
||||
if (aState.hasThemeState(CPThemeStateHovered))
|
||||
{
|
||||
[_disclosureButton unsetThemeState:CPThemeStateHovered];
|
||||
[_deleteButton unsetThemeState:CPThemeStateHovered];
|
||||
|
||||
@@ -30,6 +30,15 @@
|
||||
|
||||
@global CPApp
|
||||
|
||||
var CPToolbarDelegate_toolbar_itemForItemIdentifier_willBeInsertedIntoToolbar_ = 1 << 0,
|
||||
CPToolbarDelegate_toolbarAllowedItemIdentifiers_ = 1 << 1,
|
||||
CPToolbarDelegate_toolbarDefaultItemIdentifiers_ = 1 << 2,
|
||||
CPToolbarDelegate_toolbarDidRemoveItem_ = 1 << 3,
|
||||
CPToolbarDelegate_toolbarSelectableItemIdentifiers_ = 1 << 4,
|
||||
CPToolbarDelegate_toolbarWillAddItem_ = 1 << 5;
|
||||
|
||||
|
||||
@typedef CPToolbarDisplayMode
|
||||
/*
|
||||
@global
|
||||
@group CPToolbarDisplayMode
|
||||
@@ -51,7 +60,7 @@ CPToolbarDisplayModeIconOnly = 2;
|
||||
*/
|
||||
CPToolbarDisplayModeLabelOnly = 3;
|
||||
|
||||
|
||||
@typedef CPToolbarSizeMode
|
||||
CPToolbarSizeModeDefault = 0;
|
||||
CPToolbarSizeModeRegular = 1;
|
||||
CPToolbarSizeModeSmall = 2;
|
||||
@@ -59,6 +68,20 @@ CPToolbarSizeModeSmall = 2;
|
||||
var CPToolbarsByIdentifier = nil,
|
||||
CPToolbarConfigurationsByIdentifier = nil;
|
||||
|
||||
|
||||
@protocol CPToolbarDelegate <CPObject>
|
||||
|
||||
@optional
|
||||
- (CPToolbarItem)toolbar:(CPToolbar)toolbar itemForItemIdentifier:(CPString)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag;
|
||||
- (CPArray)toolbarAllowedItemIdentifiers:(CPToolbar)toolbar;
|
||||
- (CPArray)toolbarDefaultItemIdentifiers:(CPToolbar)toolbar;
|
||||
- (void)toolbarDidRemoveItem:(CPNotification)notification;
|
||||
- (CPArray)toolbarSelectableItemIdentifiers:(CPToolbar)toolbar;
|
||||
- (void)toolbarWillAddItem:(CPNotification)notification;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
/*!
|
||||
@ingroup appkit
|
||||
@class CPToolbar
|
||||
@@ -89,14 +112,15 @@ var CPToolbarsByIdentifier = nil,
|
||||
@implementation CPToolbar : CPObject
|
||||
{
|
||||
CPString _identifier;
|
||||
CPToolbarDisplayMode _displayMode @accessors(property=displayMode);
|
||||
CPToolbarDisplayMode _displayMode @accessors(property=displayMode);
|
||||
BOOL _showsBaselineSeparator;
|
||||
BOOL _allowsUserCustomization;
|
||||
BOOL _isVisible;
|
||||
CPToolbarSizeMode _sizeMode @accessors(property=sizeMode);
|
||||
CPToolbarSizeMode _sizeMode @accessors(property=sizeMode);
|
||||
int _desiredHeight;
|
||||
|
||||
id _delegate;
|
||||
id <CPToolbarDelegate> _delegate;
|
||||
unsigned _implementedDelegateMethods;
|
||||
|
||||
CPArray _itemIdentifiers;
|
||||
|
||||
@@ -239,6 +263,25 @@ var CPToolbarsByIdentifier = nil,
|
||||
return;
|
||||
|
||||
_delegate = aDelegate;
|
||||
_implementedDelegateMethods = 0;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(toolbar:itemForItemIdentifier:willBeInsertedIntoToolbar:)])
|
||||
_implementedDelegateMethods |= CPToolbarDelegate_toolbar_itemForItemIdentifier_willBeInsertedIntoToolbar_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(toolbarAllowedItemIdentifiers:)])
|
||||
_implementedDelegateMethods |= CPToolbarDelegate_toolbarAllowedItemIdentifiers_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(toolbarDefaultItemIdentifiers:)])
|
||||
_implementedDelegateMethods |= CPToolbarDelegate_toolbarDefaultItemIdentifiers_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(toolbarDidRemoveItem:)])
|
||||
_implementedDelegateMethods |= CPToolbarDelegate_toolbarDidRemoveItem_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(toolbarSelectableItemIdentifiers:)])
|
||||
_implementedDelegateMethods |= CPToolbarDelegate_toolbarSelectableItemIdentifiers_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(toolbarWillAddItem:)])
|
||||
_implementedDelegateMethods |= CPToolbarDelegate_toolbarWillAddItem_;
|
||||
|
||||
[self _reloadToolbarItems];
|
||||
}
|
||||
@@ -289,9 +332,9 @@ var CPToolbarsByIdentifier = nil,
|
||||
// _defaultItems may have been loaded from Cib
|
||||
_itemIdentifiers = [_defaultItems valueForKey:@"itemIdentifier"] || [];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(toolbarDefaultItemIdentifiers:)])
|
||||
if ([self _delegateRespondsToToolbarDefaultItemIdentifiers])
|
||||
{
|
||||
var itemIdentifiersFromDelegate = [_delegate toolbarDefaultItemIdentifiers:self];
|
||||
var itemIdentifiersFromDelegate = [self _sendDelegateToolbarDefaultItemIdentifiers];
|
||||
|
||||
// If we get items both from the Cib and from the delegate method, put the delegate items before the
|
||||
// Cib ones.
|
||||
@@ -316,7 +359,7 @@ var CPToolbarsByIdentifier = nil,
|
||||
item = [_identifiedItems objectForKey:identifier];
|
||||
|
||||
if (!item && _delegate)
|
||||
item = [_delegate toolbar:self itemForItemIdentifier:identifier willBeInsertedIntoToolbar:YES];
|
||||
item = [self _sendDelegateItemForItemIdentifier:identifier willBeInsertedIntoToolbar:YES];
|
||||
|
||||
item = [item copy];
|
||||
|
||||
@@ -394,12 +437,14 @@ var CPToolbarsByIdentifier = nil,
|
||||
- (id)_itemForItemIdentifier:(CPString)identifier willBeInsertedIntoToolbar:(BOOL)toolbar
|
||||
{
|
||||
var item = [_identifiedItems objectForKey:identifier];
|
||||
|
||||
if (!item)
|
||||
{
|
||||
item = [CPToolbarItem _standardItemWithItemIdentifier:identifier];
|
||||
|
||||
if (_delegate && !item)
|
||||
{
|
||||
item = [[_delegate toolbar:self itemForItemIdentifier:identifier willBeInsertedIntoToolbar:toolbar] copy];
|
||||
item = [[self _sendDelegateItemForItemIdentifier:identifier willBeInsertedIntoToolbar:toolbar] copy];
|
||||
if (!item)
|
||||
[CPException raise:CPInvalidArgumentException
|
||||
reason:@"Toolbar delegate " + _delegate + " returned nil toolbar item for identifier " + identifier];
|
||||
@@ -424,11 +469,11 @@ var CPToolbarsByIdentifier = nil,
|
||||
/* @ignore */
|
||||
- (id)_defaultToolbarItems
|
||||
{
|
||||
if (!_defaultItems && [_delegate respondsToSelector:@selector(toolbarDefaultItemIdentifiers:)])
|
||||
if (!_defaultItems && [self _delegateRespondsToToolbarDefaultItemIdentifiers])
|
||||
{
|
||||
_defaultItems = [];
|
||||
|
||||
var identifiers = [_delegate toolbarDefaultItemIdentifiers:self],
|
||||
var identifiers = [self _sendDelegateToolbarDefaultItemIdentifiers],
|
||||
index = 0,
|
||||
count = [identifiers count];
|
||||
|
||||
@@ -800,7 +845,6 @@ var _CPToolbarItemInfoMake = function(anIndex, aView, aLabel, aMinWidth)
|
||||
var index = 0,
|
||||
count = _visibleItems.length,
|
||||
x = contentInset.left,
|
||||
contentInset = [self valueForThemeAttribute:@"content-inset"],
|
||||
y = contentInset.top;
|
||||
|
||||
for (; index < count; ++index)
|
||||
@@ -1240,3 +1284,89 @@ var LABEL_MARGIN = 2.0;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation CPToolbar (CPToolbarDelegate)
|
||||
|
||||
/*
|
||||
@ignore
|
||||
Return YES if the delegate implements toolbarDefaultItemIdentifiers:
|
||||
*/
|
||||
- (BOOL)_delegateRespondsToToolbarDefaultItemIdentifiers
|
||||
{
|
||||
return _implementedDelegateMethods & CPToolbarDelegate_toolbarDefaultItemIdentifiers_;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call the delegate toolbar:itemForItemIdentifier:willBeInsertedIntoToolbar:
|
||||
*/
|
||||
- (CPToolbarItem)_sendDelegateItemForItemIdentifier:(CPString)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPToolbarDelegate_toolbar_itemForItemIdentifier_willBeInsertedIntoToolbar_))
|
||||
return nil;
|
||||
|
||||
return [_delegate toolbar:self itemForItemIdentifier:itemIdentifier willBeInsertedIntoToolbar:flag];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call the delegate toolbarAllowedItemIdentifiers:
|
||||
*/
|
||||
- (CPArray)_sendDelegateToolbarAllowedItemIdentifiers
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPToolbarDelegate_toolbarAllowedItemIdentifiers_))
|
||||
return [];
|
||||
|
||||
return [_delegate toolbarAllowedItemIdentifiers:self];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call the delegate toolbarDefaultItemIdentifiers:
|
||||
*/
|
||||
- (CPArray)_sendDelegateToolbarDefaultItemIdentifiers
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPToolbarDelegate_toolbarDefaultItemIdentifiers_))
|
||||
return [];
|
||||
|
||||
return [_delegate toolbarDefaultItemIdentifiers:self];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call the delegate toolbarDidRemoveItem:
|
||||
*/
|
||||
- (void)_sendDelegateToolbarDidRemoveItem:(CPNotification)notification
|
||||
{
|
||||
if (!(_delegate & CPToolbarDelegate_toolbarDidRemoveItem_))
|
||||
return;
|
||||
|
||||
[_delegate toolbarDidRemoveItem:notification];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call the delegate toolbarSelectableItemIdentifiers:
|
||||
*/
|
||||
- (CPArray)_sendDelegateToolbarSelectableItemIdentifiers
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPToolbarDelegate_toolbarSelectableItemIdentifiers_))
|
||||
return [];
|
||||
|
||||
return [_delegate toolbarSelectableItemIdentifiers:self];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call the delegate toolbarWillAddItem:
|
||||
*/
|
||||
- (void)_sendDelegateToolbarWillAddItem:(CPNotification)notification
|
||||
{
|
||||
if (!(_delegate & CPToolbarDelegate_toolbarWillAddItem_))
|
||||
return;
|
||||
|
||||
[_delegate toolbarWillAddItem:notification];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -40,9 +40,12 @@
|
||||
@class CPMenu
|
||||
@class CPClipView
|
||||
@class CPScrollView
|
||||
@class CALayer
|
||||
|
||||
@global appkit_tag_dom_elements
|
||||
|
||||
@typedef _CPViewFullScreenModeState
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
|
||||
if (typeof(appkit_tag_dom_elements) !== "undefined" && appkit_tag_dom_elements)
|
||||
@@ -172,6 +175,7 @@ var CPViewFlags = { },
|
||||
BOOL _postsBoundsChangedNotifications;
|
||||
BOOL _inhibitFrameAndBoundsChangedNotifications;
|
||||
BOOL _inLiveResize;
|
||||
BOOL _isSuperviewAClipView;
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
DOMElement _DOMElement;
|
||||
@@ -228,6 +232,8 @@ var CPViewFlags = { },
|
||||
Function _toolTipFunctionIn;
|
||||
Function _toolTipFunctionOut;
|
||||
BOOL _toolTipInstalled;
|
||||
|
||||
BOOL _isObserving;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -343,6 +349,9 @@ var CPViewFlags = { },
|
||||
_scaleSize = CGSizeMake(1.0, 1.0);
|
||||
_isScaled = NO;
|
||||
|
||||
_theme = [CPTheme defaultTheme];
|
||||
_themeState = CPThemeStateNormal;
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
_DOMElement = DOMElementPrototype.cloneNode(false);
|
||||
AppKitTagDOMElement(self, _DOMElement);
|
||||
@@ -354,9 +363,6 @@ var CPViewFlags = { },
|
||||
_DOMImageSizes = [];
|
||||
#endif
|
||||
|
||||
_theme = [CPTheme defaultTheme];
|
||||
_themeState = CPThemeStateNormal;
|
||||
|
||||
[self _setupToolTipHandlers];
|
||||
[self _setupViewFlags];
|
||||
|
||||
@@ -508,8 +514,12 @@ var CPViewFlags = { },
|
||||
[CPException raise:CPInvalidArgumentException reason:"can't insert a subview in duplicate (probably partially decoded)"];
|
||||
#endif
|
||||
|
||||
// Notify the subview that it will be moving.
|
||||
[aSubview viewWillMoveToSuperview:self];
|
||||
|
||||
// We will have to adjust the z-index of all views starting at this index.
|
||||
var count = _subviews.length;
|
||||
var count = _subviews.length,
|
||||
lastWindow;
|
||||
|
||||
// Dirty the key view loop, in case the window wants to auto recalculate it
|
||||
[[self window] _dirtyKeyViewLoop];
|
||||
@@ -537,14 +547,12 @@ var CPViewFlags = { },
|
||||
}
|
||||
else
|
||||
{
|
||||
var superview = aSubview._superview;
|
||||
|
||||
lastWindow = [superview window];
|
||||
|
||||
// Remove the view from its previous superview.
|
||||
[aSubview removeFromSuperview];
|
||||
|
||||
// Set the subview's window to our own.
|
||||
[aSubview _setWindow:_window];
|
||||
|
||||
// Notify the subview that it will be moving.
|
||||
[aSubview viewWillMoveToSuperview:self];
|
||||
[aSubview _removeFromSuperview];
|
||||
|
||||
// Set ourselves as the superview.
|
||||
aSubview._superview = self;
|
||||
@@ -579,6 +587,28 @@ var CPViewFlags = { },
|
||||
|
||||
[aSubview viewDidMoveToSuperview];
|
||||
|
||||
// Set the subview's window to our own.
|
||||
if (_window)
|
||||
[aSubview _setWindow:_window];
|
||||
|
||||
if (!_window && lastWindow)
|
||||
[aSubview _setWindow:nil];
|
||||
|
||||
// This method might be called before we are fully unarchived, in which case the theme state isn't set up yet
|
||||
// and none of the below matters anyhow.
|
||||
if (_themeState)
|
||||
{
|
||||
if ([self hasThemeState:CPThemeStateFirstResponder])
|
||||
[aSubview _notifyViewDidBecomeFirstResponder];
|
||||
else
|
||||
[aSubview _notifyViewDidResignFirstResponder];
|
||||
|
||||
if ([self hasThemeState:CPThemeStateKeyWindow])
|
||||
[aSubview _notifyWindowDidBecomeKey];
|
||||
else
|
||||
[aSubview _notifyWindowDidResignKey];
|
||||
}
|
||||
|
||||
[self didAddSubview:aSubview];
|
||||
}
|
||||
|
||||
@@ -595,6 +625,18 @@ var CPViewFlags = { },
|
||||
Does nothing if there's no container view.
|
||||
*/
|
||||
- (void)removeFromSuperview
|
||||
{
|
||||
var superview = _superview;
|
||||
|
||||
[self viewWillMoveToSuperview:nil];
|
||||
[self _removeFromSuperview];
|
||||
[self viewDidMoveToSuperview];
|
||||
|
||||
if (superview)
|
||||
[self _setWindow:nil];
|
||||
}
|
||||
|
||||
- (void)_removeFromSuperview
|
||||
{
|
||||
if (!_superview)
|
||||
return;
|
||||
@@ -615,9 +657,10 @@ var CPViewFlags = { },
|
||||
if (!_isHidden && [_superview isHiddenOrHasHiddenAncestor])
|
||||
[self _notifyViewDidUnhide];
|
||||
|
||||
_superview = nil;
|
||||
[self _notifyWindowDidResignKey];
|
||||
[self _notifyViewDidResignFirstResponder];
|
||||
|
||||
[self _setWindow:nil];
|
||||
_superview = nil;
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -627,14 +670,14 @@ var CPViewFlags = { },
|
||||
*/
|
||||
- (void)replaceSubview:(CPView)aSubview with:(CPView)aView
|
||||
{
|
||||
if (aSubview._superview !== self)
|
||||
if (aSubview._superview !== self || aSubview === aView)
|
||||
return;
|
||||
|
||||
var index = [_subviews indexOfObjectIdenticalTo:aSubview];
|
||||
|
||||
[aSubview removeFromSuperview];
|
||||
|
||||
[self _insertSubview:aView atIndex:index];
|
||||
|
||||
[aSubview removeFromSuperview];
|
||||
}
|
||||
|
||||
- (void)setSubviews:(CPArray)newSubviews
|
||||
@@ -709,13 +752,10 @@ var CPViewFlags = { },
|
||||
/* @ignore */
|
||||
- (void)_setWindow:(CPWindow)aWindow
|
||||
{
|
||||
if (_window === aWindow)
|
||||
return;
|
||||
|
||||
[[self window] _dirtyKeyViewLoop];
|
||||
|
||||
// Clear out first responder if we're the first responder and leaving.
|
||||
if ([_window firstResponder] === self)
|
||||
if ([_window firstResponder] === self && _window != aWindow)
|
||||
[_window makeFirstResponder:nil];
|
||||
|
||||
// Notify the view and its subviews
|
||||
@@ -736,6 +776,11 @@ var CPViewFlags = { },
|
||||
while (count--)
|
||||
[_subviews[count] _setWindow:aWindow];
|
||||
|
||||
if ([_window isKeyWindow])
|
||||
[self setThemeState:CPThemeStateKeyWindow];
|
||||
else
|
||||
[self unsetThemeState:CPThemeStateKeyWindow];
|
||||
|
||||
[self viewDidMoveToWindow];
|
||||
|
||||
[[self window] _dirtyKeyViewLoop];
|
||||
@@ -780,6 +825,12 @@ var CPViewFlags = { },
|
||||
*/
|
||||
- (void)viewWillMoveToSuperview:(CPView)aView
|
||||
{
|
||||
_isSuperviewAClipView = [aView isKindOfClass:[CPClipView class]];
|
||||
|
||||
[self _removeObservers];
|
||||
|
||||
if (aView)
|
||||
[self _addObservers];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -798,6 +849,32 @@ var CPViewFlags = { },
|
||||
{
|
||||
}
|
||||
|
||||
- (void)_removeObservers
|
||||
{
|
||||
if (!_isObserving)
|
||||
return;
|
||||
|
||||
var count = [_subviews count];
|
||||
|
||||
while (count--)
|
||||
[_subviews[count] _removeObservers];
|
||||
|
||||
_isObserving = NO;
|
||||
}
|
||||
|
||||
- (void)_addObservers
|
||||
{
|
||||
if (_isObserving)
|
||||
return;
|
||||
|
||||
var count = [_subviews count];
|
||||
|
||||
while (count--)
|
||||
[_subviews[count] _addObservers];
|
||||
|
||||
_isObserving = YES;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the menu item containing the receiver or one of its ancestor views.
|
||||
@return a menu item, or \c nil if the view or one of its ancestors wasn't found
|
||||
@@ -881,6 +958,9 @@ var CPViewFlags = { },
|
||||
|
||||
if (_postsFrameChangedNotifications)
|
||||
[CachedNotificationCenter postNotificationName:CPViewFrameDidChangeNotification object:self];
|
||||
|
||||
if (_isSuperviewAClipView)
|
||||
[[self superview] viewFrameChanged:[[CPNotification alloc] initWithName:CPViewFrameDidChangeNotification object:self userInfo:nil]];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -943,6 +1023,9 @@ var CPViewFlags = { },
|
||||
if (_postsFrameChangedNotifications && !_inhibitFrameAndBoundsChangedNotifications)
|
||||
[CachedNotificationCenter postNotificationName:CPViewFrameDidChangeNotification object:self];
|
||||
|
||||
if (_isSuperviewAClipView && !_inhibitFrameAndBoundsChangedNotifications)
|
||||
[[self superview] viewFrameChanged:[[CPNotification alloc] initWithName:CPViewFrameDidChangeNotification object:self userInfo:nil]];
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
var transform = _superview ? _superview._boundsTransform : NULL;
|
||||
|
||||
@@ -1001,7 +1084,8 @@ var CPViewFlags = { },
|
||||
else
|
||||
{
|
||||
var images = [[_backgroundColor patternImage] imageSlices],
|
||||
partIndex = 0;
|
||||
partIndex = 0,
|
||||
frameSize = aSize;
|
||||
|
||||
if (_backgroundType === BackgroundVerticalThreePartImage)
|
||||
{
|
||||
@@ -1011,16 +1095,21 @@ var CPViewFlags = { },
|
||||
// Make sure to repeat the top and bottom pieces horizontally if they're not the exact width needed.
|
||||
if (top)
|
||||
{
|
||||
CPDOMDisplayServerSetStyleBackgroundSize(_DOMImageParts[partIndex], frameSize.width + "px", top + "px");
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], size.width, top);
|
||||
partIndex++;
|
||||
}
|
||||
if (_DOMImageSizes[1])
|
||||
{
|
||||
var height = frameSize.height - top - bottom;
|
||||
|
||||
CPDOMDisplayServerSetStyleBackgroundSize(_DOMImageParts[partIndex], frameSize.width + "px", height + "px");
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], size.width, size.height - top - bottom);
|
||||
partIndex++;
|
||||
}
|
||||
if (bottom)
|
||||
{
|
||||
CPDOMDisplayServerSetStyleBackgroundSize(_DOMImageParts[partIndex], frameSize.width + "px", bottom + "px");
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], size.width, bottom);
|
||||
}
|
||||
}
|
||||
@@ -1032,16 +1121,21 @@ var CPViewFlags = { },
|
||||
// Make sure to repeat the left and right pieces vertically if they're not the exact height needed.
|
||||
if (left)
|
||||
{
|
||||
CPDOMDisplayServerSetStyleBackgroundSize(_DOMImageParts[partIndex], left + "px", frameSize.height + "px");
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], left, size.height);
|
||||
partIndex++;
|
||||
}
|
||||
if (_DOMImageSizes[1])
|
||||
{
|
||||
var width = (frameSize.width - left - right);
|
||||
|
||||
CPDOMDisplayServerSetStyleBackgroundSize(_DOMImageParts[partIndex], width + "px", frameSize.height + "px");
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], size.width - left - right, size.height);
|
||||
partIndex++;
|
||||
}
|
||||
if (right)
|
||||
{
|
||||
CPDOMDisplayServerSetStyleBackgroundSize(_DOMImageParts[partIndex], right + "px", frameSize.height + "px");
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], right, size.height);
|
||||
}
|
||||
}
|
||||
@@ -1091,6 +1185,9 @@ var CPViewFlags = { },
|
||||
|
||||
if (_postsFrameChangedNotifications && !_inhibitFrameAndBoundsChangedNotifications)
|
||||
[CachedNotificationCenter postNotificationName:CPViewFrameDidChangeNotification object:self];
|
||||
|
||||
if (_isSuperviewAClipView && !_inhibitFrameAndBoundsChangedNotifications)
|
||||
[[self superview] viewFrameChanged:[[CPNotification alloc] initWithName:CPViewFrameDidChangeNotification object:self userInfo:nil]];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -1125,6 +1222,9 @@ var CPViewFlags = { },
|
||||
|
||||
if (_postsBoundsChangedNotifications)
|
||||
[CachedNotificationCenter postNotificationName:CPViewBoundsDidChangeNotification object:self];
|
||||
|
||||
if (_isSuperviewAClipView)
|
||||
[[self superview] viewBoundsChanged:[[CPNotification alloc] initWithName:CPViewBoundsDidChangeNotification object:self userInfo:nil]];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -1187,6 +1287,9 @@ var CPViewFlags = { },
|
||||
|
||||
if (_postsBoundsChangedNotifications && !_inhibitFrameAndBoundsChangedNotifications)
|
||||
[CachedNotificationCenter postNotificationName:CPViewBoundsDidChangeNotification object:self];
|
||||
|
||||
if (_isSuperviewAClipView && !_inhibitFrameAndBoundsChangedNotifications)
|
||||
[[self superview] viewBoundsChanged:[[CPNotification alloc] initWithName:CPViewBoundsDidChangeNotification object:self userInfo:nil]];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -1225,6 +1328,9 @@ var CPViewFlags = { },
|
||||
|
||||
if (_postsBoundsChangedNotifications && !_inhibitFrameAndBoundsChangedNotifications)
|
||||
[CachedNotificationCenter postNotificationName:CPViewBoundsDidChangeNotification object:self];
|
||||
|
||||
if (_isSuperviewAClipView && !_inhibitFrameAndBoundsChangedNotifications)
|
||||
[[self superview] viewBoundsChanged:[[CPNotification alloc] initWithName:CPViewBoundsDidChangeNotification object:self userInfo:nil]];
|
||||
}
|
||||
|
||||
|
||||
@@ -1782,6 +1888,9 @@ var CPViewFlags = { },
|
||||
_DOMElement.style.background = "";
|
||||
_DOMImageParts[0].style.background = [_backgroundColor cssString];
|
||||
|
||||
if (patternImage)
|
||||
CPDOMDisplayServerSetStyleBackgroundSize(_DOMImageParts[0], [patternImage size].width + "px", [patternImage size].height + "px");
|
||||
|
||||
if (CPFeatureIsCompatible(CPOpacityRequiresFilterFeature))
|
||||
_DOMImageParts[0].style.filter = "alpha(opacity=" + [_backgroundColor alphaComponent] * 100 + ")";
|
||||
else
|
||||
@@ -1792,6 +1901,9 @@ var CPViewFlags = { },
|
||||
}
|
||||
else
|
||||
_DOMElement.style.background = colorCSS;
|
||||
|
||||
if (patternImage)
|
||||
CPDOMDisplayServerSetStyleBackgroundSize(_DOMElement, [patternImage size].width + "px", [patternImage size].height + "px");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1896,18 +2008,24 @@ var CPViewFlags = { },
|
||||
// Make sure to repeat the top and bottom pieces horizontally if they're not the exact width needed.
|
||||
if (top)
|
||||
{
|
||||
CPDOMDisplayServerSetStyleBackgroundSize(_DOMImageParts[partIndex], frameSize.width + "px", top + "px");
|
||||
CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[partIndex], NULL, 0.0, 0.0);
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], frameSize.width, top);
|
||||
partIndex++;
|
||||
}
|
||||
if (_DOMImageSizes[1])
|
||||
{
|
||||
var height = frameSize.height - top - bottom;
|
||||
|
||||
//_DOMImageParts[partIndex].style.backgroundSize = frameSize.width + "px " + height + "px";
|
||||
CPDOMDisplayServerSetStyleBackgroundSize(_DOMImageParts[partIndex], frameSize.width + "px", height + "px");
|
||||
CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[partIndex], NULL, 0.0, top);
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], frameSize.width, frameSize.height - top - bottom);
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], frameSize.width, height);
|
||||
partIndex++;
|
||||
}
|
||||
if (bottom)
|
||||
{
|
||||
CPDOMDisplayServerSetStyleBackgroundSize(_DOMImageParts[partIndex], frameSize.width + "px", bottom + "px");
|
||||
CPDOMDisplayServerSetStyleLeftBottom(_DOMImageParts[partIndex], NULL, 0.0, 0.0);
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], frameSize.width, bottom);
|
||||
}
|
||||
@@ -1922,18 +2040,23 @@ var CPViewFlags = { },
|
||||
// Make sure to repeat the left and right pieces vertically if they're not the exact height needed.
|
||||
if (left)
|
||||
{
|
||||
CPDOMDisplayServerSetStyleBackgroundSize(_DOMImageParts[partIndex], left + "px", frameSize.height + "px");
|
||||
CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[partIndex], NULL, 0.0, 0.0);
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], left, frameSize.height);
|
||||
partIndex++;
|
||||
}
|
||||
if (_DOMImageSizes[1])
|
||||
{
|
||||
var width = (frameSize.width - left - right);
|
||||
|
||||
CPDOMDisplayServerSetStyleBackgroundSize(_DOMImageParts[partIndex], width + "px", frameSize.height + "px");
|
||||
CPDOMDisplayServerSetStyleLeftTop(_DOMImageParts[partIndex], NULL, left, 0.0);
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], frameSize.width - left - right, frameSize.height);
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], width, frameSize.height);
|
||||
partIndex++;
|
||||
}
|
||||
if (right)
|
||||
{
|
||||
CPDOMDisplayServerSetStyleBackgroundSize(_DOMImageParts[partIndex], right + "px", frameSize.height + "px");
|
||||
CPDOMDisplayServerSetStyleRightTop(_DOMImageParts[partIndex], NULL, 0.0, 0.0);
|
||||
CPDOMDisplayServerSetStyleSize(_DOMImageParts[partIndex], right, frameSize.height);
|
||||
}
|
||||
@@ -2518,7 +2641,7 @@ setBoundsOrigin:
|
||||
/*!
|
||||
Scrolls the nearest ancestor CPClipView a minimum amount so \c aRect can become visible.
|
||||
@param aRect the area to become visible
|
||||
@return <codeYES if any scrolling occurred, \c NO otherwise.
|
||||
@return \c YES if any scrolling occurred, \c NO otherwise.
|
||||
*/
|
||||
- (BOOL)scrollRectToVisible:(CGRect)aRect
|
||||
{
|
||||
@@ -2887,23 +3010,23 @@ setBoundsOrigin:
|
||||
return _themeState;
|
||||
}
|
||||
|
||||
- (BOOL)hasThemeState:(CPThemeState)aState
|
||||
- (BOOL)hasThemeState:(ThemeState)aState
|
||||
{
|
||||
// Because CPThemeStateNormal is defined as 0 we need to check for it explicitly here
|
||||
if (aState === CPThemeStateNormal && _themeState === CPThemeStateNormal)
|
||||
return YES;
|
||||
if (aState.isa && [aState isKindOfClass:CPArray])
|
||||
return _themeState.hasThemeState.apply(_themeState, aState);
|
||||
|
||||
return !!(_themeState & ((typeof aState === "string") ? CPThemeState(aState) : aState));
|
||||
return _themeState.hasThemeState(aState);
|
||||
}
|
||||
|
||||
- (BOOL)setThemeState:(CPThemeState)aState
|
||||
- (BOOL)setThemeState:(ThemeState)aState
|
||||
{
|
||||
var newState = (typeof aState === "string") ? CPThemeState(aState) : aState;
|
||||
if (aState && aState.isa && [aState isKindOfClass:CPArray])
|
||||
aState = CPThemeState.apply(null, aState);
|
||||
|
||||
if (_themeState & newState)
|
||||
if (_themeState.hasThemeState(aState))
|
||||
return NO;
|
||||
|
||||
_themeState |= newState;
|
||||
_themeState = CPThemeState(_themeState, aState);
|
||||
|
||||
[self setNeedsLayout];
|
||||
[self setNeedsDisplay:YES];
|
||||
@@ -2911,21 +3034,75 @@ setBoundsOrigin:
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)unsetThemeState:(CPThemeState)aState
|
||||
- (BOOL)unsetThemeState:(ThemeState)aState
|
||||
{
|
||||
var newState = ((typeof aState === "string") ? CPThemeState(aState) : aState);
|
||||
if (aState && aState.isa && [aState isKindOfClass:CPArray])
|
||||
aState = CPThemeState.apply(null, aState);
|
||||
|
||||
if (!(_themeState & newState))
|
||||
var oldThemeState = _themeState;
|
||||
_themeState = _themeState.without(aState);
|
||||
|
||||
if (oldThemeState === _themeState)
|
||||
return NO;
|
||||
|
||||
_themeState &= ~newState;
|
||||
|
||||
[self setNeedsLayout];
|
||||
[self setNeedsDisplay:YES];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)becomeFirstResponder
|
||||
{
|
||||
var r = [super becomeFirstResponder];
|
||||
if (r)
|
||||
[self _notifyViewDidBecomeFirstResponder];
|
||||
return r;
|
||||
}
|
||||
|
||||
- (void)_notifyViewDidBecomeFirstResponder
|
||||
{
|
||||
[self setThemeState:CPThemeStateFirstResponder];
|
||||
|
||||
var count = [_subviews count];
|
||||
while (count--)
|
||||
[_subviews[count] _notifyViewDidBecomeFirstResponder];
|
||||
}
|
||||
|
||||
- (BOOL)resignFirstResponder
|
||||
{
|
||||
var r = [super resignFirstResponder];
|
||||
if (r)
|
||||
[self _notifyViewDidResignFirstResponder];
|
||||
return r;
|
||||
}
|
||||
|
||||
- (void)_notifyViewDidResignFirstResponder
|
||||
{
|
||||
[self unsetThemeState:CPThemeStateFirstResponder];
|
||||
|
||||
var count = [_subviews count];
|
||||
while (count--)
|
||||
[_subviews[count] _notifyViewDidResignFirstResponder];
|
||||
}
|
||||
|
||||
- (void)_notifyWindowDidBecomeKey
|
||||
{
|
||||
[self setThemeState:CPThemeStateKeyWindow];
|
||||
|
||||
var count = [_subviews count];
|
||||
while (count--)
|
||||
[_subviews[count] _notifyWindowDidBecomeKey];
|
||||
}
|
||||
|
||||
- (void)_notifyWindowDidResignKey
|
||||
{
|
||||
[self unsetThemeState:CPThemeStateKeyWindow];
|
||||
|
||||
var count = [_subviews count];
|
||||
while (count--)
|
||||
[_subviews[count] _notifyWindowDidResignKey];
|
||||
}
|
||||
|
||||
#pragma mark Theme Attributes
|
||||
|
||||
+ (CPString)defaultThemeClass
|
||||
@@ -3077,8 +3254,11 @@ setBoundsOrigin:
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
- (void)setValue:(id)aValue forThemeAttribute:(CPString)aName inState:(CPThemeState)aState
|
||||
- (void)setValue:(id)aValue forThemeAttribute:(CPString)aName inState:(ThemeState)aState
|
||||
{
|
||||
if (aState.isa && [aState isKindOfClass:CPArray])
|
||||
aState = CPThemeState.apply(null, aState);
|
||||
|
||||
if (!_themeAttributes || !_themeAttributes[aName])
|
||||
[CPException raise:CPInvalidArgumentException reason:[self className] + " does not contain theme attribute '" + aName + "'"];
|
||||
|
||||
@@ -3109,8 +3289,11 @@ setBoundsOrigin:
|
||||
[self setNeedsLayout];
|
||||
}
|
||||
|
||||
- (id)valueForThemeAttribute:(CPString)aName inState:(CPThemeState)aState
|
||||
- (id)valueForThemeAttribute:(CPString)aName inState:(ThemeState)aState
|
||||
{
|
||||
if (aState.isa && [aState isKindOfClass:CPArray])
|
||||
aState = CPThemeState.apply(null, aState);
|
||||
|
||||
if (!_themeAttributes || !_themeAttributes[aName])
|
||||
[CPException raise:CPInvalidArgumentException reason:[self className] + " does not contain theme attribute '" + aName + "'"];
|
||||
|
||||
@@ -3361,7 +3544,7 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
|
||||
|
||||
_theme = [CPTheme defaultTheme];
|
||||
_themeClass = [aCoder decodeObjectForKey:CPViewThemeClassKey];
|
||||
_themeState = CPThemeState([aCoder decodeIntForKey:CPViewThemeStateKey]);
|
||||
_themeState = CPThemeState([aCoder decodeObjectForKey:CPViewThemeStateKey]);
|
||||
_themeAttributes = {};
|
||||
|
||||
var theClass = [self class],
|
||||
@@ -3452,7 +3635,7 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
|
||||
[aCoder encodeConditionalObject:previousKeyView forKey:CPViewPreviousKeyViewKey];
|
||||
|
||||
[aCoder encodeObject:[self themeClass] forKey:CPViewThemeClassKey];
|
||||
[aCoder encodeInt:CPThemeStateName(_themeState) forKey:CPViewThemeStateKey];
|
||||
[aCoder encodeObject:String(_themeState) forKey:CPViewThemeStateKey];
|
||||
|
||||
for (var attributeName in _themeAttributes)
|
||||
if (_themeAttributes.hasOwnProperty(attributeName))
|
||||
|
||||
@@ -210,6 +210,7 @@ var CPViewControllerCachedCibs;
|
||||
[cibOwner viewControllerDidLoadCib:self];
|
||||
|
||||
_isLoading = NO;
|
||||
_isLazy = NO;
|
||||
[self _viewDidLoad];
|
||||
}
|
||||
else if (_isLazy)
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
@import "CPView.j"
|
||||
@import "CPScrollView.j"
|
||||
|
||||
@class CPWebScriptObject
|
||||
|
||||
@typedef Window
|
||||
|
||||
// FIXME: implement these where possible:
|
||||
/*
|
||||
@@ -93,7 +96,7 @@ CPWebViewAppKitScrollMaxPollCount = 3;
|
||||
CPScrollView _scrollView;
|
||||
CPView _frameView;
|
||||
|
||||
IFrame _iframe;
|
||||
DOMElement _iframe;
|
||||
CPString _mainFrameURL;
|
||||
CPArray _backwardStack;
|
||||
CPArray _forwardStack;
|
||||
|
||||
@@ -50,9 +50,36 @@
|
||||
|
||||
@class CPMenu
|
||||
@class CPProgressIndicator
|
||||
@class CPToolbar
|
||||
@class CPWindowController
|
||||
@class _CPWindowFrameAnimation
|
||||
|
||||
@global CPApp
|
||||
|
||||
@typedef _CPWindowFullPlatformWindowSession
|
||||
|
||||
|
||||
@protocol CPWindowDelegate <CPObject>
|
||||
|
||||
@optional
|
||||
- (BOOL)windowShouldClose:(CPWindow)aWindow;
|
||||
- (CPUndoManager)windowWillReturnUndoManager:(CPWindow)window;
|
||||
- (void)windowDidBecomeKey:(CPNotification)aNotification;
|
||||
- (void)windowDidBecomeMain:(CPNotification)aNotification;
|
||||
- (void)windowDidEndSheet:(CPNotification)aNotification;
|
||||
- (void)windowDidMove:(CPNotification)aNotification;
|
||||
- (void)windowDidResignKey:(CPNotification)aNotification;
|
||||
- (void)windowDidResignMain:(CPNotification)aNotification;
|
||||
- (void)windowDidResize:(CPNotification)aNotification;
|
||||
- (void)windowWillBeginSheet:(CPNotification)aNotification;
|
||||
- (void)windowWillClose:(CPWindow)aWindow;
|
||||
|
||||
@end
|
||||
|
||||
var CPWindowDelegate_windowShouldClose_ = 1 << 1
|
||||
CPWindowDelegate_windowWillReturnUndoManager_ = 1 << 2,
|
||||
CPWindowDelegate_windowWillClose_ = 1 << 3;
|
||||
|
||||
var CPWindowSaveImage = nil,
|
||||
|
||||
CPWindowResizeTime = 0.2,
|
||||
@@ -171,7 +198,8 @@ var CPWindowActionMessageKeys = [
|
||||
CPResponder _firstResponder;
|
||||
CPResponder _initialFirstResponder;
|
||||
BOOL _hasBecomeKeyWindow;
|
||||
id _delegate;
|
||||
id <CPWindowDelegate> _delegate;
|
||||
unsigned _implementedDelegateMethods;
|
||||
|
||||
CPString _title;
|
||||
|
||||
@@ -205,8 +233,6 @@ var CPWindowActionMessageKeys = [
|
||||
|
||||
unsigned _autoresizingMask;
|
||||
|
||||
BOOL _delegateRespondsToWindowWillReturnUndoManagerSelector;
|
||||
|
||||
BOOL _isFullPlatformWindow;
|
||||
_CPWindowFullPlatformWindowSession _fullPlatformWindowSession;
|
||||
|
||||
@@ -881,16 +907,21 @@ CPTexturedBackgroundWindowMask
|
||||
|
||||
- (void)_orderFront
|
||||
{
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
// -dw- if a sheet is clicked, the parent window should come up too
|
||||
if (_isSheet)
|
||||
[_parentView orderFront:self];
|
||||
|
||||
if (!_isVisible)
|
||||
[self _setFrame:_frame display:YES animate:NO constrainWidth:YES constrainHeight:YES];
|
||||
// Save the boolean since it will be updated in the method order:window:relativeTo:
|
||||
var wasVisible = _isVisible;
|
||||
|
||||
[_platformWindow orderFront:self];
|
||||
[_platformWindow order:CPWindowAbove window:self relativeTo:nil];
|
||||
|
||||
// setFrame is set after ordering the window as this method can send some notifications
|
||||
if (!wasVisible)
|
||||
[self _setFrame:_frame display:YES animate:NO constrainWidth:YES constrainHeight:YES];
|
||||
#endif
|
||||
|
||||
if (!CPApp._keyWindow)
|
||||
@@ -911,6 +942,23 @@ CPTexturedBackgroundWindowMask
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
Called when the window is displayed in the DOM
|
||||
*/
|
||||
- (void)_windowWillBeAddedToTheDOM
|
||||
{
|
||||
[[self contentView] _addObservers];
|
||||
}
|
||||
|
||||
/*
|
||||
Called when the window is removed in the DOM
|
||||
*/
|
||||
- (void)_windowWillBeRemovedFromTheDOM
|
||||
{
|
||||
[[self contentView] _removeObservers];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Makes the receiver the last window in the screen ordering.
|
||||
@param aSender the object that requested this
|
||||
@@ -957,6 +1005,7 @@ CPTexturedBackgroundWindowMask
|
||||
[_platformWindow order:CPWindowOut window:self relativeTo:nil];
|
||||
#endif
|
||||
|
||||
[self makeFirstResponder:nil];
|
||||
[self _updateMainAndKeyWindows];
|
||||
}
|
||||
|
||||
@@ -1110,7 +1159,7 @@ CPTexturedBackgroundWindowMask
|
||||
*/
|
||||
- (void)setContentView:(CPView)aView
|
||||
{
|
||||
if (_contentView)
|
||||
if (_contentView && _contentView !== aView)
|
||||
[_contentView removeFromSuperview];
|
||||
|
||||
var bounds = CGRectMake(0.0, 0.0, CGRectGetWidth(_frame), CGRectGetHeight(_frame));
|
||||
@@ -1343,8 +1392,11 @@ CPTexturedBackgroundWindowMask
|
||||
Sets the delegate for the window. Passing \c nil will just remove the window's current delegate.
|
||||
@param aDelegate an object to respond to the various delegate methods of CPWindow
|
||||
*/
|
||||
- (void)setDelegate:(id)aDelegate
|
||||
- (void)setDelegate:(id <CPWindowDelegate>)aDelegate
|
||||
{
|
||||
if (_delegate === aDelegate)
|
||||
return;
|
||||
|
||||
var defaultCenter = [CPNotificationCenter defaultCenter];
|
||||
|
||||
[defaultCenter removeObserver:_delegate name:CPWindowDidResignKeyNotification object:self];
|
||||
@@ -1357,7 +1409,16 @@ CPTexturedBackgroundWindowMask
|
||||
[defaultCenter removeObserver:_delegate name:CPWindowDidEndSheetNotification object:self];
|
||||
|
||||
_delegate = aDelegate;
|
||||
_delegateRespondsToWindowWillReturnUndoManagerSelector = [_delegate respondsToSelector:@selector(windowWillReturnUndoManager:)];
|
||||
_implementedDelegateMethods = 0;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(windowShouldClose:)])
|
||||
_implementedDelegateMethods |= CPWindowDelegate_windowShouldClose_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(windowWillReturnUndoManager:)])
|
||||
_implementedDelegateMethods |= CPWindowDelegate_windowWillReturnUndoManager_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(windowWillClose:)])
|
||||
_implementedDelegateMethods |= CPWindowDelegate_windowWillClose_;
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(windowDidResignKey:)])
|
||||
[defaultCenter
|
||||
@@ -1759,10 +1820,14 @@ CPTexturedBackgroundWindowMask
|
||||
// even that we just moved it to a new first responder.
|
||||
[[[anEvent window] platformWindow] _propagateCurrentDOMEvent:NO]
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
return didTabBack;
|
||||
}
|
||||
else if ([anEvent charactersIgnoringModifiers] == CPEscapeFunctionKey && [self _processKeyboardUIKey:anEvent])
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
[[self firstResponder] keyDown:anEvent];
|
||||
|
||||
@@ -1805,6 +1870,12 @@ CPTexturedBackgroundWindowMask
|
||||
if (_leftMouseDownView !== _firstResponder && [_leftMouseDownView acceptsFirstResponder])
|
||||
[self makeFirstResponder:_leftMouseDownView];
|
||||
|
||||
var keyWindow = [CPApp keyWindow];
|
||||
|
||||
// This is only when we move from a platform to another one
|
||||
if ([keyWindow platformWindow] != [self platformWindow])
|
||||
[self makeKeyAndOrderFront:self];
|
||||
|
||||
[CPApp activateIgnoringOtherApps:YES];
|
||||
|
||||
var theWindow = [anEvent window],
|
||||
@@ -1932,6 +2003,7 @@ CPTexturedBackgroundWindowMask
|
||||
_hasBecomeKeyWindow = YES;
|
||||
|
||||
[_windowView noteKeyWindowStateChanged];
|
||||
[_contentView _notifyWindowDidBecomeKey];
|
||||
|
||||
[[CPNotificationCenter defaultCenter]
|
||||
postNotificationName:CPWindowDidBecomeKeyNotification
|
||||
@@ -2000,6 +2072,7 @@ CPTexturedBackgroundWindowMask
|
||||
CPApp._keyWindow = nil;
|
||||
|
||||
[_windowView noteKeyWindowStateChanged];
|
||||
[_contentView _notifyWindowDidResignKey];
|
||||
|
||||
[[CPNotificationCenter defaultCenter]
|
||||
postNotificationName:CPWindowDidResignKeyNotification
|
||||
@@ -2243,9 +2316,9 @@ CPTexturedBackgroundWindowMask
|
||||
|
||||
// The Cocoa docs say that if both the delegate and the window implement
|
||||
// windowShouldClose:, only the delegate receives the message.
|
||||
if ([_delegate respondsToSelector:@selector(windowShouldClose:)])
|
||||
if ([self _delegateRespondsToWindowShouldClose])
|
||||
{
|
||||
if (![_delegate windowShouldClose:self])
|
||||
if (![self _sendDelegateWindowShouldClose])
|
||||
return;
|
||||
}
|
||||
else if ([self respondsToSelector:@selector(windowShouldClose:)])
|
||||
@@ -2301,8 +2374,7 @@ CPTexturedBackgroundWindowMask
|
||||
*/
|
||||
- (void)close
|
||||
{
|
||||
if ([_delegate respondsToSelector:@selector(windowWillClose:)])
|
||||
[_delegate windowWillClose:self];
|
||||
[self _sendDelegateWindowWillClose];
|
||||
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPWindowWillCloseNotification object:self];
|
||||
|
||||
@@ -2435,7 +2507,7 @@ CPTexturedBackgroundWindowMask
|
||||
if (currentWindow === self || currentWindow === menuWindow)
|
||||
continue;
|
||||
|
||||
if ([currentWindow isVisible] && [currentWindow canBecomeKeyWindow])
|
||||
if ([currentWindow isVisible] && [currentWindow canBecomeKeyWindow] && [currentWindow platformWindow] == [keyWindow platformWindow])
|
||||
{
|
||||
[currentWindow makeKeyWindow];
|
||||
break;
|
||||
@@ -2637,6 +2709,23 @@ CPTexturedBackgroundWindowMask
|
||||
[attachedSheet setFrame:sheetFrame display:YES animate:NO];
|
||||
}
|
||||
|
||||
- (void)_previousSheetIsClosedNotification:(CPNotification)aNotification
|
||||
{
|
||||
[[CPNotificationCenter defaultCenter] removeObserver:self name:CPWindowDidEndSheetNotification object:self];
|
||||
|
||||
var sheet = _sheetContext[@"nextSheet"],
|
||||
modalDelegate =_sheetContext[@"nextModalDelegate"],
|
||||
endSelector = _sheetContext[@"nextEndSelector"],
|
||||
contextInfo = _sheetContext[@"nextContextInfo"];
|
||||
|
||||
// Needed, because when the notification CPWindowDidEndSheetNotification is sent, the sheetContext is not up to date...
|
||||
setTimeout(function()
|
||||
{
|
||||
[sheet._windowView _enableSheet:YES inWindow:self];
|
||||
[self _attachSheet:sheet modalDelegate:modalDelegate didEndSelector:endSelector contextInfo:contextInfo];
|
||||
}, 0)
|
||||
}
|
||||
|
||||
/*
|
||||
Starting point for sheet session, called from CPApplication beginSheet:
|
||||
*/
|
||||
@@ -2645,9 +2734,24 @@ CPTexturedBackgroundWindowMask
|
||||
{
|
||||
if (_sheetContext)
|
||||
{
|
||||
[CPException raise:CPInternalInconsistencyException
|
||||
reason:@"The target window of beginSheet: already has a sheet, did you forget orderOut: ?"];
|
||||
return;
|
||||
// Here we wait till the current sheet is closed
|
||||
if (_sheetContext[@"isClosing"])
|
||||
{
|
||||
// Here we save the next sheet to open
|
||||
_sheetContext[@"nextSheet"] = aSheet;
|
||||
_sheetContext[@"nextModalDelegate"] = aModalDelegate;
|
||||
_sheetContext[@"nextEndSelector"] = didEndSelector;
|
||||
_sheetContext[@"nextContextInfo"] = contextInfo;
|
||||
|
||||
[[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_previousSheetIsClosedNotification:) name:CPWindowDidEndSheetNotification object:self];
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
[CPException raise:CPInternalInconsistencyException
|
||||
reason:@"The target window of beginSheet: already has a sheet, did you forget orderOut: ?"];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_sheetContext = {
|
||||
@@ -2699,7 +2803,12 @@ CPTexturedBackgroundWindowMask
|
||||
*/
|
||||
- (void)_detachSheetWindow
|
||||
{
|
||||
if (_sheetContext["isClosing"])
|
||||
return;
|
||||
|
||||
_sheetContext["isAttached"] = NO;
|
||||
_sheetContext["isClosing"] = YES;
|
||||
_sheetContext["opened"] = NO;
|
||||
|
||||
// A timer seems to be necessary for the animation to work correctly.
|
||||
// It would be ideal to block here and spin the event loop, until attach is complete.
|
||||
@@ -2832,12 +2941,6 @@ CPTexturedBackgroundWindowMask
|
||||
return;
|
||||
}
|
||||
|
||||
if (_sheetContext["isClosing"])
|
||||
return;
|
||||
|
||||
_sheetContext["opened"] = NO;
|
||||
_sheetContext["isClosing"] = YES;
|
||||
|
||||
// The parent window can be orderedOut to disable the sheet animate out, as in Cocoa
|
||||
if ([self isVisible])
|
||||
{
|
||||
@@ -2984,20 +3087,9 @@ CPTexturedBackgroundWindowMask
|
||||
if ([selectors count] <= 0)
|
||||
return NO;
|
||||
|
||||
if (character !== CPEscapeFunctionKey)
|
||||
{
|
||||
var selector = [selectors objectAtIndex:0];
|
||||
return [[self firstResponder] tryToPerform:selector with:self];
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
Cocoa sends complete: for the escape key (instead of the default cancelOperation:). This is also the only action that is not sent directly to the first responder, but through doCommandBySelector. The difference is that doCommandBySelector: will also send the action to the window and application delegates.
|
||||
*/
|
||||
[[self firstResponder] doCommandBySelector:@selector(complete:)];
|
||||
}
|
||||
var selector = [selectors objectAtIndex:0];
|
||||
|
||||
return NO;
|
||||
return [[self firstResponder] tryToPerform:selector with:self];
|
||||
}
|
||||
|
||||
- (void)_dirtyKeyViewLoop
|
||||
@@ -3294,6 +3386,66 @@ var keyViewComparator = function(lhs, rhs, context)
|
||||
return CPOrderedDescending;
|
||||
};
|
||||
|
||||
|
||||
@implementation CPWindow (CPWindowDelegate)
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Check if the delegate implements windowWillReturnUndoManager:
|
||||
*/
|
||||
- (BOOL)_delegateRespondsToWindowWillUndoManager
|
||||
{
|
||||
return _implementedDelegateMethods & CPWindowDelegate_windowWillReturnUndoManager_;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Check if the delegate implements windowShouldClose
|
||||
*/
|
||||
- (BOOL)_delegateRespondsToWindowShouldClose
|
||||
{
|
||||
return _implementedDelegateMethods & CPWindowDelegate_windowShouldClose_
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call delegate windowShouldClose:
|
||||
*/
|
||||
- (BOOL)_sendDelegateWindowShouldClose
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPWindowDelegate_windowShouldClose_))
|
||||
return YES;
|
||||
|
||||
return [_delegate windowShouldClose:self];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call delegate windowWillReturnUndoManager:
|
||||
*/
|
||||
- (BOOL)_sendDelegateWindowWillReturnUndoManager
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPWindowDelegate_windowWillReturnUndoManager_))
|
||||
return nil;
|
||||
|
||||
return [_delegate windowWillReturnUndoManager:self];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Call delegate windowWillClose:
|
||||
*/
|
||||
- (void)_sendDelegateWindowWillClose
|
||||
{
|
||||
if (!(_implementedDelegateMethods & CPWindowDelegate_windowWillClose_))
|
||||
return;
|
||||
|
||||
[_delegate windowWillClose:self];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation CPWindow (BridgeSupport)
|
||||
|
||||
/*
|
||||
@@ -3431,8 +3583,8 @@ var keyViewComparator = function(lhs, rhs, context)
|
||||
return documentUndoManager;
|
||||
|
||||
// If not, check to see if the delegate has one.
|
||||
if (_delegateRespondsToWindowWillReturnUndoManagerSelector)
|
||||
return [_delegate windowWillReturnUndoManager:self];
|
||||
if ([self _delegateRespondsToWindowWillUndoManager])
|
||||
return [self _sendDelegateWindowWillReturnUndoManager];
|
||||
|
||||
// If not, create one.
|
||||
if (!_undoManager)
|
||||
|
||||
@@ -81,6 +81,7 @@ CPWindowMinYMargin = 8;
|
||||
CPWindowHeightSizable = 16;
|
||||
CPWindowMaxYMargin = 32;
|
||||
|
||||
@typedef CPWindowLevel
|
||||
CPBackgroundWindowLevel = -1;
|
||||
/*
|
||||
Default level for windows
|
||||
@@ -143,6 +144,7 @@ CPDraggingWindowLevel = 500;
|
||||
*/
|
||||
CPScreenSaverWindowLevel = 1000;
|
||||
|
||||
@typedef CPWindowOrderingMode
|
||||
/*
|
||||
The receiver is placed directly in front of the window specified.
|
||||
@global
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
@import "CPCib.j"
|
||||
@import "CPResponder.j"
|
||||
@import "CPViewController.j"
|
||||
@import "CPWindow.j"
|
||||
|
||||
@class CPDocument
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
|
||||
// Not being able to set the action is a fatal error.
|
||||
if ([_source respondsToSelector:@selector(setAction:)])
|
||||
objj_msgSend(_source, @selector(setAction:), selector);
|
||||
[_source setAction:selector];
|
||||
|
||||
else
|
||||
[CPException
|
||||
@@ -60,7 +60,7 @@
|
||||
|
||||
// Not being able to set the target is a fatal error.
|
||||
if ([_source respondsToSelector:@selector(setTarget:)])
|
||||
objj_msgSend(_source, @selector(setTarget:), _destination);
|
||||
[_source setTarget:_destination];
|
||||
|
||||
else
|
||||
[CPException
|
||||
|
||||
@@ -498,6 +498,7 @@ var CALayerRegisteredRunLoopUpdates = nil;
|
||||
{
|
||||
_context = CGBitmapGraphicsContextCreate();
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
_DOMContentsElement = _context.DOMElement;
|
||||
|
||||
_DOMContentsElement.style.zIndex = -100;
|
||||
@@ -515,6 +516,7 @@ var CALayerRegisteredRunLoopUpdates = nil;
|
||||
_DOMContentsElement.style.height = ROUND(CGRectGetHeight(_backingStoreFrame)) + "px";
|
||||
|
||||
_DOMElement.appendChild(_DOMContentsElement);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (USE_BUFFER)
|
||||
@@ -1036,6 +1038,7 @@ function _CALayerUpdateSublayerTransformForSublayers(aLayer)
|
||||
|
||||
function _CALayerUpdateDOM(aLayer, aMask)
|
||||
{
|
||||
#if PLATFORM(DOM)
|
||||
var DOMElementStyle = aLayer._DOMElement.style;
|
||||
|
||||
if (aMask & CALayerZPositionUpdateMask)
|
||||
@@ -1066,6 +1069,7 @@ function _CALayerUpdateDOM(aLayer, aMask)
|
||||
DOMContentsElement.style.height = height + "px";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
function _CALayerRecalculateGeometry(aLayer, aGeometryChange)
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
|
||||
@import "CGGeometry.j"
|
||||
|
||||
@typedef CGAffineTransform
|
||||
|
||||
|
||||
function CGAffineTransformMake(a, b, c, d, tx, ty)
|
||||
{
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
@typedef CGColorSpace
|
||||
|
||||
kCGColorSpaceModelUnknown = -1;
|
||||
kCGColorSpaceModelMonochrome = 0;
|
||||
kCGColorSpaceModelRGB = 1;
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
@import "CGGeometry.j"
|
||||
@import "CGPath.j"
|
||||
|
||||
@typedef CGContext
|
||||
|
||||
kCGLineCapButt = 0;
|
||||
kCGLineCapRound = 1;
|
||||
@@ -737,7 +738,7 @@ else if (CPFeatureIsCompatible(CPVMLFeature))
|
||||
else
|
||||
{
|
||||
// I have declared these functions here to make it compile without warnings with the new compiler under rhino.
|
||||
CGContextClearRect = CGContextDrawLinearGradient = CGContextClip = CGContextClipToRect = function() {throw new Error("function is not declared in this environment")}
|
||||
CGContextClearRect = CGContextDrawLinearGradient = CGContextClip = CGContextClipToRect = CGContextDrawImage = function() {throw new Error("function is not declared in this environment")}
|
||||
}
|
||||
/*!
|
||||
@endcond
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
@import "CGColor.j"
|
||||
@import "CGColorSpace.j"
|
||||
|
||||
@typedef CGGradient
|
||||
|
||||
kCGGradientDrawsBeforeStartLocation = 1 << 0;
|
||||
kCGGradientDrawsAfterEndLocation = 1 << 1;
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
@import "CGAffineTransform.j"
|
||||
@import "CGGeometry.j"
|
||||
|
||||
@typedef CGPath
|
||||
|
||||
kCGPathElementMoveToPoint = 0;
|
||||
kCGPathElementAddLineToPoint = 1;
|
||||
@@ -629,4 +630,4 @@ function CGPathContainsPoint(aPath, aTransform, point, eoFill)
|
||||
|
||||
/*!
|
||||
@}
|
||||
*/
|
||||
*/
|
||||
|
||||
@@ -27,9 +27,12 @@
|
||||
|
||||
@class CPMenu
|
||||
@class CPPlatformPasteboard
|
||||
@class CPWindow
|
||||
|
||||
@global CPApp
|
||||
|
||||
@typedef DOMWindow
|
||||
|
||||
var PrimaryPlatformWindow = NULL;
|
||||
|
||||
@implementation CPPlatformWindow : CPObject
|
||||
|
||||
@@ -80,6 +80,9 @@ aDOMElement.style.bottom = ROUND(____p.y) + "px";
|
||||
aDOMElement.width = MAX(0.0, ROUND(aWidth));\
|
||||
aDOMElement.height = MAX(0.0, ROUND(aHeight));
|
||||
|
||||
#define CPDOMDisplayServerSetStyleBackgroundSize(aDOMElement, aWidth, aHeight)\
|
||||
aDOMElement.style.backgroundSize = aWidth + ' ' + aHeight;
|
||||
|
||||
#define CPDOMDisplayServerAppendChild(aParentElement, aChildElement) aParentElement.appendChild(aChildElement)
|
||||
|
||||
#define CPDOMDisplayServerInsertBefore(aParentElement, aChildElement, aBeforeElement) aParentElement.insertBefore(aChildElement, aBeforeElement)
|
||||
@@ -126,6 +129,9 @@ aDOMElement.style.bottom = ROUND(____p.y) + "px";
|
||||
CPDOMDisplayServerInstructions[__index + 2] = aWidth;\
|
||||
CPDOMDisplayServerInstructions[__index + 3] = aHeight;
|
||||
|
||||
#define CPDOMDisplayServerSetStyleBackgroundSize(aDOMElement, aWidth, aHeight)\
|
||||
aDOMElement.style.backgroundSize = aWidth + ' ' + aHeight;
|
||||
|
||||
#define CPDOMDisplayServerAppendChild(aParentElement, aChildElement)\
|
||||
if (aChildElement.CPDOMDisplayContext) aChildElement.CPDOMDisplayContext[SetStyleOrigin] = -1;\
|
||||
CPDOMDisplayServerInstructions[CPDOMDisplayServerInstructionCount++] = AppendChild;\
|
||||
|
||||
@@ -71,7 +71,6 @@ var hasEditableTarget = function(aDOMEvent)
|
||||
BOOL hasBugWhichPreventsNonEditablePaste;
|
||||
BOOL hasBugWhichPreventsNonEditablePasteRedirect;
|
||||
|
||||
CPEvent _lastKeyDownEvent;
|
||||
BOOL currentEventIsNativePasteEvent;
|
||||
BOOL currentEventIsNativeCopyOrCutEvent;
|
||||
BOOL currentEventShouldBeSuppressed;
|
||||
@@ -208,8 +207,6 @@ var hasEditableTarget = function(aDOMEvent)
|
||||
if (!(modifierFlags & (CPControlKeyMask | CPCommandKeyMask)))
|
||||
return;
|
||||
|
||||
_lastKeyDownEvent = anEvent;
|
||||
|
||||
var aDOMEvent = anEvent._DOMEvent,
|
||||
characters = [anEvent characters],
|
||||
mayRequireDOMPasteboardElement = [self _mayRequireDOMPasteboardElementHack:aDOMEvent flags:modifierFlags];
|
||||
@@ -302,7 +299,7 @@ var hasEditableTarget = function(aDOMEvent)
|
||||
timestamp = [CPEvent currentTimestamp], // fake event, might as well use current timestamp
|
||||
windowNumber = [[CPApp keyWindow] windowNumber],
|
||||
modifierFlags = CPPlatformActionKeyMask,
|
||||
location = [_lastKeyDownEvent locationInWindow],
|
||||
location = [[CPApp currentEvent] locationInWindow],
|
||||
anEvent = [CPEvent keyEventWithType:CPKeyDown location:location modifierFlags:modifierFlags
|
||||
timestamp:timestamp windowNumber:windowNumber context:nil
|
||||
characters:characters charactersIgnoringModifiers:characters isARepeat:NO keyCode:keyCode];
|
||||
|
||||
@@ -151,7 +151,7 @@ var DOMFixedWidthSpanElement = nil,
|
||||
else if (CPFeatureIsCompatible(CPJavaScriptTextContentFeature))
|
||||
span.textContent = aString;
|
||||
|
||||
return CGSizeMake(span.clientWidth, span.clientHeight);
|
||||
return CGSizeMake(span.clientWidth + 1, span.clientHeight);
|
||||
}
|
||||
|
||||
+ (CPDictionary)metricsOfFont:(CPFont)aFont
|
||||
|
||||
@@ -201,6 +201,11 @@ var ModifierKeyCodes = [
|
||||
supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop];
|
||||
|
||||
var resizeTimer = nil;
|
||||
var PreventScroll = true;
|
||||
|
||||
// When scrolling with an old-style scroll wheel with discete steps ('clicks'), the scroll amount can indicate how many "lines" to
|
||||
// scroll.
|
||||
#define SCROLLWHEEL_LINE_PIXELS 6.0
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
|
||||
@@ -325,8 +330,8 @@ var resizeTimer = nil;
|
||||
_DOMScrollingElement.style.position = "absolute";
|
||||
_DOMScrollingElement.style.visibility = "hidden";
|
||||
_DOMScrollingElement.style.zIndex = @"999";
|
||||
_DOMScrollingElement.style.height = "60px";
|
||||
_DOMScrollingElement.style.width = "60px";
|
||||
_DOMScrollingElement.style.height = "500px";
|
||||
_DOMScrollingElement.style.width = "500px";
|
||||
_DOMScrollingElement.style.overflow = "scroll";
|
||||
//_DOMScrollingElement.style.backgroundColor = "rgba(0,0,0,1.0)"; // debug help.
|
||||
_DOMScrollingElement.style.opacity = "0";
|
||||
@@ -335,8 +340,8 @@ var resizeTimer = nil;
|
||||
_DOMBodyElement.appendChild(_DOMScrollingElement);
|
||||
|
||||
var _DOMInnerScrollingElement = theDocument.createElement("div");
|
||||
_DOMInnerScrollingElement.style.width = "400px";
|
||||
_DOMInnerScrollingElement.style.height = "400px";
|
||||
_DOMInnerScrollingElement.style.width = "5000px";
|
||||
_DOMInnerScrollingElement.style.height = "5000px";
|
||||
_DOMScrollingElement.appendChild(_DOMInnerScrollingElement);
|
||||
|
||||
// Set an initial scroll offset
|
||||
@@ -842,6 +847,12 @@ var resizeTimer = nil;
|
||||
|
||||
- (void)scrollEvent:(DOMEvent)aDOMEvent
|
||||
{
|
||||
if (PreventScroll)
|
||||
{
|
||||
PreventScroll = false;
|
||||
aDOMEvent.preventDefault();
|
||||
}
|
||||
|
||||
if (_hideDOMScrollingElementTimeout)
|
||||
{
|
||||
clearTimeout(_hideDOMScrollingElementTimeout);
|
||||
@@ -852,7 +863,6 @@ var resizeTimer = nil;
|
||||
aDOMEvent = window.event;
|
||||
|
||||
var location = nil;
|
||||
|
||||
if (CPFeatureIsCompatible(CPJavaScriptMouseWheelValues_8_15))
|
||||
{
|
||||
var x = aDOMEvent._offsetX || 0.0,
|
||||
@@ -911,9 +921,22 @@ var resizeTimer = nil;
|
||||
// We lag 1 event behind without this timeout.
|
||||
setTimeout(function()
|
||||
{
|
||||
// Find the scroll delta
|
||||
var deltaX = _DOMScrollingElement.scrollLeft - 150,
|
||||
deltaY = (_DOMScrollingElement.scrollTop - 150) || (aDOMEvent.deltaY === undefined ? 0 : aDOMEvent.deltaY);
|
||||
if (aDOMEvent.deltaMode !== undefined && aDOMEvent.deltaMode !== 0)
|
||||
{
|
||||
event._hasPreciseScrollingDeltas = NO;
|
||||
event._scrollingDeltaX = aDOMEvent.deltaX;
|
||||
event._scrollingDeltaY = aDOMEvent.deltaY;
|
||||
event._deltaX = aDOMEvent.deltaX * SCROLLWHEEL_LINE_PIXELS;
|
||||
event._deltaY = aDOMEvent.deltaY * SCROLLWHEEL_LINE_PIXELS;
|
||||
}
|
||||
else
|
||||
{
|
||||
event._hasPreciseScrollingDeltas = YES;
|
||||
event._scrollingDeltaX = (_DOMScrollingElement.scrollLeft - 150) || aDOMEvent.deltaX || 0;
|
||||
event._scrollingDeltaY = (_DOMScrollingElement.scrollTop - 150) || aDOMEvent.deltaY || 0;
|
||||
event._deltaX = event._scrollingDeltaX;
|
||||
event._deltaY = event._scrollingDeltaY;
|
||||
}
|
||||
|
||||
// If we scroll super with momentum,
|
||||
// there are so many events going off that
|
||||
@@ -924,13 +947,8 @@ var resizeTimer = nil;
|
||||
//
|
||||
// We get free performance boost if we skip sending these events,
|
||||
// as sending a scroll event with no deltas doesn't do anything.
|
||||
if (deltaX || deltaY)
|
||||
{
|
||||
event._deltaX = deltaX;
|
||||
event._deltaY = deltaY;
|
||||
|
||||
if (event._deltaX || event._deltaY)
|
||||
[CPApp sendEvent:event];
|
||||
}
|
||||
|
||||
// We set StopDOMEventPropagation = NO on line 1008
|
||||
//if (StopDOMEventPropagation)
|
||||
@@ -950,6 +968,7 @@ var resizeTimer = nil;
|
||||
// can receive events.
|
||||
_hideDOMScrollingElementTimeout = setTimeout(function()
|
||||
{
|
||||
PreventScroll = true;
|
||||
_DOMScrollingElement.style.visibility = "hidden";
|
||||
}, 300);
|
||||
}
|
||||
@@ -1124,7 +1143,7 @@ var resizeTimer = nil;
|
||||
|
||||
_mouseDownIsRightClick = button == 2 || (CPBrowserIsOperatingSystem(CPMacOperatingSystem) && button == 0 && modifierFlags & CPControlKeyMask);
|
||||
|
||||
if (sourceElement.tagName === "INPUT" && sourceElement != _DOMFocusElement)
|
||||
if ((sourceElement.tagName === "INPUT" || sourceElement.tagName === "TEXTAREA") && sourceElement != _DOMFocusElement)
|
||||
{
|
||||
if ([CPPlatform supportsDragAndDrop])
|
||||
{
|
||||
@@ -1261,7 +1280,7 @@ var resizeTimer = nil;
|
||||
insertionIndex = _windowLevels[middle] > aLevel ? middle : middle + 1
|
||||
|
||||
[_windowLevels insertObject:aLevel atIndex:insertionIndex];
|
||||
layer._DOMElement.style.zIndex = aLevel;
|
||||
layer._DOMElement.style.zIndex = aLevel + 1; // adding one avoids negative zIndices. These have been causing issues in Chrome
|
||||
|
||||
_DOMBodyElement.appendChild(layer._DOMElement);
|
||||
}
|
||||
@@ -1280,7 +1299,10 @@ var resizeTimer = nil;
|
||||
// When ordering out, ignore otherWindow, simply remove aWindow from its level.
|
||||
// If layer is nil, this will be a no-op.
|
||||
if (orderingMode === CPWindowOut)
|
||||
{
|
||||
[aWindow _windowWillBeRemovedFromTheDOM];
|
||||
return [layer removeWindow:aWindow];
|
||||
}
|
||||
|
||||
/*
|
||||
If aWindow is a child of otherWindow and is not yet visible,
|
||||
@@ -1326,6 +1348,8 @@ var resizeTimer = nil;
|
||||
if (otherWindow)
|
||||
insertionIndex = orderingMode === CPWindowAbove ? otherWindow._index + 1 : otherWindow._index;
|
||||
|
||||
[aWindow _windowWillBeAddedToTheDOM];
|
||||
|
||||
// Place the window at the appropriate index.
|
||||
[layer insertWindow:aWindow atIndex:insertionIndex];
|
||||
|
||||
@@ -1376,6 +1400,9 @@ var resizeTimer = nil;
|
||||
|
||||
var index = ordering === CPWindowAbove ? parent._index + 1 : parent._index;
|
||||
|
||||
if (!childWasVisible)
|
||||
[child _windowWillBeAddedToTheDOM];
|
||||
|
||||
[aLayer insertWindow:child atIndex:index];
|
||||
|
||||
if (!childWasVisible)
|
||||
@@ -1654,16 +1681,15 @@ var CPDOMEventGetClickCount = function(aComparisonEvent, aTimestamp, aLocation)
|
||||
// Global.
|
||||
_CPDOMEventStop = function(aDOMEvent, aPlatformWindow)
|
||||
{
|
||||
// IE Model
|
||||
aDOMEvent.cancelBubble = true;
|
||||
aDOMEvent.returnValue = false;
|
||||
|
||||
// W3C Model
|
||||
if (aDOMEvent.preventDefault)
|
||||
if (aDOMEvent.preventDefault) // W3C Model
|
||||
aDOMEvent.preventDefault();
|
||||
else // IE Model
|
||||
aDOMEvent.returnValue = false;
|
||||
|
||||
if (aDOMEvent.stopPropagation)
|
||||
if (aDOMEvent.stopPropagation) // W3C Model
|
||||
aDOMEvent.stopPropagation();
|
||||
else // IE Model
|
||||
aDOMEvent.cancelBubble = true;
|
||||
};
|
||||
|
||||
function CPWindowObjectList()
|
||||
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 88 B |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 79 B |