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