* Bugs: EXT-1111 EXT-915 EXT-1131 EXT-1200 EXT-1202 EXT-1201 EXT-1205 EXT-1212 EXT-1173 EXT-1229 EXT-1218 EXT-1164 EXT-996 EXT-821 EXT-1030 EXT-1031 EXT-816
* Major Bugs: EXT-1142 (timeout during login due to processing group IMs)
* Changes: EXT-1216 (minimize message well)
master
Steven Bennetts 2009-10-01 17:44:44 +00:00
parent 090977608d
commit f05df68656
73 changed files with 1520 additions and 1201 deletions

View File

@ -85,6 +85,7 @@ set(llui_SOURCE_FILES
lltextbox.cpp
lltexteditor.cpp
lltextparser.cpp
lltransientfloatermgr.cpp
lltransutil.cpp
lltooltip.cpp
llui.cpp
@ -171,6 +172,7 @@ set(llui_HEADER_FILES
lltexteditor.h
lltextparser.h
lltooltip.h
lltransientfloatermgr.h
lltransutil.h
lluicolortable.h
lluiconstants.h

View File

@ -71,9 +71,9 @@ void LLDockableFloater::resetInstance()
if (sInstanceHandle.get() != NULL && sInstanceHandle.get()->isDocked())
{
sInstanceHandle.get()->setVisible(FALSE);
}
}
sInstanceHandle = getHandle();
}
}
}
void LLDockableFloater::setVisible(BOOL visible)
@ -105,11 +105,11 @@ void LLDockableFloater::setDocked(bool docked, bool pop_on_undock)
mDockControl.get()->off();
}
if (!docked && pop_on_undock)
{
// visually pop up a little bit to emphasize the undocking
translate(0, UNDOCK_LEAP_HEIGHT);
}
if (!docked && pop_on_undock)
{
// visually pop up a little bit to emphasize the undocking
translate(0, UNDOCK_LEAP_HEIGHT);
}
}
else
{
@ -126,8 +126,8 @@ void LLDockableFloater::draw()
mDockControl.get()->repositionDockable();
if (isDocked())
{
mDockControl.get()->drawToungue();
}
mDockControl.get()->drawToungue();
}
}
LLFloater::draw();
}

View File

@ -35,7 +35,7 @@
#include "lldockcontrol.h"
LLDockControl::LLDockControl(LLView* dockWidget, LLFloater* dockableFloater,
const LLUIImagePtr& dockTongue, DocAt dockAt, get_rect_callback_t get_rect_callback) :
const LLUIImagePtr& dockTongue, DocAt dockAt, get_allowed_rect_callback_t get_allowed_rect_callback) :
mDockWidget(dockWidget), mDockableFloater(dockableFloater), mDockTongue(dockTongue)
{
mDockAt = dockAt;
@ -49,13 +49,13 @@ LLDockControl::LLDockControl(LLView* dockWidget, LLFloater* dockableFloater,
off();
}
if (!(get_rect_callback))
if (!(get_allowed_rect_callback))
{
mGetRectCallback = boost::bind(&LLDockControl::getEnabledRect, this, _1);
mGetAllowedRectCallback = boost::bind(&LLDockControl::getAllowedRect, this, _1);
}
else
{
mGetRectCallback = get_rect_callback;
mGetAllowedRectCallback = get_allowed_rect_callback;
}
if (dockWidget != NULL)
@ -77,7 +77,7 @@ void LLDockControl::setDock(LLView* dockWidget)
}
}
void LLDockControl::getEnabledRect(LLRect& rect)
void LLDockControl::getAllowedRect(LLRect& rect)
{
rect = mDockableFloater->getRootView()->getRect();
}
@ -86,7 +86,7 @@ void LLDockControl::repositionDockable()
{
LLRect dockRect = mDockWidget->calcScreenRect();
LLRect rootRect;
mGetRectCallback(rootRect);
mGetAllowedRectCallback(rootRect);
static BOOL prev_visibility = !mDockWidget->getVisible();
// recalculate dockable position if dock position changed, dock visibility changed,
@ -100,7 +100,7 @@ void LLDockControl::repositionDockable()
mDockableFloater->setDocked(false);
// force off() since dockable may not have dockControll at this time
off();
}
}
else
{
moveDockable();
@ -123,10 +123,10 @@ bool LLDockControl::isDockVisible()
res = mDockWidget->isInVisibleChain();
if (res)
{
LLRect dockRect = mDockWidget->calcScreenRect();
LLRect dockRect = mDockWidget->calcScreenRect();
switch (mDockAt)
{
{
case TOP:
// check is dock inside parent rect
LLRect dockParentRect =
@ -149,25 +149,25 @@ void LLDockControl::moveDockable()
// calculate new dockable position
LLRect dockRect = mDockWidget->calcScreenRect();
LLRect rootRect;
mGetRectCallback(rootRect);
mGetAllowedRectCallback(rootRect);
LLRect dockableRect = mDockableFloater->calcScreenRect();
S32 x = 0;
S32 y = 0;
switch (mDockAt)
{
case TOP:
x = dockRect.getCenterX() - dockableRect.getWidth() / 2;
LLRect dockableRect = mDockableFloater->calcScreenRect();
S32 x = 0;
S32 y = 0;
switch (mDockAt)
{
case TOP:
x = dockRect.getCenterX() - dockableRect.getWidth() / 2;
y = dockRect.mTop + mDockTongue->getHeight() + dockableRect.getHeight();
// check is dockable inside root view rect
if (x < rootRect.mLeft)
{
x = rootRect.mLeft;
}
if (x + dockableRect.getWidth() > rootRect.mRight)
{
x = rootRect.mRight - dockableRect.getWidth();
}
if (x < rootRect.mLeft)
{
x = rootRect.mLeft;
}
if (x + dockableRect.getWidth() > rootRect.mRight)
{
x = rootRect.mRight - dockableRect.getWidth();
}
// calculate dock tongue position
@ -185,21 +185,21 @@ void LLDockControl::moveDockable()
{
mDockTongueX = dockRect.getCenterX() - mDockTongue->getWidth() / 2;
}
mDockTongueY = dockRect.mTop;
mDockTongueY = dockRect.mTop;
break;
}
break;
}
// move dockable
dockableRect.setLeftTopAndSize(x, y, dockableRect.getWidth(),
dockableRect.getHeight());
LLRect localDocableParentRect;
mDockableFloater->getParent()->screenRectToLocal(dockableRect,
&localDocableParentRect);
mDockableFloater->setRect(localDocableParentRect);
dockableRect.setLeftTopAndSize(x, y, dockableRect.getWidth(),
dockableRect.getHeight());
LLRect localDocableParentRect;
mDockableFloater->getParent()->screenRectToLocal(dockableRect,
&localDocableParentRect);
mDockableFloater->setRect(localDocableParentRect);
mDockableFloater->screenPointToLocal(mDockTongueX, mDockTongueY,
&mDockTongueX, &mDockTongueY);
mDockableFloater->screenPointToLocal(mDockTongueX, mDockTongueY,
&mDockTongueX, &mDockTongueY);
}
@ -207,9 +207,9 @@ void LLDockControl::on()
{
if (isDockVisible())
{
mDockableFloater->setCanDrag(false);
mEnabled = true;
mRecalculateDocablePosition = true;
mDockableFloater->setCanDrag(false);
mEnabled = true;
mRecalculateDocablePosition = true;
}
}

View File

@ -52,11 +52,11 @@ public:
public:
// callback for a function getting a rect valid for control's position
typedef boost::function<void (LLRect& )> get_rect_callback_t;
typedef boost::function<void (LLRect& )> get_allowed_rect_callback_t;
LOG_CLASS(LLDockControl);
LLDockControl(LLView* dockWidget, LLFloater* dockableFloater,
const LLUIImagePtr& dockTongue, DocAt dockAt, get_rect_callback_t get_rect_callback = NULL);
const LLUIImagePtr& dockTongue, DocAt dockAt, get_allowed_rect_callback_t get_rect_callback = NULL);
virtual ~LLDockControl();
public:
@ -67,13 +67,13 @@ public:
void drawToungue();
bool isDockVisible();
// gets a rect that bounds possible positions for a dockable control
void getEnabledRect(LLRect& rect);
// gets a rect that bounds possible positions for a dockable control (EXT-1111)
void getAllowedRect(LLRect& rect);
private:
virtual void moveDockable();
private:
get_rect_callback_t mGetRectCallback;
get_allowed_rect_callback_t mGetAllowedRectCallback;
bool mEnabled;
bool mRecalculateDocablePosition;
DocAt mDockAt;

View File

@ -39,8 +39,8 @@
static const LLDefaultChildRegistry::Register<LLFlatListView> flat_list_view("flat_list_view");
const LLSD SELECTED_EVENT = LLSD().insert("selected", true);
const LLSD UNSELECTED_EVENT = LLSD().insert("selected", false);
const LLSD SELECTED_EVENT = LLSD().insert("selected", true);
const LLSD UNSELECTED_EVENT = LLSD().insert("selected", false);
static const std::string COMMENT_TEXTBOX = "comment_text";

View File

@ -2001,6 +2001,8 @@ void LLTextEditor::cut()
deleteSelection( FALSE );
needsReflow();
onKeyStroke();
}
BOOL LLTextEditor::canCopy() const
@ -2105,6 +2107,8 @@ void LLTextEditor::pasteHelper(bool is_primary)
deselect();
needsReflow();
onKeyStroke();
}
@ -2492,6 +2496,8 @@ BOOL LLTextEditor::handleKeyHere(KEY key, MASK mask )
if(text_may_have_changed)
{
needsReflow();
onKeyStroke();
}
needsScroll();
}
@ -2534,6 +2540,8 @@ BOOL LLTextEditor::handleUnicodeCharHere(llwchar uni_char)
deselect();
needsReflow();
onKeyStroke();
}
return handled;
@ -2588,6 +2596,8 @@ void LLTextEditor::doDelete()
setCursorPos(mCursorPos + 1);
removeChar();
}
onKeyStroke();
}
needsReflow();
@ -2634,6 +2644,8 @@ void LLTextEditor::undo()
setCursorPos(pos);
needsReflow();
onKeyStroke();
}
BOOL LLTextEditor::canRedo() const
@ -2676,6 +2688,8 @@ void LLTextEditor::redo()
setCursorPos(pos);
needsReflow();
onKeyStroke();
}
void LLTextEditor::onFocusReceived()
@ -4402,6 +4416,8 @@ void LLTextEditor::updatePreedit(const LLWString &preedit_string,
// Update of the preedit should be caused by some key strokes.
mKeystrokeTimer.reset();
onKeyStroke();
}
BOOL LLTextEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect *bounds, LLRect *control) const
@ -4648,3 +4664,30 @@ void LLInlineViewSegment::linkToDocument(LLTextBase* editor)
ed->addDocumentChild(mView);
}
}
BOOL LLTextEditor::isDirty() const
{
if(mReadOnly)
{
return FALSE;
}
if( mPristineCmd )
{
return ( mPristineCmd == mLastCmd );
}
else
{
return ( NULL != mLastCmd );
}
}
void LLTextEditor::setKeystrokeCallback(const keystroke_signal_t::slot_type& callback)
{
mKeystrokeSignal.connect(callback);
}
void LLTextEditor::onKeyStroke()
{
mKeystrokeSignal(this);
}

View File

@ -139,6 +139,10 @@ public:
virtual ~LLTextEditor();
typedef boost::signals2::signal<void (LLTextEditor* caller)> keystroke_signal_t;
void setKeystrokeCallback(const keystroke_signal_t::slot_type& callback);
void setParseHighlights(BOOL parsing) {mParseHighlights=parsing;}
// mousehandler overrides
@ -169,7 +173,7 @@ public:
virtual void clear();
virtual void setFocus( BOOL b );
virtual BOOL acceptsTextInput() const;
virtual BOOL isDirty() const { return isPristine(); }
virtual BOOL isDirty() const;
virtual void setValue(const LLSD& value);
// LLEditMenuHandler interface
@ -503,6 +507,8 @@ private:
S32 getFirstVisibleLine() const;
void onKeyStroke();
//
// Data
//
@ -568,6 +574,8 @@ private:
BOOL mHandleEditKeysDirectly;
LLCoordGL mLastIMEPosition; // Last position of the IME editor
keystroke_signal_t mKeystrokeSignal;
}; // end class LLTextEditor

View File

