Files
SingularityViewer/indra/newview/lltoolbar.cpp
Aleric Inglewood fae8f7803e Fix for Communicate flyout button.
Remove erroneously linked control variable.

The 'value' of a LLFlyoutButton is the (last) selected value:
a string. Linking it to some random boolean control variable
causes this value to be (re)assigned to the flyout button list
through LLControlVariable::setValue (whenever said boolean
changes, in this case when the floater is made to appear)
which calls getComparableValue with the string value (ie "mute list")
and tries to convert that to a boolean. Obviously That fails
and the value is set to "", effectively having nothing selected
anymore.

This fixes
http://code.google.com/p/singularity-viewer/issues/detail?id=21
2011-06-25 13:45:04 +02:00

565 lines
15 KiB
C++

/**
* @file lltoolbar.cpp
* @author James Cook, Richard Nelson
* @brief Large friendly buttons at bottom of screen.
*
* $LicenseInfo:firstyear=2002&license=viewergpl$
*
* Copyright (c) 2002-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "lltoolbar.h"
#include "imageids.h"
#include "llfontgl.h"
#include "llrect.h"
#include "llparcel.h"
#include "llagent.h"
#include "llagentcamera.h"
#include "llbutton.h"
#include "llfocusmgr.h"
#include "llviewercontrol.h"
#include "llmenucommands.h"
#include "llimview.h"
#include "lluiconstants.h"
#include "llvoavatar.h"
#include "lltooldraganddrop.h"
#include "llinventoryview.h"
#include "llfloaterchatterbox.h"
#include "llfloaterfriends.h"
#include "llfloatersnapshot.h"
#include "llfloateravatarlist.h"
#include "lltoolmgr.h"
#include "llui.h"
#include "llviewermenu.h"
#include "llfirstuse.h"
#include "llviewerparcelmgr.h"
#include "lluictrlfactory.h"
#include "llviewerwindow.h"
#include "lltoolgrab.h"
#include "llcombobox.h"
#include "llfloaterchat.h"
#include "llfloatermute.h"
#include "llimpanel.h"
#include "llscrolllistctrl.h"
// [RLVa:KB]
#include "rlvhandler.h"
// [/RLVa:KB]
#if LL_DARWIN
#include "llresizehandle.h"
// This class draws like an LLResizeHandle but has no interactivity.
// It's just there to provide a cue to the user that the lower right corner of the window functions as a resize handle.
class LLFakeResizeHandle : public LLResizeHandle
{
public:
LLFakeResizeHandle(const std::string& name, const LLRect& rect, S32 min_width, S32 min_height, ECorner corner = RIGHT_BOTTOM )
: LLResizeHandle(name, rect, min_width, min_height, corner )
{
}
virtual BOOL handleHover(S32 x, S32 y, MASK mask) { return FALSE; };
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) { return FALSE; };
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask) { return FALSE; };
};
#endif // LL_DARWIN
//
// Globals
//
LLToolBar *gToolBar = NULL;
S32 TOOL_BAR_HEIGHT = 20;
//
// Statics
//
F32 LLToolBar::sInventoryAutoOpenTime = 1.f;
//
// Functions
//
LLToolBar::LLToolBar()
: LLPanel()
#if LL_DARWIN
, mResizeHandle(NULL)
#endif // LL_DARWIN
{
setIsChrome(TRUE);
setFocusRoot(TRUE);
}
BOOL LLToolBar::postBuild()
{
childSetCommitCallback("communicate_btn", onClickCommunicate, this);
childSetAction("chat_btn", onClickChat, this);
childSetControlName("chat_btn", "ChatVisible");
childSetAction("appearance_btn", onClickAppearance, this);
childSetControlName("appearance_btn", "");
childSetAction("radar_list_btn", onClickRadarList, this);
childSetControlName("radar_list_btn", "RadarListBtnState");
childSetAction("fly_btn", onClickFly, this);
childSetControlName("fly_btn", "FlyBtnState");
childSetAction("sit_btn", onClickSit, this);
childSetControlName("sit_btn", "SitBtnState");
childSetAction("snapshot_btn", onClickSnapshot, this);
childSetControlName("snapshot_btn", "");
childSetAction("directory_btn", onClickDirectory, this);
childSetControlName("directory_btn", "ShowDirectory");
childSetAction("build_btn", onClickBuild, this);
childSetControlName("build_btn", "BuildBtnState");
childSetAction("radar_btn", onClickRadar, this);
childSetControlName("radar_btn", "ShowMiniMap");
childSetAction("map_btn", onClickMap, this);
childSetControlName("map_btn", "ShowWorldMap");
childSetAction("inventory_btn", onClickInventory, this);
childSetControlName("inventory_btn", "ShowInventory");
for (child_list_const_iter_t child_iter = getChildList()->begin();
child_iter != getChildList()->end(); ++child_iter)
{
LLView *view = *child_iter;
LLButton* buttonp = dynamic_cast<LLButton*>(view);
if(buttonp)
{
buttonp->setSoundFlags(LLView::SILENT);
}
}
#if LL_DARWIN
if(mResizeHandle == NULL)
{
LLRect rect(0, 0, RESIZE_HANDLE_WIDTH, RESIZE_HANDLE_HEIGHT);
mResizeHandle = new LLFakeResizeHandle(std::string(""), rect, RESIZE_HANDLE_WIDTH, RESIZE_HANDLE_HEIGHT);
this->addChildAtEnd(mResizeHandle);
LLLayoutStack* toolbar_stack = getChild<LLLayoutStack>("toolbar_stack");
toolbar_stack->reshape(toolbar_stack->getRect().getWidth() - RESIZE_HANDLE_WIDTH, toolbar_stack->getRect().getHeight());
}
#endif // LL_DARWIN
layoutButtons();
return TRUE;
}
LLToolBar::~LLToolBar()
{
// LLView destructor cleans up children
}
BOOL LLToolBar::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,
EAcceptance* accept,
std::string& tooltip_msg)
{
LLButton* inventory_btn = getChild<LLButton>("inventory_btn");
if (!inventory_btn) return FALSE;
LLInventoryView* active_inventory = LLInventoryView::getActiveInventory();
if(active_inventory && active_inventory->getVisible())
{
mInventoryAutoOpen = FALSE;
}
else if (inventory_btn->getRect().pointInRect(x, y))
{
if (mInventoryAutoOpen)
{
if (!(active_inventory && active_inventory->getVisible()) &&
mInventoryAutoOpenTimer.getElapsedTimeF32() > sInventoryAutoOpenTime)
{
LLInventoryView::showAgentInventory();
}
}
else
{
mInventoryAutoOpen = TRUE;
mInventoryAutoOpenTimer.reset();
}
}
return LLPanel::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
}
// static
void LLToolBar::toggle(void*)
{
BOOL show = gSavedSettings.getBOOL("ShowToolBar");
gSavedSettings.setBOOL("ShowToolBar", !show);
gToolBar->setVisible(!show);
}
// static
BOOL LLToolBar::visible(void*)
{
return gToolBar->getVisible();
}
void LLToolBar::layoutButtons()
{
#if LL_DARWIN
const S32 FUDGE_WIDTH_OF_SCREEN = 4;
S32 width = gViewerWindow->getWindowWidth() + FUDGE_WIDTH_OF_SCREEN;
S32 pad = 2;
// this function may be called before postBuild(), in which case mResizeHandle won't have been set up yet.
if(mResizeHandle != NULL)
{
if(!gViewerWindow->getWindow()->getFullscreen())
{
// Only when running in windowed mode on the Mac, leave room for a resize widget on the right edge of the bar.
width -= RESIZE_HANDLE_WIDTH;
LLRect r;
r.mLeft = width - pad;
r.mBottom = 0;
r.mRight = r.mLeft + RESIZE_HANDLE_WIDTH;
r.mTop = r.mBottom + RESIZE_HANDLE_HEIGHT;
mResizeHandle->setRect(r);
mResizeHandle->setVisible(TRUE);
}
else
{
mResizeHandle->setVisible(FALSE);
}
}
#endif // LL_DARWIN
}
// virtual
void LLToolBar::reshape(S32 width, S32 height, BOOL called_from_parent)
{
LLPanel::reshape(width, height, called_from_parent);
layoutButtons();
}
// Per-frame updates of visibility
void LLToolBar::refresh()
{
BOOL show = gSavedSettings.getBOOL("ShowToolBar");
BOOL mouselook = gAgentCamera.cameraMouselook();
setVisible(show && !mouselook);
BOOL sitting = FALSE;
if (gAgent.getAvatarObject())
{
sitting = gAgent.getAvatarObject()->isSitting();
}
childSetEnabled("fly_btn", (gAgent.canFly() || gAgent.getFlying() || gSavedSettings.getBOOL("AscentFlyAlwaysEnabled")) && !sitting );
childSetEnabled("build_btn", (LLViewerParcelMgr::getInstance()->agentCanBuild() || gSavedSettings.getBOOL("AscentBuildAlwaysEnabled")) );
// Check to see if we're in build mode
BOOL build_mode = LLToolMgr::getInstance()->inEdit();
// And not just clicking on a scripted object
if (LLToolGrab::getInstance()->getHideBuildHighlight())
{
build_mode = FALSE;
}
static LLCachedControl<bool> build_btn_state("BuildBtnState",false);
if(build_btn_state!=(bool)build_mode)
build_btn_state = build_mode;
// [RLVa:KB] - Version: 1.23.4 | Checked: 2009-07-10 (RLVa-1.0.0g)
// Called per-frame so this really can't be slow
if (rlv_handler_t::isEnabled())
{
// If we're rez-restricted, we can still edit => allow build floater
// If we're edit-restricted, we can still rez => allow build floater
childSetEnabled("build_btn", !(gRlvHandler.hasBehaviour(RLV_BHVR_REZ) && gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) );
childSetEnabled("map_btn", !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWWORLDMAP) );
childSetEnabled("radar_btn", !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWMINIMAP) );
childSetEnabled("inventory_btn", !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWINV) );
}
// [/RLVa:KB]
if (isInVisibleChain())
{
updateCommunicateList();
}
}
void LLToolBar::updateCommunicateList()
{
LLFlyoutButton* communicate_button = getChild<LLFlyoutButton>("communicate_btn");
LLSD selected = communicate_button->getValue();
communicate_button->removeall();
LLFloater* frontmost_floater = LLFloaterChatterBox::getInstance()->getActiveFloater();
LLScrollListItem* itemp = NULL;
itemp = communicate_button->add(LLFloaterMyFriends::getInstance()->getShortTitle(), LLSD("contacts"), ADD_TOP);
if (LLFloaterMyFriends::getInstance() == frontmost_floater)
{
((LLScrollListText*)itemp->getColumn(0))->setFontStyle(LLFontGL::BOLD);
// make sure current tab is selected in list
if (selected.isUndefined())
{
selected = itemp->getValue();
}
}
itemp = communicate_button->add(LLFloaterChat::getInstance()->getShortTitle(), LLSD("local chat"), ADD_TOP);
if (LLFloaterChat::getInstance() == frontmost_floater)
{
((LLScrollListText*)itemp->getColumn(0))->setFontStyle(LLFontGL::BOLD);
if (selected.isUndefined())
{
selected = itemp->getValue();
}
}
communicate_button->addSeparator(ADD_TOP);
communicate_button->add(getString("Redock Windows"), LLSD("redock"), ADD_TOP);
communicate_button->addSeparator(ADD_TOP);
communicate_button->add(LLFloaterMute::getInstance()->getShortTitle(), LLSD("mute list"), ADD_TOP);
std::set<LLHandle<LLFloater> >::const_iterator floater_handle_it;
if (gIMMgr->getIMFloaterHandles().size() > 0)
{
communicate_button->addSeparator(ADD_TOP);
}
for(floater_handle_it = gIMMgr->getIMFloaterHandles().begin(); floater_handle_it != gIMMgr->getIMFloaterHandles().end(); ++floater_handle_it)
{
LLFloaterIMPanel* im_floaterp = (LLFloaterIMPanel*)floater_handle_it->get();
if (im_floaterp)
{
std::string floater_title = im_floaterp->getNumUnreadMessages() > 0 ? "*" : "";
floater_title.append(im_floaterp->getShortTitle());
itemp = communicate_button->add(floater_title, im_floaterp->getSessionID(), ADD_TOP);
if (im_floaterp == frontmost_floater)
{
((LLScrollListText*)itemp->getColumn(0))->setFontStyle(LLFontGL::BOLD);
if (selected.isUndefined())
{
selected = itemp->getValue();
}
}
}
}
communicate_button->setToggleState(gSavedSettings.getBOOL("ShowCommunicate"));
communicate_button->setValue(selected);
}
// static
void LLToolBar::onClickCommunicate(LLUICtrl* ctrl, void* user_data)
{
LLToolBar* toolbar = (LLToolBar*)user_data;
LLFlyoutButton* communicate_button = toolbar->getChild<LLFlyoutButton>("communicate_btn");
LLSD selected_option = communicate_button->getValue();
if (selected_option.asString() == "contacts")
{
LLFloaterMyFriends::showInstance();
}
else if (selected_option.asString() == "local chat")
{
LLFloaterChat::showInstance();
}
else if (selected_option.asString() == "redock")
{
LLFloaterChatterBox::getInstance()->addFloater(LLFloaterMyFriends::getInstance(), FALSE);
LLFloaterChatterBox::getInstance()->addFloater(LLFloaterChat::getInstance(), FALSE);
LLUUID session_to_show;
std::set<LLHandle<LLFloater> >::const_iterator floater_handle_it;
for(floater_handle_it = gIMMgr->getIMFloaterHandles().begin(); floater_handle_it != gIMMgr->getIMFloaterHandles().end(); ++floater_handle_it)
{
LLFloater* im_floaterp = floater_handle_it->get();
if (im_floaterp)
{
if (im_floaterp->isFrontmost())
{
session_to_show = ((LLFloaterIMPanel*)im_floaterp)->getSessionID();
}
LLFloaterChatterBox::getInstance()->addFloater(im_floaterp, FALSE);
}
}
LLFloaterChatterBox::showInstance(session_to_show);
}
else if (selected_option.asString() == "mute list")
{
LLFloaterMute::showInstance();
}
else if (selected_option.isUndefined()) // user just clicked the communicate button, treat as toggle
{
if (LLFloaterChatterBox::getInstance()->getFloaterCount() == 0)
{
LLFloaterMyFriends::toggleInstance();
}
else
{
LLFloaterChatterBox::toggleInstance();
}
}
else // otherwise selection_option is a specific IM session id
{
LLFloaterChatterBox::showInstance(selected_option);
}
}
// static
void LLToolBar::onClickChat(void* user_data)
{
handle_chat(NULL);
}
// static
void LLToolBar::onClickAppearance(void*)
{
if (gAgentWearables.areWearablesLoaded())
{
gAgentCamera.changeCameraToCustomizeAvatar();
}
}
// static
void LLToolBar::onClickRadarList(void*)
{
LLFloaterAvatarList::toggle(0);
bool vis = false;
if(LLFloaterAvatarList::getInstance())
{
vis = (bool)LLFloaterAvatarList::getInstance()->getVisible();
}
}
// static
void LLToolBar::onClickFly(void*)
{
gAgent.toggleFlying();
}
// static
void LLToolBar::onClickSit(void*)
{
if (!(gAgent.getControlFlags() & AGENT_CONTROL_SIT_ON_GROUND))
{
// sit down
gAgent.setFlying(FALSE);
gAgent.setControlFlags(AGENT_CONTROL_SIT_ON_GROUND);
// Might be first sit
LLFirstUse::useSit();
}
else
{
// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g)
// NOTE-RLVa: dead code?
if (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT))
{
return;
}
// [/RLVa:KB]
// stand up
gAgent.setFlying(FALSE);
gAgent.setControlFlags(AGENT_CONTROL_STAND_UP);
}
}
// static
void LLToolBar::onClickSnapshot(void*)
{
LLFloaterSnapshot::show (0);
}
// static
void LLToolBar::onClickDirectory(void*)
{
handle_find(NULL);
}
// static
void LLToolBar::onClickBuild(void*)
{
toggle_build_mode();
}
// static
void LLToolBar::onClickRadar(void*)
{
handle_mini_map(NULL);
}
// static
void LLToolBar::onClickMap(void*)
{
handle_map(NULL);
}
// static
void LLToolBar::onClickInventory(void*)
{
handle_inventory(NULL);
}