SWAT-484, SWAT-485: add LLSideTrayListener, a new LLEventAPI.
Expand XUI-visible LLUICtrl::CommitCallbackRegistry operations to include "SideTray.Toggle" and "SideTray.Collapse". Give LLSideTrayListener friend access to LLSideTray so it can query the attached and detached tabs. Introduce tab_cast template to deal with the unavailability of the LLSideTrayTab class outside of llsidetray.cpp.meow-7.2.2
parent
34ba85dd59
commit
5946d84eef
|
|
@ -412,6 +412,7 @@ set(viewer_SOURCE_FILES
|
|||
llsidepaneliteminfo.cpp
|
||||
llsidepaneltaskinfo.cpp
|
||||
llsidetray.cpp
|
||||
llsidetraylistener.cpp
|
||||
llsidetraypanelcontainer.cpp
|
||||
llsky.cpp
|
||||
llslurl.cpp
|
||||
|
|
@ -947,6 +948,7 @@ set(viewer_HEADER_FILES
|
|||
llsidepaneliteminfo.h
|
||||
llsidepaneltaskinfo.h
|
||||
llsidetray.h
|
||||
llsidetraylistener.h
|
||||
llsidetraypanelcontainer.h
|
||||
llsky.h
|
||||
llslurl.h
|
||||
|
|
|
|||
|
|
@ -53,6 +53,8 @@
|
|||
|
||||
#include "llsidepanelappearance.h"
|
||||
|
||||
#include "llsidetraylistener.h"
|
||||
|
||||
//#include "llscrollcontainer.h"
|
||||
|
||||
using namespace std;
|
||||
|
|
@ -71,6 +73,8 @@ static const std::string TAB_PANEL_CAPTION_TITLE_BOX = "sidetray_tab_title";
|
|||
|
||||
LLSideTray* LLSideTray::sInstance = 0;
|
||||
|
||||
static LLSideTrayListener sSideTrayListener(LLSideTray::getInstance);
|
||||
|
||||
// static
|
||||
LLSideTray* LLSideTray::getInstance()
|
||||
{
|
||||
|
|
@ -417,6 +421,11 @@ LLSideTrayTab* LLSideTrayTab::createInstance ()
|
|||
return tab;
|
||||
}
|
||||
|
||||
// Now that we know the definition of LLSideTrayTab, we can implement
|
||||
// tab_cast.
|
||||
template <>
|
||||
LLPanel* tab_cast<LLPanel*>(LLSideTrayTab* tab) { return tab; }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// LLSideTrayButton
|
||||
// Side Tray tab button with "tear off" handling.
|
||||
|
|
@ -530,6 +539,8 @@ LLSideTray::LLSideTray(const Params& params)
|
|||
// register handler function to process data from the xml.
|
||||
// panel_name should be specified via "parameter" attribute.
|
||||
commit.add("SideTray.ShowPanel", boost::bind(&LLSideTray::showPanel, this, _2, LLUUID::null));
|
||||
commit.add("SideTray.Toggle", boost::bind(&LLSideTray::onToggleCollapse, this));
|
||||
commit.add("SideTray.Collapse", boost::bind(&LLSideTray::collapseSideBar, this));
|
||||
LLTransientFloaterMgr::getInstance()->addControlView(this);
|
||||
LLView* side_bar_tabs = gViewerWindow->getRootView()->getChildView("side_bar_tabs");
|
||||
if (side_bar_tabs != NULL)
|
||||
|
|
|
|||
|
|
@ -33,6 +33,13 @@
|
|||
class LLAccordionCtrl;
|
||||
class LLSideTrayTab;
|
||||
|
||||
// Deal with LLSideTrayTab being opaque. Generic do-nothing cast...
|
||||
template <class T>
|
||||
T tab_cast(LLSideTrayTab* tab) { return tab; }
|
||||
// specialized for implementation in presence of LLSideTrayTab definition
|
||||
template <>
|
||||
LLPanel* tab_cast<LLPanel*>(LLSideTrayTab* tab);
|
||||
|
||||
// added inheritance from LLDestroyClass<LLSideTray> to enable Side Tray perform necessary actions
|
||||
// while disconnecting viewer in LLAppViewer::disconnectViewer().
|
||||
// LLDestroyClassList::instance().fireCallbacks() calls destroyClass method. See EXT-245.
|
||||
|
|
@ -217,6 +224,9 @@ private:
|
|||
}
|
||||
|
||||
private:
|
||||
// Since we provide no public way to query mTabs and mDetachedTabs, give
|
||||
// LLSideTrayListener friend access.
|
||||
friend class LLSideTrayListener;
|
||||
LLPanel* mButtonsPanel;
|
||||
typedef std::map<std::string,LLButton*> button_map_t;
|
||||
button_map_t mTabButtons;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,167 @@
|
|||
/**
|
||||
* @file llsidetraylistener.cpp
|
||||
* @author Nat Goodspeed
|
||||
* @date 2011-02-15
|
||||
* @brief Implementation for llsidetraylistener.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2011&license=lgpl$
|
||||
* Copyright (c) 2011, Linden Research, Inc.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
// Precompiled header
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
// associated header
|
||||
#include "llsidetraylistener.h"
|
||||
// STL headers
|
||||
// std headers
|
||||
// external library headers
|
||||
// other Linden headers
|
||||
#include "llsidetray.h"
|
||||
#include "llsdutil.h"
|
||||
|
||||
LLSideTrayListener::LLSideTrayListener(const Getter& getter):
|
||||
LLEventAPI("LLSideTray",
|
||||
"Operations on side tray (e.g. query state, query tabs)"),
|
||||
mGetter(getter)
|
||||
{
|
||||
add("getCollapsed", "Send on [\"reply\"] an [\"open\"] Boolean",
|
||||
&LLSideTrayListener::getCollapsed, LLSDMap("reply", LLSD()));
|
||||
add("getTabs",
|
||||
"Send on [\"reply\"] a map of tab names and info about them",
|
||||
&LLSideTrayListener::getTabs, LLSDMap("reply", LLSD()));
|
||||
add("getPanels",
|
||||
"Send on [\"reply\"] data about panels available with SideTray.ShowPanel",
|
||||
&LLSideTrayListener::getPanels, LLSDMap("reply", LLSD()));
|
||||
}
|
||||
|
||||
void LLSideTrayListener::getCollapsed(const LLSD& event) const
|
||||
{
|
||||
LLReqID reqID(event);
|
||||
LLSD reply(reqID.makeResponse());
|
||||
reply["open"] = ! mGetter()->getCollapsed();
|
||||
LLEventPumps::instance().obtain(event["reply"]).post(reply);
|
||||
}
|
||||
|
||||
void LLSideTrayListener::getTabs(const LLSD& event) const
|
||||
{
|
||||
LLReqID reqID(event);
|
||||
LLSD reply(reqID.makeResponse());
|
||||
|
||||
LLSideTray* tray = mGetter();
|
||||
LLSD::Integer ord(0);
|
||||
for (LLSideTray::child_list_const_iter_t chi(tray->beginChild()), chend(tray->endChild());
|
||||
chi != chend; ++chi, ++ord)
|
||||
{
|
||||
LLView* child = *chi;
|
||||
// How much info is important? Toss in as much as seems reasonable for
|
||||
// each tab. But to me, at least for the moment, the most important
|
||||
// item is the tab name.
|
||||
LLSD info;
|
||||
// I like the idea of returning a map keyed by tab name. But as
|
||||
// compared to an array of maps, that loses sequence information.
|
||||
// Address that by indicating the original order in each map entry.
|
||||
info["ord"] = ord;
|
||||
info["visible"] = bool(child->getVisible());
|
||||
info["enabled"] = bool(child->getEnabled());
|
||||
info["available"] = child->isAvailable();
|
||||
reply[child->getName()] = info;
|
||||
}
|
||||
|
||||
LLEventPumps::instance().obtain(event["reply"]).post(reply);
|
||||
}
|
||||
|
||||
static LLSD getTabInfo(LLPanel* tab)
|
||||
{
|
||||
LLSD panels;
|
||||
for (LLPanel::tree_iterator_t ti(tab->beginTreeDFS()), tend(tab->endTreeDFS());
|
||||
ti != tend; ++ti)
|
||||
{
|
||||
// *ti is actually an LLView*, which had better not be NULL
|
||||
LLView* view(*ti);
|
||||
if (! view)
|
||||
{
|
||||
LL_ERRS("LLSideTrayListener") << "LLSideTrayTab '" << tab->getName()
|
||||
<< "' has a NULL child LLView*" << LL_ENDL;
|
||||
}
|
||||
|
||||
// The logic we use to decide what "panel" names to return is heavily
|
||||
// based on LLSideTray::showPanel(): the function that actually
|
||||
// implements the "SideTray.ShowPanel" operation. showPanel(), in
|
||||
// turn, depends on LLSideTray::openChildPanel(): when
|
||||
// openChildPanel() returns non-NULL, showPanel() stops searching
|
||||
// attached and detached LLSideTrayTab tabs.
|
||||
|
||||
// For each LLSideTrayTab, openChildPanel() first calls
|
||||
// findChildView(panel_name, true). In other words, panel_name need
|
||||
// not be a direct LLSideTrayTab child, it's sought recursively.
|
||||
// That's why we use (begin|end)TreeDFS() in this loop.
|
||||
|
||||
// But this tree_iterator_t loop will actually traverse every widget
|
||||
// in every panel. Returning all those names will not help our caller:
|
||||
// passing most such names to openChildPanel() would not do what we
|
||||
// want. Even though the code suggests that passing ANY valid
|
||||
// side-panel widget name to openChildPanel() will open the tab
|
||||
// containing that widget, results could get confusing since followup
|
||||
// (onOpen()) logic wouldn't be invoked, and showPanel() wouldn't stop
|
||||
// searching because openChildPanel() would return NULL.
|
||||
|
||||
// We must filter these LLView items, using logic that (sigh!) mirrors
|
||||
// openChildPanel()'s own.
|
||||
|
||||
// openChildPanel() returns a non-NULL LLPanel* when either:
|
||||
// - the LLView is a direct child of an LLSideTrayPanelContainer
|
||||
// - the LLView is itself an LLPanel.
|
||||
// But as LLSideTrayPanelContainer can directly contain LLView items
|
||||
// that are NOT themselves LLPanels (e.g. "sidebar_me" contains an
|
||||
// LLButton called "Jump Right Arrow"), we'd better focus only on
|
||||
// LLSideTrayPanelContainer children that are themselves LLPanel
|
||||
// items. Which means that the second test completely subsumes the
|
||||
// first.
|
||||
LLPanel* panel(dynamic_cast<LLPanel*>(view));
|
||||
if (panel)
|
||||
{
|
||||
// Maybe it's overkill to construct an LLSD::Map for each panel, but
|
||||
// the possibility remains that we might want to deliver more info
|
||||
// about each panel than just its name.
|
||||
panels.append(LLSDMap("name", panel->getName()));
|
||||
}
|
||||
}
|
||||
|
||||
return LLSDMap("panels", panels);
|
||||
}
|
||||
|
||||
void LLSideTrayListener::getPanels(const LLSD& event) const
|
||||
{
|
||||
LLReqID reqID(event);
|
||||
LLSD reply(reqID.makeResponse());
|
||||
|
||||
LLSideTray* tray = mGetter();
|
||||
// Iterate through the attached tabs.
|
||||
LLSD::Integer ord(0);
|
||||
for (LLSideTray::child_vector_t::const_iterator
|
||||
ati(tray->mTabs.begin()), atend(tray->mTabs.end());
|
||||
ati != atend; ++ati)
|
||||
{
|
||||
// We don't have access to LLSideTrayTab: the class definition is
|
||||
// hidden in llsidetray.cpp. But as LLSideTrayTab isa LLPanel, use the
|
||||
// LLPanel API. Unfortunately, without the LLSideTrayTab definition,
|
||||
// the compiler doesn't even know this LLSideTrayTab* is an LLPanel*.
|
||||
// Persuade it.
|
||||
LLPanel* tab(tab_cast<LLPanel*>(*ati));
|
||||
reply[tab->getName()] = getTabInfo(tab).with("attached", true).with("ord", ord);
|
||||
}
|
||||
|
||||
// Now iterate over the detached tabs. These can also be opened via
|
||||
// SideTray.ShowPanel.
|
||||
ord = 0;
|
||||
for (LLSideTray::child_vector_t::const_iterator
|
||||
dti(tray->mDetachedTabs.begin()), dtend(tray->mDetachedTabs.end());
|
||||
dti != dtend; ++dti)
|
||||
{
|
||||
LLPanel* tab(tab_cast<LLPanel*>(*dti));
|
||||
reply[tab->getName()] = getTabInfo(tab).with("attached", false).with("ord", ord);
|
||||
}
|
||||
|
||||
LLEventPumps::instance().obtain(event["reply"]).post(reply);
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* @file llsidetraylistener.h
|
||||
* @author Nat Goodspeed
|
||||
* @date 2011-02-15
|
||||
* @brief
|
||||
*
|
||||
* $LicenseInfo:firstyear=2011&license=lgpl$
|
||||
* Copyright (c) 2011, Linden Research, Inc.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#if ! defined(LL_LLSIDETRAYLISTENER_H)
|
||||
#define LL_LLSIDETRAYLISTENER_H
|
||||
|
||||
#include "lleventapi.h"
|
||||
#include <boost/function.hpp>
|
||||
|
||||
class LLSideTray;
|
||||
class LLSD;
|
||||
|
||||
class LLSideTrayListener: public LLEventAPI
|
||||
{
|
||||
typedef boost::function<LLSideTray*()> Getter;
|
||||
|
||||
public:
|
||||
LLSideTrayListener(const Getter& getter);
|
||||
|
||||
private:
|
||||
void getCollapsed(const LLSD& event) const;
|
||||
void getTabs(const LLSD& event) const;
|
||||
void getPanels(const LLSD& event) const;
|
||||
|
||||
Getter mGetter;
|
||||
};
|
||||
|
||||
#endif /* ! defined(LL_LLSIDETRAYLISTENER_H) */
|
||||
Loading…
Reference in New Issue