@ -41,6 +41,10 @@
static LLDefaultChildRegistry::Register<LLAvatarList> r("avatar_list");
// Maximum number of avatars that can be added to a list in one pass.
// Used to limit time spent for avatar list update per frame.
static const unsigned ADD_LIMIT = 50;
static bool findInsensitive(std::string haystack, const std::string& needle_upper)
{
LLStringUtil::toUpper(haystack);
@ -65,6 +69,7 @@ LLAvatarList::LLAvatarList(const Params& p)
: LLFlatListView(p)
, mOnlineGoFirst(p.online_go_first)
, mContextMenu(NULL)
, mDirty(true) // to force initial update
{
setCommitOnSelectionChange(true);
@ -72,6 +77,138 @@ LLAvatarList::LLAvatarList(const Params& p)
setComparator(&NAME_COMPARATOR);
}
// virtual
void LLAvatarList::draw()
{
if (mDirty)
refresh();
LLFlatListView::draw();
}
void LLAvatarList::setNameFilter(const std::string& filter)
{
if (mNameFilter != filter)
{
mNameFilter = filter;
setDirty();
}
}
void LLAvatarList::sortByName()
{
setComparator(&NAME_COMPARATOR);
sort();
}
//////////////////////////////////////////////////////////////////////////
// PROTECTED SECTION
//////////////////////////////////////////////////////////////////////////
void LLAvatarList::refresh()
{
bool have_names = TRUE;
bool add_limit_exceeded = false;
bool modified = false;
bool have_filter = !mNameFilter.empty();
// Save selection.
std::vector<LLUUID> selected_ids;
getSelectedUUIDs(selected_ids);
LLUUID current_id = getSelectedUUID();
// Determine what to add and what to remove.
std::vector<LLUUID> added, removed;
LLAvatarList::computeDifference(getIDs(), added, removed);
// Handle added items.
unsigned nadded = 0;
for (std::vector<LLUUID>::const_iterator it=added.begin(); it != added.end(); it++)
{
std::string name;
const LLUUID& buddy_id = *it;
have_names &= (bool)gCacheName->getFullName(buddy_id, name);
if (!have_filter || findInsensitive(name, mNameFilter))
{
if (nadded >= ADD_LIMIT)
{
add_limit_exceeded = true;
break;
}
else
{
addNewItem(buddy_id, name, LLAvatarTracker::instance().isBuddyOnline(buddy_id));
modified = true;
nadded++;
}
}
}
// Handle removed items.
for (std::vector<LLUUID>::const_iterator it=removed.begin(); it != removed.end(); it++)
{
removeItemByUUID(*it);
modified = true;
}
// Handle filter.
if (have_filter)
{
std::vector<LLSD> cur_values;
getValues(cur_values);
for (std::vector<LLSD>::const_iterator it=cur_values.begin(); it != cur_values.end(); it++)
{
std::string name;
const LLUUID& buddy_id = it->asUUID();
have_names &= (bool)gCacheName->getFullName(buddy_id, name);
if (!findInsensitive(name, mNameFilter))
{
removeItemByUUID(buddy_id);
modified = true;
}
}
}
// Changed item in place, need to request sort and update columns
// because we might have changed data in a column on which the user
// has already sorted. JC
sort();
// re-select items
// selectMultiple(selected_ids); // TODO: implement in LLFlatListView if need
selectItemByUUID(current_id);
// If the name filter is specified and the names are incomplete,
// we need to re-update when the names are complete so that
// the filter can be applied correctly.
//
// Otherwise, if we have no filter then no need to update again
// because the items will update their names.
bool dirty = add_limit_exceeded || (have_filter && !have_names);
setDirty(dirty);
// Commit if we've added/removed items.
if (modified)
onCommit();
}
void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is_bold, EAddPosition pos)
{
LLAvatarListItem* item = new LLAvatarListItem();
item->showStatus(false);
item->showInfoBtn(true);
item->showSpeakingIndicator(true);
item->setName(name);
item->setAvatarId(id);
item->setContextMenu(mContextMenu);
item->childSetVisible("info_btn", false);
addItem(item, id, pos);
}
void LLAvatarList::computeDifference(
const std::vector<LLUUID>& vnew_unsorted,
std::vector<LLUUID>& vadded,
@ -106,97 +243,6 @@ void LLAvatarList::computeDifference(
vadded.erase(it, vadded.end());
}
BOOL LLAvatarList::update(const std::vector<LLUUID>& all_buddies, const std::string& name_filter)
{
BOOL have_names = TRUE;
bool have_filter = name_filter != LLStringUtil::null;
// Save selection.
std::vector<LLUUID> selected_ids;
getSelectedUUIDs(selected_ids);
LLUUID current_id = getSelectedUUID();
// Determine what to add and what to remove.
std::vector<LLUUID> added, removed;
LLAvatarList::computeDifference(all_buddies, added, removed);
// Handle added items.
for (std::vector<LLUUID>::const_iterator it=added.begin(); it != added.end(); it++)
{
std::string name;
const LLUUID& buddy_id = *it;
have_names &= gCacheName->getFullName(buddy_id, name);
if (!have_filter || findInsensitive(name, name_filter))
addNewItem(buddy_id, name, LLAvatarTracker::instance().isBuddyOnline(buddy_id));
}
// Handle removed items.
for (std::vector<LLUUID>::const_iterator it=removed.begin(); it != removed.end(); it++)
{
removeItemByUUID(*it);
}
// Handle filter.
if (have_filter)
{
std::vector<LLSD> cur_values;
getValues(cur_values);
for (std::vector<LLSD>::const_iterator it=cur_values.begin(); it != cur_values.end(); it++)
{
std::string name;
const LLUUID& buddy_id = it->asUUID();
have_names &= gCacheName->getFullName(buddy_id, name);
if (!findInsensitive(name, name_filter))
removeItemByUUID(buddy_id);
}
}
// Changed item in place, need to request sort and update columns
// because we might have changed data in a column on which the user
// has already sorted. JC
sort();
// re-select items
// selectMultiple(selected_ids); // TODO: implement in LLFlatListView if need
selectItemByUUID(current_id);
// If the name filter is specified and the names are incomplete,
// we need to re-update when the names are complete so that
// the filter can be applied correctly.
//
// Otherwise, if we have no filter then no need to update again
// because the items will update their names.
return !have_filter || have_names;
}
void LLAvatarList::sortByName()
{
setComparator(&NAME_COMPARATOR);
sort();
}
//////////////////////////////////////////////////////////////////////////
// PROTECTED SECTION
//////////////////////////////////////////////////////////////////////////
void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is_bold, EAddPosition pos)
{
LLAvatarListItem* item = new LLAvatarListItem();
item->showStatus(false);
item->showInfoBtn(true);
item->showSpeakingIndicator(true);
item->setName(name);
item->setAvatarId(id);
item->setContextMenu(mContextMenu);
item->childSetVisible("info_btn", false);
addItem(item, id, pos);
}
bool LLAvatarItemComparator::compare(const LLPanel* item1, const LLPanel* item2) const
{
const LLAvatarListItem* avatar_item1 = dynamic_cast<const LLAvatarListItem*>(item1);

View File

@ -37,10 +37,22 @@
#include "llavatarlistitem.h"
/**
* Generic list of avatars.
*
* Updates itself when it's dirty, using optional name filter.
* To initiate update, modify the UUID list and call setDirty().
*
* @see getIDs()
* @see setDirty()
* @see setNameFilter()
*/
class LLAvatarList : public LLFlatListView
{
LOG_CLASS(LLAvatarList);
public:
typedef std::vector<LLUUID> uuid_vector_t;
struct Params : public LLInitParam::Block<Params, LLFlatListView::Params>
{
Optional<S32> volume_column_width;
@ -51,14 +63,19 @@ public:
LLAvatarList(const Params&);
virtual ~LLAvatarList() {}
BOOL update(const std::vector<LLUUID>& all_buddies,
const std::string& name_filter = LLStringUtil::null);
virtual void draw(); // from LLView
void setNameFilter(const std::string& filter);
void setDirty(bool val = true) { mDirty = val; }
uuid_vector_t& getIDs() { return mIDs; }
void setContextMenu(LLAvatarListItem::ContextMenu* menu) { mContextMenu = menu; }
void sortByName();
protected:
void refresh();
void addNewItem(const LLUUID& id, const std::string& name, BOOL is_bold, EAddPosition pos = ADD_BOTTOM);
void computeDifference(
const std::vector<LLUUID>& vnew,
@ -68,6 +85,10 @@ protected:
private:
bool mOnlineGoFirst;
bool mDirty;
std::string mNameFilter;
uuid_vector_t mIDs;
LLAvatarListItem::ContextMenu* mContextMenu;
};

View File

@ -133,6 +133,7 @@ LLIMChiclet* LLBottomTray::createIMChiclet(const LLUUID& session_id)
case LLIMChiclet::TYPE_IM:
return getChicletPanel()->createChiclet<LLIMP2PChiclet>(session_id);
case LLIMChiclet::TYPE_GROUP:
case LLIMChiclet::TYPE_AD_HOC:
return getChicletPanel()->createChiclet<LLIMGroupChiclet>(session_id);
case LLIMChiclet::TYPE_UNKNOWN:
break;
@ -231,7 +232,7 @@ void LLBottomTray::showBottomTrayContextMenu(S32 x, S32 y, MASK mask)
mBottomTrayContextMenu->updateParent(LLMenuGL::sMenuContainer);
LLMenuGL::showPopup(this, mBottomTrayContextMenu, x, y);
}
}
}
void LLBottomTray::showGestureButton(BOOL visible)
@ -243,7 +244,7 @@ void LLBottomTray::showGestureButton(BOOL visible)
mGestureCombo->setVisible(visible);
if (!visible)
{
{
LLFloaterReg::hideFloaterInstance("gestures");
r.mRight -= mGestureCombo->getRect().getWidth();
}

View File

@ -77,7 +77,7 @@ LLScreenChannel* LLChannelManager::createNotificationChannel()
p.channel_align = CA_RIGHT;
// Getting a Channel for our notifications
return LLChannelManager::getInstance()->getChannel(p);
return dynamic_cast<LLScreenChannel*> (LLChannelManager::getInstance()->createChannel(p));
}
//--------------------------------------------------------------------------
@ -113,7 +113,7 @@ void LLChannelManager::onLoginCompleted()
LLChannelManager::Params p;
p.id = LLUUID(gSavedSettings.getString("StartUpChannelUUID"));
p.channel_align = CA_RIGHT;
mStartUpChannel = getChannel(p);
mStartUpChannel = createChannel(p);
if(!mStartUpChannel)
{
@ -147,22 +147,32 @@ void LLChannelManager::onStartUpToastClose()
LLScreenChannel::setStartUpToastShown();
// force NEARBY CHAT CHANNEL to repost all toasts if present
LLScreenChannel* nearby_channel = findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID")));
nearby_channel->loadStoredToastsToChannel();
nearby_channel->setCanStoreToasts(false);
//LLScreenChannelBase* nearby_channel = findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID")));
//!!!!!!!!!!!!!!
//FIXME
//nearby_channel->loadStoredToastsToChannel();
//nearby_channel->setCanStoreToasts(false);
}
//--------------------------------------------------------------------------
LLScreenChannel* LLChannelManager::getChannel(LLChannelManager::Params& p)
LLScreenChannelBase* LLChannelManager::addChannel(LLScreenChannelBase* channel)
{
LLScreenChannel* new_channel = NULL;
if(!channel)
return 0;
new_channel = findChannelByID(p.id);
ChannelElem new_elem;
new_elem.id = channel->getChannelID();
new_elem.channel = channel;
if(new_channel)
return new_channel;
mChannelList.push_back(new_elem);
new_channel = new LLScreenChannel(p.id);
return channel;
}
LLScreenChannel* LLChannelManager::createChannel(LLChannelManager::Params& p)
{
LLScreenChannel* new_channel = new LLScreenChannel(p.id);
if(!new_channel)
{
@ -172,20 +182,26 @@ LLScreenChannel* LLChannelManager::getChannel(LLChannelManager::Params& p)
{
new_channel->setToastAlignment(p.toast_align);
new_channel->setChannelAlignment(p.channel_align);
new_channel->setDisplayToastsAlways(p.display_toasts_always);
new_channel->setDisplayToastsAlways(p.display_toasts_always);
ChannelElem new_elem;
new_elem.id = p.id;
new_elem.channel = new_channel;
mChannelList.push_back(new_elem);
addChannel(new_channel);
}
return new_channel;
}
LLScreenChannelBase* LLChannelManager::getChannel(LLChannelManager::Params& p)
{
LLScreenChannelBase* new_channel = findChannelByID(p.id);
if(new_channel)
return new_channel;
return createChannel(p);
}
//--------------------------------------------------------------------------
LLScreenChannel* LLChannelManager::findChannelByID(const LLUUID id)
LLScreenChannelBase* LLChannelManager::findChannelByID(const LLUUID id)
{
std::vector<ChannelElem>::iterator it = find(mChannelList.begin(), mChannelList.end(), id);
if(it != mChannelList.end())

View File

@ -52,8 +52,8 @@ class LLChannelManager : public LLSingleton<LLChannelManager>
public:
struct Params
{
LLUUID id;
bool display_toasts_always;
LLUUID id;
bool display_toasts_always;
EToastAlignment toast_align;
EChannelAlignment channel_align;
@ -64,7 +64,7 @@ public:
struct ChannelElem
{
LLUUID id;
LLScreenChannel* channel;
LLScreenChannelBase* channel;
ChannelElem() : id(LLUUID("")), channel(NULL) { }
@ -89,19 +89,23 @@ public:
void onStartUpToastClose();
// creates a new ScreenChannel according to the given parameters or returns existing if present
LLScreenChannel* getChannel(LLChannelManager::Params& p);
LLScreenChannelBase* getChannel(LLChannelManager::Params& p);
LLScreenChannelBase* addChannel(LLScreenChannelBase* channel);
// returns a channel by its ID
LLScreenChannel* findChannelByID(const LLUUID id);
LLScreenChannelBase* findChannelByID(const LLUUID id);
// creator of the Notification channel, that is used in more than one handler
LLScreenChannel* createNotificationChannel();
LLScreenChannel* createNotificationChannel();
// remove channel methods
void removeChannelByID(const LLUUID id);
private:
LLScreenChannel* createChannel(LLChannelManager::Params& p);
LLScreenChannel* mStartUpChannel;
std::vector<ChannelElem> mChannelList;
};

View File

@ -44,6 +44,7 @@
#include "llviewercontrol.h"
#include "llagentdata.h"
/*
static const S32 BORDER_MARGIN = 2;
static const S32 PARENT_BORDER_MARGIN = 0;
@ -53,33 +54,27 @@ static const F32 MIN_AUTO_SCROLL_RATE = 120.f;
static const F32 MAX_AUTO_SCROLL_RATE = 500.f;
static const F32 AUTO_SCROLL_RATE_ACCEL = 120.f;
#define MAX_CHAT_HISTORY 100
*/
static const S32 msg_left_offset = 30;
static const S32 msg_right_offset = 10;
#define MAX_CHAT_HISTORY 100
static LLDefaultChildRegistry::Register<LLChatItemsContainerCtrl> t2("chat_items_container");
//static LLDefaultChildRegistry::Register<LLChatItemsContainerCtrl> t2("chat_items_container");
//*******************************************************************************************************************
//LLChatItemCtrl
//*******************************************************************************************************************
LLChatItemCtrl* LLChatItemCtrl::createInstance()
LLNearbyChatToastPanel* LLNearbyChatToastPanel::createInstance()
{
LLChatItemCtrl* item = new LLChatItemCtrl();
LLNearbyChatToastPanel* item = new LLNearbyChatToastPanel();
LLUICtrlFactory::getInstance()->buildPanel(item, "panel_chat_item.xml");
item->setFollows(FOLLOWS_NONE);
return item;
}
void LLChatItemCtrl::draw()
{
LLPanel::draw();
}
void LLChatItemCtrl::reshape (S32 width, S32 height, BOOL called_from_parent )
void LLNearbyChatToastPanel::reshape (S32 width, S32 height, BOOL called_from_parent )
{
LLPanel::reshape(width, height,called_from_parent);
@ -101,13 +96,13 @@ void LLChatItemCtrl::reshape (S32 width, S32 height, BOOL called_from_parent )
}
}
BOOL LLChatItemCtrl::postBuild()
BOOL LLNearbyChatToastPanel::postBuild()
{
return LLPanel::postBuild();
}
std::string LLChatItemCtrl::appendTime()
std::string LLNearbyChatToastPanel::appendTime()
{
time_t utc_time;
utc_time = time_corrected();
@ -124,48 +119,63 @@ std::string LLChatItemCtrl::appendTime()
void LLChatItemCtrl::addText (const std::string& message)
void LLNearbyChatToastPanel::addText (const std::string& message)
{
LLChatMsgBox* msg_text = getChild<LLChatMsgBox>("msg_text", false);
msg_text->addText(message);
mMessages.push_back(message);
}
void LLChatItemCtrl::setMessage (const LLChat& msg)
void LLNearbyChatToastPanel::init(LLSD& notification)
{
LLPanel* caption = getChild<LLPanel>("msg_caption", false);
mText = notification["message"].asString(); // UTF-8 line of text
mFromName = notification["from"].asString(); // agent or object name
mFromID = notification["from_id"].asUUID(); // agent id or object id
int sType = notification["source"].asInteger();
mSourceType = (EChatSourceType)sType;
std::string str_sender;
if(gAgentID != msg.mFromID)
str_sender = msg.mFromName;
if(gAgentID != mFromID)
str_sender = mFromName;
else
str_sender = LLTrans::getString("You");;
caption->getChild<LLTextBox>("sender_name", false)->setText(str_sender);
std::string tt = appendTime();
caption->getChild<LLTextBox>("msg_time", false)->setText(tt);
caption->getChild<LLTextBox>("msg_time", false)->setText(appendTime());
caption->getChild<LLAvatarIconCtrl>("avatar_icon", false)->setValue(msg.mFromID);
mOriginalMessage = msg;
LLChatMsgBox* msg_text = getChild<LLChatMsgBox>("msg_text", false);
msg_text->setText(msg.mText);
msg_text->setText(mText);
LLUICtrl* msg_inspector = caption->getChild<LLUICtrl>("msg_inspector");
if(mOriginalMessage.mSourceType != CHAT_SOURCE_AGENT)
if(mSourceType != CHAT_SOURCE_AGENT)
msg_inspector->setVisible(false);
mMessages.clear();
snapToMessageHeight ();
mIsDirty = true;//will set Avatar Icon in draw
}
void LLChatItemCtrl::snapToMessageHeight ()
void LLNearbyChatToastPanel::setMessage (const LLChat& chat_msg)
{
LLSD notification;
notification["message"] = chat_msg.mText;
notification["from"] = chat_msg.mFromName;
notification["from_id"] = chat_msg.mFromID;
notification["time"] = chat_msg.mTime;
notification["source"] = (S32)chat_msg.mSourceType;
init(notification);
}
void LLNearbyChatToastPanel::snapToMessageHeight ()
{
LLChatMsgBox* text_box = getChild<LLChatMsgBox>("msg_text", false);
S32 new_height = text_box->getTextPixelHeight();
@ -184,14 +194,14 @@ void LLChatItemCtrl::snapToMessageHeight ()
}
void LLChatItemCtrl::setWidth(S32 width)
void LLNearbyChatToastPanel::setWidth(S32 width)
{
LLChatMsgBox* text_box = getChild<LLChatMsgBox>("msg_text", false);
text_box->reshape(width - msg_left_offset - msg_right_offset,100/*its not magic number, we just need any number*/);
LLChatMsgBox* msg_text = getChild<LLChatMsgBox>("msg_text", false);
if(mOriginalMessage.mText.length())
msg_text->setText(mOriginalMessage.mText);
if(mText.length())
msg_text->setText(mText);
for(size_t i=0;i<mMessages.size();++i)
msg_text->addText(mMessages[i]);
@ -200,25 +210,25 @@ void LLChatItemCtrl::setWidth(S32 width)
snapToMessageHeight ();
}
void LLChatItemCtrl::onMouseLeave (S32 x, S32 y, MASK mask)
void LLNearbyChatToastPanel::onMouseLeave (S32 x, S32 y, MASK mask)
{
LLPanel* caption = getChild<LLPanel>("msg_caption", false);
LLUICtrl* msg_inspector = caption->getChild<LLUICtrl>("msg_inspector");
msg_inspector->setVisible(false);
}
void LLChatItemCtrl::onMouseEnter (S32 x, S32 y, MASK mask)
void LLNearbyChatToastPanel::onMouseEnter (S32 x, S32 y, MASK mask)
{
if(mOriginalMessage.mSourceType != CHAT_SOURCE_AGENT)
if(mSourceType != CHAT_SOURCE_AGENT)
return;
LLPanel* caption = getChild<LLPanel>("msg_caption", false);
LLUICtrl* msg_inspector = caption->getChild<LLUICtrl>("msg_inspector");
msg_inspector->setVisible(true);
}
BOOL LLChatItemCtrl::handleMouseDown (S32 x, S32 y, MASK mask)
BOOL LLNearbyChatToastPanel::handleMouseDown (S32 x, S32 y, MASK mask)
{
if(mOriginalMessage.mSourceType != CHAT_SOURCE_AGENT)
if(mSourceType != CHAT_SOURCE_AGENT)
return LLPanel::handleMouseDown(x,y,mask);
LLPanel* caption = getChild<LLPanel>("msg_caption", false);
LLUICtrl* msg_inspector = caption->getChild<LLUICtrl>("msg_inspector");
@ -226,12 +236,16 @@ BOOL LLChatItemCtrl::handleMouseDown (S32 x, S32 y, MASK mask)
S32 local_y = y - msg_inspector->getRect().mBottom - caption->getRect().mBottom;
if(msg_inspector->pointInView(local_x, local_y))
{
LLFloaterReg::showInstance("inspect_avatar", mOriginalMessage.mFromID);
LLFloaterReg::showInstance("inspect_avatar", mFromID);
}
else
{
LLFloaterReg::showInstance("nearby_chat",LLSD());
}
return LLPanel::handleMouseDown(x,y,mask);
}
void LLChatItemCtrl::setHeaderVisibility(EShowItemHeader e)
void LLNearbyChatToastPanel::setHeaderVisibility(EShowItemHeader e)
{
LLPanel* caption = getChild<LLPanel>("msg_caption", false);
@ -243,7 +257,7 @@ void LLChatItemCtrl::setHeaderVisibility(EShowItemHeader e)
}
bool LLChatItemCtrl::canAddText ()
bool LLNearbyChatToastPanel::canAddText ()
{
LLChatMsgBox* msg_text = findChild<LLChatMsgBox>("msg_text");
if(!msg_text)
@ -251,7 +265,7 @@ bool LLChatItemCtrl::canAddText ()
return msg_text->getTextLinesNum()<10;
}
BOOL LLChatItemCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask)
BOOL LLNearbyChatToastPanel::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
LLPanel* caption = getChild<LLPanel>("msg_caption", false);
LLUICtrl* avatar_icon = caption->getChild<LLUICtrl>("avatar_icon", false);
@ -260,296 +274,20 @@ BOOL LLChatItemCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask)
S32 local_y = y - avatar_icon->getRect().mBottom - caption->getRect().mBottom;
//eat message for avatar icon if msg was from object
if(avatar_icon->pointInView(local_x, local_y) && mOriginalMessage.mSourceType != CHAT_SOURCE_AGENT)
if(avatar_icon->pointInView(local_x, local_y) && mSourceType != CHAT_SOURCE_AGENT)
return TRUE;
return LLPanel::handleRightMouseDown(x,y,mask);
}
//*******************************************************************************************************************
//LLChatItemsContainerCtrl
//*******************************************************************************************************************
LLChatItemsContainerCtrl::LLChatItemsContainerCtrl(const Params& params):LLPanel(params)
void LLNearbyChatToastPanel::draw()
{
mEShowItemHeader = CHATITEMHEADER_SHOW_BOTH;
}
void LLChatItemsContainerCtrl::addMessage(const LLChat& msg)
{
/*
if(msg.mChatType == CHAT_TYPE_DEBUG_MSG)
return;
*/
if(mItems.size() >= MAX_CHAT_HISTORY)
if(mIsDirty)
{
LLChatItemCtrl* item = mItems[0];
removeChild(item);
delete item;
mItems.erase(mItems.begin());
}
if(mItems.size() > 0
&& msg.mFromID == mItems[mItems.size()-1]->getMessage().mFromID
&& (msg.mTime-mItems[mItems.size()-1]->getMessage().mTime)<60
&& mItems[mItems.size()-1]->canAddText()
)
{
mItems[mItems.size()-1]->addText(msg.mText);
mItems[mItems.size()-1]->snapToMessageHeight();
}
else
{
LLChatItemCtrl* item = LLChatItemCtrl::createInstance();
mItems.push_back(item);
addChild(item,0);
item->setWidth(getRect().getWidth() - 16);
item->setMessage(msg);
item->snapToMessageHeight();
item->setHeaderVisibility((EShowItemHeader)gSavedSettings.getS32("nearbychat_showicons_and_names"));
item->setVisible(true);
}
arrange(getRect().getWidth(),getRect().getHeight());
updateLayout(getRect().getWidth(),getRect().getHeight());
scrollToBottom();
}
void LLChatItemsContainerCtrl::scrollToBottom ()
{
if(mScrollbar->getVisible())
{
mScrollbar->setDocPos(mScrollbar->getDocPosMax());
onScrollPosChangeCallback(0,0);
}
}
void LLChatItemsContainerCtrl::draw()
{
LLLocalClipRect clip(getRect());
LLPanel::draw();
}
void LLChatItemsContainerCtrl::reshape (S32 width, S32 height, BOOL called_from_parent )
{
S32 delta_width = width - getRect().getWidth();
S32 delta_height = height - getRect().getHeight();
if (delta_width || delta_height || sForceReshape)
{
arrange(width, height);
}
updateBoundingRect();
}
void LLChatItemsContainerCtrl::arrange (S32 width, S32 height)
{
S32 delta_width = width - getRect().getWidth();
if(delta_width)//width changed...too bad. now we need to reformat all items
reformatHistoryScrollItems(width);
calcRecuiredHeight();
show_hide_scrollbar(width,height);
updateLayout(width,height);
}
void LLChatItemsContainerCtrl::reformatHistoryScrollItems(S32 width)
{
for(std::vector<LLChatItemCtrl*>::iterator it = mItems.begin(); it != mItems.end();++it)
{
(*it)->setWidth(width);
}
}
S32 LLChatItemsContainerCtrl::calcRecuiredHeight ()
{
S32 rec_height = 0;
std::vector<LLChatItemCtrl*>::iterator it;
for(it=mItems.begin(); it!=mItems.end(); ++it)
{
rec_height += (*it)->getRect().getHeight();
}
mInnerRect.setLeftTopAndSize(0,rec_height + BORDER_MARGIN*2,getRect().getWidth(),rec_height + BORDER_MARGIN);
return mInnerRect.getHeight();
}
void LLChatItemsContainerCtrl::updateLayout (S32 width, S32 height)
{
S32 panel_top = height - BORDER_MARGIN ;
S32 panel_width = width;
if(mScrollbar->getVisible())
{
static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
panel_top+=mScrollbar->getDocPos();
panel_width-=scrollbar_size;
}
//set sizes for first panels and dragbars
for(size_t i=0;i<mItems.size();++i)
{
LLRect panel_rect = mItems[i]->getRect();
panelSetLeftTopAndSize(mItems[i],panel_rect.mLeft,panel_top,panel_width,panel_rect.getHeight());
panel_top-=panel_rect.getHeight();
}
}
void LLChatItemsContainerCtrl::show_hide_scrollbar (S32 width, S32 height)
{
calcRecuiredHeight();
if(getRecuiredHeight() > height )
showScrollbar(width, height);
else
hideScrollbar(width, height);
}
void LLChatItemsContainerCtrl::showScrollbar (S32 width, S32 height)
{
bool was_visible = mScrollbar->getVisible();
mScrollbar->setVisible(true);
static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
panelSetLeftTopAndSize(mScrollbar,width-scrollbar_size
,height-PARENT_BORDER_MARGIN,scrollbar_size,height-2*PARENT_BORDER_MARGIN);
mScrollbar->setPageSize(height);
mScrollbar->setDocParams(mInnerRect.getHeight(),mScrollbar->getDocPos());
if(was_visible)
{
S32 scroll_pos = llmin(mScrollbar->getDocPos(), getRecuiredHeight() - height - 1);
mScrollbar->setDocPos(scroll_pos);
updateLayout(width,height);
return;
}
}
void LLChatItemsContainerCtrl::hideScrollbar (S32 width, S32 height)
{
if(mScrollbar->getVisible() == false)
return;
mScrollbar->setVisible(false);
mScrollbar->setDocPos(0);
if(mItems.size()>0)
{
S32 panel_top = height - BORDER_MARGIN; // Top coordinate of the first panel
S32 diff = panel_top - mItems[0]->getRect().mTop;
shiftPanels(diff);
}
}
//---------------------------------------------------------------------------------
void LLChatItemsContainerCtrl::panelSetLeftTopAndSize(LLView* panel, S32 left, S32 top, S32 width, S32 height)
{
if(!panel)
return;
LLRect panel_rect = panel->getRect();
panel_rect.setLeftTopAndSize( left, top, width, height);
panel->reshape( width, height, 1);
panel->setRect(panel_rect);
}
void LLChatItemsContainerCtrl::panelShiftVertical(LLView* panel,S32 delta)
{
if(!panel)
return;
panel->translate(0,delta);
}
void LLChatItemsContainerCtrl::shiftPanels(S32 delta)
{
//Arrange panels
for(std::vector<LLChatItemCtrl*>::iterator it = mItems.begin(); it != mItems.end();++it)
{
panelShiftVertical((*it),delta);
}
}
//---------------------------------------------------------------------------------
void LLChatItemsContainerCtrl::onScrollPosChangeCallback(S32, LLScrollbar*)
{
updateLayout(getRect().getWidth(),getRect().getHeight());
}
BOOL LLChatItemsContainerCtrl::postBuild()
{
static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
LLRect scroll_rect;
scroll_rect.setOriginAndSize(
getRect().getWidth() - scrollbar_size,
1,
scrollbar_size,
getRect().getHeight() - 1);
LLScrollbar::Params sbparams;
sbparams.name("scrollable vertical");
sbparams.rect(scroll_rect);
sbparams.orientation(LLScrollbar::VERTICAL);
sbparams.doc_size(mInnerRect.getHeight());
sbparams.doc_pos(0);
sbparams.page_size(mInnerRect.getHeight());
sbparams.step_size(VERTICAL_MULTIPLE);
sbparams.follows.flags(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM);
sbparams.change_callback(boost::bind(&LLChatItemsContainerCtrl::onScrollPosChangeCallback, this, _1, _2));
mScrollbar = LLUICtrlFactory::create<LLScrollbar> (sbparams);
LLView::addChild( mScrollbar );
mScrollbar->setVisible( true );
mScrollbar->setFollowsRight();
mScrollbar->setFollowsTop();
mScrollbar->setFollowsBottom();
reformatHistoryScrollItems(getRect().getWidth());
arrange(getRect().getWidth(),getRect().getHeight());
return LLPanel::postBuild();
}
BOOL LLChatItemsContainerCtrl::handleMouseDown (S32 x, S32 y, MASK mask)
{
return LLPanel::handleMouseDown(x,y,mask);
}
BOOL LLChatItemsContainerCtrl::handleKeyHere (KEY key, MASK mask)
{
if( mScrollbar->getVisible() && mScrollbar->handleKeyHere( key,mask ) )
return TRUE;
return LLPanel::handleKeyHere(key,mask);
}
BOOL LLChatItemsContainerCtrl::handleScrollWheel ( S32 x, S32 y, S32 clicks )
{
if( mScrollbar->getVisible() && mScrollbar->handleScrollWheel( 0, 0, clicks ) )
return TRUE;
return false;
}
void LLChatItemsContainerCtrl::setHeaderVisibility(EShowItemHeader e)
{
if(e == mEShowItemHeader)
return;
mEShowItemHeader = e;
for(std::vector<LLChatItemCtrl*>::iterator it = mItems.begin(); it != mItems.end();++it)
{
(*it)->setHeaderVisibility(e);
LLPanel* caption = findChild<LLPanel>("msg_caption", false);
if(caption)
caption->getChild<LLAvatarIconCtrl>("avatar_icon", false)->setValue(mFromID);
mIsDirty = false;
}
LLToastPanelBase::draw();
}

