master
prep 2013-03-11 15:05:47 -04:00
commit e0c9174609
526 changed files with 32949 additions and 26187 deletions

130
.hgtags
View File

@ -72,35 +72,35 @@ b53a0576eec80614d7767ed72b40ed67aeff27c9 DRTVWR-38_2.5.2-release
461c8c65b5c799ddfe365422f9be9c0095d91e7d 2.6.0-beta1-tip
9e4641f4a7870c0f565a25a2971368d5a29516a1 2.6.0-beta2
9e4641f4a7870c0f565a25a2971368d5a29516a1 DRTVWR-41_2.6.0-beta2
42f32494bac475d0737799346f6831558ae8bf5d 2.6.0-release
42f32494bac475d0737799346f6831558ae8bf5d DRTVWR-39_2.6.0-release
c5bdef3aaa2744626aef3c217ce29e1900d357b3 2.6.1-beta1
c5bdef3aaa2744626aef3c217ce29e1900d357b3 2.6.1-start
c5bdef3aaa2744626aef3c217ce29e1900d357b3 DRTVWR-43_2.6.1-beta1
c9182ed77d427c759cfacf49a7b71a2e20d522aa 2.6.1-release
c9182ed77d427c759cfacf49a7b71a2e20d522aa DRTVWR-42_2.6.1-release
56b2778c743c2a964d82e1caf11084d76a87de2c 2.6.2-start
d1203046bb653b763f835b04d184646949d8dd5c 2.6.2-beta1
d1203046bb653b763f835b04d184646949d8dd5c DRTVWR-45_2.6.2-beta1
42f32494bac475d0737799346f6831558ae8bf5d 2.6.0-release
42f32494bac475d0737799346f6831558ae8bf5d DRTVWR-39_2.6.0-release
c9182ed77d427c759cfacf49a7b71a2e20d522aa 2.6.1-release
c9182ed77d427c759cfacf49a7b71a2e20d522aa DRTVWR-42_2.6.1-release
214180ad5714ce8392b82bbebcc92f4babd98300 2.6.2-release
214180ad5714ce8392b82bbebcc92f4babd98300 DRTVWR-44_2.6.2-release
52b2263ab28f0976c689fd0b76c55a9eb027cdbf end-of-develop.py
ec32f1045e7c2644015245df3a9933620aa194b8 2.6.3-start
d7fcefabdf32bb61a9ea6d6037c1bb26190a85bc 2.6.3-beta1
d7fcefabdf32bb61a9ea6d6037c1bb26190a85bc DRTVWR-47_2.6.3-beta1
0630e977504af5ea320c58d33cae4e1ddee793e9 2.6.3-beta2
0630e977504af5ea320c58d33cae4e1ddee793e9 DRTVWR-48_2.6.3-beta2
3178e311da3a8739a85363665006ea3c4610cad4 dons-headless-hackathon-work
214180ad5714ce8392b82bbebcc92f4babd98300 2.6.2-release
214180ad5714ce8392b82bbebcc92f4babd98300 DRTVWR-44_2.6.2-release
7db558aaa7c176f2022b3e9cfe38ac72f6d1fccd 2.6.5-beta1
7db558aaa7c176f2022b3e9cfe38ac72f6d1fccd DRTVWR-50_2.6.5-beta1
8f2da1701c81a62352df2b8d413d27fb2cade9a6 2.6.3-release
8f2da1701c81a62352df2b8d413d27fb2cade9a6 DRTVWR-46_2.6.3-release
3178e311da3a8739a85363665006ea3c4610cad4 dons-headless-hackathon-work
7db558aaa7c176f2022b3e9cfe38ac72f6d1fccd 2.6.5-beta1
7db558aaa7c176f2022b3e9cfe38ac72f6d1fccd DRTVWR-50_2.6.5-beta1
800cefce8d364ffdd2f383cbecb91294da3ea424 2.6.6-start
bb1075286b3b147b1dae2e3d6b2d56f04ff03f35 2.6.6-beta1
bb1075286b3b147b1dae2e3d6b2d56f04ff03f35 DRTVWR-52_2.6.6-beta1
5e349dbe9cc84ea5795af8aeb6d473a0af9d4953 2.6.8-start
dac76a711da5f1489a01c1fa62ec97d99c25736d 2.6.6-release
dac76a711da5f1489a01c1fa62ec97d99c25736d DRTVWR-51_2.6.6-release
5e349dbe9cc84ea5795af8aeb6d473a0af9d4953 2.6.8-start
beafa8a9bd1d1b670b7523d865204dc4a4b38eef 2.6.8-beta1
beafa8a9bd1d1b670b7523d865204dc4a4b38eef DRTVWR-55_2.6.8-beta1
be2000b946f8cb3de5f44b2d419287d4c48ec4eb 2.6.8-release
@ -119,50 +119,50 @@ e67da2c6e3125966dd49eef98b36317afac1fcfe 2.6.9-start
9f79a6ed8fdcd2f3dac33ea6b3236eeb278dccfe 2.7.2-start
e0dc8b741eaa27dcdfbc9e956bb2579b954d15eb 2.7.2-beta1
e0dc8b741eaa27dcdfbc9e956bb2579b954d15eb DRTVWR-63_2.7.2-beta1
6a3e7e403bd19e45fdfc2fcc716867af3ab80861 2.7.3-start
fe3a8e7973072ea62043c08b19b66626c1a720eb 2.7.1-release
fe3a8e7973072ea62043c08b19b66626c1a720eb 2.7.2-release
fe3a8e7973072ea62043c08b19b66626c1a720eb DRTVWR-60_2.7.1-release
fe3a8e7973072ea62043c08b19b66626c1a720eb DRTVWR-62_2.7.2-release
6a3e7e403bd19e45fdfc2fcc716867af3ab80861 2.7.3-start
6af10678de4736222b2c3f7e010e984fb5b327de 2.7.4-start
be963a4eef635542f9617d7f5fd22ba48fb71958 2.7.4-beta1
be963a4eef635542f9617d7f5fd22ba48fb71958 DRTVWR-67_2.7.4-beta1
057f319dd8eccdf63a54d99686c68cdcb31b6abc 2.7.4-release
057f319dd8eccdf63a54d99686c68cdcb31b6abc DRTVWR-66_2.7.4-release
19a498fa62570f352d7d246f17e3c81cc1d82d8b 2.7.5-start
09984bfa6cae17e0f72d02b75c1b7393c65eecfc 2.7.5-beta1
09984bfa6cae17e0f72d02b75c1b7393c65eecfc DRTVWR-69_2.7.5-beta1
6866d9df6efbd441c66451debd376d21211de39c 2.7.5-release
6866d9df6efbd441c66451debd376d21211de39c DRTVWR-68_2.7.5-release
e1ed60913230dd64269a7f7fc52cbc6004f6d52c 2.8.0-beta1
e1ed60913230dd64269a7f7fc52cbc6004f6d52c 2.8.0-start
e1ed60913230dd64269a7f7fc52cbc6004f6d52c DRTVWR-71_2.8.0-beta1
057f319dd8eccdf63a54d99686c68cdcb31b6abc 2.7.4-release
057f319dd8eccdf63a54d99686c68cdcb31b6abc DRTVWR-66_2.7.4-release
6866d9df6efbd441c66451debd376d21211de39c 2.7.5-release
6866d9df6efbd441c66451debd376d21211de39c DRTVWR-68_2.7.5-release
493d9127ee50e84ba08a736a65a23ca86f7a5b01 2.8.0-release
493d9127ee50e84ba08a736a65a23ca86f7a5b01 DRTVWR-70_2.8.0-release
502f6a5deca9365ddae57db4f1e30172668e171e 2.8.1-start
2c7e459e0c883f8e406b932e41e60097e9ee077e 2.8.1-beta1
2c7e459e0c883f8e406b932e41e60097e9ee077e DRTVWR-73_2.8.1-beta1
493d9127ee50e84ba08a736a65a23ca86f7a5b01 2.8.0-release
493d9127ee50e84ba08a736a65a23ca86f7a5b01 DRTVWR-70_2.8.0-release
54bc7823ad4e3a436fef79710f685a7372bbf795 2.8.2-start
ac0f1a132d35c02a58861d37cca75b0429ac9137 2.8.3-start
29e93d7e19991011bd12b5748142b11a5dcb4370 2.8.1-release
29e93d7e19991011bd12b5748142b11a5dcb4370 DRTVWR-72_2.8.1-release
4780e3bd2b3042f91be3426151f28c30d199bb3b 2.8.1-hotfix
4780e3bd2b3042f91be3426151f28c30d199bb3b DRTVWR-76_2.8.1-hotfix
54bc7823ad4e3a436fef79710f685a7372bbf795 2.8.2-start
ac0f1a132d35c02a58861d37cca75b0429ac9137 2.8.3-start
599677276b227357140dda35bea4a2c18e2e67b5 2.8.3-beta1
599677276b227357140dda35bea4a2c18e2e67b5 DRTVWR-75_2.8.3-beta1
fb85792b84bf28428889c4cc966469d92e5dac4c 2.8.3-release
fb85792b84bf28428889c4cc966469d92e5dac4c DRTVWR-74_2.8.3-release
6b678ea52f90d5c14181661dcd2546e25bde483e 3.0.0-start
b0be6ce3adfef3a014a2389d360539f8a86c5439 3.0.0-beta1
b0be6ce3adfef3a014a2389d360539f8a86c5439 DRTVWR-78_3.0.0-beta1
fb85792b84bf28428889c4cc966469d92e5dac4c 2.8.3-release
fb85792b84bf28428889c4cc966469d92e5dac4c DRTVWR-74_2.8.3-release
1778f26b6d0ae762dec3ca37140f66620f2485d9 3.0.0-release
1778f26b6d0ae762dec3ca37140f66620f2485d9 DRTVWR-77_3.0.0-release
82a2079ffcb57ecb1b3849cb41376b443e1eb912 3.0.1-start
364fd63517fbacbbcb9129d096187171ba8c9e48 3.0.1-beta1
364fd63517fbacbbcb9129d096187171ba8c9e48 DRTVWR-81_3.0.1-beta1
f2412ecd6740803ea9452f1d17fd872e263a0df7 3.0.2-start
42784bf50fa01974bada2a1af3892ee09c93fcda 3.0.2-beta1
42784bf50fa01974bada2a1af3892ee09c93fcda DRTVWR-83_3.0.2-beta1
1778f26b6d0ae762dec3ca37140f66620f2485d9 3.0.0-release
1778f26b6d0ae762dec3ca37140f66620f2485d9 DRTVWR-77_3.0.0-release
e5c9af2d7980a99a71650be3a0cf7b2b3c3b897e 3.0.2-beta2
e5c9af2d7980a99a71650be3a0cf7b2b3c3b897e DRTVWR-86_3.0.2-beta2
b95ddac176ac944efdc85cbee94ac2e1eab44c79 3.0.3-start
@ -170,9 +170,9 @@ b95ddac176ac944efdc85cbee94ac2e1eab44c79 3.0.3-start
6694f3f062aa45f64ab391d25a3eb3d5eb1b0871 DRTVWR-85_3.0.3-beta1
61aa7974df089e8621fe9a4c69bcdefdb3cc208a 3.0.3-beta2
61aa7974df089e8621fe9a4c69bcdefdb3cc208a DRTVWR-89_3.0.3-beta2
586907287be581817b2422b5137971b22d54ea48 3.0.4-start
0496d2f74043cf4e6058e76ac3db03d44cff42ce 3.0.3-release
0496d2f74043cf4e6058e76ac3db03d44cff42ce DRTVWR-84_3.0.3-release
586907287be581817b2422b5137971b22d54ea48 3.0.4-start
92a3aa04775438226399b19deee12ac3b5a62838 3.0.5-start
c7282e59f374ee904bd793c3c444455e3399b0c5 3.1.0-start
2657fa785bbfac115852c41bd0adaff74c2ad5da 3.1.0-beta1
@ -193,11 +193,11 @@ e440cd1dfbd128d7d5467019e497f7f803640ad6 DRTVWR-95_3.2.0-beta1
c4911ec8cd81e676dfd2af438b3e065407a94a7a 3.2.1-start
9e390d76807fa70d356b8716fb83b8ce42a629ef 3.2.1-beta1
9e390d76807fa70d356b8716fb83b8ce42a629ef DRTVWR-100_3.2.1-beta1
a8c7030d6845186fac7c188be4323a0e887b4184 3.2.1-release
a8c7030d6845186fac7c188be4323a0e887b4184 DRTVWR-99_3.2.1-release
40b46edba007d15d0059c80864b708b99c1da368 3.2.2-start
523df3e67378541498d516d52af4402176a26bac 3.2.2-beta1
523df3e67378541498d516d52af4402176a26bac DRTVWR-102_3.2.2-beta1
a8c7030d6845186fac7c188be4323a0e887b4184 3.2.1-release
a8c7030d6845186fac7c188be4323a0e887b4184 DRTVWR-99_3.2.1-release
80f3e30d8aa4d8f674a48bd742aaa6d8e9eae0b5 3.2.3-start
3fe994349fae64fc40874bb59db387131eb35a41 3.2.4-beta1
3fe994349fae64fc40874bb59db387131eb35a41 3.2.4-start
@ -248,57 +248,68 @@ bb9932a7a5fd00edf52d95f354e3b37ae6a942db DRTVWR-156
6414ecdabc5d89515b08d1f872cf923ed3a5523a DRTVWR-148
2a3965b3ad202df7ea25d2be689291bb14a1280e DRTVWR-155
24a7281bef42bd4430ceb25db8b195449c2c7de3 DRTVWR-153
a716684aa7c07c440b1de5815b8a1f3dd3fd8bfb DRTVWR-159
9a78ac13f047056f788c4734dd91aebfe30970e3 DRTVWR-157
5910f8063a7e1ddddf504c2f35ca831cc5e8f469 DRTVWR-160
f0a174c2adb4bc39b16722a61d7eeb4f2a1d4843 3.3.3-beta1
f0a174c2adb4bc39b16722a61d7eeb4f2a1d4843 DRTVWR-144
2d6c0634b11e6f3df11002b8510a72a0433da00a DRTVWR-164
089e5c84b2dece68f2b016c842ef9b5de4786842 DRTVWR-161
600f3b3920d94de805ac6dc8bb6def9c069dd360 DRTVWR-162
c08e2ac17a99973b2a94477659220b99b8847ae2 DRTVWR-163
2d6c0634b11e6f3df11002b8510a72a0433da00a DRTVWR-164
80b5e5e9775966d3839331ffa7a16a60f9d7c930 DRTVWR-165
fdcc08a4f20ae9bb060f4693c8980d216534efdf 3.3.3-beta2
af5f3e43e6e4424b1da19d9e16f6b853a7b822ed DRTVWR-169
4b3c68199a86cabaa5d9466d7b0f7e141e901d7a 3.3.3-beta3
6428242e124b523813bfaf4c45b3d422f0298c81 3.3.3-release
a716684aa7c07c440b1de5815b8a1f3dd3fd8bfb DRTVWR-159
9a78ac13f047056f788c4734dd91aebfe30970e3 DRTVWR-157
089e5c84b2dece68f2b016c842ef9b5de4786842 DRTVWR-161
c08e2ac17a99973b2a94477659220b99b8847ae2 DRTVWR-163
b9d0170b62eb1c7c3adaa37a0b13a833e5e659f9 DRTVWR-171
050e48759337249130f684b4a21080b683f61732 DRTVWR-168
09ef7fd1b0781f33b8a3a9af6236b7bcb4831910 DRTVWR-170
f87bfbe0b62d26f451d02a47c80ebef6b9168fc2 DRTVWR-158
f91d003091a61937a044652c4c674447f7dcbb7a 3.3.4-beta1
005dfe5c4c377207d065fb27858d2eb0b53b143a DRTVWR-167
bce218b2b45b730b22cc51e4807aa8b571cadef3 DRTVWR-173
cbea6356ce9cb0c313b6777f10c5c14783264fcc DRTVWR-174
82b5330bc8b17d0d4b598832e9c5a92e90075682 3.3.4-beta2
57d221de3df94f90b55204313c2cef044a3c0ae2 DRTVWR-176
eb539c65e6ee26eea2bf373af2d0f4b52dc91289 DRTVWR-177
a8057e1b9a1246b434a27405be35e030f7d28b0c 3.3.4-beta3
888768f162d2c0a8de1dcc5fb9a08bd8bd120a6b DRTVWR-175
4281aa899fb2cedb7a9ca7ce91c5c29d4aa69594 DRTVWR-180
5c08e1d8edd871807153603b690e3ee9dbb548aa DRTVWR-183
6c75f220b103db1420919c8b635fe53e2177f318 3.3.4-beta4
9cd174d3a54d93d409a7c346a15b8bfb40fc58f4 DRTVWR-184
ab2ffc547c8a8950ff187c4f6c95e5334fab597b 3.3.4-beta5
28e100d0379a2b0710c57647a28fc5239d3d7b99 3.3.4-release
005dfe5c4c377207d065fb27858d2eb0b53b143a DRTVWR-167
888768f162d2c0a8de1dcc5fb9a08bd8bd120a6b DRTVWR-175
a8b3eca451a9eaab59987efb0ab1c4217e3f2dcc DRTVWR-182
1f27cdfdc54246484f8afbbe42ce48e954175cbd 3.4.0-beta1
9ee9387789701d597130f879d9011a4958753862 DRTVWR-189
81f6b745ef27f5915fd07f988fdec9944f2bb73e DRTVWR-186
47f0d08ba7ade0a3905074009067c6d3df7e16ae DRTVWR-190
cc953f00956be52cc64c30637bbeec310eea603f DRTVWR-181
c04e68e1b0034fd0a20815ae24c77e5f8428e822 DRTVWR-188
9ee9387789701d597130f879d9011a4958753862 DRTVWR-189
421126293dcbde918e0da027ca0ab9deb5b4fbf2 DRTVWR-192
4b2c52aecb7a75de31dbb12d9f5b9a251d8707be DRTVWR-191
33a2fc7a910ae29ff8b4850316ed7fbff9f64d33 DRTVWR-195
e9732c739c8a72a590216951505ea9c76a526a84 DRTVWR-193
78ca0bbf43a92e8914d4cfa87d69a6717ef7d4cf DRTVWR-194
7602f61c804a512764e349c034c02ddabeefebc4 DRTVWR-196
ae5c83dd61d2d37c45f1d5b8bf2b036d87599f1b DRTVWR-198
507bdfbd6bf844a511c1ffeda4baa80016ed1346 DRTVWR-197
b1dbb1a83f48f93f6f878cff9e52d2cb635e145c 3.4.0-beta2
37402e2b19af970d51b0a814d79892cc5647532b DRTVWR-200
182a9bf30e81070361bb020a78003b1cf398e79c 3.4.0-beta3
248f4acd92a706c79e842bc83d80baa7369c0c2e DRTVWR-203
6dfb0fba782c9233dd95f24ec48146db0d3f210b DRTVWR-199
7c9102fb998885621919f2474a002c35b583539b 3.3.4-release2
7649a3dff5ec22d3727377e5f02efd0f421e4cb5 DRTVWR-201
84fb70dfe3444e75a44fb4bee43e2fc8221cebdd 3.4.0-beta4
de3be913f68813a9bac7d1c671fef96d1159bcd6 DRTVWR-202
092a9effbedd1a0276fa5ced520992ce00f96fbf CHUI-PV-0
573e863be2f26d3687161def4b9fea9b7038dda8 3.4.0-beta5
34dbbe2b00afe90352d3acf8290eb10ab90d1c8b oz-build-test-tag
6ee71714935ffcd159db3d4f5800c1929aac54e1 DRTVWR-205
7b22c612fc756e0ea63b10b163e81d107f85dbf8 DRTVWR-206
8c9085066c78ed5f6c9379dc054c82a6fcdb1851 DRTVWR-207
351eea5f9dc192fc5ddea3b02958de97677a0a12 3.3.4-release3
af7b28e75bd5a629cd9e0dc46fb3f1757626f493 DRTVWR-212
@ -309,6 +320,7 @@ ceed0b65a69f1eac20d523e0203320a32f9a3f3c DRTVWR-215
97977c67245f52db20eb15f1918cc0f24778cabc 3.4.0-release
5adb2b8f96c3cac88ad7c7d996d707f1b29df336 3.4.1-beta1
b3f74858a1c8720c82d0978f3877a3fc8ba459ec 3.4.1-beta1a
b61afe175b829c149d369524a4e974dfda99facf DRTVWR-219
2b779f233ee6f38c89cb921650c773a96e63da92 DRTVWR-220
0b9d95f4bfb6867cbf56eaec51633b0da2f1262d DRTVWR-221
e6e553761829dc0270eaaa712b7cb0622535b076 3.4.1-beta3
@ -333,36 +345,31 @@ baf97f06ae17223614c5e31aa42e71d87cff07fe DRTVWR-236
b2f21e3442542283a80e7eaebae9f833e5a927b6 DRTVWR-237
3f9be82de642d468c5fc272cb9d96b46b5498402 3.4.1-beta12
e59ffd3fe0838ae6b09b242a6e9df71761b88f41 3.4.1-release
81f6b745ef27f5915fd07f988fdec9944f2bb73e DRTVWR-186
cc953f00956be52cc64c30637bbeec310eea603f DRTVWR-181
c04e68e1b0034fd0a20815ae24c77e5f8428e822 DRTVWR-188
4b2c52aecb7a75de31dbb12d9f5b9a251d8707be DRTVWR-191
78ca0bbf43a92e8914d4cfa87d69a6717ef7d4cf DRTVWR-194
248f4acd92a706c79e842bc83d80baa7369c0c2e DRTVWR-203
de3be913f68813a9bac7d1c671fef96d1159bcd6 DRTVWR-202
34dbbe2b00afe90352d3acf8290eb10ab90d1c8b oz-build-test-tag
6ee71714935ffcd159db3d4f5800c1929aac54e1 DRTVWR-205
7b22c612fc756e0ea63b10b163e81d107f85dbf8 DRTVWR-206
b61afe175b829c149d369524a4e974dfda99facf DRTVWR-219
32896d5e920ca9a29256ff3b747c2e99752aa5ae DRTVWR-217
704bbae7b182a1f2811a47a054e680522966f54a 3.4.2-beta1
288539fc0408ed4b69a99665de33bbbc2c3c08fe DRTVWR-216
e664473c16df1d82ffaff382e7b3e023da202d52 3.4.2-beta2
0891d7a773a31397dcad48be3fa66531d567a821 DRTVWR-242
710785535362b3cb801b6a3dc4703be3373bd0cd 3.4.2-beta3
e9a5886052433d5db9e504ffaca10890f9932979 DRTVWR-243
73b84b9864dc650fe7c8fc9f52361450f0849004 3.4.2-beta4
16310aabccf315870f7cc9bf966926c0ad6954fa 3.4.2-release
d799593b53ed733862e9a13871e318e886469377 DRTVWR-208
e497dcde7a3653e384eb223a8a460030e89c294c DRTVWR-223
288539fc0408ed4b69a99665de33bbbc2c3c08fe DRTVWR-216
e664473c16df1d82ffaff382e7b3e023da202d52 3.4.2-beta2
93ab02d83f51e30a3cabad98aff89601befd9413 DRTVWR-240
0891d7a773a31397dcad48be3fa66531d567a821 DRTVWR-242
710785535362b3cb801b6a3dc4703be3373bd0cd 3.4.2-beta3
2aa72e3372a83dece4df9cf72fb1e7c34f90b5e3 DRTVWR-209
f7bedce18ad52283e6072814db23318907261487 DRTVWR-238
7b64c96fbcadf360bd2feaae19d330166b70877c DRTVWR-210
e9a5886052433d5db9e504ffaca10890f9932979 DRTVWR-243
73b84b9864dc650fe7c8fc9f52361450f0849004 3.4.2-beta4
16310aabccf315870f7cc9bf966926c0ad6954fa 3.4.2-release
5e4e4128b256525bafc07a62e35ae8527aaa9c9d DRTVWR-241
f1d3b3fcab28ed9ea532bf50db0ba96f5c8cc8e9 DRTVWR-232
4918b150e75df6b516fb6c2616d32043fa6b4cac DRTVWR-245
94ab2b49458ab372a95d2d6949fdf574f413068d 3.4.3-beta1
4c3460cb1fb7c6da9965e09c734d282a8e9c81f0 DRTVWR-229
f4481df42f9a4a92bf475a80f0c51d1a4bbdfd59 DRTVWR-246
39c5204b6e800983a41ccac8ad6dc993120197c6 DRTVWR-247
7c7d57d393e8ae7b61623279de06eb4a62ccae6a DRTVWR-249
f72b50ef168c159d6e79e97aa2bcafaf8577ab99 DRTVWR-230
b418be80903520c492e1173f3afbc4021cad5d07 DRTVWR-255
965b9a35e260c0f53be1a25f0db7abc8a67eaf47 DRTVWR-252
bb10adc4f76cf0067fca7075146f00cdc0740e9d DRTVWR-251
ab0aa2f6ba22b52fed30a2337197f589156edc75 DRTVWR-253
@ -371,31 +378,25 @@ ab0aa2f6ba22b52fed30a2337197f589156edc75 DRTVWR-253
44e764a6ac9e672a4f3bce821a4b6a218590c374 DRTVWR-258
c23d734065ed593b2413385aecd8366d8e0ee96b DRTVWR-257
452ce96d4046dc05a3ecaecc203e2cc8ddd72e76 DRTVWR-259
9aa1aa9f1fe13c194695a0b8f0af298296241dc2 DRTVWR-260
daca610d840625b5bebb966a57cb49581852c417 DRTVWR-265
9afbdc4e24cc04feacfb2b7a10b78a64f780901a DRTVWR-266
73280db02501f5ad041fc18b1eba68e73a81996c DRTVWR-267
870e2d79e0063fda87187f17bbc2747766733194 3.4.3-beta3
0a2ca6546b499239afeb66d17b2fadbcdbe36ab1 3.4.3-release
4c3460cb1fb7c6da9965e09c734d282a8e9c81f0 DRTVWR-229
f4481df42f9a4a92bf475a80f0c51d1a4bbdfd59 DRTVWR-246
39c5204b6e800983a41ccac8ad6dc993120197c6 DRTVWR-247
7c7d57d393e8ae7b61623279de06eb4a62ccae6a DRTVWR-249
f72b50ef168c159d6e79e97aa2bcafaf8577ab99 DRTVWR-230
b418be80903520c492e1173f3afbc4021cad5d07 DRTVWR-255
9aa1aa9f1fe13c194695a0b8f0af298296241dc2 DRTVWR-260
84fbaf2d4141bd161731430e760949dc787ca206 DRTVWR-244
083d2d36b5bb1c54fc3dd7caac0e7ac381a9cef0 3.4.4-beta1
391a8c74cec7275c5d26c85ad108d4782a3e3dd9 DRTVWR-268
b634dec987c16e8c9c938e11e52591d9ead8fa9b DRTVWR-270
cd39255bd23330fd30c04105f2811e941d8524fe 3.4.4-beta2
2c4011bbc2b15b82198fd8b51f3a9fe765a08c4d DRTVWR-271
2f8a3ef687bc55828abcb17ac1ad7cde70536d7e 3.4.4-beta3
35cfd4cf5b895fa776592f2e630e330be7f0604e DRTVWR-273
a36f1f354b02aa6e448ca13685de167d0a0a3d03 DRTVWR-272
37dba00ad820de3a808d4039396b162a9c275b3e DRTVWR-269
c374035d459af3c03dea2dd90880dfc25de64706 DRTVWR-275
05d9f1dd7a954069af2a33abedb7713fa36a04cb 3.4.4-beta4
e1bb1ae7d8b12faeb37933a737c199cc9b9f89cc 3.4.4-release
391a8c74cec7275c5d26c85ad108d4782a3e3dd9 DRTVWR-268
a36f1f354b02aa6e448ca13685de167d0a0a3d03 DRTVWR-272
37dba00ad820de3a808d4039396b162a9c275b3e DRTVWR-269
7c6dfdc1b7a2ce0d8e3a8f3ce3058547ea065c0f DRTVWR-250
b9ff9730daa53a541925300cbd02bb14575a5705 DRTVWR-277
af6b711a97073431953b55ee808aaa09900c27e5 DRTVWR-276
@ -405,6 +406,8 @@ c296133849d1f103c0e2abc41e6599daed00b67b DRTVWR-280
5df4802bec93c8d0a509946d826bb4c50c5442ec DRTVWR-281
7c1c33ba4cfd2d15ca51cc1ac440eca551331a4a DRTVWR-283
6b9c7dbebef793230d64e1b452577c8b142d4143 3.4.5-beta2
37947e4f771f001b551581bf7cd0051c3153beed DRTVWR-282
6482cceb91cda68b799f3e6cdc66d33bf123547a DRTVWR-284
ccf991e02dc2f63fb646324230d54832683f4a9b DRTVWR-286
2d849850558a5a0324b398d1c102d30bcbdfb88f DRTVWR-287
e06898df8644fe567bee94f817d03abc1c380993 3.4.5-beta3
@ -416,3 +419,6 @@ b23419a2748483c98f3b84b630468a21c88feba5 DRTVWR-292
1cce8447f8f574673e3f47d6fe584262e6964fe2 DRTVWR-296
0a5d409161ef2a89b28c9a741051dd2dedc707d6 DRTVWR-297
852b69ef0b5fe6b13b69cc2217282cc64de6afab 3.4.5-beta5
a49c715243a36a8a380504d14cb7416b3039c956 3.4.5-release
279ef1dfc9b749a6cc499cf190fec0c090b6d682 DRTVWR-288
9b19edaf1d8ddf435f60fbbb444dd25db8f63953 3.5.0-beta1

View File

@ -132,6 +132,18 @@ viewer-pathfinding.build_debug_release_separately = true
viewer-pathfinding.build_CYGWIN_Debug = false
viewer-pathfinding.build_viewer_update_version_manager = false
# ========================================
# viewer-chui
#
# ========================================
viewer-chui.viewer_channel = "Project Viewer - CHUI"
viewer-chui.login_channel = "Project Viewer - CHUI"
viewer-chui.viewer_grid = agni
viewer-chui.build_debug_release_separately = true
viewer-chui.build_CYGWIN_Debug = false
viewer-chui.build_viewer_update_version_manager = false
# =================================================================
# asset delivery 2010 projects
# =================================================================

View File

@ -38,7 +38,8 @@
#include "llvfs.h"
#include "lltexlayerparams.h"
#include "lltexturemanagerbridge.h"
#include "llrender2dutils.h"
//#include "llrender2dutils.h"
#include "..\llui\llui.h"
#include "llwearable.h"
#include "llwearabledata.h"
#include "llvertexbuffer.h"

View File

@ -33,7 +33,8 @@
#include "llquantize.h"
#include "lltexlayer.h"
#include "lltexturemanagerbridge.h"
#include "llrender2dutils.h"
//#include "llrender2dutils.h"
#include "..\llui\llui.h"
#include "llwearable.h"
//-----------------------------------------------------------------------------

View File

@ -839,6 +839,10 @@ void LLAudioEngine::triggerSound(const LLUUID &audio_uuid, const LLUUID& owner_i
asp->play(audio_uuid);
}
void LLAudioEngine::triggerSound(SoundData& soundData)
{
triggerSound(soundData.audio_uuid, soundData.owner_id, soundData.gain, soundData.type, soundData.pos_global);
}
void LLAudioEngine::setListenerPos(LLVector3 aVec)
{

View File

@ -66,6 +66,7 @@ class LLAudioChannel;
class LLAudioChannelOpenAL;
class LLAudioBuffer;
class LLStreamingAudioInterface;
struct SoundData;
//
@ -144,6 +145,8 @@ public:
void triggerSound(const LLUUID &sound_id, const LLUUID& owner_id, const F32 gain,
const S32 type = LLAudioEngine::AUDIO_TYPE_NONE,
const LLVector3d &pos_global = LLVector3d::zero);
void triggerSound(SoundData& soundData);
bool preloadSound(const LLUUID &id);
void addAudioSource(LLAudioSource *asp);
@ -456,6 +459,27 @@ protected:
LLFrameTimer mLastUseTimer;
};
struct SoundData
{
LLUUID audio_uuid;
LLUUID owner_id;
F32 gain;
S32 type;
LLVector3d pos_global;
SoundData(const LLUUID &audio_uuid,
const LLUUID& owner_id,
const F32 gain,
const S32 type = LLAudioEngine::AUDIO_TYPE_NONE,
const LLVector3d &pos_global = LLVector3d::zero)
{
this->audio_uuid = audio_uuid;
this->owner_id = owner_id;
this->gain = gain;
this->type = type;
this->pos_global = pos_global;
}
};
extern LLAudioEngine* gAudiop;

View File

@ -46,7 +46,7 @@ LLUUID const ANIM_AGENT_BLOW_KISS ("db84829b-462c-ee83-1e27-9bbee66b
LLUUID const ANIM_AGENT_BORED ("b906c4ba-703b-1940-32a3-0c7f7d791510");
LLUUID const ANIM_AGENT_BOW ("82e99230-c906-1403-4d9c-3889dd98daba");
LLUUID const ANIM_AGENT_BRUSH ("349a3801-54f9-bf2c-3bd0-1ac89772af01");
LLUUID const ANIM_AGENT_BUSY ("efcf670c-2d18-8128-973a-034ebc806b67");
LLUUID const ANIM_AGENT_DO_NOT_DISTURB ("efcf670c-2d18-8128-973a-034ebc806b67");
LLUUID const ANIM_AGENT_CLAP ("9b0c1c4e-8ac7-7969-1494-28c874c4f668");
LLUUID const ANIM_AGENT_COURTBOW ("9ba1c942-08be-e43a-fb29-16ad440efc50");
LLUUID const ANIM_AGENT_CROUCH ("201f3fdf-cb1f-dbec-201f-7333e328ae7c");
@ -211,7 +211,7 @@ LLAnimationLibrary::LLAnimationLibrary() :
mAnimMap[ANIM_AGENT_BORED]= mAnimStringTable.addString("express_bored");
mAnimMap[ANIM_AGENT_BOW]= mAnimStringTable.addString("bow");
mAnimMap[ANIM_AGENT_BRUSH]= mAnimStringTable.addString("brush");
mAnimMap[ANIM_AGENT_BUSY]= mAnimStringTable.addString("busy");
mAnimMap[ANIM_AGENT_DO_NOT_DISTURB]= mAnimStringTable.addString("busy");
mAnimMap[ANIM_AGENT_CLAP]= mAnimStringTable.addString("clap");
mAnimMap[ANIM_AGENT_COURTBOW]= mAnimStringTable.addString("courtbow");
mAnimMap[ANIM_AGENT_CROUCH]= mAnimStringTable.addString("crouch");

View File

@ -56,7 +56,7 @@ extern const LLUUID ANIM_AGENT_BLOW_KISS;
extern const LLUUID ANIM_AGENT_BORED;
extern const LLUUID ANIM_AGENT_BOW;
extern const LLUUID ANIM_AGENT_BRUSH;
extern const LLUUID ANIM_AGENT_BUSY;
extern const LLUUID ANIM_AGENT_DO_NOT_DISTURB;
extern const LLUUID ANIM_AGENT_CLAP;
extern const LLUUID ANIM_AGENT_COURTBOW;
extern const LLUUID ANIM_AGENT_CROUCH;

View File

@ -95,6 +95,7 @@ LLAssetDictionary::LLAssetDictionary()
addEntry(LLAssetType::AT_LINK_FOLDER, new AssetEntry("FOLDER_LINK", "link_f", "sym folder link", false, false, true));
addEntry(LLAssetType::AT_MESH, new AssetEntry("MESH", "mesh", "mesh", false, false, false));
addEntry(LLAssetType::AT_WIDGET, new AssetEntry("WIDGET", "widget", "widget", false, false, false));
addEntry(LLAssetType::AT_PERSON, new AssetEntry("PERSON", "person", "person", false, false, false));
addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, FALSE, FALSE, FALSE));
};

View File

@ -112,6 +112,9 @@ public:
AT_WIDGET = 40,
// UI Widget: this is *not* an inventory asset type, only a viewer side asset (e.g. button, other ui items...)
AT_PERSON = 45,
// A user uuid which is not an inventory asset type, used in viewer only for adding a person to a chat via drag and drop.
AT_MESH = 49,
// Mesh data in our proprietary SLM format

View File

@ -30,6 +30,7 @@
#include "llavatarname.h"
#include "lldate.h"
#include "llframetimer.h"
#include "llsd.h"
// Store these in pre-built std::strings to avoid memory allocations in
@ -42,6 +43,14 @@ static const std::string IS_DISPLAY_NAME_DEFAULT("is_display_name_default");
static const std::string DISPLAY_NAME_EXPIRES("display_name_expires");
static const std::string DISPLAY_NAME_NEXT_UPDATE("display_name_next_update");
bool LLAvatarName::sUseDisplayNames = true;
// Minimum time-to-live (in seconds) for a name entry.
// Avatar name should always guarantee to expire reasonably soon by default
// so if the failure to get a valid expiration time was due to something temporary
// we will eventually request and get the right data.
const F64 MIN_ENTRY_LIFETIME = 60.0;
LLAvatarName::LLAvatarName()
: mUsername(),
mDisplayName(),
@ -61,6 +70,17 @@ bool LLAvatarName::operator<(const LLAvatarName& rhs) const
return mUsername < rhs.mUsername;
}
//static
void LLAvatarName::setUseDisplayNames(bool use)
{
sUseDisplayNames = use;
}
//static
bool LLAvatarName::useDisplayNames()
{
return sUseDisplayNames;
}
LLSD LLAvatarName::asLLSD() const
{
LLSD sd;
@ -85,21 +105,75 @@ void LLAvatarName::fromLLSD(const LLSD& sd)
mExpires = expires.secondsSinceEpoch();
LLDate next_update = sd[DISPLAY_NAME_NEXT_UPDATE];
mNextUpdate = next_update.secondsSinceEpoch();
// Some avatars don't have explicit display names set. Force a legible display name here.
if (mDisplayName.empty())
{
mDisplayName = mUsername;
}
}
// Transform a string (typically provided by the legacy service) into a decent
// avatar name instance.
void LLAvatarName::fromString(const std::string& full_name)
{
mDisplayName = full_name;
std::string::size_type index = full_name.find(' ');
if (index != std::string::npos)
{
// The name is in 2 parts (first last)
mLegacyFirstName = full_name.substr(0, index);
mLegacyLastName = full_name.substr(index+1);
if (mLegacyLastName != "Resident")
{
mUsername = mLegacyFirstName + "." + mLegacyLastName;
mDisplayName = full_name;
LLStringUtil::toLower(mUsername);
}
else
{
// Very old names do have a dummy "Resident" last name
// that we choose to hide from users.
mUsername = mLegacyFirstName;
mDisplayName = mLegacyFirstName;
}
}
else
{
mLegacyFirstName = full_name;
mLegacyLastName = "";
mUsername = full_name;
mDisplayName = full_name;
}
mIsDisplayNameDefault = true;
mIsTemporaryName = true;
setExpires(MIN_ENTRY_LIFETIME);
}
void LLAvatarName::setExpires(F64 expires)
{
mExpires = LLFrameTimer::getTotalSeconds() + expires;
}
std::string LLAvatarName::getCompleteName() const
{
std::string name;
if (mUsername.empty() || mIsDisplayNameDefault)
// If the display name feature is off
// OR this particular display name is defaulted (i.e. based on user name),
// then display only the easier to read instance of the person's name.
if (sUseDisplayNames)
{
name = mDisplayName;
if (mUsername.empty() || mIsDisplayNameDefault)
{
// If this particular display name is defaulted (i.e. based on user name),
// then display only the easier to read instance of the person's name.
name = mDisplayName;
}
else
{
name = mDisplayName + " (" + mUsername + ")";
}
}
else
{
name = mDisplayName + " (" + mUsername + ")";
name = getUserName();
}
return name;
}
@ -118,3 +192,48 @@ std::string LLAvatarName::getLegacyName() const
name += mLegacyLastName;
return name;
}
std::string LLAvatarName::getDisplayName() const
{
if (sUseDisplayNames)
{
return mDisplayName;
}
else
{
return getUserName();
}
}
std::string LLAvatarName::getUserName() const
{
std::string name;
if (mLegacyLastName.empty() || (mLegacyLastName == "Resident"))
{
if (mLegacyFirstName.empty())
{
// If we cannot create a user name from the legacy strings, use the display name
name = mDisplayName;
}
else
{
// The last name might be empty if it defaulted to "Resident"
name = mLegacyFirstName;
}
}
else
{
name = mLegacyFirstName + " " + mLegacyLastName;
}
return name;
}
void LLAvatarName::dump() const
{
LL_DEBUGS("AvNameCache") << "LLAvatarName: "
<< "user '" << mUsername << "' "
<< "display '" << mDisplayName << "' "
<< "expires in " << mExpires - LLFrameTimer::getTotalSeconds() << " seconds"
<< LL_ENDL;
}

View File

@ -39,10 +39,27 @@ public:
bool operator<(const LLAvatarName& rhs) const;
// Conversion to and from LLSD (cache file or server response)
LLSD asLLSD() const;
void fromLLSD(const LLSD& sd);
// Used only in legacy mode when the display name capability is not provided server side
// or to otherwise create a temporary valid item.
void fromString(const std::string& full_name);
// Set the name object to become invalid in "expires" seconds from now
void setExpires(F64 expires);
// Set and get the display name flag set by the user in preferences.
static void setUseDisplayNames(bool use);
static bool useDisplayNames();
// A name object is valid if not temporary and not yet expired (default is expiration not checked)
bool isValidName(F64 max_unrefreshed = 0.0f) const { return !mIsTemporaryName && (mExpires >= max_unrefreshed); }
// Return true if the name is made up from legacy or temporary data
bool isDisplayNameDefault() const { return mIsDisplayNameDefault; }
// For normal names, returns "James Linden (james.linden)"
// When display names are disabled returns just "James Linden"
std::string getCompleteName() const;
@ -51,11 +68,38 @@ public:
// compatibility with systems like voice and muting
// *TODO: Eliminate this in favor of username only
std::string getLegacyName() const;
// "José Sanchez" or "James Linden", UTF-8 encoded Unicode
// Takes the display name preference into account. This is truly the name that should
// be used for all UI where an avatar name has to be used unless we truly want something else (rare)
std::string getDisplayName() const;
// Returns "James Linden" or "bobsmith123 Resident"
// Used where we explicitely prefer or need a non UTF-8 legacy (ASCII) name
// Also used for backwards compatibility with systems like voice and muting
std::string getUserName() const;
// Returns "james.linden" or the legacy name for very old names
std::string getAccountName() const { return mUsername; }
// Debug print of the object
void dump() const;
// Names can change, so need to keep track of when name was
// last checked.
// Unix time-from-epoch seconds for efficiency
F64 mExpires;
// You can only change your name every N hours, so record
// when the next update is allowed
// Unix time-from-epoch seconds
F64 mNextUpdate;
private:
// "bobsmith123" or "james.linden", US-ASCII only
std::string mUsername;
// "Jose' Sanchez" or "James Linden", UTF-8 encoded Unicode
// "José Sanchez" or "James Linden", UTF-8 encoded Unicode
// Contains data whether or not user has explicitly set
// a display name; may duplicate their username.
std::string mDisplayName;
@ -81,15 +125,9 @@ public:
// shown in UI, but are not serialized.
bool mIsTemporaryName;
// Names can change, so need to keep track of when name was
// last checked.
// Unix time-from-epoch seconds for efficiency
F64 mExpires;
// You can only change your name every N hours, so record
// when the next update is allowed
// Unix time-from-epoch seconds
F64 mNextUpdate;
// Global flag indicating if display name should be used or not
// This will affect the output of the high level "get" methods
static bool sUseDisplayNames;
};
#endif

View File

@ -194,13 +194,6 @@ public:
return mHandle;
}
protected:
typedef LLHandle<T> handle_type_t;
LLHandleProvider()
{
// provided here to enforce T deriving from LLHandleProvider<T>
}
template <typename U>
LLHandle<U> getDerivedHandle(typename boost::enable_if< typename boost::is_convertible<U*, T*> >::type* dummy = 0) const
{
@ -209,6 +202,12 @@ protected:
return downcast_handle;
}
protected:
typedef LLHandle<T> handle_type_t;
LLHandleProvider()
{
// provided here to enforce T deriving from LLHandleProvider<T>
}
private:
mutable LLRootHandle<T> mHandle;

View File

@ -40,7 +40,9 @@ namespace LLInitParam
{
const U8* my_addr = reinterpret_cast<const U8*>(this);
const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block);
mEnclosingBlockOffset = 0x7FFFffff & (U32)(my_addr - block_addr);
U32 enclosing_block_offset = 0x7FFFffff & (U32)(my_addr - block_addr);
mEnclosingBlockOffsetLow = enclosing_block_offset & 0x0000ffff;
mEnclosingBlockOffsetHigh = (enclosing_block_offset & 0x007f0000) >> 16;
}
//
@ -112,6 +114,35 @@ namespace LLInitParam
std::copy(src_block_data.mAllParams.begin(), src_block_data.mAllParams.end(), std::back_inserter(mAllParams));
}
void BlockDescriptor::addParam(const ParamDescriptorPtr in_param, const char* char_name)
{
// create a copy of the param descriptor in mAllParams
// so other data structures can store a pointer to it
mAllParams.push_back(in_param);
ParamDescriptorPtr param(mAllParams.back());
std::string name(char_name);
if ((size_t)param->mParamHandle > mMaxParamOffset)
{
llerrs << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << llendl;
}
if (name.empty())
{
mUnnamedParams.push_back(param);
}
else
{
// don't use insert, since we want to overwrite existing entries
mNamedParams[name] = param;
}
if (param->mValidationFunc)
{
mValidationList.push_back(std::make_pair(param->mParamHandle, param->mValidationFunc));
}
}
BlockDescriptor::BlockDescriptor()
: mMaxParamOffset(0),
mInitializationState(UNINITIALIZED),
@ -150,7 +181,8 @@ namespace LLInitParam
bool BaseBlock::submitValue(Parser::name_stack_t& name_stack, Parser& p, bool silent)
{
if (!deserializeBlock(p, std::make_pair(name_stack.begin(), name_stack.end()), true))
Parser::name_stack_range_t range = std::make_pair(name_stack.begin(), name_stack.end());
if (!deserializeBlock(p, range, true))
{
if (!silent)
{
@ -196,12 +228,7 @@ namespace LLInitParam
if (serialize_func)
{
const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL;
// each param descriptor remembers its serial number
// so we can inspect the same param under different names
// and see that it has the same number
name_stack.push_back(std::make_pair("", true));
serialize_func(*param, parser, name_stack, diff_param);
name_stack.pop_back();
}
}
@ -295,7 +322,7 @@ namespace LLInitParam
return true;
}
bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool ignored)
bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool ignored)
{
BlockDescriptor& block_data = mostDerivedBlockDescriptor();
bool names_left = name_stack_range.first != name_stack_range.second;
@ -308,15 +335,12 @@ namespace LLInitParam
{
const std::string& top_name = name_stack_range.first->first;
ParamDescriptor::deserialize_func_t deserialize_func = NULL;
Param* paramp = NULL;
BlockDescriptor::param_map_t::iterator found_it = block_data.mNamedParams.find(top_name);
if (found_it != block_data.mNamedParams.end())
{
// find pointer to member parameter from offset table
paramp = getParamFromHandle(found_it->second->mParamHandle);
deserialize_func = found_it->second->mDeserializeFunc;
Param* paramp = getParamFromHandle(found_it->second->mParamHandle);
ParamDescriptor::deserialize_func_t deserialize_func = found_it->second->mDeserializeFunc;
Parser::name_stack_range_t new_name_stack(name_stack_range.first, name_stack_range.second);
++new_name_stack.first;
@ -358,36 +382,6 @@ namespace LLInitParam
return false;
}
//static
void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptorPtr in_param, const char* char_name)
{
// create a copy of the param descriptor in mAllParams
// so other data structures can store a pointer to it
block_data.mAllParams.push_back(in_param);
ParamDescriptorPtr param(block_data.mAllParams.back());
std::string name(char_name);
if ((size_t)param->mParamHandle > block_data.mMaxParamOffset)
{
llerrs << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << llendl;
}
if (name.empty())
{
block_data.mUnnamedParams.push_back(param);
}
else
{
// don't use insert, since we want to overwrite existing entries
block_data.mNamedParams[name] = param;
}
if (param->mValidationFunc)
{
block_data.mValidationList.push_back(std::make_pair(param->mParamHandle, param->mValidationFunc));
}
}
void BaseBlock::addSynonym(Param& param, const std::string& synonym)
{
BlockDescriptor& block_data = mostDerivedBlockDescriptor();
@ -460,7 +454,7 @@ namespace LLInitParam
if (merge_func)
{
Param* paramp = getParamFromHandle((*it)->mParamHandle);
llassert(paramp->mEnclosingBlockOffset == (*it)->mParamHandle);
llassert(paramp->getEnclosingBlockOffset() == (*it)->mParamHandle);
some_param_changed |= merge_func(*paramp, *other_paramp, overwrite);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -43,7 +43,7 @@
* semantics: one instance per process, rather than one instance per module as
* sometimes happens with data simply declared static.
*/
class LL_COMMON_API LLInstanceTrackerBase : public boost::noncopyable
class LL_COMMON_API LLInstanceTrackerBase
{
protected:
/// Get a process-unique void* pointer slot for the specified type_info
@ -210,6 +210,9 @@ protected:
virtual const KEY& getKey() const { return mInstanceKey; }
private:
LLInstanceTracker( const LLInstanceTracker& );
const LLInstanceTracker& operator=( const LLInstanceTracker& );
void add_(KEY key)
{
mInstanceKey = key;

View File

@ -27,6 +27,7 @@
#define LLREFCOUNT_H
#include <boost/noncopyable.hpp>
#include <boost/intrusive_ptr.hpp>
#define LL_REF_COUNT_DEBUG 0
#if LL_REF_COUNT_DEBUG
@ -86,4 +87,22 @@ private:
#endif
};
/**
* intrusive pointer support
* this allows you to use boost::intrusive_ptr with any LLRefCount-derived type
*/
namespace boost
{
inline void intrusive_ptr_add_ref(LLRefCount* p)
{
p->ref();
}
inline void intrusive_ptr_release(LLRefCount* p)
{
p->unref();
}
};
#endif

View File

@ -307,6 +307,10 @@ public:
virtual ~StaticRegistrar() {}
StaticRegistrar(ref_const_key_t key, ref_const_value_t value)
{
if (singleton_t::instance().exists(key))
{
llerrs << "Duplicate registry entry under key \"" << key << "\"" << llendl;
}
singleton_t::instance().mStaticScope->add(key, value);
}
};

View File

@ -223,10 +223,14 @@ LLSD& LLParamSDParserUtilities::getSDWriteNode(LLSD& input, LLInitParam::Parser:
{
bool new_traversal = it->second;
LLSD* child_sd = it->first.empty() ? sd_to_write : &(*sd_to_write)[it->first];
if (child_sd->isArray())
LLSD* child_sd;
if (it->first.empty())
{
child_sd = sd_to_write;
if (child_sd->isUndefined())
{
*child_sd = LLSD::emptyArray();
}
if (new_traversal)
{
// write to new element at end
@ -240,22 +244,7 @@ LLSD& LLParamSDParserUtilities::getSDWriteNode(LLSD& input, LLInitParam::Parser:
}
else
{
if (new_traversal
&& child_sd->isDefined()
&& !child_sd->isArray())
{
// copy child contents into first element of an array
LLSD new_array = LLSD::emptyArray();
new_array.append(*child_sd);
// assign array to slot that previously held the single value
*child_sd = new_array;
// return next element in that array
sd_to_write = &((*child_sd)[1]);
}
else
{
sd_to_write = child_sd;
}
sd_to_write = &(*sd_to_write)[it->first];
}
it->second = false;
}
@ -283,8 +272,9 @@ void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd, LLI
it != sd.endArray();
++it)
{
stack.back().second = true;
stack.push_back(make_pair(std::string(), true));
readSDValues(cb, *it, stack);
stack.pop_back();
}
}
else if (sd.isUndefined())
@ -313,8 +303,14 @@ namespace LLInitParam
{
// LLSD specialization
// block param interface
bool ParamValue<LLSD, TypeValues<LLSD>, false>::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name)
bool ParamValue<LLSD, NOT_BLOCK>::deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack, bool new_name)
{
if (name_stack.first == name_stack.second
&& p.readValue<LLSD>(mValue))
{
return true;
}
LLSD& sd = LLParamSDParserUtilities::getSDWriteNode(mValue, name_stack);
LLSD::String string;
@ -328,15 +324,18 @@ namespace LLInitParam
}
//static
void ParamValue<LLSD, TypeValues<LLSD>, false>::serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack)
void ParamValue<LLSD, NOT_BLOCK>::serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack)
{
p.writeValue<LLSD::String>(sd.asString(), name_stack);
}
void ParamValue<LLSD, TypeValues<LLSD>, false>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const
void ParamValue<LLSD, NOT_BLOCK>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const
{
// read from LLSD value and serialize out to parser (which could be LLSD, XUI, etc)
Parser::name_stack_t stack;
LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, stack);
// attempt to write LLSD out directly
if (!p.writeValue<LLSD>(mValue, name_stack))
{
// otherwise read from LLSD value and serialize out to parser (which could be LLSD, XUI, etc)
LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, name_stack);
}
}
}

View File

@ -30,6 +30,7 @@
#include "llapp.h"
#include "llapr.h"
#include "apr_thread_cond.h"
#include "boost/intrusive_ptr.hpp"
class LLThread;
class LLMutex;
@ -284,6 +285,22 @@ private:
S32 mRef;
};
/**
* intrusive pointer support for LLThreadSafeRefCount
* this allows you to use boost::intrusive_ptr with any LLThreadSafeRefCount-derived type
*/
namespace boost
{
inline void intrusive_ptr_add_ref(LLThreadSafeRefCount* p)
{
p->ref();
}
inline void intrusive_ptr_release(LLThreadSafeRefCount* p)
{
p->unref();
}
};
//============================================================================
// Simple responder for self destructing callbacks

View File

@ -28,8 +28,8 @@
#define LL_LLVERSIONVIEWER_H
const S32 LL_VERSION_MAJOR = 3;
const S32 LL_VERSION_MINOR = 4;
const S32 LL_VERSION_PATCH = 5;
const S32 LL_VERSION_MINOR = 5;
const S32 LL_VERSION_PATCH = 0;
const S32 LL_VERSION_BUILD = 264760;
const char * const LL_CHANNEL = "Second Life Developer";

View File

@ -51,7 +51,8 @@ enum EDragAndDropType
DAD_LINK = 14,
DAD_MESH = 15,
DAD_WIDGET = 16,
DAD_COUNT = 17, // number of types in this enum
DAD_PERSON = 17,
DAD_COUNT = 18, // number of types in this enum
};
// Reasons for drags to be denied.

View File

@ -580,8 +580,13 @@ size_t HttpOpRequest::readCallback(void * data, size_t size, size_t nmemb, void
const size_t body_size(op->mReqBody->size());
if (body_size <= op->mCurlBodyPos)
{
LL_WARNS("HttpCore") << "Request body position beyond body size. Aborting request."
<< LL_ENDL;
if (body_size < op->mCurlBodyPos)
{
// Warn but continue if the read position moves beyond end-of-body
// for some reason.
LL_WARNS("HttpCore") << "Request body position beyond body size. Truncating request body."
<< LL_ENDL;
}
return 0;
}

View File

@ -75,13 +75,15 @@ LLInventoryObject::LLInventoryObject(const LLUUID& uuid,
mUUID(uuid),
mParentUUID(parent_uuid),
mType(type),
mName(name)
mName(name),
mCreationDate(0)
{
correctInventoryName(mName);
}
LLInventoryObject::LLInventoryObject() :
mType(LLAssetType::AT_NONE)
mType(LLAssetType::AT_NONE),
mCreationDate(0)
{
}
@ -275,6 +277,18 @@ void LLInventoryObject::correctInventoryName(std::string& name)
LLStringUtil::truncate(name, DB_INV_ITEM_NAME_STR_LEN);
}
time_t LLInventoryObject::getCreationDate() const
{
return mCreationDate;
}
void LLInventoryObject::setCreationDate(time_t creation_date_utc)
{
mCreationDate = creation_date_utc;
}
///----------------------------------------------------------------------------
/// Class LLInventoryItem
@ -297,9 +311,10 @@ LLInventoryItem::LLInventoryItem(const LLUUID& uuid,
mDescription(desc),
mSaleInfo(sale_info),
mInventoryType(inv_type),
mFlags(flags),
mCreationDate(creation_date_utc)
mFlags(flags)
{
mCreationDate = creation_date_utc;
LLStringUtil::replaceNonstandardASCII(mDescription, ' ');
LLStringUtil::replaceChar(mDescription, '|', ' ');
mPermissions.initMasks(inv_type);
@ -312,9 +327,9 @@ LLInventoryItem::LLInventoryItem() :
mDescription(),
mSaleInfo(),
mInventoryType(LLInventoryType::IT_NONE),
mFlags(0),
mCreationDate(0)
mFlags(0)
{
mCreationDate = 0;
}
LLInventoryItem::LLInventoryItem(const LLInventoryItem* other) :
@ -384,11 +399,6 @@ const std::string& LLInventoryItem::getActualDescription() const
return mDescription;
}
time_t LLInventoryItem::getCreationDate() const
{
return mCreationDate;
}
U32 LLInventoryItem::getCRC32() const
{
// *FIX: Not a real crc - more of a checksum.
@ -445,11 +455,6 @@ void LLInventoryItem::setFlags(U32 flags)
mFlags = flags;
}
void LLInventoryItem::setCreationDate(time_t creation_date_utc)
{
mCreationDate = creation_date_utc;
}
// Currently only used in the Viewer to handle calling cards
// where the creator is actually used to store the target.
void LLInventoryItem::setCreator(const LLUUID& creator)
@ -511,6 +516,12 @@ U32 LLInventoryItem::getFlags() const
return mFlags;
}
time_t LLInventoryItem::getCreationDate() const
{
return mCreationDate;
}
// virtual
void LLInventoryItem::packMessage(LLMessageSystem* msg) const
{

View File

@ -73,6 +73,7 @@ public:
virtual LLAssetType::EType getType() const;
LLAssetType::EType getActualType() const; // bypasses indirection for linked items
BOOL getIsLinkType() const;
virtual time_t getCreationDate() const;
//--------------------------------------------------------------------
// Mutators
@ -83,6 +84,7 @@ public:
virtual void rename(const std::string& new_name);
void setParent(const LLUUID& new_parent);
void setType(LLAssetType::EType type);
virtual void setCreationDate(time_t creation_date_utc); // only stored for items
private:
// in place correction for inventory name string
@ -111,6 +113,7 @@ protected:
LLUUID mParentUUID; // Parent category. Root categories have LLUUID::NULL.
LLAssetType::EType mType;
std::string mName;
time_t mCreationDate; // seconds from 1/1/1970, UTC
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -176,7 +179,6 @@ public:
void setPermissions(const LLPermissions& perm);
void setInventoryType(LLInventoryType::EType inv_type);
void setFlags(U32 flags);
void setCreationDate(time_t creation_date_utc);
void setCreator(const LLUUID& creator); // only used for calling cards
// Check for changes in permissions masks and sale info
@ -222,7 +224,6 @@ protected:
LLSaleInfo mSaleInfo;
LLInventoryType::EType mInventoryType;
U32 mFlags;
time_t mCreationDate; // seconds from 1/1/1970, UTC
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -85,6 +85,7 @@ LLInventoryDictionary::LLInventoryDictionary()
addEntry(LLInventoryType::IT_GESTURE, new InventoryEntry("gesture", "gesture", 1, LLAssetType::AT_GESTURE));
addEntry(LLInventoryType::IT_MESH, new InventoryEntry("mesh", "mesh", 1, LLAssetType::AT_MESH));
addEntry(LLInventoryType::IT_WIDGET, new InventoryEntry("widget", "widget", 1, LLAssetType::AT_WIDGET));
addEntry(LLInventoryType::IT_PERSON, new InventoryEntry("person", "person", 1, LLAssetType::AT_PERSON));
}
@ -140,7 +141,7 @@ DEFAULT_ASSET_FOR_INV_TYPE[LLAssetType::AT_COUNT] =
LLInventoryType::IT_NONE, // 42 AT_NONE
LLInventoryType::IT_NONE, // 43 AT_NONE
LLInventoryType::IT_NONE, // 44 AT_NONE
LLInventoryType::IT_NONE, // 45 AT_NONE
LLInventoryType::IT_PERSON, // 45 AT_PERSON
LLInventoryType::IT_NONE, // 46 AT_NONE
LLInventoryType::IT_NONE, // 47 AT_NONE
LLInventoryType::IT_NONE, // 48 AT_NONE

View File

@ -63,7 +63,8 @@ public:
IT_GESTURE = 20,
IT_MESH = 22,
IT_WIDGET = 23,
IT_COUNT = 24,
IT_PERSON = 24,
IT_COUNT = 25,
IT_NONE = -1
};

View File

@ -43,26 +43,26 @@ namespace LLAvatarNameCache
{
use_display_name_signal_t mUseDisplayNamesSignal;
// Manual override for display names - can disable even if the region
// supports it.
bool sUseDisplayNames = true;
// Cache starts in a paused state until we can determine if the
// current region supports display names.
bool sRunning = false;
// Use the People API (modern) for fetching name if true. Use the old legacy protocol if false.
// For testing, there's a UsePeopleAPI setting that can be flipped (must restart viewer).
bool sUsePeopleAPI = true;
// Base lookup URL for name service.
// On simulator, loaded from indra.xml
// On viewer, usually a simulator capability (at People API team's request)
// Includes the trailing slash, like "http://pdp60.lindenlab.com:8000/agents/"
std::string sNameLookupURL;
// accumulated agent IDs for next query against service
// Accumulated agent IDs for next query against service
typedef std::set<LLUUID> ask_queue_t;
ask_queue_t sAskQueue;
// agent IDs that have been requested, but with no reply
// maps agent ID to frame time request was made
// Agent IDs that have been requested, but with no reply.
// Maps agent ID to frame time request was made.
typedef std::map<LLUUID, F64> pending_queue_t;
pending_queue_t sPendingQueue;
@ -73,21 +73,21 @@ namespace LLAvatarNameCache
typedef std::map<LLUUID, callback_signal_t*> signal_map_t;
signal_map_t sSignalMap;
// names we know about
// The cache at last, i.e. avatar names we know about.
typedef std::map<LLUUID, LLAvatarName> cache_t;
cache_t sCache;
// Send bulk lookup requests a few times a second at most
// only need per-frame timing resolution
// Send bulk lookup requests a few times a second at most.
// Only need per-frame timing resolution.
LLFrameTimer sRequestTimer;
/// Maximum time an unrefreshed cache entry is allowed
// Maximum time an unrefreshed cache entry is allowed.
const F64 MAX_UNREFRESHED_TIME = 20.0 * 60.0;
/// Time when unrefreshed cached names were checked last
// Time when unrefreshed cached names were checked last.
static F64 sLastExpireCheck;
/// Time-to-live for a temp cache entry.
// Time-to-live for a temp cache entry.
const F64 TEMP_CACHE_ENTRY_LIFETIME = 60.0;
//-----------------------------------------------------------------------
@ -95,26 +95,21 @@ namespace LLAvatarNameCache
//-----------------------------------------------------------------------
// Handle name response off network.
// Optionally skip adding to cache, used when this is a fallback to the
// legacy name system.
void processName(const LLUUID& agent_id,
const LLAvatarName& av_name,
bool add_to_cache);
const LLAvatarName& av_name);
void requestNamesViaCapability();
// Legacy name system callback
// Legacy name system callbacks
void legacyNameCallback(const LLUUID& agent_id,
const std::string& full_name,
bool is_group
);
bool is_group);
void legacyNameFetch(const LLUUID& agent_id,
const std::string& full_name,
bool is_group);
void requestNamesViaLegacy();
// Fill in an LLAvatarName with the legacy name data
void buildLegacyName(const std::string& full_name,
LLAvatarName* av_name);
// Do a single callback to a given slot
void fireSignal(const LLUUID& agent_id,
const callback_slot_t& slot,
@ -209,20 +204,11 @@ public:
// Use expiration time from header
av_name.mExpires = expires;
// Some avatars don't have explicit display names set
if (av_name.mDisplayName.empty())
{
av_name.mDisplayName = av_name.mUsername;
}
LL_DEBUGS("AvNameCache") << "LLAvatarNameResponder::result for " << agent_id << " "
<< "user '" << av_name.mUsername << "' "
<< "display '" << av_name.mDisplayName << "' "
<< "expires in " << expires - now << " seconds"
<< LL_ENDL;
LL_DEBUGS("AvNameCache") << "LLAvatarNameResponder::result for " << agent_id << LL_ENDL;
av_name.dump();
// cache it and fire signals
LLAvatarNameCache::processName(agent_id, av_name, true);
LLAvatarNameCache::processName(agent_id, av_name);
}
// Same logic as error response case
@ -279,40 +265,34 @@ void LLAvatarNameCache::handleAgentError(const LLUUID& agent_id)
LL_WARNS("AvNameCache") << "LLAvatarNameCache get legacy for agent "
<< agent_id << LL_ENDL;
gCacheName->get(agent_id, false, // legacy compatibility
boost::bind(&LLAvatarNameCache::legacyNameCallback,
_1, _2, _3));
boost::bind(&LLAvatarNameCache::legacyNameFetch, _1, _2, _3));
}
else
{
// we have a chached (but probably expired) entry - since that would have
// we have a cached (but probably expired) entry - since that would have
// been returned by the get method, there is no need to signal anyone
// Clear this agent from the pending list
LLAvatarNameCache::sPendingQueue.erase(agent_id);
LLAvatarName& av_name = existing->second;
LL_DEBUGS("AvNameCache") << "LLAvatarNameCache use cache for agent "
<< agent_id
<< "user '" << av_name.mUsername << "' "
<< "display '" << av_name.mDisplayName << "' "
<< "expires in " << av_name.mExpires - LLFrameTimer::getTotalSeconds() << " seconds"
<< LL_ENDL;
av_name.mExpires = LLFrameTimer::getTotalSeconds() + TEMP_CACHE_ENTRY_LIFETIME; // reset expiry time so we don't constantly rerequest.
LL_DEBUGS("AvNameCache") << "LLAvatarNameCache use cache for agent " << agent_id << LL_ENDL;
av_name.dump();
// Reset expiry time so we don't constantly rerequest.
av_name.setExpires(TEMP_CACHE_ENTRY_LIFETIME);
}
}
void LLAvatarNameCache::processName(const LLUUID& agent_id,
const LLAvatarName& av_name,
bool add_to_cache)
void LLAvatarNameCache::processName(const LLUUID& agent_id, const LLAvatarName& av_name)
{
if (add_to_cache)
{
sCache[agent_id] = av_name;
}
// Add to the cache
sCache[agent_id] = av_name;
// Suppress request from the queue
sPendingQueue.erase(agent_id);
// signal everyone waiting on this name
// Signal everyone waiting on this name
signal_map_t::iterator sig_it = sSignalMap.find(agent_id);
if (sig_it != sSignalMap.end())
{
@ -389,22 +369,33 @@ void LLAvatarNameCache::legacyNameCallback(const LLUUID& agent_id,
const std::string& full_name,
bool is_group)
{
// Construct a dummy record for this name. By convention, SLID is blank
// Never expires, but not written to disk, so lasts until end of session.
LLAvatarName av_name;
LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::legacyNameCallback "
<< "agent " << agent_id << " "
<< "full name '" << full_name << "'"
<< ( is_group ? " [group]" : "" )
<< LL_ENDL;
buildLegacyName(full_name, &av_name);
// Put the received data in the cache
legacyNameFetch(agent_id, full_name, is_group);
// Retrieve the name and set it to never (or almost never...) expire: when we are using the legacy
// protocol, we do not get an expiration date for each name and there's no reason to ask the
// data again and again so we set the expiration time to the largest value admissible.
std::map<LLUUID,LLAvatarName>::iterator av_record = sCache.find(agent_id);
LLAvatarName& av_name = av_record->second;
av_name.setExpires(MAX_UNREFRESHED_TIME);
}
// Add to cache, because if we don't we'll keep rerequesting the
// same record forever. buildLegacyName should always guarantee
// that these records expire reasonably soon
// (in TEMP_CACHE_ENTRY_LIFETIME seconds), so if the failure was due
// to something temporary we will eventually request and get the right data.
processName(agent_id, av_name, true);
void LLAvatarNameCache::legacyNameFetch(const LLUUID& agent_id,
const std::string& full_name,
bool is_group)
{
LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::legacyNameFetch "
<< "agent " << agent_id << " "
<< "full name '" << full_name << "'"
<< ( is_group ? " [group]" : "" )
<< LL_ENDL;
// Construct an av_name record from this name.
LLAvatarName av_name;
av_name.fromString(full_name);
// Add to cache: we're still using the new cache even if we're using the old (legacy) protocol.
processName(agent_id, av_name);
}
void LLAvatarNameCache::requestNamesViaLegacy()
@ -426,18 +417,19 @@ void LLAvatarNameCache::requestNamesViaLegacy()
LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::requestNamesViaLegacy agent " << agent_id << LL_ENDL;
gCacheName->get(agent_id, false, // legacy compatibility
boost::bind(&LLAvatarNameCache::legacyNameCallback,
_1, _2, _3));
boost::bind(&LLAvatarNameCache::legacyNameCallback, _1, _2, _3));
}
}
void LLAvatarNameCache::initClass(bool running)
void LLAvatarNameCache::initClass(bool running, bool usePeopleAPI)
{
sRunning = running;
sUsePeopleAPI = usePeopleAPI;
}
void LLAvatarNameCache::cleanupClass()
{
sCache.clear();
}
void LLAvatarNameCache::importFile(std::istream& istr)
@ -478,7 +470,7 @@ void LLAvatarNameCache::exportFile(std::ostream& ostr)
const LLUUID& agent_id = it->first;
const LLAvatarName& av_name = it->second;
// Do not write temporary or expired entries to the stored cache
if (!av_name.mIsTemporaryName && av_name.mExpires >= max_unrefreshed)
if (av_name.isValidName(max_unrefreshed))
{
// key must be a string
agents[agent_id.asString()] = av_name.asLLSD();
@ -499,6 +491,11 @@ bool LLAvatarNameCache::hasNameLookupURL()
return !sNameLookupURL.empty();
}
bool LLAvatarNameCache::usePeopleAPI()
{
return hasNameLookupURL() && sUsePeopleAPI;
}
void LLAvatarNameCache::idle()
{
// By convention, start running at first idle() call
@ -515,13 +512,12 @@ void LLAvatarNameCache::idle()
if (!sAskQueue.empty())
{
if (useDisplayNames())
if (usePeopleAPI())
{
requestNamesViaCapability();
}
else
{
// ...fall back to legacy name cache system
requestNamesViaLegacy();
}
}
@ -566,7 +562,7 @@ void LLAvatarNameCache::eraseUnrefreshed()
if (av_name.mExpires < max_unrefreshed)
{
LL_DEBUGS("AvNameCache") << it->first
<< " user '" << av_name.mUsername << "' "
<< " user '" << av_name.getAccountName() << "' "
<< "expired " << now - av_name.mExpires << " secs ago"
<< LL_ENDL;
sCache.erase(it++);
@ -580,20 +576,6 @@ void LLAvatarNameCache::eraseUnrefreshed()
}
}
void LLAvatarNameCache::buildLegacyName(const std::string& full_name,
LLAvatarName* av_name)
{
llassert(av_name);
av_name->mUsername = "";
av_name->mDisplayName = full_name;
av_name->mIsDisplayNameDefault = true;
av_name->mIsTemporaryName = true;
av_name->mExpires = LLFrameTimer::getTotalSeconds() + TEMP_CACHE_ENTRY_LIFETIME;
LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::buildLegacyName "
<< full_name
<< LL_ENDL;
}
// fills in av_name if it has it in the cache, even if expired (can check expiry time)
// returns bool specifying if av_name was filled, false otherwise
bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name)
@ -601,38 +583,24 @@ bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name)
if (sRunning)
{
// ...only do immediate lookups when cache is running
if (useDisplayNames())
std::map<LLUUID,LLAvatarName>::iterator it = sCache.find(agent_id);
if (it != sCache.end())
{
// ...use display names cache
std::map<LLUUID,LLAvatarName>::iterator it = sCache.find(agent_id);
if (it != sCache.end())
{
*av_name = it->second;
*av_name = it->second;
// re-request name if entry is expired
if (av_name->mExpires < LLFrameTimer::getTotalSeconds())
{
if (!isRequestPending(agent_id))
{
LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::get "
<< "refresh agent " << agent_id
<< LL_ENDL;
sAskQueue.insert(agent_id);
}
}
return true;
}
}
else
{
// ...use legacy names cache
std::string full_name;
if (gCacheName->getFullName(agent_id, full_name))
// re-request name if entry is expired
if (av_name->mExpires < LLFrameTimer::getTotalSeconds())
{
buildLegacyName(full_name, av_name);
return true;
if (!isRequestPending(agent_id))
{
LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::get "
<< "refresh agent " << agent_id
<< LL_ENDL;
sAskQueue.insert(agent_id);
}
}
return true;
}
}
@ -663,30 +631,14 @@ LLAvatarNameCache::callback_connection_t LLAvatarNameCache::get(const LLUUID& ag
if (sRunning)
{
// ...only do immediate lookups when cache is running
if (useDisplayNames())
std::map<LLUUID,LLAvatarName>::iterator it = sCache.find(agent_id);
if (it != sCache.end())
{
// ...use new cache
std::map<LLUUID,LLAvatarName>::iterator it = sCache.find(agent_id);
if (it != sCache.end())
const LLAvatarName& av_name = it->second;
if (av_name.mExpires > LLFrameTimer::getTotalSeconds())
{
const LLAvatarName& av_name = it->second;
if (av_name.mExpires > LLFrameTimer::getTotalSeconds())
{
// ...name already exists in cache, fire callback now
fireSignal(agent_id, slot, av_name);
return connection;
}
}
}
else
{
// ...use old name system
std::string full_name;
if (gCacheName->getFullName(agent_id, full_name))
{
LLAvatarName av_name;
buildLegacyName(full_name, &av_name);
// ...name already exists in cache, fire callback now
fireSignal(agent_id, slot, av_name);
return connection;
}
@ -721,22 +673,13 @@ LLAvatarNameCache::callback_connection_t LLAvatarNameCache::get(const LLUUID& ag
void LLAvatarNameCache::setUseDisplayNames(bool use)
{
if (use != sUseDisplayNames)
if (use != LLAvatarName::useDisplayNames())
{
sUseDisplayNames = use;
// flush our cache
sCache.clear();
LLAvatarName::setUseDisplayNames(use);
mUseDisplayNamesSignal();
}
}
bool LLAvatarNameCache::useDisplayNames()
{
// Must be both manually set on and able to look up names.
return sUseDisplayNames && !sNameLookupURL.empty();
}
void LLAvatarNameCache::erase(const LLUUID& agent_id)
{
sCache.erase(agent_id);

View File

@ -37,33 +37,33 @@ class LLUUID;
namespace LLAvatarNameCache
{
typedef boost::signals2::signal<void (void)> use_display_name_signal_t;
// Until the cache is set running, immediate lookups will fail and
// async lookups will be queued. This allows us to block requests
// until we know if the first region supports display names.
void initClass(bool running);
void initClass(bool running, bool usePeopleAPI);
void cleanupClass();
// Import/export the name cache to file.
void importFile(std::istream& istr);
void exportFile(std::ostream& ostr);
// On the viewer, usually a simulator capabilitity
// If empty, name cache will fall back to using legacy name
// lookup system
// On the viewer, usually a simulator capabilitity.
// If empty, name cache will fall back to using legacy name lookup system.
void setNameLookupURL(const std::string& name_lookup_url);
// Do we have a valid lookup URL, hence are we trying to use the
// new display name lookup system?
// Do we have a valid lookup URL, i.e. are we trying to use the
// more recent display name lookup system?
bool hasNameLookupURL();
bool usePeopleAPI();
// Periodically makes a batch request for display names not already in
// cache. Call once per frame.
// cache. Called once per frame.
void idle();
// If name is in cache, returns true and fills in provided LLAvatarName
// otherwise returns false
// otherwise returns false.
bool get(const LLUUID& agent_id, LLAvatarName *av_name);
// Callback types for get() below
@ -73,21 +73,19 @@ namespace LLAvatarNameCache
typedef callback_signal_t::slot_type callback_slot_t;
typedef boost::signals2::connection callback_connection_t;
// Fetches name information and calls callback.
// If name information is in cache, callback will be called immediately.
// Fetches name information and calls callbacks.
// If name information is in cache, callbacks will be called immediately.
callback_connection_t get(const LLUUID& agent_id, callback_slot_t slot);
// Allow display names to be explicitly disabled for testing.
// Set display name: flips the switch and triggers the callbacks.
void setUseDisplayNames(bool use);
bool useDisplayNames();
void insert(const LLUUID& agent_id, const LLAvatarName& av_name);
void erase(const LLUUID& agent_id);
/// Provide some fallback for agents that return errors
/// Provide some fallback for agents that return errors.
void handleAgentError(const LLUUID& agent_id);
void insert(const LLUUID& agent_id, const LLAvatarName& av_name);
// Compute name expiration time from HTTP Cache-Control header,
// or return default value, in seconds from epoch.
F64 nameExpirationFromHeaders(LLSD headers);

View File

@ -525,6 +525,7 @@ std::string LLCacheName::cleanFullName(const std::string& full_name)
}
//static
// Transform hard-coded name provided by server to a more legible username
std::string LLCacheName::buildUsername(const std::string& full_name)
{
// rare, but handle hard-coded error names returned from server
@ -550,8 +551,9 @@ std::string LLCacheName::buildUsername(const std::string& full_name)
return username;
}
// if the input wasn't a correctly formatted legacy name just return it unchanged
return full_name;
// if the input wasn't a correctly formatted legacy name, just return it
// cleaned up from a potential terminal "Resident"
return cleanFullName(full_name);
}
//static

View File

@ -40,7 +40,7 @@ typedef boost::signals2::signal<void (const LLUUID& id,
bool is_group)> LLCacheNameSignal;
typedef LLCacheNameSignal::slot_type LLCacheNameCallback;
// Old callback with user data for compatability
// Old callback with user data for compatibility
typedef void (*old_callback_t)(const LLUUID&, const std::string&, bool, void*);
// Here's the theory:

View File

@ -156,18 +156,6 @@ const S32 DB_USER_SKILLS_BUF_SIZE = 255;
const S32 DB_NV_NAME_STR_LEN = 128;
const S32 DB_NV_NAME_BUF_SIZE = 129;
// votes.vote_text varchar(254)
const S32 DB_VOTE_TEXT_STR_LEN = 254;
const S32 DB_VOTE_TEXT_BUF_SIZE = 255;
// vpte type text varchar(9)
const S32 DB_VOTE_TYPE_STR_LEN = 9;
const S32 DB_VOTE_TYPE_BUF_SIZE = 10;
// vote result text
const S32 DB_VOTE_RESULT_BUF_LEN = 8;
const S32 DB_VOTE_RESULT_BUF_SIZE = 9;
// user_start_location.location_name varchar(254)
const S32 DB_START_LOCATION_STR_LEN = 254;
const S32 DB_START_LOCATION_BUF_SIZE = 255;

View File

@ -43,14 +43,6 @@
const U8 IM_ONLINE = 0;
const U8 IM_OFFLINE = 1;
const S32 VOTE_YES = 1;
const S32 VOTE_NO = 0;
const S32 VOTE_ABSTAIN = -1;
const S32 VOTE_MAJORITY = 0;
const S32 VOTE_SUPER_MAJORITY = 1;
const S32 VOTE_UNANIMOUS = 2;
const char EMPTY_BINARY_BUCKET[] = "";
const S32 EMPTY_BINARY_BUCKET_SIZE = 1;
const U32 NO_TIMESTAMP = 0;
@ -69,7 +61,6 @@ LLIMInfo::LLIMInfo() :
mViewerThinksToIsOnline(false),
mIMType(IM_NOTHING_SPECIAL),
mTimeStamp(0),
mSource(IM_FROM_SIM),
mTTL(IM_TTL)
{
}
@ -88,7 +79,6 @@ LLIMInfo::LLIMInfo(
LLSD data,
U8 offline,
U32 timestamp,
EIMSource source,
S32 ttl) :
mFromID(from_id),
mFromGroup(from_group),
@ -104,14 +94,12 @@ LLIMInfo::LLIMInfo(
mName(name),
mMessage(message),
mData(data),
mSource(source),
mTTL(ttl)
{
}
LLIMInfo::LLIMInfo(LLMessageSystem* msg, EIMSource source, S32 ttl) :
LLIMInfo::LLIMInfo(LLMessageSystem* msg, S32 ttl) :
mViewerThinksToIsOnline(false),
mSource(source),
mTTL(ttl)
{
unpackMessageBlock(msg);
@ -326,7 +314,6 @@ LLSD im_info_to_llsd(LLPointer<LLIMInfo> im_info)
param_message["region_id"] = im_info->mRegionID;
param_message["position"] = ll_sd_from_vector3(im_info->mPosition);
param_message["data"] = im_info->mData;
param_message["source"]= im_info->mSource;
param_message["ttl"] = im_info->mTTL;
LLSD param_agent;
@ -359,7 +346,6 @@ LLPointer<LLIMInfo> llsd_to_im_info(const LLSD& im_info_sd)
param_message["data"],
(U8) param_message["offline"].asInteger(),
(U32) param_message["timestamp"].asInteger(),
(EIMSource)param_message["source"].asInteger(),
param_message["ttl"].asInteger());
return im_info;
@ -381,7 +367,6 @@ LLPointer<LLIMInfo> LLIMInfo::clone()
mData,
mOffline,
mTimeStamp,
mSource,
mTTL);
}

View File

@ -115,8 +115,8 @@ enum EInstantMessage
// viewer, since you can't IM an object yet.
IM_FROM_TASK = 19,
// sent an IM to a busy user, this is the auto response
IM_BUSY_AUTO_RESPONSE = 20,
// sent an IM to a do not disturb user, this is the auto response
IM_DO_NOT_DISTURB_AUTO_RESPONSE = 20,
// Shows the message in the console and chat history
IM_CONSOLE_AND_CHAT_HISTORY = 21,
@ -164,57 +164,9 @@ enum EInstantMessage
};
// Hooks for quickly hacking in experimental admin debug messages
// without needing to recompile the viewer
// *NOTE: This functionality has been moved to be a string based
// operation so that we don't even have to do a full recompile. This
// enumeration will be phased out soon.
enum EGodlikeRequest
{
GOD_WANTS_NOTHING,
// for requesting physics information about an object
GOD_WANTS_PHYSICS_INFO,
// two unused requests that can be appropriated for debug
// purposes (no viewer recompile necessary)
GOD_WANTS_FOO,
GOD_WANTS_BAR,
// to dump simulator terrain data to terrain.raw file
GOD_WANTS_TERRAIN_SAVE,
// to load simulator terrain data from terrain.raw file
GOD_WANTS_TERRAIN_LOAD,
GOD_WANTS_TOGGLE_AVATAR_GEOMETRY, // HACK for testing new avatar geom
// real-time telehub operations
GOD_WANTS_TELEHUB_INFO,
GOD_WANTS_CONNECT_TELEHUB,
GOD_WANTS_DELETE_TELEHUB,
GOD_WANTS_ADD_TELEHUB_SPAWNPOINT,
GOD_WANTS_REMOVE_TELEHUB_SPAWNPOINT,
};
enum EIMSource
{
IM_FROM_VIEWER,
IM_FROM_DATASERVER,
IM_FROM_SIM
};
extern const U8 IM_ONLINE;
extern const U8 IM_OFFLINE;
extern const S32 VOTE_YES;
extern const S32 VOTE_NO;
extern const S32 VOTE_ABSTAIN;
extern const S32 VOTE_MAJORITY;
extern const S32 VOTE_SUPER_MAJORITY;
extern const S32 VOTE_UNANIMOUS;
extern const char EMPTY_BINARY_BUCKET[];
extern const S32 EMPTY_BINARY_BUCKET_SIZE;
@ -234,7 +186,6 @@ protected:
public:
LLIMInfo(LLMessageSystem* msg,
EIMSource source = IM_FROM_SIM,
S32 ttl = IM_TTL);
LLIMInfo(
@ -251,7 +202,6 @@ public:
LLSD data,
U8 offline,
U32 timestamp,
EIMSource source,
S32 ttl = IM_TTL);
void packInstantMessage(LLMessageSystem* msg) const;
@ -274,7 +224,6 @@ public:
std::string mMessage;
LLSD mData;
EIMSource mSource;
S32 mTTL;
};

View File

@ -43,13 +43,11 @@ set(llrender_SOURCE_FILES
llimagegl.cpp
llpostprocess.cpp
llrender.cpp
llrender2dutils.cpp
llrendernavprim.cpp
llrendersphere.cpp
llrendertarget.cpp
llshadermgr.cpp
lltexture.cpp
lluiimage.cpp
llvertexbuffer.cpp
)
@ -71,12 +69,10 @@ set(llrender_HEADER_FILES
llimagegl.h
llpostprocess.h
llrender.h
llrender2dutils.h
llrendernavprim.h
llrendersphere.h
llshadermgr.h
lltexture.h
lluiimage.h
llvertexbuffer.h
)

View File

@ -57,8 +57,13 @@
BOOL gDebugSession = FALSE;
BOOL gDebugGL = FALSE;
BOOL gClothRipple = FALSE;
BOOL gHeadlessClient = FALSE;
BOOL gGLActive = FALSE;
static const std::string HEADLESS_VENDOR_STRING("Linden Lab");
static const std::string HEADLESS_RENDERER_STRING("Headless");
static const std::string HEADLESS_VERSION_STRING("1.0");
std::ofstream gFailLog;
#if GL_ARB_debug_output
@ -388,7 +393,7 @@ PFNGLACTIVETEXTUREARBPROC glActiveTextureARB = NULL;
PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTextureARB = NULL;
PFNGLDRAWRANGEELEMENTSPROC glDrawRangeElements = NULL;
#endif // LL_LINUX_NV_GL_HEADERS
#endif // (LL_WINDOWS || LL_LINUX || LL_SOLARIS) && !LL_MESA_HEADLESS
#endif
LLGLManager gGLManager;
@ -592,12 +597,11 @@ bool LLGLManager::initGL()
if (mGLVendor.substr(0,4) == "ATI ")
{
mGLVendorShort = "ATI";
// "mobile" appears to be unused, and this code was causing warnings.
//BOOL mobile = FALSE;
//if (mGLRenderer.find("MOBILITY") != std::string::npos)
//{
// mobile = TRUE;
//}
BOOL mobile = FALSE;
if (mGLRenderer.find("MOBILITY") != std::string::npos)
{
mobile = TRUE;
}
mIsATI = TRUE;
#if LL_WINDOWS && !LL_MESA_HEADLESS
@ -784,9 +788,19 @@ void LLGLManager::setToDebugGPU()
void LLGLManager::getGLInfo(LLSD& info)
{
info["GLInfo"]["GLVendor"] = std::string((const char *)glGetString(GL_VENDOR));
info["GLInfo"]["GLRenderer"] = std::string((const char *)glGetString(GL_RENDERER));
info["GLInfo"]["GLVersion"] = std::string((const char *)glGetString(GL_VERSION));
if (gHeadlessClient)
{
info["GLInfo"]["GLVendor"] = HEADLESS_VENDOR_STRING;
info["GLInfo"]["GLRenderer"] = HEADLESS_RENDERER_STRING;
info["GLInfo"]["GLVersion"] = HEADLESS_VERSION_STRING;
return;
}
else
{
info["GLInfo"]["GLVendor"] = std::string((const char *)glGetString(GL_VENDOR));
info["GLInfo"]["GLRenderer"] = std::string((const char *)glGetString(GL_RENDERER));
info["GLInfo"]["GLVersion"] = std::string((const char *)glGetString(GL_VERSION));
}
#if !LL_MESA_HEADLESS
std::string all_exts = ll_safe_string((const char *)gGLHExts.mSysExts);
@ -803,9 +817,18 @@ std::string LLGLManager::getGLInfoString()
{
std::string info_str;
info_str += std::string("GL_VENDOR ") + ll_safe_string((const char *)glGetString(GL_VENDOR)) + std::string("\n");
info_str += std::string("GL_RENDERER ") + ll_safe_string((const char *)glGetString(GL_RENDERER)) + std::string("\n");
info_str += std::string("GL_VERSION ") + ll_safe_string((const char *)glGetString(GL_VERSION)) + std::string("\n");
if (gHeadlessClient)
{
info_str += std::string("GL_VENDOR ") + HEADLESS_VENDOR_STRING + std::string("\n");
info_str += std::string("GL_RENDERER ") + HEADLESS_RENDERER_STRING + std::string("\n");
info_str += std::string("GL_VERSION ") + HEADLESS_VERSION_STRING + std::string("\n");
}
else
{
info_str += std::string("GL_VENDOR ") + ll_safe_string((const char *)glGetString(GL_VENDOR)) + std::string("\n");
info_str += std::string("GL_RENDERER ") + ll_safe_string((const char *)glGetString(GL_RENDERER)) + std::string("\n");
info_str += std::string("GL_VERSION ") + ll_safe_string((const char *)glGetString(GL_VERSION)) + std::string("\n");
}
#if !LL_MESA_HEADLESS
std::string all_exts= ll_safe_string(((const char *)gGLHExts.mSysExts));
@ -818,9 +841,18 @@ std::string LLGLManager::getGLInfoString()
void LLGLManager::printGLInfoString()
{
LL_INFOS("RenderInit") << "GL_VENDOR: " << ((const char *)glGetString(GL_VENDOR)) << LL_ENDL;
LL_INFOS("RenderInit") << "GL_RENDERER: " << ((const char *)glGetString(GL_RENDERER)) << LL_ENDL;
LL_INFOS("RenderInit") << "GL_VERSION: " << ((const char *)glGetString(GL_VERSION)) << LL_ENDL;
if (gHeadlessClient)
{
LL_INFOS("RenderInit") << "GL_VENDOR: " << HEADLESS_VENDOR_STRING << LL_ENDL;
LL_INFOS("RenderInit") << "GL_RENDERER: " << HEADLESS_RENDERER_STRING << LL_ENDL;
LL_INFOS("RenderInit") << "GL_VERSION: " << HEADLESS_VERSION_STRING << LL_ENDL;
}
else
{
LL_INFOS("RenderInit") << "GL_VENDOR: " << ((const char *)glGetString(GL_VENDOR)) << LL_ENDL;
LL_INFOS("RenderInit") << "GL_RENDERER: " << ((const char *)glGetString(GL_RENDERER)) << LL_ENDL;
LL_INFOS("RenderInit") << "GL_VERSION: " << ((const char *)glGetString(GL_VERSION)) << LL_ENDL;
}
#if !LL_MESA_HEADLESS
std::string all_exts= ll_safe_string(((const char *)gGLHExts.mSysExts));
@ -832,7 +864,14 @@ void LLGLManager::printGLInfoString()
std::string LLGLManager::getRawGLString()
{
std::string gl_string;
gl_string = ll_safe_string((char*)glGetString(GL_VENDOR)) + " " + ll_safe_string((char*)glGetString(GL_RENDERER));
if (gHeadlessClient)
{
gl_string = HEADLESS_VENDOR_STRING + " " + HEADLESS_RENDERER_STRING;
}
else
{
gl_string = ll_safe_string((char*)glGetString(GL_VENDOR)) + " " + ll_safe_string((char*)glGetString(GL_RENDERER));
}
return gl_string;
}
@ -898,7 +937,7 @@ void LLGLManager::initExtensions()
mHasCubeMap = FALSE;
mHasOcclusionQuery = FALSE;
mHasPointParameters = FALSE;
mHasShaderObjects = TRUE;
mHasShaderObjects = FALSE;
mHasVertexShader = FALSE;
mHasFragmentShader = FALSE;
mHasTextureRectangle = FALSE;
@ -1451,7 +1490,8 @@ void assert_glerror()
void clear_glerror()
{
// Create or update texture to be used with this data
glGetError();
GLenum error;
error = glGetError();
}
///////////////////////////////////////////////////////////////
@ -1950,10 +1990,7 @@ LLGLState::LLGLState(LLGLenum state, S32 enabled) :
if (mState)
{
mWasEnabled = sStateMap[state];
if (gDebugGL)
{
llassert(mWasEnabled == glIsEnabled(state));
}
llassert(mWasEnabled == glIsEnabled(state));
setEnabled(enabled);
stop_glerror();
}

View File

@ -457,6 +457,7 @@ void init_glstates();
void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific, std::string* version_string );
extern BOOL gClothRipple;
extern BOOL gHeadlessClient;
extern BOOL gGLActive;
// Deal with changing glext.h definitions for newer SDK versions, specifically

File diff suppressed because it is too large Load Diff

View File

@ -1,164 +0,0 @@
/**
* @file llrender2dutils.h
* @brief GL function declarations for immediate-mode gl drawing.
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* 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;
* version 2.1 of the License only.
*
* 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
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
// All immediate-mode gl drawing should happen here.
#ifndef LL_RENDER2DUTILS_H
#define LL_RENDER2DUTILS_H
#include "llpointer.h" // LLPointer<>
#include "llrect.h"
#include "llglslshader.h"
class LLColor4;
class LLVector3;
class LLVector2;
class LLUIImage;
class LLUUID;
extern const LLColor4 UI_VERTEX_COLOR;
BOOL ui_point_in_rect(S32 x, S32 y, S32 left, S32 top, S32 right, S32 bottom);
void gl_state_for_2d(S32 width, S32 height);
void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2);
void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2, const LLColor4 &color );
void gl_triangle_2d(S32 x1, S32 y1, S32 x2, S32 y2, S32 x3, S32 y3, const LLColor4& color, BOOL filled);
void gl_rect_2d_simple( S32 width, S32 height );
void gl_draw_x(const LLRect& rect, const LLColor4& color);
void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, BOOL filled = TRUE );
void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, BOOL filled = TRUE );
void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, S32 pixel_offset = 0, BOOL filled = TRUE );
void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, S32 pixel_offset = 0, BOOL filled = TRUE );
void gl_rect_2d(const LLRect& rect, BOOL filled = TRUE );
void gl_rect_2d(const LLRect& rect, const LLColor4& color, BOOL filled = TRUE );
void gl_rect_2d_checkerboard(const LLRect& rect, GLfloat alpha = 1.0f);
void gl_drop_shadow(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &start_color, S32 lines);
void gl_circle_2d(F32 x, F32 y, F32 radius, S32 steps, BOOL filled);
void gl_arc_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled, F32 start_angle, F32 end_angle);
void gl_deep_circle( F32 radius, F32 depth );
void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor4& side_color, S32 steps, BOOL render_center );
void gl_corners_2d(S32 left, S32 top, S32 right, S32 bottom, S32 length, F32 max_frac);
void gl_washer_2d(F32 outer_radius, F32 inner_radius, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color);
void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians, F32 end_radians, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color);
void gl_draw_image(S32 x, S32 y, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees,LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), const LLRectf& scale_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase = 0.f );
void gl_rect_2d_simple_tex( S32 width, S32 height );
// segmented rectangles
/*
TL |______TOP_________| TR
/| |\
_/_|__________________|_\_
L| | MIDDLE | |R
_|_|__________________|_|_
\ | BOTTOM | /
BL\|__________________|/ BR
| |
*/
typedef enum e_rounded_edge
{
ROUNDED_RECT_LEFT = 0x1,
ROUNDED_RECT_TOP = 0x2,
ROUNDED_RECT_RIGHT = 0x4,
ROUNDED_RECT_BOTTOM = 0x8,
ROUNDED_RECT_ALL = 0xf
}ERoundedEdge;
void gl_segmented_rect_2d_tex(const S32 left, const S32 top, const S32 right, const S32 bottom, const S32 texture_width, const S32 texture_height, const S32 border_size, const U32 edges = ROUNDED_RECT_ALL);
void gl_segmented_rect_2d_fragment_tex(const S32 left, const S32 top, const S32 right, const S32 bottom, const S32 texture_width, const S32 texture_height, const S32 border_size, const F32 start_fragment, const F32 end_fragment, const U32 edges = ROUNDED_RECT_ALL);
void gl_segmented_rect_3d_tex(const LLVector2& border_scale, const LLVector3& border_width, const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec, U32 edges = ROUNDED_RECT_ALL);
void gl_segmented_rect_3d_tex_top(const LLVector2& border_scale, const LLVector3& border_width, const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec);
inline void gl_rect_2d( const LLRect& rect, BOOL filled )
{
gl_rect_2d( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, filled );
}
inline void gl_rect_2d_offset_local( const LLRect& rect, S32 pixel_offset, BOOL filled)
{
gl_rect_2d_offset_local( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, pixel_offset, filled );
}
class LLImageProviderInterface;
class LLRender2D
{
LOG_CLASS(LLRender2D);
public:
static void initClass(LLImageProviderInterface* image_provider,
const LLVector2* scale_factor);
static void cleanupClass();
static void pushMatrix();
static void popMatrix();
static void loadIdentity();
static void translate(F32 x, F32 y, F32 z = 0.0f);
static void setLineWidth(F32 width);
static void setScaleFactor(const LLVector2& scale_factor);
static LLPointer<LLUIImage> getUIImageByID(const LLUUID& image_id, S32 priority = 0);
static LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority = 0);
static LLVector2 sGLScaleFactor;
private:
static LLImageProviderInterface* sImageProvider;
};
class LLImageProviderInterface
{
protected:
LLImageProviderInterface() {};
virtual ~LLImageProviderInterface() {};
public:
virtual LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority) = 0;
virtual LLPointer<LLUIImage> getUIImageByID(const LLUUID& id, S32 priority) = 0;
virtual void cleanUp() = 0;
};
extern LLGLSLShader gSolidColorProgram;
extern LLGLSLShader gUIProgram;
#endif // LL_RENDER2DUTILS_H

View File

@ -37,6 +37,7 @@ set(llui_SOURCE_FILES
llbadgeholder.cpp
llbadgeowner.cpp
llbutton.cpp
llchatentry.cpp
llcheckboxctrl.cpp
llclipboard.cpp
llcombobox.cpp
@ -50,12 +51,16 @@ set(llui_SOURCE_FILES
lleditmenuhandler.cpp
llf32uictrl.cpp
llfiltereditor.cpp
llflashtimer.cpp
llflatlistview.cpp
llfloater.cpp
llfloaterreg.cpp
llfloaterreglistener.cpp
llflyoutbutton.cpp
llfocusmgr.cpp
llfolderview.cpp
llfolderviewitem.cpp
llfolderviewmodel.cpp
llfunctorregistry.cpp
lliconctrl.cpp
llkeywords.cpp
@ -70,7 +75,6 @@ set(llui_SOURCE_FILES
llmultislider.cpp
llmultisliderctrl.cpp
llnotifications.cpp
llnotificationslistener.cpp
llnotificationsutil.cpp
llpanel.cpp
llprogressbar.cpp
@ -113,6 +117,7 @@ set(llui_SOURCE_FILES
lluicolortable.cpp
lluictrl.cpp
lluictrlfactory.cpp
lluiimage.cpp
lluistring.cpp
llundo.cpp
llurlaction.cpp
@ -138,6 +143,7 @@ set(llui_HEADER_FILES
llbadgeowner.h
llbutton.h
llcallbackmap.h
llchatentry.h
llcheckboxctrl.h
llclipboard.h
llcombobox.h
@ -151,12 +157,16 @@ set(llui_HEADER_FILES
lleditmenuhandler.h
llf32uictrl.h
llfiltereditor.h
llflashtimer.h
llflatlistview.h
llfloater.h
llfloaterreg.h
llfloaterreglistener.h
llflyoutbutton.h
llfocusmgr.h
llfolderview.h
llfolderviewitem.h
llfolderviewmodel.h
llfunctorregistry.h
llhelp.h
lliconctrl.h
@ -174,7 +184,6 @@ set(llui_HEADER_FILES
llmultislider.h
llnotificationptr.h
llnotifications.h
llnotificationslistener.h
llnotificationsutil.h
llnotificationtemplate.h
llnotificationvisibilityrule.h
@ -222,6 +231,7 @@ set(llui_HEADER_FILES
lluifwd.h
llui.h
lluicolor.h
lluiimage.h
lluistring.h
llundo.h
llurlaction.h

View File

@ -184,7 +184,7 @@ void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::setTitleFontStyle(std::string
if (mHeaderTextbox)
{
std::string text = mHeaderTextbox->getText();
mStyleParams.font(mHeaderTextbox->getDefaultFont());
mStyleParams.font(mHeaderTextbox->getFont());
mStyleParams.font.style(style);
mHeaderTextbox->setText(text, mStyleParams);
}

View File

@ -105,6 +105,7 @@ LLButton::Params::Params()
badge("badge"),
handle_right_mouse("handle_right_mouse"),
held_down_delay("held_down_delay"),
button_flash_enable("button_flash_enable", false),
button_flash_count("button_flash_count"),
button_flash_rate("button_flash_rate")
{
@ -171,9 +172,24 @@ LLButton::LLButton(const LLButton::Params& p)
mHeldDownSignal(NULL),
mUseDrawContextAlpha(p.use_draw_context_alpha),
mHandleRightMouse(p.handle_right_mouse),
mButtonFlashCount(p.button_flash_count),
mButtonFlashRate(p.button_flash_rate)
mFlashingTimer(NULL)
{
if (p.button_flash_enable)
{
// If optional parameter "p.button_flash_count" is not provided, LLFlashTimer will be
// used instead it a "default" value from gSavedSettings.getS32("FlashCount")).
// Likewise, missing "p.button_flash_rate" is replaced by gSavedSettings.getF32("FlashPeriod").
// Note: flashing should be allowed in settings.xml (boolean key "EnableButtonFlashing").
S32 flash_count = p.button_flash_count.isProvided()? p.button_flash_count : 0;
F32 flash_rate = p.button_flash_rate.isProvided()? p.button_flash_rate : 0.0;
mFlashingTimer = new LLFlashTimer ((LLFlashTimer::callback_t)NULL, flash_count, flash_rate);
}
else
{
mButtonFlashCount = p.button_flash_count;
mButtonFlashRate = p.button_flash_rate;
}
static LLUICachedControl<S32> llbutton_orig_h_pad ("UIButtonOrigHPad", 0);
static Params default_params(LLUICtrlFactory::getDefaultParams<LLButton>());
@ -267,6 +283,11 @@ LLButton::~LLButton()
delete mMouseDownSignal;
delete mMouseUpSignal;
delete mHeldDownSignal;
if (mFlashingTimer)
{
mFlashingTimer->unset();
}
}
// HACK: Committing a button is the same as instantly clicking it.
@ -591,22 +612,6 @@ void LLButton::draw()
{
static LLCachedControl<bool> sEnableButtonFlashing(*LLUI::sSettingGroups["config"], "EnableButtonFlashing", true);
F32 alpha = mUseDrawContextAlpha ? getDrawContext().mAlpha : getCurrentTransparency();
bool flash = FALSE;
if( mFlashing)
{
if ( sEnableButtonFlashing)
{
F32 elapsed = mFlashingTimer.getElapsedTimeF32();
S32 flash_count = S32(elapsed * mButtonFlashRate * 2.f);
// flash on or off?
flash = (flash_count % 2 == 0) || flash_count > S32((F32)mButtonFlashCount * 2.f);
}
else
{ // otherwise just highlight button in flash color
flash = true;
}
}
bool pressed_by_keyboard = FALSE;
if (hasFocus())
@ -631,9 +636,21 @@ void LLButton::draw()
bool selected = getToggleState();
bool use_glow_effect = FALSE;
LLColor4 glow_color = LLColor4::white;
LLColor4 highlighting_color = LLColor4::white;
LLColor4 glow_color;
LLRender::eBlendType glow_type = LLRender::BT_ADD_WITH_ALPHA;
LLUIImage* imagep = NULL;
// Cancel sticking of color, if the button is pressed,
// or when a flashing of the previously selected button is ended
if (mFlashingTimer
&& ((selected && !mFlashingTimer->isFlashingInProgress()) || pressed))
{
mFlashing = false;
}
bool flash = mFlashing && sEnableButtonFlashing;
if (pressed && mDisplayPressedState)
{
imagep = selected ? mImagePressedSelected : mImagePressed;
@ -699,15 +716,20 @@ void LLButton::draw()
imagep = mImageFlash;
}
// else use usual flashing via flash_color
else
else if (mFlashingTimer)
{
LLColor4 flash_color = mFlashBgColor.get();
use_glow_effect = TRUE;
glow_type = LLRender::BT_ALPHA; // blend the glow
if (mNeedsHighlight) // highlighted AND flashing
glow_color = (glow_color*0.5f + flash_color*0.5f) % 2.0f; // average between flash and highlight colour, with sum of the opacity
else
if (mFlashingTimer->isCurrentlyHighlighted() || !mFlashingTimer->isFlashingInProgress())
{
glow_color = flash_color;
}
else if (mNeedsHighlight)
{
glow_color = highlighting_color;
}
}
}
@ -756,8 +778,7 @@ void LLButton::draw()
if (use_glow_effect)
{
mCurGlowStrength = lerp(mCurGlowStrength,
mFlashing ? (flash? 1.0 : 0.0)
: mHoverGlowStrength,
mFlashing ? (mFlashingTimer->isCurrentlyHighlighted() || !mFlashingTimer->isFlashingInProgress() || mNeedsHighlight? 1.0 : 0.0) : mHoverGlowStrength,
LLCriticalDamp::getInterpolant(0.05f));
}
else
@ -944,21 +965,26 @@ void LLButton::setToggleState(BOOL b)
{
setControlValue(b); // will fire LLControlVariable callbacks (if any)
setValue(b); // may or may not be redundant
setFlashing(false); // stop flash state whenever the selected/unselected state if reset
// Unselected label assignments
autoResize();
}
}
void LLButton::setFlashing( BOOL b )
void LLButton::setFlashing(bool b)
{
if ((bool)b != mFlashing)
if (mFlashingTimer)
{
mFlashing = b;
mFlashingTimer.reset();
(b ? mFlashingTimer->startFlashing() : mFlashingTimer->stopFlashing());
}
else if (b != mFlashing)
{
mFlashing = b;
mFrameTimer.reset();
}
}
BOOL LLButton::toggleState()
{
bool flipped = ! getToggleState();

View File

@ -30,6 +30,7 @@
#include "lluuid.h"
#include "llbadgeowner.h"
#include "llcontrol.h"
#include "llflashtimer.h"
#include "lluictrl.h"
#include "v4color.h"
#include "llframetimer.h"
@ -133,6 +134,7 @@ public:
Optional<bool> handle_right_mouse;
Optional<bool> button_flash_enable;
Optional<S32> button_flash_count;
Optional<F32> button_flash_rate;
@ -199,8 +201,9 @@ public:
void setToggleState(BOOL b);
void setHighlight(bool b);
void setFlashing( BOOL b );
void setFlashing( bool b );
BOOL getFlashing() const { return mFlashing; }
LLFlashTimer* getFlashTimer() {return mFlashingTimer;}
void setHAlign( LLFontGL::HAlign align ) { mHAlign = align; }
LLFontGL::HAlign getHAlign() const { return mHAlign; }
@ -373,7 +376,8 @@ protected:
bool mForcePressedState;
bool mDisplayPressedState;
LLFrameTimer mFlashingTimer;
LLFrameTimer mFrameTimer;
LLFlashTimer * mFlashingTimer;
bool mHandleRightMouse;
};

228
indra/llui/llchatentry.cpp Normal file
View File

@ -0,0 +1,228 @@
/**
* @file llchatentry.cpp
* @brief LLChatEntry implementation
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc.
*
* 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;
* version 2.1 of the License only.
*
* 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
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llchatentry.h"
static LLDefaultChildRegistry::Register<LLChatEntry> r("chat_editor");
LLChatEntry::Params::Params()
: has_history("has_history", true),
is_expandable("is_expandable", false),
expand_lines_count("expand_lines_count", 1)
{}
LLChatEntry::LLChatEntry(const Params& p)
: LLTextEditor(p),
mTextExpandedSignal(NULL),
mHasHistory(p.has_history),
mIsExpandable(p.is_expandable),
mExpandLinesCount(p.expand_lines_count),
mPrevLinesCount(0)
{
// Initialize current history line iterator
mCurrentHistoryLine = mLineHistory.begin();
mAutoIndent = false;
}
LLChatEntry::~LLChatEntry()
{
delete mTextExpandedSignal;
}
void LLChatEntry::draw()
{
if(mIsExpandable)
{
expandText();
}
LLTextEditor::draw();
}
void LLChatEntry::onCommit()
{
updateHistory();
LLTextEditor::onCommit();
}
boost::signals2::connection LLChatEntry::setTextExpandedCallback(const commit_signal_t::slot_type& cb)
{
if (!mTextExpandedSignal)
{
mTextExpandedSignal = new commit_signal_t();
}
return mTextExpandedSignal->connect(cb);
}
void LLChatEntry::expandText()
{
int visible_lines_count = llabs(getVisibleLines(true).first - getVisibleLines(true).second);
bool can_expand = getLineCount() <= mExpandLinesCount;
// true if pasted text has more lines than expand height limit and expand limit is not reached yet
bool text_pasted = (getLineCount() > mExpandLinesCount) && (visible_lines_count < mExpandLinesCount);
if (mIsExpandable && (can_expand || text_pasted) && getLineCount() != mPrevLinesCount)
{
int lines_height = 0;
if (text_pasted)
{
// text is pasted and now mLineInfoList.size() > mExpandLineCounts and mLineInfoList is not empty,
// so lines_height is the sum of the last 'mExpandLinesCount' lines height
lines_height = (mLineInfoList.end() - mExpandLinesCount)->mRect.mTop - mLineInfoList.back().mRect.mBottom;
}
else
{
lines_height = mLineInfoList.begin()->mRect.mTop - mLineInfoList.back().mRect.mBottom;
}
int height = mVPad * 2 + lines_height;
LLRect doc_rect = getRect();
doc_rect.setOriginAndSize(doc_rect.mLeft, doc_rect.mBottom, doc_rect.getWidth(), height);
setShape(doc_rect);
mPrevLinesCount = getLineCount();
if (mTextExpandedSignal)
{
(*mTextExpandedSignal)(this, LLSD() );
}
}
}
// line history support
void LLChatEntry::updateHistory()
{
// On history enabled, remember committed line and
// reset current history line number.
// Be sure only to remember lines that are not empty and that are
// different from the last on the list.
if (mHasHistory && getLength())
{
// Add text to history, ignoring duplicates
if (mLineHistory.empty() || getText() != mLineHistory.back())
{
mLineHistory.push_back(getText());
}
mCurrentHistoryLine = mLineHistory.end();
}
}
void LLChatEntry::beforeValueChange()
{
if(this->getLength() == 0 && !mLabel.empty())
{
this->clearSegments();
}
}
void LLChatEntry::onValueChange(S32 start, S32 end)
{
//Internally resetLabel() must meet a condition before it can reset the label
resetLabel();
}
bool LLChatEntry::useLabel()
{
return !getLength() && !mLabel.empty();
}
void LLChatEntry::onFocusReceived()
{
}
void LLChatEntry::onFocusLost()
{
}
BOOL LLChatEntry::handleSpecialKey(const KEY key, const MASK mask)
{
BOOL handled = FALSE;
LLTextEditor::handleSpecialKey(key, mask);
switch(key)
{
case KEY_RETURN:
if (MASK_NONE == mask)
{
needsReflow();
}
break;
case KEY_UP:
if (mHasHistory && MASK_CONTROL == mask)
{
if (!mLineHistory.empty() && mCurrentHistoryLine > mLineHistory.begin())
{
setText(*(--mCurrentHistoryLine));
endOfDoc();
}
else
{
LLUI::reportBadKeystroke();
}
handled = TRUE;
}
break;
case KEY_DOWN:
if (mHasHistory && MASK_CONTROL == mask)
{
if (!mLineHistory.empty() && mCurrentHistoryLine < (mLineHistory.end() - 1) )
{
setText(*(++mCurrentHistoryLine));
endOfDoc();
}
else if (!mLineHistory.empty() && mCurrentHistoryLine == (mLineHistory.end() - 1) )
{
mCurrentHistoryLine++;
std::string empty("");
setText(empty);
needsReflow();
endOfDoc();
}
else
{
LLUI::reportBadKeystroke();
}
handled = TRUE;
}
break;
default:
break;
}
return handled;
}

103
indra/llui/llchatentry.h Normal file
View File

@ -0,0 +1,103 @@
/**
* @file llchatentry.h
* @author Paul Guslisty
* @brief Text editor widget which is used for user input
*
* Features:
* Optional line history so previous entries can be recalled by CTRL UP/DOWN
* Optional auto-resize behavior on input chat field
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc.
*
* 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;
* version 2.1 of the License only.
*
* 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
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LLCHATENTRY_H_
#define LLCHATENTRY_H_
#include "lltexteditor.h"
class LLChatEntry : public LLTextEditor
{
public:
struct Params : public LLInitParam::Block<Params, LLTextEditor::Params>
{
Optional<bool> has_history,
is_expandable;
Optional<int> expand_lines_count;
Params();
};
virtual ~LLChatEntry();
protected:
friend class LLUICtrlFactory;
LLChatEntry(const Params& p);
/*virtual*/ void beforeValueChange();
/*virtual*/ void onValueChange(S32 start, S32 end);
/*virtual*/ bool useLabel();
public:
virtual void draw();
virtual void onCommit();
/*virtual*/ void onFocusReceived();
/*virtual*/ void onFocusLost();
boost::signals2::connection setTextExpandedCallback(const commit_signal_t::slot_type& cb);
private:
/**
* Implements auto-resize behavior.
* When user's typing reaches the right edge of the chat field
* the chat field expands vertically by one line. The bottom of
* the chat field remains bottom-justified. The chat field does
* not expand beyond mExpandLinesCount.
*/
void expandText();
/**
* Implements line history so previous entries can be recalled by CTRL UP/DOWN
*/
void updateHistory();
BOOL handleSpecialKey(const KEY key, const MASK mask);
// Fired when text height expanded to mExpandLinesCount
commit_signal_t* mTextExpandedSignal;
// line history support:
typedef std::vector<std::string> line_history_t;
line_history_t::iterator mCurrentHistoryLine; // currently browsed history line
line_history_t mLineHistory; // line history storage
bool mHasHistory; // flag for enabled/disabled line history
bool mIsExpandable;
int mExpandLinesCount;
int mPrevLinesCount;
};
#endif /* LLCHATENTRY_H_ */

View File

@ -107,7 +107,7 @@ LLCheckBoxCtrl::LLCheckBoxCtrl(const LLCheckBoxCtrl::Params& p)
LLButton::Params params = p.check_button;
params.rect(btn_rect);
//params.control_name(p.control_name);
params.click_callback.function(boost::bind(&LLCheckBoxCtrl::onButtonPress, this, _2));
params.click_callback.function(boost::bind(&LLCheckBoxCtrl::onCommit, this));
params.commit_on_return(false);
// Checkboxes only allow boolean initial values, but buttons can
// take any LLSD.
@ -123,18 +123,6 @@ LLCheckBoxCtrl::~LLCheckBoxCtrl()
// Children all cleaned up by default view destructor.
}
// static
void LLCheckBoxCtrl::onButtonPress( const LLSD& data )
{
//if (mRadioStyle)
//{
// setValue(TRUE);
//}
onCommit();
}
void LLCheckBoxCtrl::onCommit()
{
if( getEnabled() )

View File

@ -103,8 +103,6 @@ public:
virtual void setControlName(const std::string& control_name, LLView* context);
void onButtonPress(const LLSD& data);
virtual BOOL isDirty() const; // Returns TRUE if the user has modified this control.
virtual void resetDirty(); // Clear dirty state

View File

@ -551,7 +551,7 @@ void LLComboBox::showList()
LLCoordWindow window_size;
getWindow()->getSize(&window_size);
//HACK: shouldn't have to know about scale here
mList->fitContents( 192, llfloor((F32)window_size.mY / LLUI::getScaleFactor().mV[VY]) - 50 );
mList->fitContents( 192, llfloor((F32)window_size.mY / LLUI::sGLScaleFactor.mV[VY]) - 50 );
// Make sure that we can see the whole list
LLRect root_view_local;

View File

@ -63,6 +63,7 @@ LLCommand::Params::Params()
, is_running_parameters("is_running_parameters")
, is_starting_function("is_starting_function")
, is_starting_parameters("is_starting_parameters")
, is_flashing_allowed("is_flashing_allowed", false)
{
}
@ -83,6 +84,7 @@ LLCommand::LLCommand(const LLCommand::Params& p)
, mIsRunningParameters(p.is_running_parameters)
, mIsStartingFunction(p.is_starting_function)
, mIsStartingParameters(p.is_starting_parameters)
, mIsFlashingAllowed(p.is_flashing_allowed)
{
}

View File

@ -111,6 +111,8 @@ public:
Optional<std::string> is_starting_function;
Optional<LLSD> is_starting_parameters;
Optional<bool> is_flashing_allowed;
Params();
};
@ -138,6 +140,8 @@ public:
const std::string& isStartingFunctionName() const { return mIsStartingFunction; }
const LLSD& isStartingParameters() const { return mIsStartingParameters; }
bool isFlashingAllowed() const { return mIsFlashingAllowed; }
private:
LLCommandId mIdentifier;
@ -161,6 +165,8 @@ private:
std::string mIsStartingFunction;
LLSD mIsStartingParameters;
bool mIsFlashingAllowed;
};

View File

@ -31,7 +31,6 @@
LLDockControl::LLDockControl(LLView* dockWidget, LLFloater* dockableFloater,
const LLUIImagePtr& dockTongue, DocAt dockAt, get_allowed_rect_callback_t get_allowed_rect_callback) :
mDockWidget(dockWidget),
mDockableFloater(dockableFloater),
mDockTongue(dockTongue),
mDockTongueX(0),
@ -39,6 +38,11 @@ LLDockControl::LLDockControl(LLView* dockWidget, LLFloater* dockableFloater,
{
mDockAt = dockAt;
if (dockWidget != NULL)
{
mDockWidgetHandle = dockWidget->getHandle();
}
if (dockableFloater->isDocked())
{
on();
@ -62,7 +66,7 @@ LLDockControl::LLDockControl(LLView* dockWidget, LLFloater* dockableFloater,
repositionDockable();
}
if (mDockWidget != NULL)
if (getDock() != NULL)
{
mDockWidgetVisible = isDockVisible();
}
@ -78,14 +82,15 @@ LLDockControl::~LLDockControl()
void LLDockControl::setDock(LLView* dockWidget)
{
mDockWidget = dockWidget;
if (mDockWidget != NULL)
if (dockWidget != NULL)
{
mDockWidgetHandle = dockWidget->getHandle();
repositionDockable();
mDockWidgetVisible = isDockVisible();
}
else
{
mDockWidgetHandle = LLHandle<LLView>();
mDockWidgetVisible = false;
}
}
@ -97,8 +102,8 @@ void LLDockControl::getAllowedRect(LLRect& rect)
void LLDockControl::repositionDockable()
{
if (!mDockWidget) return;
LLRect dockRect = mDockWidget->calcScreenRect();
if (!getDock()) return;
LLRect dockRect = getDock()->calcScreenRect();
LLRect rootRect;
LLRect floater_rect = mDockableFloater->calcScreenRect();
mGetAllowedRectCallback(rootRect);
@ -150,13 +155,13 @@ bool LLDockControl::isDockVisible()
{
bool res = true;
if (mDockWidget != NULL)
if (getDock() != NULL)
{
//we should check all hierarchy
res = mDockWidget->isInVisibleChain();
res = getDock()->isInVisibleChain();
if (res)
{
LLRect dockRect = mDockWidget->calcScreenRect();
LLRect dockRect = getDock()->calcScreenRect();
switch (mDockAt)
{
@ -169,7 +174,7 @@ bool LLDockControl::isDockVisible()
// assume that parent for all dockable floaters
// is the root view
LLRect dockParentRect =
mDockWidget->getRootView()->calcScreenRect();
getDock()->getRootView()->calcScreenRect();
if (dockRect.mRight <= dockParentRect.mLeft
|| dockRect.mLeft >= dockParentRect.mRight)
{
@ -189,7 +194,7 @@ bool LLDockControl::isDockVisible()
void LLDockControl::moveDockable()
{
// calculate new dockable position
LLRect dockRect = mDockWidget->calcScreenRect();
LLRect dockRect = getDock()->calcScreenRect();
LLRect rootRect;
mGetAllowedRectCallback(rootRect);
@ -263,7 +268,7 @@ void LLDockControl::moveDockable()
// calculate dock tongue position
dockParentRect = mDockWidget->getParent()->calcScreenRect();
dockParentRect = getDock()->getParent()->calcScreenRect();
if (dockRect.getCenterX() < dockParentRect.mLeft)
{
mDockTongueX = dockParentRect.mLeft - mDockTongue->getWidth() / 2;
@ -299,7 +304,7 @@ void LLDockControl::moveDockable()
}
// calculate dock tongue position
dockParentRect = mDockWidget->getParent()->calcScreenRect();
dockParentRect = getDock()->getParent()->calcScreenRect();
if (dockRect.getCenterX() < dockParentRect.mLeft)
{
mDockTongueX = dockParentRect.mLeft - mDockTongue->getWidth() / 2;

View File

@ -63,7 +63,7 @@ public:
void setDock(LLView* dockWidget);
LLView* getDock()
{
return mDockWidget;
return mDockWidgetHandle.get();
}
void repositionDockable();
void drawToungue();
@ -83,7 +83,7 @@ private:
bool mRecalculateDockablePosition;
bool mDockWidgetVisible;
DocAt mDockAt;
LLView* mDockWidget;
LLHandle<LLView> mDockWidgetHandle;
LLRect mPrevDockRect;
LLRect mRootRect;
LLRect mFloaterRect;

100
indra/llui/llflashtimer.cpp Normal file
View File

@ -0,0 +1,100 @@
/**
* @file llflashtimer.cpp
* @brief LLFlashTimer class implementation
*
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc.
*
* 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;
* version 2.1 of the License only.
*
* 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
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "../newview/llviewerprecompiledheaders.h"
#include "llflashtimer.h"
#include "../newview/llviewercontrol.h"
#include "lleventtimer.h"
LLFlashTimer::LLFlashTimer(callback_t cb, S32 count, F32 period)
: LLEventTimer(period)
, mCallback(cb)
, mCurrentTickCount(0)
, mIsFlashingInProgress(false)
, mIsCurrentlyHighlighted(false)
, mUnset(false)
{
mEventTimer.stop();
// By default use settings from settings.xml to be able change them via Debug settings. See EXT-5973.
// Due to Timer is implemented as derived class from EventTimer it is impossible to change period
// in runtime. So, both settings are made as required restart.
mFlashCount = 2 * ((count > 0) ? count : gSavedSettings.getS32("FlashCount"));
if (mPeriod <= 0)
{
mPeriod = gSavedSettings.getF32("FlashPeriod");
}
}
void LLFlashTimer::unset()
{
mUnset = true;
mCallback = NULL;
}
BOOL LLFlashTimer::tick()
{
mIsCurrentlyHighlighted = !mIsCurrentlyHighlighted;
if (mCallback)
{
mCallback(mIsCurrentlyHighlighted);
}
if (++mCurrentTickCount >= mFlashCount)
{
stopFlashing();
}
return mUnset;
}
void LLFlashTimer::startFlashing()
{
mIsFlashingInProgress = true;
mIsCurrentlyHighlighted = true;
mEventTimer.start();
}
void LLFlashTimer::stopFlashing()
{
mEventTimer.stop();
mIsFlashingInProgress = false;
mIsCurrentlyHighlighted = false;
mCurrentTickCount = 0;
}
bool LLFlashTimer::isFlashingInProgress()
{
return mIsFlashingInProgress;
}
bool LLFlashTimer::isCurrentlyHighlighted()
{
return mIsCurrentlyHighlighted;
}

73
indra/llui/llflashtimer.h Normal file
View File

@ -0,0 +1,73 @@
/**
* @file llflashtimer.h
* @brief LLFlashTimer class implementation
*
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc.
*
* 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;
* version 2.1 of the License only.
*
* 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
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_FLASHTIMER_H
#define LL_FLASHTIMER_H
#include "lleventtimer.h"
class LLFlashTimer : public LLEventTimer
{
public:
typedef boost::function<void (bool)> callback_t;
/**
* Constructor.
*
* @param count - how many times callback should be called (twice to not change original state)
* @param period - how frequently callback should be called
* @param cb - callback to be called each tick
*/
LLFlashTimer(callback_t cb = NULL, S32 count = 0, F32 period = 0.0);
~LLFlashTimer() {};
/*virtual*/ BOOL tick();
void startFlashing();
void stopFlashing();
bool isFlashingInProgress();
bool isCurrentlyHighlighted();
/*
* Use this instead of deleting this object.
* The next call to tick() will return true and that will destroy this object.
*/
void unset();
private:
callback_t mCallback;
/**
* How many times parent will blink.
*/
S32 mFlashCount;
S32 mCurrentTickCount;
bool mIsCurrentlyHighlighted;
bool mIsFlashingInProgress;
bool mUnset;
};
#endif /* LL_FLASHTIMER_H */

View File

@ -64,6 +64,8 @@
// use this to control "jumping" behavior when Ctrl-Tabbing
const S32 TABBED_FLOATER_OFFSET = 0;
extern LLControlGroup gSavedSettings;
namespace LLInitParam
{
void TypeValues<LLFloaterEnums::EOpenPositioning>::declareValues()
@ -627,6 +629,17 @@ void LLFloater::setVisible( BOOL visible )
storeVisibilityControl();
}
void LLFloater::setIsSingleInstance(BOOL is_single_instance)
{
mSingleInstance = is_single_instance;
if (!mIsReuseInitialized)
{
mReuseInstance = is_single_instance; // reuse single-instance floaters by default
}
}
// virtual
void LLFloater::handleVisibilityChange ( BOOL new_visibility )
{
@ -642,14 +655,20 @@ void LLFloater::openFloater(const LLSD& key)
{
llinfos << "Opening floater " << getName() << llendl;
mKey = key; // in case we need to open ourselves again
if (getSoundFlags() != SILENT
// don't play open sound for hosted (tabbed) windows
&& !getHost()
&& !getFloaterHost()
&& (!getVisible() || isMinimized()))
{
make_ui_sound("UISndWindowOpen");
//Don't play a sound for incoming voice call based upon chat preference setting
bool playSound = !(getName() == "incoming call" && gSavedSettings.getBOOL("PlaySoundIncomingVoiceCall") == FALSE);
if(playSound)
{
make_ui_sound("UISndWindowOpen");
}
}
//RN: for now, we don't allow rehosting from one multifloater to another
@ -713,6 +732,33 @@ void LLFloater::closeFloater(bool app_quitting)
make_ui_sound("UISndWindowClose");
}
gFocusMgr.clearLastFocusForGroup(this);
if (hasFocus())
{
// Do this early, so UI controls will commit before the
// window is taken down.
releaseFocus();
// give focus to dependee floater if it exists, and we had focus first
if (isDependent())
{
LLFloater* dependee = mDependeeHandle.get();
if (dependee && !dependee->isDead())
{
dependee->setFocus(TRUE);
}
}
}
//If floater is a dependent, remove it from parent (dependee)
LLFloater* dependee = mDependeeHandle.get();
if (dependee)
{
dependee->removeDependentFloater(this);
}
// now close dependent floater
for(handle_set_iter_t dependent_it = mDependents.begin();
dependent_it != mDependents.end(); )
@ -731,28 +777,6 @@ void LLFloater::closeFloater(bool app_quitting)
}
cleanupHandles();
gFocusMgr.clearLastFocusForGroup(this);
if (hasFocus())
{
// Do this early, so UI controls will commit before the
// window is taken down.
releaseFocus();
// give focus to dependee floater if it exists, and we had focus first
if (isDependent())
{
LLFloater* dependee = mDependeeHandle.get();
if (dependee && !dependee->isDead())
{
dependee->setFocus(TRUE);
}
}
// STORM-1879: since this floater has focus, treat the closeFloater- call
// like a click on the close-button, and close gear- and contextmenus
LLMenuGL::sMenuContainer->hideMenus();
}
dirtyRect();
@ -788,6 +812,20 @@ void LLFloater::closeFloater(bool app_quitting)
}
}
/*virtual*/
void LLFloater::closeHostedFloater()
{
// When toggling *visibility*, close the host instead of the floater when hosted
if (getHost())
{
getHost()->closeFloater();
}
else
{
closeFloater();
}
}
/*virtual*/
void LLFloater::reshape(S32 width, S32 height, BOOL called_from_parent)
{
@ -1188,7 +1226,6 @@ void LLFloater::setMinimized(BOOL minimize)
{
// minimized flag should be turned on before release focus
mMinimized = TRUE;
mExpandedRect = getRect();
// If the floater has been dragged while minimized in the
@ -1261,7 +1298,6 @@ void LLFloater::setMinimized(BOOL minimize)
}
setOrigin( mExpandedRect.mLeft, mExpandedRect.mBottom );
if (mButtonsEnabled[BUTTON_RESTORE])
{
mButtonsEnabled[BUTTON_MINIMIZE] = TRUE;
@ -1297,7 +1333,6 @@ void LLFloater::setMinimized(BOOL minimize)
// Reshape *after* setting mMinimized
reshape( mExpandedRect.getWidth(), mExpandedRect.getHeight(), TRUE );
applyPositioning(NULL, false);
}
make_ui_sound("UISndWindowClose");
@ -1419,7 +1454,6 @@ void LLFloater::setHost(LLMultiFloater* host)
mButtonScale = 1.f;
//mButtonsEnabled[BUTTON_TEAR_OFF] = FALSE;
}
updateTitleButtons();
if (host)
{
mHostHandle = host->getHandle();
@ -1429,6 +1463,8 @@ void LLFloater::setHost(LLMultiFloater* host)
{
mHostHandle.markDead();
}
updateTitleButtons();
}
void LLFloater::moveResizeHandlesToFront()
@ -1587,8 +1623,17 @@ void LLFloater::bringToFront( S32 x, S32 y )
// virtual
void LLFloater::setVisibleAndFrontmost(BOOL take_focus)
{
setVisible(TRUE);
setFrontmost(take_focus);
LLMultiFloater* hostp = getHost();
if (hostp)
{
hostp->setVisible(TRUE);
hostp->setFrontmost(take_focus);
}
else
{
setVisible(TRUE);
setFrontmost(take_focus);
}
}
void LLFloater::setFrontmost(BOOL take_focus)
@ -1670,10 +1715,12 @@ void LLFloater::onClickTearOff(LLFloater* self)
gFloaterView->addChild(self);
self->openFloater(self->getKey());
// only force position for floaters that don't have that data saved
if (self->mRectControl.empty())
if (self->mSaveRect && !self->mRectControl.empty())
{
self->applyRectControl();
}
else
{ // only force position for floaters that don't have that data saved
new_rect.setLeftTopAndSize(host_floater->getRect().mLeft + 5, host_floater->getRect().mTop - floater_header_size - 5, self->getRect().getWidth(), self->getRect().getHeight());
self->setRect(new_rect);
}
@ -1687,6 +1734,10 @@ void LLFloater::onClickTearOff(LLFloater* self)
LLMultiFloater* new_host = (LLMultiFloater*)self->mLastHostHandle.get();
if (new_host)
{
if (self->mSaveRect)
{
self->storeRectControl();
}
self->setMinimized(FALSE); // to reenable minimize button if it was minimized
new_host->showFloater(self);
// make sure host is visible
@ -1695,6 +1746,7 @@ void LLFloater::onClickTearOff(LLFloater* self)
self->setTornOff(false);
}
self->updateTitleButtons();
self->setOpenPositioning(LLFloaterEnums::POSITIONING_RELATIVE);
}
// static
@ -1720,6 +1772,18 @@ void LLFloater::onClickHelp( LLFloater* self )
}
}
void LLFloater::initRectControl()
{
// save_rect and save_visibility only apply to registered floaters
if (mSaveRect)
{
std::string ctrl_name = getControlName(mInstanceName, mKey);
mRectControl = LLFloaterReg::declareRectControl(ctrl_name);
mPosXControl = LLFloaterReg::declarePosXControl(ctrl_name);
mPosYControl = LLFloaterReg::declarePosYControl(ctrl_name);
}
}
// static
void LLFloater::closeFrontmostFloater()
{
@ -2164,7 +2228,8 @@ LLFloaterView::LLFloaterView (const Params& p)
mFocusCycleMode(FALSE),
mMinimizePositionVOffset(0),
mSnapOffsetBottom(0),
mSnapOffsetRight(0)
mSnapOffsetRight(0),
mFrontChild(NULL)
{
mSnapView = getHandle();
}
@ -2313,6 +2378,17 @@ LLRect LLFloaterView::findNeighboringPosition( LLFloater* reference_floater, LLF
void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus)
{
if (mFrontChild == child)
{
if (give_focus && !gFocusMgr.childHasKeyboardFocus(child))
{
child->setFocus(TRUE);
}
return;
}
mFrontChild = child;
// *TODO: make this respect floater's mAutoFocus value, instead of
// using parameter
if (child->getHost())
@ -2320,15 +2396,14 @@ void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus)
// this floater is hosted elsewhere and hence not one of our children, abort
return;
}
std::vector<LLView*> floaters_to_move;
std::vector<LLFloater*> floaters_to_move;
// Look at all floaters...tab
for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
for (child_list_const_iter_t child_it = beginChild(); child_it != endChild(); ++child_it)
{
LLView* viewp = *child_it;
LLFloater *floater = (LLFloater *)viewp;
LLFloater* floater = dynamic_cast<LLFloater*>(*child_it);
// ...but if I'm a dependent floater...
if (child->isDependent())
if (floater && child->isDependent())
{
// ...look for floaters that have me as a dependent...
LLFloater::handle_set_iter_t found_dependent = floater->mDependents.find(child->getHandle());
@ -2336,15 +2411,14 @@ void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus)
if (found_dependent != floater->mDependents.end())
{
// ...and make sure all children of that floater (including me) are brought to front...
for(LLFloater::handle_set_iter_t dependent_it = floater->mDependents.begin();
dependent_it != floater->mDependents.end(); )
for (LLFloater::handle_set_iter_t dependent_it = floater->mDependents.begin();
dependent_it != floater->mDependents.end(); ++dependent_it)
{
LLFloater* sibling = dependent_it->get();
if (sibling)
{
floaters_to_move.push_back(sibling);
}
++dependent_it;
}
//...before bringing my parent to the front...
floaters_to_move.push_back(floater);
@ -2352,10 +2426,10 @@ void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus)
}
}
std::vector<LLView*>::iterator view_it;
for(view_it = floaters_to_move.begin(); view_it != floaters_to_move.end(); ++view_it)
std::vector<LLFloater*>::iterator floater_it;
for(floater_it = floaters_to_move.begin(); floater_it != floaters_to_move.end(); ++floater_it)
{
LLFloater* floaterp = (LLFloater*)(*view_it);
LLFloater* floaterp = *floater_it;
sendChildToFront(floaterp);
// always unminimize dependee, but allow dependents to stay minimized
@ -2367,23 +2441,19 @@ void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus)
floaters_to_move.clear();
// ...then bringing my own dependents to the front...
for(LLFloater::handle_set_iter_t dependent_it = child->mDependents.begin();
dependent_it != child->mDependents.end(); )
for (LLFloater::handle_set_iter_t dependent_it = child->mDependents.begin();
dependent_it != child->mDependents.end(); ++dependent_it)
{
LLFloater* dependent = dependent_it->get();
if (dependent)
{
sendChildToFront(dependent);
//don't un-minimize dependent windows automatically
// respect user's wishes
//dependent->setMinimized(FALSE);
}
++dependent_it;
}
// ...and finally bringing myself to front
// (do this last, so that I'm left in front at end of this call)
if( *getChildList()->begin() != child )
if (*beginChild() != child)
{
sendChildToFront(child);
}
@ -2923,21 +2993,14 @@ void LLFloaterView::popVisibleAll(const skip_list_t& skip_list)
void LLFloater::setInstanceName(const std::string& name)
{
if (name == mInstanceName)
return;
if (name != mInstanceName)
{
llassert_always(mInstanceName.empty());
mInstanceName = name;
if (!mInstanceName.empty())
{
std::string ctrl_name = getControlName(mInstanceName, mKey);
// save_rect and save_visibility only apply to registered floaters
if (mSaveRect)
{
mRectControl = LLFloaterReg::declareRectControl(ctrl_name);
mPosXControl = LLFloaterReg::declarePosXControl(ctrl_name);
mPosYControl = LLFloaterReg::declarePosYControl(ctrl_name);
}
initRectControl();
if (!mVisibilityControl.empty())
{
mVisibilityControl = LLFloaterReg::declareVisibilityControl(ctrl_name);
@ -2948,6 +3011,7 @@ void LLFloater::setInstanceName(const std::string& name)
}
}
}
}
void LLFloater::setKey(const LLSD& newkey)
{

View File

@ -217,13 +217,17 @@ public:
/*virtual*/ void setFocus( BOOL b );
/*virtual*/ void setIsChrome(BOOL is_chrome);
/*virtual*/ void setRect(const LLRect &rect);
void setIsSingleInstance(BOOL is_single_instance);
void initFloater(const Params& p);
void openFloater(const LLSD& key = LLSD());
// If allowed, close the floater cleanly, releasing focus.
void closeFloater(bool app_quitting = false);
virtual void closeFloater(bool app_quitting = false);
// Close the floater or its host. Use when hidding or toggling a floater instance.
virtual void closeHostedFloater();
/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
@ -301,6 +305,7 @@ public:
/*virtual*/ void handleVisibilityChange ( BOOL new_visibility ); // do not override
void setFrontmost(BOOL take_focus = TRUE);
virtual void setVisibleAndFrontmost(BOOL take_focus=TRUE);
// Defaults to false.
virtual BOOL canSaveAs() const { return FALSE; }
@ -324,6 +329,8 @@ public:
virtual void setDocked(bool docked, bool pop_on_undock = true);
virtual void setTornOff(bool torn_off) { mTornOff = torn_off; }
bool isTornOff() {return mTornOff;}
void setOpenPositioning(LLFloaterEnums::EOpenPositioning pos) {mPositioning = pos;}
// Close the floater returned by getFrontmostClosableFloater() and
@ -354,6 +361,7 @@ protected:
void stackWith(LLFloater& other);
virtual void initRectControl();
virtual bool applyRectControl();
bool applyDockState();
void applyPositioning(LLFloater* other, bool on_open);
@ -367,7 +375,6 @@ protected:
void setInstanceName(const std::string& name);
virtual void bringToFront(S32 x, S32 y);
virtual void setVisibleAndFrontmost(BOOL take_focus=TRUE);
void setExpandedRect(const LLRect& rect) { mExpandedRect = rect; } // size when not minimized
const LLRect& getExpandedRect() const { return mExpandedRect; }
@ -441,9 +448,10 @@ private:
LLUIString mTitle;
LLUIString mShortTitle;
BOOL mSingleInstance; // TRUE if there is only ever one instance of the floater
bool mReuseInstance; // true if we want to hide the floater when we close it instead of destroying it
std::string mInstanceName; // Store the instance name so we can remove ourselves from the list
BOOL mSingleInstance; // TRUE if there is only ever one instance of the floater
bool mReuseInstance; // true if we want to hide the floater when we close it instead of destroying it
bool mIsReuseInitialized; // true if mReuseInstance already set from parameters
std::string mInstanceName; // Store the instance name so we can remove ourselves from the list
BOOL mCanTearOff;
BOOL mCanMinimize;
@ -570,6 +578,7 @@ private:
S32 mMinimizePositionVOffset;
typedef std::vector<std::pair<LLHandle<LLFloater>, boost::signals2::connection> > hidden_floaters_t;
hidden_floaters_t mHiddenFloaters;
LLFloater * mFrontChild;
};
//

View File

@ -264,17 +264,9 @@ bool LLFloaterReg::hideInstance(const std::string& name, const LLSD& key)
LLFloater* instance = findInstance(name, key);
if (instance)
{
// When toggling *visibility*, close the host instead of the floater when hosted
if (instance->getHost())
instance->getHost()->closeFloater();
else
instance->closeFloater();
return true;
}
else
{
return false;
instance->closeHostedFloater();
}
return (instance != NULL);
}
//static
@ -284,11 +276,7 @@ bool LLFloaterReg::toggleInstance(const std::string& name, const LLSD& key)
LLFloater* instance = findInstance(name, key);
if (LLFloater::isShown(instance))
{
// When toggling *visibility*, close the host instead of the floater when hosted
if (instance->getHost())
instance->getHost()->closeFloater();
else
instance->closeFloater();
instance->closeHostedFloater();
return false;
}
else
@ -481,31 +469,58 @@ void LLFloaterReg::toggleInstanceOrBringToFront(const LLSD& sdname, const LLSD&
// * Also, if it is not on top, bring it forward when focus is given.
// * Else the target floater is open, close it.
//
std::string name = sdname.asString();
LLFloater* instance = getInstance(name, key);
if (!instance)
{
lldebugs << "Unable to get instance of floater '" << name << "'" << llendl;
return;
}
else if (instance->isMinimized())
// If hosted, we need to take that into account
LLFloater* host = instance->getHost();
if (host)
{
instance->setMinimized(FALSE);
instance->setVisibleAndFrontmost();
}
else if (!instance->isShown())
{
instance->openFloater(key);
instance->setVisibleAndFrontmost();
}
else if (!instance->isFrontmost())
{
instance->setVisibleAndFrontmost();
if (host->isMinimized() || !host->isShown() || !host->isFrontmost())
{
host->setMinimized(FALSE);
instance->openFloater(key);
instance->setVisibleAndFrontmost();
}
else if (!instance->getVisible())
{
instance->openFloater(key);
instance->setVisibleAndFrontmost();
instance->setFocus(TRUE);
}
else
{
instance->closeHostedFloater();
}
}
else
{
instance->closeFloater();
if (instance->isMinimized())
{
instance->setMinimized(FALSE);
instance->setVisibleAndFrontmost();
}
else if (!instance->isShown())
{
instance->openFloater(key);
instance->setVisibleAndFrontmost();
}
else if (!instance->isFrontmost())
{
instance->setVisibleAndFrontmost();
}
else
{
instance->closeHostedFloater();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -39,19 +39,16 @@
#include "lluictrl.h"
#include "v4color.h"
#include "lldarray.h"
#include "stdenums.h"
#include "lldepthstack.h"
#include "lleditmenuhandler.h"
#include "llfontgl.h"
#include "llscrollcontainer.h"
#include "lltooldraganddrop.h"
#include "llviewertexture.h"
class LLFolderViewEventListener;
class LLFolderViewModelInterface;
class LLFolderViewFolder;
class LLFolderViewItem;
class LLInventoryModel;
class LLFolderViewFilter;
class LLPanel;
class LLLineEditor;
class LLMenuGL;
@ -90,136 +87,104 @@ public:
struct Params : public LLInitParam::Block<Params, LLFolderViewFolder::Params>
{
Mandatory<LLPanel*> parent_panel;
Optional<LLUUID> task_id;
Optional<std::string> title;
Optional<bool> use_label_suffix,
allow_multiselect,
show_empty_message,
show_load_status,
use_ellipses;
use_ellipses,
show_item_link_overlays;
Mandatory<LLFolderViewModelInterface*> view_model;
Mandatory<std::string> options_menu;
Params();
};
friend class LLFolderViewScrollContainer;
typedef std::deque<LLFolderViewItem*> selected_items_t;
LLFolderView(const Params&);
virtual ~LLFolderView( void );
virtual BOOL canFocusChildren() const;
virtual const LLFolderView* getRoot() const { return this; }
virtual LLFolderView* getRoot() { return this; }
// FolderViews default to sort by name. This will change that,
// and resort the items if necessary.
void setSortOrder(U32 order);
void setFilterPermMask(PermissionMask filter_perm_mask);
LLFolderViewModelInterface* getFolderViewModel() { return mViewModel; }
const LLFolderViewModelInterface* getFolderViewModel() const { return mViewModel; }
typedef boost::signals2::signal<void (const std::deque<LLFolderViewItem*>& items, BOOL user_action)> signal_t;
void setSelectCallback(const signal_t::slot_type& cb) { mSelectSignal.connect(cb); }
void setReshapeCallback(const signal_t::slot_type& cb) { mReshapeSignal.connect(cb); }
// filter is never null
LLInventoryFilter* getFilter();
const std::string getFilterSubString(BOOL trim = FALSE);
U32 getFilterObjectTypes() const;
PermissionMask getFilterPermissions() const;
// *NOTE: use getFilter()->getShowFolderState();
//LLInventoryFilter::EFolderShow getShowFolderState();
U32 getSortOrder() const;
BOOL isFilterModified();
bool getAllowMultiSelect() { return mAllowMultiSelect; }
// Close all folders in the view
void closeAllFolders();
void openTopLevelFolders();
virtual void toggleOpen() {};
virtual void setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse);
virtual BOOL addFolder( LLFolderViewFolder* folder);
virtual void addFolder( LLFolderViewFolder* folder);
// Find width and height of this object and its children. Also
// makes sure that this view and its children are the right size.
virtual S32 arrange( S32* width, S32* height, S32 filter_generation );
virtual S32 arrange( S32* width, S32* height );
virtual S32 getItemHeight();
void arrangeAll() { mArrangeGeneration++; }
S32 getArrangeGeneration() { return mArrangeGeneration; }
// Apply filters to control visibility of inventory items
virtual void filter( LLInventoryFilter& filter);
// applies filters to control visibility of items
virtual void filter( LLFolderViewFilter& filter);
// Get the last selected item
virtual LLFolderViewItem* getCurSelectedItem( void );
selected_items_t& getSelectedItems( void );
// Record the selected item and pass it down the hierarchy.
virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem,
BOOL take_keyboard_focus);
BOOL take_keyboard_focus = TRUE);
// Used by menu callbacks
void setSelectionByID(const LLUUID& obj_id, BOOL take_keyboard_focus);
// Called once a frame to update the selection if mSelectThisID has been set
void updateSelection();
// This method is used to toggle the selection of an item.
// Walks children and keeps track of selected objects.
// This method is used to toggle the selection of an item. Walks
// children, and keeps track of selected objects.
virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected);
virtual std::set<LLUUID> getSelectionList() const;
virtual std::set<LLFolderViewItem*> getSelectionList() const;
// Make sure if ancestor is selected, descendents are not
// Make sure if ancestor is selected, descendants are not
void sanitizeSelection();
void clearSelection();
virtual void clearSelection();
void addToSelectionList(LLFolderViewItem* item);
void removeFromSelectionList(LLFolderViewItem* item);
BOOL startDrag(LLToolDragAndDrop::ESource source);
bool startDrag();
void setDragAndDropThisFrame() { mDragAndDropThisFrame = TRUE; }
void setDraggingOverItem(LLFolderViewItem* item) { mDraggingOverItem = item; }
LLFolderViewItem* getDraggingOverItem() { return mDraggingOverItem; }
// Deletion functionality
void removeSelectedItems();
static void removeCutItems();
// Open the selected item
void openSelectedItems( void );
void propertiesSelectedItems( void );
// Change the folder type
void changeType(LLInventoryModel *model, LLFolderType::EType new_folder_type);
void autoOpenItem(LLFolderViewFolder* item);
void closeAutoOpenedFolders();
BOOL autoOpenTest(LLFolderViewFolder* item);
BOOL isOpen() const { return TRUE; } // root folder always open
// Copy & paste
virtual void copy();
virtual BOOL canCopy() const;
virtual void copy();
virtual void cut();
virtual BOOL canCut() const;
virtual void cut();
virtual void paste();
virtual BOOL canPaste() const;
virtual void doDelete();
virtual BOOL canDoDelete() const;
virtual void paste();
LLFolderViewItem* getNextUnselectedItem();
// Public rename functionality - can only start the process
void startRenamingSelectedItem( void );
// These functions were used when there was only one folderview,
// and relied on that concept. This functionality is now handled
// by the listeners and the lldraganddroptool.
//LLFolderViewItem* getMovingItem() { return mMovingItem; }
//void setMovingItem( LLFolderViewItem* item ) { mMovingItem = item; }
//void dragItemIntoFolder( LLFolderViewItem* moving_item, LLFolderViewFolder* dst_folder, BOOL drop, BOOL* accept );
//void dragFolderIntoFolder( LLFolderViewFolder* moving_folder, LLFolderViewFolder* dst_folder, BOOL drop, BOOL* accept );
// LLView functionality
///*virtual*/ BOOL handleKey( KEY key, MASK mask, BOOL called_from_parent );
/*virtual*/ BOOL handleKeyHere( KEY key, MASK mask );
@ -250,16 +215,9 @@ public:
BOOL getShowSingleSelection() { return mShowSingleSelection; }
F32 getSelectionFadeElapsedTime() { return mMultiSelectionFadeTimer.getElapsedTimeF32(); }
bool getUseEllipses() { return mUseEllipses; }
S32 getSelectedCount() { return (S32)mSelectedItems.size(); }
void addItemID(const LLUUID& id, LLFolderViewItem* itemp);
void removeItemID(const LLUUID& id);
LLFolderViewItem* getItemByID(const LLUUID& id);
LLFolderViewFolder* getFolderByID(const LLUUID& id);
bool doToSelected(LLInventoryModel* model, const LLSD& userdata);
void doIdle(); // Real idle routine
static void idle(void* user_data); // static glue to doIdle()
void update(); // needs to be called periodically (e.g. once per frame)
BOOL needsAutoSelect() { return mNeedsAutoSelect && !mAutoSelectOverride; }
BOOL needsAutoRename() { return mNeedsAutoRename; }
@ -267,9 +225,9 @@ public:
void setPinningSelectedItem(BOOL val) { mPinningSelectedItem = val; }
void setAutoSelectOverride(BOOL val) { mAutoSelectOverride = val; }
void setCallbackRegistrar(LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* registrar) { mCallbackRegistrar = registrar; }
bool showItemLinkOverlays() { return mShowItemLinkOverlays; }
BOOL getDebugFilters() { return mDebugFilters; }
void setCallbackRegistrar(LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* registrar) { mCallbackRegistrar = registrar; }
LLPanel* getParentPanel() { return mParentPanel; }
// DEBUG only
@ -298,18 +256,15 @@ protected:
BOOL addNoOptions(LLMenuGL* menu) const;
void onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response);
protected:
LLHandle<LLView> mPopupMenuHandle;
typedef std::deque<LLFolderViewItem*> selected_items_t;
selected_items_t mSelectedItems;
BOOL mKeyboardSelection;
BOOL mAllowMultiSelect;
BOOL mShowEmptyMessage;
BOOL mShowFolderHierarchy;
LLUUID mSourceID;
// Renaming variables and methods
LLFolderViewItem* mRenameItem; // The item currently being renamed
@ -322,15 +277,13 @@ protected:
BOOL mAutoSelectOverride;
BOOL mNeedsAutoRename;
bool mUseLabelSuffix;
bool mShowItemLinkOverlays;
BOOL mDebugFilters;
U32 mSortOrder;
LLDepthStack<LLFolderViewFolder> mAutoOpenItems;
LLFolderViewFolder* mAutoOpenCandidate;
LLFrameTimer mAutoOpenTimer;
LLFrameTimer mSearchTimer;
std::string mSearchString;
LLInventoryFilter* mFilter;
BOOL mShowSelectionContext;
BOOL mShowSingleSelection;
LLFrameTimer mMultiSelectionFadeTimer;
@ -340,13 +293,11 @@ protected:
signal_t mReshapeSignal;
S32 mSignalSelectCallback;
S32 mMinWidth;
S32 mRunningHeight;
std::map<LLUUID, LLFolderViewItem*> mItemMap;
BOOL mDragAndDropThisFrame;
LLUUID mSelectThisID; // if non null, select this item
LLPanel* mParentPanel;
LLFolderViewModelInterface* mViewModel;
/**
* Is used to determine if we need to cut text In LLFolderViewItem to avoid horizontal scroll.
@ -367,11 +318,82 @@ public:
};
bool sort_item_name(LLFolderViewItem* a, LLFolderViewItem* b);
bool sort_item_date(LLFolderViewItem* a, LLFolderViewItem* b);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLFolderViewFunctor
//
// Simple abstract base class for applying a functor to folders and
// items in a folder view hierarchy. This is suboptimal for algorithms
// that only work folders or only work on items, but I'll worry about
// that later when it's determined to be too slow.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class LLFolderViewFunctor
{
public:
virtual ~LLFolderViewFunctor() {}
virtual void doFolder(LLFolderViewFolder* folder) = 0;
virtual void doItem(LLFolderViewItem* item) = 0;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLSelectFirstFilteredItem
//
// This will select the first *item* found in the hierarchy. If no item can be
// selected, the first matching folder will.
// Since doFolder() is done first but we prioritize item selection, we let the
// first filtered folder set the selection and raise a folder flag.
// The selection might be overridden by the first filtered item in doItem()
// which checks an item flag. Since doFolder() checks the item flag too, the first
// item will still be selected if items were to be done first and folders second.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class LLSelectFirstFilteredItem : public LLFolderViewFunctor
{
public:
LLSelectFirstFilteredItem() : mItemSelected(FALSE), mFolderSelected(FALSE) {}
virtual ~LLSelectFirstFilteredItem() {}
virtual void doFolder(LLFolderViewFolder* folder);
virtual void doItem(LLFolderViewItem* item);
BOOL wasItemSelected() { return mItemSelected || mFolderSelected; }
protected:
BOOL mItemSelected;
BOOL mFolderSelected;
};
class LLOpenFilteredFolders : public LLFolderViewFunctor
{
public:
LLOpenFilteredFolders() {}
virtual ~LLOpenFilteredFolders() {}
virtual void doFolder(LLFolderViewFolder* folder);
virtual void doItem(LLFolderViewItem* item);
};
class LLSaveFolderState : public LLFolderViewFunctor
{
public:
LLSaveFolderState() : mApply(FALSE) {}
virtual ~LLSaveFolderState() {}
virtual void doFolder(LLFolderViewFolder* folder);
virtual void doItem(LLFolderViewItem* item) {}
void setApply(BOOL apply);
void clearOpenFolders() { mOpenFolders.clear(); }
protected:
std::set<LLUUID> mOpenFolders;
BOOL mApply;
};
class LLOpenFoldersWithSelection : public LLFolderViewFunctor
{
public:
LLOpenFoldersWithSelection() {}
virtual ~LLOpenFoldersWithSelection() {}
virtual void doFolder(LLFolderViewFolder* folder);
virtual void doItem(LLFolderViewItem* item);
};
// Flags for buildContextMenu()
const U32 SUPPRESS_OPEN_ITEM = 0x1;
const U32 FIRST_SELECTED_ITEM = 0x2;
const U32 ITEM_IN_MULTI_SELECTION = 0x4;
#endif // LL_LLFOLDERVIEW_H

File diff suppressed because it is too large Load Diff

View File

@ -26,55 +26,16 @@
#ifndef LLFOLDERVIEWITEM_H
#define LLFOLDERVIEWITEM_H
#include "llflashtimer.h"
#include "llview.h"
#include "lldarray.h" // *TODO: Eliminate, forward declare
#include "lluiimage.h"
class LLFontGL;
class LLFolderView;
class LLFolderViewEventListener;
class LLFolderViewModelItem;
class LLFolderViewFolder;
class LLFolderViewFunctor;
class LLFolderViewItem;
class LLFolderViewListenerFunctor;
class LLInventoryFilter;
class LLMenuGL;
class LLUIImage;
class LLViewerInventoryItem;
// These are grouping of inventory types.
// Order matters when sorting system folders to the top.
enum EInventorySortGroup
{
SG_SYSTEM_FOLDER,
SG_TRASH_FOLDER,
SG_NORMAL_FOLDER,
SG_ITEM
};
// *TODO: do we really need one sort object per folder?
// can we just have one of these per LLFolderView ?
class LLInventorySort
{
public:
LLInventorySort()
: mSortOrder(0),
mByDate(false),
mSystemToTop(false),
mFoldersByName(false) { }
// Returns true if order has changed
bool updateSort(U32 order);
U32 getSort() { return mSortOrder; }
bool isByDate() { return mByDate; }
bool operator()(const LLFolderViewItem* const& a, const LLFolderViewItem* const& b);
private:
U32 mSortOrder;
bool mByDate;
bool mSystemToTop;
bool mFoldersByName;
};
class LLFolderViewFilter;
class LLFolderViewModelInterface;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLFolderViewItem
@ -86,134 +47,130 @@ private:
class LLFolderViewItem : public LLView
{
public:
static void initClass();
static void cleanupClass();
struct Params : public LLInitParam::Block<Params, LLView::Params>
{
Optional<LLUIImage*> icon;
Optional<LLUIImage*> icon_open; // used for folders
Optional<LLUIImage*> icon_overlay; // for links
Optional<LLFolderView*> root;
Mandatory<LLFolderViewEventListener*> listener;
Optional<LLUIImage*> folder_arrow_image,
selection_image;
Mandatory<LLFolderView*> root;
Mandatory<LLFolderViewModelItem*> listener;
Optional<LLUIImage*> folder_arrow_image;
Optional<S32> folder_indentation; // pixels
Optional<LLUIImage*> selection_image;
Optional<S32> item_height; // pixels
Optional<S32> item_top_pad; // pixels
Optional<S32> folder_indentation, // pixels
item_height,
item_top_pad;
Optional<S32> creation_date; //UTC seconds
Optional<time_t> creation_date;
Optional<bool> allow_open;
Optional<LLUIColor> font_color;
Optional<LLUIColor> font_highlight_color;
Optional<S32> left_pad,
icon_pad,
icon_width,
text_pad,
text_pad_right,
arrow_size,
max_folder_item_overlap;
Params();
};
// layout constants
static const S32 LEFT_PAD = 5;
// LEFT_INDENTATION is set via folder_indentation above
static const S32 ICON_PAD = 2;
static const S32 ICON_WIDTH = 16;
static const S32 TEXT_PAD = 1;
static const S32 TEXT_PAD_RIGHT = 4;
static const S32 ARROW_SIZE = 12;
static const S32 MAX_FOLDER_ITEM_OVERLAP = 2;
static const S32 DEFAULT_LABEL_PADDING_RIGHT = 4;
// animation parameters
static const F32 FOLDER_CLOSE_TIME_CONSTANT;
static const F32 FOLDER_OPEN_TIME_CONSTANT;
// Mostly for debugging printout purposes.
const std::string& getSearchableLabel() { return mSearchableLabel; }
BOOL isLoading() const { return mIsLoading; }
private:
BOOL mIsSelected;
static const F32 FOLDER_CLOSE_TIME_CONSTANT,
FOLDER_OPEN_TIME_CONSTANT;
protected:
friend class LLUICtrlFactory;
friend class LLFolderViewEventListener;
friend class LLFolderViewModelItem;
LLFolderViewItem(const Params& p);
std::string mLabel;
std::string mSearchableLabel;
S32 mLabelWidth;
bool mLabelWidthDirty;
time_t mCreationDate;
S32 mLabelPaddingRight;
LLFolderViewFolder* mParentFolder;
LLFolderViewEventListener* mListener;
BOOL mIsCurSelection;
BOOL mSelectPending;
LLPointer<LLFolderViewModelItem> mViewModelItem;
LLFontGL::StyleFlags mLabelStyle;
std::string mLabelSuffix;
LLUIImagePtr mIcon;
std::string mStatusText;
LLUIImagePtr mIconOpen;
LLUIImagePtr mIconOverlay;
BOOL mHasVisibleChildren;
LLUIImagePtr mIcon,
mIconOpen,
mIconOverlay;
S32 mLocalIndentation;
S32 mIndentation;
S32 mItemHeight;
BOOL mPassedFilter;
S32 mLastFilterGeneration;
std::string::size_type mStringMatchOffset;
S32 mDragStartX,
mDragStartY;
S32 mLeftPad,
mIconPad,
mIconWidth,
mTextPad,
mTextPadRight,
mArrowSize,
mMaxFolderItemOverlap;
F32 mControlLabelRotation;
LLFolderView* mRoot;
BOOL mDragAndDropTarget;
BOOL mIsLoading;
LLTimer mTimeSinceRequestStart;
bool mShowLoadStatus;
bool mIsMouseOverTitle;
bool mHasVisibleChildren,
mIsCurSelection,
mDragAndDropTarget,
mIsMouseOverTitle,
mAllowOpen,
mSelectPending;
LLUIColor mFontColor;
LLUIColor mFontHighlightColor;
// helper function to change the selection from the root.
void changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected);
// For now assuming all colors are the same in derived classes.
static bool sColorSetInitialized;
static LLUIColor sFgColor;
static LLUIColor sFgDisabledColor;
static LLUIColor sHighlightBgColor;
static LLUIColor sFlashBgColor;
static LLUIColor sFocusOutlineColor;
static LLUIColor sMouseOverColor;
static LLUIColor sFilterBGColor;
static LLUIColor sFilterTextColor;
static LLUIColor sSuffixColor;
static LLUIColor sSearchStatusColor;
// this is an internal method used for adding items to folders. A
// no-op at this level, but reimplemented in derived classes.
virtual BOOL addItem(LLFolderViewItem*) { return FALSE; }
virtual BOOL addFolder(LLFolderViewFolder*) { return FALSE; }
virtual void addItem(LLFolderViewItem*) { }
virtual void addFolder(LLFolderViewFolder*) { }
virtual bool isHighlightAllowed();
virtual bool isHighlightActive();
virtual bool isFlashing() { return false; }
virtual void setFlashState(bool) { }
static LLFontGL* getLabelFontForStyle(U8 style);
virtual void setCreationDate(time_t creation_date_utc) { mCreationDate = creation_date_utc; }
BOOL mIsSelected;
public:
static void initClass();
static void cleanupClass();
BOOL postBuild();
// This function clears the currently selected item, and records
// the specified selected item appropriately for display and use
// in the UI. If open is TRUE, then folders are opened up along
// the way to the selection.
void setSelectionFromRoot(LLFolderViewItem* selection, BOOL openitem,
BOOL take_keyboard_focus = TRUE);
virtual void openItem( void );
// This function is called when the folder view is dirty. It's
// implemented here but called by derived classes when folding the
// views.
void arrangeFromRoot();
void filterFromRoot( void );
void arrangeAndSet(BOOL set_selection, BOOL take_keyboard_focus);
virtual ~LLFolderViewItem( void );
// addToFolder() returns TRUE if it succeeds. FALSE otherwise
enum { ARRANGE = TRUE, DO_NOT_ARRANGE = FALSE };
virtual BOOL addToFolder(LLFolderViewFolder* folder, LLFolderView* root);
virtual EInventorySortGroup getSortGroup() const;
virtual void addToFolder(LLFolderViewFolder* folder);
// Finds width and height of this object and it's children. Also
// makes sure that this view and it's children are the right size.
virtual S32 arrange( S32* width, S32* height, S32 filter_generation );
virtual S32 arrange( S32* width, S32* height );
virtual S32 getItemHeight();
// applies filters to control visibility of inventory items
virtual void filter( LLInventoryFilter& filter);
// updates filter serial number and optionally propagated value up to root
S32 getLastFilterGeneration() { return mLastFilterGeneration; }
virtual void dirtyFilter();
virtual S32 getLabelXPos();
S32 getIconPad();
S32 getTextPad();
// If 'selection' is 'this' then note that otherwise ignore.
// Returns TRUE if this item ends up being selected.
@ -231,7 +188,7 @@ public:
virtual void selectItem();
// gets multiple-element selection
virtual std::set<LLUUID> getSelectionList() const;
virtual std::set<LLFolderViewItem*> getSelectionList() const;
// Returns true is this object and all of its children can be removed (deleted by user)
virtual BOOL isRemovable();
@ -253,74 +210,54 @@ public:
BOOL hasVisibleChildren() { return mHasVisibleChildren; }
void setShowLoadStatus(bool status) { mShowLoadStatus = status; }
// Call through to the viewed object and return true if it can be
// removed. Returns true if it's removed.
//virtual BOOL removeRecursively(BOOL single_item);
BOOL remove();
// Build an appropriate context menu for the item. Flags unused.
void buildContextMenu(LLMenuGL& menu, U32 flags);
void buildContextMenu(class LLMenuGL& menu, U32 flags);
// This method returns the actual name of the thing being
// viewed. This method will ask the viewed object itself.
const std::string& getName( void ) const;
const std::string& getSearchableLabel( void ) const;
// This method returns the label displayed on the view. This
// method was primarily added to allow sorting on the folder
// contents possible before the entire view has been constructed.
const std::string& getLabel() const { return mLabel; }
// Used for sorting, like getLabel() above.
virtual time_t getCreationDate() const { return mCreationDate; }
LLFolderViewFolder* getParentFolder( void ) { return mParentFolder; }
const LLFolderViewFolder* getParentFolder( void ) const { return mParentFolder; }
void setParentFolder(LLFolderViewFolder* parent) { mParentFolder = parent; }
LLFolderViewItem* getNextOpenNode( BOOL include_children = TRUE );
LLFolderViewItem* getPreviousOpenNode( BOOL include_children = TRUE );
const LLFolderViewEventListener* getListener( void ) const { return mListener; }
LLFolderViewEventListener* getListener( void ) { return mListener; }
// Gets the inventory item if it exists (null otherwise)
LLViewerInventoryItem * getInventoryItem(void);
const LLFolderViewModelItem* getViewModelItem( void ) const { return mViewModelItem; }
LLFolderViewModelItem* getViewModelItem( void ) { return mViewModelItem; }
const LLFolderViewModelInterface* getFolderViewModel( void ) const;
LLFolderViewModelInterface* getFolderViewModel( void );
// just rename the object.
void rename(const std::string& new_name);
// open
virtual void openItem( void );
virtual void preview(void);
// Show children (unfortunate that this is called "open")
// Show children
virtual void setOpen(BOOL open = TRUE) {};
virtual BOOL isOpen() const { return FALSE; }
virtual LLFolderView* getRoot();
virtual const LLFolderView* getRoot() const;
BOOL isDescendantOf( const LLFolderViewFolder* potential_ancestor );
S32 getIndentation() { return mIndentation; }
virtual BOOL potentiallyVisible(); // do we know for a fact that this item won't be displayed?
virtual BOOL potentiallyFiltered(); // do we know for a fact that this item has been filtered out?
virtual BOOL getFiltered();
virtual BOOL getFiltered(S32 filter_generation);
virtual void setFiltered(BOOL filtered, S32 filter_generation);
// change the icon
void setIcon(LLUIImagePtr icon);
virtual BOOL passedFilter(S32 filter_generation = -1);
// refresh information from the object being viewed.
void refreshFromListener();
virtual void refresh();
virtual void applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor);
// LLView functionality
virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask );
virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask );
@ -330,25 +267,23 @@ public:
virtual void onMouseLeave(S32 x, S32 y, MASK mask);
virtual LLView* findChildView(const std::string& name, BOOL recurse) const { return NULL; }
//virtual LLView* findChildView(const std::string& name, BOOL recurse) const { return LLView::findChildView(name, recurse); }
// virtual void handleDropped();
virtual void draw();
void drawOpenFolderArrow(const Params& default_params, const LLUIColor& fg_color);
void drawHighlight(const BOOL showContent, const BOOL hasKeyboardFocus, const LLUIColor &selectColor, const LLUIColor &flashColor, const LLUIColor &outlineColor, const LLUIColor &mouseOverColor);
void drawLabel(const LLFontGL * font, const F32 x, const F32 y, const LLColor4& color, F32 &right_x);
virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,
EAcceptance* accept,
std::string& tooltip_msg);
EDragAndDropType cargo_type,
void* cargo_data,
EAcceptance* accept,
std::string& tooltip_msg);
private:
static std::map<U8, LLFontGL*> sFonts; // map of styles to fonts
};
// function used for sorting.
typedef bool (*sort_order_f)(LLFolderViewItem* a, LLFolderViewItem* b);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLFolderViewFolder
//
@ -363,33 +298,26 @@ protected:
LLFolderViewFolder( const LLFolderViewItem::Params& );
friend class LLUICtrlFactory;
public:
typedef enum e_trash
{
UNKNOWN, TRASH, NOT_TRASH
} ETrash;
void updateLabelRotation();
virtual bool isCollapsed() { return FALSE; }
public:
typedef std::list<LLFolderViewItem*> items_t;
typedef std::list<LLFolderViewFolder*> folders_t;
protected:
items_t mItems;
folders_t mFolders;
LLInventorySort mSortFunction;
BOOL mIsOpen;
BOOL mExpanderHighlighted;
F32 mCurHeight;
F32 mTargetHeight;
F32 mAutoOpenCountdown;
time_t mSubtreeCreationDate;
mutable ETrash mAmTrash;
S32 mLastArrangeGeneration;
S32 mLastCalculatedWidth;
S32 mCompletedFilterGeneration;
S32 mMostFilteredDescendantGeneration;
bool mNeedsSort;
bool mPassedFolderFilter;
public:
typedef enum e_recurse_type
@ -403,48 +331,25 @@ public:
virtual ~LLFolderViewFolder( void );
virtual BOOL potentiallyVisible();
LLFolderViewItem* getNextFromChild( LLFolderViewItem*, BOOL include_children = TRUE );
LLFolderViewItem* getPreviousFromChild( LLFolderViewItem*, BOOL include_children = TRUE );
// addToFolder() returns TRUE if it succeeds. FALSE otherwise
virtual BOOL addToFolder(LLFolderViewFolder* folder, LLFolderView* root);
virtual void addToFolder(LLFolderViewFolder* folder);
// Finds width and height of this object and it's children. Also
// makes sure that this view and it's children are the right size.
virtual S32 arrange( S32* width, S32* height, S32 filter_generation );
virtual S32 arrange( S32* width, S32* height );
BOOL needsArrange();
void requestSort();
// Returns the sort group (system, trash, folder) for this folder.
virtual EInventorySortGroup getSortGroup() const;
virtual void setCompletedFilterGeneration(S32 generation, BOOL recurse_up);
virtual S32 getCompletedFilterGeneration() { return mCompletedFilterGeneration; }
BOOL hasFilteredDescendants(S32 filter_generation);
BOOL hasFilteredDescendants();
// applies filters to control visibility of inventory items
virtual void filter( LLInventoryFilter& filter);
virtual void setFiltered(BOOL filtered, S32 filter_generation);
virtual BOOL getFiltered();
virtual BOOL getFiltered(S32 filter_generation);
virtual void dirtyFilter();
// folder-specific filtering (filter status propagates top down instead of bottom up)
void filterFolder(LLInventoryFilter& filter);
void setFilteredFolder(bool filtered, S32 filter_generation);
bool getFilteredFolder(S32 filter_generation);
bool descendantsPassedFilter(S32 filter_generation = -1);
// Passes selection information on to children and record
// selection information if necessary.
// Returns TRUE if this object (or a child) ends up being selected.
// If 'openitem' is TRUE then folders are opened up along the way to the selection.
virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus);
virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus = TRUE);
// This method is used to change the selection of an item.
// Recursively traverse all children; if 'selection' is 'this' then change
@ -464,31 +369,13 @@ public:
// destroys this folder, and all children
virtual void destroyView();
// If this folder can be removed, remove all children that can be
// removed, return TRUE if this is empty after the operation and
// it's viewed folder object can be removed.
//virtual BOOL removeRecursively(BOOL single_item);
//virtual BOOL remove();
// remove the specified item (and any children) if
// possible. Return TRUE if the item was deleted.
BOOL removeItem(LLFolderViewItem* item);
// simply remove the view (and any children) Don't bother telling
// the listeners.
void removeView(LLFolderViewItem* item);
// extractItem() removes the specified item from the folder, but
// doesn't delete it.
void extractItem( LLFolderViewItem* item );
virtual void extractItem( LLFolderViewItem* item );
// This function is called by a child that needs to be resorted.
void resort(LLFolderViewItem* item);
void setItemSortOrder(U32 ordering);
void sortBy(U32);
//BOOL (*func)(LLFolderViewItem* a, LLFolderViewItem* b));
void setAutoOpenCountdown(F32 countdown) { mAutoOpenCountdown = countdown; }
// folders can be opened. This will usually be called by internal
@ -499,8 +386,7 @@ public:
virtual void setOpen(BOOL openitem = TRUE);
// Called when a child is refreshed.
// don't rearrange child folder contents unless explicitly requested
virtual void requestArrange(BOOL include_descendants = FALSE);
virtual void requestArrange();
// internal method which doesn't update the entire view. This
// method was written because the list iterators destroy the state
@ -513,65 +399,60 @@ public:
// special case if an object is dropped on the child.
BOOL handleDragAndDropFromChild(MASK mask,
BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,
EAcceptance* accept,
std::string& tooltip_msg);
BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,
EAcceptance* accept,
std::string& tooltip_msg);
void applyFunctorRecursively(LLFolderViewFunctor& functor);
virtual void applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor);
// Just apply this functor to the folder's immediate children.
void applyFunctorToChildren(LLFolderViewFunctor& functor);
// apply this functor to the folder's descendants.
void applyFunctorRecursively(LLFolderViewFunctor& functor);
virtual void openItem( void );
virtual BOOL addItem(LLFolderViewItem* item);
virtual BOOL addFolder( LLFolderViewFolder* folder);
// LLView functionality
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask );
virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask );
virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask );
virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,
EAcceptance* accept,
std::string& tooltip_msg);
BOOL handleDragAndDropToThisFolder(MASK mask, BOOL drop,
virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask,
BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,
EAcceptance* accept,
std::string& tooltip_msg);
BOOL handleDragAndDropToThisFolder(MASK mask,
BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,
EAcceptance* accept,
std::string& tooltip_msg);
virtual void draw();
time_t getCreationDate() const;
bool isTrash() const;
folders_t::const_iterator getFoldersBegin() const { return mFolders.begin(); }
folders_t::const_iterator getFoldersEnd() const { return mFolders.end(); }
folders_t::iterator getFoldersBegin() { return mFolders.begin(); }
folders_t::iterator getFoldersEnd() { return mFolders.end(); }
folders_t::size_type getFoldersCount() const { return mFolders.size(); }
items_t::const_iterator getItemsBegin() const { return mItems.begin(); }
items_t::const_iterator getItemsEnd() const { return mItems.end(); }
items_t::size_type getItemsCount() const { return mItems.size(); }
LLFolderViewFolder* getCommonAncestor(LLFolderViewItem* item_a, LLFolderViewItem* item_b, bool& reverse);
void gatherChildRangeExclusive(LLFolderViewItem* start, LLFolderViewItem* end, bool reverse, std::vector<LLFolderViewItem*>& items);
// internal functions for tracking folders and items separately
// use addToFolder() virtual method to ensure folders are always added to mFolders
// and not mItems
void addItem(LLFolderViewItem* item);
void addFolder( LLFolderViewFolder* folder);
//WARNING: do not call directly...use the appropriate LLFolderViewModel-derived class instead
template<typename SORT_FUNC> void sortFolders(const SORT_FUNC& func) { mFolders.sort(func); }
template<typename SORT_FUNC> void sortItems(const SORT_FUNC& func) { mItems.sort(func); }
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLFolderViewListenerFunctor
//
// This simple abstract base class can be used to applied to all
// listeners in a hierarchy.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class LLFolderViewListenerFunctor
{
public:
virtual ~LLFolderViewListenerFunctor() {}
virtual void operator()(LLFolderViewEventListener* listener) = 0;
};
#endif // LLFOLDERVIEWITEM_H

View File

@ -0,0 +1,68 @@
/**
* @file llfolderviewmodel.cpp
* @brief Implementation of the view model collection of classes.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* 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;
* version 2.1 of the License only.
*
* 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
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llfolderviewmodel.h"
#include "lltrans.h"
bool LLFolderViewModelCommon::needsSort(LLFolderViewModelItem* item)
{
return item->getSortVersion() < mTargetSortVersion;
}
std::string LLFolderViewModelCommon::getStatusText()
{
if (!contentsReady() || mFolderView->getViewModelItem()->getLastFilterGeneration() < getFilter().getCurrentGeneration())
{
return LLTrans::getString("Searching");
}
else
{
return getFilter().getEmptyLookupMessage();
}
}
void LLFolderViewModelCommon::filter()
{
getFilter().setFilterCount(llclamp(LLUI::sSettingGroups["config"]->getS32("FilterItemsPerFrame"), 1, 5000));
mFolderView->getViewModelItem()->filter(getFilter());
}
bool LLFolderViewModelItemCommon::hasFilterStringMatch()
{
return mStringMatchOffsetFilter != std::string::npos;
}
std::string::size_type LLFolderViewModelItemCommon::getFilterStringOffset()
{
return mStringMatchOffsetFilter;
}
std::string::size_type LLFolderViewModelItemCommon::getFilterStringSize()
{
return mRootViewModel.getFilter().getFilterStringSize();
}

View File

@ -0,0 +1,444 @@
/**
* @file llfolderviewmodel.h
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* 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;
* version 2.1 of the License only.
*
* 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
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LLFOLDERVIEWMODEL_H
#define LLFOLDERVIEWMODEL_H
#include "llfontgl.h" // just for StyleFlags enum
#include "llfolderview.h"
// These are grouping of inventory types.
// Order matters when sorting system folders to the top.
enum EInventorySortGroup
{
SG_SYSTEM_FOLDER,
SG_TRASH_FOLDER,
SG_NORMAL_FOLDER,
SG_ITEM
};
class LLFontGL;
class LLInventoryModel;
class LLMenuGL;
class LLUIImage;
class LLUUID;
class LLFolderViewItem;
class LLFolderViewFolder;
class LLFolderViewFilter
{
public:
enum EFilterModified
{
FILTER_NONE, // nothing to do, already filtered
FILTER_RESTART, // restart filtering from scratch
FILTER_LESS_RESTRICTIVE, // existing filtered items will certainly pass this filter
FILTER_MORE_RESTRICTIVE // if you didn't pass the previous filter, you definitely won't pass this one
};
public:
LLFolderViewFilter() {}
virtual ~LLFolderViewFilter() {}
// +-------------------------------------------------------------------+
// + Execution And Results
// +-------------------------------------------------------------------+
virtual bool check(const LLFolderViewModelItem* item) = 0;
virtual bool checkFolder(const LLFolderViewModelItem* folder) const = 0;
virtual void setEmptyLookupMessage(const std::string& message) = 0;
virtual std::string getEmptyLookupMessage() const = 0;
virtual bool showAllResults() const = 0;
virtual std::string::size_type getStringMatchOffset(LLFolderViewModelItem* item) const = 0;
virtual std::string::size_type getFilterStringSize() const = 0;
// +-------------------------------------------------------------------+
// + Status
// +-------------------------------------------------------------------+
virtual bool isActive() const = 0;
virtual bool isModified() const = 0;
virtual void clearModified() = 0;
virtual const std::string& getName() const = 0;
virtual const std::string& getFilterText() = 0;
//RN: this is public to allow system to externally force a global refilter
virtual void setModified(EFilterModified behavior = FILTER_RESTART) = 0;
// +-------------------------------------------------------------------+
// + Count
// +-------------------------------------------------------------------+
virtual void setFilterCount(S32 count) = 0;
virtual S32 getFilterCount() const = 0;
virtual void decrementFilterCount() = 0;
// +-------------------------------------------------------------------+
// + Default
// +-------------------------------------------------------------------+
virtual bool isDefault() const = 0;
virtual bool isNotDefault() const = 0;
virtual void markDefault() = 0;
virtual void resetDefault() = 0;
// +-------------------------------------------------------------------+
// + Generation
// +-------------------------------------------------------------------+
virtual S32 getCurrentGeneration() const = 0;
virtual S32 getFirstSuccessGeneration() const = 0;
virtual S32 getFirstRequiredGeneration() const = 0;
};
class LLFolderViewModelInterface
{
public:
virtual ~LLFolderViewModelInterface() {}
virtual void requestSortAll() = 0;
virtual void sort(class LLFolderViewFolder*) = 0;
virtual void filter() = 0;
virtual bool contentsReady() = 0;
virtual void setFolderView(LLFolderView* folder_view) = 0;
virtual LLFolderViewFilter& getFilter() = 0;
virtual const LLFolderViewFilter& getFilter() const = 0;
virtual std::string getStatusText() = 0;
virtual bool startDrag(std::vector<LLFolderViewModelItem*>& items) = 0;
};
// This is an abstract base class that users of the folderview classes
// would use to bridge the folder view with the underlying data
class LLFolderViewModelItem : public LLRefCount
{
public:
LLFolderViewModelItem() { }
virtual ~LLFolderViewModelItem() { }
virtual void update() {} //called when drawing
virtual const std::string& getName() const = 0;
virtual const std::string& getDisplayName() const = 0;
virtual const std::string& getSearchableName() const = 0;
virtual LLPointer<LLUIImage> getIcon() const = 0;
virtual LLPointer<LLUIImage> getIconOpen() const { return getIcon(); }
virtual LLPointer<LLUIImage> getIconOverlay() const { return NULL; }
virtual LLFontGL::StyleFlags getLabelStyle() const = 0;
virtual std::string getLabelSuffix() const = 0;
virtual void openItem( void ) = 0;
virtual void closeItem( void ) = 0;
virtual void selectItem(void) = 0;
virtual BOOL isItemRenameable() const = 0;
virtual BOOL renameItem(const std::string& new_name) = 0;
virtual BOOL isItemMovable( void ) const = 0; // Can be moved to another folder
virtual void move( LLFolderViewModelItem* parent_listener ) = 0;
virtual BOOL isItemRemovable( void ) const = 0; // Can be destroyed
virtual BOOL removeItem() = 0;
virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch) = 0;
virtual BOOL isItemCopyable() const = 0;
virtual BOOL copyToClipboard() const = 0;
virtual BOOL cutToClipboard() const = 0;
virtual BOOL isClipboardPasteable() const = 0;
virtual void pasteFromClipboard() = 0;
virtual void pasteLinkFromClipboard() = 0;
virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0;
virtual bool potentiallyVisible() = 0; // is the item definitely visible or we haven't made up our minds yet?
virtual bool filter( LLFolderViewFilter& filter) = 0;
virtual bool passedFilter(S32 filter_generation = -1) = 0;
virtual bool descendantsPassedFilter(S32 filter_generation = -1) = 0;
virtual void setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0) = 0;
virtual void setPassedFolderFilter(bool passed, S32 filter_generation) = 0;
virtual void dirtyFilter() = 0;
virtual bool hasFilterStringMatch() = 0;
virtual std::string::size_type getFilterStringOffset() = 0;
virtual std::string::size_type getFilterStringSize() = 0;
virtual S32 getLastFilterGeneration() const = 0;
virtual bool hasChildren() const = 0;
virtual void addChild(LLFolderViewModelItem* child) = 0;
virtual void removeChild(LLFolderViewModelItem* child) = 0;
// This method will be called to determine if a drop can be
// performed, and will set drop to TRUE if a drop is
// requested. Returns TRUE if a drop is possible/happened,
// otherwise FALSE.
virtual BOOL dragOrDrop(MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,
std::string& tooltip_msg) = 0;
virtual void requestSort() = 0;
virtual S32 getSortVersion() = 0;
virtual void setSortVersion(S32 version) = 0;
virtual void setParent(LLFolderViewModelItem* parent) = 0;
virtual bool hasParent() = 0;
protected:
friend class LLFolderViewItem;
virtual void setFolderViewItem(LLFolderViewItem* folder_view_item) = 0;
};
class LLFolderViewModelItemCommon : public LLFolderViewModelItem
{
public:
LLFolderViewModelItemCommon(LLFolderViewModelInterface& root_view_model)
: mSortVersion(-1),
mPassedFilter(true),
mPassedFolderFilter(true),
mStringMatchOffsetFilter(std::string::npos),
mStringFilterSize(0),
mFolderViewItem(NULL),
mLastFilterGeneration(-1),
mLastFolderFilterGeneration(-1),
mMostFilteredDescendantGeneration(-1),
mParent(NULL),
mRootViewModel(root_view_model)
{
mChildren.clear();
}
void requestSort() { mSortVersion = -1; }
S32 getSortVersion() { return mSortVersion; }
void setSortVersion(S32 version) { mSortVersion = version;}
S32 getLastFilterGeneration() const { return mLastFilterGeneration; }
S32 getLastFolderFilterGeneration() const { return mLastFolderFilterGeneration; }
void dirtyFilter()
{
mLastFilterGeneration = -1;
mLastFolderFilterGeneration = -1;
// bubble up dirty flag all the way to root
if (mParent)
{
mParent->dirtyFilter();
}
}
bool hasFilterStringMatch();
std::string::size_type getFilterStringOffset();
std::string::size_type getFilterStringSize();
typedef std::list<LLFolderViewModelItem*> child_list_t;
virtual void addChild(LLFolderViewModelItem* child)
{
// Avoid duplicates: bail out if that child is already present in the list
// Note: this happens when models are created before views
child_list_t::const_iterator iter;
for (iter = mChildren.begin(); iter != mChildren.end(); iter++)
{
if (child == *iter)
{
return;
}
}
mChildren.push_back(child);
child->setParent(this);
dirtyFilter();
requestSort();
}
virtual void removeChild(LLFolderViewModelItem* child)
{
mChildren.remove(child);
child->setParent(NULL);
dirtyFilter();
}
virtual void clearChildren()
{
// As this is cleaning the whole list of children wholesale, we do need to delete the pointed objects
// This is different and not equivalent to calling removeChild() on each child
std::for_each(mChildren.begin(), mChildren.end(), DeletePointer());
mChildren.clear();
dirtyFilter();
}
child_list_t::const_iterator getChildrenBegin() const { return mChildren.begin(); }
child_list_t::const_iterator getChildrenEnd() const { return mChildren.end(); }
child_list_t::size_type getChildrenCount() const { return mChildren.size(); }
void setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0)
{
mPassedFilter = passed;
mLastFilterGeneration = filter_generation;
mStringMatchOffsetFilter = string_offset;
mStringFilterSize = string_size;
}
void setPassedFolderFilter(bool passed, S32 filter_generation)
{
mPassedFolderFilter = passed;
mLastFolderFilterGeneration = filter_generation;
}
virtual bool potentiallyVisible()
{
return passedFilter() // we've passed the filter
|| getLastFilterGeneration() < mRootViewModel.getFilter().getFirstSuccessGeneration() // or we don't know yet
|| descendantsPassedFilter();
}
virtual bool passedFilter(S32 filter_generation = -1)
{
if (filter_generation < 0)
filter_generation = mRootViewModel.getFilter().getFirstSuccessGeneration();
bool passed_folder_filter = mPassedFolderFilter && mLastFolderFilterGeneration >= filter_generation;
bool passed_filter = mPassedFilter && mLastFilterGeneration >= filter_generation;
return passed_folder_filter
&& (descendantsPassedFilter(filter_generation)
|| passed_filter);
}
virtual bool descendantsPassedFilter(S32 filter_generation = -1)
{
if (filter_generation < 0) filter_generation = mRootViewModel.getFilter().getFirstSuccessGeneration();
return mMostFilteredDescendantGeneration >= filter_generation;
}
protected:
virtual void setParent(LLFolderViewModelItem* parent) { mParent = parent; }
virtual bool hasParent() { return mParent != NULL; }
S32 mSortVersion;
bool mPassedFilter;
bool mPassedFolderFilter;
std::string::size_type mStringMatchOffsetFilter;
std::string::size_type mStringFilterSize;
S32 mLastFilterGeneration;
S32 mLastFolderFilterGeneration;
S32 mMostFilteredDescendantGeneration;
child_list_t mChildren;
LLFolderViewModelItem* mParent;
LLFolderViewModelInterface& mRootViewModel;
void setFolderViewItem(LLFolderViewItem* folder_view_item) { mFolderViewItem = folder_view_item;}
LLFolderViewItem* mFolderViewItem;
};
class LLFolderViewModelCommon : public LLFolderViewModelInterface
{
public:
LLFolderViewModelCommon()
: mTargetSortVersion(0),
mFolderView(NULL)
{}
virtual void requestSortAll()
{
// sort everything
mTargetSortVersion++;
}
virtual std::string getStatusText();
virtual void filter();
void setFolderView(LLFolderView* folder_view) { mFolderView = folder_view;}
protected:
bool needsSort(class LLFolderViewModelItem* item);
S32 mTargetSortVersion;
LLFolderView* mFolderView;
};
template <typename SORT_TYPE, typename ITEM_TYPE, typename FOLDER_TYPE, typename FILTER_TYPE>
class LLFolderViewModel : public LLFolderViewModelCommon
{
public:
LLFolderViewModel(){}
virtual ~LLFolderViewModel() {}
typedef SORT_TYPE SortType;
typedef ITEM_TYPE ItemType;
typedef FOLDER_TYPE FolderType;
typedef FILTER_TYPE FilterType;
virtual SortType& getSorter() { return mSorter; }
virtual const SortType& getSorter() const { return mSorter; }
virtual void setSorter(const SortType& sorter) { mSorter = sorter; requestSortAll(); }
virtual FilterType& getFilter() { return mFilter; }
virtual const FilterType& getFilter() const { return mFilter; }
virtual void setFilter(const FilterType& filter) { mFilter = filter; }
// By default, we assume the content is available. If a network fetch mechanism is implemented for the model,
// this method needs to be overloaded and return the relevant fetch status.
virtual bool contentsReady() { return true; }
struct ViewModelCompare
{
ViewModelCompare(const SortType& sorter)
: mSorter(sorter)
{}
bool operator () (const LLFolderViewItem* a, const LLFolderViewItem* b) const
{
return mSorter(static_cast<const ItemType*>(a->getViewModelItem()), static_cast<const ItemType*>(b->getViewModelItem()));
}
bool operator () (const LLFolderViewFolder* a, const LLFolderViewFolder* b) const
{
return mSorter(static_cast<const ItemType*>(a->getViewModelItem()), static_cast<const ItemType*>(b->getViewModelItem()));
}
const SortType& mSorter;
};
void sort(LLFolderViewFolder* folder)
{
if (needsSort(folder->getViewModelItem()))
{
folder->sortFolders(ViewModelCompare(getSorter()));
folder->sortItems(ViewModelCompare(getSorter()));
folder->getViewModelItem()->setSortVersion(mTargetSortVersion);
folder->requestArrange();
}
}
protected:
SortType mSorter;
FilterType mFilter;
};
#endif // LLFOLDERVIEWMODEL_H

View File

@ -32,11 +32,10 @@
#include "lllocalcliprect.h"
#include "llpanel.h"
#include "llresizebar.h"
#include "llcriticaldamp.h"
#include "boost/foreach.hpp"
static const F32 MIN_FRACTIONAL_SIZE = 0.0f;
static const F32 MIN_FRACTIONAL_SIZE = 0.00001f;
static const F32 MAX_FRACTIONAL_SIZE = 1.f;
static LLDefaultChildRegistry::Register<LLLayoutStack> register_layout_stack("layout_stack");
@ -71,7 +70,7 @@ LLLayoutPanel::LLLayoutPanel(const Params& p)
mCollapseAmt(0.f),
mVisibleAmt(1.f), // default to fully visible
mResizeBar(NULL),
mFractionalSize(MIN_FRACTIONAL_SIZE),
mFractionalSize(0.f),
mTargetDim(0),
mIgnoreReshape(false),
mOrientation(LLLayoutStack::HORIZONTAL)
@ -520,7 +519,7 @@ void LLLayoutStack::updateFractionalSizes()
{
if (panelp->mAutoResize)
{
total_resizable_dim += llmax(0, panelp->getLayoutDim() - panelp->getRelevantMinDim());
total_resizable_dim += llmax(MIN_FRACTIONAL_SIZE, (F32)(panelp->getLayoutDim() - panelp->getRelevantMinDim()));
}
}
@ -671,12 +670,12 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
S32 new_dim = (mOrientation == HORIZONTAL)
? new_rect.getWidth()
: new_rect.getHeight();
S32 delta_dim = new_dim - resized_panel->getVisibleDim();
if (delta_dim == 0) return;
S32 delta_panel_dim = new_dim - resized_panel->getVisibleDim();
if (delta_panel_dim == 0) return;
F32 total_visible_fraction = 0.f;
F32 delta_auto_resize_headroom = 0.f;
F32 original_auto_resize_headroom = 0.f;
F32 old_auto_resize_headroom = 0.f;
LLLayoutPanel* other_resize_panel = NULL;
LLLayoutPanel* following_panel = NULL;
@ -685,7 +684,7 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
{
if (panelp->mAutoResize)
{
original_auto_resize_headroom += (F32)(panelp->mTargetDim - panelp->getRelevantMinDim());
old_auto_resize_headroom += (F32)(panelp->mTargetDim - panelp->getRelevantMinDim());
if (panelp->getVisible() && !panelp->mCollapsed)
{
total_visible_fraction += panelp->mFractionalSize;
@ -703,25 +702,24 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
}
}
if (resized_panel->mAutoResize)
{
if (!other_resize_panel || !other_resize_panel->mAutoResize)
{
delta_auto_resize_headroom += delta_dim;
delta_auto_resize_headroom += delta_panel_dim;
}
}
else
{
if (!other_resize_panel || other_resize_panel->mAutoResize)
{
delta_auto_resize_headroom -= delta_dim;
delta_auto_resize_headroom -= delta_panel_dim;
}
}
F32 fraction_given_up = 0.f;
F32 fraction_remaining = 1.f;
F32 updated_auto_resize_headroom = original_auto_resize_headroom + delta_auto_resize_headroom;
F32 new_auto_resize_headroom = old_auto_resize_headroom + delta_auto_resize_headroom;
enum
{
@ -733,7 +731,14 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
BOOST_FOREACH(LLLayoutPanel* panelp, mPanels)
{
if (!panelp->getVisible() || panelp->mCollapsed) continue;
if (!panelp->getVisible() || panelp->mCollapsed)
{
if (panelp->mAutoResize)
{
fraction_remaining -= panelp->mFractionalSize;
}
continue;
}
if (panelp == resized_panel)
{
@ -745,9 +750,9 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
case BEFORE_RESIZED_PANEL:
if (panelp->mAutoResize)
{ // freeze current size as fraction of overall auto_resize space
F32 fractional_adjustment_factor = updated_auto_resize_headroom == 0.f
F32 fractional_adjustment_factor = new_auto_resize_headroom == 0.f
? 1.f
: original_auto_resize_headroom / updated_auto_resize_headroom;
: old_auto_resize_headroom / new_auto_resize_headroom;
F32 new_fractional_size = llclamp(panelp->mFractionalSize * fractional_adjustment_factor,
MIN_FRACTIONAL_SIZE,
MAX_FRACTIONAL_SIZE);
@ -764,9 +769,9 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
case RESIZED_PANEL:
if (panelp->mAutoResize)
{ // freeze new size as fraction
F32 new_fractional_size = (updated_auto_resize_headroom == 0.f)
F32 new_fractional_size = (new_auto_resize_headroom == 0.f)
? MAX_FRACTIONAL_SIZE
: llclamp(total_visible_fraction * (F32)(new_dim - panelp->getRelevantMinDim()) / updated_auto_resize_headroom, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE);
: llclamp(total_visible_fraction * (F32)(new_dim - panelp->getRelevantMinDim()) / new_auto_resize_headroom, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE);
fraction_given_up -= new_fractional_size - panelp->mFractionalSize;
fraction_remaining -= panelp->mFractionalSize;
panelp->mFractionalSize = new_fractional_size;
@ -789,8 +794,13 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
}
else
{
if (new_auto_resize_headroom < 1.f)
{
new_auto_resize_headroom = 1.f;
}
F32 new_fractional_size = llclamp(total_visible_fraction * (F32)(panelp->mTargetDim - panelp->getRelevantMinDim() + delta_auto_resize_headroom)
/ updated_auto_resize_headroom,
/ new_auto_resize_headroom,
MIN_FRACTIONAL_SIZE,
MAX_FRACTIONAL_SIZE);
fraction_given_up -= new_fractional_size - panelp->mFractionalSize;
@ -799,7 +809,7 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
}
else
{
panelp->mTargetDim -= delta_dim;
panelp->mTargetDim -= delta_panel_dim;
}
which_panel = AFTER_RESIZED_PANEL;
break;
@ -815,7 +825,7 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&
}
}
updateLayout();
normalizeFractionalSizes();
//normalizeFractionalSizes();
}
void LLLayoutStack::reshape(S32 width, S32 height, BOOL called_from_parent)

View File

@ -29,6 +29,7 @@
#define LL_LLLAYOUTSTACK_H
#include "llpanel.h"
#include "llresizebar.h"
class LLLayoutPanel;
@ -178,6 +179,9 @@ public:
F32 getAutoResizeFactor() const;
F32 getVisibleAmount() const;
S32 getVisibleDim() const;
LLResizeBar* getResizeBar() { return mResizeBar; }
bool isCollapsed() const { return mCollapsed;}
void setOrientation(LLLayoutStack::ELayoutOrientation orientation);
void storeOriginalDim();

View File

@ -157,8 +157,7 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
mHighlightColor(p.highlight_color()),
mPreeditBgColor(p.preedit_bg_color()),
mGLFont(p.font),
mContextMenuHandle(),
mAutoreplaceCallback()
mContextMenuHandle()
{
llassert( mMaxLengthBytes > 0 );
@ -971,12 +970,6 @@ void LLLineEditor::addChar(const llwchar uni_char)
LLUI::reportBadKeystroke();
}
if (!mReadOnly && mAutoreplaceCallback != NULL)
{
// call callback
mAutoreplaceCallback(mText, mCursorPos);
}
getWindow()->hideCursorUntilMouseMove();
}
@ -2022,8 +2015,8 @@ void LLLineEditor::draw()
LLRect screen_pos = calcScreenRect();
LLCoordGL ime_pos( screen_pos.mLeft + pixels_after_scroll, screen_pos.mTop - lineeditor_v_pad );
ime_pos.mX = (S32) (ime_pos.mX * LLUI::getScaleFactor().mV[VX]);
ime_pos.mY = (S32) (ime_pos.mY * LLUI::getScaleFactor().mV[VY]);
ime_pos.mX = (S32) (ime_pos.mX * LLUI::sGLScaleFactor.mV[VX]);
ime_pos.mY = (S32) (ime_pos.mY * LLUI::sGLScaleFactor.mV[VY]);
getWindow()->setLanguageTextInput( ime_pos );
}
}
@ -2570,7 +2563,7 @@ void LLLineEditor::markAsPreedit(S32 position, S32 length)
S32 LLLineEditor::getPreeditFontSize() const
{
return llround(mGLFont->getLineHeight() * LLUI::getScaleFactor().mV[VY]);
return llround(mGLFont->getLineHeight() * LLUI::sGLScaleFactor.mV[VY]);
}
void LLLineEditor::setReplaceNewlinesWithSpaces(BOOL replace)

View File

@ -189,9 +189,6 @@ public:
virtual BOOL setTextArg( const std::string& key, const LLStringExplicit& text );
virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text );
typedef boost::function<void(LLUIString&, S32&)> autoreplace_callback_t;
autoreplace_callback_t mAutoreplaceCallback;
void setAutoreplaceCallback(autoreplace_callback_t cb) { mAutoreplaceCallback = cb; }
void setLabel(const LLStringExplicit &new_label) { mLabel = new_label; }
const std::string& getLabel() { return mLabel.getString(); }

View File

@ -52,7 +52,7 @@ LLLoadingIndicator::LLLoadingIndicator(const Params& p)
void LLLoadingIndicator::initFromParams(const Params& p)
{
BOOST_FOREACH(LLUIImage* image, p.images.image)
BOOST_FOREACH(LLUIImage* image, p.images().image)
{
mImages.push_back(image);
}

View File

@ -51,7 +51,7 @@ class LLLoadingIndicator
LOG_CLASS(LLLoadingIndicator);
public:
struct Images : public LLInitParam::BatchBlock<Images>
struct Images : public LLInitParam::Block<Images>
{
Multiple<LLUIImage*> image;
@ -62,8 +62,8 @@ public:
struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
{
Optional<F32> images_per_sec;
Optional<Images> images;
Optional<F32> images_per_sec;
Optional<Atomic<Images> > images;
Params()
: images_per_sec("images_per_sec", 1.0f),

View File

@ -33,7 +33,7 @@
LLScreenClipRect::LLScreenClipRect(const LLRect& rect, BOOL enabled)
: mScissorState(GL_SCISSOR_TEST),
: mScissorState(GL_SCISSOR_TEST),
mEnabled(enabled)
{
if (mEnabled)
@ -88,10 +88,10 @@ void LLScreenClipRect::updateScissorRegion()
LLRect rect = sClipRectStack.top();
stop_glerror();
S32 x,y,w,h;
x = llfloor(rect.mLeft * LLUI::getScaleFactor().mV[VX]);
y = llfloor(rect.mBottom * LLUI::getScaleFactor().mV[VY]);
w = llmax(0, llceil(rect.getWidth() * LLUI::getScaleFactor().mV[VX])) + 1;
h = llmax(0, llceil(rect.getHeight() * LLUI::getScaleFactor().mV[VY])) + 1;
x = llfloor(rect.mLeft * LLUI::sGLScaleFactor.mV[VX]);
y = llfloor(rect.mBottom * LLUI::sGLScaleFactor.mV[VY]);
w = llmax(0, llceil(rect.getWidth() * LLUI::sGLScaleFactor.mV[VX])) + 1;
h = llmax(0, llceil(rect.getHeight() * LLUI::sGLScaleFactor.mV[VY])) + 1;
glScissor( x,y,w,h );
stop_glerror();
}
@ -100,10 +100,10 @@ void LLScreenClipRect::updateScissorRegion()
// LLLocalClipRect
//---------------------------------------------------------------------------
LLLocalClipRect::LLLocalClipRect(const LLRect& rect, BOOL enabled /* = TRUE */)
: LLScreenClipRect(LLRect(rect.mLeft + LLFontGL::sCurOrigin.mX,
rect.mTop + LLFontGL::sCurOrigin.mY,
rect.mRight + LLFontGL::sCurOrigin.mX,
rect.mBottom + LLFontGL::sCurOrigin.mY), enabled)
: LLScreenClipRect(LLRect(rect.mLeft + LLFontGL::sCurOrigin.mX,
rect.mTop + LLFontGL::sCurOrigin.mY,
rect.mRight + LLFontGL::sCurOrigin.mX,
rect.mBottom + LLFontGL::sCurOrigin.mY), enabled)
{}
LLLocalClipRect::~LLLocalClipRect()

View File

@ -44,33 +44,27 @@ void LLMenuButton::MenuPositions::declareValues()
LLMenuButton::Params::Params()
: menu_filename("menu_filename"),
position("position", MP_BOTTOM_LEFT)
position("menu_position", MP_BOTTOM_LEFT)
{
addSynonym(position, "position");
}
LLMenuButton::LLMenuButton(const LLMenuButton::Params& p)
: LLButton(p),
mIsMenuShown(false),
mMenuPosition(p.position)
mMenuPosition(p.position),
mOwnMenu(false)
{
std::string menu_filename = p.menu_filename;
if (!menu_filename.empty())
{
LLToggleableMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(menu_filename, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
if (!menu)
{
llwarns << "Error loading menu_button menu" << llendl;
return;
}
setMenu(menu_filename, mMenuPosition);
updateMenuOrigin();
}
menu->setVisibilityChangeCallback(boost::bind(&LLMenuButton::onMenuVisibilityChange, this, _2));
mMenuHandle = menu->getHandle();
updateMenuOrigin();
}
LLMenuButton::~LLMenuButton()
{
cleanup();
}
boost::signals2::connection LLMenuButton::setMouseDownCallback( const mouse_signal_t::slot_type& cb )
@ -80,9 +74,7 @@ boost::signals2::connection LLMenuButton::setMouseDownCallback( const mouse_sign
void LLMenuButton::hideMenu()
{
if(mMenuHandle.isDead()) return;
LLToggleableMenu* menu = dynamic_cast<LLToggleableMenu*>(mMenuHandle.get());
LLToggleableMenu* menu = getMenu();
if (menu)
{
menu->setVisible(FALSE);
@ -94,19 +86,39 @@ LLToggleableMenu* LLMenuButton::getMenu()
return dynamic_cast<LLToggleableMenu*>(mMenuHandle.get());
}
void LLMenuButton::setMenu(LLToggleableMenu* menu, EMenuPosition position /*MP_TOP_LEFT*/)
void LLMenuButton::setMenu(const std::string& menu_filename, EMenuPosition position /*MP_TOP_LEFT*/)
{
if (menu_filename.empty())
{
return;
}
LLToggleableMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(menu_filename, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
if (!menu)
{
llwarns << "Error loading menu_button menu" << llendl;
return;
}
setMenu(menu, position, true);
}
void LLMenuButton::setMenu(LLToggleableMenu* menu, EMenuPosition position /*MP_TOP_LEFT*/, bool take_ownership /*false*/)
{
if (!menu) return;
cleanup(); // destroy the previous memnu if we own it
mMenuHandle = menu->getHandle();
mMenuPosition = position;
mOwnMenu = take_ownership;
menu->setVisibilityChangeCallback(boost::bind(&LLMenuButton::onMenuVisibilityChange, this, _2));
}
BOOL LLMenuButton::handleKeyHere(KEY key, MASK mask )
{
if (mMenuHandle.isDead()) return FALSE;
if (!getMenu()) return FALSE;
if( KEY_RETURN == key && mask == MASK_NONE && !gKeyboard->getKeyRepeated(key))
{
@ -118,7 +130,7 @@ BOOL LLMenuButton::handleKeyHere(KEY key, MASK mask )
return TRUE;
}
LLToggleableMenu* menu = dynamic_cast<LLToggleableMenu*>(mMenuHandle.get());
LLToggleableMenu* menu = getMenu();
if (menu && menu->getVisible() && key == KEY_ESCAPE && mask == MASK_NONE)
{
menu->setVisible(FALSE);
@ -139,9 +151,12 @@ BOOL LLMenuButton::handleMouseDown(S32 x, S32 y, MASK mask)
void LLMenuButton::toggleMenu()
{
if(mMenuHandle.isDead()) return;
if (mValidateSignal && !(*mValidateSignal)(this, LLSD()))
{
return;
}
LLToggleableMenu* menu = dynamic_cast<LLToggleableMenu*>(mMenuHandle.get());
LLToggleableMenu* menu = getMenu();
if (!menu) return;
// Store the button rectangle to toggle menu visibility if a mouse event
@ -170,7 +185,8 @@ void LLMenuButton::toggleMenu()
void LLMenuButton::updateMenuOrigin()
{
if (mMenuHandle.isDead()) return;
LLToggleableMenu* menu = getMenu();
if (!menu) return;
LLRect rect = getRect();
@ -179,12 +195,12 @@ void LLMenuButton::updateMenuOrigin()
case MP_TOP_LEFT:
{
mX = rect.mLeft;
mY = rect.mTop + mMenuHandle.get()->getRect().getHeight();
mY = rect.mTop + menu->getRect().getHeight();
break;
}
case MP_TOP_RIGHT:
{
const LLRect& menu_rect = mMenuHandle.get()->getRect();
const LLRect& menu_rect = menu->getRect();
mX = rect.mRight - menu_rect.getWidth();
mY = rect.mTop + menu_rect.getHeight();
break;
@ -211,3 +227,11 @@ void LLMenuButton::onMenuVisibilityChange(const LLSD& param)
mIsMenuShown = false;
}
}
void LLMenuButton::cleanup()
{
if (mMenuHandle.get() && mOwnMenu)
{
mMenuHandle.get()->die();
}
}

View File

@ -34,6 +34,8 @@ class LLToggleableMenu;
class LLMenuButton
: public LLButton
{
LOG_CLASS(LLMenuButton);
public:
typedef enum e_menu_position
{
@ -53,7 +55,7 @@ public:
{
// filename for it's toggleable menu
Optional<std::string> menu_filename;
Optional<EMenuPosition> position;
Optional<EMenuPosition, MenuPositions> position;
Params();
};
@ -68,13 +70,15 @@ public:
void hideMenu();
LLToggleableMenu* getMenu();
void setMenu(LLToggleableMenu* menu, EMenuPosition position = MP_TOP_LEFT);
void setMenu(const std::string& menu_filename, EMenuPosition position = MP_TOP_LEFT);
void setMenu(LLToggleableMenu* menu, EMenuPosition position = MP_TOP_LEFT, bool take_ownership = false);
void setMenuPosition(EMenuPosition position) { mMenuPosition = position; }
protected:
friend class LLUICtrlFactory;
LLMenuButton(const Params&);
~LLMenuButton();
void toggleMenu();
void updateMenuOrigin();
@ -82,11 +86,14 @@ protected:
void onMenuVisibilityChange(const LLSD& param);
private:
void cleanup();
LLHandle<LLView> mMenuHandle;
bool mIsMenuShown;
EMenuPosition mMenuPosition;
S32 mX;
S32 mY;
bool mOwnMenu; // true if we manage the menu lifetime
};

View File

@ -593,12 +593,12 @@ BOOL LLMenuItemSeparatorGL::handleMouseDown(S32 x, S32 y, MASK mask)
{
// the menu items are in the child list in bottom up order
LLView* prev_menu_item = parent_menu->findNextSibling(this);
return prev_menu_item ? prev_menu_item->handleMouseDown(x, prev_menu_item->getRect().getHeight(), mask) : FALSE;
return (prev_menu_item && prev_menu_item->getVisible() && prev_menu_item->getEnabled()) ? prev_menu_item->handleMouseDown(x, prev_menu_item->getRect().getHeight(), mask) : FALSE;
}
else
{
LLView* next_menu_item = parent_menu->findPrevSibling(this);
return next_menu_item ? next_menu_item->handleMouseDown(x, 0, mask) : FALSE;
return (next_menu_item && next_menu_item->getVisible() && next_menu_item->getEnabled()) ? next_menu_item->handleMouseDown(x, 0, mask) : FALSE;
}
}
@ -608,12 +608,12 @@ BOOL LLMenuItemSeparatorGL::handleMouseUp(S32 x, S32 y, MASK mask)
if (y > getRect().getHeight() / 2)
{
LLView* prev_menu_item = parent_menu->findNextSibling(this);
return prev_menu_item ? prev_menu_item->handleMouseUp(x, prev_menu_item->getRect().getHeight(), mask) : FALSE;
return (prev_menu_item && prev_menu_item->getVisible() && prev_menu_item->getEnabled()) ? prev_menu_item->handleMouseUp(x, prev_menu_item->getRect().getHeight(), mask) : FALSE;
}
else
{
LLView* next_menu_item = parent_menu->findPrevSibling(this);
return next_menu_item ? next_menu_item->handleMouseUp(x, 0, mask) : FALSE;
return (next_menu_item && next_menu_item->getVisible() && next_menu_item->getEnabled()) ? next_menu_item->handleMouseUp(x, 0, mask) : FALSE;
}
}
@ -1751,35 +1751,50 @@ void LLMenuGL::setCanTearOff(BOOL tear_off)
bool LLMenuGL::addChild(LLView* view, S32 tab_group)
{
if (LLMenuGL* menup = dynamic_cast<LLMenuGL*>(view))
LLMenuGL* menup = dynamic_cast<LLMenuGL*>(view);
if (menup)
{
appendMenu(menup);
return true;
return appendMenu(menup);
}
else if (LLMenuItemGL* itemp = dynamic_cast<LLMenuItemGL*>(view))
LLMenuItemGL* itemp = dynamic_cast<LLMenuItemGL*>(view);
if (itemp)
{
append(itemp);
return true;
return append(itemp);
}
return false;
}
// Used in LLContextMenu and in LLTogleableMenu
// to add an item of context menu branch
// Add an item to the context menu branch
bool LLMenuGL::addContextChild(LLView* view, S32 tab_group)
{
LLContextMenu* context = dynamic_cast<LLContextMenu*>(view);
if (context)
{
return appendContextSubMenu(context);
}
LLMenuItemSeparatorGL* separator = dynamic_cast<LLMenuItemSeparatorGL*>(view);
if (separator)
{
return append(separator);
}
LLMenuItemGL* item = dynamic_cast<LLMenuItemGL*>(view);
if (item)
{
return append(item);
}
LLMenuGL* menup = dynamic_cast<LLMenuGL*>(view);
if (menup)
{
return appendMenu(menup);
}
return false;
}
@ -2446,6 +2461,56 @@ void LLMenuGL::empty( void )
deleteAllChildren();
}
// erase group of items from menu
void LLMenuGL::erase( S32 begin, S32 end, bool arrange/* = true*/)
{
S32 items = mItems.size();
if ( items == 0 || begin >= end || begin < 0 || end > items )
{
return;
}
item_list_t::iterator start_position = mItems.begin();
std::advance(start_position, begin);
item_list_t::iterator end_position = mItems.begin();
std::advance(end_position, end);
for (item_list_t::iterator position_iter = start_position; position_iter != end_position; position_iter++)
{
LLUICtrl::removeChild(*position_iter);
}
mItems.erase(start_position, end_position);
if (arrange)
{
needsArrange();
}
}
// add new item at position
void LLMenuGL::insert( S32 position, LLView * ctrl, bool arrange /*= true*/ )
{
LLMenuItemGL * item = dynamic_cast<LLMenuItemGL *>(ctrl);
if (NULL == item || position < 0 || position >= mItems.size())
{
return;
}
item_list_t::iterator position_iter = mItems.begin();
std::advance(position_iter, position);
mItems.insert(position_iter, item);
LLUICtrl::addChild(item);
if (arrange)
{
needsArrange();
}
}
// Adjust rectangle of the menu
void LLMenuGL::setLeftAndBottom(S32 left, S32 bottom)
{
@ -2487,7 +2552,8 @@ BOOL LLMenuGL::append( LLMenuItemGL* item )
// add a separator to this menu
BOOL LLMenuGL::addSeparator()
{
LLMenuItemGL* separator = new LLMenuItemSeparatorGL();
LLMenuItemSeparatorGL::Params p;
LLMenuItemGL* separator = LLUICtrlFactory::create<LLMenuItemSeparatorGL>(p);
return addChild(separator);
}
@ -3080,7 +3146,17 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y)
const S32 CURSOR_HEIGHT = 22; // Approximate "normal" cursor size
const S32 CURSOR_WIDTH = 12;
if(menu->getChildList()->empty())
//Do not show menu if all menu items are disabled
BOOL item_enabled = false;
for (LLView::child_list_t::const_iterator itor = menu->getChildList()->begin();
itor != menu->getChildList()->end();
++itor)
{
LLView *menu_item = (*itor);
item_enabled = item_enabled || menu_item->getEnabled();
}
if(menu->getChildList()->empty() || !item_enabled)
{
return;
}
@ -4039,11 +4115,6 @@ BOOL LLContextMenu::handleRightMouseUp( S32 x, S32 y, MASK mask )
return result;
}
void LLContextMenu::draw()
{
LLMenuGL::draw();
}
bool LLContextMenu::addChild(LLView* view, S32 tab_group)
{
return addContextChild(view, tab_group);

View File

@ -478,6 +478,12 @@ public:
// remove all items on the menu
void empty( void );
// erase group of items from menu
void erase( S32 begin, S32 end, bool arrange = true );
// add new item at position
void insert( S32 begin, LLView * ctrl, bool arrange = true );
void setItemLastSelected(LLMenuItemGL* item); // must be in menu
U32 getItemCount(); // number of menu items
LLMenuItemGL* getItem(S32 number); // 0 = first item
@ -675,8 +681,6 @@ public:
// can't set visibility directly, must call show or hide
virtual void setVisible (BOOL visible);
virtual void draw ();
virtual void show (S32 x, S32 y, LLView* spawning_view = NULL);
virtual void hide ();
@ -698,7 +702,6 @@ protected:
LLHandle<LLView> mSpawningViewHandle;
};
//-----------------------------------------------------------------------------
// class LLContextMenuBranch
// A branch to another context menu

View File

@ -41,8 +41,8 @@ LLMultiFloater::LLMultiFloater(const LLSD& key, const LLFloater::Params& params)
mTabContainer(NULL),
mTabPos(LLTabContainer::TOP),
mAutoResize(TRUE),
mOrigMinWidth(0),
mOrigMinHeight(0)
mOrigMinWidth(params.min_width),
mOrigMinHeight(params.min_height)
{
}
@ -173,7 +173,7 @@ void LLMultiFloater::addFloater(LLFloater* floaterp, BOOL select_added_floater,
else if (floaterp->getHost())
{
// floaterp is hosted by somebody else and
// this is adding it, so remove it from it's old host
// this is adding it, so remove it from its old host
floaterp->getHost()->removeFloater(floaterp);
}
else if (floaterp->getParent() == gFloaterView)
@ -188,11 +188,13 @@ void LLMultiFloater::addFloater(LLFloater* floaterp, BOOL select_added_floater,
floater_data.mHeight = floaterp->getRect().getHeight();
floater_data.mCanMinimize = floaterp->isMinimizeable();
floater_data.mCanResize = floaterp->isResizable();
floater_data.mSaveRect = floaterp->mSaveRect;
// remove minimize and close buttons
floaterp->setCanMinimize(FALSE);
floaterp->setCanResize(FALSE);
floaterp->setCanDrag(FALSE);
floaterp->mSaveRect = FALSE;
floaterp->storeRectControl();
// avoid double rendering of floater background (makes it more opaque)
floaterp->setBackgroundVisible(FALSE);
@ -291,6 +293,7 @@ void LLMultiFloater::removeFloater(LLFloater* floaterp)
{
LLFloaterData& floater_data = found_data_it->second;
floaterp->setCanMinimize(floater_data.mCanMinimize);
floaterp->mSaveRect = floater_data.mSaveRect;
if (!floater_data.mCanResize)
{
// restore original size
@ -468,23 +471,12 @@ BOOL LLMultiFloater::postBuild()
void LLMultiFloater::updateResizeLimits()
{
static LLUICachedControl<S32> tabcntr_close_btn_size ("UITabCntrCloseBtnSize", 0);
const LLFloater::Params& default_params = LLFloater::getDefaultParams();
S32 floater_header_size = default_params.header_height;
S32 tabcntr_header_height = LLPANEL_BORDER_WIDTH + tabcntr_close_btn_size;
// initialize minimum size constraint to the original xml values.
S32 new_min_width = mOrigMinWidth;
S32 new_min_height = mOrigMinHeight;
// possibly increase minimum size constraint due to children's minimums.
for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx)
{
LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(tab_idx);
if (floaterp)
{
new_min_width = llmax(new_min_width, floaterp->getMinWidth() + LLPANEL_BORDER_WIDTH * 2);
new_min_height = llmax(new_min_height, floaterp->getMinHeight() + floater_header_size + tabcntr_header_height);
}
}
computeResizeLimits(new_min_width, new_min_height);
setResizeLimits(new_min_width, new_min_height);
S32 cur_height = getRect().getHeight();
@ -510,3 +502,22 @@ void LLMultiFloater::updateResizeLimits()
gFloaterView->adjustToFitScreen(this, TRUE);
}
}
void LLMultiFloater::computeResizeLimits(S32& new_min_width, S32& new_min_height)
{
static LLUICachedControl<S32> tabcntr_close_btn_size ("UITabCntrCloseBtnSize", 0);
const LLFloater::Params& default_params = LLFloater::getDefaultParams();
S32 floater_header_size = default_params.header_height;
S32 tabcntr_header_height = LLPANEL_BORDER_WIDTH + tabcntr_close_btn_size;
// possibly increase minimum size constraint due to children's minimums.
for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx)
{
LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(tab_idx);
if (floaterp)
{
new_min_width = llmax(new_min_width, floaterp->getMinWidth() + LLPANEL_BORDER_WIDTH * 2);
new_min_height = llmax(new_min_height, floaterp->getMinHeight() + floater_header_size + tabcntr_header_height);
}
}
}

View File

@ -45,8 +45,8 @@ public:
virtual BOOL postBuild();
/*virtual*/ void onOpen(const LLSD& key);
/*virtual*/ void draw();
/*virtual*/ void setVisible(BOOL visible);
virtual void draw();
virtual void setVisible(BOOL visible);
/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
/*virtual*/ bool addChild(LLView* view, S32 tab_group = 0);
@ -79,10 +79,11 @@ public:
protected:
struct LLFloaterData
{
S32 mWidth;
S32 mHeight;
BOOL mCanMinimize;
BOOL mCanResize;
S32 mWidth;
S32 mHeight;
BOOL mCanMinimize;
BOOL mCanResize;
BOOL mSaveRect;
};
LLTabContainer* mTabContainer;
@ -93,6 +94,9 @@ protected:
LLTabContainer::TabPosition mTabPos;
BOOL mAutoResize;
S32 mOrigMinWidth, mOrigMinHeight; // logically const but initialized late
private:
virtual void computeResizeLimits(S32& new_min_width, S32& new_min_height);
};
#endif // LL_MULTI_FLOATER_H

View File

@ -39,7 +39,6 @@
#include "lldir.h"
#include "llsdserialize.h"
#include "lltrans.h"
#include "llnotificationslistener.h"
#include "llstring.h"
#include "llsdparam.h"
#include "llsdutil.h"
@ -60,7 +59,8 @@ void NotificationPriorityValues::declareValues()
}
LLNotificationForm::FormElementBase::FormElementBase()
: name("name")
: name("name"),
enabled("enabled", true)
{}
LLNotificationForm::FormIgnore::FormIgnore()
@ -104,39 +104,7 @@ LLNotificationForm::Params::Params()
form_elements("")
{}
// Local channel for persistent notifications
// Stores only persistent notifications.
// Class users can use connectChanged() to process persistent notifications
// (see LLNotificationStorage for example).
class LLPersistentNotificationChannel : public LLNotificationChannel
{
LOG_CLASS(LLPersistentNotificationChannel);
public:
LLPersistentNotificationChannel() :
LLNotificationChannel("Persistent", "Visible", &notificationFilter, LLNotificationComparators::orderByUUID())
{
}
private:
// The channel gets all persistent notifications except those that have been canceled
static bool notificationFilter(LLNotificationPtr pNotification)
{
bool handle_notification = false;
handle_notification = pNotification->isPersistent()
&& !pNotification->isCancelled();
return handle_notification;
}
void onDelete(LLNotificationPtr pNotification)
{
// we want to keep deleted notifications in our log, otherwise some
// notifications will be lost on exit.
mItems.insert(pNotification);
}
};
bool filterIgnoredNotifications(LLNotificationPtr notification)
{
@ -210,6 +178,14 @@ LLNotificationForm::LLNotificationForm()
{
}
LLNotificationForm::LLNotificationForm( const LLNotificationForm& other )
{
mFormData = other.mFormData;
mIgnore = other.mIgnore;
mIgnoreMsg = other.mIgnoreMsg;
mIgnoreSetting = other.mIgnoreSetting;
mInvertSetting = other.mInvertSetting;
}
LLNotificationForm::LLNotificationForm(const std::string& name, const LLNotificationForm::Params& p)
: mIgnore(IGNORE_NO),
@ -246,14 +222,6 @@ LLNotificationForm::LLNotificationForm(const std::string& name, const LLNotifica
LLParamSDParser parser;
parser.writeSD(mFormData, p.form_elements);
if (!mFormData.isArray())
{
// change existing contents to a one element array
LLSD new_llsd_array = LLSD::emptyArray();
new_llsd_array.append(mFormData);
mFormData = new_llsd_array;
}
for (LLSD::array_iterator it = mFormData.beginArray(), end_it = mFormData.endArray();
it != end_it;
++it)
@ -300,7 +268,7 @@ LLSD LLNotificationForm::getElement(const std::string& element_name)
}
bool LLNotificationForm::hasElement(const std::string& element_name)
bool LLNotificationForm::hasElement(const std::string& element_name) const
{
for (LLSD::array_const_iterator it = mFormData.beginArray();
it != mFormData.endArray();
@ -311,7 +279,48 @@ bool LLNotificationForm::hasElement(const std::string& element_name)
return false;
}
void LLNotificationForm::addElement(const std::string& type, const std::string& name, const LLSD& value)
void LLNotificationForm::getElements(LLSD& elements, S32 offset)
{
//Finds elements that the template did not add
LLSD::array_const_iterator it = mFormData.beginArray() + offset;
//Keeps track of only the dynamic elements
for(; it != mFormData.endArray(); ++it)
{
elements.append(*it);
}
}
bool LLNotificationForm::getElementEnabled(const std::string& element_name) const
{
for (LLSD::array_const_iterator it = mFormData.beginArray();
it != mFormData.endArray();
++it)
{
if ((*it)["name"].asString() == element_name)
{
return (*it)["enabled"].asBoolean();
}
}
return false;
}
void LLNotificationForm::setElementEnabled(const std::string& element_name, bool enabled)
{
for (LLSD::array_iterator it = mFormData.beginArray();
it != mFormData.endArray();
++it)
{
if ((*it)["name"].asString() == element_name)
{
(*it)["enabled"] = enabled;
}
}
}
void LLNotificationForm::addElement(const std::string& type, const std::string& name, const LLSD& value, bool enabled)
{
LLSD element;
element["type"] = type;
@ -319,6 +328,7 @@ void LLNotificationForm::addElement(const std::string& type, const std::string&
element["text"] = name;
element["value"] = value;
element["index"] = mFormData.size();
element["enabled"] = enabled;
mFormData.append(element);
}
@ -408,14 +418,19 @@ LLNotificationTemplate::LLNotificationTemplate(const LLNotificationTemplate::Par
mURLOption(p.url.option),
mURLTarget(p.url.target),
mUnique(p.unique.isProvided()),
mCombineBehavior(p.unique.combine),
mPriority(p.priority),
mPersist(p.persist),
mDefaultFunctor(p.functor.isProvided() ? p.functor() : p.name())
mDefaultFunctor(p.functor.isProvided() ? p.functor() : p.name()),
mLogToChat(p.log_to_chat),
mLogToIM(p.log_to_im),
mShowToast(p.show_toast),
mSoundName("")
{
if (p.sound.isProvided()
&& LLUI::sSettingGroups["config"]->controlExists(p.sound))
{
mSoundEffect = LLUUID(LLUI::sSettingGroups["config"]->getString(p.sound));
mSoundName = p.sound;
}
BOOST_FOREACH(const LLNotificationTemplate::UniquenessContext& context, p.unique.contexts)
@ -460,18 +475,20 @@ LLNotificationVisibilityRule::LLNotificationVisibilityRule(const LLNotificationV
}
}
LLNotification::LLNotification(const LLNotification::Params& p) :
LLNotification::LLNotification(const LLSDParamAdapter<Params>& p) :
mTimestamp(p.time_stamp),
mSubstitutions(p.substitutions),
mPayload(p.payload),
mExpiresAt(0),
mExpiresAt(p.expiry),
mTemporaryResponder(false),
mRespondedTo(false),
mPriority(p.priority),
mCancelled(false),
mIgnored(false),
mResponderObj(NULL),
mIsReusable(false)
mId(p.id.isProvided() ? p.id : LLUUID::generateNewID()),
mOfferFromAgent(p.offer_from_agent),
mIsDND(p.is_dnd)
{
if (p.functor.name.isChosen())
{
@ -494,52 +511,52 @@ LLNotification::LLNotification(const LLNotification::Params& p) :
mResponderObj = p.responder;
}
mId.generate();
init(p.name, p.form_elements);
}
LLNotification::LLNotification(const LLSD& sd) :
mTemporaryResponder(false),
mRespondedTo(false),
mCancelled(false),
mIgnored(false),
mResponderObj(NULL),
mIsReusable(false)
{
mId.generate();
mSubstitutions = sd["substitutions"];
mPayload = sd["payload"];
mTimestamp = sd["time"];
mExpiresAt = sd["expiry"];
mPriority = (ENotificationPriority)sd["priority"].asInteger();
mResponseFunctorName = sd["responseFunctor"].asString();
std::string templatename = sd["name"].asString();
init(templatename, LLSD());
// replace form with serialized version
mForm = LLNotificationFormPtr(new LLNotificationForm(sd["form"]));
}
LLSD LLNotification::asLLSD()
LLSD LLNotification::asLLSD(bool excludeTemplateElements)
{
LLSD output;
output["id"] = mId;
output["name"] = mTemplatep->mName;
output["form"] = getForm()->asLLSD();
output["substitutions"] = mSubstitutions;
output["payload"] = mPayload;
output["time"] = mTimestamp;
output["expiry"] = mExpiresAt;
output["priority"] = (S32)mPriority;
output["responseFunctor"] = mResponseFunctorName;
output["reusable"] = mIsReusable;
LLParamSDParser parser;
if(mResponder)
Params p;
p.id = mId;
p.name = mTemplatep->mName;
p.substitutions = mSubstitutions;
p.payload = mPayload;
p.time_stamp = mTimestamp;
p.expiry = mExpiresAt;
p.priority = mPriority;
LLNotificationFormPtr templateForm = mTemplatep->mForm;
LLSD formElements = mForm->asLLSD();
//All form elements (dynamic or not)
if(!excludeTemplateElements)
{
p.form_elements = formElements;
}
//Only dynamic form elements (exclude template elements)
else if(templateForm->getNumElements() < formElements.size())
{
LLSD dynamicElements;
//Offset to dynamic elements and store them
mForm->getElements(dynamicElements, templateForm->getNumElements());
p.form_elements = dynamicElements;
}
if(mResponder)
{
p.functor.responder_sd = mResponder->asLLSD();
}
if(!mResponseFunctorName.empty())
{
output["responder"] = mResponder->asLLSD();
p.functor.name = mResponseFunctorName;
}
LLSD output;
parser.writeSD(output, p);
return output;
}
@ -569,7 +586,6 @@ void LLNotification::updateFrom(LLNotificationPtr other)
mRespondedTo = other->mRespondedTo;
mResponse = other->mResponse;
mTemporaryResponder = other->mTemporaryResponder;
mIsReusable = other->isReusable();
update();
}
@ -668,7 +684,7 @@ void LLNotification::respond(const LLSD& response)
return;
}
if (mTemporaryResponder && !isReusable())
if (mTemporaryResponder)
{
LLNotificationFunctorRegistry::instance().unregisterFunctor(mResponseFunctorName);
mResponseFunctorName = "";
@ -829,7 +845,7 @@ void LLNotification::init(const std::string& template_name, const LLSD& form_ele
//mSubstitutions["_ARGS"] = get_all_arguments_as_text(mSubstitutions);
mForm = LLNotificationFormPtr(new LLNotificationForm(*mTemplatep->mForm));
mForm->append(form_elements);
mForm->append(form_elements);
// apply substitution to form labels
mForm->formatElements(mSubstitutions);
@ -897,6 +913,49 @@ std::string LLNotification::getURL() const
return (mTemplatep ? url : "");
}
bool LLNotification::canLogToChat() const
{
return mTemplatep->mLogToChat;
}
bool LLNotification::canLogToIM() const
{
return mTemplatep->mLogToIM;
}
bool LLNotification::canShowToast() const
{
return mTemplatep->mShowToast;
}
bool LLNotification::hasFormElements() const
{
return mTemplatep->mForm->getNumElements() != 0;
}
void LLNotification::playSound()
{
make_ui_sound(mTemplatep->mSoundName.c_str());
}
LLNotification::ECombineBehavior LLNotification::getCombineBehavior() const
{
return mTemplatep->mCombineBehavior;
}
void LLNotification::updateForm( const LLNotificationFormPtr& form )
{
mForm = form;
}
void LLNotification::repost()
{
mRespondedTo = false;
LLNotifications::instance().update(shared_from_this());
}
// =========================================================
// LLNotificationChannel implementation
// ---
@ -957,7 +1016,7 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt
std::string cmd = payload["sigtype"];
LLNotificationSet::iterator foundItem = mItems.find(pNotification);
bool wasFound = (foundItem != mItems.end());
bool passesFilter = mFilter(pNotification);
bool passesFilter = mFilter ? mFilter(pNotification) : true;
// first, we offer the result of the filter test to the simple
// signals for pass/fail. One of these is guaranteed to be called.
@ -966,10 +1025,12 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt
bool abortProcessing = false;
if (passesFilter)
{
onFilterPass(pNotification);
abortProcessing = mPassedFilter(payload);
}
else
{
onFilterFail(pNotification);
abortProcessing = mFailedFilter(payload);
}
@ -987,8 +1048,8 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt
{
// not in our list, add it and say so
mItems.insert(pNotification);
abortProcessing = mChanged(payload);
onLoad(pNotification);
abortProcessing = mChanged(payload);
}
}
else if (cmd == "change")
@ -1003,18 +1064,18 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt
{
// it already existed, so this is a change
// since it changed in place, all we have to do is resend the signal
abortProcessing = mChanged(payload);
onChange(pNotification);
abortProcessing = mChanged(payload);
}
else
{
// not in our list, add it and say so
mItems.insert(pNotification);
onChange(pNotification);
// our payload is const, so make a copy before changing it
LLSD newpayload = payload;
newpayload["sigtype"] = "add";
abortProcessing = mChanged(newpayload);
onChange(pNotification);
}
}
else
@ -1023,11 +1084,11 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt
{
// it already existed, so this is a delete
mItems.erase(pNotification);
onChange(pNotification);
// our payload is const, so make a copy before changing it
LLSD newpayload = payload;
newpayload["sigtype"] = "delete";
abortProcessing = mChanged(newpayload);
onChange(pNotification);
}
// didn't pass, not on our list, do nothing
}
@ -1041,8 +1102,8 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt
{
// not in our list, add it and say so
mItems.insert(pNotification);
abortProcessing = mChanged(payload);
onAdd(pNotification);
abortProcessing = mChanged(payload);
}
}
else if (cmd == "delete")
@ -1050,65 +1111,35 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt
// if we have it in our list, pass on the delete, then delete it, else do nothing
if (wasFound)
{
onDelete(pNotification);
abortProcessing = mChanged(payload);
// do not delete the notification to make LLChatHistory::appendMessage add notification panel to IM window
if( ! pNotification->isReusable() )
{
mItems.erase(pNotification);
onDelete(pNotification);
}
mItems.erase(pNotification);
}
}
return abortProcessing;
}
/* static */
LLNotificationChannelPtr LLNotificationChannel::buildChannel(const std::string& name,
const std::string& parent,
LLNotificationFilter filter,
LLNotificationComparator comparator)
LLNotificationChannel::LLNotificationChannel(const Params& p)
: LLNotificationChannelBase(p.filter()),
LLInstanceTracker<LLNotificationChannel, std::string>(p.name.isProvided() ? p.name : LLUUID::generateNewID().asString()),
mName(p.name.isProvided() ? p.name : LLUUID::generateNewID().asString())
{
// note: this is not a leak; notifications are self-registering.
// This factory helps to prevent excess deletions by making sure all smart
// pointers to notification channels come from the same source
new LLNotificationChannel(name, parent, filter, comparator);
return LLNotifications::instance().getChannel(name);
BOOST_FOREACH(const std::string& source, p.sources)
{
connectToChannel(source);
}
}
LLNotificationChannel::LLNotificationChannel(const std::string& name,
const std::string& parent,
LLNotificationFilter filter,
LLNotificationComparator comparator) :
LLNotificationChannelBase(filter, comparator),
mName(name),
mParent(parent)
LLNotificationFilter filter)
: LLNotificationChannelBase(filter),
LLInstanceTracker<LLNotificationChannel, std::string>(name),
mName(name)
{
// store myself in the channel map
LLNotifications::instance().addChannel(LLNotificationChannelPtr(this));
// bind to notification broadcast
if (parent.empty())
{
LLNotifications::instance().connectChanged(
boost::bind(&LLNotificationChannelBase::updateItem, this, _1));
}
else
{
LLNotificationChannelPtr p = LLNotifications::instance().getChannel(parent);
p->connectChanged(boost::bind(&LLNotificationChannelBase::updateItem, this, _1));
}
}
void LLNotificationChannel::setComparator(LLNotificationComparator comparator)
{
mComparator = comparator;
LLNotificationSet s2(mComparator);
s2.insert(mItems.begin(), mItems.end());
mItems.swap(s2);
// notify clients that we've been resorted
mChanged(LLSD().with("sigtype", "sort"));
connectToChannel(parent);
}
bool LLNotificationChannel::isEmpty() const
@ -1131,6 +1162,11 @@ LLNotificationChannel::Iterator LLNotificationChannel::end()
return mItems.end();
}
size_t LLNotificationChannel::size()
{
return mItems.size();
}
std::string LLNotificationChannel::summarize()
{
std::string s("Channel '");
@ -1144,22 +1180,33 @@ std::string LLNotificationChannel::summarize()
return s;
}
void LLNotificationChannel::connectToChannel( const std::string& channel_name )
{
if (channel_name.empty())
{
LLNotifications::instance().connectChanged(
boost::bind(&LLNotificationChannelBase::updateItem, this, _1));
}
else
{
LLNotificationChannelPtr p = LLNotifications::instance().getChannel(channel_name);
p->connectChanged(boost::bind(&LLNotificationChannelBase::updateItem, this, _1));
}
}
// ---
// END OF LLNotificationChannel implementation
// =========================================================
// =========================================================
// ============================================== ===========
// LLNotifications implementation
// ---
LLNotifications::LLNotifications() : LLNotificationChannelBase(LLNotificationFilters::includeEverything,
LLNotificationComparators::orderByUUID()),
mIgnoreAllNotifications(false)
LLNotifications::LLNotifications()
: LLNotificationChannelBase(LLNotificationFilters::includeEverything),
mIgnoreAllNotifications(false)
{
LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Notification.Show", boost::bind(&LLNotifications::addFromCallback, this, _2));
mListener.reset(new LLNotificationsListener(*this));
}
@ -1196,7 +1243,15 @@ bool LLNotifications::uniqueFilter(LLNotificationPtr pNotif)
if (pNotif != existing_notification
&& pNotif->isEquivalentTo(existing_notification))
{
return false;
if (pNotif->getCombineBehavior() == LLNotification::CANCEL_OLD)
{
cancel(existing_notification);
return true;
}
else
{
return false;
}
}
}
@ -1236,43 +1291,43 @@ bool LLNotifications::failedUniquenessTest(const LLSD& payload)
return false;
}
// Update the existing unique notification with the data from this particular instance...
// This guarantees that duplicate notifications will be collapsed to the one
// most recently triggered
for (LLNotificationMap::iterator existing_it = mUniqueNotifications.find(pNotif->getName());
existing_it != mUniqueNotifications.end();
++existing_it)
switch(pNotif->getCombineBehavior())
{
LLNotificationPtr existing_notification = existing_it->second;
if (pNotif != existing_notification
&& pNotif->isEquivalentTo(existing_notification))
case LLNotification::REPLACE_WITH_NEW:
// Update the existing unique notification with the data from this particular instance...
// This guarantees that duplicate notifications will be collapsed to the one
// most recently triggered
for (LLNotificationMap::iterator existing_it = mUniqueNotifications.find(pNotif->getName());
existing_it != mUniqueNotifications.end();
++existing_it)
{
// copy notification instance data over to oldest instance
// of this unique notification and update it
existing_notification->updateFrom(pNotif);
// then delete the new one
cancel(pNotif);
LLNotificationPtr existing_notification = existing_it->second;
if (pNotif != existing_notification
&& pNotif->isEquivalentTo(existing_notification))
{
// copy notification instance data over to oldest instance
// of this unique notification and update it
existing_notification->updateFrom(pNotif);
// then delete the new one
cancel(pNotif);
}
}
break;
case LLNotification::KEEP_OLD:
break;
case LLNotification::CANCEL_OLD:
// already handled by filter logic
break;
default:
break;
}
return false;
}
void LLNotifications::addChannel(LLNotificationChannelPtr pChan)
{
mChannels[pChan->getName()] = pChan;
}
LLNotificationChannelPtr LLNotifications::getChannel(const std::string& channelName)
{
ChannelMap::iterator p = mChannels.find(channelName);
if(p == mChannels.end())
{
llerrs << "Did not find channel named " << channelName << llendl;
return LLNotificationChannelPtr();
}
return p->second;
return LLNotificationChannelPtr(LLNotificationChannel::getInstance(channelName));
}
@ -1288,24 +1343,21 @@ void LLNotifications::createDefaultChannels()
{
// now construct the various channels AFTER loading the notifications,
// because the history channel is going to rewrite the stored notifications file
LLNotificationChannel::buildChannel("Enabled", "",
!boost::bind(&LLNotifications::getIgnoreAllNotifications, this));
LLNotificationChannel::buildChannel("Expiration", "Enabled",
boost::bind(&LLNotifications::expirationFilter, this, _1));
LLNotificationChannel::buildChannel("Unexpired", "Enabled",
!boost::bind(&LLNotifications::expirationFilter, this, _1)); // use negated bind
LLNotificationChannel::buildChannel("Unique", "Unexpired",
boost::bind(&LLNotifications::uniqueFilter, this, _1));
LLNotificationChannel::buildChannel("Ignore", "Unique",
filterIgnoredNotifications);
LLNotificationChannel::buildChannel("VisibilityRules", "Ignore",
boost::bind(&LLNotifications::isVisibleByRules, this, _1));
LLNotificationChannel::buildChannel("Visible", "VisibilityRules",
&LLNotificationFilters::includeEverything);
// create special persistent notification channel
// this isn't a leak, don't worry about the empty "new"
new LLPersistentNotificationChannel();
mDefaultChannels.push_back(new LLNotificationChannel("Enabled", "",
!boost::bind(&LLNotifications::getIgnoreAllNotifications, this)));
mDefaultChannels.push_back(new LLNotificationChannel("Expiration", "Enabled",
boost::bind(&LLNotifications::expirationFilter, this, _1)));
mDefaultChannels.push_back(new LLNotificationChannel("Unexpired", "Enabled",
!boost::bind(&LLNotifications::expirationFilter, this, _1))); // use negated bind
mDefaultChannels.push_back(new LLNotificationChannel("Unique", "Unexpired",
boost::bind(&LLNotifications::uniqueFilter, this, _1)));
mDefaultChannels.push_back(new LLNotificationChannel("Ignore", "Unique",
filterIgnoredNotifications));
mDefaultChannels.push_back(new LLNotificationChannel("VisibilityRules", "Ignore",
boost::bind(&LLNotifications::isVisibleByRules, this, _1)));
mDefaultChannels.push_back(new LLNotificationChannel("Visible", "VisibilityRules",
&LLNotificationFilters::includeEverything));
mDefaultChannels.push_back(new LLPersistentNotificationChannel());
// connect action methods to these channels
LLNotifications::instance().getChannel("Enabled")->
@ -1537,34 +1589,32 @@ void LLNotifications::addFromCallback(const LLSD& name)
add(name.asString(), LLSD(), LLSD());
}
LLNotificationPtr LLNotifications::add(const std::string& name,
const LLSD& substitutions,
const LLSD& payload)
LLNotificationPtr LLNotifications::add(const std::string& name, const LLSD& substitutions, const LLSD& payload)
{
LLNotification::Params::Functor functor_p;
functor_p.name = name;
return add(LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p));
}
LLNotificationPtr LLNotifications::add(const std::string& name,
const LLSD& substitutions,
const LLSD& payload,
const std::string& functor_name)
LLNotificationPtr LLNotifications::add(const std::string& name, const LLSD& substitutions, const LLSD& payload, const std::string& functor_name)
{
LLNotification::Params::Functor functor_p;
functor_p.name = functor_name;
return add(LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p));
return add(LLNotification::Params().name(name)
.substitutions(substitutions)
.payload(payload)
.functor(functor_p));
}
//virtual
LLNotificationPtr LLNotifications::add(const std::string& name,
const LLSD& substitutions,
const LLSD& payload,
LLNotificationFunctorRegistry::ResponseFunctor functor)
LLNotificationPtr LLNotifications::add(const std::string& name, const LLSD& substitutions, const LLSD& payload, LLNotificationFunctorRegistry::ResponseFunctor functor)
{
LLNotification::Params::Functor functor_p;
functor_p.function = functor;
return add(LLNotification::Params().name(name).substitutions(substitutions).payload(payload).functor(functor_p));
return add(LLNotification::Params().name(name)
.substitutions(substitutions)
.payload(payload)
.functor(functor_p));
}
// generalized add function that takes a parameter block object for more complex instantiations
@ -1595,12 +1645,11 @@ void LLNotifications::cancel(LLNotificationPtr pNotif)
if (pNotif == NULL || pNotif->isCancelled()) return;
LLNotificationSet::iterator it=mItems.find(pNotif);
if (it == mItems.end())
if (it != mItems.end())
{
llerrs << "Attempted to delete nonexistent notification " << pNotif->getName() << llendl;
pNotif->cancel();
updateItem(LLSD().with("sigtype", "delete").with("id", pNotif->id()), pNotif);
}
pNotif->cancel();
updateItem(LLSD().with("sigtype", "delete").with("id", pNotif->id()), pNotif);
}
void LLNotifications::cancelByName(const std::string& name)
@ -1639,7 +1688,7 @@ void LLNotifications::update(const LLNotificationPtr pNotif)
LLNotificationPtr LLNotifications::find(LLUUID uuid)
{
LLNotificationPtr target = LLNotificationPtr(new LLNotification(uuid));
LLNotificationPtr target = LLNotificationPtr(new LLNotification(LLNotification::Params().id(uuid)));
LLNotificationSet::iterator it=mItems.find(target);
if (it == mItems.end())
{
@ -1778,22 +1827,18 @@ std::ostream& operator<<(std::ostream& s, const LLNotification& notification)
return s;
}
//static
void LLPostponedNotification::lookupName(LLPostponedNotification* thiz,
const LLUUID& id,
void LLPostponedNotification::lookupName(const LLUUID& id,
bool is_group)
{
if (is_group)
{
gCacheName->getGroup(id,
boost::bind(&LLPostponedNotification::onGroupNameCache,
thiz, _1, _2, _3));
this, _1, _2, _3));
}
else
{
LLAvatarNameCache::get(id,
boost::bind(&LLPostponedNotification::onAvatarNameCache,
thiz, _1, _2));
fetchAvatarName(id);
}
}
@ -1804,9 +1849,24 @@ void LLPostponedNotification::onGroupNameCache(const LLUUID& id,
finalizeName(full_name);
}
void LLPostponedNotification::fetchAvatarName(const LLUUID& id)
{
if (id.notNull())
{
if (mAvatarNameCacheConnection.connected())
{
mAvatarNameCacheConnection.disconnect();
}
mAvatarNameCacheConnection = LLAvatarNameCache::get(id, boost::bind(&LLPostponedNotification::onAvatarNameCache, this, _1, _2));
}
}
void LLPostponedNotification::onAvatarNameCache(const LLUUID& agent_id,
const LLAvatarName& av_name)
{
mAvatarNameCacheConnection.disconnect();
std::string name = av_name.getCompleteName();
// from PE merge - we should figure out if this is the right thing to do

View File

@ -87,17 +87,16 @@
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/type_traits.hpp>
#include <boost/signals2.hpp>
// we want to minimize external dependencies, but this one is important
#include "llsd.h"
// and we need this to manage the notification callbacks
#include "llevents.h"
#include "llfunctorregistry.h"
#include "llpointer.h"
#include "llinitparam.h"
#include "llnotificationslistener.h"
#include "llmortician.h"
#include "llnotificationptr.h"
#include "llpointer.h"
#include "llrefcount.h"
#include "llsdparam.h"
class LLAvatarName;
typedef enum e_notification_priority
@ -164,6 +163,7 @@ public:
struct FormElementBase : public LLInitParam::Block<FormElementBase>
{
Optional<std::string> name;
Optional<bool> enabled;
FormElementBase();
};
@ -233,16 +233,21 @@ public:
} EIgnoreType;
LLNotificationForm();
LLNotificationForm(const LLNotificationForm&);
LLNotificationForm(const LLSD& sd);
LLNotificationForm(const std::string& name, const Params& p);
void fromLLSD(const LLSD& sd);
LLSD asLLSD() const;
S32 getNumElements() { return mFormData.size(); }
LLSD getElement(S32 index) { return mFormData.get(index); }
LLSD getElement(const std::string& element_name);
bool hasElement(const std::string& element_name);
void addElement(const std::string& type, const std::string& name, const LLSD& value = LLSD());
void getElements(LLSD& elements, S32 offset = 0);
bool hasElement(const std::string& element_name) const;
bool getElementEnabled(const std::string& element_name) const;
void setElementEnabled(const std::string& element_name, bool enabled);
void addElement(const std::string& type, const std::string& name, const LLSD& value = LLSD(), bool enabled = true);
void formatElements(const LLSD& substitutions);
// appends form elements from another form serialized as LLSD
void append(const LLSD& sub_form);
@ -296,42 +301,52 @@ LOG_CLASS(LLNotification);
friend class LLNotifications;
public:
// parameter object used to instantiate a new notification
struct Params : public LLInitParam::Block<Params>
{
friend class LLNotification;
Mandatory<std::string> name;
// optional
Optional<LLSD> substitutions;
Optional<LLSD> payload;
Optional<LLUUID> id;
Optional<LLSD> substitutions,
form_elements,
payload;
Optional<ENotificationPriority, NotificationPriorityValues> priority;
Optional<LLSD> form_elements;
Optional<LLDate> time_stamp;
Optional<LLDate> time_stamp,
expiry;
Optional<LLNotificationContext*> context;
Optional<void*> responder;
Optional<bool> offer_from_agent;
Optional<bool> is_dnd;
struct Functor : public LLInitParam::ChoiceBlock<Functor>
{
Alternative<std::string> name;
Alternative<LLNotificationFunctorRegistry::ResponseFunctor> function;
Alternative<LLNotificationResponderPtr> responder;
Alternative<LLSD> responder_sd;
Functor()
: name("functor_name"),
: name("responseFunctor"),
function("functor"),
responder("responder")
responder("responder"),
responder_sd("responder_sd")
{}
};
Optional<Functor> functor;
Params()
: name("name"),
id("id"),
priority("priority", NOTIFICATION_PRIORITY_UNSPECIFIED),
time_stamp("time_stamp"),
time_stamp("time"),
payload("payload"),
form_elements("form_elements")
form_elements("form"),
substitutions("substitutions"),
expiry("expiry"),
offer_from_agent("offer_from_agent", false),
is_dnd("is_dnd", false)
{
time_stamp = LLDate::now();
responder = NULL;
@ -340,9 +355,13 @@ public:
Params(const std::string& _name)
: name("name"),
priority("priority", NOTIFICATION_PRIORITY_UNSPECIFIED),
time_stamp("time_stamp"),
time_stamp("time"),
payload("payload"),
form_elements("form_elements")
form_elements("form"),
substitutions("substitutions"),
expiry("expiry"),
offer_from_agent("offer_from_agent", false),
is_dnd("is_dnd", false)
{
functor.name = _name;
name = _name;
@ -355,7 +374,7 @@ public:
private:
LLUUID mId;
const LLUUID mId;
LLSD mPayload;
LLSD mSubstitutions;
LLDate mTimestamp;
@ -367,8 +386,9 @@ private:
ENotificationPriority mPriority;
LLNotificationFormPtr mForm;
void* mResponderObj; // TODO - refactor/remove this field
bool mIsReusable;
LLNotificationResponderPtr mResponder;
bool mOfferFromAgent;
bool mIsDND;
// a reference to the template
LLNotificationTemplatePtr mTemplatep;
@ -392,18 +412,10 @@ private:
void init(const std::string& template_name, const LLSD& form_elements);
LLNotification(const Params& p);
// this is just for making it easy to look things up in a set organized by UUID -- DON'T USE IT
// for anything real!
LLNotification(LLUUID uuid) : mId(uuid), mCancelled(false), mRespondedTo(false), mIgnored(false), mPriority(NOTIFICATION_PRIORITY_UNSPECIFIED), mTemporaryResponder(false) {}
void cancel();
public:
// constructor from a saved notification
LLNotification(const LLSD& sd);
LLNotification(const LLSDParamAdapter<Params>& p);
void setResponseFunctor(std::string const &responseFunctorName);
@ -446,7 +458,12 @@ public:
// ["time"] = time at which notification was generated;
// ["expiry"] = time at which notification expires;
// ["responseFunctor"] = name of registered functor that handles responses to notification;
LLSD asLLSD();
LLSD asLLSD(bool excludeTemplateElements = false);
const LLNotificationFormPtr getForm();
void updateForm(const LLNotificationFormPtr& form);
void repost();
void respond(const LLSD& sd);
void respondWithDefault();
@ -507,6 +524,21 @@ public:
return mTimestamp;
}
bool getOfferFromAgent() const
{
return mOfferFromAgent;
}
bool isDND() const
{
return mIsDND;
}
void setDND(const bool flag)
{
mIsDND = flag;
}
std::string getType() const;
std::string getMessage() const;
std::string getFooter() const;
@ -514,8 +546,21 @@ public:
std::string getURL() const;
S32 getURLOption() const;
S32 getURLOpenExternally() const;
bool canLogToChat() const;
bool canLogToIM() const;
bool canShowToast() const;
bool hasFormElements() const;
void playSound();
typedef enum e_combine_behavior
{
REPLACE_WITH_NEW,
KEEP_OLD,
CANCEL_OLD
} ECombineBehavior;
const LLNotificationFormPtr getForm();
ECombineBehavior getCombineBehavior() const;
const LLDate getExpiration() const
{
@ -532,10 +577,6 @@ public:
return mId;
}
bool isReusable() { return mIsReusable; }
void setReusable(bool reusable) { mIsReusable = reusable; }
// comparing two notifications normally means comparing them by UUID (so we can look them
// up quickly this way)
bool operator<(const LLNotification& rhs) const
@ -647,44 +688,17 @@ namespace LLNotificationFilters
namespace LLNotificationComparators
{
typedef enum e_direction { ORDER_DECREASING, ORDER_INCREASING } EDirection;
// generic order functor that takes method or member variable reference
template<typename T>
struct orderBy
struct orderByUUID
{
typedef boost::function<T (LLNotificationPtr)> field_t;
orderBy(field_t field, EDirection direction = ORDER_INCREASING) : mField(field), mDirection(direction) {}
bool operator()(LLNotificationPtr lhs, LLNotificationPtr rhs)
{
if (mDirection == ORDER_DECREASING)
{
return mField(lhs) > mField(rhs);
}
else
{
return mField(lhs) < mField(rhs);
}
return lhs->id() < rhs->id();
}
field_t mField;
EDirection mDirection;
};
struct orderByUUID : public orderBy<const LLUUID&>
{
orderByUUID(EDirection direction = ORDER_INCREASING) : orderBy<const LLUUID&>(&LLNotification::id, direction) {}
};
struct orderByDate : public orderBy<const LLDate&>
{
orderByDate(EDirection direction = ORDER_INCREASING) : orderBy<const LLDate&>(&LLNotification::getDate, direction) {}
};
};
typedef boost::function<bool (LLNotificationPtr)> LLNotificationFilter;
typedef boost::function<bool (LLNotificationPtr, LLNotificationPtr)> LLNotificationComparator;
typedef std::set<LLNotificationPtr, LLNotificationComparator> LLNotificationSet;
typedef std::set<LLNotificationPtr, LLNotificationComparators::orderByUUID> LLNotificationSet;
typedef std::multimap<std::string, LLNotificationPtr> LLNotificationMap;
// ========================================================
@ -705,12 +719,14 @@ typedef std::multimap<std::string, LLNotificationPtr> LLNotificationMap;
// all of the built-in tests should attach to the "Visible" channel
//
class LLNotificationChannelBase :
public LLEventTrackable
public LLEventTrackable,
public LLRefCount
{
LOG_CLASS(LLNotificationChannelBase);
public:
LLNotificationChannelBase(LLNotificationFilter filter, LLNotificationComparator comp) :
mFilter(filter), mItems(comp)
LLNotificationChannelBase(LLNotificationFilter filter)
: mFilter(filter),
mItems()
{}
virtual ~LLNotificationChannelBase() {}
// you can also connect to a Channel, so you can be notified of
@ -776,6 +792,9 @@ protected:
virtual void onDelete(LLNotificationPtr p) {}
virtual void onChange(LLNotificationPtr p) {}
virtual void onFilterPass(LLNotificationPtr p) {}
virtual void onFilterFail(LLNotificationPtr p) {}
bool updateItem(const LLSD& payload, LLNotificationPtr pNotification);
LLNotificationFilter mFilter;
};
@ -785,64 +804,53 @@ protected:
// destroy it, but if it becomes necessary to do so, the shared_ptr model
// will ensure that we don't leak resources.
class LLNotificationChannel;
typedef boost::shared_ptr<LLNotificationChannel> LLNotificationChannelPtr;
typedef boost::intrusive_ptr<LLNotificationChannel> LLNotificationChannelPtr;
// manages a list of notifications
// Note that if this is ever copied around, we might find ourselves with multiple copies
// of a queue with notifications being added to different nonequivalent copies. So we
// make it inherit from boost::noncopyable, and then create a map of shared_ptr to manage it.
//
// NOTE: LLNotificationChannel is self-registering. The *correct* way to create one is to
// do something like:
// LLNotificationChannel::buildChannel("name", "parent"...);
// This returns an LLNotificationChannelPtr, which you can store, or
// you can then retrieve the channel by using the registry:
// LLNotifications::instance().getChannel("name")...
// make it inherit from boost::noncopyable, and then create a map of LLPointer to manage it.
//
class LLNotificationChannel :
boost::noncopyable,
public LLNotificationChannelBase
public LLNotificationChannelBase,
public LLInstanceTracker<LLNotificationChannel, std::string>
{
LOG_CLASS(LLNotificationChannel);
public:
// Notification Channels have a filter, which determines which notifications
// will be added to this channel.
// Channel filters cannot change.
struct Params : public LLInitParam::Block<Params>
{
Mandatory<std::string> name;
Optional<LLNotificationFilter> filter;
Multiple<std::string> sources;
};
LLNotificationChannel(const Params& p = Params());
LLNotificationChannel(const std::string& name, const std::string& parent, LLNotificationFilter filter);
virtual ~LLNotificationChannel() {}
typedef LLNotificationSet::iterator Iterator;
std::string getName() const { return mName; }
std::string getParentChannelName() { return mParent; }
void connectToChannel(const std::string& channel_name);
bool isEmpty() const;
S32 size() const;
Iterator begin();
Iterator end();
size_t size();
// Channels have a comparator to control sort order;
// the default sorts by arrival date
void setComparator(LLNotificationComparator comparator);
std::string summarize();
// factory method for constructing these channels; since they're self-registering,
// we want to make sure that you can't use new to make them
static LLNotificationChannelPtr buildChannel(const std::string& name, const std::string& parent,
LLNotificationFilter filter=LLNotificationFilters::includeEverything,
LLNotificationComparator comparator=LLNotificationComparators::orderByUUID());
protected:
// Notification Channels have a filter, which determines which notifications
// will be added to this channel.
// Channel filters cannot change.
// Channels have a protected constructor so you can't make smart pointers that don't
// come from our internal reference; call NotificationChannel::build(args)
LLNotificationChannel(const std::string& name, const std::string& parent,
LLNotificationFilter filter, LLNotificationComparator comparator);
private:
std::string mName;
std::string mParent;
LLNotificationComparator mComparator;
};
// An interface class to provide a clean linker seam to the LLNotifications class.
@ -925,10 +933,6 @@ public:
void createDefaultChannels();
typedef std::map<std::string, LLNotificationChannelPtr> ChannelMap;
ChannelMap mChannels;
void addChannel(LLNotificationChannelPtr pChan);
LLNotificationChannelPtr getChannel(const std::string& channelName);
std::string getGlobalString(const std::string& key) const;
@ -966,7 +970,7 @@ private:
bool mIgnoreAllNotifications;
boost::scoped_ptr<LLNotificationsListener> mListener;
std::vector<LLNotificationChannelPtr> mDefaultChannels;
};
/**
@ -979,7 +983,7 @@ private:
* 1 create class derived from LLPostponedNotification;
* 2 call LLPostponedNotification::add method;
*/
class LLPostponedNotification
class LLPostponedNotification : public LLMortician
{
public:
/**
@ -997,26 +1001,38 @@ public:
thiz->mParams = params;
// Avoid header file dependency on llcachename.h
lookupName(thiz, id, is_group);
thiz->lookupName(id, is_group);
}
private:
static void lookupName(LLPostponedNotification* thiz, const LLUUID& id, bool is_group);
void lookupName(const LLUUID& id, bool is_group);
// only used for groups
void onGroupNameCache(const LLUUID& id, const std::string& full_name, bool is_group);
// only used for avatars
void fetchAvatarName(const LLUUID& id);
void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name);
// used for both group and avatar names
void finalizeName(const std::string& name);
void cleanup()
{
delete this;
die();
}
protected:
LLPostponedNotification() {}
virtual ~LLPostponedNotification() {}
LLPostponedNotification()
: mParams(),
mName(),
mAvatarNameCacheConnection()
{}
virtual ~LLPostponedNotification()
{
if (mAvatarNameCacheConnection.connected())
{
mAvatarNameCacheConnection.disconnect();
}
}
/**
* Abstract method provides possibility to modify notification parameters and
@ -1027,6 +1043,58 @@ protected:
LLNotification::Params mParams;
std::string mName;
boost::signals2::connection mAvatarNameCacheConnection;
};
// Stores only persistent notifications.
// Class users can use connectChanged() to process persistent notifications
// (see LLPersistentNotificationStorage for example).
class LLPersistentNotificationChannel : public LLNotificationChannel
{
LOG_CLASS(LLPersistentNotificationChannel);
public:
LLPersistentNotificationChannel()
: LLNotificationChannel("Persistent", "Visible", &notificationFilter)
{
}
typedef std::vector<LLNotificationPtr> history_list_t;
history_list_t::iterator beginHistory() { sortHistory(); return mHistory.begin(); }
history_list_t::iterator endHistory() { return mHistory.end(); }
private:
struct sortByTime
{
S32 operator ()(const LLNotificationPtr& a, const LLNotificationPtr& b)
{
return a->getDate() < b->getDate();
}
};
void sortHistory()
{
std::sort(mHistory.begin(), mHistory.end(), sortByTime());
}
// The channel gets all persistent notifications except those that have been canceled
static bool notificationFilter(LLNotificationPtr pNotification)
{
bool handle_notification = false;
handle_notification = pNotification->isPersistent()
&& !pNotification->isCancelled();
return handle_notification;
}
void onAdd(LLNotificationPtr p)
{
mHistory.push_back(p);
}
std::vector<LLNotificationPtr> mHistory;
};
#endif//LL_LLNOTIFICATIONS_H

View File

@ -1,354 +0,0 @@
/**
* @file llnotificationslistener.cpp
* @author Brad Kittenbrink
* @date 2009-07-08
* @brief Implementation for llnotificationslistener.
*
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* 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;
* version 2.1 of the License only.
*
* 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
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llnotificationslistener.h"
#include "llnotifications.h"
#include "llnotificationtemplate.h"
#include "llsd.h"
#include "llui.h"
LLNotificationsListener::LLNotificationsListener(LLNotifications & notifications) :
LLEventAPI("LLNotifications",
"LLNotifications listener to (e.g.) pop up a notification"),
mNotifications(notifications)
{
add("requestAdd",
"Add a notification with specified [\"name\"], [\"substitutions\"] and [\"payload\"].\n"
"If optional [\"reply\"] specified, arrange to send user response on that LLEventPump.",
&LLNotificationsListener::requestAdd);
add("listChannels",
"Post to [\"reply\"] a map of info on existing channels",
&LLNotificationsListener::listChannels,
LLSD().with("reply", LLSD()));
add("listChannelNotifications",
"Post to [\"reply\"] an array of info on notifications in channel [\"channel\"]",
&LLNotificationsListener::listChannelNotifications,
LLSD().with("reply", LLSD()).with("channel", LLSD()));
add("respond",
"Respond to notification [\"uuid\"] with data in [\"response\"]",
&LLNotificationsListener::respond,
LLSD().with("uuid", LLSD()));
add("cancel",
"Cancel notification [\"uuid\"]",
&LLNotificationsListener::cancel,
LLSD().with("uuid", LLSD()));
add("ignore",
"Ignore future notification [\"name\"]\n"
"(from <notification name= > in notifications.xml)\n"
"according to boolean [\"ignore\"].\n"
"If [\"name\"] is omitted or undefined, [un]ignore all future notifications.\n"
"Note that ignored notifications are not forwarded unless intercepted before\n"
"the \"Ignore\" channel.",
&LLNotificationsListener::ignore);
add("forward",
"Forward to [\"pump\"] future notifications on channel [\"channel\"]\n"
"according to boolean [\"forward\"]. When enabled, only types matching\n"
"[\"types\"] are forwarded, as follows:\n"
"omitted or undefined: forward all notifications\n"
"string: forward only the specific named [sig]type\n"
"array of string: forward any notification matching any named [sig]type.\n"
"When boolean [\"respond\"] is true, we auto-respond to each forwarded\n"
"notification.",
&LLNotificationsListener::forward,
LLSD().with("channel", LLSD()));
}
// This is here in the .cpp file so we don't need the definition of class
// Forwarder in the header file.
LLNotificationsListener::~LLNotificationsListener()
{
}
void LLNotificationsListener::requestAdd(const LLSD& event_data) const
{
if(event_data.has("reply"))
{
mNotifications.add(event_data["name"],
event_data["substitutions"],
event_data["payload"],
boost::bind(&LLNotificationsListener::NotificationResponder,
this,
event_data["reply"].asString(),
_1, _2
)
);
}
else
{
mNotifications.add(event_data["name"],
event_data["substitutions"],
event_data["payload"]);
}
}
void LLNotificationsListener::NotificationResponder(const std::string& reply_pump,
const LLSD& notification,
const LLSD& response) const
{
LLSD reponse_event;
reponse_event["notification"] = notification;
reponse_event["response"] = response;
LLEventPumps::getInstance()->obtain(reply_pump).post(reponse_event);
}
void LLNotificationsListener::listChannels(const LLSD& params) const
{
LLReqID reqID(params);
LLSD response(reqID.makeResponse());
for (LLNotifications::ChannelMap::const_iterator cmi(mNotifications.mChannels.begin()),
cmend(mNotifications.mChannels.end());
cmi != cmend; ++cmi)
{
LLSD channelInfo;
channelInfo["parent"] = cmi->second->getParentChannelName();
response[cmi->first] = channelInfo;
}
LLEventPumps::instance().obtain(params["reply"]).post(response);
}
void LLNotificationsListener::listChannelNotifications(const LLSD& params) const
{
LLReqID reqID(params);
LLSD response(reqID.makeResponse());
LLNotificationChannelPtr channel(mNotifications.getChannel(params["channel"]));
if (channel)
{
LLSD notifications(LLSD::emptyArray());
for (LLNotificationChannel::Iterator ni(channel->begin()), nend(channel->end());
ni != nend; ++ni)
{
notifications.append(asLLSD(*ni));
}
response["notifications"] = notifications;
}
LLEventPumps::instance().obtain(params["reply"]).post(response);
}
void LLNotificationsListener::respond(const LLSD& params) const
{
LLNotificationPtr notification(mNotifications.find(params["uuid"]));
if (notification)
{
notification->respond(params["response"]);
}
}
void LLNotificationsListener::cancel(const LLSD& params) const
{
LLNotificationPtr notification(mNotifications.find(params["uuid"]));
if (notification)
{
mNotifications.cancel(notification);
}
}
void LLNotificationsListener::ignore(const LLSD& params) const
{
// Calling a method named "ignore", but omitting its "ignore" Boolean
// argument, should by default cause something to be ignored. Explicitly
// pass ["ignore"] = false to cancel ignore.
bool ignore = true;
if (params.has("ignore"))
{
ignore = params["ignore"].asBoolean();
}
// This method can be used to affect either a single notification name or
// all future notifications. The two use substantially different mechanisms.
if (params["name"].isDefined())
{
// ["name"] was passed: ignore just that notification
LLNotificationTemplatePtr templatep = mNotifications.getTemplate(params["name"]);
if (templatep)
{
templatep->mForm->setIgnored(ignore);
}
}
else
{
// no ["name"]: ignore all future notifications
mNotifications.setIgnoreAllNotifications(ignore);
}
}
class LLNotificationsListener::Forwarder: public LLEventTrackable
{
LOG_CLASS(LLNotificationsListener::Forwarder);
public:
Forwarder(LLNotifications& llnotifications, const std::string& channel):
mNotifications(llnotifications),
mRespond(false)
{
// Connect to the specified channel on construction. Because
// LLEventTrackable is a base, we should automatically disconnect when
// destroyed.
LLNotificationChannelPtr channelptr(llnotifications.getChannel(channel));
if (channelptr)
{
// Insert our processing as a "passed filter" listener. This way
// we get to run before all the "changed" listeners, and we get to
// swipe it (hide it from the other listeners) if desired.
channelptr->connectPassedFilter(boost::bind(&Forwarder::handle, this, _1));
}
}
void setPumpName(const std::string& name) { mPumpName = name; }
void setTypes(const LLSD& types) { mTypes = types; }
void setRespond(bool respond) { mRespond = respond; }
private:
bool handle(const LLSD& notification) const;
bool matchType(const LLSD& filter, const std::string& type) const;
LLNotifications& mNotifications;
std::string mPumpName;
LLSD mTypes;
bool mRespond;
};
void LLNotificationsListener::forward(const LLSD& params)
{
std::string channel(params["channel"]);
// First decide whether we're supposed to start forwarding or stop it.
// Default to true.
bool forward = true;
if (params.has("forward"))
{
forward = params["forward"].asBoolean();
}
if (! forward)
{
// This is a request to stop forwarding notifications on the specified
// channel. The rest of the params don't matter.
// Because mForwarders contains scoped_ptrs, erasing the map entry
// DOES delete the heap Forwarder object. Because Forwarder derives
// from LLEventTrackable, destroying it disconnects it from the
// channel.
mForwarders.erase(channel);
return;
}
// From here on, we know we're being asked to start (or modify) forwarding
// on the specified channel. Find or create an appropriate Forwarder.
ForwarderMap::iterator
entry(mForwarders.insert(ForwarderMap::value_type(channel, ForwarderMap::mapped_type())).first);
if (! entry->second)
{
entry->second.reset(new Forwarder(mNotifications, channel));
}
// Now, whether this Forwarder is brand-new or not, update it with the new
// request info.
Forwarder& fwd(*entry->second);
fwd.setPumpName(params["pump"]);
fwd.setTypes(params["types"]);
fwd.setRespond(params["respond"]);
}
bool LLNotificationsListener::Forwarder::handle(const LLSD& notification) const
{
LL_INFOS("LLNotificationsListener") << "handle(" << notification << ")" << LL_ENDL;
if (notification["sigtype"].asString() == "delete")
{
LL_INFOS("LLNotificationsListener") << "ignoring delete" << LL_ENDL;
// let other listeners see the "delete" operation
return false;
}
LLNotificationPtr note(mNotifications.find(notification["id"]));
if (! note)
{
LL_INFOS("LLNotificationsListener") << notification["id"] << " not found" << LL_ENDL;
return false;
}
if (! matchType(mTypes, note->getType()))
{
LL_INFOS("LLNotificationsListener") << "didn't match types " << mTypes << LL_ENDL;
// We're not supposed to intercept this particular notification. Let
// other listeners process it.
return false;
}
LL_INFOS("LLNotificationsListener") << "sending via '" << mPumpName << "'" << LL_ENDL;
// This is a notification we care about. Forward it through specified
// LLEventPump.
LLEventPumps::instance().obtain(mPumpName).post(asLLSD(note));
// Are we also being asked to auto-respond?
if (mRespond)
{
LL_INFOS("LLNotificationsListener") << "should respond" << LL_ENDL;
note->respond(LLSD::emptyMap());
// Did that succeed in removing the notification? Only cancel() if
// it's still around -- otherwise we get an LL_ERRS crash!
note = mNotifications.find(notification["id"]);
if (note)
{
LL_INFOS("LLNotificationsListener") << "respond() didn't clear, canceling" << LL_ENDL;
mNotifications.cancel(note);
}
}
// If we've auto-responded to this notification, then it's going to be
// deleted. Other listeners would get the change operation, try to look it
// up and be baffled by lookup failure. So when we auto-respond, suppress
// this notification: don't pass it to other listeners.
return mRespond;
}
bool LLNotificationsListener::Forwarder::matchType(const LLSD& filter, const std::string& type) const
{
// Decide whether this notification matches filter:
// undefined: forward all notifications
if (filter.isUndefined())
{
return true;
}
// array of string: forward any notification matching any named type
if (filter.isArray())
{
for (LLSD::array_const_iterator ti(filter.beginArray()), tend(filter.endArray());
ti != tend; ++ti)
{
if (ti->asString() == type)
{
return true;
}
}
// Didn't match any entry in the array
return false;
}
// string: forward only the specific named type
return (filter.asString() == type);
}
LLSD LLNotificationsListener::asLLSD(LLNotificationPtr note)
{
LLSD notificationInfo(note->asLLSD());
// For some reason the following aren't included in LLNotification::asLLSD().
notificationInfo["summary"] = note->summarize();
notificationInfo["id"] = note->id();
notificationInfo["type"] = note->getType();
notificationInfo["message"] = note->getMessage();
notificationInfo["label"] = note->getLabel();
return notificationInfo;
}

View File

@ -1,69 +0,0 @@
/**
* @file llnotificationslistener.h
* @author Brad Kittenbrink
* @date 2009-07-08
* @brief Wrap subset of LLNotifications API in event API for test scripts.
*
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* 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;
* version 2.1 of the License only.
*
* 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
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLNOTIFICATIONSLISTENER_H
#define LL_LLNOTIFICATIONSLISTENER_H
#include "lleventapi.h"
#include "llnotificationptr.h"
#include <boost/shared_ptr.hpp>
#include <map>
#include <string>
class LLNotifications;
class LLSD;
class LLNotificationsListener : public LLEventAPI
{
public:
LLNotificationsListener(LLNotifications & notifications);
~LLNotificationsListener();
private:
void requestAdd(LLSD const & event_data) const;
void NotificationResponder(const std::string& replypump,
const LLSD& notification,
const LLSD& response) const;
void listChannels(const LLSD& params) const;
void listChannelNotifications(const LLSD& params) const;
void respond(const LLSD& params) const;
void cancel(const LLSD& params) const;
void ignore(const LLSD& params) const;
void forward(const LLSD& params);
static LLSD asLLSD(LLNotificationPtr);
class Forwarder;
typedef std::map<std::string, boost::shared_ptr<Forwarder> > ForwarderMap;
ForwarderMap mForwarders;
LLNotifications & mNotifications;
};
#endif // LL_LLNOTIFICATIONSLISTENER_H

View File

@ -49,7 +49,6 @@
//#include "llfunctorregistry.h"
//#include "llpointer.h"
#include "llinitparam.h"
//#include "llnotificationslistener.h"
//#include "llnotificationptr.h"
//#include "llcachename.h"
#include "llnotifications.h"
@ -61,6 +60,18 @@ typedef boost::shared_ptr<LLNotificationForm> LLNotificationFormPtr;
// from the appropriate local language directory).
struct LLNotificationTemplate
{
struct CombineBehaviorNames
: public LLInitParam::TypeValuesHelper<LLNotification::ECombineBehavior, CombineBehaviorNames>
{
static void declareValues()
{
declare("replace_with_new", LLNotification::REPLACE_WITH_NEW);
declare("keep_old", LLNotification::KEEP_OLD);
declare("cancel_old", LLNotification::CANCEL_OLD);
}
};
struct GlobalString : public LLInitParam::Block<GlobalString>
{
Mandatory<std::string> name,
@ -94,9 +105,11 @@ struct LLNotificationTemplate
Optional<LLInitParam::Flag> dummy_val;
public:
Multiple<UniquenessContext> contexts;
Optional<LLNotification::ECombineBehavior, CombineBehaviorNames> combine;
UniquenessConstraint()
: contexts("context"),
combine("combine", LLNotification::REPLACE_WITH_NEW),
dummy_val("")
{}
};
@ -183,7 +196,10 @@ struct LLNotificationTemplate
struct Params : public LLInitParam::Block<Params>
{
Mandatory<std::string> name;
Optional<bool> persist;
Optional<bool> persist,
log_to_im,
show_toast,
log_to_chat;
Optional<std::string> functor,
icon,
label,
@ -204,6 +220,9 @@ struct LLNotificationTemplate
Params()
: name("name"),
persist("persist", false),
log_to_im("log_to_im", false),
show_toast("show_toast", true),
log_to_chat("log_to_chat", true),
functor("functor"),
icon("icon"),
label("label"),
@ -262,6 +281,7 @@ struct LLNotificationTemplate
// (used for things like progress indications, or repeating warnings
// like "the grid is going down in N minutes")
bool mUnique;
LLNotification::ECombineBehavior mCombineBehavior;
// if we want to be unique only if a certain part of the payload or substitutions args
// are constant specify the field names for the payload. The notification will only be
// combined if all of the fields named in the context are identical in the
@ -302,12 +322,15 @@ struct LLNotificationTemplate
LLNotificationFormPtr mForm;
// default priority for notifications of this type
ENotificationPriority mPriority;
// UUID of the audio file to be played when this notification arrives
// this is loaded as a name, but looked up to get the UUID upon template load.
// If null, it wasn't specified.
LLUUID mSoundEffect;
// Stores the sound name which can then be used to play the sound using make_ui_sound
std::string mSoundName;
// List of tags that rules can match against.
std::list<std::string> mTags;
// inject these notifications into chat/IM streams
bool mLogToChat;
bool mLogToIM;
bool mShowToast;
};
#endif //LL_LLNOTIFICATION_TEMPLATE_H

View File

@ -45,7 +45,8 @@ LLResizeBar::LLResizeBar(const LLResizeBar::Params& p)
mSide( p.side ),
mSnappingEnabled(p.snapping_enabled),
mAllowDoubleClickSnapping(p.allow_double_click_snapping),
mResizingView(p.resizing_view)
mResizingView(p.resizing_view),
mResizeListener(NULL)
{
setFollowsNone();
// set up some generically good follow code.
@ -300,6 +301,11 @@ BOOL LLResizeBar::handleHover(S32 x, S32 y, MASK mask)
}
}
if (mResizeListener)
{
mResizeListener(NULL);
}
return handled;
} // end LLResizeBar::handleHover

View File

@ -71,6 +71,7 @@ public:
void setEnableSnapping(BOOL enable) { mSnappingEnabled = enable; }
void setAllowDoubleClickSnapping(BOOL allow) { mAllowDoubleClickSnapping = allow; }
bool canResize() { return getEnabled() && mMaxSize > mMinSize; }
void setResizeListener(boost::function<void(void*)> listener) {mResizeListener = listener;}
private:
S32 mDragLastScreenX;
@ -84,6 +85,7 @@ private:
BOOL mSnappingEnabled;
BOOL mAllowDoubleClickSnapping;
LLView* mResizingView;
boost::function<void(void*)> mResizeListener;
};
#endif // LL_RESIZEBAR_H

View File

@ -1841,7 +1841,7 @@ void LLScrollListCtrl::copyNameToClipboard(std::string id, bool is_group)
{
LLAvatarName av_name;
LLAvatarNameCache::get(LLUUID(id), &av_name);
name = av_name.getLegacyName();
name = av_name.getAccountName();
}
LLUrlAction::copyURLToClipboard(name);
}

View File

@ -52,6 +52,7 @@ LLSpinCtrl::Params::Params()
: label_width("label_width"),
decimal_digits("decimal_digits"),
allow_text_entry("allow_text_entry", true),
allow_digits_only("allow_digits_only", false),
label_wrap("label_wrap", false),
text_enabled_color("text_enabled_color"),
text_disabled_color("text_disabled_color"),
@ -129,6 +130,10 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p)
params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM);
mEditor = LLUICtrlFactory::create<LLLineEditor> (params);
mEditor->setFocusReceivedCallback( boost::bind(&LLSpinCtrl::onEditorGainFocus, _1, this ));
if (p.allow_digits_only)
{
mEditor->setPrevalidateInput(LLTextValidate::validateNonNegativeS32NoSpace);
}
//RN: this seems to be a BAD IDEA, as it makes the editor behavior different when it has focus
// than when it doesn't. Instead, if you always have to double click to select all the text,
// it's easier to understand

View File

@ -44,6 +44,7 @@ public:
Optional<S32> label_width;
Optional<U32> decimal_digits;
Optional<bool> allow_text_entry;
Optional<bool> allow_digits_only;
Optional<bool> label_wrap;
Optional<LLUIColor> text_enabled_color;

View File

@ -506,8 +506,8 @@ void LLTabContainer::draw()
}
}
mPrevArrowBtn->setFlashing(FALSE);
mNextArrowBtn->setFlashing(FALSE);
mPrevArrowBtn->setFlashing(false);
mNextArrowBtn->setFlashing(false);
}
@ -1209,7 +1209,11 @@ void LLTabContainer::removeTabPanel(LLPanel* child)
update_images(mTabList[mTabList.size()-2], mLastTabParams, getTabPosition());
}
removeChild( tuple->mButton );
if (!getTabsHidden())
{
// We need to remove tab buttons only if the tabs are not hidden.
removeChild( tuple->mButton );
}
delete tuple->mButton;
removeChild( tuple->mTabPanel );
@ -1479,6 +1483,8 @@ BOOL LLTabContainer::setTab(S32 which)
for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
{
LLTabTuple* tuple = *iter;
if (!tuple)
continue;
BOOL is_selected = ( tuple == selected_tuple );
tuple->mButton->setUseEllipses(mUseTabEllipses);
tuple->mButton->setHAlign(mFontHalign);

View File

@ -188,10 +188,11 @@ public:
void selectFirstTab();
void selectLastTab();
void selectNextTab();
void selectPrevTab();
void selectPrevTab();
BOOL selectTabPanel( LLPanel* child );
BOOL selectTab(S32 which);
BOOL selectTabByName(const std::string& title);
void setCurrentPanelIndex(S32 index) { mCurrentTabIdx = index; }
BOOL getTabPanelFlashing(LLPanel* child);
void setTabPanelFlashing(LLPanel* child, BOOL state);
@ -242,8 +243,6 @@ private:
void setTabsHidden(BOOL hidden) { mTabsHidden = hidden; }
BOOL getTabsHidden() const { return mTabsHidden; }
void setCurrentPanelIndex(S32 index) { mCurrentTabIdx = index; }
void scrollPrev() { mScrollPos = llmax(0, mScrollPos-1); } // No wrap
void scrollNext() { mScrollPos = llmin(mScrollPos+1, mMaxScrollPos); } // No wrap

View File

@ -46,6 +46,7 @@
const F32 CURSOR_FLASH_DELAY = 1.0f; // in seconds
const S32 CURSOR_THICKNESS = 2;
const F32 TRIPLE_CLICK_INTERVAL = 0.3f; // delay between double and triple click.
LLTextBase::line_info::line_info(S32 index_start, S32 index_end, LLRect rect, S32 line_num)
: mDocIndexStart(index_start),
@ -145,6 +146,7 @@ LLTextBase::Params::Params()
: cursor_color("cursor_color"),
text_color("text_color"),
text_readonly_color("text_readonly_color"),
text_tentative_color("text_tentative_color"),
bg_visible("bg_visible", false),
border_visible("border_visible", false),
bg_readonly_color("bg_readonly_color"),
@ -179,7 +181,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)
: LLUICtrl(p, LLTextViewModelPtr(new LLTextViewModel)),
mURLClickSignal(NULL),
mMaxTextByteLength( p.max_text_length ),
mDefaultFont(p.font),
mFont(p.font),
mFontShadow(p.font_shadow),
mPopupMenu(NULL),
mReadOnly(p.read_only),
@ -190,6 +192,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)
mFgColor(p.text_color),
mBorderVisible( p.border_visible ),
mReadOnlyFgColor(p.text_readonly_color),
mTentativeFgColor(p.text_tentative_color()),
mWriteableBgColor(p.bg_writeable_color),
mReadOnlyBgColor(p.bg_readonly_color),
mFocusBgColor(p.bg_focus_color),
@ -319,21 +322,26 @@ bool LLTextBase::truncate()
return did_truncate;
}
const LLStyle::Params& LLTextBase::getDefaultStyleParams()
const LLStyle::Params& LLTextBase::getStyleParams()
{
//FIXME: convert mDefaultStyle to a flyweight http://www.boost.org/doc/libs/1_40_0/libs/flyweight/doc/index.html
//and eliminate color member values
if (mStyleDirty)
{
mDefaultStyle
mStyle
.color(LLUIColor(&mFgColor)) // pass linked color instead of copy of mFGColor
.readonly_color(LLUIColor(&mReadOnlyFgColor))
.selected_color(LLUIColor(&mTextSelectedColor))
.font(mDefaultFont)
.font(mFont)
.drop_shadow(mFontShadow);
mStyleDirty = false;
}
return mDefaultStyle;
return mStyle;
}
void LLTextBase::beforeValueChange()
{
}
void LLTextBase::onValueChange(S32 start, S32 end)
@ -351,6 +359,7 @@ void LLTextBase::drawSelectionBackground()
S32 selection_left = llmin( mSelectionStart, mSelectionEnd );
S32 selection_right = llmax( mSelectionStart, mSelectionEnd );
LLRect selection_rect = mVisibleTextRect;
// Skip through the lines we aren't drawing.
LLRect content_display_rect = getVisibleDocumentRect();
@ -512,8 +521,8 @@ void LLTextBase::drawCursor()
LLRect screen_pos = calcScreenRect();
LLCoordGL ime_pos( screen_pos.mLeft + llfloor(cursor_rect.mLeft), screen_pos.mBottom + llfloor(cursor_rect.mTop) );
ime_pos.mX = (S32) (ime_pos.mX * LLUI::getScaleFactor().mV[VX]);
ime_pos.mY = (S32) (ime_pos.mY * LLUI::getScaleFactor().mV[VY]);
ime_pos.mX = (S32) (ime_pos.mX * LLUI::sGLScaleFactor.mV[VX]);
ime_pos.mY = (S32) (ime_pos.mY * LLUI::sGLScaleFactor.mV[VY]);
getWindow()->setLanguageTextInput( ime_pos );
}
}
@ -521,11 +530,17 @@ void LLTextBase::drawCursor()
void LLTextBase::drawText()
{
const S32 text_len = getLength();
if( text_len <= 0 )
S32 text_len = getLength();
if (text_len <= 0 && mLabel.empty())
{
return;
}
else if (useLabel())
{
text_len = mLabel.getWString().length();
}
S32 selection_left = -1;
S32 selection_right = -1;
// Draw selection even if we don't have keyboard focus for search/replace
@ -591,7 +606,8 @@ void LLTextBase::drawText()
// Find the start of the first word
U32 word_start = seg_start, word_end = -1;
while ( (word_start < wstrText.length()) && (!LLStringOps::isAlpha(wstrText[word_start])) )
U32 text_length = wstrText.length();
while ( (word_start < text_length) && (!LLStringOps::isAlpha(wstrText[word_start])) )
{
word_start++;
}
@ -613,11 +629,15 @@ void LLTextBase::drawText()
break;
}
// Don't process words shorter than 3 characters
std::string word = wstring_to_utf8str(wstrText.substr(word_start, word_end - word_start));
if ( (word.length() >= 3) && (!LLSpellChecker::instance().checkSpelling(word)) )
if (word_start < text_length && word_end <= text_length && word_end > word_start)
{
mMisspellRanges.push_back(std::pair<U32, U32>(word_start, word_end));
std::string word = wstring_to_utf8str(wstrText.substr(word_start, word_end - word_start));
// Don't process words shorter than 3 characters
if ( (word.length() >= 3) && (!LLSpellChecker::instance().checkSpelling(word)) )
{
mMisspellRanges.push_back(std::pair<U32, U32>(word_start, word_end));
}
}
// Find the start of the next word
@ -738,6 +758,8 @@ void LLTextBase::drawText()
S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::segment_vec_t* segments )
{
beforeValueChange();
S32 old_len = getLength(); // length() returns character length
S32 insert_len = wstr.length();
@ -769,7 +791,7 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s
else
{
// create default editable segment to hold new text
LLStyleConstSP sp(new LLStyle(getDefaultStyleParams()));
LLStyleConstSP sp(new LLStyle(getStyleParams()));
default_segment = new LLNormalTextSegment( sp, pos, pos + insert_len, *this);
}
@ -813,6 +835,8 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s
S32 LLTextBase::removeStringNoUndo(S32 pos, S32 length)
{
beforeValueChange();
segment_set_t::iterator seg_iter = getSegIterContaining(pos);
while(seg_iter != mSegments.end())
{
@ -871,6 +895,8 @@ S32 LLTextBase::removeStringNoUndo(S32 pos, S32 length)
S32 LLTextBase::overwriteCharNoUndo(S32 pos, llwchar wc)
{
beforeValueChange();
if (pos > (S32)getLength())
{
return 0;
@ -889,7 +915,7 @@ void LLTextBase::createDefaultSegment()
// ensures that there is always at least one segment
if (mSegments.empty())
{
LLStyleConstSP sp(new LLStyle(getDefaultStyleParams()));
LLStyleConstSP sp(new LLStyle(getStyleParams()));
LLTextSegmentPtr default_segment = new LLNormalTextSegment( sp, 0, getLength() + 1, *this);
mSegments.insert(default_segment);
default_segment->linkToDocument(this);
@ -979,6 +1005,13 @@ void LLTextBase::insertSegment(LLTextSegmentPtr segment_to_insert)
BOOL LLTextBase::handleMouseDown(S32 x, S32 y, MASK mask)
{
// handle triple click
if (!mTripleClickTimer.hasExpired())
{
selectAll();
return TRUE;
}
LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y);
if (cur_segment && cur_segment->handleMouseDown(x, y, mask))
{
@ -1053,6 +1086,7 @@ BOOL LLTextBase::handleRightMouseUp(S32 x, S32 y, MASK mask)
BOOL LLTextBase::handleDoubleClick(S32 x, S32 y, MASK mask)
{
mTripleClickTimer.setTimerExpirySec(TRIPLE_CLICK_INTERVAL);
LLTextSegmentPtr cur_segment = getSegmentAtLocalPos(x, y);
if (cur_segment && cur_segment->handleDoubleClick(x, y, mask))
{
@ -1337,6 +1371,25 @@ void LLTextBase::onSpellCheckSettingsChange()
mSpellCheckStart = mSpellCheckEnd = -1;
}
void LLTextBase::onFocusReceived()
{
LLUICtrl::onFocusReceived();
if (!getLength() && !mLabel.empty())
{
// delete label which is LLLabelTextSegment
clearSegments();
}
}
void LLTextBase::onFocusLost()
{
LLUICtrl::onFocusLost();
if (!getLength() && !mLabel.empty())
{
resetLabel();
}
}
// Sets the scrollbar from the cursor position
void LLTextBase::updateScrollFromCursor()
{
@ -1923,7 +1976,7 @@ static LLFastTimer::DeclareTimer FTM_PARSE_HTML("Parse HTML");
void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params)
{
LLStyle::Params style_params(input_params);
style_params.fillFrom(getDefaultStyleParams());
style_params.fillFrom(getStyleParams());
S32 part = (S32)LLTextParser::WHOLE;
if (mParseHTML && !style_params.is_link) // Don't search for URLs inside a link segment (STORM-358).
@ -2008,6 +2061,44 @@ void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, c
appendTextImpl(new_text,input_params);
}
void LLTextBase::setLabel(const LLStringExplicit& label)
{
mLabel = label;
resetLabel();
}
BOOL LLTextBase::setLabelArg(const std::string& key, const LLStringExplicit& text )
{
mLabel.setArg(key, text);
return TRUE;
}
void LLTextBase::resetLabel()
{
if (useLabel())
{
clearSegments();
LLStyle* style = new LLStyle(getStyleParams());
style->setColor(mTentativeFgColor);
LLStyleConstSP sp(style);
LLTextSegmentPtr label = new LLLabelTextSegment(sp, 0, mLabel.getWString().length() + 1, *this);
insertSegment(label);
}
}
bool LLTextBase::useLabel()
{
return !getLength() && !mLabel.empty() && !hasFocus();
}
void LLTextBase::setFont(const LLFontGL* font)
{
mFont = font;
mStyleDirty = true;
}
void LLTextBase::needsReflow(S32 index)
{
lldebugs << "reflow on object " << (void*)this << " index = " << mReflowIndex << ", new index = " << index << llendl;
@ -2238,6 +2329,7 @@ const LLWString& LLTextBase::getWText() const
S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round, bool hit_past_end_of_line) const
{
// Figure out which line we're nearest to.
LLRect visible_region = getVisibleDocumentRect();
LLRect doc_rect = mDocumentView->getRect();
S32 doc_y = local_y - doc_rect.mBottom;
@ -2397,7 +2489,7 @@ LLRect LLTextBase::getLocalRectFromDocIndex(S32 pos) const
{
// return default height rect in upper left
local_rect = content_window_rect;
local_rect.mBottom = local_rect.mTop - mDefaultFont->getLineHeight();
local_rect.mBottom = local_rect.mTop - mFont->getLineHeight();
return local_rect;
}
@ -2902,7 +2994,7 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele
{
F32 alpha = LLViewDrawContext::getCurrentContext().mAlpha;
const LLWString &text = mEditor.getWText();
const LLWString &text = getWText();
F32 right_x = rect.mLeft;
if (!mStyle->isVisible())
@ -3065,7 +3157,7 @@ bool LLNormalTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& widt
if (num_chars > 0)
{
height = mFontHeight;
const LLWString &text = mEditor.getWText();
const LLWString &text = getWText();
// if last character is a newline, then return true, forcing line break
width = mStyle->getFont()->getWidth(text.c_str(), mStart + first_char, num_chars);
}
@ -3074,7 +3166,7 @@ bool LLNormalTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& widt
S32 LLNormalTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const
{
const LLWString &text = mEditor.getWText();
const LLWString &text = getWText();
return mStyle->getFont()->charFromPixelOffset(text.c_str(), mStart + start_offset,
(F32)segment_local_x_coord,
F32_MAX,
@ -3084,7 +3176,7 @@ S32 LLNormalTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset,
S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const
{
const LLWString &text = mEditor.getWText();
const LLWString &text = getWText();
LLUIImagePtr image = mStyle->getImage();
if( image.notNull())
@ -3120,7 +3212,7 @@ S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin
S32 last_char_in_run = mStart + segment_offset + num_chars;
// check length first to avoid indexing off end of string
if (last_char_in_run < mEnd
&& (last_char_in_run >= mEditor.getLength() ))
&& (last_char_in_run >= getLength()))
{
num_chars++;
}
@ -3138,6 +3230,39 @@ void LLNormalTextSegment::dump() const
llendl;
}
/*virtual*/
const LLWString& LLNormalTextSegment::getWText() const
{
return mEditor.getWText();
}
/*virtual*/
const S32 LLNormalTextSegment::getLength() const
{
return mEditor.getLength();
}
LLLabelTextSegment::LLLabelTextSegment( LLStyleConstSP style, S32 start, S32 end, LLTextBase& editor )
: LLNormalTextSegment(style, start, end, editor)
{
}
LLLabelTextSegment::LLLabelTextSegment( const LLColor4& color, S32 start, S32 end, LLTextBase& editor, BOOL is_visible)
: LLNormalTextSegment(color, start, end, editor, is_visible)
{
}
/*virtual*/
const LLWString& LLLabelTextSegment::getWText() const
{
return mEditor.getWlabel();
}
/*virtual*/
const S32 LLLabelTextSegment::getLength() const
{
return mEditor.getWlabel().length();
}
//
// LLOnHoverChangeableTextSegment
//

View File

@ -106,7 +106,7 @@ class LLNormalTextSegment : public LLTextSegment
public:
LLNormalTextSegment( LLStyleConstSP style, S32 start, S32 end, LLTextBase& editor );
LLNormalTextSegment( const LLColor4& color, S32 start, S32 end, LLTextBase& editor, BOOL is_visible = TRUE);
~LLNormalTextSegment();
virtual ~LLNormalTextSegment();
/*virtual*/ bool getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const;
/*virtual*/ S32 getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const;
@ -131,6 +131,9 @@ public:
protected:
F32 drawClippedSegment(S32 seg_start, S32 seg_end, S32 selection_start, S32 selection_end, LLRect rect);
virtual const LLWString& getWText() const;
virtual const S32 getLength() const;
protected:
class LLTextBase& mEditor;
LLStyleConstSP mStyle;
@ -140,6 +143,21 @@ protected:
boost::signals2::connection mImageLoadedConnection;
};
// This text segment is the same as LLNormalTextSegment, the only difference
// is that LLNormalTextSegment draws value of LLTextBase (LLTextBase::getWText()),
// but LLLabelTextSegment draws label of the LLTextBase (LLTextBase::mLabel)
class LLLabelTextSegment : public LLNormalTextSegment
{
public:
LLLabelTextSegment( LLStyleConstSP style, S32 start, S32 end, LLTextBase& editor );
LLLabelTextSegment( const LLColor4& color, S32 start, S32 end, LLTextBase& editor, BOOL is_visible = TRUE);
protected:
/*virtual*/ const LLWString& getWText() const;
/*virtual*/ const S32 getLength() const;
};
// Text segment that changes it's style depending of mouse pointer position ( is it inside or outside segment)
class LLOnHoverChangeableTextSegment : public LLNormalTextSegment
{
@ -251,6 +269,7 @@ public:
Optional<LLUIColor> cursor_color,
text_color,
text_readonly_color,
text_tentative_color,
bg_readonly_color,
bg_writeable_color,
bg_focus_color,
@ -314,6 +333,9 @@ public:
/*virtual*/ BOOL canDeselect() const;
/*virtual*/ void deselect();
virtual void onFocusReceived();
virtual void onFocusLost();
// LLSpellCheckMenuHandler overrides
/*virtual*/ bool getSpellCheck() const;
@ -351,6 +373,21 @@ public:
const LLWString& getWText() const;
void appendText(const std::string &new_text, bool prepend_newline, const LLStyle::Params& input_params = LLStyle::Params());
void setLabel(const LLStringExplicit& label);
virtual BOOL setLabelArg(const std::string& key, const LLStringExplicit& text );
const std::string& getLabel() { return mLabel.getString(); }
const LLWString& getWlabel() { return mLabel.getWString();}
/**
* If label is set, draws text label (which is LLLabelTextSegment)
* that is visible when no user text provided
*/
void resetLabel();
void setFont(const LLFontGL* font);
// force reflow of text
void needsReflow(S32 index = 0);
@ -390,7 +427,7 @@ public:
bool scrolledToStart();
bool scrolledToEnd();
const LLFontGL* getDefaultFont() const { return mDefaultFont; }
const LLFontGL* getFont() const { return mFont; }
virtual void appendLineBreakSegment(const LLStyle::Params& style_params);
virtual void appendImageSegment(const LLStyle::Params& style_params);
@ -464,7 +501,9 @@ protected:
LLTextBase(const Params &p);
virtual ~LLTextBase();
void initFromParams(const Params& p);
virtual void beforeValueChange();
virtual void onValueChange(S32 start, S32 end);
virtual bool useLabel();
// draw methods
void drawSelectionBackground(); // draws the black box behind the selected text
@ -490,7 +529,7 @@ protected:
void createDefaultSegment();
virtual void updateSegments();
void insertSegment(LLTextSegmentPtr segment_to_insert);
const LLStyle::Params& getDefaultStyleParams();
const LLStyle::Params& getStyleParams();
// manage lines
S32 getLineStart( S32 line ) const;
@ -535,15 +574,16 @@ protected:
LLRect mTextBoundingRect;
// default text style
LLStyle::Params mDefaultStyle;
LLStyle::Params mStyle;
bool mStyleDirty;
const LLFontGL* const mDefaultFont; // font that is used when none specified, can only be set by constructor
const LLFontGL::ShadowType mFontShadow; // shadow style, can only be set by constructor
const LLFontGL* mFont;
const LLFontGL::ShadowType mFontShadow;
// colors
LLUIColor mCursorColor;
LLUIColor mFgColor;
LLUIColor mReadOnlyFgColor;
LLUIColor mTentativeFgColor;
LLUIColor mWriteableBgColor;
LLUIColor mReadOnlyBgColor;
LLUIColor mFocusBgColor;
@ -558,7 +598,8 @@ protected:
// selection
S32 mSelectionStart;
S32 mSelectionEnd;
LLTimer mTripleClickTimer;
BOOL mIsSelecting; // Are we in the middle of a drag-select?
// spell checking
@ -587,6 +628,7 @@ protected:
bool mClip; // clip text to widget rect
bool mClipPartial; // false if we show lines that are partially inside bounding rect
bool mPlainText; // didn't use Image or Icon segments
bool mAutoIndent;
S32 mMaxTextByteLength; // Maximum length mText is allowed to be in bytes
// support widgets
@ -602,6 +644,7 @@ protected:
// Fired when a URL link is clicked
commit_signal_t* mURLClickSignal;
LLUIString mLabel; // text label that is visible when no user text provided
};
#endif

View File

@ -237,6 +237,7 @@ LLTextEditor::Params::Params()
embedded_items("embedded_items", false),
ignore_tab("ignore_tab", true),
show_line_numbers("show_line_numbers", false),
auto_indent("auto_indent", true),
default_color("default_color"),
commit_on_focus_lost("commit_on_focus_lost", false),
show_context_menu("show_context_menu"),
@ -247,11 +248,13 @@ LLTextEditor::Params::Params()
LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :
LLTextBase(p),
mAutoreplaceCallback(),
mBaseDocIsPristine(TRUE),
mPristineCmd( NULL ),
mLastCmd( NULL ),
mDefaultColor( p.default_color() ),
mShowLineNumbers ( p.show_line_numbers ),
mAutoIndent(p.auto_indent),
mCommitOnFocusLost( p.commit_on_focus_lost),
mAllowEmbeddedItems( p.embedded_items ),
mMouseDownX(0),
@ -260,7 +263,8 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :
mPrevalidateFunc(p.prevalidate_callback()),
mContextMenu(NULL),
mShowContextMenu(p.show_context_menu),
mEnableTooltipPaste(p.enable_tooltip_paste)
mEnableTooltipPaste(p.enable_tooltip_paste),
mPassDelete(FALSE)
{
mSourceID.generate();
@ -1096,7 +1100,25 @@ void LLTextEditor::addChar(llwchar wc)
}
setCursorPos(mCursorPos + addChar( mCursorPos, wc ));
if (!mReadOnly && mAutoreplaceCallback != NULL)
{
// autoreplace the text, if necessary
S32 replacement_start;
S32 replacement_length;
LLWString replacement_string;
S32 new_cursor_pos = mCursorPos;
mAutoreplaceCallback(replacement_start, replacement_length, replacement_string, new_cursor_pos, getWText());
if (replacement_length > 0 || !replacement_string.empty())
{
remove(replacement_start, replacement_length, true);
insert(replacement_start, replacement_string, false, LLTextSegmentPtr());
setCursorPos(new_cursor_pos);
}
}
}
void LLTextEditor::addLineBreakChar()
{
if( !getEnabled() )
@ -1621,7 +1643,10 @@ BOOL LLTextEditor::handleSpecialKey(const KEY key, const MASK mask)
{
deleteSelection(FALSE);
}
autoIndent(); // TODO: make this optional
if (mAutoIndent)
{
autoIndent();
}
}
else
{
@ -1792,7 +1817,7 @@ BOOL LLTextEditor::handleUnicodeCharHere(llwchar uni_char)
// virtual
BOOL LLTextEditor::canDoDelete() const
{
return !mReadOnly && ( hasSelection() || (mCursorPos < getLength()) );
return !mReadOnly && ( !mPassDelete || ( hasSelection() || (mCursorPos < getLength())) );
}
void LLTextEditor::doDelete()
@ -2061,7 +2086,7 @@ void LLTextEditor::drawPreeditMarker()
return;
}
const S32 line_height = mDefaultFont->getLineHeight();
const S32 line_height = mFont->getLineHeight();
S32 line_start = getLineStart(cur_line);
S32 line_y = mVisibleTextRect.mTop - line_height;
@ -2100,16 +2125,16 @@ void LLTextEditor::drawPreeditMarker()
S32 preedit_left = mVisibleTextRect.mLeft;
if (left > line_start)
{
preedit_left += mDefaultFont->getWidth(text, line_start, left - line_start);
preedit_left += mFont->getWidth(text, line_start, left - line_start);
}
S32 preedit_right = mVisibleTextRect.mLeft;
if (right < line_end)
{
preedit_right += mDefaultFont->getWidth(text, line_start, right - line_start);
preedit_right += mFont->getWidth(text, line_start, right - line_start);
}
else
{
preedit_right += mDefaultFont->getWidth(text, line_start, line_end - line_start);
preedit_right += mFont->getWidth(text, line_start, line_end - line_start);
}
if (mPreeditStandouts[i])
@ -2783,11 +2808,11 @@ BOOL LLTextEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect
const LLWString textString(getWText());
const llwchar * const text = textString.c_str();
const S32 line_height = mDefaultFont->getLineHeight();
const S32 line_height = mFont->getLineHeight();
if (coord)
{
const S32 query_x = mVisibleTextRect.mLeft + mDefaultFont->getWidth(text, current_line_start, query - current_line_start);
const S32 query_x = mVisibleTextRect.mLeft + mFont->getWidth(text, current_line_start, query - current_line_start);
const S32 query_y = mVisibleTextRect.mTop - (current_line - first_visible_line) * line_height - line_height / 2;
S32 query_screen_x, query_screen_y;
localPointToScreen(query_x, query_y, &query_screen_x, &query_screen_y);
@ -2799,17 +2824,17 @@ BOOL LLTextEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect
S32 preedit_left = mVisibleTextRect.mLeft;
if (preedit_left_position > current_line_start)
{
preedit_left += mDefaultFont->getWidth(text, current_line_start, preedit_left_position - current_line_start);
preedit_left += mFont->getWidth(text, current_line_start, preedit_left_position - current_line_start);
}
S32 preedit_right = mVisibleTextRect.mLeft;
if (preedit_right_position < current_line_end)
{
preedit_right += mDefaultFont->getWidth(text, current_line_start, preedit_right_position - current_line_start);
preedit_right += mFont->getWidth(text, current_line_start, preedit_right_position - current_line_start);
}
else
{
preedit_right += mDefaultFont->getWidth(text, current_line_start, current_line_end - current_line_start);
preedit_right += mFont->getWidth(text, current_line_start, current_line_end - current_line_start);
}
const S32 preedit_top = mVisibleTextRect.mTop - (current_line - first_visible_line) * line_height;
@ -2886,7 +2911,7 @@ void LLTextEditor::markAsPreedit(S32 position, S32 length)
S32 LLTextEditor::getPreeditFontSize() const
{
return llround((F32)mDefaultFont->getLineHeight() * LLUI::getScaleFactor().mV[VY]);
return llround((F32)mFont->getLineHeight() * LLUI::sGLScaleFactor.mV[VY]);
}
BOOL LLTextEditor::isDirty() const

View File

@ -65,7 +65,8 @@ public:
show_line_numbers,
commit_on_focus_lost,
show_context_menu,
enable_tooltip_paste;
enable_tooltip_paste,
auto_indent;
//colors
Optional<LLUIColor> default_color;
@ -157,6 +158,11 @@ public:
BOOL isPristine() const;
BOOL allowsEmbeddedItems() const { return mAllowEmbeddedItems; }
// Autoreplace (formerly part of LLLineEditor)
typedef boost::function<void(S32&, S32&, LLWString&, S32&, const LLWString&)> autoreplace_callback_t;
autoreplace_callback_t mAutoreplaceCallback;
void setAutoreplaceCallback(autoreplace_callback_t cb) { mAutoreplaceCallback = cb; }
//
// Text manipulation
//
@ -203,6 +209,8 @@ public:
void setShowContextMenu(bool show) { mShowContextMenu = show; }
bool getShowContextMenu() const { return mShowContextMenu; }
void setPassDelete(BOOL b) { mPassDelete = b; }
protected:
void showContextMenu(S32 x, S32 y);
void drawPreeditMarker();
@ -215,8 +223,8 @@ protected:
S32 indentLine( S32 pos, S32 spaces );
void unindentLineBeforeCloseBrace();
virtual BOOL handleSpecialKey(const KEY key, const MASK mask);
BOOL handleNavigationKey(const KEY key, const MASK mask);
BOOL handleSpecialKey(const KEY key, const MASK mask);
BOOL handleSelectionKey(const KEY key, const MASK mask);
BOOL handleControlKey(const KEY key, const MASK mask);
@ -280,6 +288,7 @@ protected:
LLUIColor mDefaultColor;
BOOL mShowLineNumbers;
bool mAutoIndent;
/*virtual*/ void updateSegments();
void updateLinkSegments();
@ -325,6 +334,7 @@ private:
bool mShowContextMenu;
bool mParseOnTheFly;
bool mEnableTooltipPaste;
bool mPassDelete;
LLUUID mSourceID;

View File

@ -60,6 +60,8 @@ public:
// its visibility off.
bool toggleVisibility();
LLHandle<LLToggleableMenu> getHandle() { return getDerivedHandle<LLToggleableMenu>(); }
protected:
bool mClosedByButtonClick;
LLRect mButtonRect;

View File

@ -868,8 +868,15 @@ void LLToolBar::reshape(S32 width, S32 height, BOOL called_from_parent)
void LLToolBar::createButtons()
{
std::set<LLUUID> set_flashing;
BOOST_FOREACH(LLToolBarButton* button, mButtons)
{
if (button->getFlashTimer() && button->getFlashTimer()->isFlashingInProgress())
{
set_flashing.insert(button->getCommandId().uuid());
}
if (mButtonRemoveSignal)
{
(*mButtonRemoveSignal)(button);
@ -892,6 +899,11 @@ void LLToolBar::createButtons()
{
(*mButtonAddSignal)(button);
}
if (set_flashing.find(button->getCommandId().uuid()) != set_flashing.end())
{
button->setFlashing(true);
}
}
mNeedsLayout = true;
}
@ -916,6 +928,7 @@ LLToolBarButton* LLToolBar::createButton(const LLCommandId& id)
button_p.label = LLTrans::getString(commandp->labelRef());
button_p.tool_tip = LLTrans::getString(commandp->tooltipRef());
button_p.image_overlay = LLUI::getUIImage(commandp->icon());
button_p.button_flash_enable = commandp->isFlashingAllowed();
button_p.overwriteFrom(mButtonParams[mButtonType]);
LLToolBarButton* button = LLUICtrlFactory::create<LLToolBarButton>(button_p);

View File

@ -288,7 +288,7 @@ void LLToolTip::initFromParams(const LLToolTip::Params& p)
mTextBox->setText(p.message());
}
S32 text_width = llmin(p.max_width(), mTextBox->getTextPixelWidth());
S32 text_width = llmin(p.max_width(), mTextBox->getTextPixelWidth() + 1);
S32 text_height = mTextBox->getTextPixelHeight();
mTextBox->reshape(text_width, text_height);
if (mInfoButton)

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/**
* @file llui.h
* @brief General static UI services.
* @brief GL function declarations and other general static UI services.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
@ -24,36 +24,121 @@
* $/LicenseInfo$
*/
// All immediate-mode gl drawing should happen here.
#ifndef LL_LLUI_H
#define LL_LLUI_H
#include "llpointer.h" // LLPointer<>
#include "llrect.h"
#include "llcontrol.h"
#include "llcoord.h"
#include "v2math.h"
#include "llglslshader.h"
#include "llinitparam.h"
#include "llregistry.h"
#include "llrender2dutils.h"
#include "llpointer.h"
#include "lluicolor.h"
#include "lluicolortable.h"
#include "lluiimage.h"
#include <boost/signals2.hpp>
#include "lllazyvalue.h"
#include "llframetimer.h"
#include <limits>
// LLUIFactory
#include "llsd.h"
// for initparam specialization
#include "llfontgl.h"
class LLColor4;
class LLVector3;
class LLVector2;
class LLUIImage;
class LLUUID;
class LLWindow;
class LLView;
class LLHelp;
// UI colors
extern const LLColor4 UI_VERTEX_COLOR;
void make_ui_sound(const char* name);
void make_ui_sound_deferred(const char * name);
BOOL ui_point_in_rect(S32 x, S32 y, S32 left, S32 top, S32 right, S32 bottom);
void gl_state_for_2d(S32 width, S32 height);
void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2);
void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2, const LLColor4 &color );
void gl_triangle_2d(S32 x1, S32 y1, S32 x2, S32 y2, S32 x3, S32 y3, const LLColor4& color, BOOL filled);
void gl_rect_2d_simple( S32 width, S32 height );
void gl_draw_x(const LLRect& rect, const LLColor4& color);
void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, BOOL filled = TRUE );
void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, BOOL filled = TRUE );
void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, S32 pixel_offset = 0, BOOL filled = TRUE );
void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, S32 pixel_offset = 0, BOOL filled = TRUE );
void gl_rect_2d(const LLRect& rect, BOOL filled = TRUE );
void gl_rect_2d(const LLRect& rect, const LLColor4& color, BOOL filled = TRUE );
void gl_rect_2d_checkerboard(const LLRect& rect, GLfloat alpha = 1.0f);
void gl_drop_shadow(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &start_color, S32 lines);
void gl_circle_2d(F32 x, F32 y, F32 radius, S32 steps, BOOL filled);
void gl_arc_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled, F32 start_angle, F32 end_angle);
void gl_deep_circle( F32 radius, F32 depth );
void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor4& side_color, S32 steps, BOOL render_center );
void gl_corners_2d(S32 left, S32 top, S32 right, S32 bottom, S32 length, F32 max_frac);
void gl_washer_2d(F32 outer_radius, F32 inner_radius, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color);
void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians, F32 end_radians, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color);
void gl_draw_image(S32 x, S32 y, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees,LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), const LLRectf& scale_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase = 0.f );
void gl_rect_2d_simple_tex( S32 width, S32 height );
// segmented rectangles
/*
TL |______TOP_________| TR
/| |\
_/_|__________________|_\_
L| | MIDDLE | |R
_|_|__________________|_|_
\ | BOTTOM | /
BL\|__________________|/ BR
| |
*/
typedef enum e_rounded_edge
{
ROUNDED_RECT_LEFT = 0x1,
ROUNDED_RECT_TOP = 0x2,
ROUNDED_RECT_RIGHT = 0x4,
ROUNDED_RECT_BOTTOM = 0x8,
ROUNDED_RECT_ALL = 0xf
}ERoundedEdge;
void gl_segmented_rect_2d_tex(const S32 left, const S32 top, const S32 right, const S32 bottom, const S32 texture_width, const S32 texture_height, const S32 border_size, const U32 edges = ROUNDED_RECT_ALL);
void gl_segmented_rect_2d_fragment_tex(const S32 left, const S32 top, const S32 right, const S32 bottom, const S32 texture_width, const S32 texture_height, const S32 border_size, const F32 start_fragment, const F32 end_fragment, const U32 edges = ROUNDED_RECT_ALL);
void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv_rect, const LLRectf& center_draw_rect, const LLVector3& width_vec, const LLVector3& height_vec);
inline void gl_rect_2d( const LLRect& rect, BOOL filled )
{
gl_rect_2d( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, filled );
}
inline void gl_rect_2d_offset_local( const LLRect& rect, S32 pixel_offset, BOOL filled)
{
gl_rect_2d_offset_local( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, pixel_offset, filled );
}
class LLImageProviderInterface;
@ -190,15 +275,16 @@ public:
static void initClass(const settings_map_t& settings,
LLImageProviderInterface* image_provider,
LLUIAudioCallback audio_callback = NULL,
LLUIAudioCallback deferred_audio_callback = NULL,
const LLVector2 *scale_factor = NULL,
const std::string& language = LLStringUtil::null);
static void cleanupClass();
static void setPopupFuncs(const add_popup_t& add_popup, const remove_popup_t&, const clear_popups_t& );
static void pushMatrix() { LLRender2D::pushMatrix(); }
static void popMatrix() { LLRender2D::popMatrix(); }
static void loadIdentity() { LLRender2D::loadIdentity(); }
static void translate(F32 x, F32 y, F32 z = 0.0f) { LLRender2D::translate(x, y, z); }
static void pushMatrix();
static void popMatrix();
static void loadIdentity();
static void translate(F32 x, F32 y, F32 z = 0.0f);
static LLRect sDirtyRect;
static BOOL sDirty;
@ -243,13 +329,10 @@ public:
static void getMousePositionScreen(S32 *x, S32 *y);
static void setMousePositionLocal(const LLView* viewp, S32 x, S32 y);
static void getMousePositionLocal(const LLView* viewp, S32 *x, S32 *y);
static LLVector2& getScaleFactor() { return LLRender2D::sGLScaleFactor; }
static void setScaleFactor(const LLVector2& scale_factor) { LLRender2D::setScaleFactor(scale_factor); }
static void setLineWidth(F32 width) { LLRender2D::setLineWidth(width); }
static LLPointer<LLUIImage> getUIImageByID(const LLUUID& image_id, S32 priority = 0)
{ return LLRender2D::getUIImageByID(image_id, priority); }
static LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority = 0)
{ return LLRender2D::getUIImage(name, priority); }
static void setScaleFactor(const LLVector2& scale_factor);
static void setLineWidth(F32 width);
static LLPointer<LLUIImage> getUIImageByID(const LLUUID& image_id, S32 priority = 0);
static LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority = 0);
static LLVector2 getWindowSize();
static void screenPointToGL(S32 screen_x, S32 screen_y, S32 *gl_x, S32 *gl_y);
static void glPointToScreen(S32 gl_x, S32 gl_y, S32 *screen_x, S32 *screen_y);
@ -278,10 +361,13 @@ public:
//
static settings_map_t sSettingGroups;
static LLUIAudioCallback sAudioCallback;
static LLUIAudioCallback sDeferredAudioCallback;
static LLVector2 sGLScaleFactor;
static LLWindow* sWindow;
static LLView* sRootView;
static LLHelp* sHelpImpl;
private:
static LLImageProviderInterface* sImageProvider;
static std::vector<std::string> sXUIPaths;
static LLFrameTimer sMouseIdleTimer;
static add_popup_t sAddPopupFunc;
@ -292,6 +378,18 @@ private:
// Moved LLLocalClipRect to lllocalcliprect.h
//RN: maybe this needs to moved elsewhere?
class LLImageProviderInterface
{
protected:
LLImageProviderInterface() {};
virtual ~LLImageProviderInterface() {};
public:
virtual LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority) = 0;
virtual LLPointer<LLUIImage> getUIImageByID(const LLUUID& id, S32 priority) = 0;
virtual void cleanUp() = 0;
};
class LLCallbackRegistry
{
public:
@ -342,10 +440,8 @@ public:
// even if their constructors have side effects
void reference()
{
#ifdef LL_WINDOWS
S32 dummy;
dummy = 0;
#endif /*LL_WINDOWS*/
}
};
@ -413,7 +509,7 @@ public:
namespace LLInitParam
{
template<>
class ParamValue<LLRect, TypeValues<LLRect> >
class ParamValue<LLRect>
: public CustomParamValue<LLRect>
{
typedef CustomParamValue<LLRect> super_t;
@ -432,7 +528,7 @@ namespace LLInitParam
};
template<>
class ParamValue<LLUIColor, TypeValues<LLUIColor> >
class ParamValue<LLUIColor>
: public CustomParamValue<LLUIColor>
{
typedef CustomParamValue<LLUIColor> super_t;
@ -450,7 +546,7 @@ namespace LLInitParam
};
template<>
class ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >
class ParamValue<const LLFontGL*>
: public CustomParamValue<const LLFontGL* >
{
typedef CustomParamValue<const LLFontGL*> super_t;
@ -490,7 +586,7 @@ namespace LLInitParam
template<>
class ParamValue<LLCoordGL, TypeValues<LLCoordGL> >
class ParamValue<LLCoordGL>
: public CustomParamValue<LLCoordGL>
{
typedef CustomParamValue<LLCoordGL> super_t;
@ -504,4 +600,7 @@ namespace LLInitParam
};
}
extern LLGLSLShader gSolidColorProgram;
extern LLGLSLShader gUIProgram;
#endif

View File

@ -247,13 +247,13 @@ const LLInitParam::BaseBlock& get_empty_param_block()
// adds a widget and its param block to various registries
//static
void LLUICtrlFactory::registerWidget(const std::type_info* widget_type, const std::type_info* param_block_type, const std::string& tag)
void LLUICtrlFactory::registerWidget(const std::type_info* widget_type, const std::type_info* param_block_type, const std::string& name)
{
// associate parameter block type with template .xml file
std::string* existing_tag = LLWidgetNameRegistry::instance().getValue(param_block_type);
if (existing_tag != NULL)
std::string* existing_name = LLWidgetNameRegistry::instance().getValue(param_block_type);
if (existing_name != NULL)
{
if(*existing_tag != tag)
if(*existing_name != name)
{
std::cerr << "Duplicate entry for T::Params, try creating empty param block in derived classes that inherit T::Params" << std::endl;
// forcing crash here
@ -262,19 +262,15 @@ void LLUICtrlFactory::registerWidget(const std::type_info* widget_type, const st
}
else
{
// widget already registered
// widget already registered this name
return;
}
}
LLWidgetNameRegistry::instance().defaultRegistrar().add(param_block_type, tag);
LLWidgetNameRegistry::instance().defaultRegistrar().add(param_block_type, name);
//FIXME: comment this in when working on schema generation
//LLWidgetTypeRegistry::instance().defaultRegistrar().add(tag, widget_type);
//LLDefaultParamBlockRegistry::instance().defaultRegistrar().add(widget_type, &get_empty_param_block<T>);
}
//static
const std::string* LLUICtrlFactory::getWidgetTag(const std::type_info* widget_type)
{
return LLWidgetNameRegistry::instance().getValue(widget_type);
}

View File

@ -98,7 +98,7 @@ private:
ParamDefaults()
{
// look up template file for this param block...
const std::string* param_block_tag = getWidgetTag(&typeid(PARAM_BLOCK));
const std::string* param_block_tag = LLWidgetNameRegistry::instance().getValue(&typeid(PARAM_BLOCK));
if (param_block_tag)
{ // ...and if it exists, back fill values using the most specific template first
PARAM_BLOCK params;
@ -132,7 +132,6 @@ public:
template<typename T>
static const typename T::Params& getDefaultParams()
{
//#pragma message("Generating ParamDefaults")
return ParamDefaults<typename T::Params, 0>::instance().get();
}
@ -285,8 +284,6 @@ private:
}
static const std::string* getWidgetTag(const std::type_info* widget_type);
// this exists to get around dependency on llview
static void setCtrlParent(LLView* view, LLView* parent, S32 tab_group);

View File

@ -31,7 +31,7 @@
// Project includes
#include "lluiimage.h"
#include "llrender2dutils.h"
#include "llui.h"
LLUIImage::LLUIImage(const std::string& name, LLPointer<LLTexture> image)
: mName(name),
@ -112,6 +112,50 @@ void LLUIImage::drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4&
drawSolid(border_rect, color);
}
void LLUIImage::draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, const LLVector3& y_axis,
const LLRect& rect, const LLColor4& color)
{
F32 border_scale = 1.f;
F32 border_height = (1.f - mScaleRegion.getHeight()) * getHeight();
F32 border_width = (1.f - mScaleRegion.getWidth()) * getWidth();
if (rect.getHeight() < border_height || rect.getWidth() < border_width)
{
if(border_height - rect.getHeight() > border_width - rect.getWidth())
{
border_scale = (F32)rect.getHeight() / border_height;
}
else
{
border_scale = (F32)rect.getWidth() / border_width;
}
}
LLUI::pushMatrix();
{
LLVector3 rect_origin = origin_agent + (rect.mLeft * x_axis) + (rect.mBottom * y_axis);
LLUI::translate(rect_origin.mV[VX],
rect_origin.mV[VY],
rect_origin.mV[VZ]);
gGL.getTexUnit(0)->bind(getImage());
gGL.color4fv(color.mV);
LLRectf center_uv_rect(mClipRegion.mLeft + mScaleRegion.mLeft * mClipRegion.getWidth(),
mClipRegion.mBottom + mScaleRegion.mTop * mClipRegion.getHeight(),
mClipRegion.mLeft + mScaleRegion.mRight * mClipRegion.getWidth(),
mClipRegion.mBottom + mScaleRegion.mBottom * mClipRegion.getHeight());
gl_segmented_rect_3d_tex(mClipRegion,
center_uv_rect,
LLRectf(border_width * border_scale * 0.5f / (F32)rect.getWidth(),
(rect.getHeight() - (border_height * border_scale * 0.5f)) / (F32)rect.getHeight(),
(rect.getWidth() - (border_width * border_scale * 0.5f)) / (F32)rect.getWidth(),
(border_height * border_scale * 0.5f) / (F32)rect.getHeight()),
rect.getWidth() * x_axis,
rect.getHeight() * y_axis);
} LLUI::popMatrix();
}
S32 LLUIImage::getWidth() const
{
// return clipped dimensions of actual image area
@ -155,7 +199,7 @@ void LLUIImage::onImageLoaded()
namespace LLInitParam
{
void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateValueFromBlock()
void ParamValue<LLUIImage*>::updateValueFromBlock()
{
// The keyword "none" is specifically requesting a null image
// do not default to current value. Used to overwrite template images.
@ -165,14 +209,14 @@ namespace LLInitParam
return;
}
LLUIImage* imagep = LLRender2D::getUIImage(name());
LLUIImage* imagep = LLUI::getUIImage(name());
if (imagep)
{
updateValue(imagep);
}
}
void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateBlockFromValue(bool make_block_authoritative)
void ParamValue<LLUIImage*>::updateBlockFromValue(bool make_block_authoritative)
{
if (getValue() == NULL)
{

Some files were not shown because too many files have changed in this diff Show More