aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llui/llfloater.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--linden/indra/llui/llfloater.cpp265
1 files changed, 157 insertions, 108 deletions
diff --git a/linden/indra/llui/llfloater.cpp b/linden/indra/llui/llfloater.cpp
index bc5f197..02a410e 100644
--- a/linden/indra/llui/llfloater.cpp
+++ b/linden/indra/llui/llfloater.cpp
@@ -506,26 +506,25 @@ void LLFloater::setVisible( BOOL visible )
506 } 506 }
507} 507}
508 508
509LLView* LLFloater::getRootMostFastFrameView() 509void LLFloater::open() /* Flawfinder: ignore */
510{ 510{
511 // trying to render a background floater in a fast frame, abort!!! 511 if (mSoundFlags != SILENT
512 //if (!isFrontmost()) 512 // don't play open sound for hosted (tabbed) windows
513 //{ 513 && !getHost()
514 // gViewerWindow->finishFastFrame(); 514 && !sHostp
515 //} 515 && (!getVisible() || isMinimized()))
516 516 {
517 return LLView::getRootMostFastFrameView(); 517 make_ui_sound("UISndWindowOpen");
518} 518 }
519 519
520void LLFloater::open()
521{
522 //RN: for now, we don't allow rehosting from one multifloater to another 520 //RN: for now, we don't allow rehosting from one multifloater to another
523 // just need to fix the bugs 521 // just need to fix the bugs
524 LLMultiFloater* hostp = getHost(); 522 LLMultiFloater* hostp = getHost();
525 if (sHostp != NULL && hostp == NULL) 523 if (sHostp != NULL && hostp == NULL)
526 { 524 {
527 // needs a host 525 // needs a host
528 sHostp->addFloater(this, TRUE); 526 // only select tabs if window they are hosted in is visible
527 sHostp->addFloater(this, sHostp->getVisible());
529 } 528 }
530 else if (hostp != NULL) 529 else if (hostp != NULL)
531 { 530 {
@@ -538,13 +537,7 @@ void LLFloater::open()
538 setVisibleAndFrontmost(mAutoFocus); 537 setVisibleAndFrontmost(mAutoFocus);
539 } 538 }
540 539
541 if (mSoundFlags != SILENT) 540 onOpen();
542 {
543 if (!getVisible() || isMinimized())
544 {
545 make_ui_sound("UISndWindowOpen");
546 }
547 }
548} 541}
549 542
550void LLFloater::close(bool app_quitting) 543void LLFloater::close(bool app_quitting)
@@ -562,6 +555,7 @@ void LLFloater::close(bool app_quitting)
562 555
563 if (mSoundFlags != SILENT 556 if (mSoundFlags != SILENT
564 && getVisible() 557 && getVisible()
558 && !getHost()
565 && !app_quitting) 559 && !app_quitting)
566 { 560 {
567 make_ui_sound("UISndWindowClose"); 561 make_ui_sound("UISndWindowClose");
@@ -689,7 +683,7 @@ const LLString& LLFloater::getTitle() const
689 683
690void LLFloater::translate(S32 x, S32 y) 684void LLFloater::translate(S32 x, S32 y)
691{ 685{
692 LLView::translate(x, y); 686 LLPanel::translate(x, y);
693 687
694 if (x != 0 || y != 0) 688 if (x != 0 || y != 0)
695 { 689 {
@@ -719,7 +713,7 @@ BOOL LLFloater::canSnapTo(LLView* other_view)
719 } 713 }
720 } 714 }
721 715
722 return LLView::canSnapTo(other_view); 716 return LLPanel::canSnapTo(other_view);
723} 717}
724 718
725void LLFloater::snappedTo(LLView* snap_view) 719void LLFloater::snappedTo(LLView* snap_view)
@@ -783,8 +777,6 @@ void LLFloater::setMinimized(BOOL minimize)
783 777
784 if (minimize) 778 if (minimize)
785 { 779 {
786 mMinimized = TRUE;
787
788 mPreviousRect = mRect; 780 mPreviousRect = mRect;
789 781
790 reshape( MINIMIZED_WIDTH, LLFLOATER_HEADER_SIZE, TRUE); 782 reshape( MINIMIZED_WIDTH, LLFLOATER_HEADER_SIZE, TRUE);
@@ -830,6 +822,8 @@ void LLFloater::setMinimized(BOOL minimize)
830 ++dependent_it; 822 ++dependent_it;
831 } 823 }
832 824
825 mMinimized = TRUE;
826
833 // Lose keyboard focus when minimized 827 // Lose keyboard focus when minimized
834 releaseFocus(); 828 releaseFocus();
835 } 829 }
@@ -1207,12 +1201,12 @@ void LLFloater::onClickTearOff(void *userdata)
1207 1201
1208 new_rect.setLeftTopAndSize(host_floater->getRect().mLeft + 5, host_floater->getRect().mTop - LLFLOATER_HEADER_SIZE - 5, self->mRect.getWidth(), self->mRect.getHeight()); 1202 new_rect.setLeftTopAndSize(host_floater->getRect().mLeft + 5, host_floater->getRect().mTop - LLFLOATER_HEADER_SIZE - 5, self->mRect.getWidth(), self->mRect.getHeight());
1209 1203
1210 self->open(); 1204 self->open(); /* Flawfinder: ignore */
1211 self->setRect(new_rect); 1205 self->setRect(new_rect);
1212 gFloaterView->adjustToFitScreen(self, FALSE); 1206 gFloaterView->adjustToFitScreen(self, FALSE);
1213 self->setCanDrag(TRUE); 1207 self->setCanDrag(TRUE);
1214 self->setCanResize(TRUE); 1208 // give focus to new window to keep continuity for the user
1215 self->setCanMinimize(TRUE); 1209 self->setFocus(TRUE);
1216 } 1210 }
1217 else //Attach to parent. 1211 else //Attach to parent.
1218 { 1212 {
@@ -1234,24 +1228,36 @@ void LLFloater::onClickEdit(void *userdata)
1234} 1228}
1235 1229
1236// static 1230// static
1237void LLFloater::closeByMenu( void* userdata ) 1231void LLFloater::closeFocusedFloater()
1238{ 1232{
1239 LLFloater* self = (LLFloater*) userdata; 1233 LLFloater* focused_floater = NULL;
1240 if (!self || self->getHost()) return;
1241 1234
1242 LLFloaterView* parent = (LLFloaterView*) self->getParent(); 1235 std::map<LLViewHandle, LLFloater*>::iterator iter;
1236 for(iter = sFloaterMap.begin(); iter != sFloaterMap.end(); ++iter)
1237 {
1238 focused_floater = iter->second;
1239 if (focused_floater->hasFocus())
1240 {
1241 break;
1242 }
1243 }
1243 1244
1244 // grab focus status before close just in case floater is deleted 1245 if (iter == sFloaterMap.end())
1245 BOOL has_focus = gFocusMgr.childHasKeyboardFocus(self); 1246 {
1246 self->close(); 1247 // nothing found, return
1248 return;
1249 }
1250
1251 focused_floater->close();
1247 1252
1248 // if this floater used to have focus and now nothing took focus 1253 // if nothing took focus after closing focused floater
1249 // give it to next floater (to allow closing multiple windows via keyboard in rapid succession) 1254 // give it to next floater (to allow closing multiple windows via keyboard in rapid succession)
1250 if (has_focus && gFocusMgr.getKeyboardFocus() == NULL) 1255 if (gFocusMgr.getKeyboardFocus() == NULL)
1251 { 1256 {
1252 parent->focusFrontFloater(); 1257 // HACK: use gFloaterView directly in case we are using Ctrl-W to close snapshot window
1258 // which sits in gSnapshotFloaterView, and needs to pass focus on to normal floater view
1259 gFloaterView->focusFrontFloater();
1253 } 1260 }
1254
1255} 1261}
1256 1262
1257 1263
@@ -1351,10 +1357,26 @@ void LLFloater::draw()
1351 focused_child->setVisible(TRUE); 1357 focused_child->setVisible(TRUE);
1352 } 1358 }
1353 drawChild(focused_child); 1359 drawChild(focused_child);
1360
1361 // update tearoff button for torn off floaters
1362 // when last host goes away
1363 if (mCanTearOff && !getHost())
1364 {
1365 LLFloater* old_host = gFloaterView->getFloaterByHandle(mLastHostHandle);
1366 if (!old_host)
1367 {
1368 setCanTearOff(FALSE);
1369 }
1370 }
1354 } 1371 }
1355} 1372}
1356 1373
1357// virtual 1374// virtual
1375void LLFloater::onOpen()
1376{
1377}
1378
1379// virtual
1358void LLFloater::onClose(bool app_quitting) 1380void LLFloater::onClose(bool app_quitting)
1359{ 1381{
1360 destroy(); 1382 destroy();
@@ -2018,23 +2040,52 @@ void LLFloaterView::focusFrontFloater()
2018 2040
2019void LLFloaterView::getMinimizePosition(S32 *left, S32 *bottom) 2041void LLFloaterView::getMinimizePosition(S32 *left, S32 *bottom)
2020{ 2042{
2021 // count the number of minimized children 2043 S32 col = 0;
2022 S32 count = 0; 2044 LLRect snap_rect_local = getSnapRect();
2023 for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) 2045 snap_rect_local.translate(-mRect.mLeft, -mRect.mBottom);
2024 { 2046 for(S32 row = snap_rect_local.mBottom;
2025 LLView* viewp = *child_it; 2047 row < snap_rect_local.getHeight() - LLFLOATER_HEADER_SIZE;
2026 LLFloater *floater = (LLFloater *)viewp; 2048 row += LLFLOATER_HEADER_SIZE ) //loop rows
2027 if (floater->isMinimized()) 2049 {
2028 { 2050 for(col = snap_rect_local.mLeft;
2029 count++; 2051 col < snap_rect_local.getWidth() - MINIMIZED_WIDTH;
2030 } 2052 col += MINIMIZED_WIDTH)
2053 {
2054 bool foundGap = TRUE;
2055 for(child_list_const_iter_t child_it = getChildList()->begin();
2056 child_it != getChildList()->end();
2057 ++child_it) //loop floaters
2058 {
2059 // Examine minimized children.
2060 LLFloater* floater = (LLFloater*)((LLView*)*child_it);
2061 if(floater->isMinimized())
2062 {
2063 LLRect r = floater->getRect();
2064 if((r.mBottom < (row + LLFLOATER_HEADER_SIZE))
2065 && (r.mBottom > (row - LLFLOATER_HEADER_SIZE))
2066 && (r.mLeft < (col + MINIMIZED_WIDTH))
2067 && (r.mLeft > (col - MINIMIZED_WIDTH)))
2068 {
2069 // needs the check for off grid. can't drag,
2070 // but window resize makes them off
2071 foundGap = FALSE;
2072 break;
2073 }
2074 }
2075 } //done floaters
2076 if(foundGap)
2077 {
2078 *left = col;
2079 *bottom = row;
2080 return; //done
2081 }
2082 } //done this col
2031 } 2083 }
2032 2084
2033 // space over for that many and up if necessary 2085 // crude - stack'em all at 0,0 when screen is full of minimized
2034 S32 tiles_per_row = mRect.getWidth() / MINIMIZED_WIDTH; 2086 // floaters.
2035 2087 *left = snap_rect_local.mLeft;
2036 *left = (count % tiles_per_row) * MINIMIZED_WIDTH; 2088 *bottom = snap_rect_local.mBottom;
2037 *bottom = (count / tiles_per_row) * LLFLOATER_HEADER_SIZE;
2038} 2089}
2039 2090
2040 2091
@@ -2211,7 +2262,7 @@ LLFloater *LLFloaterView::getFrontmost()
2211 for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) 2262 for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
2212 { 2263 {
2213 LLView* viewp = *child_it; 2264 LLView* viewp = *child_it;
2214 if ( viewp->getVisible() ) 2265 if ( viewp->getVisible() && !viewp->isDead())
2215 { 2266 {
2216 return (LLFloater *)viewp; 2267 return (LLFloater *)viewp;
2217 } 2268 }
@@ -2423,31 +2474,11 @@ LLString LLMultiFloater::getWidgetTag() const
2423 return LL_MULTI_FLOATER_TAG; 2474 return LL_MULTI_FLOATER_TAG;
2424} 2475}
2425 2476
2426void LLMultiFloater::init(const LLString& title, BOOL resizable, 2477void LLMultiFloater::open() /* Flawfinder: ignore */
2427 S32 min_width, S32 min_height, BOOL drag_on_left,
2428 BOOL minimizable, BOOL close_btn)
2429{
2430 LLFloater::init(title, resizable, min_width, min_height, drag_on_left, minimizable, close_btn);
2431
2432 /*mTabContainer = new LLTabContainer("Preview Tabs",
2433 LLRect(LLPANEL_BORDER_WIDTH, mRect.getHeight() - LLFLOATER_HEADER_SIZE, mRect.getWidth() - LLPANEL_BORDER_WIDTH, 0),
2434 mTabPos,
2435 NULL,
2436 NULL);
2437 mTabContainer->setFollowsAll();
2438 if (mResizable && mTabPos == LLTabContainerCommon::BOTTOM)
2439 {
2440 mTabContainer->setRightTabBtnOffset(RESIZE_HANDLE_WIDTH);
2441 }
2442
2443 addChild(mTabContainer);*/
2444}
2445
2446void LLMultiFloater::open()
2447{ 2478{
2448 if (mTabContainer->getTabCount() > 0) 2479 if (mTabContainer->getTabCount() > 0)
2449 { 2480 {
2450 LLFloater::open(); 2481 LLFloater::open(); /* Flawfinder: ignore */
2451 } 2482 }
2452 else 2483 else
2453 { 2484 {
@@ -2519,16 +2550,9 @@ void LLMultiFloater::growToFit(LLFloater* floaterp, S32 width, S32 height)
2519 // store new width and height with this floater so that it will keep its size when detached 2550 // store new width and height with this floater so that it will keep its size when detached
2520 found_data_it->second.mWidth = width; 2551 found_data_it->second.mWidth = width;
2521 found_data_it->second.mHeight = height; 2552 found_data_it->second.mHeight = height;
2522
2523 S32 cur_height = mRect.getHeight();
2524 reshape(llmax(mRect.getWidth(), width + LLPANEL_BORDER_WIDTH * 2), llmax(mRect.getHeight(), height + LLFLOATER_HEADER_SIZE + TABCNTR_HEADER_HEIGHT + (LLPANEL_BORDER_WIDTH * 2)));
2525
2526 // make sure upper left corner doesn't move
2527 translate(0, mRect.getHeight() - cur_height);
2528
2529 // Try to keep whole view onscreen, don't allow partial offscreen.
2530 gFloaterView->adjustToFitScreen(this, FALSE);
2531 } 2553 }
2554
2555 resizeToContents();
2532} 2556}
2533 2557
2534/** 2558/**
@@ -2597,8 +2621,6 @@ void LLMultiFloater::addFloater(LLFloater* floaterp, BOOL select_added_floater,
2597 if ( select_added_floater ) 2621 if ( select_added_floater )
2598 { 2622 {
2599 mTabContainer->selectLastTab(); 2623 mTabContainer->selectLastTab();
2600 // explicitly call tabopen to load preview assets, etc.
2601 tabOpen((LLFloater*)mTabContainer->getCurrentPanel(), true);
2602 } 2624 }
2603 2625
2604 floaterp->setHost(this); 2626 floaterp->setHost(this);
@@ -2671,24 +2693,7 @@ void LLMultiFloater::removeFloater(LLFloater* floaterp)
2671 2693
2672 if (mAutoResize) 2694 if (mAutoResize)
2673 { 2695 {
2674 floater_data_map_t::iterator floater_it; 2696 resizeToContents();
2675 S32 new_width = 0;
2676 S32 new_height = 0;
2677 for (floater_it = mFloaterDataMap.begin(); floater_it != mFloaterDataMap.end(); ++floater_it)
2678 {
2679 new_width = llmax(new_width, floater_it->second.mWidth + LLPANEL_BORDER_WIDTH * 2);
2680 new_height = llmax(new_height, floater_it->second.mHeight + LLFLOATER_HEADER_SIZE + TABCNTR_HEADER_HEIGHT);
2681 }
2682
2683 S32 cur_height = mRect.getHeight();
2684
2685 reshape(new_width, new_height);
2686
2687 // make sure upper left corner doesn't move
2688 translate(0, cur_height - new_height);
2689
2690 // Try to keep whole view onscreen, don't allow partial offscreen.
2691 gFloaterView->adjustToFitScreen(this, FALSE);
2692 } 2697 }
2693 2698
2694 tabOpen((LLFloater*)mTabContainer->getCurrentPanel(), false); 2699 tabOpen((LLFloater*)mTabContainer->getCurrentPanel(), false);
@@ -2721,6 +2726,13 @@ void LLMultiFloater::setVisible(BOOL visible)
2721 { 2726 {
2722 cur_floaterp->setVisible(visible); 2727 cur_floaterp->setVisible(visible);
2723 } 2728 }
2729
2730 // if no tab selected, and we're being shown,
2731 // select last tab to be added
2732 if (visible && !cur_floaterp)
2733 {
2734 mTabContainer->selectLastTab();
2735 }
2724 } 2736 }
2725} 2737}
2726 2738
@@ -2823,6 +2835,43 @@ BOOL LLMultiFloater::postBuild()
2823 return FALSE; 2835 return FALSE;
2824} 2836}
2825 2837
2838void LLMultiFloater::resizeToContents()
2839{
2840 // we're already in the middle of a reshape, don't interrupt it
2841 floater_data_map_t::iterator floater_it;
2842 S32 new_width = 0;
2843 S32 new_height = 0;
2844 for (floater_it = mFloaterDataMap.begin(); floater_it != mFloaterDataMap.end(); ++floater_it)
2845 {
2846 new_width = llmax(new_width, floater_it->second.mWidth + LLPANEL_BORDER_WIDTH * 2);
2847 new_height = llmax(new_height, floater_it->second.mHeight + LLFLOATER_HEADER_SIZE + TABCNTR_HEADER_HEIGHT);
2848 }
2849
2850 S32 new_min_width = 0;
2851 S32 new_min_height = 0;
2852 S32 tab_idx;
2853 for (tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx)
2854 {
2855 LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(tab_idx);
2856 if (floaterp)
2857 {
2858 new_min_width = llmax(new_min_width, floaterp->getMinWidth() + LLPANEL_BORDER_WIDTH * 2);
2859 new_min_height = llmax(new_min_height, floaterp->getMinHeight() + LLFLOATER_HEADER_SIZE + TABCNTR_HEADER_HEIGHT);
2860 }
2861 }
2862 setResizeLimits(new_min_width, new_min_height);
2863
2864 S32 cur_height = mRect.getHeight();
2865
2866 reshape(new_width, new_height);
2867
2868 // make sure upper left corner doesn't move
2869 translate(0, cur_height - new_height);
2870
2871 // Try to keep whole view onscreen, don't allow partial offscreen.
2872 gFloaterView->adjustToFitScreen(this, FALSE);
2873}
2874
2826// virtual 2875// virtual
2827LLXMLNodePtr LLFloater::getXML(bool save_children) const 2876LLXMLNodePtr LLFloater::getXML(bool save_children) const
2828{ 2877{
@@ -2872,7 +2921,7 @@ LLView* LLFloater::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *f
2872 return floaterp; 2921 return floaterp;
2873} 2922}
2874 2923
2875void LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory, BOOL open) 2924void LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory, BOOL open) /* Flawfinder: ignore */
2876{ 2925{
2877 LLString name(getName()); 2926 LLString name(getName());
2878 LLString title(getTitle()); 2927 LLString title(getTitle());
@@ -2946,8 +2995,8 @@ void LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactor
2946 } 2995 }
2947 2996
2948 applyRectControl(); 2997 applyRectControl();
2949 if (open) 2998 if (open) /* Flawfinder: ignore */
2950 { 2999 {
2951 this->open(); 3000 this->open(); /* Flawfinder: ignore */
2952 } 3001 }
2953} 3002}