View File

@ -37,6 +37,7 @@
#include "llscrollbar.h"
#include "string"
#include "llchat.h"
#include "lltoastpanel.h"
typedef enum e_show_item_header
{
@ -45,20 +46,18 @@ typedef enum e_show_item_header
CHATITEMHEADER_SHOW_BOTH
} EShowItemHeader;
class LLChatItemCtrl: public LLPanel
class LLNearbyChatToastPanel: public LLToastPanelBase
{
protected:
LLChatItemCtrl(){};
LLNearbyChatToastPanel():mIsDirty(false){};
public:
~LLChatItemCtrl(){}
~LLNearbyChatToastPanel(){}
static LLChatItemCtrl* createInstance();
static LLNearbyChatToastPanel* createInstance();
void draw();
const LLChat& getMessage() const { return mOriginalMessage;}
const LLUUID& getFromID() const { return mFromID;}
void addText (const std::string& message);
void setMessage (const LLChat& msg);
@ -77,77 +76,26 @@ public:
void setHeaderVisibility(EShowItemHeader e);
BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
virtual void init(LLSD& data);
virtual void draw();
private:
std::string appendTime ();
private:
LLChat mOriginalMessage;
std::string mText; // UTF-8 line of text
std::string mFromName; // agent or object name
LLUUID mFromID; // agent id or object id
EChatSourceType mSourceType;
std::vector<std::string> mMessages;
bool mIsDirty;
};
class LLChatItemsContainerCtrl: public LLPanel
{
public:
struct Params
: public LLInitParam::Block<Params, LLPanel::Params>
{
Params(){};
};
LLChatItemsContainerCtrl(const Params& params);
~LLChatItemsContainerCtrl(){}
void addMessage (const LLChat& msg);
void draw();
void reshape (S32 width, S32 height, BOOL called_from_parent = TRUE);
void onScrollPosChangeCallback(S32, LLScrollbar*);
virtual BOOL postBuild();
BOOL handleMouseDown (S32 x, S32 y, MASK mask);
BOOL handleKeyHere (KEY key, MASK mask);
BOOL handleScrollWheel( S32 x, S32 y, S32 clicks );
void scrollToBottom ();
void setHeaderVisibility(EShowItemHeader e);
EShowItemHeader getHeaderVisibility() const { return mEShowItemHeader;};
private:
void reformatHistoryScrollItems(S32 width);
void arrange (S32 width, S32 height);
S32 calcRecuiredHeight ();
S32 getRecuiredHeight () const { return mInnerRect.getHeight(); }
void updateLayout (S32 width, S32 height);
void show_hide_scrollbar (S32 width, S32 height);
void showScrollbar (S32 width, S32 height);
void hideScrollbar (S32 width, S32 height);
void panelSetLeftTopAndSize (LLView* panel, S32 left, S32 top, S32 width, S32 height);
void panelShiftVertical (LLView* panel,S32 delta);
void shiftPanels (S32 delta);
private:
std::vector<LLChatItemCtrl*> mItems;
EShowItemHeader mEShowItemHeader;
LLRect mInnerRect;
LLScrollbar* mScrollbar;
};
#endif

View File

@ -102,7 +102,7 @@ void LLChatMsgBox::drawText(S32 x, S32 y, const LLWString &text, const LLColor4
// iterate through each block of text that has been added
y -= mLineSpacing;
for (std::vector<S32>::iterator it = mSeparatorOffset.begin(); true ;)
for (std::vector<S32>::iterator it = mSeparatorOffset.begin(); it != mSeparatorOffset.end() ;)
{
// display the text for this block
S32 num_chars = *it - start;

View File

@ -49,6 +49,7 @@
#include "llvoicecontrolpanel.h"
#include "llgroupmgr.h"
#include "llnotificationmanager.h"
#include "lltransientfloatermgr.h"
static LLDefaultChildRegistry::Register<LLChicletPanel> t1("chiclet_panel");
static LLDefaultChildRegistry::Register<LLTalkButton> t2("chiclet_talk");
@ -243,26 +244,36 @@ void LLIMChiclet::draw()
LLIMChiclet::EType LLIMChiclet::getIMSessionType(const LLUUID& session_id)
{
EType type = TYPE_UNKNOWN;
LLFloaterIMPanel* im = NULL;
if(session_id.isNull())
return type;
if (!(im = LLIMMgr::getInstance()->findFloaterBySession(session_id)))
EInstantMessage im_type = LLIMModel::getInstance()->getType(session_id);
if (IM_COUNT == im_type)
{
llassert_always(0 && "IM session not found"); // should never happen
return type;
}
switch(im->getDialogType())
switch(im_type)
{
case IM_NOTHING_SPECIAL:
case IM_SESSION_P2P_INVITE:
type = TYPE_IM;
break;
case IM_SESSION_GROUP_START:
case IM_SESSION_INVITE:
type = TYPE_GROUP;
if (gAgent.isInGroup(session_id))
{
type = TYPE_GROUP;
}
else
{
type = TYPE_AD_HOC;
}
break;
case IM_SESSION_CONFERENCE_START:
type = TYPE_AD_HOC;
default:
break;
}
@ -285,6 +296,11 @@ LLIMP2PChiclet::Params::Params()
avatar_icon.name("avatar_icon");
avatar_icon.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP | FOLLOWS_BOTTOM);
// *NOTE dzaporozhan
// Changed icon height from 25 to 24 to fix ticket EXT-794.
// In some cases(after changing UI scale) 25 pixel height icon was
// drawn incorrectly, i'm not sure why.
avatar_icon.rect(LLRect(0, 24, 25, 0));
avatar_icon.mouse_opaque(false);
@ -458,6 +474,11 @@ LLIMGroupChiclet::Params::Params()
rect(LLRect(0, 25, 45, 0));
group_icon.name("group_icon");
// *NOTE dzaporozhan
// Changed icon height from 25 to 24 to fix ticket EXT-794.
// In some cases(after changing UI scale) 25 pixel height icon was
// drawn incorrectly, i'm not sure why.
group_icon.rect(LLRect(0, 24, 25, 0));
unread_notifications.name("unread");
@ -1164,6 +1185,7 @@ LLTalkButton::LLTalkButton(const Params& p)
speak_params.rect(speak_rect);
mSpeakBtn = LLUICtrlFactory::create<LLButton>(speak_params);
addChild(mSpeakBtn);
LLTransientFloaterMgr::getInstance()->addControlView(mSpeakBtn);
mSpeakBtn->setClickedCallback(boost::bind(&LLTalkButton::onClick_SpeakBtn, this));
mSpeakBtn->setToggleState(FALSE);
@ -1172,6 +1194,7 @@ LLTalkButton::LLTalkButton(const Params& p)
show_params.rect(show_rect);
mShowBtn = LLUICtrlFactory::create<LLButton>(show_params);
addChild(mShowBtn);
LLTransientFloaterMgr::getInstance()->addControlView(mShowBtn);
mShowBtn->setClickedCallback(boost::bind(&LLTalkButton::onClick_ShowBtn, this));
mShowBtn->setToggleState(FALSE);

View File

@ -275,7 +275,8 @@ public:
enum EType {
TYPE_UNKNOWN,
TYPE_IM,
TYPE_GROUP
TYPE_GROUP,
TYPE_AD_HOC
};
/*virtual*/ ~LLIMChiclet() {};

View File

@ -934,6 +934,17 @@ void LLFavoritesBarCtrl::onButtonRightClick( LLUUID item_id,LLView* fav_button,S
LLMenuGL::showPopup(fav_button, menu, x, y);
}
BOOL LLFavoritesBarCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
BOOL handled = childrenHandleRightMouseDown( x, y, mask) != NULL;
if(!handled && !gMenuHolder->hasVisibleMenu())
{
show_navbar_context_menu(this,x,y);
handled = true;
}
return handled;
}
void copy_slurl_to_clipboard_cb(std::string& slurl)
{
gClipboard.copyFromString(utf8str_to_wstring(slurl));

View File

@ -62,7 +62,7 @@ public:
std::string& tooltip_msg);
/*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
// LLInventoryObserver observer trigger
virtual void changed(U32 mask);
virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);

View File

@ -363,7 +363,8 @@ LLFloater* LLFloaterChatterBox::getCurrentVoiceFloater()
{
// only LLFloaterIMPanels are called "im_floater"
LLFloaterIMPanel* im_floaterp = (LLFloaterIMPanel*)panelp;
if (im_floaterp->getVoiceChannel() == LLVoiceChannel::getCurrentVoiceChannel())
LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(im_floaterp->getSessionID());
if (voice_channel == LLVoiceChannel::getCurrentVoiceChannel())
{
return im_floaterp;
}

View File

@ -73,7 +73,11 @@ LLGroupList::Params::Params()
LLGroupList::LLGroupList(const Params& p)
: LLFlatListView(p)
, mDirty(true) // to force initial update
{
// Listen for agent group changes.
gAgent.addListener(this, "new group");
mShowIcons = gSavedSettings.getBOOL("GroupListShowIcons");
setCommitOnSelectionChange(true);
// TODO: implement context menu
@ -84,17 +88,41 @@ LLGroupList::LLGroupList(const Params& p)
setComparator(&GROUP_COMPARATOR);
}
LLGroupList::~LLGroupList()
{
gAgent.removeListener(this);
}
// virtual
void LLGroupList::draw()
{
if (mDirty)
refresh();
LLFlatListView::draw();
}
void LLGroupList::setNameFilter(const std::string& filter)
{
if (mNameFilter != filter)
{
mNameFilter = filter;
setDirty();
}
}
static bool findInsensitive(std::string haystack, const std::string& needle_upper)
{
LLStringUtil::toUpper(haystack);
return haystack.find(needle_upper) != std::string::npos;
}
BOOL LLGroupList::update(const std::string& name_filter)
void LLGroupList::refresh()
{
const LLUUID& highlight_id = gAgent.getGroupID();
S32 count = gAgent.mGroups.count();
LLUUID id;
bool have_filter = !mNameFilter.empty();
clear();
@ -102,7 +130,7 @@ BOOL LLGroupList::update(const std::string& name_filter)
{
id = gAgent.mGroups.get(i).mID;
const LLGroupData& group_data = gAgent.mGroups.get(i);
if (name_filter != LLStringUtil::null && !findInsensitive(group_data.mName, name_filter))
if (have_filter && !findInsensitive(group_data.mName, mNameFilter))
continue;
addNewItem(id, group_data.mName, group_data.mInsigniaID, highlight_id == id, ADD_BOTTOM);
}
@ -113,13 +141,14 @@ BOOL LLGroupList::update(const std::string& name_filter)
// add "none" to list at top
{
std::string loc_none = LLTrans::getString("GroupsNone");
if (name_filter == LLStringUtil::null || findInsensitive(loc_none, name_filter))
if (have_filter || findInsensitive(loc_none, mNameFilter))
addNewItem(LLUUID::null, loc_none, LLUUID::null, highlight_id.isNull(), ADD_TOP);
}
selectItemByUUID(highlight_id);
return TRUE;
setDirty(false);
onCommit();
}
void LLGroupList::toggleIcons()
@ -158,6 +187,18 @@ void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LL
// setCommentVisible(false);
}
// virtual
bool LLGroupList::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
{
// Why is "new group" sufficient?
if (event->desc() == "new group")
{
setDirty();
return true;
}
return false;
}
/************************************************************************/
/* LLGroupListItem implementation */

View File

@ -33,10 +33,19 @@
#ifndef LL_LLGROUPLIST_H
#define LL_LLGROUPLIST_H
#include "llevent.h"
#include "llflatlistview.h"
#include "llpanel.h"
#include "llpointer.h"
class LLGroupList: public LLFlatListView
/**
* Auto-updating list of agent groups.
*
* Can use optional group name filter.
*
* @see setNameFilter()
*/
class LLGroupList: public LLFlatListView, public LLOldEvents::LLSimpleListener
{
LOG_CLASS(LLGroupList);
public:
@ -46,14 +55,23 @@ public:
};
LLGroupList(const Params& p);
BOOL update(const std::string& name_filter = LLStringUtil::null);
virtual ~LLGroupList();
virtual void draw(); // from LLView
void setNameFilter(const std::string& filter);
void toggleIcons();
bool getIconsVisible() const { return mShowIcons; }
private:
void setDirty(bool val = true) { mDirty = val; }
void refresh();
void addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, BOOL is_bold, EAddPosition pos = ADD_BOTTOM);
bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); // called on agent group list changes
bool mShowIcons;
bool mDirty;
std::string mNameFilter;
};
class LLButton;

View File

