diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/llui/lltabcontainervertical.cpp | |
parent | README.txt (diff) | |
download | meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2 meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz |
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/llui/lltabcontainervertical.cpp')
-rw-r--r-- | linden/indra/llui/lltabcontainervertical.cpp | 610 |
1 files changed, 610 insertions, 0 deletions
diff --git a/linden/indra/llui/lltabcontainervertical.cpp b/linden/indra/llui/lltabcontainervertical.cpp new file mode 100644 index 0000000..121adf1 --- /dev/null +++ b/linden/indra/llui/lltabcontainervertical.cpp | |||
@@ -0,0 +1,610 @@ | |||
1 | /** | ||
2 | * @file lltabcontainervertical.cpp | ||
3 | * @brief LLTabContainerVertical base class | ||
4 | * | ||
5 | * Copyright (c) 2001-2007, Linden Research, Inc. | ||
6 | * | ||
7 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
8 | * to you under the terms of the GNU General Public License, version 2.0 | ||
9 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
10 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
11 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
12 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
13 | * | ||
14 | * There are special exceptions to the terms and conditions of the GPL as | ||
15 | * it is applied to this Source Code. View the full text of the exception | ||
16 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
17 | * online at http://secondlife.com/developers/opensource/flossexception | ||
18 | * | ||
19 | * By copying, modifying or distributing this software, you acknowledge | ||
20 | * that you have read and understood your obligations described above, | ||
21 | * and agree to abide by those obligations. | ||
22 | * | ||
23 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
24 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
25 | * COMPLETENESS OR PERFORMANCE. | ||
26 | */ | ||
27 | |||
28 | // Fear my script-fu! | ||
29 | |||
30 | #include "linden_common.h" | ||
31 | |||
32 | #include "lltabcontainervertical.h" | ||
33 | |||
34 | #include "llfocusmgr.h" | ||
35 | #include "llfontgl.h" | ||
36 | #include "llgl.h" | ||
37 | |||
38 | #include "llbutton.h" | ||
39 | #include "llrect.h" | ||
40 | #include "llpanel.h" | ||
41 | #include "llresmgr.h" | ||
42 | #include "llkeyboard.h" | ||
43 | #include "llui.h" | ||
44 | #include "lltextbox.h" | ||
45 | #include "llcontrol.h" | ||
46 | #include "llcriticaldamp.h" | ||
47 | |||
48 | #include "llglheaders.h" | ||
49 | |||
50 | LLTabContainerVertical::LLTabContainerVertical( | ||
51 | const LLString& name, const LLRect& rect, | ||
52 | void(*close_callback)(void*), void* callback_userdata, | ||
53 | U32 tab_width, BOOL bordered) | ||
54 | : | ||
55 | LLTabContainerCommon(name, rect, LEFT, close_callback, callback_userdata, bordered), | ||
56 | mTabWidth(tab_width), | ||
57 | mUpArrowBtn(NULL), | ||
58 | mDownArrowBtn(NULL) | ||
59 | { | ||
60 | initButtons(); | ||
61 | } | ||
62 | |||
63 | LLTabContainerVertical::LLTabContainerVertical( | ||
64 | const LLString& name, const LLString& rect_control, | ||
65 | void(*close_callback)(void*), void* callback_userdata, | ||
66 | U32 tab_width, BOOL bordered) | ||
67 | : | ||
68 | LLTabContainerCommon(name, rect_control, LEFT, close_callback, callback_userdata, bordered), | ||
69 | mTabWidth(tab_width) | ||
70 | { | ||
71 | initButtons(); | ||
72 | } | ||
73 | |||
74 | // Called from all constructors | ||
75 | void LLTabContainerVertical::initButtons() | ||
76 | { | ||
77 | // Hack: | ||
78 | if (mRect.getHeight() == 0 || mUpArrowBtn) | ||
79 | { | ||
80 | return; // Don't have a rect yet or already got called | ||
81 | } | ||
82 | |||
83 | LLString out_id; | ||
84 | LLString in_id; | ||
85 | |||
86 | //S32 arrow_fudge = 1; // match new art better | ||
87 | |||
88 | // Left and right scroll arrows (for when there are too many tabs to show all at once). | ||
89 | S32 btn_top = mRect.getHeight(); | ||
90 | S32 btn_top_lower = mRect.mBottom+TABCNTRV_ARROW_BTN_SIZE; | ||
91 | |||
92 | LLRect up_arrow_btn_rect; | ||
93 | up_arrow_btn_rect.setLeftTopAndSize( mTabWidth/2 , btn_top, TABCNTRV_ARROW_BTN_SIZE, TABCNTRV_ARROW_BTN_SIZE ); | ||
94 | |||
95 | LLRect down_arrow_btn_rect; | ||
96 | down_arrow_btn_rect.setLeftTopAndSize( mTabWidth/2 , btn_top_lower, TABCNTRV_ARROW_BTN_SIZE, TABCNTRV_ARROW_BTN_SIZE ); | ||
97 | |||
98 | out_id = "UIImgBtnScrollUpOutUUID"; | ||
99 | in_id = "UIImgBtnScrollUpInUUID"; | ||
100 | mUpArrowBtn = new LLButton( | ||
101 | "Up Arrow", up_arrow_btn_rect, | ||
102 | out_id, in_id, "", | ||
103 | &onPrevBtn, this, NULL ); | ||
104 | mUpArrowBtn->setHeldDownCallback(onPrevBtnHeld); | ||
105 | mUpArrowBtn->setSaveToXML(false); | ||
106 | mUpArrowBtn->setFollowsTop(); | ||
107 | mUpArrowBtn->setFollowsLeft(); | ||
108 | mUpArrowBtn->setTabStop(FALSE); | ||
109 | addChild(mUpArrowBtn); | ||
110 | |||
111 | out_id = "UIImgBtnScrollDownOutUUID"; | ||
112 | in_id = "UIImgBtnScrollDownInUUID"; | ||
113 | mDownArrowBtn = new LLButton( | ||
114 | "Down Arrow", down_arrow_btn_rect, | ||
115 | out_id, in_id, "", | ||
116 | &onNextBtn, this, NULL ); | ||
117 | mDownArrowBtn->setHeldDownCallback(onNextBtnHeld); | ||
118 | mDownArrowBtn->setSaveToXML(false); | ||
119 | mDownArrowBtn->setFollowsBottom(); | ||
120 | mDownArrowBtn->setFollowsLeft(); | ||
121 | mDownArrowBtn->setTabStop(FALSE); | ||
122 | addChild(mDownArrowBtn); | ||
123 | |||
124 | // set default tab group to be panel contents | ||
125 | mDefaultTabGroup = 1; | ||
126 | } | ||
127 | |||
128 | LLTabContainerVertical::~LLTabContainerVertical() | ||
129 | { } | ||
130 | |||
131 | void LLTabContainerVertical::addTabPanel(LLPanel* child, const LLString& label, | ||
132 | BOOL select, | ||
133 | void (*on_tab_clicked)(void*, bool), void* userdata, | ||
134 | S32 indent, | ||
135 | BOOL placeholder, eInsertionPoint insertion_point) | ||
136 | { | ||
137 | if (child->getParent() == this) | ||
138 | { | ||
139 | // already a child of mine | ||
140 | return; | ||
141 | } | ||
142 | |||
143 | const LLFontGL* font = gResMgr->getRes( LLFONT_SANSSERIF ); | ||
144 | |||
145 | // Store the original label for possible xml export. | ||
146 | child->setLabel(label); | ||
147 | // Replace long label with truncated version (e.g., "FooBa...") | ||
148 | LLString trimmed_label = label; | ||
149 | LLString::trim(trimmed_label); | ||
150 | |||
151 | // Tab panel | ||
152 | S32 tab_panel_top; | ||
153 | S32 tab_panel_bottom; | ||
154 | tab_panel_top = mRect.getHeight() | ||
155 | - mTopBorderHeight | ||
156 | - (BTN_HEIGHT - TABCNTRV_BUTTON_PANEL_OVERLAP); | ||
157 | tab_panel_bottom = LLPANEL_BORDER_WIDTH; | ||
158 | |||
159 | LLRect tab_panel_rect( | ||
160 | mTabWidth + (LLPANEL_BORDER_WIDTH * 2) + TABCNTRV_PAD, | ||
161 | mRect.getHeight() - LLPANEL_BORDER_WIDTH, | ||
162 | mRect.getWidth() - LLPANEL_BORDER_WIDTH, | ||
163 | LLPANEL_BORDER_WIDTH); | ||
164 | |||
165 | child->setFollowsAll(); | ||
166 | child->translate( tab_panel_rect.mLeft - child->getRect().mLeft, tab_panel_rect.mBottom - child->getRect().mBottom); | ||
167 | child->reshape( tab_panel_rect.getWidth(), tab_panel_rect.getHeight(), TRUE ); | ||
168 | child->setBackgroundVisible( FALSE ); // No need to overdraw | ||
169 | |||
170 | child->setVisible( FALSE ); // Will be made visible when selected | ||
171 | |||
172 | // Tab button | ||
173 | LLRect btn_rect; | ||
174 | btn_rect.setLeftTopAndSize( | ||
175 | TABCNTRV_PAD + LLPANEL_BORDER_WIDTH + 2, // JC - Fudge factor | ||
176 | (mRect.getHeight() - mTopBorderHeight - LLPANEL_BORDER_WIDTH - 1) - ((BTN_HEIGHT + TABCNTRV_PAD) * mTabList.size()), | ||
177 | mTabWidth, | ||
178 | BTN_HEIGHT); | ||
179 | |||
180 | if (!placeholder) | ||
181 | { | ||
182 | LLButton *btn = new LLButton("vert tab button", | ||
183 | btn_rect, | ||
184 | "tab_left.tga", | ||
185 | "tab_left_selected.tga", | ||
186 | "", | ||
187 | &LLTabContainerVertical::onTabBtn, NULL, | ||
188 | font, | ||
189 | trimmed_label, trimmed_label); | ||
190 | btn->setSaveToXML(false); | ||
191 | btn->setFixedBorder(16, 16); | ||
192 | btn->setScaleImage(TRUE); | ||
193 | btn->setHAlign(LLFontGL::LEFT); | ||
194 | btn->setFollows(FOLLOWS_TOP | FOLLOWS_LEFT); | ||
195 | btn->setTabStop(FALSE); | ||
196 | if (indent) | ||
197 | { | ||
198 | btn->setLeftHPad(indent); | ||
199 | } | ||
200 | |||
201 | LLTabTuple* tuple = new LLTabTuple( this, child, btn, on_tab_clicked, userdata ); | ||
202 | insertTuple( tuple, insertion_point ); | ||
203 | |||
204 | btn->setCallbackUserData( tuple ); | ||
205 | addChild( btn, 0 ); | ||
206 | addChild(child, 1); | ||
207 | |||
208 | if( select ) | ||
209 | { | ||
210 | selectTab( mTabList.size()-1 ); | ||
211 | } | ||
212 | } | ||
213 | else | ||
214 | { | ||
215 | btn_rect.translate(0, -LLBUTTON_V_PAD-2); | ||
216 | LLString box_label = trimmed_label; | ||
217 | LLTextBox* text = new LLTextBox(box_label, btn_rect, box_label, font); | ||
218 | text->setSaveToXML(false); | ||
219 | addChild( text, 0 ); | ||
220 | |||
221 | LLButton* btn = new LLButton("", LLRect(0,0,0,0)); | ||
222 | btn->setSaveToXML(false); | ||
223 | addChild(btn, 0); | ||
224 | addChild(child, 1); | ||
225 | |||
226 | LLTabTuple* tuple = new LLTabTuple( this, child, btn, on_tab_clicked, userdata, text ); | ||
227 | insertTuple( tuple, insertion_point ); | ||
228 | } | ||
229 | |||
230 | updateMaxScrollPos(); | ||
231 | } | ||
232 | |||
233 | void LLTabContainerVertical::removeTabPanel(LLPanel* child) | ||
234 | { | ||
235 | LLTabContainerCommon::removeTabPanel(child); | ||
236 | |||
237 | // Fix-up button sizes | ||
238 | S32 tab_count = 0; | ||
239 | for(std::vector<LLTabTuple*>::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) | ||
240 | { | ||
241 | LLTabTuple* tuple = *iter; | ||
242 | LLRect rect; | ||
243 | rect.setLeftTopAndSize(TABCNTRV_PAD + LLPANEL_BORDER_WIDTH + 2, // JC - Fudge factor | ||
244 | (mRect.getHeight() - LLPANEL_BORDER_WIDTH - 1) - ((BTN_HEIGHT + TABCNTRV_PAD) * (tab_count)), | ||
245 | mTabWidth, | ||
246 | BTN_HEIGHT); | ||
247 | if (tuple->mPlaceholderText) | ||
248 | { | ||
249 | tuple->mPlaceholderText->setRect(rect); | ||
250 | } | ||
251 | else | ||
252 | { | ||
253 | tuple->mButton->setRect(rect); | ||
254 | } | ||
255 | tab_count++; | ||
256 | } | ||
257 | } | ||
258 | |||
259 | void LLTabContainerVertical::updateMaxScrollPos() | ||
260 | { | ||
261 | S32 tab_total_height = (BTN_HEIGHT + TABCNTRV_PAD) * mTabList.size(); | ||
262 | S32 available_height = mRect.getHeight() - mTopBorderHeight; | ||
263 | if( tab_total_height > available_height ) | ||
264 | { | ||
265 | S32 available_height_with_arrows = mRect.getHeight() - 2*(TABCNTRV_ARROW_BTN_SIZE + 3*TABCNTRV_PAD); | ||
266 | S32 additional_needed = tab_total_height - available_height_with_arrows; | ||
267 | mMaxScrollPos = S32( ceil(additional_needed / float(BTN_HEIGHT) ) ); | ||
268 | } | ||
269 | else | ||
270 | { | ||
271 | mMaxScrollPos = 0; | ||
272 | mScrollPos = 0; | ||
273 | } | ||
274 | if (mScrollPos > mMaxScrollPos) | ||
275 | { | ||
276 | mScrollPos = mMaxScrollPos; | ||
277 | } | ||
278 | } | ||
279 | |||
280 | void LLTabContainerVertical::commitHoveredButton(S32 x, S32 y) | ||
281 | { | ||
282 | if (gFocusMgr.getMouseCapture() == this) | ||
283 | { | ||
284 | for(std::vector<LLTabTuple*>::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) | ||
285 | { | ||
286 | LLTabTuple* tuple = *iter; | ||
287 | tuple->mButton->setVisible( TRUE ); | ||
288 | S32 local_x = x - tuple->mButton->getRect().mLeft; | ||
289 | S32 local_y = y - tuple->mButton->getRect().mBottom; | ||
290 | if (tuple->mButton->pointInView(local_x, local_y) && tuple->mButton->getEnabled() && !tuple->mTabPanel->getVisible()) | ||
291 | { | ||
292 | tuple->mButton->onCommit(); | ||
293 | } | ||
294 | } | ||
295 | } | ||
296 | } | ||
297 | |||
298 | BOOL LLTabContainerVertical::selectTab(S32 which) | ||
299 | { | ||
300 | if (which >= (S32)mTabList.size()) return FALSE; | ||
301 | if (which < 0) return FALSE; | ||
302 | |||
303 | //if( gFocusMgr.childHasKeyboardFocus( this ) ) | ||
304 | //{ | ||
305 | // gFocusMgr.setKeyboardFocus( NULL, NULL ); | ||
306 | //} | ||
307 | |||
308 | LLTabTuple* selected_tuple = mTabList[which]; | ||
309 | if (!selected_tuple) | ||
310 | { | ||
311 | return FALSE; | ||
312 | } | ||
313 | |||
314 | BOOL is_visible = FALSE; | ||
315 | if (which != mCurrentTabIdx) | ||
316 | { | ||
317 | mCurrentTabIdx = which; | ||
318 | |||
319 | S32 i = 0; | ||
320 | for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) | ||
321 | { | ||
322 | LLTabTuple* tuple = *iter; | ||
323 | BOOL is_selected = ( tuple == selected_tuple ); | ||
324 | tuple->mTabPanel->setVisible( is_selected ); | ||
325 | // tuple->mTabPanel->setFocus(is_selected); // not clear that we want to do this here. | ||
326 | tuple->mButton->setToggleState( is_selected ); | ||
327 | // RN: this limits tab-stops to active button only, which would require arrow keys to switch tabs | ||
328 | tuple->mButton->setTabStop( is_selected ); | ||
329 | |||
330 | if( is_selected ) | ||
331 | { | ||
332 | // Make sure tab is within scroll | ||
333 | S32 num_visible = mTabList.size() - mMaxScrollPos; | ||
334 | if( i >= mScrollPos && i <= mScrollPos + num_visible) | ||
335 | { | ||
336 | mCurrentTabIdx = which; | ||
337 | is_visible = TRUE; | ||
338 | } | ||
339 | else | ||
340 | { | ||
341 | is_visible = FALSE; | ||
342 | } | ||
343 | } | ||
344 | i++; | ||
345 | } | ||
346 | if( selected_tuple->mOnChangeCallback ) | ||
347 | { | ||
348 | selected_tuple->mOnChangeCallback( selected_tuple->mUserData, false ); | ||
349 | } | ||
350 | } | ||
351 | if(mCurrentTabIdx >= 0) | ||
352 | { | ||
353 | LLTabTuple* tuple = mTabList[mCurrentTabIdx]; | ||
354 | tuple->mTabPanel->setVisible( TRUE ); | ||
355 | tuple->mButton->setToggleState( TRUE ); | ||
356 | } | ||
357 | return is_visible; | ||
358 | } | ||
359 | |||
360 | |||
361 | |||
362 | void LLTabContainerVertical::draw() | ||
363 | { | ||
364 | S32 target_pixel_scroll = mScrollPos * (BTN_HEIGHT + TABCNTRV_PAD); | ||
365 | |||
366 | mScrollPosPixels = (S32)lerp((F32)mScrollPosPixels, (F32)target_pixel_scroll, LLCriticalDamp::getInterpolant(0.08f)); | ||
367 | if( getVisible() ) | ||
368 | { | ||
369 | BOOL has_scroll_arrows = (mMaxScrollPos > 0) || (mScrollPosPixels > 0); | ||
370 | mUpArrowBtn->setVisible( has_scroll_arrows ); | ||
371 | mDownArrowBtn->setVisible( has_scroll_arrows ); | ||
372 | |||
373 | // Set the topmost position of the tab buttons. | ||
374 | S32 top = mRect.getHeight() - mTopBorderHeight - LLPANEL_BORDER_WIDTH - 1 - (has_scroll_arrows ? TABCNTRV_ARROW_BTN_SIZE : 0); | ||
375 | top += mScrollPosPixels; | ||
376 | |||
377 | // Hide all the buttons | ||
378 | for(std::vector<LLTabTuple*>::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) | ||
379 | { | ||
380 | LLTabTuple* tuple = *iter; | ||
381 | tuple->mButton->setVisible( FALSE ); | ||
382 | } | ||
383 | |||
384 | LLPanel::draw(); | ||
385 | |||
386 | // Show all the buttons | ||
387 | for(std::vector<LLTabTuple*>::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) | ||
388 | { | ||
389 | LLTabTuple* tuple = *iter; | ||
390 | tuple->mButton->setVisible( TRUE ); | ||
391 | } | ||
392 | |||
393 | // Draw some of the buttons... | ||
394 | |||
395 | LLGLEnable scissor_test(has_scroll_arrows ? GL_SCISSOR_TEST : GL_FALSE); | ||
396 | |||
397 | if( has_scroll_arrows ) | ||
398 | { | ||
399 | // ...but clip them. | ||
400 | S32 x1 = mRect.mLeft; | ||
401 | S32 y1 = mDownArrowBtn->getRect().mTop + 3*TABCNTRV_PAD; | ||
402 | S32 x2 = mRect.mRight; | ||
403 | S32 y2 = mUpArrowBtn->getRect().mBottom - 3*TABCNTRV_PAD; | ||
404 | LLUI::setScissorRegionLocal(LLRect(x1, y2, x2, y1)); | ||
405 | } | ||
406 | |||
407 | //S32 max_scroll_visible = mTabList.size() - mMaxScrollPos + mScrollPos; | ||
408 | S32 idx = 0; | ||
409 | for(std::vector<LLTabTuple*>::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) | ||
410 | { | ||
411 | LLTabTuple* tuple = *iter; | ||
412 | tuple->mButton->translate( 0 , top - tuple->mButton->getRect().mTop); | ||
413 | top -= BTN_HEIGHT + TABCNTRV_PAD; | ||
414 | |||
415 | LLUI::pushMatrix(); | ||
416 | { | ||
417 | LLUI::translate((F32)tuple->mButton->getRect().mLeft, (F32)tuple->mButton->getRect().mBottom, 0.f); | ||
418 | tuple->mButton->draw(); | ||
419 | } | ||
420 | LLUI::popMatrix(); | ||
421 | |||
422 | idx++; | ||
423 | } | ||
424 | |||
425 | if( has_scroll_arrows ) | ||
426 | { | ||
427 | // Redraw the arrows so that they appears on top. | ||
428 | glPushMatrix(); | ||
429 | glTranslatef((F32)mUpArrowBtn->getRect().mLeft, (F32)mUpArrowBtn->getRect().mBottom, 0.f); | ||
430 | mUpArrowBtn->draw(); | ||
431 | glPopMatrix(); | ||
432 | |||
433 | glPushMatrix(); | ||
434 | glTranslatef((F32)mDownArrowBtn->getRect().mLeft, (F32)mDownArrowBtn->getRect().mBottom, 0.f); | ||
435 | mDownArrowBtn->draw(); | ||
436 | glPopMatrix(); | ||
437 | } | ||
438 | } | ||
439 | } | ||
440 | |||
441 | BOOL LLTabContainerVertical::handleMouseDown( S32 x, S32 y, MASK mask ) | ||
442 | { | ||
443 | BOOL handled = FALSE; | ||
444 | BOOL has_scroll_arrows = (mMaxScrollPos > 0); | ||
445 | |||
446 | if (has_scroll_arrows) | ||
447 | { | ||
448 | if (mUpArrowBtn->getRect().pointInRect(x, y)) | ||
449 | { | ||
450 | S32 local_x = x - mUpArrowBtn->getRect().mLeft; | ||
451 | S32 local_y = y - mUpArrowBtn->getRect().mBottom; | ||
452 | handled = mUpArrowBtn->handleMouseDown(local_x, local_y, mask); | ||
453 | } | ||
454 | else if (mDownArrowBtn->getRect().pointInRect(x, y)) | ||
455 | { | ||
456 | S32 local_x = x - mDownArrowBtn->getRect().mLeft; | ||
457 | S32 local_y = y - mDownArrowBtn->getRect().mBottom; | ||
458 | handled = mDownArrowBtn->handleMouseDown(local_x, local_y, mask); | ||
459 | } | ||
460 | } | ||
461 | if (!handled) | ||
462 | { | ||
463 | handled = LLPanel::handleMouseDown( x, y, mask ); | ||
464 | } | ||
465 | |||
466 | if (mTabList.size() > 0) | ||
467 | { | ||
468 | LLTabTuple* firsttuple = mTabList[0]; | ||
469 | LLRect tab_rect(firsttuple->mButton->getRect().mLeft, | ||
470 | has_scroll_arrows ? mUpArrowBtn->getRect().mBottom - TABCNTRV_PAD : mUpArrowBtn->getRect().mTop, | ||
471 | firsttuple->mButton->getRect().mRight, | ||
472 | has_scroll_arrows ? mDownArrowBtn->getRect().mTop + TABCNTRV_PAD : mDownArrowBtn->getRect().mBottom ); | ||
473 | if( tab_rect.pointInRect( x, y ) ) | ||
474 | { | ||
475 | LLButton* tab_button = mTabList[getCurrentPanelIndex()]->mButton; | ||
476 | gFocusMgr.setMouseCapture(this, NULL); | ||
477 | gFocusMgr.setKeyboardFocus(tab_button, NULL); | ||
478 | } | ||
479 | } | ||
480 | return handled; | ||
481 | } | ||
482 | |||
483 | BOOL LLTabContainerVertical::handleHover( S32 x, S32 y, MASK mask ) | ||
484 | { | ||
485 | BOOL handled = FALSE; | ||
486 | BOOL has_scroll_arrows = (mMaxScrollPos > 0); | ||
487 | |||
488 | if (has_scroll_arrows) | ||
489 | { | ||
490 | if (mUpArrowBtn->getRect().pointInRect(x, y)) | ||
491 | { | ||
492 | S32 local_x = x - mUpArrowBtn->getRect().mLeft; | ||
493 | S32 local_y = y - mUpArrowBtn->getRect().mBottom; | ||
494 | handled = mUpArrowBtn->handleHover(local_x, local_y, mask); | ||
495 | } | ||
496 | else if (mDownArrowBtn->getRect().pointInRect(x, y)) | ||
497 | { | ||
498 | S32 local_x = x - mDownArrowBtn->getRect().mLeft; | ||
499 | S32 local_y = y - mDownArrowBtn->getRect().mBottom; | ||
500 | handled = mDownArrowBtn->handleHover(local_x, local_y, mask); | ||
501 | } | ||
502 | } | ||
503 | if (!handled) | ||
504 | { | ||
505 | handled = LLPanel::handleHover(x, y, mask); | ||
506 | } | ||
507 | |||
508 | commitHoveredButton(x, y); | ||
509 | return handled; | ||
510 | } | ||
511 | |||
512 | BOOL LLTabContainerVertical::handleMouseUp( S32 x, S32 y, MASK mask ) | ||
513 | { | ||
514 | BOOL handled = FALSE; | ||
515 | BOOL has_scroll_arrows = (mMaxScrollPos > 0); | ||
516 | |||
517 | if (has_scroll_arrows) | ||
518 | { | ||
519 | if (mUpArrowBtn->getRect().pointInRect(x, y)) | ||
520 | { | ||
521 | S32 local_x = x - mUpArrowBtn->getRect().mLeft; | ||
522 | S32 local_y = y - mUpArrowBtn->getRect().mBottom; | ||
523 | handled = mUpArrowBtn->handleMouseUp(local_x, local_y, mask); | ||
524 | } | ||
525 | else if (mDownArrowBtn->getRect().pointInRect(x, y)) | ||
526 | { | ||
527 | S32 local_x = x - mDownArrowBtn->getRect().mLeft; | ||
528 | S32 local_y = y - mDownArrowBtn->getRect().mBottom; | ||
529 | handled = mDownArrowBtn->handleMouseUp(local_x, local_y, mask); | ||
530 | } | ||
531 | } | ||
532 | if (!handled) | ||
533 | { | ||
534 | handled = LLPanel::handleMouseUp( x, y, mask ); | ||
535 | } | ||
536 | |||
537 | commitHoveredButton(x, y); | ||
538 | LLPanel* cur_panel = getCurrentPanel(); | ||
539 | if (gFocusMgr.getMouseCapture() == this) | ||
540 | { | ||
541 | if (cur_panel) | ||
542 | { | ||
543 | if (!cur_panel->focusFirstItem(FALSE)) | ||
544 | { | ||
545 | mTabList[getCurrentPanelIndex()]->mButton->setFocus(TRUE); | ||
546 | } | ||
547 | } | ||
548 | gFocusMgr.setMouseCapture(NULL, NULL); | ||
549 | } | ||
550 | |||
551 | return handled; | ||
552 | } | ||
553 | |||
554 | BOOL LLTabContainerVertical::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent) | ||
555 | { | ||
556 | BOOL handled = FALSE; | ||
557 | if (getEnabled()) | ||
558 | { | ||
559 | if (key == '[' && mask == MASK_CONTROL) | ||
560 | { | ||
561 | selectPrevTab(); | ||
562 | handled = TRUE; | ||
563 | } | ||
564 | else if (key == ']' && mask == MASK_CONTROL) | ||
565 | { | ||
566 | selectNextTab(); | ||
567 | handled = TRUE; | ||
568 | } | ||
569 | |||
570 | // focus is on button | ||
571 | if (!handled && !gFocusMgr.childHasKeyboardFocus(getCurrentPanel())) | ||
572 | { | ||
573 | switch(key) | ||
574 | { | ||
575 | case KEY_UP: | ||
576 | selectPrevTab(); | ||
577 | handled = TRUE; | ||
578 | break; | ||
579 | case KEY_DOWN: | ||
580 | selectNextTab(); | ||
581 | handled = TRUE; | ||
582 | break; | ||
583 | case KEY_LEFT: | ||
584 | handled = TRUE; | ||
585 | break; | ||
586 | case KEY_RIGHT: | ||
587 | if (getTabPosition() == LEFT && getCurrentPanel()) | ||
588 | { | ||
589 | getCurrentPanel()->setFocus(TRUE); | ||
590 | } | ||
591 | handled = TRUE; | ||
592 | break; | ||
593 | default: | ||
594 | break; | ||
595 | } | ||
596 | } | ||
597 | } | ||
598 | return handled; | ||
599 | } | ||
600 | |||
601 | // virtual | ||
602 | LLXMLNodePtr LLTabContainerVertical::getXML(bool save_children) const | ||
603 | { | ||
604 | LLXMLNodePtr node = LLTabContainerCommon::getXML(); | ||
605 | |||
606 | // TomY TODO Is this redundant or will it be used later? | ||
607 | node->createChild("tab_position", TRUE)->setStringValue("left"); | ||
608 | |||
609 | return node; | ||
610 | } | ||