diff options
Diffstat (limited to 'linden/indra/llui/llpanel.cpp')
-rw-r--r-- | linden/indra/llui/llpanel.cpp | 659 |
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 | |||
54 | LLPanel::panel_map_t LLPanel::sPanelMap; | 60 | LLPanel::panel_map_t LLPanel::sPanelMap; |
55 | LLPanel::alert_queue_t LLPanel::sAlertQueue; | 61 | LLPanel::alert_queue_t LLPanel::sAlertQueue; |
56 | 62 | ||
63 | const S32 RESIZE_BAR_OVERLAP = 1; | ||
64 | const S32 PANEL_STACK_GAP = RESIZE_BAR_HEIGHT; | ||
65 | |||
57 | void LLPanel::init() | 66 | void 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 | ||
131 | void LLPanel::removeBorder() | ||
132 | { | ||
133 | delete mBorder; | ||
134 | mBorder = NULL; | ||
135 | } | ||
136 | |||
122 | 137 | ||
123 | LLPanel::~LLPanel() | 138 | LLPanel::~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 | ||
180 | void LLPanel::draw() | 192 | void 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 | ||
222 | void LLPanel::refresh() | 231 | void LLPanel::refresh() |
@@ -572,7 +581,7 @@ LLXMLNodePtr LLPanel::getXML(bool save_children) const | |||
572 | return node; | 581 | return node; |
573 | } | 582 | } |
574 | 583 | ||
575 | LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parentp, LLUICtrlFactory *factory) | 584 | LLView* 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 | ||
627 | void LLPanel::setPanelParameters(LLXMLNodePtr node, LLView* parentp) | 650 | void 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 | |||
672 | void 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 | ||
728 | LLString 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 | |||
741 | LLUIString 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 | |||
679 | void LLPanel::childSetVisible(const LLString& id, bool visible) | 752 | void 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 | ||
1141 | void LLPanel::storeRectControl() | ||
1142 | { | ||
1143 | if( !mRectControl.empty() ) | ||
1144 | { | ||
1145 | LLUI::sConfigGroup->setRect( mRectControl, mRect ); | ||
1146 | } | ||
1147 | } | ||
1148 | |||
1149 | |||
1150 | // | ||
1151 | // LLLayoutStack | ||
1152 | // | ||
1153 | struct 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 | |||
1193 | LLLayoutStack::LLLayoutStack(eLayoutOrientation orientation) : | ||
1194 | mOrientation(orientation), | ||
1195 | mMinWidth(0), | ||
1196 | mMinHeight(0) | ||
1197 | { | ||
1198 | } | ||
1199 | |||
1200 | LLLayoutStack::~LLLayoutStack() | ||
1201 | { | ||
1202 | } | ||
1203 | |||
1204 | void 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 | |||
1230 | void 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 | |||
1245 | void LLLayoutStack::reshape(S32 width, S32 height, BOOL called_from_parent) | ||
1246 | { | ||
1247 | LLView::reshape(width, height, called_from_parent); | ||
1248 | //updateLayout(); | ||
1249 | } | ||
1250 | |||
1251 | LLXMLNodePtr LLLayoutStack::getXML(bool save_children) const | ||
1252 | { | ||
1253 | LLXMLNodePtr node = LLView::getXML(); | ||
1254 | return node; | ||
1255 | } | ||
1256 | |||
1257 | //static | ||
1258 | LLView* 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 | |||
1307 | S32 LLLayoutStack::getMinWidth() | ||
1308 | { | ||
1309 | return mMinWidth; | ||
1310 | } | ||
1311 | |||
1312 | S32 LLLayoutStack::getMinHeight() | ||
1313 | { | ||
1314 | return mMinHeight; | ||
1315 | } | ||
1316 | |||
1317 | void 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 | |||
1348 | void LLLayoutStack::removePanel(LLPanel* panel) | ||
1349 | { | ||
1350 | removeChild(panel); | ||
1351 | //updateLayout(); | ||
1352 | } | ||
1353 | |||
1354 | void 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 | |||
1590 | LLLayoutStack::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 | |||
1603 | void 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 | } | ||