@ -48,6 +48,7 @@
#include "lltrans.h"
#include "llviewertexteditor.h"
#include "llviewerwindow.h"
#include "lltransientfloatermgr.h"
@ -62,33 +63,46 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)
mInputEditor(NULL),
mPositioned(false)
{
LLIMModel::LLIMSession* session = get_if_there(LLIMModel::instance().sSessionsMap, mSessionID, (LLIMModel::LLIMSession*)NULL);
if(session)
EInstantMessage type = LLIMModel::getInstance()->getType(session_id);
if(IM_COUNT != type)
{
mDialog = session->mType;
}
mDialog = type;
if (mDialog == IM_NOTHING_SPECIAL)
{
mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelIMControl, this);
if (IM_NOTHING_SPECIAL == mDialog || IM_SESSION_P2P_INVITE == mDialog)
{
mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelIMControl, this);
}
else
{
mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this);
}
}
else
{
mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this);
}
// LLUICtrlFactory::getInstance()->buildFloater(this, "floater_im_session.xml");
LLUI::getRootView()->setFocusLostCallback(boost::bind(&LLIMFloater::focusChangeCallback, this));
mCloseSignal.connect(boost::bind(&LLIMFloater::onClose, this));
LLTransientFloaterMgr::getInstance()->registerTransientFloater(this);
}
void LLIMFloater::onClose()
{
LLIMModel::instance().sendLeaveSession(mSessionID, mOtherParticipantUUID);
//*TODO - move to the IMModel::sendLeaveSession() for the integrity (IB)
gIMMgr->removeSession(mSessionID);
}
void LLIMFloater::setMinimized(BOOL minimize)
{
if(!isDocked())
{
setVisible(!minimize);
}
LLFloater::setMinimized(minimize);
}
/* static */
void LLIMFloater::newIMCallback(const LLSD& data){
@ -152,16 +166,17 @@ void LLIMFloater::sendMsg()
LLIMFloater::~LLIMFloater()
{
LLTransientFloaterMgr::getInstance()->unregisterTransientFloater(this);
}
//virtual
BOOL LLIMFloater::postBuild()
{
LLIMModel::LLIMSession* session = get_if_there(LLIMModel::instance().sSessionsMap, mSessionID, (LLIMModel::LLIMSession*)NULL);
if(session)
const LLUUID& other_party_id = LLIMModel::getInstance()->getOtherParticipantID(mSessionID);
if (other_party_id.notNull())
{
mOtherParticipantUUID = session->mOtherParticipantID;
mControlPanel->setID(session->mOtherParticipantID);
mOtherParticipantUUID = other_party_id;
mControlPanel->setID(mOtherParticipantUUID);
}
LLButton* slide_left = getChild<LLButton>("slide_left_btn");
@ -216,17 +231,6 @@ void* LLIMFloater::createPanelGroupControl(void* userdata)
return self->mControlPanel;
}
void LLIMFloater::focusChangeCallback()
{
// hide docked floater if user clicked inside in-world area
if (isDocked())
{
setVisible(false);
}
}
void LLIMFloater::onSlide()
{
LLPanel* im_control_panel = getChild<LLPanel>("panel_im_control_panel");
@ -271,13 +275,13 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id)
}
floater->setDockControl(new LLDockControl(chiclet, floater, floater->getDockTongue(),
LLDockControl::TOP, boost::bind(&LLIMFloater::getEnabledRect, floater, _1)));
LLDockControl::TOP, boost::bind(&LLIMFloater::getAllowedRect, floater, _1)));
}
return floater;
}
void LLIMFloater::getEnabledRect(LLRect& rect)
void LLIMFloater::getAllowedRect(LLRect& rect)
{
rect = gViewerWindow->getWorldViewRect();
}
@ -285,8 +289,10 @@ void LLIMFloater::getEnabledRect(LLRect& rect)
void LLIMFloater::setDocked(bool docked, bool pop_on_undock)
{
// update notification channel state
LLNotificationsUI::LLScreenChannel* channel = LLNotificationsUI::LLChannelManager::getInstance()->
findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")));
LLNotificationsUI::LLScreenChannel* channel = dynamic_cast<LLNotificationsUI::LLScreenChannel*>
(LLNotificationsUI::LLChannelManager::getInstance()->
findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID"))));
LLDockableFloater::setDocked(docked, pop_on_undock);
// update notification channel state
@ -298,8 +304,9 @@ void LLIMFloater::setDocked(bool docked, bool pop_on_undock)
void LLIMFloater::setVisible(BOOL visible)
{
LLNotificationsUI::LLScreenChannel* channel = LLNotificationsUI::LLChannelManager::getInstance()->
findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")));
LLNotificationsUI::LLScreenChannel* channel = dynamic_cast<LLNotificationsUI::LLScreenChannel*>
(LLNotificationsUI::LLChannelManager::getInstance()->
findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID"))));
LLDockableFloater::setVisible(visible);
// update notification channel state

View File

@ -57,6 +57,8 @@ public:
// LLFloater overrides
/*virtual*/ void setDocked(bool docked, bool pop_on_undock = true);
// override LLFloater's minimization according to EXT-1216
/*virtual*/ void setMinimized(BOOL minimize);
// Make IM conversion visible and update the message history
static LLIMFloater* show(const LLUUID& session_id);
@ -90,8 +92,8 @@ private:
void onSlide();
static void* createPanelIMControl(void* userdata);
static void* createPanelGroupControl(void* userdata);
void focusChangeCallback();
void getEnabledRect(LLRect& rect);
// gets a rect that bounds possible positions for the LLIMFloater on a screen (EXT-1111)
void getAllowedRect(LLRect& rect);
LLPanelChatControlPanel* mControlPanel;
LLUUID mSessionID;

View File

@ -109,7 +109,9 @@ bool LLIMHandler::processNotification(const LLSD& notify)
p.panel = im_box;
p.can_be_stored = false;
p.on_delete_toast = boost::bind(&LLIMHandler::onDeleteToast, this, _1);
mChannel->addToast(p);
LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel);
if(channel)
channel->addToast(p);
// send a signal to the counter manager;
mNewNotificationSignal();

View File

@ -940,7 +940,6 @@ LLFloaterIMPanel::LLFloaterIMPanel(const std::string& session_label,
mHistoryEditor(NULL),
mSessionUUID(session_id),
mSessionLabel(session_label),
mVoiceChannel(NULL),
mSessionInitialized(FALSE),
mSessionStartMsgPos(0),
mOtherParticipantUUID(other_participant_id),
@ -956,7 +955,6 @@ LLFloaterIMPanel::LLFloaterIMPanel(const std::string& session_label,
mTextIMPossible(TRUE),
mProfileButtonEnabled(TRUE),
mCallBackEnabled(TRUE),
mSpeakers(NULL),
mSpeakerPanel(NULL),
mFirstKeystrokeTimer(),
mLastKeystrokeTimer()
@ -967,7 +965,6 @@ LLFloaterIMPanel::LLFloaterIMPanel(const std::string& session_label,
case IM_SESSION_GROUP_START:
mFactoryMap["active_speakers_panel"] = LLCallbackMap(createSpeakersPanel, this);
xml_filename = "floater_instant_message_group.xml";
mVoiceChannel = new LLVoiceChannelGroup(mSessionUUID, mSessionLabel);
break;
case IM_SESSION_INVITE:
mFactoryMap["active_speakers_panel"] = LLCallbackMap(createSpeakersPanel, this);
@ -979,16 +976,13 @@ LLFloaterIMPanel::LLFloaterIMPanel(const std::string& session_label,
{
xml_filename = "floater_instant_message_ad_hoc.xml";
}
mVoiceChannel = new LLVoiceChannelGroup(mSessionUUID, mSessionLabel);
break;
case IM_SESSION_P2P_INVITE:
xml_filename = "floater_instant_message.xml";
mVoiceChannel = new LLVoiceChannelP2P(mSessionUUID, mSessionLabel, mOtherParticipantUUID);
break;
case IM_SESSION_CONFERENCE_START:
mFactoryMap["active_speakers_panel"] = LLCallbackMap(createSpeakersPanel, this);
xml_filename = "floater_instant_message_ad_hoc.xml";
mVoiceChannel = new LLVoiceChannelGroup(mSessionUUID, mSessionLabel);
break;
// just received text from another user
case IM_NOTHING_SPECIAL:
@ -998,8 +992,6 @@ LLFloaterIMPanel::LLFloaterIMPanel(const std::string& session_label,
mTextIMPossible = LLVoiceClient::getInstance()->isSessionTextIMPossible(mSessionUUID);
mProfileButtonEnabled = LLVoiceClient::getInstance()->isParticipantAvatar(mSessionUUID);
mCallBackEnabled = LLVoiceClient::getInstance()->isSessionCallBackPossible(mSessionUUID);
mVoiceChannel = new LLVoiceChannelP2P(mSessionUUID, mSessionLabel, mOtherParticipantUUID);
break;
default:
llwarns << "Unknown session type" << llendl;
@ -1007,10 +999,6 @@ LLFloaterIMPanel::LLFloaterIMPanel(const std::string& session_label,
break;
}
mSpeakers = new LLIMSpeakerMgr(mVoiceChannel);
// All participants will be added to the list of people we've recently interacted with.
mSpeakers->addListener(&LLRecentPeople::instance(), "add");
LLUICtrlFactory::getInstance()->buildFloater(this, xml_filename, NULL);
setTitle(mSessionLabel);
@ -1058,33 +1046,6 @@ LLFloaterIMPanel::LLFloaterIMPanel(const std::string& session_label,
LLFloaterIMPanel::~LLFloaterIMPanel()
{
delete mSpeakers;
mSpeakers = NULL;
// End the text IM session if necessary
if(gVoiceClient && mOtherParticipantUUID.notNull())
{
switch(mDialog)
{
case IM_NOTHING_SPECIAL:
case IM_SESSION_P2P_INVITE:
gVoiceClient->endUserIMSession(mOtherParticipantUUID);
break;
default:
// Appease the compiler
break;
}
}
//kicks you out of the voice channel if it is currently active
// HAVE to do this here -- if it happens in the LLVoiceChannel destructor it will call the wrong version (since the object's partially deconstructed at that point).
mVoiceChannel->deactivate();
delete mVoiceChannel;
mVoiceChannel = NULL;
//delete focus lost callback
mFocusCallbackConnection.disconnect();
}
@ -1152,7 +1113,8 @@ BOOL LLFloaterIMPanel::postBuild()
void* LLFloaterIMPanel::createSpeakersPanel(void* data)
{
LLFloaterIMPanel* floaterp = (LLFloaterIMPanel*)data;
floaterp->mSpeakerPanel = new LLPanelActiveSpeakers(floaterp->mSpeakers, TRUE);
LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(floaterp->mSessionUUID);
floaterp->mSpeakerPanel = new LLPanelActiveSpeakers(speaker_mgr, TRUE);
return floaterp->mSpeakerPanel;
}
@ -1198,12 +1160,14 @@ void LLFloaterIMPanel::draw()
&& mCallBackEnabled;
// hide/show start call and end call buttons
childSetVisible("end_call_btn", LLVoiceClient::voiceEnabled() && mVoiceChannel->getState() >= LLVoiceChannel::STATE_CALL_STARTED);
childSetVisible("start_call_btn", LLVoiceClient::voiceEnabled() && mVoiceChannel->getState() < LLVoiceChannel::STATE_CALL_STARTED);
LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionUUID);
childSetVisible("end_call_btn", LLVoiceClient::voiceEnabled() && voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED);
childSetVisible("start_call_btn", LLVoiceClient::voiceEnabled() && voice_channel->getState() < LLVoiceChannel::STATE_CALL_STARTED);
childSetEnabled("start_call_btn", enable_connect);
childSetEnabled("send_btn", !childGetValue("chat_editor").asString().empty());
LLPointer<LLSpeaker> self_speaker = mSpeakers->findSpeaker(gAgent.getID());
LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionUUID);
LLPointer<LLSpeaker> self_speaker = speaker_mgr->findSpeaker(gAgent.getID());
if(!mTextIMPossible)
{
mInputEditor->setEnabled(FALSE);
@ -1227,7 +1191,7 @@ void LLFloaterIMPanel::draw()
}
// show speakers window when voice first connects
if (mShowSpeakersOnConnect && mVoiceChannel->isActive())
if (mShowSpeakersOnConnect && voice_channel->isActive())
{
childSetVisible("active_speakers_panel", TRUE);
mShowSpeakersOnConnect = FALSE;
@ -1263,11 +1227,11 @@ void LLFloaterIMPanel::draw()
else
{
// refresh volume and mute checkbox
childSetVisible("speaker_volume", LLVoiceClient::voiceEnabled() && mVoiceChannel->isActive());
childSetVisible("speaker_volume", LLVoiceClient::voiceEnabled() && voice_channel->isActive());
childSetValue("speaker_volume", gVoiceClient->getUserVolume(mOtherParticipantUUID));
childSetValue("mute_btn", LLMuteList::getInstance()->isMuted(mOtherParticipantUUID, LLMute::flagVoiceChat));
childSetVisible("mute_btn", LLVoiceClient::voiceEnabled() && mVoiceChannel->isActive());
childSetVisible("mute_btn", LLVoiceClient::voiceEnabled() && voice_channel->isActive());
}
LLFloater::draw();
}
@ -1403,12 +1367,6 @@ void LLFloaterIMPanel::addHistoryLine(const std::string &utf8msg, const LLColor4
{
mNumUnreadMessages++;
}
if (source != LLUUID::null)
{
mSpeakers->speakerChatted(source);
mSpeakers->setSpeakerTyping(source, FALSE);
}
}
@ -1589,7 +1547,7 @@ void LLFloaterIMPanel::onClickStartCall(void* userdata)
{
LLFloaterIMPanel* self = (LLFloaterIMPanel*) userdata;
self->mVoiceChannel->activate();
LLIMModel::getInstance()->getVoiceChannel(self->mSessionUUID)->activate();
}
// static
@ -1597,7 +1555,7 @@ void LLFloaterIMPanel::onClickEndCall(void* userdata)
{
LLFloaterIMPanel* self = (LLFloaterIMPanel*) userdata;
self->getVoiceChannel()->deactivate();
LLIMModel::getInstance()->getVoiceChannel(self->mSessionUUID)->deactivate();
}
// static
@ -1671,7 +1629,8 @@ void LLFloaterIMPanel::onVisibilityChange(const LLSD& new_visibility)
mNumUnreadMessages = 0;
}
if (new_visibility.asBoolean() && mVoiceChannel->getState() == LLVoiceChannel::STATE_CONNECTED)
LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionUUID);
if (new_visibility.asBoolean() && voice_channel->getState() == LLVoiceChannel::STATE_CONNECTED)
LLFloaterReg::showInstance("voice_call", mSessionUUID);
else
LLFloaterReg::hideInstance("voice_call", mSessionUUID);
@ -1723,11 +1682,6 @@ void LLFloaterIMPanel::sendMsg()
mSentTypingState = TRUE;
}
void LLFloaterIMPanel::updateSpeakersList(const LLSD& speaker_updates)
{
mSpeakers->updateSpeakers(speaker_updates);
}
void LLFloaterIMPanel::processSessionUpdate(const LLSD& session_update)
{
if (
@ -1751,15 +1705,9 @@ void LLFloaterIMPanel::processSessionUpdate(const LLSD& session_update)
}
}
void LLFloaterIMPanel::setSpeakers(const LLSD& speaker_list)
{
mSpeakers->setSpeakers(speaker_list);
}
void LLFloaterIMPanel::sessionInitReplyReceived(const LLUUID& session_id)
{
mSessionUUID = session_id;
mVoiceChannel->updateSessionID(session_id);
mSessionInitialized = TRUE;
//we assume the history editor hasn't moved at all since
@ -1790,6 +1738,7 @@ void LLFloaterIMPanel::requestAutoConnect()
void LLFloaterIMPanel::setTyping(BOOL typing)
{
LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionUUID);
if (typing)
{
// Every time you type something, reset this timer
@ -1804,7 +1753,7 @@ void LLFloaterIMPanel::setTyping(BOOL typing)
mSentTypingState = FALSE;
}
mSpeakers->setSpeakerTyping(gAgent.getID(), TRUE);
speaker_mgr->setSpeakerTyping(gAgent.getID(), TRUE);
}
else
{
@ -1814,7 +1763,7 @@ void LLFloaterIMPanel::setTyping(BOOL typing)
sendTypingState(FALSE);
mSentTypingState = TRUE;
}
mSpeakers->setSpeakerTyping(gAgent.getID(), FALSE);
speaker_mgr->setSpeakerTyping(gAgent.getID(), FALSE);
}
mTyping = typing;
@ -1874,7 +1823,7 @@ void LLFloaterIMPanel::removeTypingIndicator(const LLIMInfo* im_info)
mHistoryEditor->removeTextFromEnd(chars_to_remove);
if (im_info)
{
mSpeakers->setSpeakerTyping(im_info->mFromID, FALSE);
LLIMModel::getInstance()->getSpeakerManager(mSessionUUID)->setSpeakerTyping(im_info->mFromID, FALSE);
}
}
}

View File

@ -33,6 +33,7 @@
#ifndef LL_IMPANEL_H
#define LL_IMPANEL_H
#include "llimview.h" //for LLIMModel
#include "lldockablefloater.h"
#include "lllogchat.h"
#include "lluuid.h"
@ -245,11 +246,7 @@ public:
const LLUUID& getSessionID() const { return mSessionUUID; }
const LLUUID& getOtherParticipantID() const { return mOtherParticipantUUID; }
LLIMSpeakerMgr* getSpeakerManager() const { return mSpeakers; }
void updateSpeakersList(const LLSD& speaker_updates);
void processSessionUpdate(const LLSD& update);
void setSpeakers(const LLSD& speaker_list);
LLVoiceChannel* getVoiceChannel() { return mVoiceChannel; }
EInstantMessage getDialogType() const { return mDialog; }
void setDialogType(EInstantMessage dialog) { mDialog = dialog; }
@ -305,7 +302,6 @@ private:
LLUUID mSessionUUID;
std::string mSessionLabel;
LLVoiceChannel* mVoiceChannel;
BOOL mSessionInitialized;
LLSD mQueuedMsgsForInit;
@ -346,7 +342,6 @@ private:
BOOL mProfileButtonEnabled;
BOOL mCallBackEnabled;
LLIMSpeakerMgr* mSpeakers;
LLPanelActiveSpeakers* mSpeakerPanel;
// Optimization: Don't send "User is typing..." until the

View File

@ -114,11 +114,85 @@ void toast_callback(const LLSD& msg){
LLIMModel::LLIMModel()
{
addChangedCallback(toast_callback);
addChangedCallback(LLIMFloater::newIMCallback);
addChangedCallback(toast_callback);
}
LLIMModel::LLIMSession::LLIMSession( const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id )
: mSessionID(session_id),
mName(name),
mType(type),
mNumUnread(0),
mOtherParticipantID(other_participant_id),
mVoiceChannel(NULL),
mSpeakers(NULL)
{
if (IM_NOTHING_SPECIAL == type || IM_SESSION_P2P_INVITE == type)
{
mVoiceChannel = new LLVoiceChannelP2P(session_id, name, other_participant_id);
}
else
{
mVoiceChannel = new LLVoiceChannelGroup(session_id, name);
}
mSpeakers = new LLIMSpeakerMgr(mVoiceChannel);
// All participants will be added to the list of people we've recently interacted with.
mSpeakers->addListener(&LLRecentPeople::instance(), "add");
}
LLIMModel::LLIMSession::~LLIMSession()
{
delete mSpeakers;
mSpeakers = NULL;
// End the text IM session if necessary
if(gVoiceClient && mOtherParticipantID.notNull())
{
switch(mType)
{
case IM_NOTHING_SPECIAL:
case IM_SESSION_P2P_INVITE:
gVoiceClient->endUserIMSession(mOtherParticipantID);
break;
default:
// Appease the linux compiler
break;
}
}
// HAVE to do this here -- if it happens in the LLVoiceChannel destructor it will call the wrong version (since the object's partially deconstructed at that point).
mVoiceChannel->deactivate();
delete mVoiceChannel;
mVoiceChannel = NULL;
}
LLIMModel::LLIMSession* LLIMModel::findIMSession(const LLUUID& session_id) const
{
return get_if_there(LLIMModel::instance().sSessionsMap, session_id,
(LLIMModel::LLIMSession*) NULL);
}
void LLIMModel::updateSessionID(const LLUUID& old_session_id, const LLUUID& new_session_id)
{
if (new_session_id == old_session_id) return;
LLIMSession* session = findIMSession(old_session_id);
if (session)
{
session->mSessionID = new_session_id;
session->mVoiceChannel->updateSessionID(new_session_id);
//*TODO set session initialized flag here? (IB)
sSessionsMap.erase(old_session_id);
sSessionsMap[new_session_id] = session;
}
}
void LLIMModel::testMessages()
{
LLUUID bot1_id("d0426ec6-6535-4c11-a5d9-526bb0c654d9");
@ -153,7 +227,7 @@ bool LLIMModel::newSession(LLUUID session_id, std::string name, EInstantMessage
return false;
}
LLIMSession* session = new LLIMSession(name, type, other_participant_id);
LLIMSession* session = new LLIMSession(session_id, name, type, other_participant_id);
sSessionsMap[session_id] = session;
LLIMMgr::getInstance()->notifyObserverSessionAdded(session_id, name, other_participant_id);
@ -170,12 +244,12 @@ bool LLIMModel::clearSession(LLUUID session_id)
return true;
}
//*TODO remake it, instead of returing the list pass it as as parameter (IB)
std::list<LLSD> LLIMModel::getMessages(LLUUID session_id, int start_index)
{
std::list<LLSD> return_list;
LLIMSession* session = get_if_there(sSessionsMap, session_id, (LLIMSession*)NULL);
LLIMSession* session = findIMSession(session_id);
if (!session)
{
llwarns << "session " << session_id << "does not exist " << llendl;
@ -202,13 +276,14 @@ std::list<LLSD> LLIMModel::getMessages(LLUUID session_id, int start_index)
mChangedSignal(arg);
// TODO: in the future is there a more efficient way to return these
//of course there is - return as parameter (IB)
return return_list;
}
bool LLIMModel::addToHistory(LLUUID session_id, std::string from, std::string utf8_text) {
LLIMSession* session = get_if_there(sSessionsMap, session_id, (LLIMSession*)NULL);
LLIMSession* session = findIMSession(session_id);
if (!session)
{
@ -231,7 +306,7 @@ bool LLIMModel::addToHistory(LLUUID session_id, std::string from, std::string ut
bool LLIMModel::addMessage(LLUUID session_id, std::string from, LLUUID from_id, std::string utf8_text) {
LLIMSession* session = get_if_there(sSessionsMap, session_id, (LLIMSession*)NULL);
LLIMSession* session = findIMSession(session_id);
if (!session)
{
@ -260,9 +335,9 @@ bool LLIMModel::addMessage(LLUUID session_id, std::string from, LLUUID from_id,
}
const std::string& LLIMModel::getName(LLUUID session_id)
const std::string& LLIMModel::getName(const LLUUID& session_id) const
{
LLIMSession* session = get_if_there(sSessionsMap, session_id, (LLIMSession*)NULL);
LLIMSession* session = findIMSession(session_id);
if (!session)
{
@ -273,6 +348,66 @@ const std::string& LLIMModel::getName(LLUUID session_id)
return session->mName;
}
const S32 LLIMModel::getNumUnread(const LLUUID& session_id) const
{
LLIMSession* session = findIMSession(session_id);
if (!session)
{
llwarns << "session " << session_id << "does not exist " << llendl;
return -1;
}
return session->mNumUnread;
}
const LLUUID& LLIMModel::getOtherParticipantID(const LLUUID& session_id) const
{
LLIMSession* session = findIMSession(session_id);
if (!session)
{
llwarns << "session " << session_id << "does not exist " << llendl;
return LLUUID::null;
}
return session->mOtherParticipantID;
}
EInstantMessage LLIMModel::getType(const LLUUID& session_id) const
{
LLIMSession* session = findIMSession(session_id);
if (!session)
{
llwarns << "session " << session_id << "does not exist " << llendl;
return IM_COUNT;
}
return session->mType;
}
LLVoiceChannel* LLIMModel::getVoiceChannel( const LLUUID& session_id ) const
{
LLIMSession* session = findIMSession(session_id);
if (!session)
{
llwarns << "session " << session_id << "does not exist " << llendl;
return NULL;
}
return session->mVoiceChannel;
}
LLIMSpeakerMgr* LLIMModel::getSpeakerManager( const LLUUID& session_id ) const
{
LLIMSession* session = findIMSession(session_id);
if (!session)
{
llwarns << "session " << session_id << "does not exist " << llendl;
return NULL;
}
return session->mSpeakers;
}
// TODO get rid of other participant ID
void LLIMModel::sendTypingState(LLUUID session_id, LLUUID other_participant_id, BOOL typing)
@ -316,7 +451,7 @@ void LLIMModel::sendLeaveSession(LLUUID session_id, LLUUID other_participant_id)
}
//*TODO update list of messages in a LLIMSession (IB)
void LLIMModel::sendMessage(const std::string& utf8_text,
const LLUUID& im_session_id,
const LLUUID& other_participant_id,
@ -415,9 +550,16 @@ void LLIMModel::sendMessage(const std::string& utf8_text,
LLFloaterIMPanel* floater = gIMMgr->findFloaterBySession(im_session_id);
if (floater) floater->addHistoryLine(history_echo, LLUIColorTable::instance().getColor("IMChatColor"), true, gAgent.getID());
LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(im_session_id);
if (speaker_mgr)
{
speaker_mgr->speakerChatted(gAgentID);
speaker_mgr->setSpeakerTyping(gAgentID, FALSE);
}
}
// Add the recipient to the recent people list.
//*TODO should be deleted, because speaker manager updates through callback the recent list
LLRecentPeople::instance().add(other_participant_id);
}
@ -633,10 +775,8 @@ public:
{
if ( gIMMgr)
{
LLFloaterIMPanel* floaterp =
gIMMgr->findFloaterBySession(mSessionID);
if (floaterp)
LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
if (speaker_mgr)
{
//we've accepted our invitation
//and received a list of agents that were
@ -650,15 +790,20 @@ public:
//but unfortunately, our base that we are receiving here
//may not be the most up to date. It was accurate at
//some point in time though.
floaterp->setSpeakers(content);
speaker_mgr->setSpeakers(content);
//we now have our base of users in the session
//that was accurate at some point, but maybe not now
//so now we apply all of the udpates we've received
//in case of race conditions
floaterp->updateSpeakersList(
gIMMgr->getPendingAgentListUpdates(mSessionID));
speaker_mgr->updateSpeakers(gIMMgr->getPendingAgentListUpdates(mSessionID));
}
LLFloaterIMPanel* floaterp =
gIMMgr->findFloaterBySession(mSessionID);
if (floaterp)
{
if ( mInvitiationType == LLIMMgr::INVITATION_TYPE_VOICE )
{
floaterp->requestAutoConnect();
@ -1104,6 +1249,12 @@ void LLIMMgr::addMessage(
//no session ID...compute new one
new_session_id = computeSessionID(dialog, other_participant_id);
}
if (!LLIMModel::getInstance()->findIMSession(new_session_id))
{
LLIMModel::instance().newSession(session_id, session_name, dialog, other_participant_id);
}
floater = findFloaterBySession(new_session_id);
if (!floater)
{
@ -1169,6 +1320,14 @@ void LLIMMgr::addMessage(
else
{
floater->addHistoryLine(msg, color, true, other_participant_id, from); // Insert linked name to front of message
//*TODO consider moving that speaker management stuff into model (IB)
LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(new_session_id);
if (speaker_mgr)
{
speaker_mgr->speakerChatted(gAgentID);
speaker_mgr->setSpeakerTyping(gAgentID, FALSE);
}
}
LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, msg);
@ -1273,11 +1432,10 @@ LLUUID LLIMMgr::addP2PSession(const std::string& name,
{
LLUUID session_id = addSession(name, IM_NOTHING_SPECIAL, other_participant_id);
LLFloaterIMPanel* floater = findFloaterBySession(session_id);
if(floater)
LLVoiceChannelP2P* voice_channel = (LLVoiceChannelP2P*) LLIMModel::getInstance()->getSpeakerManager(session_id);
if (voice_channel)
{
LLVoiceChannelP2P* voice_channelp = (LLVoiceChannelP2P*)floater->getVoiceChannel();
voice_channelp->setSessionHandle(voice_session_handle, caller_uri);
voice_channel->setSessionHandle(voice_session_handle, caller_uri);
}
return session_id;
@ -1312,6 +1470,11 @@ LLUUID LLIMMgr::addSession(
LLUUID session_id = computeSessionID(dialog,other_participant_id);
if (!LLIMModel::getInstance()->findIMSession(session_id))
{
LLIMModel::instance().newSession(session_id, name, dialog, other_participant_id);
}
LLFloaterIMPanel* floater = findFloaterBySession(session_id);
if(!floater)
{
@ -1335,17 +1498,10 @@ LLUUID LLIMMgr::addSession(
noteMutedUsers(floater, ids);
}
}
else
{
// *TODO: Remove this? Otherwise old communicate window opens on
// second initiation of IM session from People panel?
// floater->openFloater();
}
//mTabContainer->selectTabPanel(panel);
floater->setInputFocus(TRUE);
LLIMFloater::show(session_id);
notifyObserverSessionAdded(floater->getSessionID(), name, other_participant_id);
return floater->getSessionID();
return session_id;
}
// This removes the panel referenced by the uuid, and then restores
@ -1705,7 +1861,6 @@ LLFloaterIMPanel* LLIMMgr::createFloater(
LLTabContainer::eInsertionPoint i_pt = user_initiated ? LLTabContainer::RIGHT_OF_CURRENT : LLTabContainer::END;
LLFloaterChatterBox::getInstance()->addFloater(floater, FALSE, i_pt);
mFloaters.insert(floater->getHandle());
LLIMModel::instance().newSession(session_id, session_label, dialog, other_participant_id);
return floater;
}
@ -1825,24 +1980,25 @@ public:
gIMMgr->updateFloaterSessionID(
temp_session_id,
session_id);
LLIMModel::getInstance()->updateSessionID(temp_session_id, session_id);
LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id);
if (speaker_mgr)
{
speaker_mgr->setSpeakers(body);
speaker_mgr->updateSpeakers(gIMMgr->getPendingAgentListUpdates(session_id));
}
LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(session_id);
if (floaterp)
{
floaterp->setSpeakers(body);
//apply updates we've possibly received previously
floaterp->updateSpeakersList(
gIMMgr->getPendingAgentListUpdates(session_id));
if ( body.has("session_info") )
{
floaterp->processSessionUpdate(body["session_info"]);
}
//aply updates we've possibly received previously
floaterp->updateSpeakersList(
gIMMgr->getPendingAgentListUpdates(session_id));
}
gIMMgr->clearPendingAgentListUpdates(session_id);
}
else
@ -1932,15 +2088,15 @@ public:
const LLSD& context,
const LLSD& input) const
{
LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(input["body"]["session_id"].asUUID());
if (floaterp)
const LLUUID& session_id = input["body"]["session_id"].asUUID();
LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id);
if (speaker_mgr)
{
floaterp->updateSpeakersList(
input["body"]);
speaker_mgr->updateSpeakers(input["body"]);
}
else
{
//we don't have a floater yet..something went wrong
//we don't have a speaker manager yet..something went wrong
//we are probably receiving an update here before
//a start or an acceptance of an invitation. Race condition.
gIMMgr->addPendingAgentListUpdates(

View File

@ -34,6 +34,8 @@
#define LL_LLIMVIEW_H
#include "lldarray.h"
#include "llfloateractivespeakers.h" //for LLIMSpeakerMgr
#include "llimpanel.h" //for voice channels
#include "llmodaldialog.h"
#include "llinstantmessage.h"
#include "lluuid.h"
@ -50,21 +52,40 @@ public:
struct LLIMSession
{
LLIMSession(std::string name, EInstantMessage type, LLUUID other_participant_id)
:mName(name), mType(type), mNumUnread(0), mOtherParticipantID(other_participant_id) {}
LLIMSession(const LLUUID& session_id, const std::string& name,
const EInstantMessage& type, const LLUUID& other_participant_id);
virtual ~LLIMSession();
LLUUID mSessionID;
std::string mName;
EInstantMessage mType;
LLUUID mOtherParticipantID;
S32 mNumUnread;
std::list<LLSD> mMsgs;
LLVoiceChannel* mVoiceChannel;
LLIMSpeakerMgr* mSpeakers;
};
LLIMModel();
//*TODO make it non-static as LLIMMOdel is a singleton (IB)
static std::map<LLUUID, LLIMSession*> sSessionsMap; //mapping session_id to session
boost::signals2::signal<void(const LLSD&)> mChangedSignal;
/**
* Find an IM Session corresponding to session_id
* Returns NULL if the session does not exist
*/
LLIMSession* findIMSession(const LLUUID& session_id) const;
/**
* Rebind session data to a new session id.
*/
void updateSessionID(const LLUUID& old_session_id, const LLUUID& new_session_id);
boost::signals2::connection addChangedCallback( boost::function<void (const LLSD& data)> cb );
bool newSession(LLUUID session_id, std::string name, EInstantMessage type, LLUUID other_participant_id);
@ -72,10 +93,42 @@ public:
std::list<LLSD> getMessages(LLUUID session_id, int start_index = 0);
bool addMessage(LLUUID session_id, std::string from, LLUUID other_participant_id, std::string utf8_text);
bool addToHistory(LLUUID session_id, std::string from, std::string utf8_text);
//used to get the name of the session, for use as the title
//currently just the other avatar name
const std::string& getName(LLUUID session_id);
//used to get the name of the session, for use as the title
//currently just the other avatar name
const std::string& getName(const LLUUID& session_id) const;
/**
* Get number of unread messages in a session with session_id
* Returns -1 if the session with session_id doesn't exist
*/
const S32 getNumUnread(const LLUUID& session_id) const;
/**
* Get uuid of other participant in a session with session_id
* Returns LLUUID::null if the session doesn't exist
*
* *TODO what to do with other participants in ad-hoc and group chats?
*/
const LLUUID& getOtherParticipantID(const LLUUID& session_id) const;
/**
* Get type of a session specified by session_id
* Returns EInstantMessage::IM_COUNT if the session does not exist
*/
EInstantMessage getType(const LLUUID& session_id) const;
/**
* Get voice channel for the session specified by session_id
* Returns NULL if the session does not exist
*/
LLVoiceChannel* getVoiceChannel(const LLUUID& session_id) const;
/**
* Get im speaker manager for the session specified by session_id
* Returns NULL if the session does not exist
*/
LLIMSpeakerMgr* getSpeakerManager(const LLUUID& session_id) const;
static void sendLeaveSession(LLUUID session_id, LLUUID other_participant_id);
static bool sendStartSession(const LLUUID& temp_session_id, const LLUUID& other_participant_id,
const std::vector<LLUUID>& ids, EInstantMessage dialog);

View File

@ -65,6 +65,7 @@ LLNearbyChat::LLNearbyChat(const LLSD& key) :
mChatCaptionPanel(NULL),
mChatHistoryEditor(NULL)
{
m_isDirty = false;
}
LLNearbyChat::~LLNearbyChat()
@ -181,7 +182,7 @@ LLColor4 nearbychat_get_text_color(const LLChat& chat)
return text_color;
}
void nearbychat_add_timestamped_line(LLViewerTextEditor* edit, LLChat chat, const LLColor4& color)
void LLNearbyChat::add_timestamped_line(const LLChat& chat, const LLColor4& color)
{
std::string line = chat.mText;
@ -194,25 +195,28 @@ void nearbychat_add_timestamped_line(LLViewerTextEditor* edit, LLChat chat, cons
bool prepend_newline = true;
if (gSavedSettings.getBOOL("ChatShowTimestamps"))
{
edit->appendTime(prepend_newline);
mChatHistoryEditor->appendTime(prepend_newline);
prepend_newline = false;
}
// If the msg is from an agent (not yourself though),
// extract out the sender name and replace it with the hotlinked name.
std::string str_URL = chat.mURL;
if (chat.mSourceType == CHAT_SOURCE_AGENT &&
chat.mFromID != LLUUID::null)
{
chat.mURL = llformat("secondlife:///app/agent/%s/about",chat.mFromID.asString().c_str());
str_URL = llformat("secondlife:///app/agent/%s/about",chat.mFromID.asString().c_str());
}
// If the chat line has an associated url, link it up to the name.
if (!chat.mURL.empty()
if (!str_URL.empty()
&& (line.length() > chat.mFromName.length() && line.find(chat.mFromName,0) == 0))
{
std::string start_line = line.substr(0, chat.mFromName.length() + 1);
line = line.substr(chat.mFromName.length() + 1);
edit->appendStyledText(start_line, false, prepend_newline, LLStyleMap::instance().lookup(chat.mFromID,chat.mURL));
mChatHistoryEditor->appendStyledText(start_line, false, prepend_newline, LLStyleMap::instance().lookup(chat.mFromID,str_URL));
prepend_newline = false;
}
@ -225,11 +229,9 @@ void nearbychat_add_timestamped_line(LLViewerTextEditor* edit, LLChat chat, cons
else if (2 == font_size)
font_name = "sansserifbig";
edit->appendColoredText(line, false, prepend_newline, color, font_name);
mChatHistoryEditor->appendColoredText(line, false, prepend_newline, color, font_name);
}
void LLNearbyChat::addMessage(const LLChat& chat)
{
LLColor4 color = nearbychat_get_text_color(chat);
@ -254,7 +256,7 @@ void LLNearbyChat::addMessage(const LLChat& chat)
mChatHistoryEditor->setParseHighlights(TRUE);
if (!chat.mMuted)
nearbychat_add_timestamped_line(mChatHistoryEditor, chat, color);
add_timestamped_line(chat, color);
}
void LLNearbyChat::onNearbySpeakers()
@ -482,9 +484,16 @@ BOOL LLNearbyChat::handleRightMouseDown(S32 x, S32 y, MASK mask)
void LLNearbyChat::onOpen(const LLSD& key )
{
LLNotificationsUI::LLScreenChannel* chat_channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID")));
LLNotificationsUI::LLScreenChannelBase* chat_channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID")));
if(chat_channel)
{
chat_channel->removeToastsFromChannel();
}
}
void LLNearbyChat::draw ()
{
LLFloater::draw();
}

View File

@ -76,7 +76,10 @@ public:
virtual void onOpen (const LLSD& key);
virtual void draw ();
private:
void add_timestamped_line(const LLChat& chat, const LLColor4& color);
void pinn_panel();
void float_panel();
@ -86,10 +89,11 @@ private:
S32 mStart_X;
S32 mStart_Y;
//LLResizeBar* mResizeBar[RESIZE_BAR_COUNT];
LLHandle<LLView> mPopupMenuHandle;
LLPanel* mChatCaptionPanel;
LLViewerTextEditor* mChatHistoryEditor;
bool m_isDirty;
};
#endif

View File

@ -41,30 +41,227 @@
#include "llviewercontrol.h"
#include "llfloaterreg.h"//for LLFloaterReg::getTypedInstance
#include "llviewerwindow.h"//for screen channel position
//add LLNearbyChatHandler to LLNotificationsUI namespace
namespace LLNotificationsUI{
using namespace LLNotificationsUI;
//-----------------------------------------------------------------------------------------------
//LLNearbyChatScreenChannel
//-----------------------------------------------------------------------------------------------
LLToastPanelBase* createToastPanel()
{
LLNearbyChatToastPanel* item = LLNearbyChatToastPanel::createInstance();
static S32 chat_item_width = 304;
item->setWidth(chat_item_width);
return item;
}
class LLNearbyChatScreenChannel: public LLScreenChannelBase
{
public:
LLNearbyChatScreenChannel(const LLUUID& id):LLScreenChannelBase(id) { mActiveMessages = 0;};
void init (S32 channel_left, S32 channel_right);
void addNotification (LLSD& notification);
void arrangeToasts ();
void showToastsBottom ();
typedef boost::function<LLToastPanelBase* (void )> create_toast_panel_callback_t;
void setCreatePanelCallback(create_toast_panel_callback_t value) { m_create_toast_panel_callback_t = value;}
void onToastDestroyed (LLToast* toast);
void onToastFade (LLToast* toast);
// hide all toasts from screen, but not remove them from a channel
virtual void hideToastsFromScreen()
{
};
// removes all toasts from a channel
virtual void removeToastsFromChannel()
{
for(std::vector<LLToast*>::iterator it = m_active_toasts.begin(); it != m_active_toasts.end(); ++it)
{
LLToast* toast = (*it);
toast->setVisible(FALSE);
toast->stopTimer();
m_toast_pool.push_back(toast);
}
m_active_toasts.clear();
};
protected:
void createOverflowToast(S32 bottom, F32 timer);
create_toast_panel_callback_t m_create_toast_panel_callback_t;
bool createPoolToast();
std::vector<LLToast*> m_active_toasts;
std::list<LLToast*> m_toast_pool;
S32 mActiveMessages;
};
void LLNearbyChatScreenChannel::init(S32 channel_left, S32 channel_right)
{
S32 channel_top = gViewerWindow->getWorldViewRect().getHeight();
S32 channel_bottom = gViewerWindow->getWorldViewRect().mBottom;
setRect(LLRect(channel_left, channel_top, channel_right, channel_bottom));
setVisible(TRUE);
}
void LLNearbyChatScreenChannel::createOverflowToast(S32 bottom, F32 timer)
{
//we don't need overflow toast in nearby chat
}
void LLNearbyChatScreenChannel::onToastDestroyed(LLToast* toast)
{
}
void LLNearbyChatScreenChannel::onToastFade(LLToast* toast)
{
//fade mean we put toast to toast pool
if(!toast)
return;
m_toast_pool.push_back(toast);
std::vector<LLToast*>::iterator pos = std::find(m_active_toasts.begin(),m_active_toasts.end(),toast);
if(pos!=m_active_toasts.end())
m_active_toasts.erase(pos);
arrangeToasts();
}
bool LLNearbyChatScreenChannel::createPoolToast()
{
LLToastPanelBase* panel= m_create_toast_panel_callback_t();
if(!panel)
return false;
LLToast::Params p;
p.panel = panel;
LLToast* toast = new LLToast(p);
toast->setOnFadeCallback(boost::bind(&LLNearbyChatScreenChannel::onToastFade, this, _1));
toast->setOnToastDestroyedCallback(boost::bind(&LLNearbyChatScreenChannel::onToastDestroyed, this, _1));
m_toast_pool.push_back(toast);
return true;
}
void LLNearbyChatScreenChannel::addNotification(LLSD& notification)
{
//look in pool. if there is any message
if(m_toast_pool.empty())
{
//"pool" is empty - create one more panel
if(!createPoolToast())//created toast will go to pool. so next call will find it
return;
addNotification(notification);
return;
}
//take 1st element from pool, (re)initialize it, put it in active toasts
LLToast* toast = m_toast_pool.back();
m_toast_pool.pop_back();
LLToastPanelBase* panel = dynamic_cast<LLToastPanelBase*>(toast->getPanel());
if(!panel)
return;
panel->init(notification);
toast->reshapeToPanel();
toast->resetTimer();
m_active_toasts.insert(m_active_toasts.begin(),toast);
arrangeToasts();
}
void LLNearbyChatScreenChannel::arrangeToasts()
{
if(m_active_toasts.size() == 0 || mIsHovering)
return;
hideToastsFromScreen();
showToastsBottom();
}
void LLNearbyChatScreenChannel::showToastsBottom()
{
LLRect rect = getRect();
LLRect toast_rect;
S32 bottom = getRect().mBottom;
for(std::vector<LLToast*>::iterator it = m_active_toasts.begin(); it != m_active_toasts.end(); ++it)
{
LLToast* toast = (*it);
toast_rect = toast->getRect();
toast_rect.setLeftTopAndSize(getRect().mLeft, bottom + toast_rect.getHeight()+gSavedSettings.getS32("ToastMargin"), toast_rect.getWidth() ,toast_rect.getHeight());
toast->setRect(toast_rect);
if(toast->getRect().mTop > getRect().getHeight())
{
while(it!=m_active_toasts.end())
{
(*it)->setVisible(FALSE);
(*it)->stopTimer();
m_toast_pool.push_back(*it);
it=m_active_toasts.erase(it);
}
break;
}
toast->setVisible(TRUE);
bottom = toast->getRect().mTop;
}
}
//-----------------------------------------------------------------------------------------------
//LLNearbyChatHandler
//-----------------------------------------------------------------------------------------------
LLNearbyChatHandler::LLNearbyChatHandler(e_notification_type type, const LLSD& id)
{
mType = type;
LLChannelManager::Params p;
p.id = LLUUID(gSavedSettings.getString("NearByChatChannelUUID"));
// Getting a Channel for our notifications
mChannel = LLChannelManager::getInstance()->getChannel(p);
LLNearbyChatScreenChannel* channel = new LLNearbyChatScreenChannel(LLUUID(gSavedSettings.getString("NearByChatChannelUUID")));
LLNearbyChatScreenChannel::create_toast_panel_callback_t callback = createToastPanel;
channel->setCreatePanelCallback(callback);
mChannel = LLChannelManager::getInstance()->addChannel(channel);
mChannel->setOverflowFormatString("You have %d unread nearby chat messages");
}
LLNearbyChatHandler::~LLNearbyChatHandler()
{
}
void LLNearbyChatHandler::initChannel()
{
LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD());
S32 channel_right_bound = nearby_chat->getRect().mRight;
S32 channel_width = nearby_chat->getRect().mRight - 16; //HACK: 16 - ?
S32 channel_width = nearby_chat->getRect().mRight;
mChannel->init(channel_right_bound - channel_width, channel_right_bound);
}
@ -77,41 +274,42 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg)
if(chat_msg.mText.empty())
return;//don't process empty messages
LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD());
nearby_chat->addMessage(chat_msg);
if(nearby_chat->getVisible())
return;//no need in toast if chat is visible
// arrange a channel on a screen
if(!mChannel->getVisible())
{
initChannel();
}
LLUUID id;
id.generate();
LLChatItemCtrl* item = LLChatItemCtrl::createInstance();
LLNearbyChatScreenChannel* channel = dynamic_cast<LLNearbyChatScreenChannel*>(mChannel);
item->setMessage(chat_msg);
//static S32 chat_item_width = nearby_chat->getRect().getWidth() - 16;
static S32 chat_item_width = 304;
item->setWidth(chat_item_width);
item->setHeaderVisibility((EShowItemHeader)gSavedSettings.getS32("nearbychat_showicons_and_names"));
item->setVisible(true);
LLToast::Params p;
p.notif_id = id;
p.panel = item;
p.on_delete_toast = boost::bind(&LLNearbyChatHandler::onDeleteToast, this, _1);
mChannel->addToast(p);
if(channel)
{
LLSD notification;
notification["id"] = id;
notification["message"] = chat_msg.mText;
notification["from"] = chat_msg.mFromName;
notification["from_id"] = chat_msg.mFromID;
notification["time"] = chat_msg.mTime;
notification["source"] = (S32)chat_msg.mSourceType;
channel->addNotification(notification);
}
}
void LLNearbyChatHandler::onDeleteToast(LLToast* toast)
{
}
}

View File

@ -100,16 +100,23 @@ bool LLAlertHandler::processNotification(const LLSD& notify)
p.can_fade = false;
p.is_modal = mIsModal;
p.on_delete_toast = boost::bind(&LLAlertHandler::onDeleteToast, this, _1);
mChannel->addToast(p);
LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel);
if(channel)
channel->addToast(p);
}
else if (notify["sigtype"].asString() == "change")
{
LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal);
mChannel->modifyToastByNotificationID(notification->getID(), (LLToastPanel*)alert_dialog);
LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel);
if(channel)
channel->modifyToastByNotificationID(notification->getID(), (LLToastPanel*)alert_dialog);
}
else
{
mChannel->killToastByNotificationID(notification->getID());
LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel);
if(channel)
channel->killToastByNotificationID(notification->getID());
}
return true;
}

View File

@ -89,7 +89,10 @@ bool LLGroupHandler::processNotification(const LLSD& notify)
p.notification = notification;
p.panel = notify_box;
p.on_delete_toast = boost::bind(&LLGroupHandler::onDeleteToast, this, _1);
mChannel->addToast(p);
LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel);
if(channel)
channel->addToast(p);
// send a signal to the counter manager
mNewNotificationSignal();

View File

@ -104,8 +104,8 @@ protected:
// at the moment, when a handlers creates a channel.
virtual void initChannel()=0;
LLScreenChannel* mChannel;
e_notification_type mType;
LLScreenChannelBase* mChannel;
e_notification_type mType;
};

View File

@ -48,7 +48,11 @@ LLScriptHandler::LLScriptHandler(e_notification_type type, const LLSD& id)
// Getting a Channel for our notifications
mChannel = LLChannelManager::getInstance()->createNotificationChannel();
mChannel->setControlHovering(true);
mChannel->setOnRejectToastCallback(boost::bind(&LLScriptHandler::onRejectToast, this, _1));
LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel);
if(channel)
channel->setOnRejectToastCallback(boost::bind(&LLScriptHandler::onRejectToast, this, _1));
}
//--------------------------------------------------------------------------
@ -92,7 +96,10 @@ bool LLScriptHandler::processNotification(const LLSD& notify)
p.notification = notification;
p.panel = notify_box;
p.on_delete_toast = boost::bind(&LLScriptHandler::onDeleteToast, this, _1);
mChannel->addToast(p);
LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel);
if(channel)
channel->addToast(p);
// send a signal to the counter manager
mNewNotificationSignal();

