aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llpanelgroup.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llpanelgroup.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to '')
-rw-r--r--linden/indra/newview/llpanelgroup.cpp670
1 files changed, 670 insertions, 0 deletions
diff --git a/linden/indra/newview/llpanelgroup.cpp b/linden/indra/newview/llpanelgroup.cpp
new file mode 100644
index 0000000..8a44da5
--- /dev/null
+++ b/linden/indra/newview/llpanelgroup.cpp
@@ -0,0 +1,670 @@
1/**
2 * @file llpanelgroup.cpp
3 *
4 * Copyright (c) 2006-2007, Linden Research, Inc.
5 *
6 * The source code in this file ("Source Code") is provided by Linden Lab
7 * to you under the terms of the GNU General Public License, version 2.0
8 * ("GPL"), unless you have obtained a separate licensing agreement
9 * ("Other License"), formally executed by you and Linden Lab. Terms of
10 * the GPL can be found in doc/GPL-license.txt in this distribution, or
11 * online at http://secondlife.com/developers/opensource/gplv2
12 *
13 * There are special exceptions to the terms and conditions of the GPL as
14 * it is applied to this Source Code. View the full text of the exception
15 * in the file doc/FLOSS-exception.txt in this software distribution, or
16 * online at http://secondlife.com/developers/opensource/flossexception
17 *
18 * By copying, modifying or distributing this software, you acknowledge
19 * that you have read and understood your obligations described above,
20 * and agree to abide by those obligations.
21 *
22 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
23 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
24 * COMPLETENESS OR PERFORMANCE.
25 */
26
27#include "llviewerprecompiledheaders.h"
28
29#include "llpanelgroup.h"
30
31#include "llagent.h"
32#include "llbutton.h"
33#include "llpanelgroupgeneral.h"
34#include "llpanelgrouproles.h"
35#include "llpanelgroupvoting.h"
36#include "llpanelgrouplandmoney.h"
37#include "llpanelgroupnotices.h"
38#include "lltabcontainer.h"
39#include "lltextbox.h"
40#include "llviewermessage.h"
41#include "llvieweruictrlfactory.h"
42#include "llviewerwindow.h"
43#include "viewer.h"
44
45// static
46void* LLPanelGroupTab::createTab(void* data)
47{
48 LLUUID* group_id = static_cast<LLUUID*>(data);
49 return new LLPanelGroupTab("panel group tab", *group_id);
50}
51
52LLPanelGroupTab::~LLPanelGroupTab()
53{
54 mObservers.clear();
55}
56
57BOOL LLPanelGroupTab::isVisibleByAgent(LLAgent* agentp)
58{
59 //default to being visible
60 return TRUE;
61}
62
63BOOL LLPanelGroupTab::postBuild()
64{
65 // Hook up the help button callback.
66 LLButton* button = (LLButton*) getChildByName("help_button");
67 if (button)
68 {
69 button->setClickedCallback(onClickHelp);
70 button->setCallbackUserData(this);
71 }
72
73 // Read help text from the xml file.
74 LLTextBox* txt;
75 // Don't recurse for this, since we don't currently have a recursive removeChild()
76 txt = (LLTextBox*) getChildByName("help_text");
77 if (txt)
78 {
79 mHelpText = txt->getText();
80 removeChild(txt);
81 }
82 return TRUE;
83}
84
85void LLPanelGroupTab::addObserver(LLPanelGroupTabObserver *obs)
86{
87 mObservers.insert(obs);
88}
89
90void LLPanelGroupTab::removeObserver(LLPanelGroupTabObserver *obs)
91{
92 mObservers.erase(obs);
93}
94
95void LLPanelGroupTab::notifyObservers()
96{
97
98 for (observer_list_t::iterator iter = mObservers.begin();
99 iter != mObservers.end(); )
100 {
101 LLPanelGroupTabObserver* observer = *iter;
102 observer->tabChanged();
103
104 // safe way to incrament since changed may delete entries! (@!##%@!@&*!)
105 iter = mObservers.upper_bound(observer);
106 }
107}
108
109// static
110void LLPanelGroupTab::onClickHelp(void* user_data)
111{
112 LLPanelGroupTab* self = static_cast<LLPanelGroupTab*>(user_data);
113 self->handleClickHelp();
114}
115
116void LLPanelGroupTab::handleClickHelp()
117{
118 // Display the help text.
119 LLString help_text( getHelpText() );
120 if ( !help_text.empty() )
121 {
122 LLString::format_map_t args;
123 args["[MESSAGE]"] = help_text;
124 LLAlertDialog* dialogp = gViewerWindow->alertXml("GenericAlert", args);
125 if (dialogp)
126 {
127 LLView* viewp = this;
128 LLFloater* root_floater = NULL;
129 while(viewp)
130 {
131 if(viewp->getWidgetType() == WIDGET_TYPE_FLOATER)
132 {
133 root_floater = (LLFloater*)viewp;
134 }
135 viewp = viewp->getParent();
136 }
137 if (root_floater)
138 {
139 root_floater->addDependentFloater(dialogp);
140 }
141 }
142 }
143}
144
145LLPanelGroup::LLPanelGroup(const std::string& filename,
146 const std::string& name,
147 const LLUUID& group_id,
148 const std::string& initial_tab_selected)
149: LLPanel(name, LLRect(), FALSE),
150 LLGroupMgrObserver( group_id ),
151 mCurrentTab( NULL ),
152 mRequestedTab( NULL ),
153 mTabContainer( NULL ),
154 mForceClose( FALSE ),
155 mIgnoreTransition( FALSE ),
156 mInitialTab(initial_tab_selected),
157 mAllowEdit( TRUE ),
158 mShowingNotifyDialog( FALSE )
159{
160 // Set up the factory callbacks.
161 mFactoryMap["general_tab"] = LLCallbackMap(LLPanelGroupGeneral::createTab,
162 &mID);
163 mFactoryMap["roles_tab"] = LLCallbackMap(LLPanelGroupRoles::createTab,
164 &mID);
165 mFactoryMap["notices_tab"] = LLCallbackMap(LLPanelGroupNotices::createTab,
166 &mID);
167 mFactoryMap["voting_tab"] = LLCallbackMap(LLPanelGroupVoting::createTab,
168 &mID);
169 mFactoryMap["land_money_tab"]= LLCallbackMap(LLPanelGroupLandMoney::createTab,
170 &mID);
171 // Roles sub tabs
172 mFactoryMap["members_sub_tab"] = LLCallbackMap(LLPanelGroupMembersSubTab::createTab, &mID);
173 mFactoryMap["roles_sub_tab"] = LLCallbackMap(LLPanelGroupRolesSubTab::createTab, &mID);
174 mFactoryMap["actions_sub_tab"] = LLCallbackMap(LLPanelGroupActionsSubTab::createTab, &mID);
175
176 // Pass on construction of this panel to the control factory.
177 gUICtrlFactory->buildPanel(this, filename, &getFactoryMap());
178 mFilename = filename;
179
180 gGroupMgr->addObserver(this);
181}
182
183LLPanelGroup::~LLPanelGroup()
184{
185 gGroupMgr->removeObserver(this);
186
187 int i;
188 int tab_count = mTabContainer->getTabCount();
189
190 for (i = tab_count - 1; i >=0; --i)
191 {
192 LLPanelGroupTab* panelp =
193 (LLPanelGroupTab*) mTabContainer->getPanelByIndex(i);
194
195 if ( panelp ) panelp->removeObserver(this);
196 }
197}
198
199void LLPanelGroup::updateTabVisibility()
200{
201 S32 i;
202 S32 tab_count = mTabContainer->getTabCount();
203
204 for (i = tab_count - 1; i >=0; --i)
205 {
206 LLPanelGroupTab* panelp =
207 (LLPanelGroupTab*) mTabContainer->getPanelByIndex(i);
208
209 BOOL visible = panelp->isVisibleByAgent(&gAgent);
210 mTabContainer->enableTabButton(i, visible);
211
212 if ( !visible && mCurrentTab == panelp )
213 {
214 //we are disabling the currently selected tab
215 //select the previous one
216 mTabContainer->selectPrevTab();
217 mCurrentTab =
218 (LLPanelGroupTab*) mTabContainer->getCurrentPanel();
219 }
220 }
221}
222
223
224
225BOOL LLPanelGroup::postBuild()
226{
227 mTabContainer = (LLTabContainerCommon*) getChildByName("group_tab_container");
228
229 if (mTabContainer)
230 {
231 // Select the initial tab specified via constructor
232 const BOOL recurse = TRUE;
233 LLPanelGroupTab* tabp =
234 (LLPanelGroupTab*) getChildByName(mInitialTab, recurse);
235
236 if (!tabp)
237 {
238 //our initial tab selection was invalid, just select the
239 //first tab then or default to selecting the initial
240 //selected tab specified in the layout file
241 tabp = (LLPanelGroupTab*) mTabContainer->getCurrentPanel();
242
243 //no tab was initially selected through constructor
244 //or the XML, select the first tab
245 if (!tabp)
246 {
247 mTabContainer->selectFirstTab();
248 tabp = (LLPanelGroupTab*) mTabContainer->getCurrentPanel();
249 }
250 }
251 else
252 {
253 mTabContainer->selectTabPanel(tabp);
254 }
255
256 mCurrentTab = tabp;
257
258 // Add click callbacks.
259 S32 i;
260 S32 tab_count = mTabContainer->getTabCount();
261
262 for (i = tab_count - 1; i >=0; --i)
263 {
264 LLPanel* tab_panel = mTabContainer->getPanelByIndex(i);
265 LLPanelGroupTab* panelp =(LLPanelGroupTab*)tab_panel; // bit of a hack
266
267 // Pass on whether or not to allow edit to tabs.
268 panelp->setAllowEdit(mAllowEdit);
269 panelp->addObserver(this);
270
271 mTabContainer->setTabChangeCallback(panelp, onClickTab);
272 mTabContainer->setTabUserData(panelp, this);
273 }
274 updateTabVisibility();
275
276 // Act as though this tab was just activated.
277 mCurrentTab->activate();
278 }
279
280 // Read apply text from the xml file.
281 LLTextBox* txt;
282 // Don't recurse for this, since we don't currently have a recursive removeChild()
283 txt = (LLTextBox*)getChildByName("default_needs_apply_text");
284 if (txt)
285 {
286 mDefaultNeedsApplyMesg = txt->getText();
287 removeChild(txt);
288 }
289 txt = (LLTextBox*)getChildByName("want_apply_text");
290 if (txt)
291 {
292 mWantApplyMesg = txt->getText();
293 removeChild(txt);
294 }
295
296 LLButton* button = (LLButton*) getChildByName("btn_ok");
297 if (button)
298 {
299 button->setClickedCallback(onBtnOK);
300 button->setCallbackUserData(this);
301 button->setVisible(mAllowEdit);
302 }
303
304 button = (LLButton*) getChildByName("btn_cancel");
305 if (button)
306 {
307 button->setClickedCallback(onBtnCancel);
308 button->setCallbackUserData(this);
309 button->setVisible(mAllowEdit);
310 }
311
312 button = (LLButton*) getChildByName("btn_apply");
313 if (button)
314 {
315 button->setClickedCallback(onBtnApply);
316 button->setVisible(mAllowEdit);
317 button->setEnabled(FALSE);
318
319 mApplyBtn = button;
320 }
321
322 button = (LLButton*) getChildByName("btn_refresh");
323 if (button)
324 {
325 button->setClickedCallback(onBtnRefresh);
326 button->setCallbackUserData(this);
327 button->setVisible(mAllowEdit);
328 }
329
330 return TRUE;
331}
332
333void LLPanelGroup::changed(LLGroupChange gc)
334{
335 updateTabVisibility();
336 // Notify the currently active panel that group manager information has changed.
337 LLPanelGroupTab* panelp = (LLPanelGroupTab*) mTabContainer->getCurrentPanel();
338
339 if (panelp)
340 {
341 panelp->update(gc);
342 }
343}
344
345// PanelGroupTab observer trigger
346void LLPanelGroup::tabChanged()
347{
348 //some tab information has changed,....enable/disable the apply button
349 //based on if they need an apply
350 if ( mApplyBtn )
351 {
352 LLString mesg;
353 mApplyBtn->setEnabled(mAllowEdit && mCurrentTab->needsApply(mesg));
354 }
355}
356
357// static
358void LLPanelGroup::onClickTab(void* user_data, bool from_click)
359{
360 LLPanelGroup* self = static_cast<LLPanelGroup*>(user_data);
361 self->handleClickTab();
362}
363
364void LLPanelGroup::handleClickTab()
365{
366 // If we are already handling a transition,
367 // ignore this.
368 if (mIgnoreTransition)
369 {
370 return;
371 }
372
373 mRequestedTab = (LLPanelGroupTab*) mTabContainer->getCurrentPanel();
374
375 // Make sure they aren't just clicking the same tab...
376 if (mRequestedTab == mCurrentTab)
377 {
378 return;
379 }
380
381 // Try to switch from the current panel to the panel the user selected.
382 attemptTransition();
383}
384
385void LLPanelGroup::setGroupID(const LLUUID& group_id)
386{
387 LLRect rect(getRect());
388
389 gGroupMgr->removeObserver(this);
390 mID = group_id;
391 gGroupMgr->addObserver(this);
392 //TODO: this is really bad, we should add a method
393 // where the panels can just update themselves
394 // on a group id change. Similar to update() but with a group
395 // id change.
396
397 // For now, rebuild panel
398 //delete children and rebuild panel
399 deleteAllChildren();
400 gUICtrlFactory->buildPanel(this, mFilename, &getFactoryMap());
401}
402
403void LLPanelGroup::selectTab(std::string tab_name)
404{
405 const BOOL recurse = TRUE;
406
407 LLPanelGroupTab* tabp =
408 (LLPanelGroupTab*) getChildByName(tab_name, recurse);
409
410 if ( tabp && mTabContainer )
411 {
412 mTabContainer->selectTabPanel(tabp);
413 onClickTab(this, false);
414 }
415}
416
417BOOL LLPanelGroup::canClose()
418{
419 if (mShowingNotifyDialog) return FALSE;
420 if (mCurrentTab && mCurrentTab->hasModal()) return FALSE;
421 if (mForceClose || !mAllowEdit) return TRUE;
422
423 // Try to switch from the current panel to nothing, indicating a close action.
424 mRequestedTab = NULL;
425 return attemptTransition();
426}
427
428BOOL LLPanelGroup::attemptTransition()
429{
430 // Check if the current tab needs to be applied.
431 LLString mesg;
432 if (mCurrentTab && mCurrentTab->needsApply(mesg))
433 {
434 // If no message was provided, give a generic one.
435 if (mesg.empty())
436 {
437 mesg = mDefaultNeedsApplyMesg;
438 }
439 // Create a notify box, telling the user about the unapplied tab.
440 LLString::format_map_t args;
441 args["[NEEDS_APPLY_MESSAGE]"] = mesg;
442 args["[WANT_APPLY_MESSAGE]"] = mWantApplyMesg;
443 gViewerWindow->alertXml("PanelGroupApply", args,
444 onNotifyCallback, (void*) this);
445 mShowingNotifyDialog = TRUE;
446
447 // We need to reselect the current tab, since it isn't finished.
448 if (mTabContainer)
449 {
450 // selectTabPanel is going to trigger another
451 // click event. We want to ignore it so that
452 // mRequestedTab is not updated.
453 mIgnoreTransition = TRUE;
454 mTabContainer->selectTabPanel( mCurrentTab );
455 mIgnoreTransition = FALSE;
456 }
457 // Returning FALSE will block a close action from finishing until
458 // we get a response back from the user.
459 return FALSE;
460 }
461 else
462 {
463 // The current panel didn't have anything it needed to apply.
464 if ( mRequestedTab )
465 {
466 transitionToTab();
467 }
468 // Returning TRUE will allow any close action to proceed.
469 return TRUE;
470 }
471}
472
473void LLPanelGroup::transitionToTab()
474{
475 // Tell the current panel that it is being deactivated.
476 if (mCurrentTab)
477 {
478 mCurrentTab->deactivate();
479 }
480
481 // If the requested panel exists, activate it.
482 if (mRequestedTab)
483 {
484 // This is now the current tab;
485 mCurrentTab = mRequestedTab;
486 mCurrentTab->activate();
487 }
488 else // NULL requested indicates a close action.
489 {
490 close();
491 }
492}
493
494// static
495void LLPanelGroup::onNotifyCallback(S32 option, void* user_data)
496{
497 LLPanelGroup* self = static_cast<LLPanelGroup*>(user_data);
498 if (self)
499 {
500 self->handleNotifyCallback(option);
501 }
502}
503
504void LLPanelGroup::handleNotifyCallback(S32 option)
505{
506 mShowingNotifyDialog = FALSE;
507 switch (option)
508 {
509 case 0: // "Apply Changes"
510 // Try to apply changes, and switch to the requested tab.
511 if ( !apply() )
512 {
513 // There was a problem doing the apply.
514 // Skip switching tabs.
515 break;
516 }
517
518 // This panel's info successfully applied.
519 // Switch to the next panel.
520 mIgnoreTransition = TRUE;
521 mTabContainer->selectTabPanel( mRequestedTab );
522 mIgnoreTransition = FALSE;
523 transitionToTab();
524 break;
525 case 1: // "Ignore Changes"
526 // Switch to the requested panel without applying changes
527 // (Changes may already have been applied in the previous block)
528 mCurrentTab->cancel();
529 mIgnoreTransition = TRUE;
530 mTabContainer->selectTabPanel( mRequestedTab );
531 mIgnoreTransition = FALSE;
532 transitionToTab();
533 break;
534 case 2: // "Cancel"
535 default:
536 // Do nothing. The user is canceling the action.
537 // If we were quitting, we didn't really mean it.
538 app_abort_quit();
539 break;
540 }
541}
542
543// static
544void LLPanelGroup::onBtnOK(void* user_data)
545{
546 LLPanelGroup* self = static_cast<LLPanelGroup*>(user_data);
547 // If we are able to apply changes, then close.
548 if(self->apply())
549 {
550 self->close();
551 }
552}
553
554// static
555void LLPanelGroup::onBtnCancel(void* user_data)
556{
557 LLPanelGroup* self = static_cast<LLPanelGroup*>(user_data);
558 self->close();
559}
560
561// static
562void LLPanelGroup::onBtnApply(void* user_data)
563{
564 LLPanelGroup* self = static_cast<LLPanelGroup*>(user_data);
565 self->apply();
566}
567
568bool LLPanelGroup::apply()
569{
570 // Pass this along to the currently visible tab.
571 if (!mTabContainer) return false;
572
573 LLPanelGroupTab* panelp = (LLPanelGroupTab*) mTabContainer->getCurrentPanel();
574 if (!panelp) return false;
575
576 LLString mesg;
577 if ( !panelp->needsApply(mesg) )
578 {
579 // We don't need to apply anything.
580 // We're done.
581 return true;
582 }
583
584 // Ignore the needs apply message.
585 // Try to do the actual apply.
586 LLString apply_mesg;
587 if ( panelp->apply( apply_mesg ) )
588 {
589 // Everything worked. We're done.
590 return true;
591 }
592
593 // There was a problem doing the actual apply.
594 // Inform the user.
595 if ( !apply_mesg.empty() )
596 {
597 LLString::format_map_t args;
598 args["[MESSAGE]"] = apply_mesg;
599 gViewerWindow->alertXml("GenericAlert", args);
600 }
601
602 return false;
603}
604
605// static
606void LLPanelGroup::onBtnRefresh(void* user_data)
607{
608 LLPanelGroup* self = static_cast<LLPanelGroup*>(user_data);
609 self->refreshData();
610}
611
612// virtual
613void LLPanelGroup::draw()
614{
615 LLPanel::draw();
616
617 if (mRefreshTimer.hasExpired())
618 {
619 mRefreshTimer.stop();
620 childEnable("btn_refresh");
621 }
622}
623
624void LLPanelGroup::refreshData()
625{
626 gGroupMgr->clearGroupData(getID());
627 mCurrentTab->activate();
628
629 // 5 second timeout
630 childDisable("btn_refresh");
631 mRefreshTimer.start();
632 mRefreshTimer.setTimerExpirySec(5);
633}
634
635void LLPanelGroup::close()
636{
637 // Pass this to the parent, if it is a floater.
638 LLView* viewp = getParent();
639 if (viewp
640 && WIDGET_TYPE_FLOATER == viewp->getWidgetType())
641 {
642 // First, set the force close flag, since the floater
643 // will be asking us whether it can close.
644 mForceClose = TRUE;
645 // Tell the parent floater to close.
646 LLFloater* floaterp = (LLFloater*) viewp;
647 floaterp->close();
648 }
649}
650
651void LLPanelGroup::showNotice(const char* subject,
652 const char* message,
653 const bool& has_inventory,
654 const char* inventory_name,
655 LLOfferInfo* inventory_offer)
656{
657 if (mCurrentTab->getName() != "notices_tab")
658 {
659 // We need to clean up that inventory offer.
660 if (inventory_offer)
661 {
662 inventory_offer_callback( 1 , inventory_offer);
663 }
664 return;
665 }
666
667 LLPanelGroupNotices* notices = static_cast<LLPanelGroupNotices*>(mCurrentTab);
668
669 notices->showNotice(subject,message,has_inventory,inventory_name,inventory_offer);
670}