llpanel.cpp

Go to the documentation of this file.
00001 
00032 // Opaque view with a background and a border.  Can contain LLUICtrls.
00033 
00034 #include "linden_common.h"
00035 
00036 #include "llpanel.h"
00037 
00038 #include "llalertdialog.h"
00039 #include "llfocusmgr.h"
00040 #include "llfontgl.h"
00041 #include "llrect.h"
00042 #include "llerror.h"
00043 #include "lltimer.h"
00044 
00045 #include "llmenugl.h"
00046 //#include "llstatusbar.h"
00047 #include "llui.h"
00048 #include "llkeyboard.h"
00049 #include "lllineeditor.h"
00050 #include "llcontrol.h"
00051 #include "lltextbox.h"
00052 #include "lluictrl.h"
00053 #include "lluictrlfactory.h"
00054 #include "llviewborder.h"
00055 #include "llbutton.h"
00056 
00057 // LLLayoutStack
00058 #include "llgl.h"
00059 #include "llglheaders.h"
00060 #include "llresizebar.h"
00061 #include "llcriticaldamp.h"
00062 
00063 LLPanel::panel_map_t LLPanel::sPanelMap;
00064 LLPanel::alert_queue_t LLPanel::sAlertQueue;
00065 
00066 const S32 RESIZE_BAR_OVERLAP = 1;
00067 const S32 PANEL_STACK_GAP = RESIZE_BAR_HEIGHT;
00068 
00069 void LLPanel::init()
00070 {
00071         // mRectControl
00072         mBgColorAlpha        = LLUI::sColorsGroup->getColor( "DefaultBackgroundColor" );
00073         mBgColorOpaque       = LLUI::sColorsGroup->getColor( "FocusBackgroundColor" );
00074         mDefaultBtnHighlight = LLUI::sColorsGroup->getColor( "DefaultHighlightLight" );
00075         mBgVisible = FALSE;
00076         mBgOpaque = FALSE;
00077         mBorder = NULL;
00078         mDefaultBtn = NULL;
00079         setIsChrome(FALSE); //is this a decorator to a live window or a form?
00080         mLastTabGroup = 0;
00081 
00082         // add self to handle->panel map
00083         sPanelMap[mViewHandle] = this;
00084         setTabStop(FALSE);
00085 }
00086 
00087 LLPanel::LLPanel()
00088 : mRectControl()
00089 {
00090         init();
00091 }
00092 
00093 LLPanel::LLPanel(const LLString& name)
00094 :       LLUICtrl(name, LLRect(0, 0, 0, 0), TRUE, NULL, NULL),
00095         mRectControl()
00096 {
00097         init();
00098 }
00099 
00100 
00101 LLPanel::LLPanel(const LLString& name, const LLRect& rect, BOOL bordered)
00102 :       LLUICtrl(name, rect, TRUE, NULL, NULL),
00103         mRectControl()
00104 {
00105         init();
00106         if (bordered)
00107         {
00108                 addBorder();
00109         }
00110 }
00111 
00112 
00113 LLPanel::LLPanel(const LLString& name, const LLString& rect_control, BOOL bordered)
00114 :       LLUICtrl(name, LLUI::sConfigGroup->getRect(rect_control), TRUE, NULL, NULL),
00115         mRectControl( rect_control )
00116 {
00117         init();
00118         if (bordered)
00119         {
00120                 addBorder();
00121         }
00122 }
00123 
00124 void LLPanel::addBorder(LLViewBorder::EBevel border_bevel,
00125                                                 LLViewBorder::EStyle border_style, S32 border_thickness)
00126 {
00127         mBorder = new LLViewBorder( "panel border", 
00128                                                                 LLRect(0, mRect.getHeight(), mRect.getWidth(), 0), 
00129                                                                 border_bevel, border_style, border_thickness );
00130         mBorder->setSaveToXML(false);
00131         addChild( mBorder );
00132 }
00133 
00134 void LLPanel::removeBorder()
00135 {
00136         delete mBorder;
00137         mBorder = NULL;
00138 }
00139 
00140 
00141 LLPanel::~LLPanel()
00142 {
00143         storeRectControl();
00144         sPanelMap.erase(mViewHandle);
00145 }
00146 
00147 
00148 // virtual
00149 EWidgetType LLPanel::getWidgetType() const
00150 {
00151         return WIDGET_TYPE_PANEL;
00152 }
00153 
00154 // virtual
00155 LLString LLPanel::getWidgetTag() const
00156 {
00157         return LL_PANEL_TAG;
00158 }
00159 
00160 // virtual
00161 BOOL LLPanel::isPanel()
00162 {
00163         return TRUE;
00164 }
00165 
00166 // virtual
00167 BOOL LLPanel::postBuild()
00168 {
00169         return TRUE;
00170 }
00171 
00172 // virtual
00173 void LLPanel::clearCtrls()
00174 {
00175         LLView::ctrl_list_t ctrls = getCtrlList();
00176         for (LLView::ctrl_list_t::iterator ctrl_it = ctrls.begin(); ctrl_it != ctrls.end(); ++ctrl_it)
00177         {
00178                 LLUICtrl* ctrl = *ctrl_it;
00179                 ctrl->setFocus( FALSE );
00180                 ctrl->setEnabled( FALSE );
00181                 ctrl->clear();
00182         }
00183 }
00184 
00185 void LLPanel::setCtrlsEnabled( BOOL b )
00186 {
00187         LLView::ctrl_list_t ctrls = getCtrlList();
00188         for (LLView::ctrl_list_t::iterator ctrl_it = ctrls.begin(); ctrl_it != ctrls.end(); ++ctrl_it)
00189         {
00190                 LLUICtrl* ctrl = *ctrl_it;
00191                 ctrl->setEnabled( b );
00192         }
00193 }
00194 
00195 void LLPanel::draw()
00196 {
00197         // draw background
00198         if( mBgVisible )
00199         {
00200                 //RN: I don't see the point of this
00201                 S32 left = 0;//LLPANEL_BORDER_WIDTH;
00202                 S32 top = mRect.getHeight();// - LLPANEL_BORDER_WIDTH;
00203                 S32 right = mRect.getWidth();// - LLPANEL_BORDER_WIDTH;
00204                 S32 bottom = 0;//LLPANEL_BORDER_WIDTH;
00205 
00206                 if (mBgOpaque )
00207                 {
00208                         gl_rect_2d( left, top, right, bottom, mBgColorOpaque );
00209                 }
00210                 else
00211                 {
00212                         gl_rect_2d( left, top, right, bottom, mBgColorAlpha );
00213                 }
00214         }
00215 
00216         if( mDefaultBtn)
00217         {
00218                 if (gFocusMgr.childHasKeyboardFocus( this ) && mDefaultBtn->getEnabled())
00219                 {
00220                         LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus();
00221                         BOOL focus_is_child_button = focus_ctrl->getWidgetType() == WIDGET_TYPE_BUTTON && static_cast<LLButton *>(focus_ctrl)->getCommitOnReturn();
00222                         // only enable default button when current focus is not a return-capturing button
00223                         mDefaultBtn->setBorderEnabled(!focus_is_child_button);
00224                 }
00225                 else
00226                 {
00227                         mDefaultBtn->setBorderEnabled(FALSE);
00228                 }
00229         }
00230 
00231         LLView::draw();
00232 }
00233 
00234 void LLPanel::refresh()
00235 {
00236         // do nothing by default
00237         // but is automatically called in setFocus(TRUE)
00238 }
00239 
00240 void LLPanel::setDefaultBtn(LLButton* btn)
00241 {
00242         if (mDefaultBtn && mDefaultBtn->getEnabled())
00243         {
00244                 mDefaultBtn->setBorderEnabled(FALSE);
00245         }
00246         mDefaultBtn = btn; 
00247         if (mDefaultBtn)
00248         {
00249                 mDefaultBtn->setBorderEnabled(TRUE);
00250         }
00251 }
00252 
00253 void LLPanel::setDefaultBtn(const LLString& id)
00254 {
00255         LLButton *button = LLUICtrlFactory::getButtonByName(this, id);
00256         if (button)
00257         {
00258                 setDefaultBtn(button);
00259         }
00260         else
00261         {
00262                 setDefaultBtn(NULL);
00263         }
00264 }
00265 
00266 BOOL LLPanel::handleKey(KEY key, MASK mask, BOOL called_from_parent)
00267 {
00268         BOOL handled = FALSE;
00269         if (getVisible() && getEnabled())
00270         {
00271                 if( (mask == MASK_SHIFT) && (KEY_TAB == key))   
00272                 {
00273                         //SHIFT-TAB
00274                         LLView* cur_focus = gFocusMgr.getKeyboardFocus();
00275                         if (cur_focus && gFocusMgr.childHasKeyboardFocus(this))
00276                         {
00277                                 LLView* focus_root = cur_focus;
00278                                 while(cur_focus->getParent())
00279                                 {
00280                                         cur_focus = cur_focus->getParent();
00281                                         if (cur_focus->isFocusRoot())
00282                                         {
00283                                                 // this is the root-most focus root found so far
00284                                                 focus_root = cur_focus;
00285                                         }
00286                                 }
00287                                 handled = focus_root->focusPrevItem(FALSE);
00288                         }
00289                         else if (!cur_focus && mIsFocusRoot)
00290                         {
00291                                 handled = focusLastItem();
00292                                 if (!handled)
00293                                 {
00294                                         setFocus(TRUE);
00295                                         handled = TRUE;
00296                                 }
00297                         }
00298                 }
00299                 else
00300                 if( (mask == MASK_NONE ) && (KEY_TAB == key))   
00301                 {
00302                         //TAB
00303                         LLView* cur_focus = gFocusMgr.getKeyboardFocus();
00304                         if (cur_focus && gFocusMgr.childHasKeyboardFocus(this))
00305                         {
00306                                 LLView* focus_root = cur_focus;
00307                                 while(cur_focus->getParent())
00308                                 {
00309                                         cur_focus = cur_focus->getParent();
00310                                         if (cur_focus->isFocusRoot())
00311                                         {
00312                                                 focus_root = cur_focus;
00313                                         }
00314                                 }
00315                                 handled = focus_root->focusNextItem(FALSE);
00316                         }
00317                         else if (!cur_focus && mIsFocusRoot)
00318                         {
00319                                 handled = focusFirstItem();
00320                                 if (!handled)
00321                                 {
00322                                         setFocus(TRUE);
00323                                         handled = TRUE;
00324                                 }
00325                         }
00326                 }
00327         }
00328 
00329         if (!handled)
00330         {
00331                 handled = LLView::handleKey(key, mask, called_from_parent);
00332         }
00333 
00334         return handled;
00335 }
00336 
00337 void LLPanel::addCtrl( LLUICtrl* ctrl, S32 tab_group)
00338 {
00339         mLastTabGroup = tab_group;
00340 
00341         LLView::addCtrl(ctrl, tab_group);
00342         // propagate chrome to children only if they have not been flagged as chrome
00343         if (!ctrl->getIsChrome())
00344         {
00345                 ctrl->setIsChrome(getIsChrome());
00346         }
00347 }
00348 
00349 void LLPanel::addCtrlAtEnd( LLUICtrl* ctrl, S32 tab_group)
00350 {
00351         mLastTabGroup = tab_group;
00352 
00353         LLView::addCtrlAtEnd(ctrl, tab_group);
00354         if (!ctrl->getIsChrome())
00355         {
00356                 ctrl->setIsChrome(getIsChrome());
00357         }
00358 }
00359 
00360 BOOL LLPanel::handleKeyHere( KEY key, MASK mask, BOOL called_from_parent )
00361 {
00362         BOOL handled = FALSE;
00363 
00364         if( getVisible() && getEnabled() && gFocusMgr.childHasKeyboardFocus(this) && KEY_ESCAPE == key )
00365         {
00366                 gFocusMgr.setKeyboardFocus(NULL, NULL);
00367                 return TRUE;
00368         }
00369 
00370         if( getVisible() && getEnabled() && 
00371                 gFocusMgr.childHasKeyboardFocus(this) && !called_from_parent )
00372         {
00373                 LLUICtrl* cur_focus = gFocusMgr.getKeyboardFocus();
00374                 // If we have a default button, click it when
00375                 // return is pressed, unless current focus is a return-capturing button
00376                 // in which case *that* button will handle the return key
00377                 if (cur_focus && !(cur_focus->getWidgetType() == WIDGET_TYPE_BUTTON && static_cast<LLButton *>(cur_focus)->getCommitOnReturn()))
00378                 {
00379                         // RETURN key means hit default button in this case
00380                         if (key == KEY_RETURN && mask == MASK_NONE 
00381                                 && mDefaultBtn != NULL 
00382                                 && mDefaultBtn->getVisible()
00383                                 && mDefaultBtn->getEnabled())
00384                         {
00385                                 mDefaultBtn->onCommit();
00386                                 handled = TRUE;
00387                         }
00388                 }
00389 
00390                 if (key == KEY_RETURN && mask == MASK_NONE)
00391                 {
00392                         // set keyboard focus to self to trigger commitOnFocusLost behavior on current ctrl
00393                         if (cur_focus && cur_focus->acceptsTextInput())
00394                         {
00395                                 cur_focus->onCommit();
00396                                 handled = TRUE;
00397                         }
00398                 }
00399         }
00400 
00401         return handled;
00402 }
00403 
00404 void LLPanel::requires(LLString name, EWidgetType type)
00405 {
00406         mRequirements[name] = type;
00407 }
00408 
00409 BOOL LLPanel::checkRequirements()
00410 {
00411         BOOL retval = TRUE;
00412         LLString message;
00413 
00414         for (requirements_map_t::iterator i = mRequirements.begin(); i != mRequirements.end(); ++i)
00415         {
00416                 if (!this->getCtrlByNameAndType(i->first, i->second))
00417                 {
00418                         retval = FALSE;
00419                         message += i->first + " " + LLUICtrlFactory::getWidgetType(i->second) + "\n";
00420                 }
00421         }
00422 
00423         if (!retval)
00424         {
00425                 LLString::format_map_t args;
00426                 args["[COMPONENTS]"] = message;
00427                 args["[FLOATER]"] = getName();
00428 
00429                 llwarns << getName() << " failed requirements check on: \n"  
00430                                 << message << llendl;
00431                         
00432                 alertXml("FailedRequirementsCheck", args);
00433         }
00434 
00435         return retval;
00436 }
00437 
00438 //static
00439 void LLPanel::alertXml(LLString label, LLString::format_map_t args)
00440 {
00441         sAlertQueue.push(LLAlertInfo(label,args));
00442 }
00443 
00444 //static
00445 BOOL LLPanel::nextAlert(LLAlertInfo &alert)
00446 {
00447         if (!sAlertQueue.empty())
00448         {
00449                 alert = sAlertQueue.front();
00450                 sAlertQueue.pop();
00451                 return TRUE;
00452         }
00453 
00454         return FALSE;
00455 }
00456 
00457 void LLPanel::setFocus(BOOL b)
00458 {
00459         if( b )
00460         {
00461                 if (!gFocusMgr.childHasKeyboardFocus(this))
00462                 {
00463                         //refresh();
00464                         if (!focusFirstItem())
00465                         {
00466                                 LLUICtrl::setFocus(TRUE);
00467                         }
00468                         onFocusReceived();
00469                 }
00470         }
00471         else
00472         {
00473                 if( this == gFocusMgr.getKeyboardFocus() )
00474                 {
00475                         gFocusMgr.setKeyboardFocus( NULL, NULL );
00476                 }
00477                 else
00478                 {
00479                         //RN: why is this here?
00480                         LLView::ctrl_list_t ctrls = getCtrlList();
00481                         for (LLView::ctrl_list_t::iterator ctrl_it = ctrls.begin(); ctrl_it != ctrls.end(); ++ctrl_it)
00482                         {
00483                                 LLUICtrl* ctrl = *ctrl_it;
00484                                 ctrl->setFocus( FALSE );
00485                         }
00486                 }
00487         }
00488 }
00489 
00490 void LLPanel::setBackgroundColor(const LLColor4& color)
00491 {
00492         mBgColorOpaque = color;
00493 }
00494 
00495 LLColor4 LLPanel::getBackgroundColor()
00496 {
00497         return mBgColorOpaque;
00498 }
00499 
00500 void LLPanel::setTransparentColor(const LLColor4& color)
00501 {
00502         mBgColorAlpha = color;
00503 }
00504 
00505 void LLPanel::setBorderVisible(BOOL b)
00506 {
00507         if (mBorder)
00508         {
00509                 mBorder->setVisible( b );
00510         }
00511 }
00512 
00513 LLView* LLPanel::getCtrlByNameAndType(const LLString& name, EWidgetType type)
00514 {
00515         LLView* view = getChildByName(name, TRUE);
00516         if (view)
00517         {
00518                 if (type ==     WIDGET_TYPE_DONTCARE || view->getWidgetType() == type)
00519                 {
00520                         return view;
00521                 }
00522                 else
00523                 {
00524                         llwarns << "Widget " << name << " has improper type in panel " << mName << "\n"
00525                                         << "Is: \t\t" << view->getWidgetType() << "\n" 
00526                                         << "Should be: \t" << type 
00527                                         << llendl;
00528                 }
00529         }
00530         else
00531         {
00532                 childNotFound(name);
00533         }
00534         return NULL;
00535 }
00536 
00537 // static 
00538 LLPanel* LLPanel::getPanelByHandle(LLViewHandle handle)
00539 {
00540         if (!sPanelMap.count(handle))
00541         {
00542                 return NULL;
00543         }
00544  
00545         return sPanelMap[handle];
00546 }
00547 
00548 // virtual
00549 LLXMLNodePtr LLPanel::getXML(bool save_children) const
00550 {
00551         LLXMLNodePtr node = LLView::getXML();
00552 
00553         if (mBorder && mBorder->getVisible())
00554         {
00555                 node->createChild("border", TRUE)->setBoolValue(TRUE);
00556         }
00557 
00558         if (!mRectControl.empty())
00559         {
00560                 node->createChild("rect_control", TRUE)->setStringValue(mRectControl);
00561         }
00562 
00563         if (!mLabel.empty())
00564         {
00565                 node->createChild("label", TRUE)->setStringValue(mLabel);
00566         }
00567 
00568         if (save_children)
00569         {
00570                 LLView::child_list_const_reverse_iter_t rit;
00571                 for (rit = getChildList()->rbegin(); rit != getChildList()->rend(); ++rit)
00572                 {
00573                         LLView* childp = *rit;
00574 
00575                         if (childp->getSaveToXML())
00576                         {
00577                                 LLXMLNodePtr xml_node = childp->getXML();
00578 
00579                                 node->addChild(xml_node);
00580                         }
00581                 }
00582         }
00583 
00584         return node;
00585 }
00586 
00587 LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parent, LLUICtrlFactory *factory)
00588 {
00589         LLString name("panel");
00590         node->getAttributeString("name", name);
00591 
00592         LLPanel* panelp = factory->createFactoryPanel(name);
00593         // Fall back on a default panel, if there was no special factory.
00594         if (!panelp)
00595         {
00596                 LLRect rect;
00597                 createRect(node, rect, parent, LLRect());
00598                 panelp = new LLPanel(name, rect);
00599                 panelp->initPanelXML(node, parent, factory);
00600                 // preserve panel's width and height, but override the location
00601                 const LLRect& panelrect = panelp->getRect();
00602                 S32 w = panelrect.getWidth();
00603                 S32 h = panelrect.getHeight();
00604                 rect.setLeftTopAndSize(rect.mLeft, rect.mTop, w, h);
00605                 panelp->setRect(rect);
00606         }
00607         else
00608         {
00609                 panelp->initPanelXML(node, parent, factory);
00610         }
00611         return panelp;
00612 }
00613 
00614 BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
00615 {
00616         LLString name("panel");
00617         node->getAttributeString("name", name);
00618         setName(name);
00619 
00620         setPanelParameters(node, parent);
00621 
00622         initChildrenXML(node, factory);
00623 
00624         LLString xml_filename;
00625         node->getAttributeString("filename", xml_filename);
00626 
00627         BOOL didPost;
00628 
00629         if (!xml_filename.empty())
00630         {
00631                 // Preserve postion of embedded panel but allow panel to dictate width/height
00632                 LLRect rect(getRect());
00633                 didPost = factory->buildPanel(this, xml_filename, NULL);
00634                 S32 w = getRect().getWidth();
00635                 S32 h = getRect().getHeight();
00636                 rect.setLeftTopAndSize(rect.mLeft, rect.mTop, w, h);
00637                 setRect(rect);
00638         }
00639         else
00640         {
00641                 didPost = FALSE;
00642         }
00643         
00644         if (!didPost)
00645         {
00646                 postBuild();
00647                 didPost = TRUE;
00648         }
00649 
00650         return didPost;
00651 }
00652 
00653 void LLPanel::initChildrenXML(LLXMLNodePtr node, LLUICtrlFactory* factory)
00654 {
00655         LLXMLNodePtr child;
00656         for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
00657         {
00658                 // look for string declarations for programmatic text
00659                 if (child->hasName("string"))
00660                 {
00661                         LLString string_name;
00662                         child->getAttributeString("name", string_name);
00663                         if (!string_name.empty())
00664                         {
00665                                 mUIStrings[string_name] = LLUIString(child->getTextContents());
00666                         }
00667                 }
00668                 else
00669                 {
00670                         factory->createWidget(this, child);
00671                 }
00672         }
00673 }
00674 
00675 void LLPanel::setPanelParameters(LLXMLNodePtr node, LLView* parent)
00676 {
00678         initFromXML(node, parent);
00679 
00681         BOOL border = FALSE;
00682         node->getAttributeBOOL("border", border);
00683         if (border)
00684         {
00685                 LLViewBorder::EBevel bevel_style = LLViewBorder::BEVEL_OUT;
00686                 LLViewBorder::getBevelFromAttribute(node, bevel_style);
00687 
00688                 LLViewBorder::EStyle border_style = LLViewBorder::STYLE_LINE;
00689                 LLString border_string;
00690                 node->getAttributeString("border_style", border_string);
00691                 LLString::toLower(border_string);
00692 
00693                 if (border_string == "texture")
00694                 {
00695                         border_style = LLViewBorder::STYLE_TEXTURE;
00696                 }
00697 
00698                 S32 border_thickness = LLPANEL_BORDER_WIDTH;
00699                 node->getAttributeS32("border_thickness", border_thickness);
00700 
00701                 addBorder(bevel_style, border_style, border_thickness);
00702         }
00703         else
00704         {
00705                 removeBorder();
00706         }
00707 
00709         BOOL background_visible = FALSE;
00710         node->getAttributeBOOL("background_visible", background_visible);
00711         setBackgroundVisible(background_visible);
00712         
00713         BOOL background_opaque = FALSE;
00714         node->getAttributeBOOL("background_opaque", background_opaque);
00715         setBackgroundOpaque(background_opaque);
00716 
00717         LLColor4 color;
00718         color = LLUI::sColorsGroup->getColor( "FocusBackgroundColor" );
00719         LLUICtrlFactory::getAttributeColor(node,"bg_opaque_color", color);
00720         setBackgroundColor(color);
00721 
00722         color = LLUI::sColorsGroup->getColor( "DefaultBackgroundColor" );
00723         LLUICtrlFactory::getAttributeColor(node,"bg_alpha_color", color);
00724         setTransparentColor(color);
00725 
00726         LLString label;
00727         node->getAttributeString("label", label);
00728         setLabel(label);
00729 }
00730 
00731 LLString LLPanel::getFormattedUIString(const LLString& name, const LLString::format_map_t& args) const
00732 {
00733         ui_string_map_t::const_iterator found_it = mUIStrings.find(name);
00734         if (found_it != mUIStrings.end())
00735         {
00736                 // make a copy as format works in place
00737                 LLUIString formatted_string = found_it->second;
00738                 formatted_string.setArgList(args);
00739                 return formatted_string.getString();
00740         }
00741         return LLString::null;
00742 }
00743 
00744 LLUIString LLPanel::getUIString(const LLString& name) const
00745 {
00746         ui_string_map_t::const_iterator found_it = mUIStrings.find(name);
00747         if (found_it != mUIStrings.end())
00748         {
00749                 return found_it->second;
00750         }
00751         return LLUIString(LLString::null);
00752 }
00753 
00754 
00755 void LLPanel::childSetVisible(const LLString& id, bool visible)
00756 {
00757         LLView* child = getChildByName(id, true);
00758         if (child)
00759         {
00760                 child->setVisible(visible);
00761         }
00762 }
00763 
00764 bool LLPanel::childIsVisible(const LLString& id) const
00765 {
00766         LLView* child = getChildByName(id, true);
00767         if (child)
00768         {
00769                 return (bool)child->getVisible();
00770         }
00771         return false;
00772 }
00773 
00774 void LLPanel::childSetEnabled(const LLString& id, bool enabled)
00775 {
00776         LLView* child = getChildByName(id, true);
00777         if (child)
00778         {
00779                 child->setEnabled(enabled);
00780         }
00781 }
00782 
00783 void LLPanel::childSetTentative(const LLString& id, bool tentative)
00784 {
00785         LLView* child = getChildByName(id, true);
00786         if (child)
00787         {
00788                 child->setTentative(tentative);
00789         }
00790 }
00791 
00792 bool LLPanel::childIsEnabled(const LLString& id) const
00793 {
00794         LLView* child = getChildByName(id, true);
00795         if (child)
00796         {
00797                 return (bool)child->getEnabled();
00798         }
00799         return false;
00800 }
00801 
00802 
00803 void LLPanel::childSetToolTip(const LLString& id, const LLString& msg)
00804 {
00805         LLView* child = getChildByName(id, true);
00806         if (child)
00807         {
00808                 child->setToolTip(msg);
00809         }
00810 }
00811 
00812 void LLPanel::childSetRect(const LLString& id, const LLRect& rect)
00813 {
00814         LLView* child = getChildByName(id, true);
00815         if (child)
00816         {
00817                 child->setRect(rect);
00818         }
00819 }
00820 
00821 bool LLPanel::childGetRect(const LLString& id, LLRect& rect) const
00822 {
00823         LLView* child = getChildByName(id, true);
00824         if (child)
00825         {
00826                 rect = child->getRect();
00827                 return true;
00828         }
00829         return false;
00830 }
00831 
00832 void LLPanel::childSetFocus(const LLString& id, BOOL focus)
00833 {
00834         LLUICtrl* child = (LLUICtrl*)getChildByName(id, true);
00835         if (child)
00836         {
00837                 child->setFocus(focus);
00838         }
00839 }
00840 
00841 BOOL LLPanel::childHasFocus(const LLString& id)
00842 {
00843         LLUICtrl* child = (LLUICtrl*)getChildByName(id, true);
00844         if (child)
00845         {
00846                 return child->hasFocus();
00847         }
00848         else
00849         {
00850                 childNotFound(id);
00851                 return FALSE;
00852         }
00853 }
00854 
00855 
00856 void LLPanel::childSetFocusChangedCallback(const LLString& id, void (*cb)(LLUICtrl*, void*))
00857 {
00858         LLUICtrl* child = (LLUICtrl*)getChildByName(id, true);
00859         if (child)
00860         {
00861                 child->setFocusChangedCallback(cb);
00862         }
00863 }
00864 
00865 void LLPanel::childSetCommitCallback(const LLString& id, void (*cb)(LLUICtrl*, void*), void *userdata )
00866 {
00867         LLUICtrl* child = (LLUICtrl*)getChildByName(id, true);
00868         if (child)
00869         {
00870                 child->setCommitCallback(cb);
00871                 child->setCallbackUserData(userdata);
00872         }
00873 }
00874 
00875 void LLPanel::childSetDoubleClickCallback(const LLString& id, void (*cb)(void*), void *userdata )
00876 {
00877         LLUICtrl* child = (LLUICtrl*)getChildByName(id, true);
00878         if (child)
00879         {
00880                 child->setDoubleClickCallback(cb);
00881                 if (userdata)
00882                 {
00883                         child->setCallbackUserData(userdata);
00884                 }
00885         }
00886 }
00887 
00888 void LLPanel::childSetValidate(const LLString& id, BOOL (*cb)(LLUICtrl*, void*))
00889 {
00890         LLUICtrl* child = (LLUICtrl*)getChildByName(id, true);
00891         if (child)
00892         {
00893                 child->setValidateBeforeCommit(cb);
00894         }
00895 }
00896 
00897 void LLPanel::childSetUserData(const LLString& id, void* userdata)
00898 {
00899         LLUICtrl* child = (LLUICtrl*)getChildByName(id, true);
00900         if (child)
00901         {
00902                 child->setCallbackUserData(userdata);
00903         }
00904 }
00905 
00906 void LLPanel::childSetColor(const LLString& id, const LLColor4& color)
00907 {
00908         LLUICtrl* child = (LLUICtrl*)getChildByName(id, true);
00909         if (child)
00910         {
00911                 child->setColor(color);
00912         }
00913 }
00914 
00915 LLCtrlSelectionInterface* LLPanel::childGetSelectionInterface(const LLString& id)
00916 {
00917         LLUICtrl* child = (LLUICtrl*)getChildByName(id, true);
00918         if (child)
00919         {
00920                 return child->getSelectionInterface();
00921         }
00922         return NULL;
00923 }
00924 
00925 LLCtrlListInterface* LLPanel::childGetListInterface(const LLString& id)
00926 {
00927         LLUICtrl* child = (LLUICtrl*)getChildByName(id, true);
00928         if (child)
00929         {
00930                 return child->getListInterface();
00931         }
00932         return NULL;
00933 }
00934 
00935 LLCtrlScrollInterface* LLPanel::childGetScrollInterface(const LLString& id)
00936 {
00937         LLUICtrl* child = (LLUICtrl*)getChildByName(id, true);
00938         if (child)
00939         {
00940                 return child->getScrollInterface();
00941         }
00942         return NULL;
00943 }
00944 
00945 void LLPanel::childSetValue(const LLString& id, LLSD value)
00946 {
00947         LLUICtrl* child = (LLUICtrl*)getChildByName(id, true);
00948         if (child)
00949         {
00950                 child->setValue(value);
00951         }
00952 }
00953 
00954 LLSD LLPanel::childGetValue(const LLString& id) const
00955 {
00956         LLUICtrl* child = (LLUICtrl*)getChildByName(id, true);
00957         if (child)
00958         {
00959                 return child->getValue();
00960         }
00961         // Not found => return undefined
00962         return LLSD();
00963 }
00964 
00965 BOOL LLPanel::childSetTextArg(const LLString& id, const LLString& key, const LLStringExplicit& text)
00966 {
00967         LLUICtrl* child = (LLUICtrl*)getChildByName(id, true);
00968         if (child)
00969         {
00970                 return child->setTextArg(key, text);
00971         }
00972         return FALSE;
00973 }
00974 
00975 BOOL LLPanel::childSetLabelArg(const LLString& id, const LLString& key, const LLStringExplicit& text)
00976 {
00977         LLView* child = getChildByName(id, true);
00978         if (child)
00979         {
00980                 return child->setLabelArg(key, text);
00981         }
00982         return FALSE;
00983 }
00984 
00985 void LLPanel::childSetMinValue(const LLString& id, LLSD min_value)
00986 {
00987         LLUICtrl* child = (LLUICtrl*)getChildByName(id, true);
00988         if (child)
00989         {
00990                 child->setMinValue(min_value);
00991         }
00992 }
00993 
00994 void LLPanel::childSetMaxValue(const LLString& id, LLSD max_value)
00995 {
00996         LLUICtrl* child = (LLUICtrl*)getChildByName(id, true);
00997         if (child)
00998         {
00999                 child->setMaxValue(max_value);
01000         }
01001 }
01002 
01003 void LLPanel::childShowTab(const LLString& id, const LLString& tabname, bool visible)
01004 {
01005         LLTabContainerCommon* child = LLUICtrlFactory::getTabContainerByName(this, id);
01006         if (child)
01007         {
01008                 child->selectTabByName(tabname);
01009         }
01010 }
01011 
01012 LLPanel *LLPanel::childGetVisibleTab(const LLString& id)
01013 {
01014         LLTabContainerCommon* child = LLUICtrlFactory::getTabContainerByName(this, id);
01015         if (child)
01016         {
01017                 return child->getCurrentPanel();
01018         }
01019         return NULL;
01020 }
01021 
01022 void LLPanel::childSetTabChangeCallback(const LLString& id, const LLString& tabname, void (*on_tab_clicked)(void*, bool), void *userdata)
01023 {
01024         LLTabContainerCommon* child = LLUICtrlFactory::getTabContainerByName(this, id);
01025         if (child)
01026         {
01027                 LLPanel *panel = child->getPanelByName(tabname);
01028                 if (panel)
01029                 {
01030                         child->setTabChangeCallback(panel, on_tab_clicked);
01031                         child->setTabUserData(panel, userdata);
01032                 }
01033         }
01034 }
01035 
01036 void LLPanel::childSetText(const LLString& id, const LLStringExplicit& text)
01037 {
01038         childSetValue(id, LLSD(text));
01039 }
01040 
01041 void LLPanel::childSetKeystrokeCallback(const LLString& id, void (*keystroke_callback)(LLLineEditor* caller, void* user_data), void *user_data)
01042 {
01043         LLLineEditor* child = LLUICtrlFactory::getLineEditorByName(this, id);
01044         if (child)
01045         {
01046                 child->setKeystrokeCallback(keystroke_callback);
01047                 if (user_data)
01048                 {
01049                         child->setCallbackUserData(user_data);
01050                 }
01051         }
01052 }
01053 
01054 void LLPanel::childSetPrevalidate(const LLString& id, BOOL (*func)(const LLWString &) )
01055 {
01056         LLLineEditor* child = LLUICtrlFactory::getLineEditorByName(this, id);
01057         if (child)
01058         {
01059                 child->setPrevalidate(func);
01060         }
01061 }
01062 
01063 LLString LLPanel::childGetText(const LLString& id)
01064 {
01065         return childGetValue(id).asString();
01066 }
01067 
01068 void LLPanel::childSetWrappedText(const LLString& id, const LLString& text, bool visible)
01069 {
01070         LLTextBox* child = (LLTextBox*)getCtrlByNameAndType(id, WIDGET_TYPE_TEXT_BOX);
01071         if (child)
01072         {
01073                 child->setVisible(visible);
01074                 child->setWrappedText(text);
01075         }
01076 }
01077 
01078 void LLPanel::childSetAction(const LLString& id, void(*function)(void*), void* value)
01079 {
01080         LLButton* button = (LLButton*)getCtrlByNameAndType(id, WIDGET_TYPE_BUTTON);
01081         if (button)
01082         {
01083                 button->setClickedCallback(function, value);
01084         }
01085 }
01086 
01087 void LLPanel::childSetActionTextbox(const LLString& id, void(*function)(void*))
01088 {
01089         LLTextBox* textbox = (LLTextBox*)getCtrlByNameAndType(id, WIDGET_TYPE_TEXT_BOX);
01090         if (textbox)
01091         {
01092                 textbox->setClickedCallback(function);
01093         }
01094 }
01095 
01096 void LLPanel::childSetControlName(const LLString& id, const LLString& control_name)
01097 {
01098         LLView* view = getChildByName(id, TRUE);
01099         if (view)
01100         {
01101                 view->setControlName(control_name, NULL);
01102         }
01103 }
01104 
01105 //virtual
01106 LLView* LLPanel::getChildByName(const LLString& name, BOOL recurse) const
01107 {
01108         LLView* view = LLUICtrl::getChildByName(name, recurse);
01109         if (!view && !recurse)
01110         {
01111                 childNotFound(name);
01112         }
01113         return view;
01114 }
01115 
01116 void LLPanel::childNotFound(const LLString& id) const
01117 {
01118         if (mExpectedMembers.find(id) == mExpectedMembers.end())
01119         {
01120                 mNewExpectedMembers.insert(id);
01121         }
01122 }
01123 
01124 void LLPanel::childDisplayNotFound()
01125 {
01126         if (mNewExpectedMembers.empty())
01127         {
01128                 return;
01129         }
01130         LLString msg;
01131         expected_members_list_t::iterator itor;
01132         for (itor=mNewExpectedMembers.begin(); itor!=mNewExpectedMembers.end(); ++itor)
01133         {
01134                 msg.append(*itor);
01135                 msg.append("\n");
01136                 mExpectedMembers.insert(*itor);
01137         }
01138         mNewExpectedMembers.clear();
01139         LLString::format_map_t args;
01140         args["[CONTROLS]"] = msg;
01141         LLAlertDialog::showXml("FloaterNotFound", args);
01142 }
01143 
01144 void LLPanel::storeRectControl()
01145 {
01146         if( !mRectControl.empty() )
01147         {
01148                 LLUI::sConfigGroup->setRect( mRectControl, mRect );
01149         }
01150 }
01151 
01152 
01153 //
01154 // LLLayoutStack
01155 //
01156 struct LLLayoutStack::LLEmbeddedPanel
01157 {
01158         LLEmbeddedPanel(LLPanel* panelp, eLayoutOrientation orientation, S32 min_width, S32 min_height, BOOL auto_resize) : 
01159                         mPanel(panelp), 
01160                         mMinWidth(min_width), 
01161                         mMinHeight(min_height),
01162                         mAutoResize(auto_resize),
01163                         mOrientation(orientation),
01164                         mVisibleAmt(1.f) // default to fully visible
01165         {
01166                 LLResizeBar::Side side = (orientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM;
01167                 LLRect resize_bar_rect = panelp->getRect();
01168 
01169                 S32 min_dim;
01170                 if (orientation == HORIZONTAL)
01171                 {
01172                         min_dim = mMinHeight;
01173                 }
01174                 else
01175                 {
01176                         min_dim = mMinWidth;
01177                 }
01178                 mResizeBar = new LLResizeBar("resizer", mPanel, LLRect(), min_dim, S32_MAX, side);
01179                 mResizeBar->setEnableSnapping(FALSE);
01180                 // panels initialized as hidden should not start out partially visible
01181                 if (!mPanel->getVisible())
01182                 {
01183                         mVisibleAmt = 0.f;
01184                 }
01185         }
01186 
01187         LLPanel* mPanel;
01188         S32 mMinWidth;
01189         S32 mMinHeight;
01190         BOOL mAutoResize;
01191         LLResizeBar* mResizeBar;
01192         eLayoutOrientation mOrientation;
01193         F32 mVisibleAmt;
01194 };
01195 
01196 LLLayoutStack::LLLayoutStack(eLayoutOrientation orientation) : 
01197                 mOrientation(orientation),
01198                 mMinWidth(0),
01199                 mMinHeight(0)
01200 {
01201 }
01202 
01203 LLLayoutStack::~LLLayoutStack()
01204 {
01205 }
01206 
01207 void LLLayoutStack::draw()
01208 {
01209         updateLayout();
01210         {
01211                 // clip if outside nominal bounds
01212                 LLLocalClipRect clip(getLocalRect(), mRect.getWidth() > mMinWidth || mRect.getHeight() > mMinHeight);
01213                 e_panel_list_t::iterator panel_it;
01214                 for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
01215                 {
01216                         LLRect clip_rect = (*panel_it)->mPanel->getRect();
01217                         // scale clipping rectangle by visible amount
01218                         if (mOrientation == HORIZONTAL)
01219                         {
01220                                 clip_rect.mRight = clip_rect.mLeft + llround(clip_rect.getWidth() * (*panel_it)->mVisibleAmt);
01221                         }
01222                         else
01223                         {
01224                                 clip_rect.mBottom = clip_rect.mTop - llround(clip_rect.getHeight() * (*panel_it)->mVisibleAmt);
01225                         }
01226                         LLLocalClipRect clip(clip_rect, (*panel_it)->mVisibleAmt < 1.f);
01227                         // only force drawing invisible children if visible amount is non-zero
01228                         drawChild((*panel_it)->mPanel, 0, 0, (*panel_it)->mVisibleAmt > 0.f);
01229                 }
01230         }
01231 }
01232 
01233 void LLLayoutStack::removeCtrl(LLUICtrl* ctrl)
01234 {
01235         LLEmbeddedPanel* embedded_panelp = findEmbeddedPanel((LLPanel*)ctrl);
01236 
01237         if (embedded_panelp)
01238         {
01239                 mPanels.erase(std::find(mPanels.begin(), mPanels.end(), embedded_panelp));
01240                 delete embedded_panelp;
01241         }
01242 
01243         calcMinExtents();
01244 
01245         LLView::removeCtrl(ctrl);
01246 }
01247 
01248 void LLLayoutStack::reshape(S32 width, S32 height, BOOL called_from_parent)
01249 {
01250         LLView::reshape(width, height, called_from_parent);
01251         //updateLayout();
01252 }
01253 
01254 LLXMLNodePtr LLLayoutStack::getXML(bool save_children) const
01255 {
01256         LLXMLNodePtr node = LLView::getXML();
01257         return node;
01258 }
01259 
01260 //static 
01261 LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
01262 {
01263         LLString orientation_string("vertical");
01264         node->getAttributeString("orientation", orientation_string);
01265 
01266         eLayoutOrientation orientation = VERTICAL;
01267 
01268         if (orientation_string == "horizontal")
01269         {
01270                 orientation = HORIZONTAL;
01271         }
01272         else if (orientation_string == "vertical")
01273         {
01274                 orientation = VERTICAL;
01275         }
01276         else
01277         {
01278                 llwarns << "Unknown orientation " << orientation_string << ", using vertical" << llendl;
01279         }
01280 
01281         LLLayoutStack* layout_stackp = new LLLayoutStack(orientation);
01282 
01283         layout_stackp->initFromXML(node, parent);
01284 
01285         LLXMLNodePtr child;
01286         for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
01287         {
01288                 if (child->hasName("layout_panel"))
01289                 {
01290                         S32 min_width = 0;
01291                         S32 min_height = 0;
01292                         BOOL auto_resize = TRUE;
01293 
01294                         child->getAttributeS32("min_width", min_width);
01295                         child->getAttributeS32("min_height", min_height);
01296                         child->getAttributeBOOL("auto_resize", auto_resize);
01297 
01298                         LLPanel* panelp = (LLPanel*)LLPanel::fromXML(child, layout_stackp, factory);
01299                         if (panelp)
01300                         {
01301                                 panelp->setFollowsNone();
01302                                 layout_stackp->addPanel(panelp, min_width, min_height, auto_resize);
01303                         }
01304                 }
01305         }
01306 
01307         return layout_stackp;
01308 }
01309 
01310 S32 LLLayoutStack::getMinWidth()
01311 {
01312         return mMinWidth;
01313 }
01314 
01315 S32 LLLayoutStack::getMinHeight()
01316 {
01317         return mMinHeight;
01318 }
01319 
01320 void LLLayoutStack::addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, S32 index)
01321 {
01322         LLEmbeddedPanel* embedded_panel = new LLEmbeddedPanel(panel, mOrientation, min_width, min_height, auto_resize);
01323         
01324         mPanels.insert(mPanels.begin() + llclamp(index, 0, (S32)mPanels.size()), embedded_panel);
01325         addChild(panel);
01326         addChild(embedded_panel->mResizeBar);
01327 
01328         // bring all resize bars to the front so that they are clickable even over the panels
01329         // with a bit of overlap
01330         for (e_panel_list_t::iterator panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
01331         {
01332                 e_panel_list_t::iterator next_it = panel_it;
01333                 ++next_it;
01334 
01335                 LLResizeBar* resize_barp = (*panel_it)->mResizeBar;
01336                 sendChildToFront(resize_barp);
01337                 // last resize bar is disabled, since its not between any two panels
01338                 if ( next_it == mPanels.end() )
01339                 {
01340                         resize_barp->setEnabled(FALSE);
01341                 }
01342                 else
01343                 {
01344                         resize_barp->setEnabled(TRUE);
01345                 }
01346         }
01347 
01348         //updateLayout();
01349 }
01350 
01351 void LLLayoutStack::removePanel(LLPanel* panel)
01352 {
01353         removeChild(panel);
01354         //updateLayout();
01355 }
01356 
01357 void LLLayoutStack::updateLayout(BOOL force_resize)
01358 {
01359         calcMinExtents();
01360 
01361         // calculate current extents
01362         S32 cur_width = 0;
01363         S32 cur_height = 0;
01364 
01365         const F32 ANIM_OPEN_TIME = 0.02f;
01366         const F32 ANIM_CLOSE_TIME = 0.02f;
01367 
01368         e_panel_list_t::iterator panel_it;
01369         for (panel_it = mPanels.begin(); panel_it != mPanels.end();     ++panel_it)
01370         {
01371                 LLPanel* panelp = (*panel_it)->mPanel;
01372                 if (panelp->getVisible()) 
01373                 {
01374                         (*panel_it)->mVisibleAmt = lerp((*panel_it)->mVisibleAmt, 1.f, LLCriticalDamp::getInterpolant(ANIM_OPEN_TIME));
01375                         if ((*panel_it)->mVisibleAmt > 0.99f)
01376                         {
01377                                 (*panel_it)->mVisibleAmt = 1.f;
01378                         }
01379                 }
01380                 else // not visible
01381                 {
01382                         (*panel_it)->mVisibleAmt = lerp((*panel_it)->mVisibleAmt, 0.f, LLCriticalDamp::getInterpolant(ANIM_CLOSE_TIME));
01383                         if ((*panel_it)->mVisibleAmt < 0.001f)
01384                         {
01385                                 (*panel_it)->mVisibleAmt = 0.f;
01386                         }
01387                 }
01388                 if (mOrientation == HORIZONTAL)
01389                 {
01390                         // all panels get expanded to max of all the minimum dimensions
01391                         cur_height = llmax(mMinHeight, panelp->getRect().getHeight());
01392                 cur_width += llround(panelp->getRect().getWidth() * (*panel_it)->mVisibleAmt);
01393                         if (panel_it != mPanels.end())
01394                         {
01395                                 cur_width += PANEL_STACK_GAP;
01396                         }
01397                 }
01398                 else //VERTICAL
01399                 {
01400             cur_width = llmax(mMinWidth, panelp->getRect().getWidth());
01401                         cur_height += llround(panelp->getRect().getHeight() * (*panel_it)->mVisibleAmt);
01402                         if (panel_it != mPanels.end())
01403                         {
01404                                 cur_height += PANEL_STACK_GAP;
01405                         }
01406                 }
01407         }
01408 
01409         S32 num_resizable_panels = 0;
01410         S32 shrink_headroom_available = 0;
01411         S32 shrink_headroom_total = 0;
01412         for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
01413         {
01414                 // panels that are not fully visible do not count towards shrink headroom
01415                 if ((*panel_it)->mVisibleAmt < 1.f) 
01416                         continue;
01417                 // if currently resizing a panel or the panel is flagged as not automatically resizing
01418                 // only track total available headroom, but don't use it for automatic resize logic
01419                 if ((*panel_it)->mResizeBar->hasMouseCapture() || (!(*panel_it)->mAutoResize && !force_resize))
01420                 {
01421                         if (mOrientation == HORIZONTAL)
01422                         {
01423                                 shrink_headroom_total += (*panel_it)->mPanel->getRect().getWidth() - (*panel_it)->mMinWidth;
01424                         }
01425                         else //VERTICAL
01426                         {
01427                                 shrink_headroom_total += (*panel_it)->mPanel->getRect().getHeight() - (*panel_it)->mMinHeight;
01428                         }
01429                 }
01430                 else
01431                 {
01432                         num_resizable_panels++;
01433                         if (mOrientation == HORIZONTAL)
01434                         {
01435                                 shrink_headroom_available += (*panel_it)->mPanel->getRect().getWidth() - (*panel_it)->mMinWidth;
01436                                 shrink_headroom_total += (*panel_it)->mPanel->getRect().getWidth() - (*panel_it)->mMinWidth;
01437                         }
01438                         else //VERTICAL
01439                         {
01440                                 shrink_headroom_available += (*panel_it)->mPanel->getRect().getHeight() - (*panel_it)->mMinHeight;
01441                                 shrink_headroom_total += (*panel_it)->mPanel->getRect().getHeight() - (*panel_it)->mMinHeight;
01442                         }
01443                 }
01444         }
01445 
01446         // positive means panels need to grow, negative means shrink
01447         S32 pixels_to_distribute;
01448         if (mOrientation == HORIZONTAL)
01449         {
01450                 pixels_to_distribute = mRect.getWidth() - cur_width;
01451         }
01452         else //VERTICAL
01453         {
01454                 pixels_to_distribute = mRect.getHeight() - cur_height;
01455         }
01456 
01457         S32 cur_x = 0;
01458         S32 cur_y = mRect.getHeight();
01459 
01460         for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
01461         {
01462                 LLPanel* panelp = (*panel_it)->mPanel;
01463 
01464                 S32 cur_width = panelp->getRect().getWidth();
01465                 S32 cur_height = panelp->getRect().getHeight();
01466                 S32 new_width = llmax((*panel_it)->mMinWidth, cur_width);
01467                 S32 new_height = llmax((*panel_it)->mMinHeight, cur_height);
01468 
01469                 S32 delta_size = 0;
01470 
01471                 // if panel can automatically resize (not animating, and resize flag set)...
01472                 if ((*panel_it)->mVisibleAmt == 1.f && (force_resize || (*panel_it)->mAutoResize) && !(*panel_it)->mResizeBar->hasMouseCapture()) 
01473                 {
01474                         if (mOrientation == HORIZONTAL)
01475                         {
01476                                 // if we're shrinking
01477                                 if (pixels_to_distribute < 0)
01478                                 {
01479                                         // shrink proportionally to amount over minimum
01480                                         delta_size = llround((F32)pixels_to_distribute * (F32)(cur_width - (*panel_it)->mMinWidth) / (F32)shrink_headroom_available);
01481                                 }
01482                                 else
01483                                 {
01484                                         // grow all elements equally
01485                                         delta_size = llround((F32)pixels_to_distribute / (F32)num_resizable_panels);
01486                                 }
01487                                 new_width = llmax((*panel_it)->mMinWidth, panelp->getRect().getWidth() + delta_size);
01488                         }
01489                         else
01490                         {
01491                                 new_width = llmax(mMinWidth, mRect.getWidth());
01492                         }
01493 
01494                         if (mOrientation == VERTICAL)
01495                         {
01496                                 if (pixels_to_distribute < 0)
01497                                 {
01498                                         // shrink proportionally to amount over minimum
01499                                         delta_size = llround((F32)pixels_to_distribute * (F32)(cur_height - (*panel_it)->mMinHeight) / (F32)shrink_headroom_available);
01500                                 }
01501                                 else
01502                                 {
01503                                         delta_size = llround((F32)pixels_to_distribute / (F32)num_resizable_panels);
01504                                 }
01505                                 new_height = llmax((*panel_it)->mMinHeight, panelp->getRect().getHeight() + delta_size);
01506                         }
01507                         else
01508                         {
01509                                 new_height = llmax(mMinHeight, mRect.getHeight());
01510                         }
01511                 }
01512                 else // don't resize
01513                 {
01514                         if (mOrientation == HORIZONTAL)
01515                         {
01516                                 new_height = llmax(mMinHeight, mRect.getHeight());
01517                         }
01518                         else // VERTICAL
01519                         {
01520                                 new_width = llmax(mMinWidth, mRect.getWidth());
01521                         }
01522                 }
01523 
01524                 // adjust running headroom count based on new sizes
01525                 shrink_headroom_total += delta_size;
01526 
01527                 panelp->reshape(new_width, new_height);
01528                 panelp->setOrigin(cur_x, cur_y - new_height);
01529 
01530                 LLRect panel_rect = panelp->getRect();
01531                 LLRect resize_bar_rect = panel_rect;
01532                 if (mOrientation == HORIZONTAL)
01533                 {
01534                         resize_bar_rect.mLeft = panel_rect.mRight - RESIZE_BAR_OVERLAP;
01535                         resize_bar_rect.mRight = panel_rect.mRight + PANEL_STACK_GAP + RESIZE_BAR_OVERLAP;
01536                 }
01537                 else
01538                 {
01539                         resize_bar_rect.mTop = panel_rect.mBottom + RESIZE_BAR_OVERLAP;
01540                         resize_bar_rect.mBottom = panel_rect.mBottom - PANEL_STACK_GAP - RESIZE_BAR_OVERLAP;
01541                 }
01542                 (*panel_it)->mResizeBar->setRect(resize_bar_rect);
01543 
01544                 if (mOrientation == HORIZONTAL)
01545                 {
01546                         cur_x += llround(new_width * (*panel_it)->mVisibleAmt) + PANEL_STACK_GAP;
01547                 }
01548                 else //VERTICAL
01549                 {
01550                         cur_y -= llround(new_height * (*panel_it)->mVisibleAmt) + PANEL_STACK_GAP;
01551                 }
01552         }
01553 
01554         // update resize bars with new limits
01555         LLResizeBar* last_resize_bar = NULL;
01556         for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
01557         {
01558                 LLPanel* panelp = (*panel_it)->mPanel;
01559 
01560                 if (mOrientation == HORIZONTAL)
01561                 {
01562                         (*panel_it)->mResizeBar->setResizeLimits((*panel_it)->mMinWidth, (*panel_it)->mMinWidth + shrink_headroom_total);
01563                 }
01564                 else //VERTICAL
01565                 {
01566                         (*panel_it)->mResizeBar->setResizeLimits((*panel_it)->mMinHeight, (*panel_it)->mMinHeight + shrink_headroom_total);
01567                 }
01568                 // hide resize bars for invisible panels
01569                 (*panel_it)->mResizeBar->setVisible(panelp->getVisible());
01570                 if (panelp->getVisible())
01571                 {
01572                         last_resize_bar = (*panel_it)->mResizeBar;
01573                 }
01574         }
01575 
01576         // hide last resize bar as there is nothing past it
01577         if (last_resize_bar)
01578         {
01579                 last_resize_bar->setVisible(FALSE);
01580         }
01581 
01582         // not enough room to fit existing contents
01583         if (!force_resize && 
01584                 ((cur_y != -PANEL_STACK_GAP) || (cur_x != mRect.getWidth() + PANEL_STACK_GAP)))
01585         {
01586                 // do another layout pass with all stacked elements contributing
01587                 // even those that don't usually resize
01588                 llassert_always(force_resize == FALSE);
01589                 updateLayout(TRUE);
01590         }
01591 }
01592 
01593 LLLayoutStack::LLEmbeddedPanel* LLLayoutStack::findEmbeddedPanel(LLPanel* panelp)
01594 {
01595         e_panel_list_t::iterator panel_it;
01596         for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
01597         {
01598                 if ((*panel_it)->mPanel == panelp)
01599                 {
01600                         return *panel_it;
01601                 }
01602         }
01603         return NULL;
01604 }
01605 
01606 void LLLayoutStack::calcMinExtents()
01607 {
01608         mMinWidth = 0;
01609         mMinHeight = 0;
01610 
01611         e_panel_list_t::iterator panel_it;
01612         for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
01613         {
01614                 if (mOrientation == HORIZONTAL)
01615                 {
01616                         mMinHeight = llmax(mMinHeight, (*panel_it)->mMinHeight);
01617             mMinWidth += (*panel_it)->mMinWidth;
01618                         if (panel_it != mPanels.begin())
01619                         {
01620                                 mMinWidth += PANEL_STACK_GAP;
01621                         }
01622                 }
01623                 else //VERTICAL
01624                 {
01625             mMinWidth = llmax(mMinWidth, (*panel_it)->mMinWidth);
01626                         mMinHeight += (*panel_it)->mMinHeight;
01627                         if (panel_it != mPanels.begin())
01628                         {
01629                                 mMinHeight += PANEL_STACK_GAP;
01630                         }
01631                 }
01632         }
01633 }

Generated on Thu Jul 1 06:08:55 2010 for Second Life Viewer by  doxygen 1.4.7