View File

@ -93,8 +93,9 @@ bool LLTipHandler::processNotification(const LLSD& notify)
p.is_tip = true;
p.can_be_stored = false;
mChannel->addToast(p);
LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel);
if(channel)
channel->addToast(p);
}
else if (notify["sigtype"].asString() == "delete")
{

View File

@ -313,7 +313,7 @@ void LLPanelProfileTab::scrollToTop()
{
LLScrollContainer* scrollContainer = findChild<LLScrollContainer>("profile_scroll");
if (scrollContainer)
scrollContainer->goToTop();
scrollContainer->goToTop();
}
//////////////////////////////////////////////////////////////////////////

View File

@ -195,7 +195,7 @@ BOOL LLPanelGroup::postBuild()
if(panel_land) mTabs.push_back(panel_land);
if(panel_general)
panel_general->setupCtrls(this);
panel_general->setupCtrls(this);
return TRUE;
}
@ -206,8 +206,8 @@ void LLPanelGroup::reposButton(const std::string& name)
if(!button)
return;
LLRect btn_rect = button->getRect();
btn_rect.setLeftTopAndSize( btn_rect.mLeft, btn_rect.getHeight() + 2, btn_rect.getWidth(), btn_rect.getHeight());
button->setRect(btn_rect);
btn_rect.setLeftTopAndSize( btn_rect.mLeft, btn_rect.getHeight() + 2, btn_rect.getWidth(), btn_rect.getHeight());
button->setRect(btn_rect);
}
void LLPanelGroup::reshape(S32 width, S32 height, BOOL called_from_parent )
@ -235,7 +235,14 @@ void LLPanelGroup::onBtnCreate()
if(!panel_general)
return;
std::string apply_mesg;
panel_general->apply(apply_mesg);//yes yes you need to call apply to create...
if(panel_general->apply(apply_mesg))//yes yes you need to call apply to create...
return;
if ( !apply_mesg.empty() )
{
LLSD args;
args["MESSAGE"] = apply_mesg;
LLNotifications::instance().add("GenericAlert", args);
}
}
void LLPanelGroup::onBtnRefresh(void* user_data)

