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

Generated on Fri May 16 08:33:52 2008 for SecondLife by  doxygen 1.5.5