aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llui/llpanel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/llui/llpanel.cpp')
-rw-r--r--linden/indra/llui/llpanel.cpp659
1 files changed, 611 insertions, 48 deletions
diff --git a/linden/indra/llui/llpanel.cpp b/linden/indra/llui/llpanel.cpp
index dfa3f8a..91a327b 100644
--- a/linden/indra/llui/llpanel.cpp
+++ b/linden/indra/llui/llpanel.cpp
@@ -51,9 +51,18 @@
51#include "llviewborder.h" 51#include "llviewborder.h"
52#include "llbutton.h" 52#include "llbutton.h"
53 53
54// LLLayoutStack
55#include "llgl.h"
56#include "llglheaders.h"
57#include "llresizebar.h"
58#include "llcriticaldamp.h"
59
54LLPanel::panel_map_t LLPanel::sPanelMap; 60LLPanel::panel_map_t LLPanel::sPanelMap;
55LLPanel::alert_queue_t LLPanel::sAlertQueue; 61LLPanel::alert_queue_t LLPanel::sAlertQueue;
56 62
63const S32 RESIZE_BAR_OVERLAP = 1;
64const S32 PANEL_STACK_GAP = RESIZE_BAR_HEIGHT;
65
57void LLPanel::init() 66void LLPanel::init()
58{ 67{
59 // mRectControl 68 // mRectControl
@@ -119,13 +128,16 @@ void LLPanel::addBorder(LLViewBorder::EBevel border_bevel,
119 addChild( mBorder ); 128 addChild( mBorder );
120} 129}
121 130
131void LLPanel::removeBorder()
132{
133 delete mBorder;
134 mBorder = NULL;
135}
136
122 137
123LLPanel::~LLPanel() 138LLPanel::~LLPanel()
124{ 139{
125 if( !mRectControl.empty() ) 140 storeRectControl();
126 {
127 LLUI::sConfigGroup->setRect( mRectControl, mRect );
128 }
129 sPanelMap.erase(mViewHandle); 141 sPanelMap.erase(mViewHandle);
130} 142}
131 143
@@ -179,44 +191,41 @@ void LLPanel::setCtrlsEnabled( BOOL b )
179 191
180void LLPanel::draw() 192void LLPanel::draw()
181{ 193{
182 if( getVisible() ) 194 // draw background
195 if( mBgVisible )
183 { 196 {
184 // draw background 197 //RN: I don't see the point of this
185 if( mBgVisible ) 198 S32 left = 0;//LLPANEL_BORDER_WIDTH;
186 { 199 S32 top = mRect.getHeight();// - LLPANEL_BORDER_WIDTH;
187 //RN: I don't see the point of this 200 S32 right = mRect.getWidth();// - LLPANEL_BORDER_WIDTH;
188 S32 left = 0;//LLPANEL_BORDER_WIDTH; 201 S32 bottom = 0;//LLPANEL_BORDER_WIDTH;
189 S32 top = mRect.getHeight();// - LLPANEL_BORDER_WIDTH;
190 S32 right = mRect.getWidth();// - LLPANEL_BORDER_WIDTH;
191 S32 bottom = 0;//LLPANEL_BORDER_WIDTH;
192 202
193 if (mBgOpaque ) 203 if (mBgOpaque )
194 { 204 {
195 gl_rect_2d( left, top, right, bottom, mBgColorOpaque ); 205 gl_rect_2d( left, top, right, bottom, mBgColorOpaque );
196 }
197 else
198 {
199 gl_rect_2d( left, top, right, bottom, mBgColorAlpha );
200 }
201 } 206 }
202 207 else
203 if( mDefaultBtn)
204 { 208 {
205 if (gFocusMgr.childHasKeyboardFocus( this ) && mDefaultBtn->getEnabled()) 209 gl_rect_2d( left, top, right, bottom, mBgColorAlpha );
206 {
207 LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus();
208 BOOL focus_is_child_button = focus_ctrl->getWidgetType() == WIDGET_TYPE_BUTTON && static_cast<LLButton *>(focus_ctrl)->getCommitOnReturn();
209 // only enable default button when current focus is not a return-capturing button
210 mDefaultBtn->setBorderEnabled(!focus_is_child_button);
211 }
212 else
213 {
214 mDefaultBtn->setBorderEnabled(FALSE);
215 }
216 } 210 }
211 }
217 212
218 LLView::draw(); 213 if( mDefaultBtn)
214 {
215 if (gFocusMgr.childHasKeyboardFocus( this ) && mDefaultBtn->getEnabled())
216 {
217 LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus();
218 BOOL focus_is_child_button = focus_ctrl->getWidgetType() == WIDGET_TYPE_BUTTON && static_cast<LLButton *>(focus_ctrl)->getCommitOnReturn();
219 // only enable default button when current focus is not a return-capturing button
220 mDefaultBtn->setBorderEnabled(!focus_is_child_button);
221 }
222 else
223 {
224 mDefaultBtn->setBorderEnabled(FALSE);
225 }
219 } 226 }
227
228 LLView::draw();
220} 229}
221 230
222void LLPanel::refresh() 231void LLPanel::refresh()
@@ -572,7 +581,7 @@ LLXMLNodePtr LLPanel::getXML(bool save_children) const
572 return node; 581 return node;
573} 582}
574 583
575LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parentp, LLUICtrlFactory *factory) 584LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parent, LLUICtrlFactory *factory)
576{ 585{
577 LLString name("panel"); 586 LLString name("panel");
578 node->getAttributeString("name", name); 587 node->getAttributeString("name", name);
@@ -581,11 +590,21 @@ LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parentp, LLUICtrlFactory *fa
581 // Fall back on a default panel, if there was no special factory. 590 // Fall back on a default panel, if there was no special factory.
582 if (!panelp) 591 if (!panelp)
583 { 592 {
584 panelp = new LLPanel("tab panel"); 593 LLRect rect;
594 createRect(node, rect, parent, LLRect());
595 panelp = new LLPanel(name, rect);
596 panelp->initPanelXML(node, parent, factory);
597 // preserve panel's width and height, but override the location
598 const LLRect& panelrect = panelp->getRect();
599 S32 w = panelrect.getWidth();
600 S32 h = panelrect.getHeight();
601 rect.setLeftTopAndSize(rect.mLeft, rect.mTop, w, h);
602 panelp->setRect(rect);
603 }
604 else
605 {
606 panelp->initPanelXML(node, parent, factory);
585 } 607 }
586
587 panelp->initPanelXML(node, parentp, factory);
588
589 return panelp; 608 return panelp;
590} 609}
591 610
@@ -597,11 +616,7 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *f
597 616
598 setPanelParameters(node, parent); 617 setPanelParameters(node, parent);
599 618
600 LLXMLNodePtr child; 619 initChildrenXML(node, factory);
601 for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
602 {
603 factory->createWidget(this, child);
604 }
605 620
606 LLString xml_filename; 621 LLString xml_filename;
607 node->getAttributeString("filename", xml_filename); 622 node->getAttributeString("filename", xml_filename);
@@ -610,8 +625,16 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *f
610 625
611 if (!xml_filename.empty()) 626 if (!xml_filename.empty())
612 { 627 {
628 // Preserve postion of embedded panel but allow panel to dictate width/height
629 LLRect rect(getRect());
613 didPost = factory->buildPanel(this, xml_filename, NULL); 630 didPost = factory->buildPanel(this, xml_filename, NULL);
614 } else { 631 S32 w = getRect().getWidth();
632 S32 h = getRect().getHeight();
633 rect.setLeftTopAndSize(rect.mLeft, rect.mTop, w, h);
634 setRect(rect);
635 }
636 else
637 {
615 didPost = FALSE; 638 didPost = FALSE;
616 } 639 }
617 640
@@ -624,10 +647,32 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *f
624 return didPost; 647 return didPost;
625} 648}
626 649
627void LLPanel::setPanelParameters(LLXMLNodePtr node, LLView* parentp) 650void LLPanel::initChildrenXML(LLXMLNodePtr node, LLUICtrlFactory* factory)
651{
652 LLXMLNodePtr child;
653 for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
654 {
655 // look for string declarations for programmatic text
656 if (child->hasName("string"))
657 {
658 LLString string_name;
659 child->getAttributeString("name", string_name);
660 if (!string_name.empty())
661 {
662 mUIStrings[string_name] = LLUIString(child->getTextContents());
663 }
664 }
665 else
666 {
667 factory->createWidget(this, child);
668 }
669 }
670}
671
672void LLPanel::setPanelParameters(LLXMLNodePtr node, LLView* parent)
628{ 673{
629 /////// Rect, follows, tool_tip, enabled, visible attributes /////// 674 /////// Rect, follows, tool_tip, enabled, visible attributes ///////
630 initFromXML(node, parentp); 675 initFromXML(node, parent);
631 676
632 /////// Border attributes /////// 677 /////// Border attributes ///////
633 BOOL border = FALSE; 678 BOOL border = FALSE;
@@ -652,6 +697,10 @@ void LLPanel::setPanelParameters(LLXMLNodePtr node, LLView* parentp)
652 697
653 addBorder(bevel_style, border_style, border_thickness); 698 addBorder(bevel_style, border_style, border_thickness);
654 } 699 }
700 else
701 {
702 removeBorder();
703 }
655 704
656 /////// Background attributes /////// 705 /////// Background attributes ///////
657 BOOL background_visible = FALSE; 706 BOOL background_visible = FALSE;
@@ -676,6 +725,30 @@ void LLPanel::setPanelParameters(LLXMLNodePtr node, LLView* parentp)
676 setLabel(label); 725 setLabel(label);
677} 726}
678 727
728LLString LLPanel::getFormattedUIString(const LLString& name, const LLString::format_map_t& args) const
729{
730 ui_string_map_t::const_iterator found_it = mUIStrings.find(name);
731 if (found_it != mUIStrings.end())
732 {
733 // make a copy as format works in place
734 LLUIString formatted_string = found_it->second;
735 formatted_string.setArgList(args);
736 return formatted_string.getString();
737 }
738 return LLString::null;
739}
740
741LLUIString LLPanel::getUIString(const LLString& name) const
742{
743 ui_string_map_t::const_iterator found_it = mUIStrings.find(name);
744 if (found_it != mUIStrings.end())
745 {
746 return found_it->second;
747 }
748 return LLUIString(LLString::null);
749}
750
751
679void LLPanel::childSetVisible(const LLString& id, bool visible) 752void LLPanel::childSetVisible(const LLString& id, bool visible)
680{ 753{
681 LLView* child = getChildByName(id, true); 754 LLView* child = getChildByName(id, true);
@@ -1065,3 +1138,493 @@ void LLPanel::childDisplayNotFound()
1065 LLAlertDialog::showXml("FloaterNotFound", args); 1138 LLAlertDialog::showXml("FloaterNotFound", args);
1066} 1139}
1067 1140
1141void LLPanel::storeRectControl()
1142{
1143 if( !mRectControl.empty() )
1144 {
1145 LLUI::sConfigGroup->setRect( mRectControl, mRect );
1146 }
1147}
1148
1149
1150//
1151// LLLayoutStack
1152//
1153struct LLLayoutStack::LLEmbeddedPanel
1154{
1155 LLEmbeddedPanel(LLPanel* panelp, eLayoutOrientation orientation, S32 min_width, S32 min_height, BOOL auto_resize) :
1156 mPanel(panelp),
1157 mMinWidth(min_width),
1158 mMinHeight(min_height),
1159 mAutoResize(auto_resize),
1160 mOrientation(orientation),
1161 mVisibleAmt(1.f) // default to fully visible
1162 {
1163 LLResizeBar::Side side = (orientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM;
1164 LLRect resize_bar_rect = panelp->getRect();
1165
1166 S32 min_dim;
1167 if (orientation == HORIZONTAL)
1168 {
1169 min_dim = mMinHeight;
1170 }
1171 else
1172 {
1173 min_dim = mMinWidth;
1174 }
1175 mResizeBar = new LLResizeBar("resizer", mPanel, LLRect(), min_dim, S32_MAX, side);
1176 mResizeBar->setEnableSnapping(FALSE);
1177 // panels initialized as hidden should not start out partially visible
1178 if (!mPanel->getVisible())
1179 {
1180 mVisibleAmt = 0.f;
1181 }
1182 }
1183
1184 LLPanel* mPanel;
1185 S32 mMinWidth;
1186 S32 mMinHeight;
1187 BOOL mAutoResize;
1188 LLResizeBar* mResizeBar;
1189 eLayoutOrientation mOrientation;
1190 F32 mVisibleAmt;
1191};
1192
1193LLLayoutStack::LLLayoutStack(eLayoutOrientation orientation) :
1194 mOrientation(orientation),
1195 mMinWidth(0),
1196 mMinHeight(0)
1197{
1198}
1199
1200LLLayoutStack::~LLLayoutStack()
1201{
1202}
1203
1204void LLLayoutStack::draw()
1205{
1206 updateLayout();
1207 {
1208 // clip if outside nominal bounds
1209 LLLocalClipRect clip(getLocalRect(), mRect.getWidth() > mMinWidth || mRect.getHeight() > mMinHeight);
1210 e_panel_list_t::iterator panel_it;
1211 for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
1212 {
1213 LLRect clip_rect = (*panel_it)->mPanel->getRect();
1214 // scale clipping rectangle by visible amount
1215 if (mOrientation == HORIZONTAL)
1216 {
1217 clip_rect.mRight = clip_rect.mLeft + llround(clip_rect.getWidth() * (*panel_it)->mVisibleAmt);
1218 }
1219 else
1220 {
1221 clip_rect.mBottom = clip_rect.mTop - llround(clip_rect.getHeight() * (*panel_it)->mVisibleAmt);
1222 }
1223 LLLocalClipRect clip(clip_rect, (*panel_it)->mVisibleAmt < 1.f);
1224 // only force drawing invisible children if visible amount is non-zero
1225 drawChild((*panel_it)->mPanel, 0, 0, (*panel_it)->mVisibleAmt > 0.f);
1226 }
1227 }
1228}
1229
1230void LLLayoutStack::removeCtrl(LLUICtrl* ctrl)
1231{
1232 LLEmbeddedPanel* embedded_panelp = findEmbeddedPanel((LLPanel*)ctrl);
1233
1234 if (embedded_panelp)
1235 {
1236 mPanels.erase(std::find(mPanels.begin(), mPanels.end(), embedded_panelp));
1237 delete embedded_panelp;
1238 }
1239
1240 calcMinExtents();
1241
1242 LLView::removeCtrl(ctrl);
1243}
1244
1245void LLLayoutStack::reshape(S32 width, S32 height, BOOL called_from_parent)
1246{
1247 LLView::reshape(width, height, called_from_parent);
1248 //updateLayout();
1249}
1250
1251LLXMLNodePtr LLLayoutStack::getXML(bool save_children) const
1252{
1253 LLXMLNodePtr node = LLView::getXML();
1254 return node;
1255}
1256
1257//static
1258LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
1259{
1260 LLString orientation_string("vertical");
1261 node->getAttributeString("orientation", orientation_string);
1262
1263 eLayoutOrientation orientation = VERTICAL;
1264
1265 if (orientation_string == "horizontal")
1266 {
1267 orientation = HORIZONTAL;
1268 }
1269 else if (orientation_string == "vertical")
1270 {
1271 orientation = VERTICAL;
1272 }
1273 else
1274 {
1275 llwarns << "Unknown orientation " << orientation_string << ", using vertical" << llendl;
1276 }
1277
1278 LLLayoutStack* layout_stackp = new LLLayoutStack(orientation);
1279
1280 layout_stackp->initFromXML(node, parent);
1281
1282 LLXMLNodePtr child;
1283 for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
1284 {
1285 if (child->hasName("layout_panel"))
1286 {
1287 S32 min_width = 0;
1288 S32 min_height = 0;
1289 BOOL auto_resize = TRUE;
1290
1291 child->getAttributeS32("min_width", min_width);
1292 child->getAttributeS32("min_height", min_height);
1293 child->getAttributeBOOL("auto_resize", auto_resize);
1294
1295 LLPanel* panelp = (LLPanel*)LLPanel::fromXML(child, layout_stackp, factory);
1296 panelp->setFollowsNone();
1297 if (panelp)
1298 {
1299 layout_stackp->addPanel(panelp, min_width, min_height, auto_resize);
1300 }
1301 }
1302 }
1303
1304 return layout_stackp;
1305}
1306
1307S32 LLLayoutStack::getMinWidth()
1308{
1309 return mMinWidth;
1310}
1311
1312S32 LLLayoutStack::getMinHeight()
1313{
1314 return mMinHeight;
1315}
1316
1317void LLLayoutStack::addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, S32 index)
1318{
1319 LLEmbeddedPanel* embedded_panel = new LLEmbeddedPanel(panel, mOrientation, min_width, min_height, auto_resize);
1320
1321 mPanels.insert(mPanels.begin() + llclamp(index, 0, (S32)mPanels.size()), embedded_panel);
1322 addChild(panel);
1323 addChild(embedded_panel->mResizeBar);
1324
1325 // bring all resize bars to the front so that they are clickable even over the panels
1326 // with a bit of overlap
1327 for (e_panel_list_t::iterator panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
1328 {
1329 e_panel_list_t::iterator next_it = panel_it;
1330 ++next_it;
1331
1332 LLResizeBar* resize_barp = (*panel_it)->mResizeBar;
1333 sendChildToFront(resize_barp);
1334 // last resize bar is disabled, since its not between any two panels
1335 if ( next_it == mPanels.end() )
1336 {
1337 resize_barp->setEnabled(FALSE);
1338 }
1339 else
1340 {
1341 resize_barp->setEnabled(TRUE);
1342 }
1343 }
1344
1345 //updateLayout();
1346}
1347
1348void LLLayoutStack::removePanel(LLPanel* panel)
1349{
1350 removeChild(panel);
1351 //updateLayout();
1352}
1353
1354void LLLayoutStack::updateLayout(BOOL force_resize)
1355{
1356 calcMinExtents();
1357
1358 // calculate current extents
1359 S32 cur_width = 0;
1360 S32 cur_height = 0;
1361
1362 const F32 ANIM_OPEN_TIME = 0.02f;
1363 const F32 ANIM_CLOSE_TIME = 0.02f;
1364
1365 e_panel_list_t::iterator panel_it;
1366 for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
1367 {
1368 LLPanel* panelp = (*panel_it)->mPanel;
1369 if (panelp->getVisible())
1370 {
1371 (*panel_it)->mVisibleAmt = lerp((*panel_it)->mVisibleAmt, 1.f, LLCriticalDamp::getInterpolant(ANIM_OPEN_TIME));
1372 if ((*panel_it)->mVisibleAmt > 0.99f)
1373 {
1374 (*panel_it)->mVisibleAmt = 1.f;
1375 }
1376 }
1377 else // not visible
1378 {
1379 (*panel_it)->mVisibleAmt = lerp((*panel_it)->mVisibleAmt, 0.f, LLCriticalDamp::getInterpolant(ANIM_CLOSE_TIME));
1380 if ((*panel_it)->mVisibleAmt < 0.001f)
1381 {
1382 (*panel_it)->mVisibleAmt = 0.f;
1383 }
1384 }
1385 if (mOrientation == HORIZONTAL)
1386 {
1387 // all panels get expanded to max of all the minimum dimensions
1388 cur_height = llmax(mMinHeight, panelp->getRect().getHeight());
1389 cur_width += llround(panelp->getRect().getWidth() * (*panel_it)->mVisibleAmt);
1390 if (panel_it != mPanels.end())
1391 {
1392 cur_width += PANEL_STACK_GAP;
1393 }
1394 }
1395 else //VERTICAL
1396 {
1397 cur_width = llmax(mMinWidth, panelp->getRect().getWidth());
1398 cur_height += llround(panelp->getRect().getHeight() * (*panel_it)->mVisibleAmt);
1399 if (panel_it != mPanels.end())
1400 {
1401 cur_height += PANEL_STACK_GAP;
1402 }
1403 }
1404 }
1405
1406 S32 num_resizable_panels = 0;
1407 S32 shrink_headroom_available = 0;
1408 S32 shrink_headroom_total = 0;
1409 for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
1410 {
1411 // panels that are not fully visible do not count towards shrink headroom
1412 if ((*panel_it)->mVisibleAmt < 1.f)
1413 continue;
1414 // if currently resizing a panel or the panel is flagged as not automatically resizing
1415 // only track total available headroom, but don't use it for automatic resize logic
1416 if ((*panel_it)->mResizeBar->hasMouseCapture() || (!(*panel_it)->mAutoResize && !force_resize))
1417 {
1418 if (mOrientation == HORIZONTAL)
1419 {
1420 shrink_headroom_total += (*panel_it)->mPanel->getRect().getWidth() - (*panel_it)->mMinWidth;
1421 }
1422 else //VERTICAL
1423 {
1424 shrink_headroom_total += (*panel_it)->mPanel->getRect().getHeight() - (*panel_it)->mMinHeight;
1425 }
1426 }
1427 else
1428 {
1429 num_resizable_panels++;
1430 if (mOrientation == HORIZONTAL)
1431 {
1432 shrink_headroom_available += (*panel_it)->mPanel->getRect().getWidth() - (*panel_it)->mMinWidth;
1433 shrink_headroom_total += (*panel_it)->mPanel->getRect().getWidth() - (*panel_it)->mMinWidth;
1434 }
1435 else //VERTICAL
1436 {
1437 shrink_headroom_available += (*panel_it)->mPanel->getRect().getHeight() - (*panel_it)->mMinHeight;
1438 shrink_headroom_total += (*panel_it)->mPanel->getRect().getHeight() - (*panel_it)->mMinHeight;
1439 }
1440 }
1441 }
1442
1443 // positive means panels need to grow, negative means shrink
1444 S32 pixels_to_distribute;
1445 if (mOrientation == HORIZONTAL)
1446 {
1447 pixels_to_distribute = mRect.getWidth() - cur_width;
1448 }
1449 else //VERTICAL
1450 {
1451 pixels_to_distribute = mRect.getHeight() - cur_height;
1452 }
1453
1454 S32 cur_x = 0;
1455 S32 cur_y = mRect.getHeight();
1456
1457 for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
1458 {
1459 LLPanel* panelp = (*panel_it)->mPanel;
1460
1461 S32 cur_width = panelp->getRect().getWidth();
1462 S32 cur_height = panelp->getRect().getHeight();
1463 S32 new_width = llmax((*panel_it)->mMinWidth, cur_width);
1464 S32 new_height = llmax((*panel_it)->mMinHeight, cur_height);
1465
1466 S32 delta_size = 0;
1467
1468 // if panel can automatically resize (not animating, and resize flag set)...
1469 if ((*panel_it)->mVisibleAmt == 1.f && (force_resize || (*panel_it)->mAutoResize) && !(*panel_it)->mResizeBar->hasMouseCapture())
1470 {
1471 if (mOrientation == HORIZONTAL)
1472 {
1473 // if we're shrinking
1474 if (pixels_to_distribute < 0)
1475 {
1476 // shrink proportionally to amount over minimum
1477 delta_size = llround((F32)pixels_to_distribute * (F32)(cur_width - (*panel_it)->mMinWidth) / (F32)shrink_headroom_available);
1478 }
1479 else
1480 {
1481 // grow all elements equally
1482 delta_size = llround((F32)pixels_to_distribute / (F32)num_resizable_panels);
1483 }
1484 new_width = llmax((*panel_it)->mMinWidth, panelp->getRect().getWidth() + delta_size);
1485 }
1486 else
1487 {
1488 new_width = llmax(mMinWidth, mRect.getWidth());
1489 }
1490
1491 if (mOrientation == VERTICAL)
1492 {
1493 if (pixels_to_distribute < 0)
1494 {
1495 // shrink proportionally to amount over minimum
1496 delta_size = llround((F32)pixels_to_distribute * (F32)(cur_height - (*panel_it)->mMinHeight) / (F32)shrink_headroom_available);
1497 }
1498 else
1499 {
1500 delta_size = llround((F32)pixels_to_distribute / (F32)num_resizable_panels);
1501 }
1502 new_height = llmax((*panel_it)->mMinHeight, panelp->getRect().getHeight() + delta_size);
1503 }
1504 else
1505 {
1506 new_height = llmax(mMinHeight, mRect.getHeight());
1507 }
1508 }
1509 else // don't resize
1510 {
1511 if (mOrientation == HORIZONTAL)
1512 {
1513 new_height = llmax(mMinHeight, mRect.getHeight());
1514 }
1515 else // VERTICAL
1516 {
1517 new_width = llmax(mMinWidth, mRect.getWidth());
1518 }
1519 }
1520
1521 // adjust running headroom count based on new sizes
1522 shrink_headroom_total += delta_size;
1523
1524 panelp->reshape(new_width, new_height);
1525 panelp->setOrigin(cur_x, cur_y - new_height);
1526
1527 LLRect panel_rect = panelp->getRect();
1528 LLRect resize_bar_rect = panel_rect;
1529 if (mOrientation == HORIZONTAL)
1530 {
1531 resize_bar_rect.mLeft = panel_rect.mRight - RESIZE_BAR_OVERLAP;
1532 resize_bar_rect.mRight = panel_rect.mRight + PANEL_STACK_GAP + RESIZE_BAR_OVERLAP;
1533 }
1534 else
1535 {
1536 resize_bar_rect.mTop = panel_rect.mBottom + RESIZE_BAR_OVERLAP;
1537 resize_bar_rect.mBottom = panel_rect.mBottom - PANEL_STACK_GAP - RESIZE_BAR_OVERLAP;
1538 }
1539 (*panel_it)->mResizeBar->setRect(resize_bar_rect);
1540
1541 if (mOrientation == HORIZONTAL)
1542 {
1543 cur_x += llround(new_width * (*panel_it)->mVisibleAmt) + PANEL_STACK_GAP;
1544 }
1545 else //VERTICAL
1546 {
1547 cur_y -= llround(new_height * (*panel_it)->mVisibleAmt) + PANEL_STACK_GAP;
1548 }
1549 }
1550
1551 // update resize bars with new limits
1552 LLResizeBar* last_resize_bar = NULL;
1553 for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
1554 {
1555 LLPanel* panelp = (*panel_it)->mPanel;
1556
1557 if (mOrientation == HORIZONTAL)
1558 {
1559 (*panel_it)->mResizeBar->setResizeLimits((*panel_it)->mMinWidth, (*panel_it)->mMinWidth + shrink_headroom_total);
1560 }
1561 else //VERTICAL
1562 {
1563 (*panel_it)->mResizeBar->setResizeLimits((*panel_it)->mMinHeight, (*panel_it)->mMinHeight + shrink_headroom_total);
1564 }
1565 // hide resize bars for invisible panels
1566 (*panel_it)->mResizeBar->setVisible(panelp->getVisible());
1567 if (panelp->getVisible())
1568 {
1569 last_resize_bar = (*panel_it)->mResizeBar;
1570 }
1571 }
1572
1573 // hide last resize bar as there is nothing past it
1574 if (last_resize_bar)
1575 {
1576 last_resize_bar->setVisible(FALSE);
1577 }
1578
1579 // not enough room to fit existing contents
1580 if (!force_resize &&
1581 ((cur_y != -PANEL_STACK_GAP) || (cur_x != mRect.getWidth() + PANEL_STACK_GAP)))
1582 {
1583 // do another layout pass with all stacked elements contributing
1584 // even those that don't usually resize
1585 llassert_always(force_resize == FALSE);
1586 updateLayout(TRUE);
1587 }
1588}
1589
1590LLLayoutStack::LLEmbeddedPanel* LLLayoutStack::findEmbeddedPanel(LLPanel* panelp)
1591{
1592 e_panel_list_t::iterator panel_it;
1593 for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
1594 {
1595 if ((*panel_it)->mPanel == panelp)
1596 {
1597 return *panel_it;
1598 }
1599 }
1600 return NULL;
1601}
1602
1603void LLLayoutStack::calcMinExtents()
1604{
1605 mMinWidth = 0;
1606 mMinHeight = 0;
1607
1608 e_panel_list_t::iterator panel_it;
1609 for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
1610 {
1611 if (mOrientation == HORIZONTAL)
1612 {
1613 mMinHeight = llmax(mMinHeight, (*panel_it)->mMinHeight);
1614 mMinWidth += (*panel_it)->mMinWidth;
1615 if (panel_it != mPanels.begin())
1616 {
1617 mMinWidth += PANEL_STACK_GAP;
1618 }
1619 }
1620 else //VERTICAL
1621 {
1622 mMinWidth = llmax(mMinWidth, (*panel_it)->mMinWidth);
1623 mMinHeight += (*panel_it)->mMinHeight;
1624 if (panel_it != mPanels.begin())
1625 {
1626 mMinHeight += PANEL_STACK_GAP;
1627 }
1628 }
1629 }
1630}