View File

@ -835,6 +835,7 @@ void LLPanelGroupGeneral::reset()
{
std::string empty_str = "";
mEditCharter->setText(empty_str);
mGroupNameEditor->setText(empty_str);
}
{
@ -850,6 +851,7 @@ void LLPanelGroupGeneral::reset()
{
mComboMature->setEnabled(true);
mComboMature->setVisible( !gAgent.isTeen() );
mComboMature->selectFirstItem();
}

View File

@ -60,11 +60,8 @@
#include "llvoiceclient.h"
#include "llworld.h"
using namespace LLOldEvents;
#define FRIEND_LIST_UPDATE_TIMEOUT 0.5
#define NEARBY_LIST_UPDATE_INTERVAL 1
#define RECENT_LIST_UPDATE_DELAY 1
static const std::string NEARBY_TAB_NAME = "nearby_panel";
static const std::string FRIENDS_TAB_NAME = "friends_panel";
@ -102,7 +99,7 @@ static LLRegisterPanelClassWrapper<LLPanelPeople> t_people("panel_people");
class LLPanelPeople::Updater
{
public:
typedef boost::function<bool(U32)> callback_t;
typedef boost::function<void()> callback_t;
Updater(callback_t cb)
: mCallback(cb)
{
@ -112,16 +109,6 @@ public:
{
}
/**
* Force the list updates.
*
* This may start repeated updates until all names are complete.
*/
virtual void forceUpdate()
{
updateList();
}
/**
* Activate/deactivate updater.
*
@ -130,9 +117,9 @@ public:
virtual void setActive(bool) {}
protected:
bool updateList(U32 mask = 0)
void updateList()
{
return mCallback(mask);
mCallback();
}
callback_t mCallback;
@ -147,6 +134,11 @@ public:
{
mEventTimer.stop();
}
virtual BOOL tick() // from LLEventTimer
{
return FALSE;
}
};
/**
@ -178,13 +170,6 @@ public:
LLAvatarTracker::instance().removeObserver(this);
}
/*virtual*/ void forceUpdate()
{
// Perform updates until all names are loaded.
if (!updateList(LLFriendObserver::ADD))
changed(LLFriendObserver::ADD);
}
/*virtual*/ void changed(U32 mask)
{
// events can arrive quickly in bulk - we need not process EVERY one of them -
@ -198,12 +183,12 @@ public:
/*virtual*/ BOOL tick()
{
if (updateList(mMask))
{
// Got all names, stop updates.
mEventTimer.stop();
mMask = 0;
}
if (mMask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE | LLFriendObserver::ONLINE))
updateList();
// Stop updates.
mEventTimer.stop();
mMask = 0;
return FALSE;
}
@ -329,68 +314,9 @@ class LLRecentListUpdater : public LLAvatarListUpdater, public boost::signals2::
public:
LLRecentListUpdater(callback_t cb)
: LLAvatarListUpdater(cb, RECENT_LIST_UPDATE_DELAY)
: LLAvatarListUpdater(cb, 0)
{
LLRecentPeople::instance().setChangedCallback(boost::bind(&LLRecentListUpdater::onRecentPeopleChanged, this));
}
private:
/*virtual*/ void forceUpdate()
{
onRecentPeopleChanged();
}
/*virtual*/ BOOL tick()
{
// Update the list until we get all the names.
if (updateList())
{
// Got all names, stop updates.
mEventTimer.stop();
}
return FALSE;
}
void onRecentPeopleChanged()
{
if (!updateList())
{
// Some names are incomplete, schedule another update.
mEventTimer.start();
}
}
};
/**
* Updates the group list on events from LLAgent.
*/
class LLGroupListUpdater : public LLPanelPeople::Updater, public LLSimpleListener
{
LOG_CLASS(LLGroupListUpdater);
public:
LLGroupListUpdater(callback_t cb)
: LLPanelPeople::Updater(cb)
{
gAgent.addListener(this, "new group");
}
~LLGroupListUpdater()
{
gAgent.removeListener(this);
}
/*virtual*/ bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
{
// Why is "new group" sufficient?
if (event->desc() == "new group")
{
updateList();
return true;
}
return false;
LLRecentPeople::instance().setChangedCallback(boost::bind(&LLRecentListUpdater::updateList, this));
}
};
@ -404,12 +330,12 @@ LLPanelPeople::LLPanelPeople()
mOnlineFriendList(NULL),
mAllFriendList(NULL),
mNearbyList(NULL),
mRecentList(NULL)
mRecentList(NULL),
mGroupList(NULL)
{
mFriendListUpdater = new LLFriendListUpdater(boost::bind(&LLPanelPeople::onFriendListUpdate,this, _1));
mFriendListUpdater = new LLFriendListUpdater(boost::bind(&LLPanelPeople::updateFriendList, this));
mNearbyListUpdater = new LLNearbyListUpdater(boost::bind(&LLPanelPeople::updateNearbyList, this));
mRecentListUpdater = new LLRecentListUpdater(boost::bind(&LLPanelPeople::updateRecentList, this));
mGroupListUpdater = new LLGroupListUpdater (boost::bind(&LLPanelPeople::updateGroupList, this));
}
LLPanelPeople::~LLPanelPeople()
@ -417,7 +343,6 @@ LLPanelPeople::~LLPanelPeople()
delete mNearbyListUpdater;
delete mFriendListUpdater;
delete mRecentListUpdater;
delete mGroupListUpdater;
LLView::deleteViewByHandle(mGroupPlusMenuHandle);
LLView::deleteViewByHandle(mNearbyViewSortMenuHandle);
@ -512,7 +437,7 @@ BOOL LLPanelPeople::postBuild()
buttonSetAction("share_btn", boost::bind(&LLPanelPeople::onShareButtonClicked, this));
getChild<LLPanel>(NEARBY_TAB_NAME)->childSetAction("nearby_view_sort_btn",boost::bind(&LLPanelPeople::onNearbyViewSortButtonClicked, this));
getChild<LLPanel>(RECENT_TAB_NAME)->childSetAction("recent_viewsort_btn",boost::bind(&LLPanelPeople::onRecentViewSortButtonClicked, this));
getChild<LLPanel>(RECENT_TAB_NAME)->childSetAction("recent_viewsort_btn",boost::bind(&LLPanelPeople::onRecentViewSortButtonClicked, this));
getChild<LLPanel>(FRIENDS_TAB_NAME)->childSetAction("friends_viewsort_btn",boost::bind(&LLPanelPeople::onFriendsViewSortButtonClicked, this));
getChild<LLPanel>(GROUP_TAB_NAME)->childSetAction("groups_viewsort_btn",boost::bind(&LLPanelPeople::onGroupsViewSortButtonClicked, this));
@ -547,137 +472,71 @@ BOOL LLPanelPeople::postBuild()
if(recent_view_sort)
mRecentViewSortMenuHandle = recent_view_sort->getHandle();
// Perform initial update.
mFriendListUpdater->forceUpdate();
mNearbyListUpdater->forceUpdate();
mGroupListUpdater->forceUpdate();
mRecentListUpdater->forceUpdate();
// call this method in case some list is empty and buttons can be in inconsistent state
updateButtons();
return TRUE;
}
void LLPanelPeople::applyFilterToTab(const std::string& tab_name)
{
if (tab_name == FRIENDS_TAB_NAME) // this tab has two lists
filterFriendList();
else if (tab_name == NEARBY_TAB_NAME)
filterNearbyList();
else if (tab_name == RECENT_TAB_NAME)
filterRecentList();
else if (tab_name == GROUP_TAB_NAME)
updateGroupList();
}
bool LLPanelPeople::updateFriendList(U32 changed_mask)
{
// Refresh names.
if (changed_mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE | LLFriendObserver::ONLINE))
{
// get all buddies we know about
const LLAvatarTracker& av_tracker = LLAvatarTracker::instance();
LLAvatarTracker::buddy_map_t all_buddies;
av_tracker.copyBuddyList(all_buddies);
// *TODO: it's suboptimal to rebuild the whole lists on online status change.
// save them to the online and all friends vectors
mOnlineFriendVec.clear();
mAllFriendVec.clear();
LLFriendCardsManager::folderid_buddies_map_t listMap;
// *NOTE: For now collectFriendsLists returns data only for Friends/All folder. EXT-694.
LLFriendCardsManager::instance().collectFriendsLists(listMap);
if (listMap.size() > 0)
{
lldebugs << "Friends Cards were found, count: " << listMap.begin()->second.size() << llendl;
mAllFriendVec = listMap.begin()->second;
}
else
{
lldebugs << "Friends Cards were not found" << llendl;
}
LLAvatarTracker::buddy_map_t::const_iterator buddy_it = all_buddies.begin();
for (; buddy_it != all_buddies.end(); ++buddy_it)
{
LLUUID buddy_id = buddy_it->first;
if (av_tracker.isBuddyOnline(buddy_id))
mOnlineFriendVec.push_back(buddy_id);
}
return filterFriendList();
}
return true;
}
bool LLPanelPeople::updateNearbyList()
{
LLWorld::getInstance()->getAvatars(&mNearbyVec, NULL, gAgent.getPositionGlobal(), gSavedSettings.getF32("NearMeRange"));
filterNearbyList();
return true;
}
bool LLPanelPeople::updateRecentList()
{
LLRecentPeople::instance().get(mRecentVec);
filterRecentList();
return true;
}
bool LLPanelPeople::updateGroupList()
{
if (!mGroupList)
return true; // there's no point in further updates
bool have_names = mGroupList->update(mFilterSubString);
updateButtons();
return have_names;
}
bool LLPanelPeople::filterFriendList()
void LLPanelPeople::updateFriendList()
{
if (!mOnlineFriendList || !mAllFriendList)
return true; // there's no point in further updates
return;
// We must always update Friends list to clear the latest removed friend.
bool have_names =
mOnlineFriendList->update(mOnlineFriendVec, mFilterSubString) &
mAllFriendList->update(mAllFriendVec, mFilterSubString);
// get all buddies we know about
const LLAvatarTracker& av_tracker = LLAvatarTracker::instance();
LLAvatarTracker::buddy_map_t all_buddies;
av_tracker.copyBuddyList(all_buddies);
// save them to the online and all friends vectors
LLAvatarList::uuid_vector_t& online_friendsp = mOnlineFriendList->getIDs();
LLAvatarList::uuid_vector_t& all_friendsp = mAllFriendList->getIDs();
updateButtons();
return have_names;
}
all_friendsp.clear();
online_friendsp.clear();
bool LLPanelPeople::filterNearbyList()
{
bool have_names = mNearbyList->update(mNearbyVec, mFilterSubString);
updateButtons();
return have_names;
}
LLFriendCardsManager::folderid_buddies_map_t listMap;
bool LLPanelPeople::filterRecentList()
{
if (!mRecentList)
return true;
if (mRecentVec.size() > 0)
// *NOTE: For now collectFriendsLists returns data only for Friends/All folder. EXT-694.
LLFriendCardsManager::instance().collectFriendsLists(listMap);
if (listMap.size() > 0)
{
bool updated = mRecentList->update(mRecentVec, mFilterSubString);
updateButtons();
return updated;
lldebugs << "Friends Cards were found, count: " << listMap.begin()->second.size() << llendl;
all_friendsp = listMap.begin()->second;
}
else
{
lldebugs << "Friends Cards were not found" << llendl;
}
return true;
LLAvatarTracker::buddy_map_t::const_iterator buddy_it = all_buddies.begin();
for (; buddy_it != all_buddies.end(); ++buddy_it)
{
LLUUID buddy_id = buddy_it->first;
if (av_tracker.isBuddyOnline(buddy_id))
online_friendsp.push_back(buddy_id);
}
mOnlineFriendList->setDirty();
mAllFriendList->setDirty();
}
void LLPanelPeople::updateNearbyList()
{
if (!mNearbyList)
return;
LLWorld::getInstance()->getAvatars(&mNearbyList->getIDs(), NULL, gAgent.getPositionGlobal(), gSavedSettings.getF32("NearMeRange"));
mNearbyList->setDirty();
}
void LLPanelPeople::updateRecentList()
{
if (!mRecentList)
return;
LLRecentPeople::instance().get(mRecentList->getIDs());
mRecentList->setDirty();
}
void LLPanelPeople::buttonSetVisible(std::string btn_name, BOOL visible)
@ -846,16 +705,19 @@ void LLPanelPeople::onFilterEdit(const std::string& search_string)
LLStringUtil::toUpper(mFilterSubString);
LLStringUtil::trimHead(mFilterSubString);
// Apply new filter to current tab.
applyFilterToTab(getActiveTabName());
// Apply new filter.
mNearbyList->setNameFilter(mFilterSubString);
mOnlineFriendList->setNameFilter(mFilterSubString);
mAllFriendList->setNameFilter(mFilterSubString);
mRecentList->setNameFilter(mFilterSubString);
mGroupList->setNameFilter(mFilterSubString);
}
void LLPanelPeople::onTabSelected(const LLSD& param)
{
std::string tab_name = getChild<LLPanel>(param.asString())->getName();
mNearbyListUpdater->setActive(tab_name == NEARBY_TAB_NAME);
applyFilterToTab(tab_name);
// No need to call updateButtons() because applyFilterToTab() does that.
updateButtons();
if (GROUP_TAB_NAME == tab_name)
mFilterEditor->setLabel(getString("groups_filter_label"));
@ -960,17 +822,6 @@ void LLPanelPeople::onAvatarPicked(
LLAvatarActions::requestFriendshipDialog(ids[0], names[0]);
}
bool LLPanelPeople::onFriendListUpdate(U32 changed_mask)
{
bool have_names = updateFriendList(changed_mask);
// Update online status in the Recent tab.
// *TODO: isn't it too much to update the whole list?
// updateRecentList(); // mantipov: seems online status should be supported by LLAvatarListItem itself.
return have_names;
}
void LLPanelPeople::onGroupPlusButtonClicked()
{
LLMenuGL* plus_menu = (LLMenuGL*)mGroupPlusMenuHandle.get();

View File

@ -58,15 +58,10 @@ public:
private:
// methods indirectly called by the updaters
bool updateFriendList(U32 changed_mask);
bool updateNearbyList();
bool updateRecentList();
bool updateGroupList();
void updateFriendList();
void updateNearbyList();
void updateRecentList();
bool filterFriendList();
bool filterNearbyList();
bool filterRecentList();
void applyFilterToTab(const std::string& tab_name);
void updateButtons();
const std::string& getActiveTabName() const;
LLUUID getCurrentItemID() const;
@ -110,7 +105,6 @@ private:
void onRecentViewSortMenuItemClicked(const LLSD& userdata);
// misc callbacks
bool onFriendListUpdate(U32 changed_mask);
static void onAvatarPicked(
const std::vector<std::string>& names,
const std::vector<LLUUID>& ids,
@ -135,21 +129,8 @@ private:
Updater* mFriendListUpdater;
Updater* mNearbyListUpdater;
Updater* mRecentListUpdater;
Updater* mGroupListUpdater;
std::string mFilterSubString;
// The vectors below contain up-to date avatar lists
// for the corresponding tabs.
// When the user enters a filter, it gets applied
// to all the vectors and the result is shown in the tabs.
// We don't need to have such a vector for the groups tab
// since re-fetching the groups list is always fast.
typedef std::vector<LLUUID> uuid_vector_t;
uuid_vector_t mNearbyVec;
uuid_vector_t mOnlineFriendVec;
uuid_vector_t mAllFriendVec;
uuid_vector_t mRecentVec;
};
#endif //LL_LLPANELPEOPLE_H

View File

@ -39,8 +39,10 @@
#include "message.h"
#include "llagent.h"
#include "llbutton.h"
#include "lllineeditor.h"
#include "llparcel.h"
#include "llviewerparcelmgr.h"
#include "lltexteditor.h"
#include "lltexturectrl.h"
#include "lluiconstants.h"
#include "llworldmap.h"
@ -73,7 +75,8 @@ LLPanelPick::LLPanelPick(BOOL edit_mode/* = FALSE */)
mPickId(LLUUID::null),
mCreatorId(LLUUID::null),
mDataReceived(FALSE),
mIsPickNew(false)
mIsPickNew(false),
mLocationChanged(false)
{
if (edit_mode)
{
@ -123,6 +126,16 @@ BOOL LLPanelPick::postBuild()
if (mEditMode)
{
enableSaveButton(FALSE);
mSnapshotCtrl->setOnSelectCallback(boost::bind(&LLPanelPick::onPickChanged, this, _1));
LLLineEditor* line_edit = getChild<LLLineEditor>("pick_name");
line_edit->setKeystrokeCallback(boost::bind(&LLPanelPick::onPickChanged, this, _1), NULL);
LLTextEditor* text_edit = getChild<LLTextEditor>("pick_desc");
text_edit->setKeystrokeCallback(boost::bind(&LLPanelPick::onPickChanged, this, _1));
childSetAction("cancel_btn", boost::bind(&LLPanelPick::onClickCancel, this));
childSetAction("set_to_curr_location_btn", boost::bind(&LLPanelPick::onClickSet, this));
childSetAction(XML_BTN_SAVE, boost::bind(&LLPanelPick::onClickSave, this));
@ -287,6 +300,26 @@ void LLPanelPick::setEditMode( BOOL edit_mode )
updateButtons();
}
void LLPanelPick::onPickChanged(LLUICtrl* ctrl)
{
if(mLocationChanged)
{
// Pick was enabled in onClickSet
return;
}
if( mSnapshotCtrl->isDirty()
|| getChild<LLLineEditor>("pick_name")->isDirty()
|| getChild<LLTextEditor>("pick_desc")->isDirty() )
{
enableSaveButton(TRUE);
}
else
{
enableSaveButton(FALSE);
}
}
//////////////////////////////////////////////////////////////////////////
// PROTECTED AREA
//////////////////////////////////////////////////////////////////////////
@ -466,6 +499,9 @@ void LLPanelPick::onClickSet()
mSimName = parcel->getName();
}
setPickLocation(createLocationText(std::string(""), SET_LOCATION_NOTICE, mSimName, mPosGlobal));
mLocationChanged = true;
enableSaveButton(TRUE);
}
// static
@ -552,3 +588,12 @@ void LLPanelPick::processParcelInfo(const LLParcelData& parcel_data)
//*NOTE we don't removeObserver(...) ourselves cause LLRemoveParcelProcessor does it for us
}
void LLPanelPick::enableSaveButton(bool enable)
{
if(!mEditMode)
{
return;
}
childSetEnabled(XML_BTN_SAVE, enable);
}

View File

@ -74,6 +74,8 @@ public:
// switches the panel to either View or Edit mode
void setEditMode(BOOL edit_mode);
void onPickChanged(LLUICtrl* ctrl);
// because this panel works in two modes (edit/view) we are
// free from managing two panel for editing and viewing picks and so
// are free from controlling switching between them in the parent panel (e.g. Me Profile)
@ -128,6 +130,8 @@ protected:
void onClickSave();
void onClickCancel();
void enableSaveButton(bool enable);
protected:
BOOL mEditMode;
LLTextureCtrl* mSnapshotCtrl;
@ -146,6 +150,7 @@ protected:
std::string mLocation;
commit_callback_t mBackCb;
bool mLocationChanged;
};
#endif // LL_LLPANELPICK_H

