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