llpanelgroup.cpp

Go to the documentation of this file.
00001 
00031 #include "llviewerprecompiledheaders.h"
00032 
00033 #include "llpanelgroup.h"
00034 
00035 #include "llagent.h"
00036 #include "llbutton.h"
00037 #include "llpanelgroupgeneral.h"
00038 #include "llpanelgrouproles.h"
00039 #include "llpanelgroupvoting.h"
00040 #include "llpanelgrouplandmoney.h"
00041 #include "llpanelgroupnotices.h"
00042 #include "lltabcontainer.h"
00043 #include "lltextbox.h"
00044 #include "llviewermessage.h"
00045 #include "llvieweruictrlfactory.h"
00046 #include "llviewerwindow.h"
00047 #include "viewer.h"
00048 
00049 // static
00050 void* LLPanelGroupTab::createTab(void* data)
00051 {
00052         LLUUID* group_id = static_cast<LLUUID*>(data);
00053         return new LLPanelGroupTab("panel group tab", *group_id);
00054 }
00055 
00056 LLPanelGroupTab::~LLPanelGroupTab()
00057 {
00058         mObservers.clear();
00059 }
00060 
00061 BOOL LLPanelGroupTab::isVisibleByAgent(LLAgent* agentp)
00062 {
00063         //default to being visible
00064         return TRUE;
00065 }
00066 
00067 BOOL LLPanelGroupTab::postBuild()
00068 {
00069         // Hook up the help button callback.
00070         LLButton* button = (LLButton*) getChildByName("help_button");
00071         if (button)
00072         {
00073                 button->setClickedCallback(onClickHelp);
00074                 button->setCallbackUserData(this);
00075         }
00076 
00077         // Read help text from the xml file.
00078         LLTextBox* txt;
00079         // Don't recurse for this, since we don't currently have a recursive removeChild()
00080         txt = (LLTextBox*) getChildByName("help_text");
00081         if (txt)
00082         {
00083                 mHelpText = txt->getText();
00084                 removeChild(txt, TRUE);
00085         }
00086         return TRUE;
00087 }
00088 
00089 void LLPanelGroupTab::addObserver(LLPanelGroupTabObserver *obs)
00090 {
00091         mObservers.insert(obs);
00092 }
00093 
00094 void LLPanelGroupTab::removeObserver(LLPanelGroupTabObserver *obs)
00095 {
00096         mObservers.erase(obs);
00097 }
00098 
00099 void LLPanelGroupTab::notifyObservers()
00100 {
00101 
00102         for (observer_list_t::iterator iter = mObservers.begin();
00103                  iter != mObservers.end(); )
00104         {
00105                 LLPanelGroupTabObserver* observer = *iter;
00106                 observer->tabChanged();
00107 
00108                 // safe way to incrament since changed may delete entries! (@!##%@!@&*!)
00109                 iter = mObservers.upper_bound(observer); 
00110         }
00111 }
00112 
00113 // static
00114 void LLPanelGroupTab::onClickHelp(void* user_data)
00115 {
00116         LLPanelGroupTab* self = static_cast<LLPanelGroupTab*>(user_data);
00117         self->handleClickHelp();
00118 }
00119 
00120 void LLPanelGroupTab::handleClickHelp()
00121 {
00122         // Display the help text.
00123         LLString help_text( getHelpText() );
00124         if ( !help_text.empty() )
00125         {
00126                 LLString::format_map_t args;
00127                 args["[MESSAGE]"] = help_text;
00128                 LLAlertDialog* dialogp = gViewerWindow->alertXml("GenericAlert", args);
00129                 if (dialogp)
00130                 {
00131                         LLFloater* root_floater = gFloaterView->getParentFloater(this);;
00132                         if (root_floater)
00133                         {
00134                                 root_floater->addDependentFloater(dialogp);
00135                         }
00136                 }
00137         }
00138 }
00139 
00140 LLPanelGroup::LLPanelGroup(const std::string& filename,
00141                                                    const std::string& name,
00142                                                    const LLUUID& group_id,
00143                                                    const std::string& initial_tab_selected)
00144 :       LLPanel(name, LLRect(), FALSE),
00145         LLGroupMgrObserver( group_id ),
00146         mCurrentTab( NULL ),
00147         mRequestedTab( NULL ),
00148         mTabContainer( NULL ),
00149         mIgnoreTransition( FALSE ),
00150         mForceClose( FALSE ),
00151         mInitialTab(initial_tab_selected),
00152         mAllowEdit( TRUE ),
00153         mShowingNotifyDialog( FALSE )
00154 {
00155         // Set up the factory callbacks.
00156         mFactoryMap["general_tab"]      = LLCallbackMap(LLPanelGroupGeneral::createTab,
00157                                                                                                 &mID);
00158         mFactoryMap["roles_tab"]        = LLCallbackMap(LLPanelGroupRoles::createTab,
00159                                                                                                 &mID);
00160         mFactoryMap["notices_tab"]      = LLCallbackMap(LLPanelGroupNotices::createTab,
00161                                                                                                 &mID);
00162         mFactoryMap["voting_tab"]       = LLCallbackMap(LLPanelGroupVoting::createTab,
00163                                                                                                 &mID);
00164         mFactoryMap["land_money_tab"]= LLCallbackMap(LLPanelGroupLandMoney::createTab,
00165                                                                                                  &mID);
00166         // Roles sub tabs
00167         mFactoryMap["members_sub_tab"] = LLCallbackMap(LLPanelGroupMembersSubTab::createTab, &mID);
00168         mFactoryMap["roles_sub_tab"] = LLCallbackMap(LLPanelGroupRolesSubTab::createTab, &mID);
00169         mFactoryMap["actions_sub_tab"] = LLCallbackMap(LLPanelGroupActionsSubTab::createTab, &mID);
00170 
00171         gGroupMgr->addObserver(this);
00172 
00173         // Pass on construction of this panel to the control factory.
00174         gUICtrlFactory->buildPanel(this, filename, &getFactoryMap());
00175         mFilename = filename;
00176 }
00177 
00178 LLPanelGroup::~LLPanelGroup()
00179 {
00180         gGroupMgr->removeObserver(this);
00181 
00182         int i;
00183         int tab_count = mTabContainer->getTabCount();
00184 
00185         for (i = tab_count - 1; i >=0; --i)
00186         {
00187                 LLPanelGroupTab* panelp =
00188                         (LLPanelGroupTab*) mTabContainer->getPanelByIndex(i);
00189 
00190                 if ( panelp ) panelp->removeObserver(this);
00191         }
00192 }
00193 
00194 void LLPanelGroup::updateTabVisibility()
00195 {
00196         S32 i;
00197         S32 tab_count = mTabContainer->getTabCount();
00198 
00199         for (i = tab_count - 1; i >=0; --i)
00200         {
00201                 LLPanelGroupTab* panelp =
00202                         (LLPanelGroupTab*) mTabContainer->getPanelByIndex(i);
00203 
00204                 BOOL visible = panelp->isVisibleByAgent(&gAgent);
00205                 mTabContainer->enableTabButton(i, visible);
00206 
00207                 if ( !visible && mCurrentTab == panelp )
00208                 {
00209                         //we are disabling the currently selected tab
00210                         //select the previous one
00211                         mTabContainer->selectPrevTab();
00212                         mCurrentTab = 
00213                                 (LLPanelGroupTab*) mTabContainer->getCurrentPanel();
00214                 }
00215         }
00216 }
00217 
00218 
00219 
00220 BOOL LLPanelGroup::postBuild()
00221 {
00222         mTabContainer = (LLTabContainerCommon*) getChildByName("group_tab_container");
00223 
00224         if (mTabContainer)
00225         {
00226                 // Select the initial tab specified via constructor
00227                 const BOOL recurse = TRUE;
00228                 LLPanelGroupTab* tabp = 
00229                         (LLPanelGroupTab*) getChildByName(mInitialTab, recurse);
00230 
00231                 if (!tabp)
00232                 {
00233                         //our initial tab selection was invalid, just select the
00234                         //first tab then or default to selecting the initial
00235                         //selected tab specified in the layout file
00236                         tabp = (LLPanelGroupTab*) mTabContainer->getCurrentPanel();
00237 
00238                         //no tab was initially selected through constructor
00239                         //or the XML, select the first tab
00240                         if (!tabp)
00241                         {
00242                                 mTabContainer->selectFirstTab();
00243                                 tabp = (LLPanelGroupTab*) mTabContainer->getCurrentPanel();
00244                         }
00245                 }
00246                 else
00247                 {
00248                         mTabContainer->selectTabPanel(tabp);
00249                 }
00250 
00251                 mCurrentTab = tabp;
00252 
00253                 // Add click callbacks.
00254                 S32 i;
00255                 S32 tab_count = mTabContainer->getTabCount();
00256 
00257                 for (i = tab_count - 1; i >=0; --i)
00258                 {
00259                         LLPanel* tab_panel = mTabContainer->getPanelByIndex(i);
00260                         LLPanelGroupTab* panelp =(LLPanelGroupTab*)tab_panel; // bit of a hack
00261 
00262                         // Pass on whether or not to allow edit to tabs.
00263                         panelp->setAllowEdit(mAllowEdit);
00264                         panelp->addObserver(this);
00265 
00266                         mTabContainer->setTabChangeCallback(panelp, onClickTab);
00267                         mTabContainer->setTabUserData(panelp, this);
00268                 }
00269                 updateTabVisibility();
00270 
00271                 // Act as though this tab was just activated.
00272                 mCurrentTab->activate();
00273         }
00274 
00275         // Read apply text from the xml file.
00276         LLTextBox* txt;
00277         // Don't recurse for this, since we don't currently have a recursive removeChild()
00278         txt = (LLTextBox*)getChildByName("default_needs_apply_text");
00279         if (txt)
00280         {
00281                 mDefaultNeedsApplyMesg = txt->getText();
00282                 removeChild(txt, TRUE);
00283         }
00284         txt = (LLTextBox*)getChildByName("want_apply_text");
00285         if (txt)
00286         {
00287                 mWantApplyMesg = txt->getText();
00288                 removeChild(txt, TRUE);
00289         }
00290 
00291         LLButton* button = (LLButton*) getChildByName("btn_ok");
00292         if (button)
00293         {
00294                 button->setClickedCallback(onBtnOK);
00295                 button->setCallbackUserData(this);
00296                 button->setVisible(mAllowEdit);
00297         }
00298         
00299         button = (LLButton*) getChildByName("btn_cancel");
00300         if (button)
00301         {
00302                 button->setClickedCallback(onBtnCancel);
00303                 button->setCallbackUserData(this);
00304                 button->setVisible(mAllowEdit);
00305         }
00306 
00307         button = (LLButton*) getChildByName("btn_apply");
00308         if (button)
00309         {
00310                 button->setClickedCallback(onBtnApply);
00311                 button->setVisible(mAllowEdit);
00312                 button->setEnabled(FALSE);
00313 
00314                 mApplyBtn = button;
00315         }
00316 
00317         button = (LLButton*) getChildByName("btn_refresh");
00318         if (button)
00319         {
00320                 button->setClickedCallback(onBtnRefresh);
00321                 button->setCallbackUserData(this);
00322                 button->setVisible(mAllowEdit);
00323         }
00324 
00325         return TRUE;
00326 }
00327 
00328 void LLPanelGroup::changed(LLGroupChange gc)
00329 {
00330         updateTabVisibility();
00331         // Notify the currently active panel that group manager information has changed.
00332         LLPanelGroupTab* panelp = (LLPanelGroupTab*) mTabContainer->getCurrentPanel();
00333 
00334         if (panelp)
00335         {
00336                 panelp->update(gc);
00337         }
00338 }
00339 
00340 // PanelGroupTab observer trigger
00341 void LLPanelGroup::tabChanged()
00342 {
00343         //some tab information has changed,....enable/disable the apply button
00344         //based on if they need an apply
00345         if ( mApplyBtn )
00346         {
00347                 LLString mesg;
00348                 mApplyBtn->setEnabled(mCurrentTab->needsApply(mesg));
00349         }
00350 }
00351 
00352 // static
00353 void LLPanelGroup::onClickTab(void* user_data, bool from_click)
00354 {
00355         LLPanelGroup* self = static_cast<LLPanelGroup*>(user_data);
00356         self->handleClickTab();
00357 }
00358 
00359 void LLPanelGroup::handleClickTab()
00360 {
00361         // If we are already handling a transition,
00362         // ignore this.
00363         if (mIgnoreTransition)
00364         {
00365                 return;
00366         }
00367 
00368         mRequestedTab = (LLPanelGroupTab*) mTabContainer->getCurrentPanel();
00369 
00370         // Make sure they aren't just clicking the same tab...
00371         if (mRequestedTab == mCurrentTab)
00372         {
00373                 return;
00374         }
00375 
00376         // Try to switch from the current panel to the panel the user selected.
00377         attemptTransition();
00378 }
00379 
00380 void LLPanelGroup::setGroupID(const LLUUID& group_id)
00381 {
00382         LLRect rect(getRect());
00383 
00384         gGroupMgr->removeObserver(this);
00385         mID = group_id;
00386         gGroupMgr->addObserver(this);
00387         //TODO:  this is really bad, we should add a method
00388         // where the panels can just update themselves
00389         // on a group id change.  Similar to update() but with a group
00390         // id change.
00391 
00392         // For now, rebuild panel
00393         //delete children and rebuild panel
00394         deleteAllChildren();
00395         gUICtrlFactory->buildPanel(this, mFilename, &getFactoryMap());
00396 }
00397 
00398 void LLPanelGroup::selectTab(std::string tab_name)
00399 {
00400         const BOOL recurse = TRUE;
00401 
00402         LLPanelGroupTab* tabp = 
00403                 (LLPanelGroupTab*) getChildByName(tab_name, recurse);
00404 
00405         if ( tabp && mTabContainer )
00406         {
00407                 mTabContainer->selectTabPanel(tabp);
00408                 onClickTab(this, false);
00409         }
00410 }
00411 
00412 BOOL LLPanelGroup::canClose()
00413 {
00414         if (mShowingNotifyDialog) return FALSE;
00415         if (mCurrentTab && mCurrentTab->hasModal()) return FALSE;
00416         if (mForceClose || !mAllowEdit) return TRUE;
00417 
00418         // Try to switch from the current panel to nothing, indicating a close action.
00419         mRequestedTab = NULL;
00420         return attemptTransition();
00421 }
00422 
00423 BOOL LLPanelGroup::attemptTransition()
00424 {
00425         // Check if the current tab needs to be applied.
00426         LLString mesg;
00427         if (mCurrentTab && mCurrentTab->needsApply(mesg))
00428         {
00429                 // If no message was provided, give a generic one.
00430                 if (mesg.empty())
00431                 {
00432                         mesg = mDefaultNeedsApplyMesg;
00433                 }
00434                 // Create a notify box, telling the user about the unapplied tab.
00435                 LLString::format_map_t args;
00436                 args["[NEEDS_APPLY_MESSAGE]"] = mesg;
00437                 args["[WANT_APPLY_MESSAGE]"] = mWantApplyMesg;
00438                 gViewerWindow->alertXml("PanelGroupApply", args,
00439                                                                 onNotifyCallback, (void*) this);
00440                 mShowingNotifyDialog = TRUE;
00441                 
00442                 // We need to reselect the current tab, since it isn't finished.
00443                 if (mTabContainer)
00444                 {
00445                         // selectTabPanel is going to trigger another
00446                         // click event.  We want to ignore it so that
00447                         // mRequestedTab is not updated.
00448                         mIgnoreTransition = TRUE;
00449                         mTabContainer->selectTabPanel( mCurrentTab );
00450                         mIgnoreTransition = FALSE;
00451                 }
00452                 // Returning FALSE will block a close action from finishing until
00453                 // we get a response back from the user.
00454                 return FALSE;
00455         }
00456         else
00457         {
00458                 // The current panel didn't have anything it needed to apply.
00459                 if ( mRequestedTab )
00460                 {
00461                         transitionToTab();
00462                 }
00463                 // Returning TRUE will allow any close action to proceed.
00464                 return TRUE;
00465         }
00466 }
00467 
00468 void LLPanelGroup::transitionToTab()
00469 {
00470         // Tell the current panel that it is being deactivated.
00471         if (mCurrentTab)
00472         {
00473                 mCurrentTab->deactivate();
00474         }
00475         
00476         // If the requested panel exists, activate it.
00477         if (mRequestedTab)
00478         {
00479                 // This is now the current tab;
00480                 mCurrentTab = mRequestedTab;
00481                 mCurrentTab->activate();
00482         }
00483         else // NULL requested indicates a close action.
00484         {
00485                 close();
00486         }
00487 }
00488 
00489 // static
00490 void LLPanelGroup::onNotifyCallback(S32 option, void* user_data)
00491 {
00492         LLPanelGroup* self = static_cast<LLPanelGroup*>(user_data);
00493         if (self)
00494         {
00495                 self->handleNotifyCallback(option);
00496         }
00497 }
00498 
00499 void LLPanelGroup::handleNotifyCallback(S32 option)
00500 {
00501         mShowingNotifyDialog = FALSE;
00502         switch (option)
00503         {
00504         case 0: // "Apply Changes"
00505                 // Try to apply changes, and switch to the requested tab.
00506                 if ( !apply() )
00507                 {
00508                         // There was a problem doing the apply.
00509                         // Skip switching tabs.
00510                         break;
00511                 }
00512 
00513                 // This panel's info successfully applied.
00514                 // Switch to the next panel.
00515                 mIgnoreTransition = TRUE;
00516                 mTabContainer->selectTabPanel( mRequestedTab );
00517                 mIgnoreTransition = FALSE;
00518                 transitionToTab();
00519                 break;
00520         case 1: // "Ignore Changes"
00521                 // Switch to the requested panel without applying changes
00522                 // (Changes may already have been applied in the previous block)
00523                 mCurrentTab->cancel();
00524                 mIgnoreTransition = TRUE;
00525                 mTabContainer->selectTabPanel( mRequestedTab );
00526                 mIgnoreTransition = FALSE;
00527                 transitionToTab();
00528                 break;
00529         case 2: // "Cancel"
00530         default:
00531                 // Do nothing.  The user is canceling the action.
00532                 // If we were quitting, we didn't really mean it.
00533                 app_abort_quit();
00534                 break;
00535         }
00536 }
00537 
00538 // static
00539 void LLPanelGroup::onBtnOK(void* user_data)
00540 {
00541         LLPanelGroup* self = static_cast<LLPanelGroup*>(user_data);
00542         // If we are able to apply changes, then close.
00543         if(self->apply())
00544         {
00545                 self->close();
00546         }
00547 }
00548 
00549 // static
00550 void LLPanelGroup::onBtnCancel(void* user_data)
00551 {
00552         LLPanelGroup* self = static_cast<LLPanelGroup*>(user_data);
00553         self->close();
00554 }
00555 
00556 // static
00557 void LLPanelGroup::onBtnApply(void* user_data)
00558 {
00559         LLPanelGroup* self = static_cast<LLPanelGroup*>(user_data);
00560         self->apply();
00561 }
00562 
00563 bool LLPanelGroup::apply()
00564 {
00565         // Pass this along to the currently visible tab.
00566         if (!mTabContainer) return false;
00567 
00568         LLPanelGroupTab* panelp = (LLPanelGroupTab*) mTabContainer->getCurrentPanel();
00569         if (!panelp) return false;
00570         
00571         LLString mesg;
00572         if ( !panelp->needsApply(mesg) )
00573         {
00574                 // We don't need to apply anything.
00575                 // We're done.
00576                 return true;
00577         }
00578 
00579         // Ignore the needs apply message.
00580         // Try to do the actual apply.
00581         LLString apply_mesg;
00582         if ( panelp->apply( apply_mesg ) )
00583         {
00584                 // Everything worked.  We're done.
00585                 return true;
00586         }
00587 
00588         // There was a problem doing the actual apply.
00589         // Inform the user.
00590         if ( !apply_mesg.empty() )
00591         {
00592                 LLString::format_map_t args;
00593                 args["[MESSAGE]"] = apply_mesg;
00594                 gViewerWindow->alertXml("GenericAlert", args);
00595         }
00596 
00597         return false;
00598 }
00599 
00600 // static
00601 void LLPanelGroup::onBtnRefresh(void* user_data)
00602 {
00603         LLPanelGroup* self = static_cast<LLPanelGroup*>(user_data);
00604         self->refreshData();
00605 }
00606 
00607 // virtual
00608 void LLPanelGroup::draw()
00609 {
00610         LLPanel::draw();
00611 
00612         if (mRefreshTimer.hasExpired())
00613         {
00614                 mRefreshTimer.stop();
00615                 childEnable("btn_refresh");
00616         }
00617         if (mCurrentTab)
00618         {
00619                 LLString mesg;
00620                 childSetEnabled("btn_apply", mCurrentTab->needsApply(mesg));
00621         }
00622 
00623 }
00624 
00625 void LLPanelGroup::refreshData()
00626 {
00627         gGroupMgr->clearGroupData(getID());
00628         mCurrentTab->activate();
00629 
00630         // 5 second timeout
00631         childDisable("btn_refresh");
00632         mRefreshTimer.start();
00633         mRefreshTimer.setTimerExpirySec(5);
00634 }
00635 
00636 void LLPanelGroup::close()
00637 {
00638         // Pass this to the parent, if it is a floater.
00639         LLView* viewp = getParent();
00640         if (viewp
00641                 && WIDGET_TYPE_FLOATER == viewp->getWidgetType())
00642         {
00643                 // First, set the force close flag, since the floater
00644                 // will be asking us whether it can close.
00645                 mForceClose = TRUE;
00646                 // Tell the parent floater to close.
00647                 LLFloater* floaterp = (LLFloater*) viewp;
00648                 floaterp->close();
00649         }
00650 }
00651 
00652 void LLPanelGroup::showNotice(const char* subject,
00653                                                         const char* message,
00654                                                         const bool& has_inventory,
00655                                                         const char* inventory_name,
00656                                                         LLOfferInfo* inventory_offer)
00657 {
00658         if (mCurrentTab->getName() != "notices_tab")
00659         {
00660                 // We need to clean up that inventory offer.
00661                 if (inventory_offer)
00662                 {
00663                         inventory_offer_callback( IOR_DECLINE , inventory_offer); 
00664                 }
00665                 return;
00666         }
00667 
00668         LLPanelGroupNotices* notices = static_cast<LLPanelGroupNotices*>(mCurrentTab);
00669 
00670         notices->showNotice(subject,message,has_inventory,inventory_name,inventory_offer);
00671 }

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