View File

@ -126,8 +126,7 @@ void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type)
mPicksList->addItem(picture, pick_value);
picture->setDoubleClickCallback(boost::bind(&LLPanelPicks::onDoubleClickItem, this, _1));
picture->setRightMouseDownCallback(boost::bind(&LLPanelPicks::onRightMouseDownItem, this, _1, _2, _3, _4));
picture->setRightMouseUpCallback(boost::bind(&LLPanelPicks::updateButtons, this));
picture->setRightMouseUpCallback(boost::bind(&LLPanelPicks::onRightMouseUpItem, this, _1, _2, _3, _4));
picture->setMouseUpCallback(boost::bind(&LLPanelPicks::updateButtons, this));
}
@ -260,8 +259,10 @@ void LLPanelPicks::onClickMap()
}
void LLPanelPicks::onRightMouseDownItem(LLUICtrl* item, S32 x, S32 y, MASK mask)
void LLPanelPicks::onRightMouseUpItem(LLUICtrl* item, S32 x, S32 y, MASK mask)
{
updateButtons();
if (mPopupMenu)
{
mPopupMenu->buildDrawLabels();

View File

@ -100,7 +100,7 @@ private:
void updateButtons();
virtual void onDoubleClickItem(LLUICtrl* item);
virtual void onRightMouseDownItem(LLUICtrl* item, S32 x, S32 y, MASK mask);
virtual void onRightMouseUpItem(LLUICtrl* item, S32 x, S32 y, MASK mask);
LLPanelProfile* getProfilePanel();

View File

@ -337,7 +337,7 @@ void LLPanelPlaces::onFilterEdit(const std::string& search_string)
LLStringUtil::trimHead(mFilterSubString);
if (mActivePanel)
mActivePanel->onSearchEdit(mFilterSubString);
mActivePanel->onSearchEdit(mFilterSubString);
}
}
@ -386,7 +386,7 @@ void LLPanelPlaces::onTeleportButtonClicked()
else
{
if (mActivePanel)
mActivePanel->onTeleport();
mActivePanel->onTeleport();
}
}
@ -432,7 +432,7 @@ void LLPanelPlaces::onShowOnMapButtonClicked()
else
{
if (mActivePanel)
mActivePanel->onShowOnMap();
mActivePanel->onShowOnMap();
}
}
@ -510,7 +510,7 @@ void LLPanelPlaces::onOverflowMenuItemClicked(const LLSD& param)
addChild(mPickPanel);
mPickPanel->setExitCallback(boost::bind(&LLPanelPlaces::togglePickPanel, this, FALSE));
}
}
togglePickPanel(TRUE);
@ -733,7 +733,7 @@ void LLPanelPlaces::updateVerbs()
else
{
if (mActivePanel)
mActivePanel->updateVerbs();
mActivePanel->updateVerbs();
}
}

View File

@ -306,12 +306,12 @@ void LLTeleportHistoryPanel::showTeleportHistory()
if (curr_tab <= tabs_cnt - 4)
{
curr_date.secondsSinceEpoch(curr_date.secondsSinceEpoch() - seconds_in_day);
curr_date.secondsSinceEpoch(curr_date.secondsSinceEpoch() - seconds_in_day);
}
else if (curr_tab == tabs_cnt - 3) // 6 day and older, low boundary is 1 month
{
curr_date = LLDate::now();
curr_date.split(&curr_year, &curr_month, &curr_day);
curr_date.split(&curr_year, &curr_month, &curr_day);
curr_month--;
if (0 == curr_month)
{
@ -376,7 +376,7 @@ void LLTeleportHistoryPanel::handleItemSelect(LLFlatListView* selected)
S32 tabs_cnt = mItemContainers.size();
for (S32 n = 0; n < tabs_cnt; n++)
{
{
LLAccordionCtrlTab* tab = mItemContainers.get(n);
if (!tab->getVisible())
@ -390,7 +390,7 @@ void LLTeleportHistoryPanel::handleItemSelect(LLFlatListView* selected)
continue;
flv->resetSelection(true);
}
}
updateVerbs();
}

View File

@ -55,36 +55,30 @@ using namespace LLNotificationsUI;
bool LLScreenChannel::mWasStartUpToastShown = false;
//--------------------------------------------------------------------------
LLScreenChannel::LLScreenChannel(LLUUID& id): mOverflowToastPanel(NULL), mStartUpToastPanel(NULL),
mToastAlignment(NA_BOTTOM), mCanStoreToasts(true),
mHiddenToastsNum(0), mOverflowToastHidden(false),
mIsHovering(false), mControlHovering(false),
mShowToasts(true)
//////////////////////
// LLScreenChannelBase
//////////////////////
LLScreenChannelBase::LLScreenChannelBase(const LLUUID& id) :
mOverflowToastPanel(NULL)
,mToastAlignment(NA_BOTTOM)
,mCanStoreToasts(true)
,mHiddenToastsNum(0)
,mOverflowToastHidden(false)
,mIsHovering(false)
,mControlHovering(false)
,mShowToasts(false)
{
mID = id;
mOverflowFormatString = LLTrans::getString("OverflowInfoChannelString");
mWorldViewRectConnection = gViewerWindow->setOnWorldViewRectUpdated(boost::bind(&LLScreenChannel::updatePositionAndSize, this, _1, _2));
mWorldViewRectConnection = gViewerWindow->setOnWorldViewRectUpdated(boost::bind(&LLScreenChannelBase::updatePositionAndSize, this, _1, _2));
setMouseOpaque( false );
setVisible(FALSE);
}
//--------------------------------------------------------------------------
void LLScreenChannel::init(S32 channel_left, S32 channel_right)
{
S32 channel_top = gViewerWindow->getWorldViewRect().getHeight();
S32 channel_bottom = gViewerWindow->getWorldViewRect().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin");
setRect(LLRect(channel_left, channel_top, channel_right, channel_bottom));
setVisible(TRUE);
}
//--------------------------------------------------------------------------
LLScreenChannel::~LLScreenChannel()
LLScreenChannelBase::~LLScreenChannelBase()
{
mWorldViewRectConnection.disconnect();
}
//--------------------------------------------------------------------------
void LLScreenChannel::updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect)
void LLScreenChannelBase::updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect)
{
S32 top_delta = old_world_rect.mTop - new_world_rect.mTop;
S32 right_delta = old_world_rect.mRight - new_world_rect.mRight;
@ -105,6 +99,42 @@ void LLScreenChannel::updatePositionAndSize(LLRect old_world_rect, LLRect new_wo
}
setRect(this_rect);
redrawToasts();
}
void LLScreenChannelBase::init(S32 channel_left, S32 channel_right)
{
S32 channel_top = gViewerWindow->getWorldViewRect().getHeight();
S32 channel_bottom = gViewerWindow->getWorldViewRect().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin");
setRect(LLRect(channel_left, channel_top, channel_right, channel_bottom));
setVisible(TRUE);
}
//--------------------------------------------------------------------------
//////////////////////
// LLScreenChannel
//////////////////////
//--------------------------------------------------------------------------
LLScreenChannel::LLScreenChannel(LLUUID& id): LLScreenChannelBase(id)
{
}
//--------------------------------------------------------------------------
void LLScreenChannel::init(S32 channel_left, S32 channel_right)
{
LLScreenChannelBase::init(channel_left, channel_right);
}
//--------------------------------------------------------------------------
LLScreenChannel::~LLScreenChannel()
{
}
//--------------------------------------------------------------------------
void LLScreenChannel::updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect)
{
LLScreenChannelBase::updatePositionAndSize(old_world_rect, new_world_rect);
}
//--------------------------------------------------------------------------
@ -561,7 +591,7 @@ void LLScreenChannel::removeAndStoreAllStorableToasts()
else
{
++it;
}
}
}
redrawToasts();
}

View File

