00001
00032
00033
00034
00035 #include "linden_common.h"
00036
00037 #include "llfloater.h"
00038
00039 #include "llfocusmgr.h"
00040
00041 #include "lluictrlfactory.h"
00042 #include "llbutton.h"
00043 #include "llcheckboxctrl.h"
00044 #include "lldraghandle.h"
00045 #include "llfocusmgr.h"
00046 #include "llresizebar.h"
00047 #include "llresizehandle.h"
00048 #include "llkeyboard.h"
00049 #include "llmenugl.h"
00050 #include "lltextbox.h"
00051 #include "llresmgr.h"
00052 #include "llui.h"
00053 #include "llwindow.h"
00054 #include "llstl.h"
00055 #include "llcontrol.h"
00056 #include "lltabcontainer.h"
00057 #include "v2math.h"
00058
00059 extern BOOL gNoRender;
00060
00061 const S32 MINIMIZED_WIDTH = 160;
00062 const S32 CLOSE_BOX_FROM_TOP = 1;
00063
00064 const S32 TABBED_FLOATER_OFFSET = 0;
00065
00066 LLString LLFloater::sButtonActiveImageNames[BUTTON_COUNT] =
00067 {
00068 "UIImgBtnCloseActiveUUID",
00069 "UIImgBtnRestoreActiveUUID",
00070 "UIImgBtnMinimizeActiveUUID",
00071 "UIImgBtnTearOffActiveUUID",
00072 "UIImgBtnCloseActiveUUID",
00073 };
00074
00075 LLString LLFloater::sButtonInactiveImageNames[BUTTON_COUNT] =
00076 {
00077 "UIImgBtnCloseInactiveUUID",
00078 "UIImgBtnRestoreInactiveUUID",
00079 "UIImgBtnMinimizeInactiveUUID",
00080 "UIImgBtnTearOffInactiveUUID",
00081 "UIImgBtnCloseInactiveUUID",
00082 };
00083
00084 LLString LLFloater::sButtonPressedImageNames[BUTTON_COUNT] =
00085 {
00086 "UIImgBtnClosePressedUUID",
00087 "UIImgBtnRestorePressedUUID",
00088 "UIImgBtnMinimizePressedUUID",
00089 "UIImgBtnTearOffPressedUUID",
00090 "UIImgBtnClosePressedUUID",
00091 };
00092
00093 LLString LLFloater::sButtonNames[BUTTON_COUNT] =
00094 {
00095 "llfloater_close_btn",
00096 "llfloater_restore_btn",
00097 "llfloater_minimize_btn",
00098 "llfloater_tear_off_btn",
00099 "llfloater_edit_btn",
00100 };
00101
00102 LLString LLFloater::sButtonToolTips[BUTTON_COUNT] =
00103 {
00104 #ifdef LL_DARWIN
00105 "Close (Cmd-W)",
00106 #else
00107 "Close (Ctrl-W)",
00108 #endif
00109 "Restore",
00110 "Minimize",
00111 "Tear Off",
00112 "Edit",
00113 };
00114
00115 LLFloater::click_callback LLFloater::sButtonCallbacks[BUTTON_COUNT] =
00116 {
00117 LLFloater::onClickClose,
00118 LLFloater::onClickMinimize,
00119 LLFloater::onClickMinimize,
00120 LLFloater::onClickTearOff,
00121 LLFloater::onClickEdit,
00122 };
00123
00124 LLMultiFloater* LLFloater::sHostp = NULL;
00125 BOOL LLFloater::sEditModeEnabled;
00126 LLFloater::handle_map_t LLFloater::sFloaterMap;
00127
00128 LLFloaterView* gFloaterView = NULL;
00129
00130 LLFloater::LLFloater() :
00131
00132 mResizable(FALSE),
00133 mDragOnLeft(FALSE),
00134 mMinWidth(0),
00135 mMinHeight(0)
00136 {
00137
00138 mAutoFocus = TRUE;
00139 for (S32 i = 0; i < BUTTON_COUNT; i++)
00140 {
00141 mButtonsEnabled[i] = FALSE;
00142 mButtons[i] = NULL;
00143 }
00144 mDragHandle = NULL;
00145 mHandle.bind(this);
00146 }
00147
00148 LLFloater::LLFloater(const LLString& name)
00149 : LLPanel(name), mAutoFocus(TRUE)
00150 {
00151 for (S32 i = 0; i < BUTTON_COUNT; i++)
00152 {
00153 mButtonsEnabled[i] = FALSE;
00154 mButtons[i] = NULL;
00155 }
00156 LLString title;
00157 initFloater(title, FALSE, DEFAULT_MIN_WIDTH, DEFAULT_MIN_HEIGHT, FALSE, TRUE, TRUE);
00158 }
00159
00160
00161 LLFloater::LLFloater(const LLString& name, const LLRect& rect, const LLString& title,
00162 BOOL resizable,
00163 S32 min_width,
00164 S32 min_height,
00165 BOOL drag_on_left,
00166 BOOL minimizable,
00167 BOOL close_btn,
00168 BOOL bordered)
00169 : LLPanel(name, rect, bordered), mAutoFocus(TRUE)
00170 {
00171 for (S32 i = 0; i < BUTTON_COUNT; i++)
00172 {
00173 mButtonsEnabled[i] = FALSE;
00174 mButtons[i] = NULL;
00175 }
00176 initFloater( title, resizable, min_width, min_height, drag_on_left, minimizable, close_btn);
00177 }
00178
00179 LLFloater::LLFloater(const LLString& name, const LLString& rect_control, const LLString& title,
00180 BOOL resizable,
00181 S32 min_width,
00182 S32 min_height,
00183 BOOL drag_on_left,
00184 BOOL minimizable,
00185 BOOL close_btn,
00186 BOOL bordered)
00187 : LLPanel(name, rect_control, bordered), mAutoFocus(TRUE)
00188 {
00189 for (S32 i = 0; i < BUTTON_COUNT; i++)
00190 {
00191 mButtonsEnabled[i] = FALSE;
00192 mButtons[i] = NULL;
00193 }
00194 initFloater( title, resizable, min_width, min_height, drag_on_left, minimizable, close_btn);
00195 }
00196
00197
00198
00199 void LLFloater::initFloater(const LLString& title,
00200 BOOL resizable, S32 min_width, S32 min_height,
00201 BOOL drag_on_left, BOOL minimizable, BOOL close_btn)
00202 {
00203 mHandle.bind(this);
00204
00205
00206 for (S32 i = 0; i < BUTTON_COUNT; i++)
00207 {
00208 mButtonsEnabled[i] = FALSE;
00209 if (mButtons[i] != NULL)
00210 {
00211 removeChild(mButtons[i]);
00212 delete mButtons[i];
00213 mButtons[i] = NULL;
00214 }
00215 }
00216 mButtonScale = 1.f;
00217
00218
00219 BOOL need_border = hasBorder();
00220
00221 removeBorder();
00222
00223 deleteAllChildren();
00224
00225 if (need_border)
00226 {
00227 addBorder();
00228 }
00229
00230
00231 setFocusRoot(!getIsChrome());
00232
00233
00234 mDragHandle = NULL;
00235 for (S32 i = 0; i < 4; i++)
00236 {
00237 mResizeBar[i] = NULL;
00238 mResizeHandle[i] = NULL;
00239 }
00240 mCanTearOff = TRUE;
00241 mEditing = FALSE;
00242
00243
00244 setMouseOpaque(TRUE);
00245
00246 mFirstLook = TRUE;
00247 mForeground = FALSE;
00248 mDragOnLeft = drag_on_left == TRUE;
00249
00250
00251 setBackgroundVisible(TRUE);
00252
00253
00254
00255 mMinimized = FALSE;
00256 mExpandedRect.set(0,0,0,0);
00257
00258 S32 close_pad;
00259 S32 close_box_size;
00260 if (close_btn)
00261 {
00262 close_box_size = LLFLOATER_CLOSE_BOX_SIZE;
00263 close_pad = 0;
00264 }
00265 else
00266 {
00267 close_box_size = 0;
00268 close_pad = 0;
00269 }
00270
00271 S32 minimize_box_size;
00272 S32 minimize_pad;
00273 if (minimizable && !drag_on_left)
00274 {
00275 minimize_box_size = LLFLOATER_CLOSE_BOX_SIZE;
00276 minimize_pad = 0;
00277 }
00278 else
00279 {
00280 minimize_box_size = 0;
00281 minimize_pad = 0;
00282 }
00283
00284
00285
00286
00287 if (drag_on_left)
00288 {
00289 LLRect drag_handle_rect;
00290 drag_handle_rect.setOriginAndSize(
00291 0, 0,
00292 DRAG_HANDLE_WIDTH,
00293 getRect().getHeight() - LLPANEL_BORDER_WIDTH - close_box_size);
00294 mDragHandle = new LLDragHandleLeft("drag", drag_handle_rect, title );
00295 }
00296 else
00297 {
00298 LLRect drag_handle_rect( 0, getRect().getHeight(), getRect().getWidth(), 0 );
00299 mDragHandle = new LLDragHandleTop( "Drag Handle", drag_handle_rect, title );
00300 }
00301 addChild(mDragHandle);
00302
00303
00304 mResizable = resizable;
00305 mMinWidth = min_width;
00306 mMinHeight = min_height;
00307
00308 if( mResizable )
00309 {
00310
00311 const S32 RESIZE_BAR_THICKNESS = 3;
00312 mResizeBar[LLResizeBar::LEFT] = new LLResizeBar(
00313 "resizebar_left",
00314 this,
00315 LLRect( 0, getRect().getHeight(), RESIZE_BAR_THICKNESS, 0),
00316 min_width, S32_MAX, LLResizeBar::LEFT );
00317 addChild( mResizeBar[0] );
00318
00319 mResizeBar[LLResizeBar::TOP] = new LLResizeBar(
00320 "resizebar_top",
00321 this,
00322 LLRect( 0, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_BAR_THICKNESS),
00323 min_height, S32_MAX, LLResizeBar::TOP );
00324 addChild( mResizeBar[1] );
00325
00326 mResizeBar[LLResizeBar::RIGHT] = new LLResizeBar(
00327 "resizebar_right",
00328 this,
00329 LLRect( getRect().getWidth() - RESIZE_BAR_THICKNESS, getRect().getHeight(), getRect().getWidth(), 0),
00330 min_width, S32_MAX, LLResizeBar::RIGHT );
00331 addChild( mResizeBar[2] );
00332
00333 mResizeBar[LLResizeBar::BOTTOM] = new LLResizeBar(
00334 "resizebar_bottom",
00335 this,
00336 LLRect( 0, RESIZE_BAR_THICKNESS, getRect().getWidth(), 0),
00337 min_height, S32_MAX, LLResizeBar::BOTTOM );
00338 addChild( mResizeBar[3] );
00339
00340
00341
00342 mResizeHandle[0] = new LLResizeHandle(
00343 "Resize Handle",
00344 LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, RESIZE_HANDLE_HEIGHT, getRect().getWidth(), 0),
00345 min_width,
00346 min_height,
00347 LLResizeHandle::RIGHT_BOTTOM);
00348 addChild(mResizeHandle[0]);
00349
00350 mResizeHandle[1] = new LLResizeHandle( "resize",
00351 LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_HANDLE_HEIGHT),
00352 min_width,
00353 min_height,
00354 LLResizeHandle::RIGHT_TOP );
00355 addChild(mResizeHandle[1]);
00356
00357 mResizeHandle[2] = new LLResizeHandle( "resize",
00358 LLRect( 0, RESIZE_HANDLE_HEIGHT, RESIZE_HANDLE_WIDTH, 0 ),
00359 min_width,
00360 min_height,
00361 LLResizeHandle::LEFT_BOTTOM );
00362 addChild(mResizeHandle[2]);
00363
00364 mResizeHandle[3] = new LLResizeHandle( "resize",
00365 LLRect( 0, getRect().getHeight(), RESIZE_HANDLE_WIDTH, getRect().getHeight() - RESIZE_HANDLE_HEIGHT ),
00366 min_width,
00367 min_height,
00368 LLResizeHandle::LEFT_TOP );
00369 addChild(mResizeHandle[3]);
00370 }
00371
00372
00373 if (close_btn)
00374 {
00375 mButtonsEnabled[BUTTON_CLOSE] = TRUE;
00376 }
00377
00378
00379 if ( !drag_on_left && minimizable )
00380 {
00381 mButtonsEnabled[BUTTON_MINIMIZE] = TRUE;
00382 }
00383
00384
00385
00386
00387 mHasBeenDraggedWhileMinimized = FALSE;
00388 mPreviousMinimizedLeft = 0;
00389 mPreviousMinimizedBottom = 0;
00390
00391 buildButtons();
00392
00393
00394
00395
00396
00397
00398 setVisible(FALSE);
00399
00400
00401 sFloaterMap[mHandle] = this;
00402
00403 if (!getParent())
00404 {
00405 gFloaterView->addChild(this);
00406 }
00407 }
00408
00409
00410 LLFloater::~LLFloater()
00411 {
00412 control_map_t::iterator itor;
00413 for (itor = mFloaterControls.begin(); itor != mFloaterControls.end(); ++itor)
00414 {
00415 delete itor->second;
00416 }
00417 mFloaterControls.clear();
00418
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431 releaseFocus();
00432
00433
00434
00435
00436 setMinimized( FALSE );
00437
00438 sFloaterMap.erase(mHandle);
00439
00440 delete mDragHandle;
00441 for (S32 i = 0; i < 4; i++)
00442 {
00443 delete mResizeBar[i];
00444 delete mResizeHandle[i];
00445 }
00446 }
00447
00448
00449 void LLFloater::setVisible( BOOL visible )
00450 {
00451 LLPanel::setVisible(visible);
00452 if( visible && mFirstLook )
00453 {
00454 mFirstLook = FALSE;
00455 }
00456
00457 if( !visible )
00458 {
00459 if( gFocusMgr.childIsTopCtrl( this ) )
00460 {
00461 gFocusMgr.setTopCtrl(NULL);
00462 }
00463
00464 if( gFocusMgr.childHasMouseCapture( this ) )
00465 {
00466 gFocusMgr.setMouseCapture(NULL);
00467 }
00468 }
00469
00470 for(handle_set_iter_t dependent_it = mDependents.begin();
00471 dependent_it != mDependents.end(); )
00472 {
00473 LLFloater* floaterp = dependent_it->get();
00474
00475 if (floaterp)
00476 {
00477 floaterp->setVisible(visible);
00478 }
00479 ++dependent_it;
00480 }
00481 }
00482
00483 void LLFloater::open()
00484 {
00485 if (getSoundFlags() != SILENT
00486
00487 && !getHost()
00488 && !getFloaterHost()
00489 && (!getVisible() || isMinimized()))
00490 {
00491 make_ui_sound("UISndWindowOpen");
00492 }
00493
00494
00495
00496 if (getFloaterHost() != NULL && getHost() == NULL)
00497 {
00498
00499
00500 getFloaterHost()->addFloater(this, getFloaterHost()->getVisible());
00501 }
00502 else if (getHost() != NULL)
00503 {
00504
00505 getHost()->showFloater(this);
00506 }
00507 else
00508 {
00509 setMinimized(FALSE);
00510 setVisibleAndFrontmost(mAutoFocus);
00511 }
00512
00513 onOpen();
00514 }
00515
00516 void LLFloater::close(bool app_quitting)
00517 {
00518
00519
00520 setMinimized(FALSE);
00521
00522 if (canClose())
00523 {
00524 if (getHost())
00525 {
00526 ((LLMultiFloater*)getHost())->removeFloater(this);
00527 }
00528
00529 if (getSoundFlags() != SILENT
00530 && getVisible()
00531 && !getHost()
00532 && !app_quitting)
00533 {
00534 make_ui_sound("UISndWindowClose");
00535 }
00536
00537
00538 for(handle_set_iter_t dependent_it = mDependents.begin();
00539 dependent_it != mDependents.end(); )
00540 {
00541
00542 LLFloater* floaterp = dependent_it->get();
00543 if (floaterp)
00544 {
00545 ++dependent_it;
00546 floaterp->close();
00547 }
00548 else
00549 {
00550 mDependents.erase(dependent_it++);
00551 }
00552 }
00553
00554 cleanupHandles();
00555 gFocusMgr.clearLastFocusForGroup(this);
00556
00557 if (hasFocus())
00558 {
00559
00560
00561 releaseFocus();
00562
00563
00564 if (isDependent())
00565 {
00566 LLFloater* dependee = mDependeeHandle.get();
00567 if (dependee && !dependee->isDead())
00568 {
00569 dependee->setFocus(TRUE);
00570 }
00571 }
00572 }
00573
00574
00575 onClose(app_quitting);
00576 }
00577 }
00578
00579
00580 void LLFloater::reshape(S32 width, S32 height, BOOL called_from_parent)
00581 {
00582 LLPanel::reshape(width, height, called_from_parent);
00583 }
00584
00585 void LLFloater::releaseFocus()
00586 {
00587 if( gFocusMgr.childIsTopCtrl( this ) )
00588 {
00589 gFocusMgr.setTopCtrl(NULL);
00590 }
00591
00592 if( gFocusMgr.childHasKeyboardFocus( this ) )
00593 {
00594 gFocusMgr.setKeyboardFocus(NULL);
00595 }
00596
00597 if( gFocusMgr.childHasMouseCapture( this ) )
00598 {
00599 gFocusMgr.setMouseCapture(NULL);
00600 }
00601 }
00602
00603
00604 void LLFloater::setResizeLimits( S32 min_width, S32 min_height )
00605 {
00606 mMinWidth = min_width;
00607 mMinHeight = min_height;
00608
00609 for( S32 i = 0; i < 4; i++ )
00610 {
00611 if( mResizeBar[i] )
00612 {
00613 if (i == LLResizeBar::LEFT || i == LLResizeBar::RIGHT)
00614 {
00615 mResizeBar[i]->setResizeLimits( min_width, S32_MAX );
00616 }
00617 else
00618 {
00619 mResizeBar[i]->setResizeLimits( min_height, S32_MAX );
00620 }
00621 }
00622 if( mResizeHandle[i] )
00623 {
00624 mResizeHandle[i]->setResizeLimits( min_width, min_height );
00625 }
00626 }
00627 }
00628
00629
00630 void LLFloater::center()
00631 {
00632 if(getHost())
00633 {
00634
00635 return;
00636 }
00637 centerWithin(gFloaterView->getRect());
00638 }
00639
00640 void LLFloater::applyRectControl()
00641 {
00642 if (!getRectControl().empty())
00643 {
00644 const LLRect& rect = LLUI::sConfigGroup->getRect(getRectControl());
00645 translate( rect.mLeft - getRect().mLeft, rect.mBottom - getRect().mBottom);
00646 if (mResizable)
00647 {
00648 reshape(llmax(mMinWidth, rect.getWidth()), llmax(mMinHeight, rect.getHeight()));
00649 }
00650 }
00651 }
00652
00653 void LLFloater::setTitle( const LLString& title )
00654 {
00655 if (gNoRender)
00656 {
00657 return;
00658 }
00659 if (mDragHandle)
00660 mDragHandle->setTitle( title );
00661 }
00662
00663 const LLString& LLFloater::getTitle() const
00664 {
00665 return mDragHandle ? mDragHandle->getTitle() : LLString::null;
00666 }
00667
00668 void LLFloater::setShortTitle( const LLString& short_title )
00669 {
00670 mShortTitle = short_title;
00671 }
00672
00673 LLString LLFloater::getShortTitle()
00674 {
00675 if (mShortTitle.empty())
00676 {
00677 return mDragHandle ? mDragHandle->getTitle() : LLString::null;
00678 }
00679 else
00680 {
00681 return mShortTitle;
00682 }
00683 }
00684
00685
00686
00687 BOOL LLFloater::canSnapTo(const LLView* other_view)
00688 {
00689 if (NULL == other_view)
00690 {
00691 llwarns << "other_view is NULL" << llendl;
00692 return FALSE;
00693 }
00694
00695 if (other_view != getParent())
00696 {
00697 LLFloater* other_floaterp = (LLFloater*)other_view;
00698
00699 if (other_floaterp->getSnapTarget() == getHandle() && mDependents.find(other_floaterp->getHandle()) != mDependents.end())
00700 {
00701
00702 return FALSE;
00703 }
00704 }
00705
00706 return LLPanel::canSnapTo(other_view);
00707 }
00708
00709 void LLFloater::snappedTo(const LLView* snap_view)
00710 {
00711 if (!snap_view || snap_view == getParent())
00712 {
00713 clearSnapTarget();
00714 }
00715 else
00716 {
00717
00718 LLFloater* floaterp = (LLFloater*)snap_view;
00719
00720 setSnapTarget(floaterp->getHandle());
00721 }
00722 }
00723
00724 void LLFloater::userSetShape(const LLRect& new_rect)
00725 {
00726 const LLRect& old_rect = getRect();
00727 LLView::userSetShape(new_rect);
00728
00729
00730 if (!isMinimized())
00731 {
00732
00733 for(handle_set_iter_t dependent_it = mDependents.begin();
00734 dependent_it != mDependents.end(); ++dependent_it)
00735 {
00736 LLFloater* floaterp = dependent_it->get();
00737
00738 if (floaterp && floaterp->getSnapTarget() == getHandle())
00739 {
00740 S32 delta_x = 0;
00741 S32 delta_y = 0;
00742
00743 LLRect dependent_rect = floaterp->getRect();
00744 if (dependent_rect.mLeft - getRect().mLeft >= old_rect.getWidth() ||
00745 dependent_rect.mRight == getRect().mLeft + old_rect.getWidth())
00746 {
00747
00748 delta_x += new_rect.getWidth() - old_rect.getWidth();
00749 }
00750 if (dependent_rect.mBottom - getRect().mBottom >= old_rect.getHeight() ||
00751 dependent_rect.mTop == getRect().mBottom + old_rect.getHeight())
00752 {
00753
00754 delta_y += new_rect.getHeight() - old_rect.getHeight();
00755 }
00756
00757
00758 delta_x += new_rect.mLeft - old_rect.mLeft;
00759 delta_y += new_rect.mBottom - old_rect.mBottom;
00760
00761 dependent_rect.translate(delta_x, delta_y);
00762 floaterp->userSetShape(dependent_rect);
00763 }
00764 }
00765 }
00766 else
00767 {
00768
00769
00770 if ((new_rect.mLeft != old_rect.mLeft) ||
00771 (new_rect.mBottom != old_rect.mBottom))
00772 {
00773 mHasBeenDraggedWhileMinimized = TRUE;
00774 }
00775 }
00776 }
00777
00778 void LLFloater::setMinimized(BOOL minimize)
00779 {
00780 if (minimize == mMinimized) return;
00781
00782 if (minimize)
00783 {
00784 mExpandedRect = getRect();
00785
00786
00787
00788
00789 if (mHasBeenDraggedWhileMinimized)
00790 {
00791 setOrigin(mPreviousMinimizedLeft, mPreviousMinimizedBottom);
00792 }
00793 else
00794 {
00795 S32 left, bottom;
00796 gFloaterView->getMinimizePosition(&left, &bottom);
00797 setOrigin( left, bottom );
00798 }
00799
00800 if (mButtonsEnabled[BUTTON_MINIMIZE])
00801 {
00802 mButtonsEnabled[BUTTON_MINIMIZE] = FALSE;
00803 mButtonsEnabled[BUTTON_RESTORE] = TRUE;
00804 }
00805
00806 if (mDragHandle)
00807 {
00808 mDragHandle->setVisible(TRUE);
00809 }
00810 setBorderVisible(TRUE);
00811
00812 for(handle_set_iter_t dependent_it = mDependents.begin();
00813 dependent_it != mDependents.end();
00814 ++dependent_it)
00815 {
00816 LLFloater* floaterp = dependent_it->get();
00817 if (floaterp)
00818 {
00819 if (floaterp->isMinimizeable())
00820 {
00821 floaterp->setMinimized(TRUE);
00822 }
00823 else if (!floaterp->isMinimized())
00824 {
00825 floaterp->setVisible(FALSE);
00826 }
00827 }
00828 }
00829
00830
00831 releaseFocus();
00832
00833 for (S32 i = 0; i < 4; i++)
00834 {
00835 if (mResizeBar[i] != NULL)
00836 {
00837 mResizeBar[i]->setEnabled(FALSE);
00838 }
00839 if (mResizeHandle[i] != NULL)
00840 {
00841 mResizeHandle[i]->setEnabled(FALSE);
00842 }
00843 }
00844
00845 mMinimized = TRUE;
00846
00847
00848 reshape( MINIMIZED_WIDTH, LLFLOATER_HEADER_SIZE, TRUE);
00849 }
00850 else
00851 {
00852
00853
00854 if (mHasBeenDraggedWhileMinimized)
00855 {
00856 const LLRect& currentRect = getRect();
00857 mPreviousMinimizedLeft = currentRect.mLeft;
00858 mPreviousMinimizedBottom = currentRect.mBottom;
00859 }
00860
00861 setOrigin( mExpandedRect.mLeft, mExpandedRect.mBottom );
00862
00863 if (mButtonsEnabled[BUTTON_RESTORE])
00864 {
00865 mButtonsEnabled[BUTTON_MINIMIZE] = TRUE;
00866 mButtonsEnabled[BUTTON_RESTORE] = FALSE;
00867 }
00868
00869
00870 for(handle_set_iter_t dependent_it = mDependents.begin();
00871 dependent_it != mDependents.end();
00872 ++dependent_it)
00873 {
00874 LLFloater* floaterp = dependent_it->get();
00875 if (floaterp)
00876 {
00877 floaterp->setMinimized(FALSE);
00878 floaterp->setVisible(TRUE);
00879 }
00880 }
00881
00882 for (S32 i = 0; i < 4; i++)
00883 {
00884 if (mResizeBar[i] != NULL)
00885 {
00886 mResizeBar[i]->setEnabled(isResizable());
00887 }
00888 if (mResizeHandle[i] != NULL)
00889 {
00890 mResizeHandle[i]->setEnabled(isResizable());
00891 }
00892 }
00893
00894 mMinimized = FALSE;
00895
00896
00897 reshape( mExpandedRect.getWidth(), mExpandedRect.getHeight(), TRUE );
00898 }
00899 make_ui_sound("UISndWindowClose");
00900 updateButtons();
00901 }
00902
00903 void LLFloater::setFocus( BOOL b )
00904 {
00905 if (b && getIsChrome())
00906 {
00907 return;
00908 }
00909 LLUICtrl* last_focus = gFocusMgr.getLastFocusForGroup(this);
00910
00911 BOOL child_had_focus = gFocusMgr.childHasKeyboardFocus(this);
00912
00913
00914 LLPanel::setFocus(b);
00915
00916 if (b)
00917 {
00918
00919 if (!getHost() && !((LLFloaterView*)getParent())->getCycleMode())
00920 {
00921 if (!isFrontmost())
00922 {
00923 setFrontmost();
00924 }
00925 }
00926
00927
00928 if (last_focus && !child_had_focus &&
00929 last_focus->isInEnabledChain() &&
00930 last_focus->isInVisibleChain())
00931 {
00932
00933 last_focus->setFocus(TRUE);
00934 }
00935 }
00936 }
00937
00938
00939 void LLFloater::setIsChrome(BOOL is_chrome)
00940 {
00941
00942 if (is_chrome)
00943 {
00944
00945 setFocus(FALSE);
00946
00947 setFocusRoot(FALSE);
00948 }
00949
00950
00951 if (mDragHandle)
00952 mDragHandle->setTitleVisible(!is_chrome);
00953
00954 LLPanel::setIsChrome(is_chrome);
00955 }
00956
00957 void LLFloater::setTitleVisible(bool visible)
00958 {
00959 if (mDragHandle)
00960 mDragHandle->setTitleVisible(visible);
00961 }
00962
00963
00964 void LLFloater::setForeground(BOOL front)
00965 {
00966 if (front != mForeground)
00967 {
00968 mForeground = front;
00969 if (mDragHandle)
00970 mDragHandle->setForeground( front );
00971
00972 if (!front)
00973 {
00974 releaseFocus();
00975 }
00976
00977 setBackgroundOpaque( front );
00978 }
00979 }
00980
00981 void LLFloater::cleanupHandles()
00982 {
00983
00984 for(handle_set_iter_t dependent_it = mDependents.begin();
00985 dependent_it != mDependents.end(); )
00986 {
00987 LLFloater* floaterp = dependent_it->get();
00988 if (!floaterp)
00989 {
00990 mDependents.erase(dependent_it++);
00991 }
00992 else
00993 {
00994 ++dependent_it;
00995 }
00996 }
00997 }
00998
00999 void LLFloater::setHost(LLMultiFloater* host)
01000 {
01001 if (mHostHandle.isDead() && host)
01002 {
01003
01004 mButtonScale = 0.9f;
01005
01006
01007 if (mCanTearOff)
01008 {
01009 mButtonsEnabled[BUTTON_TEAR_OFF] = TRUE;
01010 }
01011 }
01012 else if (!mHostHandle.isDead() && !host)
01013 {
01014 mButtonScale = 1.f;
01015
01016 }
01017 updateButtons();
01018 if (host)
01019 {
01020 mHostHandle = host->getHandle();
01021 mLastHostHandle = host->getHandle();
01022 }
01023 else
01024 {
01025 mHostHandle.markDead();
01026 }
01027 }
01028
01029 void LLFloater::moveResizeHandlesToFront()
01030 {
01031 for( S32 i = 0; i < 4; i++ )
01032 {
01033 if( mResizeBar[i] )
01034 {
01035 sendChildToFront(mResizeBar[i]);
01036 }
01037 }
01038
01039 for( S32 i = 0; i < 4; i++ )
01040 {
01041 if( mResizeHandle[i] )
01042 {
01043 sendChildToFront(mResizeHandle[i]);
01044 }
01045 }
01046 }
01047
01048 BOOL LLFloater::isFrontmost()
01049 {
01050 return gFloaterView && gFloaterView->getFrontmost() == this && getVisible();
01051 }
01052
01053 void LLFloater::addDependentFloater(LLFloater* floaterp, BOOL reposition)
01054 {
01055 mDependents.insert(floaterp->getHandle());
01056 floaterp->mDependeeHandle = getHandle();
01057
01058 if (reposition)
01059 {
01060 floaterp->setRect(gFloaterView->findNeighboringPosition(this, floaterp));
01061 floaterp->setSnapTarget(getHandle());
01062 }
01063 gFloaterView->adjustToFitScreen(floaterp, FALSE);
01064 if (floaterp->isFrontmost())
01065 {
01066
01067 gFloaterView->bringToFront(floaterp);
01068 }
01069 }
01070
01071 void LLFloater::addDependentFloater(LLHandle<LLFloater> dependent, BOOL reposition)
01072 {
01073 LLFloater* dependent_floaterp = dependent.get();
01074 if(dependent_floaterp)
01075 {
01076 addDependentFloater(dependent_floaterp, reposition);
01077 }
01078 }
01079
01080 void LLFloater::removeDependentFloater(LLFloater* floaterp)
01081 {
01082 mDependents.erase(floaterp->getHandle());
01083 floaterp->mDependeeHandle = LLHandle<LLFloater>();
01084 }
01085
01086
01087 BOOL LLFloater::handleMouseDown(S32 x, S32 y, MASK mask)
01088 {
01089 if( mMinimized )
01090 {
01091
01092 if( mButtonsEnabled[BUTTON_CLOSE] )
01093 {
01094 S32 local_x = x - mButtons[BUTTON_CLOSE]->getRect().mLeft;
01095 S32 local_y = y - mButtons[BUTTON_CLOSE]->getRect().mBottom;
01096
01097 if (mButtons[BUTTON_CLOSE]->pointInView(local_x, local_y)
01098 && mButtons[BUTTON_CLOSE]->handleMouseDown(local_x, local_y, mask))
01099 {
01100
01101 return TRUE;
01102 }
01103 }
01104
01105
01106 if( mButtonsEnabled[BUTTON_RESTORE] )
01107 {
01108 S32 local_x = x - mButtons[BUTTON_RESTORE]->getRect().mLeft;
01109 S32 local_y = y - mButtons[BUTTON_RESTORE]->getRect().mBottom;
01110
01111 if (mButtons[BUTTON_RESTORE]->pointInView(local_x, local_y)
01112 && mButtons[BUTTON_RESTORE]->handleMouseDown(local_x, local_y, mask))
01113 {
01114
01115 return TRUE;
01116 }
01117 }
01118
01119
01120 return mDragHandle->handleMouseDown(x, y, mask);
01121 }
01122 else
01123 {
01124 bringToFront( x, y );
01125 return LLPanel::handleMouseDown( x, y, mask );
01126 }
01127 }
01128
01129
01130 BOOL LLFloater::handleRightMouseDown(S32 x, S32 y, MASK mask)
01131 {
01132 BOOL was_minimized = mMinimized;
01133 bringToFront( x, y );
01134 return was_minimized || LLPanel::handleRightMouseDown( x, y, mask );
01135 }
01136
01137
01138
01139 BOOL LLFloater::handleDoubleClick(S32 x, S32 y, MASK mask)
01140 {
01141 BOOL was_minimized = mMinimized;
01142 setMinimized(FALSE);
01143 return was_minimized || LLPanel::handleDoubleClick(x, y, mask);
01144 }
01145
01146 void LLFloater::bringToFront( S32 x, S32 y )
01147 {
01148 if (getVisible() && pointInView(x, y))
01149 {
01150 LLMultiFloater* hostp = getHost();
01151 if (hostp)
01152 {
01153 hostp->showFloater(this);
01154 }
01155 else
01156 {
01157 LLFloaterView* parent = (LLFloaterView*) getParent();
01158 if (parent)
01159 {
01160 parent->bringToFront( this );
01161 }
01162 }
01163 }
01164 }
01165
01166
01167
01168 void LLFloater::setVisibleAndFrontmost(BOOL take_focus)
01169 {
01170 setVisible(TRUE);
01171 setFrontmost(take_focus);
01172 }
01173
01174 void LLFloater::setFrontmost(BOOL take_focus)
01175 {
01176 LLMultiFloater* hostp = getHost();
01177 if (hostp)
01178 {
01179
01180
01181 hostp->showFloater(this);
01182 }
01183 else
01184 {
01185
01186
01187 ((LLFloaterView*)getParent())->bringToFront(this, take_focus);
01188 }
01189 }
01190
01191
01192 void LLFloater::setEditModeEnabled(BOOL enable)
01193 {
01194 if (enable != sEditModeEnabled)
01195 {
01196 S32 count = 0;
01197 for(handle_map_iter_t iter = sFloaterMap.begin(); iter != sFloaterMap.end(); ++iter)
01198 {
01199 LLFloater* floater = iter->second;
01200 if (!floater->isDead())
01201 {
01202 iter->second->mButtonsEnabled[BUTTON_EDIT] = enable;
01203 iter->second->updateButtons();
01204 }
01205 count++;
01206 }
01207 }
01208
01209 sEditModeEnabled = enable;
01210 }
01211
01212
01213
01214 void LLFloater::onClickMinimize(void *userdata)
01215 {
01216 LLFloater* self = (LLFloater*) userdata;
01217 if (!self) return;
01218
01219 self->setMinimized( !self->isMinimized() );
01220 }
01221
01222 void LLFloater::onClickTearOff(void *userdata)
01223 {
01224 LLFloater* self = (LLFloater*) userdata;
01225 if (!self) return;
01226
01227 LLMultiFloater* host_floater = self->getHost();
01228 if (host_floater)
01229 {
01230 LLRect new_rect;
01231 host_floater->removeFloater(self);
01232
01233 gFloaterView->addChild(self);
01234
01235 self->open();
01236
01237
01238 if (self->getRectControl().empty())
01239 {
01240 new_rect.setLeftTopAndSize(host_floater->getRect().mLeft + 5, host_floater->getRect().mTop - LLFLOATER_HEADER_SIZE - 5, self->getRect().getWidth(), self->getRect().getHeight());
01241 self->setRect(new_rect);
01242 }
01243 gFloaterView->adjustToFitScreen(self, FALSE);
01244
01245 self->setFocus(TRUE);
01246 }
01247 else
01248 {
01249 LLMultiFloater* new_host = (LLMultiFloater*)self->mLastHostHandle.get();
01250 if (new_host)
01251 {
01252 new_host->showFloater(self);
01253
01254 new_host->open();
01255 }
01256 }
01257 }
01258
01259
01260 void LLFloater::onClickEdit(void *userdata)
01261 {
01262 LLFloater* self = (LLFloater*) userdata;
01263 if (!self) return;
01264
01265 self->mEditing = self->mEditing ? FALSE : TRUE;
01266 }
01267
01268
01269 void LLFloater::closeFocusedFloater()
01270 {
01271 LLFloater* focused_floater = NULL;
01272
01273 handle_map_iter_t iter;
01274 for(iter = sFloaterMap.begin(); iter != sFloaterMap.end(); ++iter)
01275 {
01276 focused_floater = iter->second;
01277 if (focused_floater->hasFocus())
01278 {
01279 break;
01280 }
01281 }
01282
01283 if (iter == sFloaterMap.end())
01284 {
01285
01286 return;
01287 }
01288
01289 focused_floater->close();
01290
01291
01292
01293 if (gFocusMgr.getKeyboardFocus() == NULL)
01294 {
01295
01296
01297 gFloaterView->focusFrontFloater();
01298 }
01299 }
01300
01301
01302
01303 void LLFloater::onClickClose( void* userdata )
01304 {
01305 LLFloater* self = (LLFloater*) userdata;
01306 if (!self) return;
01307
01308 self->close();
01309 }
01310
01311
01312
01313 void LLFloater::draw()
01314 {
01315
01316 if( isBackgroundVisible() )
01317 {
01318 S32 left = LLPANEL_BORDER_WIDTH;
01319 S32 top = getRect().getHeight() - LLPANEL_BORDER_WIDTH;
01320 S32 right = getRect().getWidth() - LLPANEL_BORDER_WIDTH;
01321 S32 bottom = LLPANEL_BORDER_WIDTH;
01322
01323 LLColor4 shadow_color = LLUI::sColorsGroup->getColor("ColorDropShadow");
01324 F32 shadow_offset = (F32)LLUI::sConfigGroup->getS32("DropShadowFloater");
01325 if (!isBackgroundOpaque())
01326 {
01327 shadow_offset *= 0.2f;
01328 shadow_color.mV[VALPHA] *= 0.5f;
01329 }
01330 gl_drop_shadow(left, top, right, bottom,
01331 shadow_color,
01332 llround(shadow_offset));
01333
01334
01335 if (isBackgroundOpaque())
01336 {
01337 gl_rect_2d( left, top, right, bottom, getBackgroundColor() );
01338 }
01339 else
01340 {
01341 gl_rect_2d( left, top, right, bottom, getTransparentColor() );
01342 }
01343
01344 if(gFocusMgr.childHasKeyboardFocus(this) && !getIsChrome() && !getTitle().empty())
01345 {
01346
01347 const LLFontGL* font = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF );
01348 LLRect r = getRect();
01349 gl_rect_2d_offset_local(0, r.getHeight(), r.getWidth(), r.getHeight() - (S32)font->getLineHeight() - 1,
01350 LLUI::sColorsGroup->getColor("TitleBarFocusColor"), 0, TRUE);
01351 }
01352 }
01353
01354 LLPanel::updateDefaultBtn();
01355
01356 if( getDefaultButton() )
01357 {
01358 if (hasFocus() && getDefaultButton()->getEnabled())
01359 {
01360 LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus();
01361
01362 BOOL focus_is_child_button = dynamic_cast<LLButton*>(focus_ctrl) != NULL && focus_ctrl->getParent() == this;
01363
01364 getDefaultButton()->setBorderEnabled(!focus_is_child_button);
01365 }
01366 else
01367 {
01368 getDefaultButton()->setBorderEnabled(FALSE);
01369 }
01370 }
01371 if (isMinimized())
01372 {
01373 for (S32 i = 0; i < BUTTON_COUNT; i++)
01374 {
01375 drawChild(mButtons[i]);
01376 }
01377 drawChild(mDragHandle);
01378 }
01379 else
01380 {
01381
01382 LLView* focused_child = gFocusMgr.getKeyboardFocus();
01383 BOOL focused_child_visible = FALSE;
01384 if (focused_child && focused_child->getParent() == this)
01385 {
01386 focused_child_visible = focused_child->getVisible();
01387 focused_child->setVisible(FALSE);
01388 }
01389
01390
01391 LLView::draw();
01392
01393 if (focused_child_visible)
01394 {
01395 focused_child->setVisible(TRUE);
01396 }
01397 drawChild(focused_child);
01398 }
01399
01400 if( isBackgroundVisible() )
01401 {
01402
01403
01404 LLUI::setLineWidth(1.5f);
01405 LLColor4 outlineColor = gFocusMgr.childHasKeyboardFocus(this) ? LLUI::sColorsGroup->getColor("FloaterFocusBorderColor") : LLUI::sColorsGroup->getColor("FloaterUnfocusBorderColor");
01406 gl_rect_2d_offset_local(0, getRect().getHeight() + 1, getRect().getWidth() + 1, 0, outlineColor, -LLPANEL_BORDER_WIDTH, FALSE);
01407 LLUI::setLineWidth(1.f);
01408 }
01409
01410
01411
01412 if (mCanTearOff && !getHost())
01413 {
01414 LLFloater* old_host = mLastHostHandle.get();
01415 if (!old_host)
01416 {
01417 setCanTearOff(FALSE);
01418 }
01419 }
01420 }
01421
01422 void LLFloater::setCanMinimize(BOOL can_minimize)
01423 {
01424
01425
01426 if (!can_minimize)
01427 {
01428 setMinimized(FALSE);
01429 }
01430
01431 if (can_minimize)
01432 {
01433 if (isMinimized())
01434 {
01435 mButtonsEnabled[BUTTON_MINIMIZE] = FALSE;
01436 mButtonsEnabled[BUTTON_RESTORE] = TRUE;
01437 }
01438 else
01439 {
01440 mButtonsEnabled[BUTTON_MINIMIZE] = TRUE;
01441 mButtonsEnabled[BUTTON_RESTORE] = FALSE;
01442 }
01443 }
01444 else
01445 {
01446 mButtonsEnabled[BUTTON_MINIMIZE] = FALSE;
01447 mButtonsEnabled[BUTTON_RESTORE] = FALSE;
01448 }
01449
01450 updateButtons();
01451 }
01452
01453 void LLFloater::setCanClose(BOOL can_close)
01454 {
01455 mButtonsEnabled[BUTTON_CLOSE] = can_close;
01456
01457 updateButtons();
01458 }
01459
01460 void LLFloater::setCanTearOff(BOOL can_tear_off)
01461 {
01462 mCanTearOff = can_tear_off;
01463 mButtonsEnabled[BUTTON_TEAR_OFF] = mCanTearOff && !mHostHandle.isDead();
01464
01465 updateButtons();
01466 }
01467
01468
01469 void LLFloater::setCanResize(BOOL can_resize)
01470 {
01471 if (mResizable && !can_resize)
01472 {
01473 for (S32 i = 0; i < 4; i++)
01474 {
01475 removeChild(mResizeBar[i], TRUE);
01476 mResizeBar[i] = NULL;
01477
01478 removeChild(mResizeHandle[i], TRUE);
01479 mResizeHandle[i] = NULL;
01480 }
01481 }
01482 else if (!mResizable && can_resize)
01483 {
01484
01485 const S32 RESIZE_BAR_THICKNESS = 3;
01486 mResizeBar[0] = new LLResizeBar(
01487 "resizebar_left",
01488 this,
01489 LLRect( 0, getRect().getHeight(), RESIZE_BAR_THICKNESS, 0),
01490 mMinWidth, S32_MAX, LLResizeBar::LEFT );
01491 addChild( mResizeBar[0] );
01492
01493 mResizeBar[1] = new LLResizeBar(
01494 "resizebar_top",
01495 this,
01496 LLRect( 0, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_BAR_THICKNESS),
01497 mMinHeight, S32_MAX, LLResizeBar::TOP );
01498 addChild( mResizeBar[1] );
01499
01500 mResizeBar[2] = new LLResizeBar(
01501 "resizebar_right",
01502 this,
01503 LLRect( getRect().getWidth() - RESIZE_BAR_THICKNESS, getRect().getHeight(), getRect().getWidth(), 0),
01504 mMinWidth, S32_MAX, LLResizeBar::RIGHT );
01505 addChild( mResizeBar[2] );
01506
01507 mResizeBar[3] = new LLResizeBar(
01508 "resizebar_bottom",
01509 this,
01510 LLRect( 0, RESIZE_BAR_THICKNESS, getRect().getWidth(), 0),
01511 mMinHeight, S32_MAX, LLResizeBar::BOTTOM );
01512 addChild( mResizeBar[3] );
01513
01514
01515
01516 mResizeHandle[0] = new LLResizeHandle(
01517 "Resize Handle",
01518 LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, RESIZE_HANDLE_HEIGHT, getRect().getWidth(), 0),
01519 mMinWidth,
01520 mMinHeight,
01521 LLResizeHandle::RIGHT_BOTTOM);
01522 addChild(mResizeHandle[0]);
01523
01524 mResizeHandle[1] = new LLResizeHandle( "resize",
01525 LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_HANDLE_HEIGHT),
01526 mMinWidth,
01527 mMinHeight,
01528 LLResizeHandle::RIGHT_TOP );
01529 addChild(mResizeHandle[1]);
01530
01531 mResizeHandle[2] = new LLResizeHandle( "resize",
01532 LLRect( 0, RESIZE_HANDLE_HEIGHT, RESIZE_HANDLE_WIDTH, 0 ),
01533 mMinWidth,
01534 mMinHeight,
01535 LLResizeHandle::LEFT_BOTTOM );
01536 addChild(mResizeHandle[2]);
01537
01538 mResizeHandle[3] = new LLResizeHandle( "resize",
01539 LLRect( 0, getRect().getHeight(), RESIZE_HANDLE_WIDTH, getRect().getHeight() - RESIZE_HANDLE_HEIGHT ),
01540 mMinWidth,
01541 mMinHeight,
01542 LLResizeHandle::LEFT_TOP );
01543 addChild(mResizeHandle[3]);
01544 }
01545 mResizable = can_resize;
01546 }
01547
01548 void LLFloater::setCanDrag(BOOL can_drag)
01549 {
01550
01551
01552 if (!can_drag && mDragHandle->getEnabled())
01553 {
01554 mDragHandle->setEnabled(FALSE);
01555 }
01556 else if (can_drag && !mDragHandle->getEnabled())
01557 {
01558 mDragHandle->setEnabled(TRUE);
01559 }
01560 }
01561
01562 void LLFloater::updateButtons()
01563 {
01564 S32 button_count = 0;
01565 for (S32 i = 0; i < BUTTON_COUNT; i++)
01566 {
01567 mButtons[i]->setEnabled(mButtonsEnabled[i]);
01568
01569 if (mButtonsEnabled[i]
01570
01571
01572
01573 || (i == BUTTON_CLOSE && mButtonScale != 1.f))
01574 {
01575 button_count++;
01576
01577 LLRect btn_rect;
01578 if (mDragOnLeft)
01579 {
01580 btn_rect.setLeftTopAndSize(
01581 LLPANEL_BORDER_WIDTH,
01582 getRect().getHeight() - CLOSE_BOX_FROM_TOP - (LLFLOATER_CLOSE_BOX_SIZE + 1) * button_count,
01583 llround((F32)LLFLOATER_CLOSE_BOX_SIZE * mButtonScale),
01584 llround((F32)LLFLOATER_CLOSE_BOX_SIZE * mButtonScale));
01585 }
01586 else
01587 {
01588 btn_rect.setLeftTopAndSize(
01589 getRect().getWidth() - LLPANEL_BORDER_WIDTH - (LLFLOATER_CLOSE_BOX_SIZE + 1) * button_count,
01590 getRect().getHeight() - CLOSE_BOX_FROM_TOP,
01591 llround((F32)LLFLOATER_CLOSE_BOX_SIZE * mButtonScale),
01592 llround((F32)LLFLOATER_CLOSE_BOX_SIZE * mButtonScale));
01593 }
01594
01595 mButtons[i]->setRect(btn_rect);
01596 mButtons[i]->setVisible(TRUE);
01597
01598 mButtons[i]->setTabStop(i == BUTTON_RESTORE);
01599 }
01600 else if (mButtons[i])
01601 {
01602 mButtons[i]->setVisible(FALSE);
01603 }
01604 }
01605 if (mDragHandle)
01606 mDragHandle->setMaxTitleWidth(getRect().getWidth() - (button_count * (LLFLOATER_CLOSE_BOX_SIZE + 1)));
01607 }
01608
01609 void LLFloater::buildButtons()
01610 {
01611 for (S32 i = 0; i < BUTTON_COUNT; i++)
01612 {
01613 LLRect btn_rect;
01614 if (mDragOnLeft)
01615 {
01616 btn_rect.setLeftTopAndSize(
01617 LLPANEL_BORDER_WIDTH,
01618 getRect().getHeight() - CLOSE_BOX_FROM_TOP - (LLFLOATER_CLOSE_BOX_SIZE + 1) * (i + 1),
01619 llround(LLFLOATER_CLOSE_BOX_SIZE * mButtonScale),
01620 llround(LLFLOATER_CLOSE_BOX_SIZE * mButtonScale));
01621 }
01622 else
01623 {
01624 btn_rect.setLeftTopAndSize(
01625 getRect().getWidth() - LLPANEL_BORDER_WIDTH - (LLFLOATER_CLOSE_BOX_SIZE + 1) * (i + 1),
01626 getRect().getHeight() - CLOSE_BOX_FROM_TOP,
01627 llround(LLFLOATER_CLOSE_BOX_SIZE * mButtonScale),
01628 llround(LLFLOATER_CLOSE_BOX_SIZE * mButtonScale));
01629 }
01630
01631 LLButton* buttonp = new LLButton(
01632 sButtonNames[i],
01633 btn_rect,
01634 sButtonActiveImageNames[i],
01635 sButtonPressedImageNames[i],
01636 "",
01637 sButtonCallbacks[i],
01638 this,
01639 LLFontGL::sSansSerif);
01640
01641 buttonp->setTabStop(FALSE);
01642 buttonp->setFollowsTop();
01643 buttonp->setFollowsRight();
01644 buttonp->setToolTip( sButtonToolTips[i] );
01645 buttonp->setImageColor(LLUI::sColorsGroup->getColor("FloaterButtonImageColor"));
01646 buttonp->setHoverImages(sButtonPressedImageNames[i],
01647 sButtonPressedImageNames[i]);
01648 buttonp->setScaleImage(TRUE);
01649 buttonp->setSaveToXML(false);
01650 addChild(buttonp);
01651 mButtons[i] = buttonp;
01652 }
01653
01654 updateButtons();
01655 }
01656
01658
01659
01660 LLFloaterView::LLFloaterView( const LLString& name, const LLRect& rect )
01661 : LLUICtrl( name, rect, FALSE, NULL, NULL, FOLLOWS_ALL ),
01662 mFocusCycleMode(FALSE),
01663 mSnapOffsetBottom(0)
01664 {
01665 setTabStop(FALSE);
01666 resetStartingFloaterPosition();
01667 }
01668
01669
01670 void LLFloaterView::reshape(S32 width, S32 height, BOOL called_from_parent)
01671 {
01672 reshapeFloater(width, height, called_from_parent, ADJUST_VERTICAL_YES);
01673 }
01674
01675
01676 void LLFloaterView::reshapeFloater(S32 width, S32 height, BOOL called_from_parent, BOOL adjust_vertical)
01677 {
01678 S32 old_width = getRect().getWidth();
01679 S32 old_height = getRect().getHeight();
01680
01681 for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
01682 {
01683 LLView* viewp = *child_it;
01684 LLFloater* floaterp = (LLFloater*)viewp;
01685 if (floaterp->isDependent())
01686 {
01687
01688 continue;
01689 }
01690 LLRect r = floaterp->getRect();
01691
01692
01693 S32 left_offset = llabs(r.mLeft - 0);
01694 S32 right_offset = llabs(old_width - r.mRight);
01695
01696 S32 top_offset = llabs(old_height - r.mTop);
01697 S32 bottom_offset = llabs(r.mBottom - 0);
01698
01699
01700 U32 follow_flags = 0x0;
01701
01702 if (left_offset < right_offset)
01703 {
01704 follow_flags |= FOLLOWS_LEFT;
01705 }
01706 else
01707 {
01708 follow_flags |= FOLLOWS_RIGHT;
01709 }
01710
01711
01712
01713
01714 if (!adjust_vertical)
01715 {
01716 follow_flags |= FOLLOWS_TOP;
01717 }
01718 else if (top_offset < bottom_offset)
01719 {
01720 follow_flags |= FOLLOWS_TOP;
01721 }
01722 else
01723 {
01724 follow_flags |= FOLLOWS_BOTTOM;
01725 }
01726
01727 floaterp->setFollows(follow_flags);
01728
01729
01730 for(LLFloater::handle_set_iter_t dependent_it = floaterp->mDependents.begin();
01731 dependent_it != floaterp->mDependents.end(); ++dependent_it)
01732 {
01733 LLFloater* dependent_floaterp = dependent_it->get();
01734 if (dependent_floaterp)
01735 {
01736 dependent_floaterp->setFollows(follow_flags);
01737 }
01738 }
01739 }
01740
01741 LLView::reshape(width, height, called_from_parent);
01742 }
01743
01744
01745 void LLFloaterView::restoreAll()
01746 {
01747
01748 for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
01749 {
01750 LLFloater* floaterp = (LLFloater*)*child_it;
01751 floaterp->setMinimized(FALSE);
01752 }
01753
01754
01755
01756
01757 }
01758
01759
01760 void LLFloaterView::getNewFloaterPosition(S32* left,S32* top)
01761 {
01762
01763 static BOOL first = TRUE;
01764 if( first )
01765 {
01766 resetStartingFloaterPosition();
01767 first = FALSE;
01768 }
01769
01770 const S32 FLOATER_PAD = 16;
01771 LLCoordWindow window_size;
01772 getWindow()->getSize(&window_size);
01773 LLRect full_window(0, window_size.mY, window_size.mX, 0);
01774 LLRect floater_creation_rect(
01775 160,
01776 full_window.getHeight() - 2 * MENU_BAR_HEIGHT,
01777 full_window.getWidth() * 2 / 3,
01778 130 );
01779 floater_creation_rect.stretch( -FLOATER_PAD );
01780
01781 *left = mNextLeft;
01782 *top = mNextTop;
01783
01784 const S32 STEP = 25;
01785 S32 bottom = floater_creation_rect.mBottom + 2 * STEP;
01786 S32 right = floater_creation_rect.mRight - 4 * STEP;
01787
01788 mNextTop -= STEP;
01789 mNextLeft += STEP;
01790
01791 if( (mNextTop < bottom ) || (mNextLeft > right) )
01792 {
01793 mColumn++;
01794 mNextTop = floater_creation_rect.mTop;
01795 mNextLeft = STEP * mColumn;
01796
01797 if( (mNextTop < bottom) || (mNextLeft > right) )
01798 {
01799
01800 resetStartingFloaterPosition();
01801 }
01802 }
01803 }
01804
01805 void LLFloaterView::resetStartingFloaterPosition()
01806 {
01807 const S32 FLOATER_PAD = 16;
01808 LLCoordWindow window_size;
01809 getWindow()->getSize(&window_size);
01810 LLRect full_window(0, window_size.mY, window_size.mX, 0);
01811 LLRect floater_creation_rect(
01812 160,
01813 full_window.getHeight() - 2 * MENU_BAR_HEIGHT,
01814 full_window.getWidth() * 2 / 3,
01815 130 );
01816 floater_creation_rect.stretch( -FLOATER_PAD );
01817
01818 mNextLeft = floater_creation_rect.mLeft;
01819 mNextTop = floater_creation_rect.mTop;
01820 mColumn = 0;
01821 }
01822
01823 LLRect LLFloaterView::findNeighboringPosition( LLFloater* reference_floater, LLFloater* neighbor )
01824 {
01825 LLRect base_rect = reference_floater->getRect();
01826 S32 width = neighbor->getRect().getWidth();
01827 S32 height = neighbor->getRect().getHeight();
01828 LLRect new_rect = neighbor->getRect();
01829
01830 LLRect expanded_base_rect = base_rect;
01831 expanded_base_rect.stretch(10);
01832 for(LLFloater::handle_set_iter_t dependent_it = reference_floater->mDependents.begin();
01833 dependent_it != reference_floater->mDependents.end(); ++dependent_it)
01834 {
01835 LLFloater* sibling = dependent_it->get();
01836
01837 if (sibling &&
01838 sibling != neighbor &&
01839 sibling->getVisible() &&
01840 expanded_base_rect.rectInRect(&sibling->getRect()))
01841 {
01842 base_rect.unionWith(sibling->getRect());
01843 }
01844 }
01845
01846 S32 left_margin = llmax(0, base_rect.mLeft);
01847 S32 right_margin = llmax(0, getRect().getWidth() - base_rect.mRight);
01848 S32 top_margin = llmax(0, getRect().getHeight() - base_rect.mTop);
01849 S32 bottom_margin = llmax(0, base_rect.mBottom);
01850
01851
01852
01853 for (S32 i = 0; i < 5; i++)
01854 {
01855 if (right_margin > width)
01856 {
01857 new_rect.translate(base_rect.mRight - neighbor->getRect().mLeft, base_rect.mTop - neighbor->getRect().mTop);
01858 return new_rect;
01859 }
01860 else if (left_margin > width)
01861 {
01862 new_rect.translate(base_rect.mLeft - neighbor->getRect().mRight, base_rect.mTop - neighbor->getRect().mTop);
01863 return new_rect;
01864 }
01865 else if (bottom_margin > height)
01866 {
01867 new_rect.translate(base_rect.mLeft - neighbor->getRect().mLeft, base_rect.mBottom - neighbor->getRect().mTop);
01868 return new_rect;
01869 }
01870 else if (top_margin > height)
01871 {
01872 new_rect.translate(base_rect.mLeft - neighbor->getRect().mLeft, base_rect.mTop - neighbor->getRect().mBottom);
01873 return new_rect;
01874 }
01875
01876
01877 left_margin += 20;
01878 right_margin += 20;
01879 top_margin += 20;
01880 bottom_margin += 20;
01881 }
01882
01883
01884 return new_rect;
01885 }
01886
01887
01888 void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus)
01889 {
01890
01891
01892 if (child->getHost())
01893 {
01894
01895 return;
01896 }
01897 std::vector<LLView*> floaters_to_move;
01898
01899 for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
01900 {
01901 LLView* viewp = *child_it;
01902 LLFloater *floater = (LLFloater *)viewp;
01903
01904
01905 if (child->isDependent())
01906 {
01907
01908 LLFloater::handle_set_iter_t found_dependent = floater->mDependents.find(child->getHandle());
01909
01910 if (found_dependent != floater->mDependents.end())
01911 {
01912
01913 for(LLFloater::handle_set_iter_t dependent_it = floater->mDependents.begin();
01914 dependent_it != floater->mDependents.end(); )
01915 {
01916 LLFloater* sibling = dependent_it->get();
01917 if (sibling)
01918 {
01919 floaters_to_move.push_back(sibling);
01920 }
01921 ++dependent_it;
01922 }
01923
01924 floaters_to_move.push_back(floater);
01925 }
01926 }
01927 }
01928
01929 std::vector<LLView*>::iterator view_it;
01930 for(view_it = floaters_to_move.begin(); view_it != floaters_to_move.end(); ++view_it)
01931 {
01932 LLFloater* floaterp = (LLFloater*)(*view_it);
01933 sendChildToFront(floaterp);
01934
01935
01936 if (!floaterp->isDependent())
01937 {
01938 floaterp->setMinimized(FALSE);
01939 }
01940 }
01941 floaters_to_move.clear();
01942
01943
01944 for(LLFloater::handle_set_iter_t dependent_it = child->mDependents.begin();
01945 dependent_it != child->mDependents.end(); )
01946 {
01947 LLFloater* dependent = dependent_it->get();
01948 if (dependent)
01949 {
01950 sendChildToFront(dependent);
01951
01952
01953
01954 }
01955 ++dependent_it;
01956 }
01957
01958
01959
01960 if( *getChildList()->begin() != child )
01961 {
01962 sendChildToFront(child);
01963 }
01964 child->setMinimized(FALSE);
01965 if (give_focus && !gFocusMgr.childHasKeyboardFocus(child))
01966 {
01967 child->setFocus(TRUE);
01968 }
01969 }
01970
01971 void LLFloaterView::highlightFocusedFloater()
01972 {
01973 for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
01974 {
01975 LLFloater *floater = (LLFloater *)(*child_it);
01976
01977
01978 if (floater->isDependent())
01979 {
01980 continue;
01981 }
01982
01983 BOOL floater_or_dependent_has_focus = gFocusMgr.childHasKeyboardFocus(floater);
01984 for(LLFloater::handle_set_iter_t dependent_it = floater->mDependents.begin();
01985 dependent_it != floater->mDependents.end();
01986 ++dependent_it)
01987 {
01988 LLFloater* dependent_floaterp = dependent_it->get();
01989 if (dependent_floaterp && gFocusMgr.childHasKeyboardFocus(dependent_floaterp))
01990 {
01991 floater_or_dependent_has_focus = TRUE;
01992 }
01993 }
01994
01995
01996 floater->setForeground(floater_or_dependent_has_focus);
01997
01998 for(LLFloater::handle_set_iter_t dependent_it = floater->mDependents.begin();
01999 dependent_it != floater->mDependents.end(); )
02000 {
02001 LLFloater* dependent_floaterp = dependent_it->get();
02002 if (dependent_floaterp)
02003 {
02004 dependent_floaterp->setForeground(floater_or_dependent_has_focus);
02005 }
02006 ++dependent_it;
02007 }
02008
02009 floater->cleanupHandles();
02010 }
02011 }
02012
02013 void LLFloaterView::unhighlightFocusedFloater()
02014 {
02015 for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
02016 {
02017 LLFloater *floater = (LLFloater *)(*child_it);
02018
02019 floater->setForeground(FALSE);
02020 }
02021 }
02022
02023 void LLFloaterView::focusFrontFloater()
02024 {
02025 LLFloater* floaterp = getFrontmost();
02026 if (floaterp)
02027 {
02028 floaterp->setFocus(TRUE);
02029 }
02030 }
02031
02032 void LLFloaterView::getMinimizePosition(S32 *left, S32 *bottom)
02033 {
02034 S32 col = 0;
02035 LLRect snap_rect_local = getLocalSnapRect();
02036 for(S32 row = snap_rect_local.mBottom;
02037 row < snap_rect_local.getHeight() - LLFLOATER_HEADER_SIZE;
02038 row += LLFLOATER_HEADER_SIZE )
02039 {
02040 for(col = snap_rect_local.mLeft;
02041 col < snap_rect_local.getWidth() - MINIMIZED_WIDTH;
02042 col += MINIMIZED_WIDTH)
02043 {
02044 bool foundGap = TRUE;
02045 for(child_list_const_iter_t child_it = getChildList()->begin();
02046 child_it != getChildList()->end();
02047 ++child_it)
02048 {
02049
02050 LLFloater* floater = (LLFloater*)((LLView*)*child_it);
02051 if(floater->isMinimized())
02052 {
02053 LLRect r = floater->getRect();
02054 if((r.mBottom < (row + LLFLOATER_HEADER_SIZE))
02055 && (r.mBottom > (row - LLFLOATER_HEADER_SIZE))
02056 && (r.mLeft < (col + MINIMIZED_WIDTH))
02057 && (r.mLeft > (col - MINIMIZED_WIDTH)))
02058 {
02059
02060
02061 foundGap = FALSE;
02062 break;
02063 }
02064 }
02065 }
02066 if(foundGap)
02067 {
02068 *left = col;
02069 *bottom = row;
02070 return;
02071 }
02072 }
02073 }
02074
02075
02076
02077 *left = snap_rect_local.mLeft;
02078 *bottom = snap_rect_local.mBottom;
02079 }
02080
02081
02082 void LLFloaterView::destroyAllChildren()
02083 {
02084 LLView::deleteAllChildren();
02085 }
02086
02087 void LLFloaterView::closeAllChildren(bool app_quitting)
02088 {
02089
02090
02091 child_list_t child_list = *(getChildList());
02092
02093 for (child_list_const_iter_t it = child_list.begin(); it != child_list.end(); ++it)
02094 {
02095 LLView* viewp = *it;
02096 child_list_const_iter_t exists = std::find(getChildList()->begin(), getChildList()->end(), viewp);
02097 if (exists == getChildList()->end())
02098 {
02099
02100 continue;
02101 }
02102
02103 LLFloater* floaterp = (LLFloater*)viewp;
02104
02105
02106
02107 if (floaterp->canClose() && !floaterp->isDead())
02108 {
02109 floaterp->close(app_quitting);
02110 }
02111 }
02112 }
02113
02114
02115 BOOL LLFloaterView::allChildrenClosed()
02116 {
02117
02118
02119 for (child_list_const_iter_t it = getChildList()->begin(); it != getChildList()->end(); ++it)
02120 {
02121 LLView* viewp = *it;
02122 LLFloater* floaterp = (LLFloater*)viewp;
02123
02124 if (floaterp->getVisible() && !floaterp->isDead() && floaterp->canClose())
02125 {
02126 return false;
02127 }
02128 }
02129 return true;
02130 }
02131
02132
02133 void LLFloaterView::refresh()
02134 {
02135
02136 for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
02137 {
02138 LLFloater* floaterp = (LLFloater*)*child_it;
02139 if( floaterp->getVisible() )
02140 {
02141
02142 adjustToFitScreen(floaterp, !floaterp->isMinimized());
02143 }
02144 }
02145 }
02146
02147 void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_outside)
02148 {
02149 if (floater->getParent() != this)
02150 {
02151
02152 return;
02153 }
02154 S32 screen_width = getSnapRect().getWidth();
02155 S32 screen_height = getSnapRect().getHeight();
02156
02157 LLRect snap_rect_local = getLocalSnapRect();
02158
02159 if( floater->isResizable() )
02160 {
02161 LLRect view_rect = floater->getRect();
02162 S32 old_width = view_rect.getWidth();
02163 S32 old_height = view_rect.getHeight();
02164 S32 min_width;
02165 S32 min_height;
02166 floater->getResizeLimits( &min_width, &min_height );
02167
02168
02169 S32 new_width = llmax( min_width, old_width );
02170 S32 new_height = llmax( min_height, old_height);
02171
02172 if((new_width > screen_width) || (new_height > screen_height))
02173 {
02174
02175 new_width = llmin(new_width, screen_width);
02176 new_height = llmin(new_height, screen_height);
02177
02178
02179 new_width = llmax(new_width, min_width);
02180 new_height = llmax(new_height, min_height);
02181
02182 floater->reshape( new_width, new_height, TRUE );
02183 if (floater->followsRight())
02184 {
02185 floater->translate(old_width - new_width, 0);
02186 }
02187
02188 if (floater->followsTop())
02189 {
02190 floater->translate(0, old_height - new_height);
02191 }
02192 }
02193 }
02194
02195
02196 if (floater->translateIntoRect( snap_rect_local, allow_partial_outside ))
02197 {
02198 floater->clearSnapTarget();
02199 }
02200 }
02201
02202 void LLFloaterView::draw()
02203 {
02204 refresh();
02205
02206
02207 LLFloater* focused_floater = getFocusedFloater();
02208
02209 if (mFocusCycleMode && focused_floater)
02210 {
02211 child_list_const_iter_t child_it = getChildList()->begin();
02212 for (;child_it != getChildList()->end(); ++child_it)
02213 {
02214 if ((*child_it) != focused_floater)
02215 {
02216 drawChild(*child_it);
02217 }
02218 }
02219
02220 drawChild(focused_floater, -TABBED_FLOATER_OFFSET, TABBED_FLOATER_OFFSET);
02221 }
02222 else
02223 {
02224 LLView::draw();
02225 }
02226 }
02227
02228 LLRect LLFloaterView::getSnapRect() const
02229 {
02230 LLRect snap_rect = getRect();
02231 snap_rect.mBottom += mSnapOffsetBottom;
02232
02233 return snap_rect;
02234 }
02235
02236 LLFloater *LLFloaterView::getFocusedFloater()
02237 {
02238 for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
02239 {
02240 LLUICtrl* ctrlp = (*child_it)->isCtrl() ? static_cast<LLUICtrl*>(*child_it) : NULL;
02241 if ( ctrlp && ctrlp->hasFocus() )
02242 {
02243 return static_cast<LLFloater *>(ctrlp);
02244 }
02245 }
02246 return NULL;
02247 }
02248
02249 LLFloater *LLFloaterView::getFrontmost()
02250 {
02251 for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
02252 {
02253 LLView* viewp = *child_it;
02254 if ( viewp->getVisible() && !viewp->isDead())
02255 {
02256 return (LLFloater *)viewp;
02257 }
02258 }
02259 return NULL;
02260 }
02261
02262 LLFloater *LLFloaterView::getBackmost()
02263 {
02264 LLFloater* back_most = NULL;
02265 for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
02266 {
02267 LLView* viewp = *child_it;
02268 if ( viewp->getVisible() )
02269 {
02270 back_most = (LLFloater *)viewp;
02271 }
02272 }
02273 return back_most;
02274 }
02275
02276 void LLFloaterView::syncFloaterTabOrder()
02277 {
02278
02279 for ( child_list_const_reverse_iter_t child_it = getChildList()->rbegin(); child_it != getChildList()->rend(); ++child_it)
02280 {
02281 LLFloater* floaterp = (LLFloater*)*child_it;
02282 if (gFocusMgr.childHasKeyboardFocus(floaterp))
02283 {
02284 bringToFront(floaterp, FALSE);
02285 break;
02286 }
02287 }
02288
02289
02290 for ( child_list_const_reverse_iter_t child_it = getChildList()->rbegin(); child_it != getChildList()->rend(); ++child_it)
02291 {
02292 LLFloater* floaterp = (LLFloater*)*child_it;
02293 moveChildToFrontOfTabGroup(floaterp);
02294 }
02295 }
02296
02297 LLFloater* LLFloaterView::getParentFloater(LLView* viewp)
02298 {
02299 LLView* parentp = viewp->getParent();
02300
02301 while(parentp && parentp != this)
02302 {
02303 viewp = parentp;
02304 parentp = parentp->getParent();
02305 }
02306
02307 if (parentp == this)
02308 {
02309 return (LLFloater*)viewp;
02310 }
02311
02312 return NULL;
02313 }
02314
02315 S32 LLFloaterView::getZOrder(LLFloater* child)
02316 {
02317 S32 rv = 0;
02318 for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
02319 {
02320 LLView* viewp = *child_it;
02321 if(viewp == child)
02322 {
02323 break;
02324 }
02325 ++rv;
02326 }
02327 return rv;
02328 }
02329
02330 void LLFloaterView::pushVisibleAll(BOOL visible, const skip_list_t& skip_list)
02331 {
02332 for (child_list_const_iter_t child_iter = getChildList()->begin();
02333 child_iter != getChildList()->end(); ++child_iter)
02334 {
02335 LLView *view = *child_iter;
02336 if (skip_list.find(view) == skip_list.end())
02337 {
02338 view->pushVisible(visible);
02339 }
02340 }
02341 }
02342
02343 void LLFloaterView::popVisibleAll(const skip_list_t& skip_list)
02344 {
02345 for (child_list_const_iter_t child_iter = getChildList()->begin();
02346 child_iter != getChildList()->end(); ++child_iter)
02347 {
02348 LLView *view = *child_iter;
02349 if (skip_list.find(view) == skip_list.end())
02350 {
02351 view->popVisible();
02352 }
02353 }
02354 }
02355
02356
02357
02358
02359
02360 LLMultiFloater::LLMultiFloater() :
02361 mTabContainer(NULL),
02362 mTabPos(LLTabContainer::TOP),
02363 mAutoResize(TRUE),
02364 mOrigMinWidth(0),
02365 mOrigMinHeight(0)
02366 {
02367
02368 }
02369
02370 LLMultiFloater::LLMultiFloater(LLTabContainer::TabPosition tab_pos) :
02371 mTabContainer(NULL),
02372 mTabPos(tab_pos),
02373 mAutoResize(TRUE),
02374 mOrigMinWidth(0),
02375 mOrigMinHeight(0)
02376 {
02377
02378 }
02379
02380 LLMultiFloater::LLMultiFloater(const LLString &name) :
02381 LLFloater(name),
02382 mTabContainer(NULL),
02383 mTabPos(LLTabContainer::TOP),
02384 mAutoResize(FALSE),
02385 mOrigMinWidth(0),
02386 mOrigMinHeight(0)
02387 {
02388 }
02389
02390 LLMultiFloater::LLMultiFloater(
02391 const LLString& name,
02392 const LLRect& rect,
02393 LLTabContainer::TabPosition tab_pos,
02394 BOOL auto_resize) :
02395 LLFloater(name, rect, name),
02396 mTabContainer(NULL),
02397 mTabPos(LLTabContainer::TOP),
02398 mAutoResize(auto_resize),
02399 mOrigMinWidth(0),
02400 mOrigMinHeight(0)
02401 {
02402 mTabContainer = new LLTabContainer("Preview Tabs",
02403 LLRect(LLPANEL_BORDER_WIDTH, getRect().getHeight() - LLFLOATER_HEADER_SIZE, getRect().getWidth() - LLPANEL_BORDER_WIDTH, 0),
02404 mTabPos,
02405 FALSE,
02406 FALSE);
02407 mTabContainer->setFollowsAll();
02408 if (isResizable())
02409 {
02410 mTabContainer->setRightTabBtnOffset(RESIZE_HANDLE_WIDTH);
02411 }
02412
02413 addChild(mTabContainer);
02414 }
02415
02416 LLMultiFloater::LLMultiFloater(
02417 const LLString& name,
02418 const LLString& rect_control,
02419 LLTabContainer::TabPosition tab_pos,
02420 BOOL auto_resize) :
02421 LLFloater(name, rect_control, name),
02422 mTabContainer(NULL),
02423 mTabPos(tab_pos),
02424 mAutoResize(auto_resize),
02425 mOrigMinWidth(0),
02426 mOrigMinHeight(0)
02427 {
02428 mTabContainer = new LLTabContainer("Preview Tabs",
02429 LLRect(LLPANEL_BORDER_WIDTH, getRect().getHeight() - LLFLOATER_HEADER_SIZE, getRect().getWidth() - LLPANEL_BORDER_WIDTH, 0),
02430 mTabPos,
02431 FALSE,
02432 FALSE);
02433 mTabContainer->setFollowsAll();
02434 if (isResizable() && mTabPos == LLTabContainer::BOTTOM)
02435 {
02436 mTabContainer->setRightTabBtnOffset(RESIZE_HANDLE_WIDTH);
02437 }
02438
02439 addChild(mTabContainer);
02440
02441 }
02442
02443
02444 void LLMultiFloater::open()
02445 {
02446 if (mTabContainer->getTabCount() > 0)
02447 {
02448 LLFloater::open();
02449 }
02450 else
02451 {
02452
02453
02454 close();
02455 }
02456 }
02457
02458 void LLMultiFloater::onClose(bool app_quitting)
02459 {
02460 if(closeAllFloaters() == TRUE)
02461 {
02462 LLFloater::onClose(app_quitting);
02463 }
02464 }
02465
02466 void LLMultiFloater::draw()
02467 {
02468 if (mTabContainer->getTabCount() == 0)
02469 {
02470
02471 close();
02472 }
02473 else
02474 {
02475 for (S32 i = 0; i < mTabContainer->getTabCount(); i++)
02476 {
02477 LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(i);
02478 if (floaterp->getShortTitle() != mTabContainer->getPanelTitle(i))
02479 {
02480 mTabContainer->setPanelTitle(i, floaterp->getShortTitle());
02481 }
02482 }
02483 LLFloater::draw();
02484 }
02485 }
02486
02487 BOOL LLMultiFloater::closeAllFloaters()
02488 {
02489 S32 tabToClose = 0;
02490 S32 lastTabCount = mTabContainer->getTabCount();
02491 while (tabToClose < mTabContainer->getTabCount())
02492 {
02493 LLFloater* first_floater = (LLFloater*)mTabContainer->getPanelByIndex(tabToClose);
02494 first_floater->close();
02495 if(lastTabCount == mTabContainer->getTabCount())
02496 {
02497
02498
02499 tabToClose++;
02500 }else
02501 {
02502
02503 lastTabCount = mTabContainer->getTabCount();
02504 }
02505 }
02506 if( mTabContainer->getTabCount() != 0 )
02507 return FALSE;
02508 return TRUE;
02509 }
02510
02511 void LLMultiFloater::growToFit(S32 content_width, S32 content_height)
02512 {
02513 S32 new_width = llmax(getRect().getWidth(), content_width + LLPANEL_BORDER_WIDTH * 2);
02514 S32 new_height = llmax(getRect().getHeight(), content_height + LLFLOATER_HEADER_SIZE + TABCNTR_HEADER_HEIGHT);
02515
02516 if (isMinimized())
02517 {
02518 LLRect newrect;
02519 newrect.setLeftTopAndSize(getExpandedRect().mLeft, getExpandedRect().mTop, new_width, new_height);
02520 setExpandedRect(newrect);
02521 }
02522 else
02523 {
02524 S32 old_height = getRect().getHeight();
02525 reshape(new_width, new_height);
02526
02527 translate(0, old_height - new_height);
02528 }
02529 }
02530
02542 void LLMultiFloater::addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point)
02543 {
02544 if (!floaterp)
02545 {
02546 return;
02547 }
02548
02549 if (!mTabContainer)
02550 {
02551 llerrs << "Tab Container used without having been initialized." << llendl;
02552 return;
02553 }
02554
02555 if (floaterp->getHost() == this)
02556 {
02557
02558
02559 mFloaterDataMap.erase(floaterp->getHandle());
02560 mTabContainer->removeTabPanel(floaterp);
02561 }
02562 else if (floaterp->getHost())
02563 {
02564
02565
02566 floaterp->getHost()->removeFloater(floaterp);
02567 }
02568 else if (floaterp->getParent() == gFloaterView)
02569 {
02570
02571 gFloaterView->removeChild(floaterp);
02572 }
02573
02574
02575 LLFloaterData floater_data;
02576 floater_data.mWidth = floaterp->getRect().getWidth();
02577 floater_data.mHeight = floaterp->getRect().getHeight();
02578 floater_data.mCanMinimize = floaterp->isMinimizeable();
02579 floater_data.mCanResize = floaterp->isResizable();
02580
02581
02582 floaterp->setCanMinimize(FALSE);
02583 floaterp->setCanResize(FALSE);
02584 floaterp->setCanDrag(FALSE);
02585 floaterp->storeRectControl();
02586
02587 floaterp->setBackgroundVisible(FALSE);
02588
02589 if (mAutoResize)
02590 {
02591 growToFit(floater_data.mWidth, floater_data.mHeight);
02592 }
02593
02594
02595 mTabContainer->addTabPanel(floaterp, floaterp->getShortTitle(), FALSE, onTabSelected, this, 0, FALSE, insertion_point);
02596 mFloaterDataMap[floaterp->getHandle()] = floater_data;
02597
02598 updateResizeLimits();
02599
02600 if ( select_added_floater )
02601 {
02602 mTabContainer->selectTabPanel(floaterp);
02603 }
02604 else
02605 {
02606
02607 mTabContainer->selectTab(mTabContainer->getCurrentPanelIndex());
02608 }
02609
02610 floaterp->setHost(this);
02611 if (isMinimized())
02612 {
02613 floaterp->setVisible(FALSE);
02614 }
02615 }
02616
02625 BOOL LLMultiFloater::selectFloater(LLFloater* floaterp)
02626 {
02627 return mTabContainer->selectTabPanel(floaterp);
02628 }
02629
02630
02631 void LLMultiFloater::selectNextFloater()
02632 {
02633 mTabContainer->selectNextTab();
02634 }
02635
02636
02637 void LLMultiFloater::selectPrevFloater()
02638 {
02639 mTabContainer->selectPrevTab();
02640 }
02641
02642 void LLMultiFloater::showFloater(LLFloater* floaterp)
02643 {
02644
02645
02646
02647
02648 if (floaterp != mTabContainer->getCurrentPanel() &&
02649 !mTabContainer->selectTabPanel(floaterp))
02650 {
02651 addFloater(floaterp, TRUE);
02652 }
02653 }
02654
02655 void LLMultiFloater::removeFloater(LLFloater* floaterp)
02656 {
02657 if ( floaterp->getHost() != this )
02658 return;
02659
02660 floater_data_map_t::iterator found_data_it = mFloaterDataMap.find(floaterp->getHandle());
02661 if (found_data_it != mFloaterDataMap.end())
02662 {
02663 LLFloaterData& floater_data = found_data_it->second;
02664 floaterp->setCanMinimize(floater_data.mCanMinimize);
02665 if (!floater_data.mCanResize)
02666 {
02667
02668 floaterp->reshape(floater_data.mWidth, floater_data.mHeight);
02669 }
02670 floaterp->setCanResize(floater_data.mCanResize);
02671 mFloaterDataMap.erase(found_data_it);
02672 }
02673 mTabContainer->removeTabPanel(floaterp);
02674 floaterp->setBackgroundVisible(TRUE);
02675 floaterp->setCanDrag(TRUE);
02676 floaterp->setHost(NULL);
02677 floaterp->applyRectControl();
02678
02679 updateResizeLimits();
02680
02681 tabOpen((LLFloater*)mTabContainer->getCurrentPanel(), false);
02682 }
02683
02684 void LLMultiFloater::tabOpen(LLFloater* opened_floater, bool from_click)
02685 {
02686
02687 }
02688
02689 void LLMultiFloater::tabClose()
02690 {
02691 if (mTabContainer->getTabCount() == 0)
02692 {
02693
02694 close();
02695 }
02696 }
02697
02698 void LLMultiFloater::setVisible(BOOL visible)
02699 {
02700
02701 LLFloater::setVisible(visible);
02702
02703 if (mTabContainer)
02704 {
02705 LLPanel* cur_floaterp = mTabContainer->getCurrentPanel();
02706
02707 if (cur_floaterp)
02708 {
02709 cur_floaterp->setVisible(visible);
02710 }
02711
02712
02713
02714 if (visible && !cur_floaterp)
02715 {
02716 mTabContainer->selectLastTab();
02717 }
02718 }
02719 }
02720
02721 BOOL LLMultiFloater::handleKeyHere(KEY key, MASK mask)
02722 {
02723 if (key == 'W' && mask == MASK_CONTROL)
02724 {
02725 LLFloater* floater = getActiveFloater();
02726
02727 if (floater && floater->canClose() && floater->isCloseable())
02728 {
02729 floater->close();
02730 }
02731 return TRUE;
02732 }
02733
02734 return LLFloater::handleKeyHere(key, mask);
02735 }
02736
02737 LLFloater* LLMultiFloater::getActiveFloater()
02738 {
02739 return (LLFloater*)mTabContainer->getCurrentPanel();
02740 }
02741
02742 S32 LLMultiFloater::getFloaterCount()
02743 {
02744 return mTabContainer->getTabCount();
02745 }
02746
02756 BOOL LLMultiFloater::isFloaterFlashing(LLFloater* floaterp)
02757 {
02758 if ( floaterp && floaterp->getHost() == this )
02759 return mTabContainer->getTabPanelFlashing(floaterp);
02760
02761 return FALSE;
02762 }
02763
02773 void LLMultiFloater::setFloaterFlashing(LLFloater* floaterp, BOOL flashing)
02774 {
02775 if ( floaterp && floaterp->getHost() == this )
02776 mTabContainer->setTabPanelFlashing(floaterp, flashing);
02777 }
02778
02779
02780 void LLMultiFloater::onTabSelected(void* userdata, bool from_click)
02781 {
02782 LLMultiFloater* floaterp = (LLMultiFloater*)userdata;
02783
02784 floaterp->tabOpen((LLFloater*)floaterp->mTabContainer->getCurrentPanel(), from_click);
02785 }
02786
02787 void LLMultiFloater::setCanResize(BOOL can_resize)
02788 {
02789 LLFloater::setCanResize(can_resize);
02790 if (isResizable() && mTabContainer->getTabPosition() == LLTabContainer::BOTTOM)
02791 {
02792 mTabContainer->setRightTabBtnOffset(RESIZE_HANDLE_WIDTH);
02793 }
02794 else
02795 {
02796 mTabContainer->setRightTabBtnOffset(0);
02797 }
02798 }
02799
02800 BOOL LLMultiFloater::postBuild()
02801 {
02802
02803 getResizeLimits(&mOrigMinWidth, &mOrigMinHeight);
02804
02805 if (mTabContainer)
02806 {
02807 return TRUE;
02808 }
02809
02810 requires<LLTabContainer>("Preview Tabs");
02811 if (checkRequirements())
02812 {
02813 mTabContainer = getChild<LLTabContainer>("Preview Tabs");
02814 return TRUE;
02815 }
02816
02817 return FALSE;
02818 }
02819
02820 void LLMultiFloater::updateResizeLimits()
02821 {
02822
02823 S32 new_min_width = mOrigMinWidth;
02824 S32 new_min_height = mOrigMinHeight;
02825
02826 for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx)
02827 {
02828 LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(tab_idx);
02829 if (floaterp)
02830 {
02831 new_min_width = llmax(new_min_width, floaterp->getMinWidth() + LLPANEL_BORDER_WIDTH * 2);
02832 new_min_height = llmax(new_min_height, floaterp->getMinHeight() + LLFLOATER_HEADER_SIZE + TABCNTR_HEADER_HEIGHT);
02833 }
02834 }
02835 setResizeLimits(new_min_width, new_min_height);
02836
02837 S32 cur_height = getRect().getHeight();
02838 S32 new_width = llmax(getRect().getWidth(), new_min_width);
02839 S32 new_height = llmax(getRect().getHeight(), new_min_height);
02840
02841 if (isMinimized())
02842 {
02843 const LLRect& expanded = getExpandedRect();
02844 LLRect newrect;
02845 newrect.setLeftTopAndSize(expanded.mLeft, expanded.mTop, llmax(expanded.getWidth(), new_width), llmax(expanded.getHeight(), new_height));
02846 setExpandedRect(newrect);
02847 }
02848 else
02849 {
02850 reshape(new_width, new_height);
02851
02852
02853 translate(0, cur_height - getRect().getHeight());
02854
02855
02856
02857 gFloaterView->adjustToFitScreen(this, TRUE);
02858 }
02859 }
02860
02861
02862 LLXMLNodePtr LLFloater::getXML(bool save_children) const
02863 {
02864 LLXMLNodePtr node = LLPanel::getXML();
02865
02866 node->createChild("title", TRUE)->setStringValue(getTitle());
02867
02868 node->createChild("can_resize", TRUE)->setBoolValue(isResizable());
02869
02870 node->createChild("can_minimize", TRUE)->setBoolValue(isMinimizeable());
02871
02872 node->createChild("can_close", TRUE)->setBoolValue(isCloseable());
02873
02874 node->createChild("can_drag_on_left", TRUE)->setBoolValue(isDragOnLeft());
02875
02876 node->createChild("min_width", TRUE)->setIntValue(getMinWidth());
02877
02878 node->createChild("min_height", TRUE)->setIntValue(getMinHeight());
02879
02880 node->createChild("can_tear_off", TRUE)->setBoolValue(mCanTearOff);
02881
02882 return node;
02883 }
02884
02885
02886 LLView* LLFloater::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
02887 {
02888 LLString name("floater");
02889 node->getAttributeString("name", name);
02890
02891 LLFloater *floaterp = new LLFloater(name);
02892
02893 LLString filename;
02894 node->getAttributeString("filename", filename);
02895
02896 if (filename.empty())
02897 {
02898
02899 floaterp->initFloaterXML(node, parent, factory);
02900 }
02901 else
02902 {
02903
02904 factory->buildFloater(floaterp, filename);
02905 }
02906
02907 return floaterp;
02908 }
02909
02910 void LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory, BOOL open)
02911 {
02912 LLString name(getName());
02913 LLString title(getTitle());
02914 LLString short_title(getShortTitle());
02915 LLString rect_control("");
02916 BOOL resizable = isResizable();
02917 S32 min_width = getMinWidth();
02918 S32 min_height = getMinHeight();
02919 BOOL drag_on_left = isDragOnLeft();
02920 BOOL minimizable = isMinimizeable();
02921 BOOL close_btn = isCloseable();
02922 LLRect rect;
02923
02924 node->getAttributeString("name", name);
02925 node->getAttributeString("title", title);
02926 node->getAttributeString("short_title", short_title);
02927 node->getAttributeString("rect_control", rect_control);
02928 node->getAttributeBOOL("can_resize", resizable);
02929 node->getAttributeBOOL("can_minimize", minimizable);
02930 node->getAttributeBOOL("can_close", close_btn);
02931 node->getAttributeBOOL("can_drag_on_left", drag_on_left);
02932 node->getAttributeS32("min_width", min_width);
02933 node->getAttributeS32("min_height", min_height);
02934
02935 if (! rect_control.empty())
02936 {
02937 setRectControl(rect_control);
02938 }
02939
02940 createRect(node, rect, parent, LLRect());
02941
02942 setRect(rect);
02943 setName(name);
02944
02945 initFloater(title,
02946 resizable,
02947 min_width,
02948 min_height,
02949 drag_on_left,
02950 minimizable,
02951 close_btn);
02952
02953 setShortTitle(short_title);
02954
02955 BOOL can_tear_off;
02956 if (node->getAttributeBOOL("can_tear_off", can_tear_off))
02957 {
02958 setCanTearOff(can_tear_off);
02959 }
02960
02961 initFromXML(node, parent);
02962
02963 LLMultiFloater* last_host = LLFloater::getFloaterHost();
02964 if (node->hasName("multi_floater"))
02965 {
02966 LLFloater::setFloaterHost((LLMultiFloater*) this);
02967 }
02968
02969 initChildrenXML(node, factory);
02970
02971 if (node->hasName("multi_floater"))
02972 {
02973 LLFloater::setFloaterHost(last_host);
02974 }
02975
02976 BOOL result = postBuild();
02977
02978 if (!result)
02979 {
02980 llerrs << "Failed to construct floater " << name << llendl;
02981 }
02982
02983 applyRectControl();
02984 if (open)
02985 {
02986 this->open();
02987 }
02988
02989 moveResizeHandlesToFront();
02990 }