diff options
Diffstat (limited to 'linden/indra/llui/lluictrl.cpp')
-rw-r--r-- | linden/indra/llui/lluictrl.cpp | 203 |
1 files changed, 141 insertions, 62 deletions
diff --git a/linden/indra/llui/lluictrl.cpp b/linden/indra/llui/lluictrl.cpp index 61d6c8c..63db1cc 100644 --- a/linden/indra/llui/lluictrl.cpp +++ b/linden/indra/llui/lluictrl.cpp | |||
@@ -13,12 +13,12 @@ | |||
13 | * ("GPL"), unless you have obtained a separate licensing agreement | 13 | * ("GPL"), unless you have obtained a separate licensing agreement |
14 | * ("Other License"), formally executed by you and Linden Lab. Terms of | 14 | * ("Other License"), formally executed by you and Linden Lab. Terms of |
15 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | 15 | * the GPL can be found in doc/GPL-license.txt in this distribution, or |
16 | * online at http://secondlife.com/developers/opensource/gplv2 | 16 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 |
17 | * | 17 | * |
18 | * There are special exceptions to the terms and conditions of the GPL as | 18 | * There are special exceptions to the terms and conditions of the GPL as |
19 | * it is applied to this Source Code. View the full text of the exception | 19 | * it is applied to this Source Code. View the full text of the exception |
20 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 20 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
21 | * online at http://secondlife.com/developers/opensource/flossexception | 21 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception |
22 | * | 22 | * |
23 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
24 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -47,11 +47,53 @@ | |||
47 | 47 | ||
48 | const U32 MAX_STRING_LENGTH = 10; | 48 | const U32 MAX_STRING_LENGTH = 10; |
49 | 49 | ||
50 | LLUICtrl::LLUICtrl() : | 50 | LLFocusableElement::LLFocusableElement() |
51 | mCommitCallback(NULL), | 51 | : mFocusLostCallback(NULL), |
52 | mFocusLostCallback(NULL), | ||
53 | mFocusReceivedCallback(NULL), | 52 | mFocusReceivedCallback(NULL), |
54 | mFocusChangedCallback(NULL), | 53 | mFocusChangedCallback(NULL), |
54 | mFocusCallbackUserData(NULL) | ||
55 | { | ||
56 | } | ||
57 | |||
58 | void LLFocusableElement::onFocusReceived() | ||
59 | { | ||
60 | if( mFocusReceivedCallback ) | ||
61 | { | ||
62 | mFocusReceivedCallback( this, mFocusCallbackUserData ); | ||
63 | } | ||
64 | if( mFocusChangedCallback ) | ||
65 | { | ||
66 | mFocusChangedCallback( this, mFocusCallbackUserData ); | ||
67 | } | ||
68 | } | ||
69 | |||
70 | void LLFocusableElement::onFocusLost() | ||
71 | { | ||
72 | if( mFocusLostCallback ) | ||
73 | { | ||
74 | mFocusLostCallback( this, mFocusCallbackUserData ); | ||
75 | } | ||
76 | |||
77 | if( mFocusChangedCallback ) | ||
78 | { | ||
79 | mFocusChangedCallback( this, mFocusCallbackUserData ); | ||
80 | } | ||
81 | } | ||
82 | |||
83 | BOOL LLFocusableElement::hasFocus() const | ||
84 | { | ||
85 | return FALSE; | ||
86 | } | ||
87 | |||
88 | void LLFocusableElement::setFocus(BOOL b) | ||
89 | { | ||
90 | } | ||
91 | |||
92 | |||
93 | |||
94 | LLUICtrl::LLUICtrl() : | ||
95 | mCommitCallback(NULL), | ||
96 | mLostTopCallback(NULL), | ||
55 | mValidateCallback(NULL), | 97 | mValidateCallback(NULL), |
56 | mCallbackUserData(NULL), | 98 | mCallbackUserData(NULL), |
57 | mTentative(FALSE), | 99 | mTentative(FALSE), |
@@ -68,9 +110,7 @@ LLUICtrl::LLUICtrl(const LLString& name, const LLRect& rect, BOOL mouse_opaque, | |||
68 | // of buttons in the UI. JC 7/20/2002 | 110 | // of buttons in the UI. JC 7/20/2002 |
69 | LLView( name, rect, mouse_opaque, reshape ), | 111 | LLView( name, rect, mouse_opaque, reshape ), |
70 | mCommitCallback( on_commit_callback) , | 112 | mCommitCallback( on_commit_callback) , |
71 | mFocusLostCallback( NULL ), | 113 | mLostTopCallback( NULL ), |
72 | mFocusReceivedCallback( NULL ), | ||
73 | mFocusChangedCallback( NULL ), | ||
74 | mValidateCallback( NULL ), | 114 | mValidateCallback( NULL ), |
75 | mCallbackUserData( callback_userdata ), | 115 | mCallbackUserData( callback_userdata ), |
76 | mTentative( FALSE ), | 116 | mTentative( FALSE ), |
@@ -128,6 +168,86 @@ LLCtrlScrollInterface* LLUICtrl::getScrollInterface() | |||
128 | return NULL; | 168 | return NULL; |
129 | } | 169 | } |
130 | 170 | ||
171 | BOOL LLUICtrl::hasFocus() const | ||
172 | { | ||
173 | return (gFocusMgr.childHasKeyboardFocus(this)); | ||
174 | } | ||
175 | |||
176 | void LLUICtrl::setFocus(BOOL b) | ||
177 | { | ||
178 | // focus NEVER goes to ui ctrls that are disabled! | ||
179 | if (!mEnabled) | ||
180 | { | ||
181 | return; | ||
182 | } | ||
183 | if( b ) | ||
184 | { | ||
185 | if (!hasFocus()) | ||
186 | { | ||
187 | gFocusMgr.setKeyboardFocus( this ); | ||
188 | } | ||
189 | } | ||
190 | else | ||
191 | { | ||
192 | if( gFocusMgr.childHasKeyboardFocus(this)) | ||
193 | { | ||
194 | gFocusMgr.setKeyboardFocus( NULL ); | ||
195 | } | ||
196 | } | ||
197 | } | ||
198 | |||
199 | void LLUICtrl::onFocusReceived() | ||
200 | { | ||
201 | // trigger callbacks | ||
202 | LLFocusableElement::onFocusReceived(); | ||
203 | |||
204 | // find first view in hierarchy above new focus that is a LLUICtrl | ||
205 | LLView* viewp = getParent(); | ||
206 | LLUICtrl* last_focus = gFocusMgr.getLastKeyboardFocus(); | ||
207 | |||
208 | while (viewp && !viewp->isCtrl()) | ||
209 | { | ||
210 | viewp = viewp->getParent(); | ||
211 | } | ||
212 | |||
213 | // and if it has newly gained focus, call onFocusReceived() | ||
214 | LLUICtrl* ctrlp = static_cast<LLUICtrl*>(viewp); | ||
215 | if (ctrlp && (!last_focus || !last_focus->hasAncestor(ctrlp))) | ||
216 | { | ||
217 | ctrlp->onFocusReceived(); | ||
218 | } | ||
219 | } | ||
220 | |||
221 | void LLUICtrl::onFocusLost() | ||
222 | { | ||
223 | // trigger callbacks | ||
224 | LLFocusableElement::onFocusLost(); | ||
225 | |||
226 | // find first view in hierarchy above old focus that is a LLUICtrl | ||
227 | LLView* viewp = getParent(); | ||
228 | while (viewp && !viewp->isCtrl()) | ||
229 | { | ||
230 | viewp = viewp->getParent(); | ||
231 | } | ||
232 | |||
233 | // and if it has just lost focus, call onFocusReceived() | ||
234 | LLUICtrl* ctrlp = static_cast<LLUICtrl*>(viewp); | ||
235 | // hasFocus() includes any descendants | ||
236 | if (ctrlp && !ctrlp->hasFocus()) | ||
237 | { | ||
238 | ctrlp->onFocusLost(); | ||
239 | } | ||
240 | } | ||
241 | |||
242 | void LLUICtrl::onLostTop() | ||
243 | { | ||
244 | if (mLostTopCallback) | ||
245 | { | ||
246 | mLostTopCallback(this, mCallbackUserData); | ||
247 | } | ||
248 | } | ||
249 | |||
250 | |||
131 | // virtual | 251 | // virtual |
132 | void LLUICtrl::setTabStop( BOOL b ) | 252 | void LLUICtrl::setTabStop( BOOL b ) |
133 | { | 253 | { |
@@ -165,68 +285,26 @@ void LLUICtrl::setIsChrome(BOOL is_chrome) | |||
165 | // virtual | 285 | // virtual |
166 | BOOL LLUICtrl::getIsChrome() const | 286 | BOOL LLUICtrl::getIsChrome() const |
167 | { | 287 | { |
168 | return mIsChrome; | 288 | // am I or any of my ancestors flagged as "chrome"? |
169 | } | 289 | if (mIsChrome) return TRUE; |
170 | 290 | ||
171 | void LLUICtrl::onFocusReceived() | 291 | LLView* parent_ctrl = getParent(); |
172 | { | 292 | while(parent_ctrl) |
173 | if( mFocusReceivedCallback ) | ||
174 | { | ||
175 | mFocusReceivedCallback( this, mCallbackUserData ); | ||
176 | } | ||
177 | if( mFocusChangedCallback ) | ||
178 | { | 293 | { |
179 | mFocusChangedCallback( this, mCallbackUserData ); | 294 | if(parent_ctrl->isCtrl()) |
180 | } | ||
181 | } | ||
182 | |||
183 | void LLUICtrl::onFocusLost() | ||
184 | { | ||
185 | if( mFocusLostCallback ) | ||
186 | { | ||
187 | mFocusLostCallback( this, mCallbackUserData ); | ||
188 | } | ||
189 | |||
190 | if( mFocusChangedCallback ) | ||
191 | { | ||
192 | mFocusChangedCallback( this, mCallbackUserData ); | ||
193 | } | ||
194 | } | ||
195 | |||
196 | BOOL LLUICtrl::hasFocus() const | ||
197 | { | ||
198 | return (gFocusMgr.childHasKeyboardFocus(this)); | ||
199 | } | ||
200 | |||
201 | void LLUICtrl::setFocus(BOOL b) | ||
202 | { | ||
203 | // focus NEVER goes to ui ctrls that are disabled! | ||
204 | if (!mEnabled) | ||
205 | { | ||
206 | return; | ||
207 | } | ||
208 | if( b ) | ||
209 | { | ||
210 | if (!hasFocus()) | ||
211 | { | 295 | { |
212 | gFocusMgr.setKeyboardFocus( this, &LLUICtrl::onFocusLostCallback ); | 296 | break; |
213 | onFocusReceived(); | ||
214 | } | 297 | } |
298 | parent_ctrl = parent_ctrl->getParent(); | ||
215 | } | 299 | } |
216 | else | 300 | |
301 | if(parent_ctrl) | ||
217 | { | 302 | { |
218 | if( gFocusMgr.childHasKeyboardFocus(this)) | 303 | // recurse into parent_ctrl and ask if it is in a chrome subtree |
219 | { | 304 | return ((LLUICtrl*)parent_ctrl)->getIsChrome(); |
220 | gFocusMgr.setKeyboardFocus( NULL, NULL ); | ||
221 | onFocusLost(); | ||
222 | } | ||
223 | } | 305 | } |
224 | } | ||
225 | 306 | ||
226 | // static | 307 | return FALSE; |
227 | void LLUICtrl::onFocusLostCallback( LLUICtrl* old_focus ) | ||
228 | { | ||
229 | old_focus->onFocusLost(); | ||
230 | } | 308 | } |
231 | 309 | ||
232 | // this comparator uses the crazy disambiguating logic of LLCompareByTabOrder, | 310 | // this comparator uses the crazy disambiguating logic of LLCompareByTabOrder, |
@@ -262,6 +340,7 @@ public: | |||
262 | } | 340 | } |
263 | }; | 341 | }; |
264 | 342 | ||
343 | |||
265 | BOOL LLUICtrl::focusFirstItem(BOOL prefer_text_fields) | 344 | BOOL LLUICtrl::focusFirstItem(BOOL prefer_text_fields) |
266 | { | 345 | { |
267 | // try to select default tab group child | 346 | // try to select default tab group child |