@ -55,10 +55,95 @@ typedef enum e_channel_alignment
CA_RIGHT,
} EChannelAlignment;
class LLScreenChannelBase : public LLUICtrl
{
friend class LLChannelManager;
public:
LLScreenChannelBase(const LLUUID& id);
~LLScreenChannelBase();
// Channel's outfit-functions
// update channel's size and position in the World View
virtual void updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect);
// initialization of channel's shape and position
virtual void init(S32 channel_left, S32 channel_right);
virtual void setToastAlignment(EToastAlignment align) {mToastAlignment = align;}
virtual void setChannelAlignment(EChannelAlignment align) {mChannelAlignment = align;}
virtual void setOverflowFormatString ( const std::string& str) { mOverflowFormatString = str; }
// kill or modify a toast by its ID
virtual void killToastByNotificationID(LLUUID id) {};
virtual void modifyToastNotificationByID(LLUUID id, LLSD data) {};
// hide all toasts from screen, but not remove them from a channel
virtual void hideToastsFromScreen() {};
// removes all toasts from a channel
virtual void removeToastsFromChannel() {};
// show all toasts in a channel
virtual void redrawToasts() {};
virtual void closeOverflowToastPanel() {};
virtual void hideOverflowToastPanel() {};
// Channel's behavior-functions
// set whether a channel will control hovering inside itself or not
virtual void setControlHovering(bool control) { mControlHovering = control; }
// set Hovering flag for a channel
virtual void setHovering(bool hovering) { mIsHovering = hovering; }
void setCanStoreToasts(bool store) { mCanStoreToasts = store; }
void setDisplayToastsAlways(bool display_toasts) { mDisplayToastsAlways = display_toasts; }
bool getDisplayToastsAlways() { return mDisplayToastsAlways; }
// get number of hidden notifications from a channel
S32 getNumberOfHiddenToasts() { return mHiddenToastsNum;}
void setShowToasts(bool show) { mShowToasts = show; }
bool getShowToasts() { return mShowToasts; }
// get toast allignment preset for a channel
e_notification_toast_alignment getToastAlignment() {return mToastAlignment;}
// get ID of a channel
LLUUID getChannelID() { return mID; }
protected:
// Channel's flags
bool mControlHovering;
bool mIsHovering;
bool mCanStoreToasts;
bool mDisplayToastsAlways;
bool mOverflowToastHidden;
// controls whether a channel shows toasts or not
bool mShowToasts;
//
EToastAlignment mToastAlignment;
EChannelAlignment mChannelAlignment;
// attributes for the Overflow Toast
S32 mHiddenToastsNum;
LLToast* mOverflowToastPanel;
std::string mOverflowFormatString;
// channel's ID
LLUUID mID;
// store a connection to prevent futher crash that is caused by sending a signal to a destroyed channel
boost::signals2::connection mWorldViewRectConnection;
};
/**
* Screen channel manages toasts visibility and positioning on the screen.
*/
class LLScreenChannel : public LLUICtrl
class LLScreenChannel : public LLScreenChannelBase
{
friend class LLChannelManager;
public:
@ -70,12 +155,6 @@ public:
void updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect);
// initialization of channel's shape and position
void init(S32 channel_left, S32 channel_right);
// set allignment of toasts inside a channel
void setToastAlignment(EToastAlignment align) {mToastAlignment = align;}
// set allignment of channel inside a world view
void setChannelAlignment(EChannelAlignment align) {mChannelAlignment = align;}
// set a template for a string in the OverflowToast
void setOverflowFormatString ( std::string str) { mOverflowFormatString = str; }
// Operating with toasts
// add a toast to a channel
@ -104,37 +183,17 @@ public:
// close the StartUp Toast
void closeStartUpToast();
// Channel's behavior-functions
// set whether a channel will control hovering inside itself or not
void setControlHovering(bool control) { mControlHovering = control; }
// set Hovering flag for a channel
void setHovering(bool hovering) { mIsHovering = hovering; }
// set whether a channel will store faded toasts or not
void setCanStoreToasts(bool store) { mCanStoreToasts = store; }
// tell all channels that the StartUp toast was shown and allow them showing of toasts
static void setStartUpToastShown() { mWasStartUpToastShown = true; }
// get StartUp Toast's state
static bool getStartUpToastShown() { return mWasStartUpToastShown; }
// set mode for dislaying of toasts
void setDisplayToastsAlways(bool display_toasts) { mDisplayToastsAlways = display_toasts; }
// get mode for dislaying of toasts
bool getDisplayToastsAlways() { return mDisplayToastsAlways; }
// tell a channel to show toasts or not
void setShowToasts(bool show) { mShowToasts = show; }
// determine whether channel shows toasts or not
bool getShowToasts() { return mShowToasts; }
// tell all channels that the StartUp toast was shown and allow them showing of toasts
static void setStartUpToastShown() { mWasStartUpToastShown = true; }
// let a channel update its ShowToast flag
void updateShowToastsState();
// Channel's other interface functions functions
// get number of hidden notifications from a channel
S32 getNumberOfHiddenToasts() { return mHiddenToastsNum;}
// update number of notifications in the StartUp Toast
void updateStartUpString(S32 num);
// get toast allignment preset for a channel
e_notification_toast_alignment getToastAlignment() {return mToastAlignment;}
// get ID of a channel
LLUUID getChannelID() { return mID; }
// Channel's signals
// signal on storing of faded toasts event
@ -201,30 +260,10 @@ private:
// Channel's flags
static bool mWasStartUpToastShown;
bool mControlHovering;
bool mIsHovering;
bool mCanStoreToasts;
bool mDisplayToastsAlways;
bool mOverflowToastHidden;
// controls whether a channel shows toasts or not
bool mShowToasts;
//
EToastAlignment mToastAlignment;
EChannelAlignment mChannelAlignment;
// attributes for the Overflow Toast
S32 mHiddenToastsNum;
LLToast* mOverflowToastPanel;
std::string mOverflowFormatString;
// attributes for the StartUp Toast
LLToast* mStartUpToastPanel;
// channel's ID
LLUUID mID;
// store a connection to prevent futher crash that is caused by sending a signal to a destroyed channel
boost::signals2::connection mWorldViewRectConnection;
std::vector<ToastElem> mToastList;
std::vector<ToastElem> mStoredToastList;

View File

@ -48,6 +48,7 @@
#include "lliconctrl.h"//for Home tab icon
#include "llsidetraypanelcontainer.h"
#include "llwindow.h"//for SetCursor
#include "lltransientfloatermgr.h"
//#include "llscrollcontainer.h"
@ -248,6 +249,7 @@ LLSideTray::LLSideTray(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));
LLTransientFloaterMgr::getInstance()->addControlView(this);
}
@ -448,13 +450,17 @@ void LLSideTray::reflectCollapseChange()
setPanelRect();
if(mCollapsed)
{
gFloaterView->setSnapOffsetRight(0);
setFocus(FALSE);
}
else
{
gFloaterView->setSnapOffsetRight(mMaxBarWidth);
setFocus(TRUE);
}
gFloaterView->refresh();
setFocus( FALSE );
}
void LLSideTray::arrange ()

View File

@ -225,22 +225,14 @@ void LLStatusBar::draw()
BOOL LLStatusBar::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
if (mHideNavbarContextMenu)
{
mHideNavbarContextMenu->buildDrawLabels();
mHideNavbarContextMenu->updateParent(LLMenuGL::sMenuContainer);
LLMenuGL::showPopup(this, mHideNavbarContextMenu, x, y);
}
show_navbar_context_menu(this,x,y);
return TRUE;
}
BOOL LLStatusBar::postBuild()
{
mHideNavbarContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_hide_navbar.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
gMenuHolder->addChild(mHideNavbarContextMenu);
gMenuBarView->setRightMouseDownCallback(boost::bind(&LLStatusBar::onMainMenuRightClicked, this, _1, _2, _3, _4));
gMenuBarView->setRightMouseDownCallback(boost::bind(&show_navbar_context_menu, _1, _2, _3));
return TRUE;
}
@ -560,11 +552,6 @@ void LLStatusBar::setupDate()
}
}
void LLStatusBar::onMainMenuRightClicked(LLUICtrl* ctrl, S32 x, S32 y, MASK mask)
{
handleRightMouseDown(x, y, mask);
}
// static
void LLStatusBar::onClickStatGraph(void* data)
{

View File

@ -91,7 +91,6 @@ private:
// simple method to setup the part that holds the date
void setupDate();
void onMainMenuRightClicked(LLUICtrl* ctrl, S32 x, S32 y, MASK mask);
static void onCommitSearch(LLUICtrl*, void* data);
static void onClickSearch(void* data);
static void onClickStatGraph(void* data);
@ -111,8 +110,7 @@ private:
S32 mSquareMetersCommitted;
LLFrameTimer* mBalanceTimer;
LLFrameTimer* mHealthTimer;
LLMenuGL* mHideNavbarContextMenu;
static std::vector<std::string> sDays;
static std::vector<std::string> sMonths;
static const U32 MAX_DATE_STRING_LENGTH;

View File

@ -108,6 +108,14 @@ BOOL LLSysWellWindow::postBuild()
return LLDockableFloater::postBuild();
}
//---------------------------------------------------------------------------------
void LLSysWellWindow::setMinimized(BOOL minimize)
{
setVisible(!minimize);
LLFloater::setMinimized(minimize);
}
//---------------------------------------------------------------------------------
void LLSysWellWindow::connectListUpdaterToSignal(std::string notification_type)
{
@ -155,10 +163,10 @@ void LLSysWellWindow::addItem(LLSysWellItem::Params p)
{
handleItemAdded(IT_NOTIFICATION);
reshapeWindow();
reshapeWindow();
new_item->setOnItemCloseCallback(boost::bind(&LLSysWellWindow::onItemClose, this, _1));
new_item->setOnItemClickCallback(boost::bind(&LLSysWellWindow::onItemClick, this, _1));
new_item->setOnItemCloseCallback(boost::bind(&LLSysWellWindow::onItemClose, this, _1));
new_item->setOnItemClickCallback(boost::bind(&LLSysWellWindow::onItemClick, this, _1));
}
else
{
@ -226,11 +234,11 @@ void LLSysWellWindow::onStoreToast(LLPanel* info_panel, LLUUID id)
//---------------------------------------------------------------------------------
void LLSysWellWindow::initChannel()
{
LLNotificationsUI::LLScreenChannel* channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(
LLNotificationsUI::LLScreenChannelBase* channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(
LLUUID(gSavedSettings.getString("NotificationChannelUUID")));
if(channel)
mChannel = dynamic_cast<LLNotificationsUI::LLScreenChannel*>(channel);
if(mChannel)
{
mChannel = channel;
mChannel->setOnStoreToastCallback(boost::bind(&LLSysWellWindow::onStoreToast, this, _1, _2));
}
else
@ -240,7 +248,7 @@ void LLSysWellWindow::initChannel()
}
//---------------------------------------------------------------------------------
void LLSysWellWindow::getEnabledRect(LLRect& rect)
void LLSysWellWindow::getAllowedRect(LLRect& rect)
{
rect = gViewerWindow->getWorldViewRect();
}
@ -252,7 +260,7 @@ void LLSysWellWindow::toggleWindow()
{
setDockControl(new LLDockControl(
LLBottomTray::getInstance()->getSysWell(), this,
getDockTongue(), LLDockControl::TOP, boost::bind(&LLSysWellWindow::getEnabledRect, this, _1)));
getDockTongue(), LLDockControl::TOP, boost::bind(&LLSysWellWindow::getAllowedRect, this, _1)));
}
if(!getVisible())
@ -404,20 +412,18 @@ bool LLSysWellWindow::isWindowEmpty()
//---------------------------------------------------------------------------------
//virtual
void LLSysWellWindow::sessionAdded(const LLUUID& sessionId,
const std::string& name, const LLUUID& otherParticipantId)
void LLSysWellWindow::sessionAdded(const LLUUID& session_id,
const std::string& name, const LLUUID& other_participant_id)
{
if (mMessageList->getItemByValue(get_session_value(sessionId)) == NULL)
//*TODO get rid of get_session_value, session_id's are unique, cause performance degradation with lots chiclets (IB)
if (mMessageList->getItemByValue(get_session_value(session_id)) == NULL)
{
S32 chicletCounter = 0;
LLIMModel::LLIMSession* session = get_if_there(LLIMModel::sSessionsMap,
sessionId, (LLIMModel::LLIMSession*) NULL);
if (session != NULL)
S32 chicletCounter = LLIMModel::getInstance()->getNumUnread(session_id);
if (chicletCounter > -1)
{
chicletCounter = session->mNumUnread;
addIMRow(session_id, chicletCounter, name, other_participant_id);
reshapeWindow();
}
addIMRow(sessionId, chicletCounter, name, otherParticipantId);
reshapeWindow();
}
}
@ -491,6 +497,7 @@ LLSysWellWindow::RowPanel::RowPanel(const LLSysWellWindow* parent, const LLUUID&
switch (im_chiclet_type)
{
case LLIMChiclet::TYPE_GROUP:
case LLIMChiclet::TYPE_AD_HOC:
mChiclet = getChild<LLIMChiclet>("group_chiclet");
childSetVisible("p2p_chiclet", false);
break;

View File

@ -68,6 +68,8 @@ public:
void toggleWindow();
/*virtual*/ BOOL canClose() { return FALSE; }
/*virtual*/ void setDocked(bool docked, bool pop_on_undock = true);
// override LLFloater's minimization according to EXT-1216
/*virtual*/ void setMinimized(BOOL minimize);
// Handlers
void onItemClick(LLSysWellItem* item);
@ -86,8 +88,8 @@ private:
IT_INSTANT_MESSAGE
}EItemType;
// gets a rect valid for SysWellWindow's position on a screen (EXT-1111)
void getEnabledRect(LLRect& rect);
// gets a rect that bounds possible positions for the SysWellWindow on a screen (EXT-1111)
void getAllowedRect(LLRect& rect);
// connect counter and list updaters to the corresponding signals
void connectListUpdaterToSignal(std::string notification_type);
// init Window's channel

View File

@ -167,15 +167,30 @@ void LLToast::tick()
}
//--------------------------------------------------------------------------
void LLToast::insertPanel(LLPanel* panel)
void LLToast::reshapeToPanel()
{
LLRect panel_rect, toast_rect;
LLPanel* panel = getPanel();
if(!panel)
return;
LLRect panel_rect;
panel_rect = panel->getRect();
reshape(panel_rect.getWidth(), panel_rect.getHeight());
panel_rect.setLeftTopAndSize(0, panel_rect.getHeight(), panel_rect.getWidth(), panel_rect.getHeight());
panel->setRect(panel_rect);
LLRect toast_rect = getRect();
toast_rect.setLeftTopAndSize(toast_rect.mLeft,toast_rect.mTop,panel_rect.getWidth(), panel_rect.getHeight());
setRect(toast_rect);
}
void LLToast::insertPanel(LLPanel* panel)
{
addChild(panel);
reshapeToPanel();
}
//--------------------------------------------------------------------------

View File

@ -99,6 +99,9 @@ public:
// Operating with toasts
// insert a panel to a toast
void insertPanel(LLPanel* panel);
void reshapeToPanel();
// get toast's panel
LLPanel* getPanel() { return mPanel; }
// enable/disable Toast's Hide button

View File

@ -39,6 +39,12 @@
#include <string>
class LLToastPanelBase: public LLPanel
{
public:
virtual void init(LLSD& data){};
};
/**
* Base class for all panels that can be added to the toast.
* All toast panels should contain necessary logic for representing certain notification

View File

@ -7666,6 +7666,19 @@ class LLHelpShowFirstTimeTip : public view_listener_t
}
};
void show_navbar_context_menu(LLView* ctrl, S32 x, S32 y)
{
static LLMenuGL* show_navbar_context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_hide_navbar.xml",
gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
if(gMenuHolder->hasVisibleMenu())
{
gMenuHolder->hideMenus();
}
show_navbar_context_menu->buildDrawLabels();
show_navbar_context_menu->updateParent(LLMenuGL::sMenuContainer);
LLMenuGL::showPopup(ctrl, show_navbar_context_menu, x, y);
}
void initialize_menus()
{
// A parameterized event handler used as ctrl-8/9/0 zoom controls below.

View File

@ -52,6 +52,7 @@ void show_debug_menus(); // checks for if menus should be shown first.
void toggle_debug_menus(void*);
void show_context_menu( S32 x, S32 y, MASK mask );
void show_build_mode_context_menu(S32 x, S32 y, MASK mask);
void show_navbar_context_menu(LLView* ctrl, S32 x, S32 y);
BOOL enable_save_into_inventory(void*);
void handle_reset_view();
void handle_cut(void*);

View File

@ -3223,9 +3223,9 @@ LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot, BOOL pick_trans
// assume that pickAsync put the results in the back of the mPicks list
if(mPicks.size() != 0)
{
mLastPick = mPicks.back();
mLastPick.fetchResults();
mPicks.pop_back();
mLastPick = mPicks.back();
mLastPick.fetchResults();
mPicks.pop_back();
}
else
{

View File

@ -12,7 +12,7 @@
width="320"
min_width="320"
height="23"
can_minimize="false"
can_minimize="true"
can_tear_off="false"
can_resize="false"
can_drag_on_left="false"
@ -22,10 +22,10 @@
<flat_list_view
color="FloaterDefaultBackgroundColor"
follows="all"
layout="topleft"
name="notification_list"
left="1"
layout="topleft"
name="notification_list"
left="1"
top="20"
height="0"
width="318"/>
height="0"
width="318"/>
</floater>

View File

@ -128,13 +128,13 @@
function="World.SetAway" />
</menu_item_call>
<menu_item_separator
layout="topleft"/>
layout="topleft"/>
<menu_item_call
label="Set Busy"
layout="topleft"
name="Set Busy">
<menu_item_call.on_click
function="World.SetBusy"/>
function="World.SetBusy"/>
</menu_item_call>
</menu>
<menu_item_separator

View File

@ -79,7 +79,6 @@
label="Move"
layout="topleft"
name="movement_btn"
tab_stop="false"
tool_tip="Shows/Hide Movement controls"
top="6"
width="70">
@ -117,7 +116,6 @@
label="View"
layout="topleft"
left="0"
tab_stop="false"
tool_tip="Shows/Hide Camera controls"
top="6"
name="camera_btn"
@ -133,7 +131,6 @@
height="20"
width="20"
left_pad="0"
tab_stop="false"
is_toggle="true"
picture_style="true"
image_selected="toggle_button_selected"

View File

@ -28,7 +28,7 @@
width="25"
height="25"
label=""
follows="top|left"
follows="top|right"
image_overlay="BackArrow_Off"
tab_stop="false" />
<text
@ -41,6 +41,7 @@
text_color="white"
follows="top|left|right"
mouse_opaque="true"
use_ellipses="true"
name="group_name">(Loading...)</text>
<line_editor
follows="left|top"

View File

@ -35,6 +35,8 @@
follows="right"
height="20"
speak_button.font="SansSerifMedium"
speak_button.tab_stop="true"
show_button.tab_stop="true"
layout="topleft"
left_pad="5"
name="talk"

View File

@ -2,7 +2,7 @@
<panel
bevel_style="in"
follows="left|top|right|bottom"
height="420"
height="460"
label="Notes &amp; Privacy"
layout="topleft"
left="0"
@ -16,7 +16,7 @@
layout="topleft"
left="0"
top="0"
height="420"
height="430"
width="313"
border_size="0">
<panel

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
follows="left|top|right|bottom"
height="515"
height="555"
label="Picks"
layout="topleft"
left="0"
@ -11,7 +11,7 @@
<flat_list_view
color="DkGray2"
follows="left|top|right|bottom"
height="495"
height="465"
layout="topleft"
left="0"
name="picks_list"

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
follows="all"
height="515"
height="560"
label="Profile"
layout="topleft"
left="0"
@ -25,7 +25,7 @@
<scroll_container
color="DkGray2"
follows="left|top|right|bottom"
height="515"
height="500"
min_height="300"
layout="topleft"
name="profile_scroll"
@ -265,6 +265,7 @@
left="0"
name="profile_buttons_panel"
top_pad="0"
height="25"
width="313">
<button
follows="bottom|left"
@ -316,6 +317,7 @@
name="profile_me_buttons_panel"
top_pad="0"
visible="false"
height="25"
width="313">
<button
follows="bottom|left"

View File

@ -2,7 +2,7 @@
<panel
background_visible="true"
follows="all"
height="660"
height="570"
layout="topleft"
min_height="350"
min_width="240"
@ -50,7 +50,7 @@
width="25" />
<tab_container
follows="left|top|right|bottom"
height="660"
height="560"
layout="topleft"
left="10"
name="tabs"

View File

@ -111,7 +111,7 @@
width="380">
</flat_list_view>
</accordion_tab>
<accordion_tab
can_resize="false"
layout="topleft"

View File

@ -10,9 +10,9 @@
highlighted_color="ScrollHighlightedColor"
column_padding="5"
draw_stripes="true"
scroll_bar_bg_visible="false"
scroll_bar_bg_color="black"
background_visible="false"
heading_height="23"
draw_border="false"
draw_heading="false"
scroll_bar_bg_visible="false"
scroll_bar_bg_color="black" />
draw_heading="false" />

View File

@ -12,17 +12,20 @@
<combo_editor
select_on_focus="true"
text_pad_left="20"
tool_tip="Search"
background_image="TextField_Search_Off"
background_image_disabled="TextField_Search_Disabled"
background_image_focused="TextField_Search_Active"/>
<combo_list
multi_select="false"
page_lines="10" />
page_lines="10"
scroll_bar_bg_visible="true" />
<search_button label=""
top_pad="4"
left_pad="4"
width="13"
height="13"
tool_tip="Search"
image_unselected="Search"
image_selected="Search" />
</search_combo_box>