* Bugs: EXT-807 EXT-810 EXT-811 EXT-784 EXT-820 EXT-393 EXT-826 EXT-811 EXT-801 EXT-808 EXT-393 EXT-743 EXT-699 EXT-397 EXT-812 EXT-736 EXT-744 EXT-809 EXT-306 EXT-854 EXT-857 EXT-790
* New Dev: EXT-694 EXT-393 EXT-367 EXT-819 EXT-795 EXT-827 EXT-788
* EXT-272 - Draggable Landmarks
* EXT-715 - Block List Panel
* EXT-782 - Implement advanced place information accordions
master
Steven Bennetts 2009-09-07 22:55:07 +00:00
parent a9b2296b2b
commit 79653dfed4
88 changed files with 3184 additions and 541 deletions

View File

@ -100,7 +100,7 @@ public:
BOOL getIsLinkType() const;
// mutators - will not call updateServer();
void setUUID(const LLUUID& new_uuid);
void rename(const std::string& new_name);
virtual void rename(const std::string& new_name);
void setParent(const LLUUID& new_parent);
void setType(LLAssetType::EType type);

View File

@ -105,7 +105,7 @@ bool removeSubString(std::string& str, const std::string& substr)
size_t pos = str.find(substr);
if (pos != string::npos)
{
str.erase(pos);
str.erase(pos, substr.size());
return true;
}
return false;

View File

@ -34,6 +34,8 @@ set(llui_SOURCE_FILES
llconsole.cpp
llcontainerview.cpp
llctrlselectioninterface.cpp
lldockablefloater.cpp
lldockcontrol.cpp
lldraghandle.cpp
lleditmenuhandler.cpp
llf32uictrl.cpp
@ -113,6 +115,8 @@ set(llui_HEADER_FILES
llcontainerview.h
llctrlselectioninterface.h
lldraghandle.h
lldockablefloater.h
lldockcontrol.h
lleditmenuhandler.h
llf32uictrl.h
llfiltereditor.h

View File

@ -355,11 +355,19 @@ BOOL LLButton::handleMouseDown(S32 x, S32 y, MASK mask)
setFocus(TRUE);
}
/*
* ATTENTION! This call fires another mouse down callback.
* If you wish to remove this call emit that signal directly
* by calling LLUICtrl::mMouseDownSignal(x, y, mask);
*/
LLUICtrl::handleMouseDown(x, y, mask);
mMouseDownSignal(this, LLSD());
mMouseDownTimer.start();
mMouseDownFrame = (S32) LLFrameTimer::getFrameCount();
mMouseHeldDownCount = 0;
if (getSoundFlags() & MOUSE_DOWN)
{
@ -378,6 +386,13 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask)
// Always release the mouse
gFocusMgr.setMouseCapture( NULL );
/*
* ATTENTION! This call fires another mouse up callback.
* If you wish to remove this call emit that signal directly
* by calling LLUICtrl::mMouseUpSignal(x, y, mask);
*/
LLUICtrl::handleMouseUp(x, y, mask);
// Regardless of where mouseup occurs, handle callback
mMouseUpSignal(this, LLSD());
@ -460,12 +475,16 @@ BOOL LLButton::handleRightMouseUp(S32 x, S32 y, MASK mask)
void LLButton::onMouseEnter(S32 x, S32 y, MASK mask)
{
LLUICtrl::onMouseEnter(x, y, mask);
if (isInEnabledChain())
mNeedsHighlight = TRUE;
}
void LLButton::onMouseLeave(S32 x, S32 y, MASK mask)
{
LLUICtrl::onMouseLeave(x, y, mask);
mNeedsHighlight = FALSE;
}

View File

@ -0,0 +1,86 @@
/**
* @file lldockablefloater.cpp
* @brief Creates a panel of a specific kind for a toast
*
* $LicenseInfo:firstyear=2000&license=viewergpl$
*
* Copyright (c) 2000-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "lldockablefloater.h"
LLDockableFloater::LLDockableFloater(LLDockControl* dockControl,
const LLSD& key, const Params& params) :
LLFloater(key, params), mDockControl(dockControl)
{
}
LLDockableFloater::~LLDockableFloater()
{
}
BOOL LLDockableFloater::postBuild()
{
mDockTongue = LLUI::getUIImage("windows/Flyout_Pointer.png");
LLFloater::setDocked(true);
return LLView::postBuild();
}
void LLDockableFloater::setDocked(bool docked, bool pop_on_undock)
{
if (docked)
{
mDockControl.get()->on();
}
else
{
mDockControl.get()->off();
}
LLFloater::setDocked(docked, pop_on_undock);
}
void LLDockableFloater::draw()
{
mDockControl.get()->repositionDockable();
mDockControl.get()->drawToungue();
LLFloater::draw();
}
void LLDockableFloater::setDockControl(LLDockControl* dockControl)
{
mDockControl.reset(dockControl);
}
const LLUIImagePtr& LLDockableFloater::getDockTongue()
{
return mDockTongue;
}
LLDockControl* LLDockableFloater::getDockControl()
{
return mDockControl.get();
}

View File

@ -0,0 +1,65 @@
/**
* @file lldockablefloater.h
* @brief Creates a panel of a specific kind for a toast.
*
* $LicenseInfo:firstyear=2003&license=viewergpl$
*
* Copyright (c) 2003-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LL_DOCKABLEFLOATER_H
#define LL_DOCKABLEFLOATER_H
#include "llerror.h"
#include "llfloater.h"
#include "lldockcontrol.h"
/**
* Represents floater that can dock.
* In case impossibility deriving from LLDockableFloater use LLDockControl.
*/
class LLDockableFloater : public LLFloater
{
public:
LOG_CLASS(LLDockableFloater);
LLDockableFloater(LLDockControl* dockControl, const LLSD& key, const Params& params = getDefaultParams());
virtual ~LLDockableFloater();
/* virtula */BOOL postBuild();
/* virtual */void setDocked(bool docked, bool pop_on_undock = true);
/* virtual */void draw();
protected:
void setDockControl(LLDockControl* dockControl);
LLDockControl* getDockControl();
const LLUIImagePtr& getDockTongue();
private:
std::auto_ptr<LLDockControl> mDockControl;
LLUIImagePtr mDockTongue;
};
#endif /* LL_DOCKABLEFLOATER_H */

View File

@ -0,0 +1,126 @@
/**
* @file lldockcontrol.cpp
* @brief Creates a panel of a specific kind for a toast
*
* $LicenseInfo:firstyear=2000&license=viewergpl$
*
* Copyright (c) 2000-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "lldockcontrol.h"
LLDockControl::LLDockControl(LLView* dockWidget, LLFloater* dockableFloater,
const LLUIImagePtr& dockTongue, DocAt dockAt, bool enabled) :
mDockWidget(dockWidget), mDockableFloater(dockableFloater), mDockTongue(
dockTongue)
{
mDockAt = dockAt;
if (enabled)
{
on();
}
else
{
off();
}
}
LLDockControl::~LLDockControl()
{
}
void LLDockControl::repositionDockable()
{
if (mEnabled)
{
calculateDockablePosition();
}
}
void LLDockControl::calculateDockablePosition()
{
LLRect dockRect = mDockWidget->calcScreenRect();
if (mPrevDockRect != dockRect || mRecalculateDocablePosition)
{
LLRect dockableRect = mDockableFloater->calcScreenRect();
LLRect rootRect = mDockableFloater->getRootView()->getRect();
S32 x = 0;
S32 y = 0;
switch (mDockAt)
{
case TOP:
x = dockRect.getCenterX() - dockableRect.getWidth() / 2;
y = dockRect.mTop + mDockTongue->getHeight()
+ dockableRect.getHeight();
if (x < rootRect.mLeft)
{
x = rootRect.mLeft;
}
if (x + dockableRect.getWidth() > rootRect.mRight)
{
x = rootRect.mRight - dockableRect.getWidth();
}
mDockTongueX = dockRect.getCenterX() - mDockTongue->getWidth() / 2;
mDockTongueY = dockRect.mTop;
break;
}
dockableRect.setLeftTopAndSize(x, y, dockableRect.getWidth(),
dockableRect.getHeight());
LLRect localDocableParentRect;
mDockableFloater->getParent()->screenRectToLocal(dockableRect,
&localDocableParentRect);
mDockableFloater->setRect(localDocableParentRect);
mDockableFloater->screenPointToLocal(mDockTongueX, mDockTongueY,
&mDockTongueX, &mDockTongueY);
mPrevDockRect = dockRect;
mRecalculateDocablePosition = false;
}
}
void LLDockControl::on()
{
mDockableFloater->setCanDrag(false);
mEnabled = true;
mRecalculateDocablePosition = true;
}
void LLDockControl::off()
{
mDockableFloater->setCanDrag(true);
mEnabled = false;
}
void LLDockControl::drawToungue()
{
if (mEnabled)
{
mDockTongue->draw(mDockTongueX, mDockTongueY);
}
}

View File

@ -0,0 +1,81 @@
/**
* @file lldockcontrol.h
* @brief Creates a panel of a specific kind for a toast.
*
* $LicenseInfo:firstyear=2003&license=viewergpl$
*
* Copyright (c) 2003-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LL_DOCKCONTROL_H
#define LL_DOCKCONTROL_H
#include "llerror.h"
#include "llview.h"
#include "llfloater.h"
#include "lluiimage.h"
/**
* Provides services for docking of specified floater.
* This class should be used in case impossibility deriving from LLDockableFloater.
*/
class LLDockControl
{
public:
enum DocAt
{
TOP
};
public:
LOG_CLASS(LLDockControl);
LLDockControl(LLView* dockWidget, LLFloater* dockableFloater,
const LLUIImagePtr& dockTongue, DocAt dockAt,
bool enabled);
virtual ~LLDockControl();
public:
void on();
void off();
void setDock(LLView* dockWidget)
{ mDockWidget = dockWidget;};
void repositionDockable();
void drawToungue();
protected:
virtual void calculateDockablePosition();
private:
bool mEnabled;
bool mRecalculateDocablePosition;
DocAt mDockAt;
LLView* mDockWidget;
LLRect mPrevDockRect;
LLFloater* mDockableFloater;
LLUIImagePtr mDockTongue;
S32 mDockTongueX;
S32 mDockTongueY;
};
#endif /* LL_DOCKCONTROL_H */

View File

@ -123,6 +123,7 @@ LLScrollListCtrl::Params::Params()
sort_ascending("sort_ascending", true),
commit_on_keyboard_movement("commit_on_keyboard_movement", true),
heading_height("heading_height"),
page_lines("page_lines", 0),
background_visible("background_visible"),
draw_stripes("draw_stripes"),
column_padding("column_padding"),
@ -145,7 +146,7 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p)
: LLUICtrl(p),
mLineHeight(0),
mScrollLines(0),
mPageLines(0),
mPageLines(p.page_lines),
mMaxSelectable(0),
mAllowKeyboardMovement(TRUE),
mCommitOnKeyboardMovement(p.commit_on_keyboard_movement),
@ -196,8 +197,6 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p)
updateLineHeight();
mPageLines = mLineHeight? (mItemListRect.getHeight()) / mLineHeight : 0;
// Init the scrollbar
static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
@ -214,7 +213,7 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p)
sbparams.orientation(LLScrollbar::VERTICAL);
sbparams.doc_size(getItemCount());
sbparams.doc_pos(mScrollLines);
sbparams.page_size(mPageLines);
sbparams.page_size( mPageLines ? mPageLines : getItemCount() );
sbparams.change_callback(boost::bind(&LLScrollListCtrl::onScrollChange, this, _1, _2));
sbparams.follows.flags(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM);
sbparams.visible(false);
@ -469,8 +468,12 @@ void LLScrollListCtrl::updateLayout()
getChildView("comment_text")->setShape(mItemListRect);
// how many lines of content in a single "page"
mPageLines = mLineHeight? mItemListRect.getHeight() / mLineHeight : 0;
BOOL scrollbar_visible = getItemCount() > mPageLines;
S32 page_lines = mLineHeight? mItemListRect.getHeight() / mLineHeight : getItemCount();
//if mPageLines is NOT provided display all item
if(mPageLines)
page_lines = mPageLines;
BOOL scrollbar_visible = mLineHeight * getItemCount() > mItemListRect.getHeight();
if (scrollbar_visible)
{
// provide space on the right for scrollbar
@ -479,7 +482,7 @@ void LLScrollListCtrl::updateLayout()
mScrollbar->setOrigin(getRect().getWidth() - mBorderThickness - scrollbar_size, mItemListRect.mBottom);
mScrollbar->reshape(scrollbar_size, mItemListRect.getHeight() + (mDisplayColumnHeaders ? mHeadingHeight : 0));
mScrollbar->setPageSize( mPageLines );
mScrollbar->setPageSize(page_lines);
mScrollbar->setDocSize( getItemCount() );
mScrollbar->setVisible(scrollbar_visible);
@ -491,6 +494,9 @@ void LLScrollListCtrl::updateLayout()
void LLScrollListCtrl::fitContents(S32 max_width, S32 max_height)
{
S32 height = llmin( getRequiredRect().getHeight(), max_height );
if(mPageLines)
height = llmin( mPageLines * mLineHeight + (mDisplayColumnHeaders ? mHeadingHeight : 0), height );
S32 width = getRect().getWidth();
reshape( width, height );
@ -721,6 +727,12 @@ void LLScrollListCtrl::setHeadingHeight(S32 heading_height)
updateLayout();
}
void LLScrollListCtrl::setPageLines(S32 new_page_lines)
{
mPageLines = new_page_lines;
updateLayout();
}
BOOL LLScrollListCtrl::selectFirstItem()
{
@ -1367,7 +1379,7 @@ void LLScrollListCtrl::drawItems()
S32 y = mItemListRect.mTop - mLineHeight;
// allow for partial line at bottom
S32 num_page_lines = mPageLines + 1;
S32 num_page_lines = (mPageLines)? mPageLines : getItemCount() + 1;
LLRect item_rect;
@ -1856,7 +1868,7 @@ LLScrollListItem* LLScrollListCtrl::hitItem( S32 x, S32 y )
mLineHeight );
// allow for partial line at bottom
S32 num_page_lines = mPageLines + 1;
S32 num_page_lines = (mPageLines)? mPageLines : getItemCount() + 1;
S32 line = 0;
item_list::iterator iter;
@ -2421,7 +2433,8 @@ void LLScrollListCtrl::scrollToShowSelected()
}
S32 lowest = mScrollLines;
S32 highest = mScrollLines + mPageLines;
S32 page_lines = (mPageLines)? mPageLines : getItemCount();
S32 highest = mScrollLines + page_lines;
if (index < lowest)
{
@ -2430,7 +2443,7 @@ void LLScrollListCtrl::scrollToShowSelected()
}
else if (highest <= index)
{
setScrollPos(index - mPageLines + 1);
setScrollPos(index - page_lines + 1);
}
}

View File

@ -87,6 +87,7 @@ public:
// layout
Optional<S32> column_padding,
page_lines,
heading_height;
// sort and search behavior
@ -314,6 +315,11 @@ public:
S32 getMaxContentWidth() { return mMaxContentWidth; }
void setHeadingHeight(S32 heading_height);
/**
* Sets max visible lines without scroolbar, if this value equals to 0,
* then display all items.
*/
void setPageLines(S32 page_lines );
void setCollapseEmptyColumns(BOOL collapse);
LLScrollListItem* hitItem(S32 x,S32 y);
@ -368,11 +374,13 @@ protected:
typedef std::deque<LLScrollListItem *> item_list;
item_list& getItemList() { return mItemList; }
void updateLineHeight();
private:
void selectPrevItem(BOOL extend_selection);
void selectNextItem(BOOL extend_selection);
void drawItems();
void updateLineHeight();
void updateLineHeightInsert(LLScrollListItem* item);
void reportInvalidInput();
BOOL isRepeatedChars(const LLWString& string) const;

View File

@ -481,7 +481,10 @@ void LLTextBox::drawText( S32 x, S32 y, const LLWString &text, const LLColor4& c
mShadowType,
line_length, getRect().getWidth(), NULL, mUseEllipses );
cur_pos += line_length + 1;
y -= llfloor(mDefaultFont->getLineHeight()) + mLineSpacing;
S32 line_height = llfloor(mDefaultFont->getLineHeight()) + mLineSpacing;
y -= line_height;
if(y < line_height)
break;
}
}
}

View File

@ -3412,11 +3412,8 @@ void LLTextEditor::endOfDoc()
// Sets the scrollbar from the cursor position
void LLTextEditor::updateScrollFromCursor()
{
if (mReadOnly)
{
// no cursor in read only mode
return;
}
// Update scroll position even in read-only mode (when there's no cursor displayed)
// because startOfDoc()/endOfDoc() modify cursor position. See EXT-736.
if (!mScrollNeeded)
{

View File

@ -2741,11 +2741,11 @@ void LLView::notifyParent(const LLSD& info)
if(parent)
parent->notifyParent(info);
}
void LLView::notifyChilds(const LLSD& info)
void LLView::notifyChildren(const LLSD& info)
{
for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
{
(*child_it)->notifyChilds(info);
(*child_it)->notifyChildren(info);
}
}

View File

@ -550,7 +550,7 @@ public:
virtual void handleReshape(const LLRect& rect, bool by_user);
virtual void notifyParent(const LLSD& info);
virtual void notifyChilds(const LLSD& info);
virtual void notifyChildren(const LLSD& info);
protected:
void drawDebugRect();

View File

@ -180,7 +180,6 @@ set(viewer_SOURCE_FILES
llfloaterlandholdings.cpp
llfloatermap.cpp
llfloatermemleak.cpp
llfloatermute.cpp
llfloaternamedesc.cpp
llfloaternotificationsconsole.cpp
llfloateropenobject.cpp
@ -286,6 +285,7 @@ set(viewer_SOURCE_FILES
llpanelavatar.cpp
llpanelavatarrow.cpp
llpanelavatartag.cpp
llpanelblockedlist.cpp
llpanelclassified.cpp
llpanelcontents.cpp
llpaneldirbrowser.cpp
@ -348,6 +348,8 @@ set(viewer_SOURCE_FILES
llremoteparcelrequest.cpp
llsavedsettingsglue.cpp
llscreenchannel.cpp
llsearchcombobox.cpp
llsearchhistory.cpp
llselectmgr.cpp
llsidetray.cpp
llsidetraypanelcontainer.cpp
@ -634,7 +636,6 @@ set(viewer_HEADER_FILES
llfloaterlandholdings.h
llfloatermap.h
llfloatermemleak.h
llfloatermute.h
llfloaternamedesc.h
llfloaternotificationsconsole.h
llfloateropenobject.h
@ -738,6 +739,7 @@ set(viewer_HEADER_FILES
llpanelavatar.h
llpanelavatarrow.h
llpanelavatartag.h
llpanelblockedlist.h
llpanelclassified.h
llpanelcontents.h
llpaneldirbrowser.h
@ -802,6 +804,8 @@ set(viewer_HEADER_FILES
llrootview.h
llscreenchannel.h
llsavedsettingsglue.h
llsearchcombobox.h
llsearchhistory.h
llselectmgr.h
llsidetray.h
llsidetraypanelcontainer.h

View File

@ -6866,10 +6866,10 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>ShowPGSearchAll</key>
<key>ShowCameraAndMoveControls</key>
<map>
<key>Comment</key>
<string>Show/Hide Navigation Bar Favorites Panel</string>
<string>Show/Hide Camera and Move controls in the bottom tray</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@ -6880,7 +6880,7 @@
<key>ShowNavbarFavoritesPanel</key>
<map>
<key>Comment</key>
<string>Show/Hide Navigation Bar Navigation Panel</string>
<string>Show/Hide Navigation Bar Favorites Panel</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@ -6889,6 +6889,17 @@
<integer>1</integer>
</map>
<key>ShowNavbarNavigationPanel</key>
<map>
<key>Comment</key>
<string>Show/Hide Navigation Bar Navigation Panel</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>ShowPGSearchAll</key>
<map>
<key>Comment</key>
<string>Display results of search All that are flagged as PG</string>

View File

@ -47,7 +47,6 @@
#include "llfloaterdirectory.h"
#include "llfloaterland.h"
#include "llfloatermute.h"
#include "llfloatersnapshot.h"
#include "llfloatertools.h"
#include "llfloaterworldmap.h"

View File

@ -223,12 +223,13 @@ BOOL LLAvatarList::update(const std::vector<LLUUID>& all_buddies, const std::str
#endif
setScrollPos(pos);
updateLineHeight();
LLRect rect = getRequiredRect();
LLSD params;
params["action"] = "size_changes";
params["width"] = rect.getWidth();
params["height"] = rect.getHeight();
params["height"] = llmax(rect.getHeight(),20) + 5;
getParent()->notifyParent(params);

View File

@ -60,7 +60,6 @@ LLBottomTray::LLBottomTray(const LLSD&)
mSysWell = getChild<LLNotificationChiclet>("sys_well");
mSysWell->setNotificationChicletWindow(LLFloaterReg::getInstance("syswell_window"));
LLFloaterReg::getTypedInstance<LLSysWellWindow>("syswell_window")->setSysWell(mSysWell);
mChicletPanel->setChicletClickedCallback(boost::bind(&LLBottomTray::onChicletClick,this,_1));
@ -80,8 +79,16 @@ LLBottomTray::LLBottomTray(const LLSD&)
BOOL LLBottomTray::postBuild()
{
mCommitCallbackRegistrar.add("ShowCamMoveCtrls.Action", boost::bind(&LLBottomTray::onShowCamMoveCtrlsContextMenuItemClicked, this, _2));
mEnableCallbackRegistrar.add("ShowCamMoveCtrls.EnableMenuItem", boost::bind(&LLBottomTray::onShowCamMoveCtrlsContextMenuItemEnabled, this, _2));
mShowCamMoveCtrlsContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_hide_camera_move_controls.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
gMenuHolder->addChild(mShowCamMoveCtrlsContextMenu);
mNearbyChatBar = getChild<LLNearbyChatBar>("chat_bar");
mToolbarStack = getChild<LLLayoutStack>("toolbar_stack");
mMovementPanel = getChild<LLPanel>("movement_panel");
mCamPanel = getChild<LLPanel>("cam_panel");
return TRUE;
}
@ -205,8 +212,9 @@ void LLBottomTray::setVisible(BOOL visible)
child_it != mToolbarStack->getChildList()->end(); child_it++)
{
LLView* viewp = *child_it;
std::string name = viewp->getName();
if ("chat_bar" == viewp->getName())
if ("chat_bar" == name || "movement_panel" == name || "cam_panel" == name)
continue;
else
{
@ -216,3 +224,45 @@ void LLBottomTray::setVisible(BOOL visible)
}
}
BOOL LLBottomTray::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
if (mShowCamMoveCtrlsContextMenu)
{
mShowCamMoveCtrlsContextMenu->buildDrawLabels();
mShowCamMoveCtrlsContextMenu->updateParent(LLMenuGL::sMenuContainer);
LLMenuGL::showPopup(this, mShowCamMoveCtrlsContextMenu, x, y);
}
return TRUE;
}
bool LLBottomTray::onShowCamMoveCtrlsContextMenuItemEnabled(const LLSD& userdata)
{
std::string item = userdata.asString();
if (item == "show_camera_move_controls")
{
return gSavedSettings.getBOOL("ShowCameraAndMoveControls");
}
return FALSE;
}
void LLBottomTray::onShowCamMoveCtrlsContextMenuItemClicked(const LLSD& userdata)
{
std::string item = userdata.asString();
if (item == "show_camera_move_controls")
{
BOOL state = !gSavedSettings.getBOOL("ShowCameraAndMoveControls");
showCameraAndMoveControls(state);
gSavedSettings.setBOOL("ShowCameraAndMoveControls", state);
}
}
void LLBottomTray::showCameraAndMoveControls(BOOL visible)
{
mCamPanel->setVisible(visible);
mMovementPanel->setVisible(visible);
}

View File

@ -33,6 +33,8 @@
#ifndef LL_LLBOTTOMPANEL_H
#define LL_LLBOTTOMPANEL_H
#include <llmenugl.h>
#include "llpanel.h"
#include "llimview.h"
@ -68,6 +70,10 @@ public:
virtual void onFocusLost();
virtual void setVisible(BOOL visible);
virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
void showCameraAndMoveControls(BOOL visible);
private:
protected:
@ -76,6 +82,9 @@ protected:
void onChicletClick(LLUICtrl* ctrl);
bool onShowCamMoveCtrlsContextMenuItemEnabled(const LLSD& userdata);
void onShowCamMoveCtrlsContextMenuItemClicked(const LLSD& userdata);
static void* createNearbyChatBar(void* userdata);
/**
@ -88,7 +97,9 @@ protected:
LLTalkButton* mTalkBtn;
LLNearbyChatBar* mNearbyChatBar;
LLLayoutStack* mToolbarStack;
LLMenuGL* mShowCamMoveCtrlsContextMenu;
LLPanel* mMovementPanel;
LLPanel* mCamPanel;
};
#endif // LL_LLBOTTOMPANEL_H

View File

@ -117,6 +117,10 @@ boost::signals2::connection LLNotificationChiclet::setClickCallback(
return mButton->setClickedCallback(cb);
}
void LLNotificationChiclet::setToggleState(BOOL toggled) {
mButton->setToggleState(toggled);
}
void LLNotificationChiclet::updateUreadIMNotifications()
{
mUreadIMNotifications = gIMMgr->getNumberOfUnreadIM();
@ -235,6 +239,7 @@ LLIMP2PChiclet::Params::Params()
avatar_icon.name("avatar_icon");
avatar_icon.rect(LLRect(0, 25, 25, 0));
avatar_icon.mouse_opaque(false);
unread_notifications.name("unread");
unread_notifications.rect(LLRect(25, 25, 45, 0));
@ -242,6 +247,7 @@ LLIMP2PChiclet::Params::Params()
unread_notifications.font_halign(LLFontGL::HCENTER);
unread_notifications.v_pad(5);
unread_notifications.text_color(LLColor4::white);
unread_notifications.mouse_opaque(false);
speaker.name("speaker");
speaker.rect(LLRect(45, 25, 65, 0));

View File

@ -537,6 +537,7 @@ public:
void incUreadSystemNotifications() { setCounter(++mUreadSystemNotifications + mUreadIMNotifications); }
void decUreadSystemNotifications() { setCounter(--mUreadSystemNotifications + mUreadIMNotifications); }
void updateUreadIMNotifications();
void setToggleState(BOOL toggled);
protected:
LLNotificationChiclet(const Params& p);

View File

@ -55,6 +55,7 @@
#include "llviewerinventory.h"
#include "llviewermenu.h"
#include "llviewermenu.h"
#include "lltooldraganddrop.h"
static LLDefaultChildRegistry::Register<LLFavoritesBarCtrl> r("favorites_bar");
@ -73,6 +74,7 @@ public:
, mLoaded(false) {}
void setLandmarkID(const LLUUID& id) { mLandmarkID = id; }
const LLUUID& getLandmarkId() const { return mLandmarkID; }
const std::string& getSLURL()
{
@ -130,8 +132,21 @@ public:
msg = mUrlGetter.getSLURL();
return TRUE;
}
/*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask)
{
LLFavoritesBarCtrl* fb = dynamic_cast<LLFavoritesBarCtrl*>(getParent());
if (fb)
{
fb->handleHover(x, y, mask);
}
return LLButton::handleHover(x, y, mask);
}
void setLandmarkID(const LLUUID& id){ mUrlGetter.setLandmarkID(id); }
const LLUUID& getLandmarkId() const { return mUrlGetter.getLandmarkId(); }
protected:
LLFavoriteLandmarkButton(const LLButton::Params& p) : LLButton(p) {}
@ -141,6 +156,33 @@ private:
LLSLURLGetter mUrlGetter;
};
class LLFavoritesToggleableMenu : public LLToggleableMenu
{
public:
virtual BOOL handleHover(S32 x, S32 y, MASK mask)
{
if (fb)
{
fb->handleHover(x, y, mask);
}
return LLToggleableMenu::handleHover(x, y, mask);
}
void initFavoritesBarPointer(LLFavoritesBarCtrl* fb) { this->fb = fb; }
protected:
LLFavoritesToggleableMenu(const LLToggleableMenu::Params& p):
LLToggleableMenu(p)
{
}
friend class LLUICtrlFactory;
private:
LLFavoritesBarCtrl* fb;
};
/**
* This class is needed to override LLMenuItemCallGL default handleToolTip function and
* show SLURL as button tooltip.
@ -164,6 +206,18 @@ public:
void setLandmarkID(const LLUUID& id){ mUrlGetter.setLandmarkID(id); }
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask)
{
mMouseDownSignal(this, x, y, mask);
return LLMenuItemCallGL::handleMouseDown(x, y, mask);
}
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask)
{
mMouseUpSignal(this, x, y, mask);
return LLMenuItemCallGL::handleMouseUp(x, y, mask);
}
protected:
LLFavoriteLandmarkMenuItem(const LLMenuItemCallGL::Params& p) : LLMenuItemCallGL(p) {}
@ -181,6 +235,14 @@ struct LLFavoritesSort
// TODO - made it customizible using gSavedSettings
bool operator()(const LLViewerInventoryItem* const& a, const LLViewerInventoryItem* const& b)
{
S32 sortField1 = a->getSortField();
S32 sortField2 = b->getSortField();
if (!(sortField1 < 0 && sortField2 < 0))
{
return sortField2 > sortField1;
}
time_t first_create = a->getCreationDate();
time_t second_create = b->getCreationDate();
if (first_create == second_create)
@ -239,29 +301,34 @@ BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
case DAD_LANDMARK:
{
// Copy the item into the favorites folder (if it's not already there).
LLInventoryItem *item = (LLInventoryItem *)cargo_data;
LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE);
if (item->getParentUUID() == favorites_id)
LLInventoryItem *item = (LLInventoryItem *)cargo_data;
// check if we are dragging an existing item from the favorites bar
if (item && mDragItemId == item->getUUID())
{
llwarns << "Attemt to copy a favorite item into the same folder." << llendl;
break;
*accept = ACCEPT_YES_SINGLE;
if (drop)
{
handleExistingFavoriteDragAndDrop(x, y);
}
}
*accept = ACCEPT_YES_COPY_SINGLE;
if (drop)
else
{
copy_inventory_item(
gAgent.getID(),
item->getPermissions().getOwner(),
item->getUUID(),
favorites_id,
std::string(),
LLPointer<LLInventoryCallback>(NULL));
LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE);
if (item->getParentUUID() == favorites_id)
{
llwarns << "Attemt to copy a favorite item into the same folder." << llendl;
break;
}
llinfos << "Copied inventory item #" << item->getUUID() << " to favorites." << llendl;
*accept = ACCEPT_YES_COPY_SINGLE;
if (drop)
{
handleNewFavoriteDragAndDrop(item, favorites_id, x, y);
}
}
}
break;
default:
@ -271,6 +338,61 @@ BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
return TRUE;
}
void LLFavoritesBarCtrl::handleExistingFavoriteDragAndDrop(S32 x, S32 y)
{
LLFavoriteLandmarkButton* dest = dynamic_cast<LLFavoriteLandmarkButton*>(findChildByLocalCoords(x, y));
if (dest)
{
updateItemsOrder(mItems, mDragItemId, dest->getLandmarkId());
}
else
{
mItems.push_back(gInventory.getItem(mDragItemId));
}
saveItemsOrder(mItems);
LLFavoritesToggleableMenu* menu = (LLFavoritesToggleableMenu*) mPopupMenuHandle.get();
if (menu && menu->getVisible())
{
menu->setVisible(FALSE);
showDropDownMenu();
}
mDragItemId = LLUUID::null;
getWindow()->setCursor(UI_CURSOR_ARROW);
}
void LLFavoritesBarCtrl::handleNewFavoriteDragAndDrop(LLInventoryItem *item, const LLUUID& favorites_id, S32 x, S32 y)
{
LLFavoriteLandmarkButton* dest = dynamic_cast<LLFavoriteLandmarkButton*>(findChildByLocalCoords(x, y));
if (dest)
{
insertBeforeItem(mItems, dest->getLandmarkId(), item->getUUID());
}
else
{
mItems.push_back(gInventory.getItem(item->getUUID()));
}
saveItemsOrder(mItems);
copy_inventory_item(
gAgent.getID(),
item->getPermissions().getOwner(),
item->getUUID(),
favorites_id,
std::string(),
LLPointer<LLInventoryCallback>(NULL));
getWindow()->setCursor(UI_CURSOR_ARROW);
llinfos << "Copied inventory item #" << item->getUUID() << " to favorites." << llendl;
}
//virtual
void LLFavoritesBarCtrl::changed(U32 mask)
{
@ -311,9 +433,9 @@ LLXMLNodePtr LLFavoritesBarCtrl::getButtonXMLNode()
void LLFavoritesBarCtrl::updateButtons(U32 bar_width)
{
LLInventoryModel::item_array_t items;
mItems.clear();
if (!collectFavoriteItems(items))
if (!collectFavoriteItems(mItems))
{
return;
}
@ -331,7 +453,7 @@ void LLFavoritesBarCtrl::updateButtons(U32 bar_width)
const S32 buttonVGap = 2;
S32 count = items.count();
S32 count = mItems.count();
const S32 buttonHPad = LLUI::sSettingGroups["config"]->getS32("ButtonHPad");
const S32 chevron_button_width = mFont->getWidth(">>") + buttonHPad * 2;
@ -369,7 +491,7 @@ void LLFavoritesBarCtrl::updateButtons(U32 bar_width)
S32 i;
for (i = 0; i < mFirstDropDownItem; ++i)
{
if (mItemNamesCache.get(i) != items.get(i)->getName())
if (mItemNamesCache.get(i) != mItems.get(i)->getName())
{
break;
}
@ -387,7 +509,7 @@ void LLFavoritesBarCtrl::updateButtons(U32 bar_width)
mItemNamesCache.clear();
for (S32 i = 0; i < mFirstDropDownItem; i++)
{
mItemNamesCache.put(items.get(i)->getName());
mItemNamesCache.put(mItems.get(i)->getName());
}
// Rebuild the buttons only
@ -404,7 +526,7 @@ void LLFavoritesBarCtrl::updateButtons(U32 bar_width)
}
}
createButtons(items, buttonXMLNode, buttonWidth, buttonHGap);
createButtons(mItems, buttonXMLNode, buttonWidth, buttonHGap);
}
// Chevron button
@ -467,9 +589,9 @@ void LLFavoritesBarCtrl::createButtons(const LLInventoryModel::item_array_t &ite
{
S32 curr_x = buttonHGap;
// Adding buttons
for(S32 i = mFirstDropDownItem -1; i >= 0; i--)
for(S32 i = mFirstDropDownItem -1, j = 0; i >= 0; i--)
{
LLInventoryItem* item = items.get(i);
LLViewerInventoryItem* item = items.get(j++);
LLFavoriteLandmarkButton* fav_btn = LLUICtrlFactory::defaultBuilder<LLFavoriteLandmarkButton>(buttonXMLNode, this, NULL);
if (NULL == fav_btn)
@ -488,6 +610,10 @@ void LLFavoritesBarCtrl::createButtons(const LLInventoryModel::item_array_t &ite
fav_btn->setToolTip(item->getName());
fav_btn->setCommitCallback(boost::bind(&LLFavoritesBarCtrl::onButtonClick, this, item->getUUID()));
fav_btn->setRightMouseDownCallback(boost::bind(&LLFavoritesBarCtrl::onButtonRightClick, this, item->getUUID(), _1, _2, _3,_4 ));
fav_btn->LLUICtrl::setMouseDownCallback(boost::bind(&LLFavoritesBarCtrl::onButtonMouseDown, this, item->getUUID(), _1, _2, _3, _4));
fav_btn->LLUICtrl::setMouseUpCallback(boost::bind(&LLFavoritesBarCtrl::onButtonMouseUp, this, item->getUUID(), _1, _2, _3, _4));
sendChildToBack(fav_btn);
curr_x += buttonWidth + buttonHGap;
@ -521,6 +647,15 @@ BOOL LLFavoritesBarCtrl::collectFavoriteItems(LLInventoryModel::item_array_t &it
std::sort(items.begin(), items.end(), LLFavoritesSort());
if (needToSaveItemsOrder(items))
{
S32 sortField = 0;
for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i)
{
(*i)->setSortField(++sortField);
}
}
return TRUE;
}
@ -528,7 +663,7 @@ void LLFavoritesBarCtrl::showDropDownMenu()
{
if (mPopupMenuHandle.isDead())
{
LLToggleableMenu::Params menu_p;
LLFavoritesToggleableMenu::Params menu_p;
menu_p.name("favorites menu");
menu_p.can_tear_off(false);
menu_p.visible(false);
@ -536,26 +671,26 @@ void LLFavoritesBarCtrl::showDropDownMenu()
menu_p.max_scrollable_items = 10;
menu_p.preferred_width = DROP_DOWN_MENU_WIDTH;
LLToggleableMenu* menu = LLUICtrlFactory::create<LLToggleableMenu>(menu_p);
LLFavoritesToggleableMenu* menu = LLUICtrlFactory::create<LLFavoritesToggleableMenu>(menu_p);
menu->initFavoritesBarPointer(this);
mPopupMenuHandle = menu->getHandle();
}
LLToggleableMenu* menu = (LLToggleableMenu*)mPopupMenuHandle.get();
LLFavoritesToggleableMenu* menu = (LLFavoritesToggleableMenu*)mPopupMenuHandle.get();
if(menu)
{
if (!menu->toggleVisibility())
return;
LLInventoryModel::item_array_t items;
mItems.clear();
if (!collectFavoriteItems(items))
if (!collectFavoriteItems(mItems))
{
return;
}
S32 count = items.count();
S32 count = mItems.count();
// Check it there are changed items, since last call
if (mItemNamesCache.size() == count)
@ -563,7 +698,7 @@ void LLFavoritesBarCtrl::showDropDownMenu()
S32 i;
for (i = mFirstDropDownItem; i < count; i++)
{
if (mItemNamesCache.get(i) != items.get(i)->getName())
if (mItemNamesCache.get(i) != mItems.get(i)->getName())
{
break;
}
@ -587,7 +722,7 @@ void LLFavoritesBarCtrl::showDropDownMenu()
{
for (S32 i = mFirstDropDownItem; i < count; i++)
{
mItemNamesCache.put(items.get(i)->getName());
mItemNamesCache.put(mItems.get(i)->getName());
}
}
@ -598,17 +733,18 @@ void LLFavoritesBarCtrl::showDropDownMenu()
for(S32 i = mFirstDropDownItem; i < count; i++)
{
LLInventoryItem* item = items.get(i);
LLViewerInventoryItem* item = mItems.get(i);
const std::string& item_name = item->getName();
LLMenuItemCallGL::Params item_params;
LLFavoriteLandmarkMenuItem::Params item_params;
item_params.name(item_name);
item_params.label(item_name);
item_params.on_click.function(boost::bind(&LLFavoritesBarCtrl::onButtonClick, this, item->getUUID()));
LLFavoriteLandmarkMenuItem *menu_item = LLUICtrlFactory::create<LLFavoriteLandmarkMenuItem>(item_params);
menu_item->setRightMouseDownCallback(boost::bind(&LLFavoritesBarCtrl::onButtonRightClick, this,item->getUUID(),_1,_2,_3,_4));
menu_item->setLandmarkID(item->getUUID());
menu_item->LLUICtrl::setMouseDownCallback(boost::bind(&LLFavoritesBarCtrl::onButtonMouseDown, this, item->getUUID(), _1, _2, _3, _4));
menu_item->LLUICtrl::setMouseUpCallback(boost::bind(&LLFavoritesBarCtrl::onButtonMouseUp, this, item->getUUID(), _1, _2, _3, _4));
// Check whether item name wider than menu
if (menu_item->getNominalWidth() > max_width)
@ -644,13 +780,6 @@ void LLFavoritesBarCtrl::showDropDownMenu()
void LLFavoritesBarCtrl::onButtonClick(LLUUID item_id)
{
LLInventoryModel::item_array_t items;
if (!collectFavoriteItems(items))
{
return;
}
// We only have one Inventory, gInventory. Some day this should be better abstracted.
LLInvFVBridgeAction::doAction(item_id,&gInventory);
}
@ -797,5 +926,135 @@ void LLFavoritesBarCtrl::pastFromClipboard() const
}
}
void LLFavoritesBarCtrl::onButtonMouseDown(LLUUID id, LLUICtrl* ctrl, S32 x, S32 y, MASK mask)
{
mDragItemId = id;
mStartDrag = TRUE;
S32 screenX, screenY;
localPointToScreen(x, y, &screenX, &screenY);
LLToolDragAndDrop::getInstance()->setDragStart(screenX, screenY);
}
void LLFavoritesBarCtrl::onButtonMouseUp(LLUUID id, LLUICtrl* ctrl, S32 x, S32 y, MASK mask)
{
mDragItemId = LLUUID::null;
}
BOOL LLFavoritesBarCtrl::handleHover(S32 x, S32 y, MASK mask)
{
if (mDragItemId != LLUUID::null && mStartDrag)
{
S32 screenX, screenY;
localPointToScreen(x, y, &screenX, &screenY);
if(LLToolDragAndDrop::getInstance()->isOverThreshold(screenX, screenY))
{
LLToolDragAndDrop::getInstance()->beginDrag(
DAD_LANDMARK, mDragItemId,
LLToolDragAndDrop::SOURCE_LIBRARY);
mStartDrag = FALSE;
return LLToolDragAndDrop::getInstance()->handleHover(x, y, mask);
}
}
return TRUE;
}
LLUICtrl* LLFavoritesBarCtrl::findChildByLocalCoords(S32 x, S32 y)
{
LLUICtrl* ctrl = 0;
S32 screenX, screenY;
const child_list_t* list = getChildList();
localPointToScreen(x, y, &screenX, &screenY);
// look for a child which contains the point (screenX, screenY) in it's rectangle
for (child_list_const_iter_t i = list->begin(); i != list->end(); ++i)
{
LLRect rect;
localRectToScreen((*i)->getRect(), &rect);
if (rect.pointInRect(screenX, screenY))
{
ctrl = dynamic_cast<LLUICtrl*>(*i);
break;
}
}
return ctrl;
}
BOOL LLFavoritesBarCtrl::needToSaveItemsOrder(const LLInventoryModel::item_array_t& items)
{
BOOL result = FALSE;
// if there is an item without sort order field set, we need to save items order
for (LLInventoryModel::item_array_t::const_iterator i = items.begin(); i != items.end(); ++i)
{
if ((*i)->getSortField() < 0)
{
result = TRUE;
break;
}
}
return result;
}
void LLFavoritesBarCtrl::saveItemsOrder(LLInventoryModel::item_array_t& items)
{
int sortField = 0;
// current order is saved by setting incremental values (1, 2, 3, ...) for the sort field
for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i)
{
LLViewerInventoryItem* item = *i;
item->setSortField(++sortField);
item->setComplete(TRUE);
item->updateServer(FALSE);
gInventory.updateItem(item);
}
gInventory.notifyObservers();
}
LLInventoryModel::item_array_t::iterator LLFavoritesBarCtrl::findItemByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id)
{
LLInventoryModel::item_array_t::iterator result = items.end();
for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i)
{
if ((*i)->getUUID() == id)
{
result = i;
break;
}
}
return result;
}
void LLFavoritesBarCtrl::updateItemsOrder(LLInventoryModel::item_array_t& items, const LLUUID& srcItemId, const LLUUID& destItemId)
{
LLViewerInventoryItem* srcItem = gInventory.getItem(srcItemId);
LLViewerInventoryItem* destItem = gInventory.getItem(destItemId);
items.erase(findItemByUUID(items, srcItem->getUUID()));
items.insert(findItemByUUID(items, destItem->getUUID()), srcItem);
}
void LLFavoritesBarCtrl::insertBeforeItem(LLInventoryModel::item_array_t& items, const LLUUID& beforeItemId, const LLUUID& insertedItemId)
{
LLViewerInventoryItem* beforeItem = gInventory.getItem(beforeItemId);
LLViewerInventoryItem* insertedItem = gInventory.getItem(insertedItemId);
items.insert(findItemByUUID(items, beforeItem->getUUID()), insertedItem);
}
// EOF

View File

@ -60,6 +60,8 @@ public:
EAcceptance* accept,
std::string& tooltip_msg);
/*virtual*/ BOOL handleHover(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);
@ -73,10 +75,12 @@ protected:
void onButtonClick(LLUUID id);
void onButtonRightClick(LLUUID id,LLView* button,S32 x,S32 y,MASK mask);
void onButtonMouseDown(LLUUID id, LLUICtrl* button, S32 x, S32 y, MASK mask);
void onButtonMouseUp(LLUUID id, LLUICtrl* button, S32 x, S32 y, MASK mask);
void doToSelected(const LLSD& userdata);
BOOL isClipboardPasteable() const;
void pastFromClipboard() const;
void showDropDownMenu();
@ -94,8 +98,49 @@ protected:
LLRect mChevronRect;
std::string mChevronButtonToolTip;
private:
/*
* Helper function to make code more readable. It handles all drag and drop
* operations of the existing favorites items on the favorites bar.
*/
void handleExistingFavoriteDragAndDrop(S32 x, S32 y);
/*
* Helper function to make code more readable. It handles all drag and drop
* operations of the new landmark to the favorites bar.
*/
void handleNewFavoriteDragAndDrop(LLInventoryItem *item, const LLUUID& favorites_id, S32 x, S32 y);
// finds a control under the specified LOCAL point
LLUICtrl* findChildByLocalCoords(S32 x, S32 y);
// checks if the current order of the favorites items must be saved
BOOL needToSaveItemsOrder(const LLInventoryModel::item_array_t& items);
// saves current order of the favorites items
void saveItemsOrder(LLInventoryModel::item_array_t& items);
/*
* changes favorites items order by insertion of the item identified by srcItemId
* BEFORE the item identified by destItemId. both items must exist in items array.
*/
void updateItemsOrder(LLInventoryModel::item_array_t& items, const LLUUID& srcItemId, const LLUUID& destItemId);
/*
* inserts an item identified by insertedItemId BEFORE an item identified by beforeItemId.
* this function assumes that an item identified by insertedItemId doesn't exist in items array.
*/
void insertBeforeItem(LLInventoryModel::item_array_t& items, const LLUUID& beforeItemId, const LLUUID& insertedItemId);
// finds an item by it's UUID in the items array
LLInventoryModel::item_array_t::iterator findItemByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id);
BOOL mSkipUpdate;
BOOL mStartDrag;
LLUUID mDragItemId;
LLInventoryModel::item_array_t mItems;
};
#endif // LL_LLFAVORITESBARCTRL_H

View File

@ -47,7 +47,6 @@
#include "llconsole.h"
#include "llfloateractivespeakers.h"
#include "llfloaterchatterbox.h"
#include "llfloatermute.h"
#include "llfloaterreg.h"
#include "llfloaterscriptdebug.h"
#include "llkeyboard.h"
@ -56,6 +55,7 @@
//#include "llresizehandle.h"
#include "llchatbar.h"
#include "llrecentpeople.h"
#include "llpanelblockedlist.h"
#include "llstatusbar.h"
#include "llviewertexteditor.h"
#include "llviewergesture.h" // for triggering gestures
@ -280,7 +280,7 @@ void LLFloaterChat::onClickMute(void *data)
LLMute mute(id);
mute.setFromDisplayName(name);
LLMuteList::getInstance()->add(mute);
LLFloaterReg::showInstance("mute");
LLPanelBlockedList::showPanelAndSelect(mute.mID);
}
//static

View File

@ -61,6 +61,7 @@
#include "llnavigationbar.h"
#include "llpanellogin.h"
#include "llradiogroup.h"
#include "llsearchcombobox.h"
#include "llsky.h"
#include "llscrolllistctrl.h"
#include "llscrolllistitem.h"
@ -214,6 +215,11 @@ bool callback_clear_browser_cache(const LLSD& notification, const LLSD& response
// flag client texture cache for clearing next time the client runs
gSavedSettings.setBOOL("PurgeCacheOnNextStartup", TRUE);
LLNotifications::instance().add("CacheWillClear");
LLSearchHistory::getInstance()->clearHistory();
LLSearchHistory::getInstance()->save();
LLSearchComboBox* search_ctrl = LLNavigationBar::getInstance()->getChild<LLSearchComboBox>("search_combo_box");
search_ctrl->clearHistory();
}
return false;

View File

@ -173,6 +173,15 @@ bool LLFriendCardsManager::isCategoryInFriendFolder(const LLViewerInventoryCateg
return TRUE == gInventory.isObjectDescendentOf(cat->getUUID(), findFriendFolderUUIDImpl());
}
bool LLFriendCardsManager::isAnyFriendCategory(const LLUUID& catID) const
{
const LLUUID& friendFolderID = findFriendFolderUUIDImpl();
if (catID == friendFolderID)
return true;
return TRUE == gInventory.isObjectDescendentOf(catID, friendFolderID);
}
void LLFriendCardsManager::syncFriendsFolder()
{
//lets create "Friends" and "Friends/All" in the Inventory "Calling Cards" if they are absent
@ -305,10 +314,12 @@ void LLFriendCardsManager::findMatchedFriendCards(const LLUUID& avatarID, LLInve
LLInventoryModel::cat_array_t cats;
LLUUID friendFolderUUID = findFriendFolderUUIDImpl();
LLParticularBuddyCollector matchFunctor(avatarID);
LLViewerInventoryCategory* friendFolder = gInventory.getCategory(friendFolderUUID);
if (NULL == friendFolder)
return;
LLParticularBuddyCollector matchFunctor(avatarID);
LLInventoryModel::cat_array_t subFolders;
subFolders.push_back(friendFolder);

View File

@ -76,6 +76,11 @@ public:
*/
bool isCategoryInFriendFolder(const LLViewerInventoryCategory* cat) const;
/**
* Checks is the specified category is a Friend folder or any its subfolder
*/
bool isAnyFriendCategory(const LLUUID& catID) const;
/**
* Synchronizes content of the Calling Card/Friends/All Global Inventory folder with Agent's Friend List
*/

View File

@ -2420,8 +2420,14 @@ BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop,
drop);
break;
case DAD_CATEGORY:
accept = dragCategoryIntoFolder((LLInventoryCategory*)cargo_data,
drop);
if (LLFriendCardsManager::instance().isAnyFriendCategory(mUUID))
{
accept = FALSE;
}
else
{
accept = dragCategoryIntoFolder((LLInventoryCategory*)cargo_data, drop);
}
break;
default:
break;

View File

@ -37,59 +37,41 @@
#include <iomanip> // for std::setw()
#include "llui.h"
const char LLLocationHistory::delimiter = '\t';
#include "llsd.h"
#include "llsdserialize.h"
LLLocationHistory::LLLocationHistory() :
mFilename("typed_locations.txt")
{
}
void LLLocationHistory::addItem(const std::string & item, const std::string & tooltip) {
void LLLocationHistory::addItem(const LLLocationHistoryItem& item) {
static LLUICachedControl<S32> max_items("LocationHistoryMaxSize", 100);
// check if this item doesn't duplicate any existing one
std::vector<std::string>::iterator item_iter = std::find_if(mItems.begin(), mItems.end(),
boost::bind(&LLLocationHistory::equalByRegionParcel,this,_1,item));
location_list_t::iterator item_iter = std::find(mItems.begin(), mItems.end(),item);
if(item_iter != mItems.end()){
/*replace duplicate.
* If an item's region and item's parcel are equal.
*/
mToolTips.erase(*item_iter);
mItems.erase(item_iter);
}
mItems.push_back(item);
mToolTips[item] = tooltip;
// If the vector size exceeds the maximum, purge the oldest items.
if ((S32)mItems.size() > max_items) {
for(std::vector<std::string>::iterator i = mItems.begin(); i != mItems.end()-max_items; ++i) {
mToolTips.erase(*i);
mItems.erase(i);
for(location_list_t::iterator i = mItems.begin(); i != mItems.end()-max_items; ++i) {
mItems.erase(i);
}
}
}
/**
* check if the history item is equal.
* @return true - if region name and parcel is equal.
/*
* @brief Try to find item in history.
* If item has been founded, it will be places into end of history.
* @return true - item has founded
*/
bool LLLocationHistory::equalByRegionParcel(const std::string& item, const std::string& newItem){
S32 itemIndex = item.find('(');
S32 newItemIndex = newItem.find('(');
std::string region_parcel = item.substr(0,itemIndex);
std::string new_region_parcel = newItem.substr(0,newItemIndex);
return region_parcel == new_region_parcel;
}
bool LLLocationHistory::touchItem(const std::string & item) {
bool LLLocationHistory::touchItem(const LLLocationHistoryItem& item) {
bool result = false;
std::vector<std::string>::iterator item_iter = std::find(mItems.begin(), mItems.end(), item);
location_list_t::iterator item_iter = std::find(mItems.begin(), mItems.end(), item);
// the last used item should be the first in the history
if (item_iter != mItems.end()) {
@ -104,13 +86,6 @@ bool LLLocationHistory::touchItem(const std::string & item) {
void LLLocationHistory::removeItems()
{
mItems.clear();
mToolTips.clear();
}
std::string LLLocationHistory::getToolTip(const std::string & item) const {
std::map<std::string, std::string>::const_iterator i = mToolTips.find(item);
return i != mToolTips.end() ? i->second : "";
}
bool LLLocationHistory::getMatchingItems(std::string substring, location_list_t& result) const
@ -123,7 +98,7 @@ bool LLLocationHistory::getMatchingItems(std::string substring, location_list_t&
for (location_list_t::const_iterator it = mItems.begin(); it != mItems.end(); ++it)
{
std::string haystack = *it;
std::string haystack = it->getLocation();
LLStringUtil::toLower(haystack);
if (haystack.find(needle) != std::string::npos)
@ -139,7 +114,7 @@ void LLLocationHistory::dump() const
int i = 0;
for (location_list_t::const_iterator it = mItems.begin(); it != mItems.end(); ++it, ++i)
{
llinfos << "#" << std::setw(2) << std::setfill('0') << i << ": " << *it << llendl;
llinfos << "#" << std::setw(2) << std::setfill('0') << i << ": " << it->getLocation() << llendl;
}
}
@ -158,11 +133,7 @@ void LLLocationHistory::save() const
for (location_list_t::const_iterator it = mItems.begin(); it != mItems.end(); ++it)
{
std::string tooltip = getToolTip(*it);
if(!tooltip.empty())
{
file << (*it) << delimiter << tooltip << std::endl;
}
file << LLSDOStreamer<LLSDNotationFormatter>((*it).toLLSD()) << std::endl;
}
file.close();
@ -186,16 +157,17 @@ void LLLocationHistory::load()
// add each line in the file to the list
std::string line;
LLPointer<LLSDParser> parser = new LLSDNotationParser();
while (std::getline(file, line)) {
size_t dp = line.find(delimiter);
if (dp != std::string::npos) {
const std::string reg_name = line.substr(0, dp);
const std::string tooltip = line.substr(dp + 1, std::string::npos);
addItem(reg_name, tooltip);
LLSD s_item;
std::istringstream iss(line);
if (parser->parse(iss, s_item, line.length()) == LLSDParser::PARSE_FAILURE)
{
llinfos<< "Parsing saved teleport history failed" << llendl;
break;
}
mItems.push_back(s_item);
}
file.close();

View File

@ -40,21 +40,84 @@
#include <map>
#include <boost/function.hpp>
class LLSD;
enum ELocationType {
TYPED_REGION_SURL//region name or surl
,LANDMARK // name of landmark
,TELEPORT_HISTORY
};
class LLLocationHistoryItem {
public:
LLLocationHistoryItem(){}
LLLocationHistoryItem(std::string typed_location,
LLVector3d global_position, std::string tooltip,ELocationType type ):
mLocation(typed_location),
mGlobalPos(global_position),
mToolTip(tooltip),
mType(type)
{}
LLLocationHistoryItem(const LLLocationHistoryItem& item):
mGlobalPos(item.mGlobalPos),
mToolTip(item.mToolTip),
mLocation(item.mLocation),
mType(item.mType)
{}
LLLocationHistoryItem(const LLSD& data):
mLocation(data["location"]),
mGlobalPos(data["global_pos"]),
mToolTip(data["tooltip"]),
mType(ELocationType(data["item_type"].asInteger()))
{}
bool operator==(const LLLocationHistoryItem& item)
{
// do not compare mGlobalPos,
// because of a rounding off , the history can contain duplicates
return mLocation == item.mLocation && (mType == item.mType);
}
bool operator!=(const LLLocationHistoryItem& item)
{
return ! (*this == item);
}
LLSD toLLSD() const
{
LLSD val;
val["location"]= mLocation;
val["global_pos"] = mGlobalPos.getValue();
val["tooltip"] = mToolTip;
val["item_type"] = mType;
return val;
}
const std::string& getLocation() const { return mLocation; };
const std::string& getToolTip() const { return mToolTip; };
//static bool equalByRegionParcel(const LLLocationHistoryItem& item1, const LLLocationHistoryItem& item2);
static bool equalByLocation(const LLLocationHistoryItem& item1, const std::string& item_location)
{
return item1.getLocation() == item_location;
}
LLVector3d mGlobalPos; // global position
std::string mToolTip;// SURL
std::string mLocation;// typed_location
ELocationType mType;
};
class LLLocationHistory: public LLSingleton<LLLocationHistory>
{
LOG_CLASS(LLLocationHistory);
public:
typedef std::vector<std::string> location_list_t;
typedef std::vector<LLLocationHistoryItem> location_list_t;
typedef boost::function<void()> loaded_callback_t;
typedef boost::signals2::signal<void()> loaded_signal_t;
LLLocationHistory();
void addItem(const std::string & item, const std::string & tooltip);
bool touchItem(const std::string & item);
void addItem(const LLLocationHistoryItem& item);
bool touchItem(const LLLocationHistoryItem& item);
void removeItems();
std::string getToolTip(const std::string & item) const;
size_t getItemCount() const { return mItems.size(); }
const location_list_t& getItems() const { return mItems; }
bool getMatchingItems(std::string substring, location_list_t& result) const;
@ -65,10 +128,8 @@ public:
void dump() const;
private:
bool equalByRegionParcel(const std::string& item, const std::string& item_to_add);
const static char delimiter;
std::vector<std::string> mItems;
std::map<std::string, std::string> mToolTips;
location_list_t mItems;
std::string mFilename; /// File to store the history to.
loaded_signal_t mLoadedSignal;
};

View File

@ -48,6 +48,7 @@
#include "lllandmarkactions.h"
#include "lllandmarklist.h"
#include "lllocationhistory.h"
#include "llteleporthistory.h"
#include "llsidetray.h"
#include "llslurl.h"
#include "lltrans.h"
@ -295,11 +296,19 @@ BOOL LLLocationInputCtrl::handleToolTip(S32 x, S32 y, std::string& msg, LLRect*
if (LLUICtrl::handleToolTip(x, y, msg, sticky_rect_screen) && !msg.empty())
{
if (mList->getRect().pointInRect(x, y)) {
LLLocationHistory* lh = LLLocationHistory::getInstance();
const std::string tooltip = lh->getToolTip(msg);
if (!tooltip.empty()) {
msg = tooltip;
S32 loc_x, loc_y;
//x,y - contain coordinates related to the location input control, but without taking the expanded list into account
//So we have to convert it again into local coordinates of mList
localPointToOtherView(x,y,&loc_x,&loc_y,mList);
LLScrollListItem* item = mList->hitItem(loc_x,loc_y);
if (item)
{
LLSD value = item->getValue();
if (value.has("tooltip"))
{
msg = value["tooltip"].asString();
}
}
}
@ -448,18 +457,58 @@ void LLLocationInputCtrl::onLocationPrearrange(const LLSD& data)
rebuildLocationHistory(filter);
//Let's add landmarks to the top of the list if any
if( filter.size() !=0 )
if(!filter.empty() )
{
LLInventoryModel::item_array_t landmark_items = LLLandmarkActions::fetchLandmarksByName(filter, TRUE);
for(U32 i=0; i < landmark_items.size(); i++)
{
mList->addSimpleElement(landmark_items[i]->getName(), ADD_TOP);
LLSD value;
//TODO:: DO we need tooltip for Landmark??
value["item_type"] = LANDMARK;
value["AssetUUID"] = landmark_items[i]->getAssetUUID();
add(landmark_items[i]->getName(), value);
}
//Let's add teleport history items
LLTeleportHistory* th = LLTeleportHistory::getInstance();
LLTeleportHistory::slurl_list_t th_items = th->getItems();
std::set<std::string> new_item_titles;// duplicate control
LLTeleportHistory::slurl_list_t::iterator result = std::find_if(
th_items.begin(), th_items.end(), boost::bind(
&LLLocationInputCtrl::findTeleportItemsByTitle, this,
_1, filter));
while (result != th_items.end())
{
//mTitile format - region_name[, parcel_name]
//mFullTitile format - region_name[, parcel_name] (local_x,local_y, local_z)
if (new_item_titles.insert(result->mFullTitle).second)
{
LLSD value;
value["item_type"] = TELEPORT_HISTORY;
value["global_pos"] = result->mGlobalPos.getValue();
std::string region_name = result->mTitle.substr(0, result->mTitle.find(','));
//TODO*: add Surl to teleportitem or parse region name from title
value["tooltip"] = LLSLURL::buildSLURLfromPosGlobal(region_name,
result->mGlobalPos, false);
add(result->getTitle(), value);
}
result = std::find_if(result + 1, th_items.end(), boost::bind(
&LLLocationInputCtrl::findTeleportItemsByTitle, this,
_1, filter));
}
}
sortByName();
mList->mouseOverHighlightNthItem(-1); // Clear highlight on the last selected item.
}
bool LLLocationInputCtrl::findTeleportItemsByTitle(const LLTeleportHistoryItem& item, const std::string& filter)
{
return item.mTitle.find(filter) != std::string::npos;
}
void LLLocationInputCtrl::onTextEditorRightClicked(S32 x, S32 y, MASK mask)
{
if (mLocationContextMenu)
@ -519,7 +568,12 @@ void LLLocationInputCtrl::rebuildLocationHistory(std::string filter)
removeall();
for (LLLocationHistory::location_list_t::const_reverse_iterator it = itemsp->rbegin(); it != itemsp->rend(); it++)
{
add(*it);
LLSD value;
value["tooltip"] = it->getToolTip();
//location history can contain only typed locations
value["item_type"] = TYPED_REGION_SURL;
value["global_pos"] = it->mGlobalPos.getValue();
add(it->getLocation(), value);
}
}

View File

@ -41,6 +41,7 @@ class LLLandmark;
class LLAddLandmarkObserver;
class LLRemoveLandmarkObserver;
class LLMenuGL;
class LLTeleportHistoryItem;
/**
* Location input control.
@ -103,6 +104,7 @@ private:
void refresh();
void refreshLocation();
void rebuildLocationHistory(std::string filter = "");
bool findTeleportItemsByTitle(const LLTeleportHistoryItem& item, const std::string& filter);
void setText(const LLStringExplicit& text);
void updateAddLandmarkButton();
void updateContextMenu();

View File

@ -45,7 +45,7 @@
#include "lllocationhistory.h"
#include "lllocationinputctrl.h"
#include "llteleporthistory.h"
#include "llsearcheditor.h"
#include "llsearchcombobox.h"
#include "llsidetray.h"
#include "llslurl.h"
#include "llurlsimstring.h"
@ -82,7 +82,6 @@ public:
Mandatory<EType> item_type;
Params() {}
Params(EType type, std::string title);
};
/*virtual*/ void draw();
@ -104,24 +103,21 @@ private:
const std::string LLTeleportHistoryMenuItem::ICON_IMG_BACKWARD("teleport_history_backward.tga");
const std::string LLTeleportHistoryMenuItem::ICON_IMG_FORWARD("teleport_history_forward.tga");
LLTeleportHistoryMenuItem::Params::Params(EType type, std::string title)
{
item_type(type);
font.name("SANSSERIF");
if (type == TYPE_CURRENT)
font.style("BOLD");
else
title = " " + title;
name(title);
label(title);
}
LLTeleportHistoryMenuItem::LLTeleportHistoryMenuItem(const Params& p)
: LLMenuItemCallGL(p),
mArrowIcon(NULL)
{
// Set appearance depending on the item type.
if (p.item_type == TYPE_CURRENT)
{
setFont(LLFontGL::getFontSansSerifBold());
}
else
{
setFont(LLFontGL::getFontSansSerif());
setLabel(std::string(" ") + std::string(p.label));
}
LLIconCtrl::Params icon_params;
icon_params.name("icon");
icon_params.rect(LLRect(0, ICON_HEIGHT, ICON_WIDTH, 0));
@ -183,14 +179,11 @@ LLNavigationBar::LLNavigationBar()
mBtnForward(NULL),
mBtnHome(NULL),
mCmbLocation(NULL),
mLeSearch(NULL),
mSearchComboBox(NULL),
mPurgeTPHistoryItems(false)
{
setIsChrome(TRUE);
mParcelMgrConnection = LLViewerParcelMgr::getInstance()->setTeleportFinishedCallback(
boost::bind(&LLNavigationBar::onTeleportFinished, this, _1));
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_navigation_bar.xml");
// set a listener function for LoginComplete event
@ -202,8 +195,10 @@ LLNavigationBar::LLNavigationBar()
LLNavigationBar::~LLNavigationBar()
{
mParcelMgrConnection.disconnect();
mTeleportFinishConnection.disconnect();
sInstance = 0;
LLSearchHistory::getInstance()->save();
}
BOOL LLNavigationBar::postBuild()
@ -213,10 +208,12 @@ BOOL LLNavigationBar::postBuild()
mBtnHome = getChild<LLButton>("home_btn");
mCmbLocation= getChild<LLLocationInputCtrl>("location_combo");
mLeSearch = getChild<LLSearchEditor>("search_input");
mSearchComboBox = getChild<LLSearchComboBox>("search_combo_box");
fillSearchComboBox();
if (!mBtnBack || !mBtnForward || !mBtnHome ||
!mCmbLocation || !mLeSearch)
!mCmbLocation || !mSearchComboBox)
{
llwarns << "Malformed navigation bar" << llendl;
return FALSE;
@ -234,7 +231,7 @@ BOOL LLNavigationBar::postBuild()
mCmbLocation->setSelectionCallback(boost::bind(&LLNavigationBar::onLocationSelection, this));
mLeSearch->setCommitCallback(boost::bind(&LLNavigationBar::onSearchCommit, this));
mSearchComboBox->setCommitCallback(boost::bind(&LLNavigationBar::onSearchCommit, this));
mDefaultNbRect = getRect();
mDefaultFpRect = getChild<LLFavoritesBarCtrl>("favorite")->getRect();
@ -246,6 +243,25 @@ BOOL LLNavigationBar::postBuild()
return TRUE;
}
void LLNavigationBar::fillSearchComboBox()
{
if(!mSearchComboBox)
{
return;
}
LLSearchHistory::getInstance()->load();
LLSearchHistory::search_history_list_t search_list =
LLSearchHistory::getInstance()->getSearchHistoryList();
LLSearchHistory::search_history_list_t::const_iterator it = search_list.begin();
for( ; search_list.end() != it; ++it)
{
LLSearchHistory::LLSearchHistoryItem item = *it;
mSearchComboBox->add(item.search_query);
}
}
void LLNavigationBar::draw()
{
if(mPurgeTPHistoryItems)
@ -280,7 +296,12 @@ void LLNavigationBar::onHomeButtonClicked()
void LLNavigationBar::onSearchCommit()
{
invokeSearch(mLeSearch->getValue().asString());
std::string search_query = mSearchComboBox->getValue().asString();
if(!search_query.empty())
{
LLSearchHistory::getInstance()->addEntry(search_query);
invokeSearch(mSearchComboBox->getValue().asString());
}
}
void LLNavigationBar::onTeleportHistoryMenuItemClicked(const LLSD& userdata)
@ -299,69 +320,107 @@ void LLNavigationBar::onLocationSelection()
if (typed_location.empty())
return;
LLSD value = mCmbLocation->getSelectedValue();
if(value.has("item_type"))
{
switch(value["item_type"].asInteger())
{
case LANDMARK:
if(value.has("AssetUUID"))
{
gAgent.teleportViaLandmark( LLUUID(value["AssetUUID"].asString()));
return;
}
else
{
LLInventoryModel::item_array_t landmark_items =
LLLandmarkActions::fetchLandmarksByName(typed_location,
FALSE);
if (!landmark_items.empty())
{
gAgent.teleportViaLandmark( landmark_items[0]->getAssetUUID());
return;
}
}
break;
case TELEPORT_HISTORY:
//in case of teleport item was selected, teleport by position too.
case TYPED_REGION_SURL:
if(value.has("global_pos"))
{
gAgent.teleportViaLocation(LLVector3d(value["global_pos"]));
return;
}
break;
default:
break;
}
}
//Let's parse surl or region name
std::string region_name;
LLVector3 local_coords(128, 128, 0);
S32 x = 0, y = 0, z = 0;
// Is the typed location a SLURL?
if (LLSLURL::isSLURL(typed_location))
{
// Yes. Extract region name and local coordinates from it.
if (LLURLSimString::parse(LLSLURL::stripProtocol(typed_location), &region_name, &x, &y, &z))
local_coords.set(x, y, z);
local_coords.set(x, y, z);
else
return;
}
else
}else
{
//If it is not slurl let's look for landmarks
LLInventoryModel::item_array_t landmark_items = LLLandmarkActions::fetchLandmarksByName(typed_location, FALSE);
if ( !landmark_items.empty() )
{
gAgent.teleportViaLandmark(landmark_items[0]->getAssetUUID());
return;
}
//No landmark match, check if it is a region name
region_name = parseLocation(typed_location, &x, &y, &z);
if (region_name != typed_location)
local_coords.set(x, y, z);
// Treat it as region name.
// region_name = typed_location;
// assume that an user has typed the {region name} or possible {region_name, parcel}
region_name = typed_location.substr(0,typed_location.find(','));
}
// Resolve the region name to its global coordinates.
// If resolution succeeds we'll teleport.
LLWorldMap::url_callback_t cb = boost::bind(
&LLNavigationBar::onRegionNameResponse, this,
typed_location, region_name, local_coords, _1, _2, _3, _4);
// connect the callback each time, when user enter new location to get real location of agent after teleport
mTeleportFinishConnection = LLViewerParcelMgr::getInstance()->
setTeleportFinishedCallback(boost::bind(&LLNavigationBar::onTeleportFinished, this, _1,typed_location));
LLWorldMap::getInstance()->sendNamedRegionRequest(region_name, cb, std::string("unused"), false);
}
void LLNavigationBar::onTeleportFinished(const LLVector3d& global_agent_pos)
void LLNavigationBar::onTeleportFinished(const LLVector3d& global_agent_pos, const std::string& typed_location)
{
// Location is valid. Add it to the typed locations history.
LLLocationHistory* lh = LLLocationHistory::getInstance();
//TODO*: do we need convert surl into readable format?
std::string location;
/*NOTE:
* We can't use gAgent.getPositionAgent() in case of local teleport to build location.
* At this moment gAgent.getPositionAgent() contains previous coordinates.
* according to EXT-65 agent position is being reseted on each frame.
*/
LLAgentUI::buildLocationString(location, LLAgentUI::LOCATION_FORMAT_WITHOUT_SIM,
gAgent.getPosAgentFromGlobal(global_agent_pos));
LLAgentUI::buildLocationString(location, LLAgentUI::LOCATION_FORMAT_WITHOUT_SIM,
gAgent.getPosAgentFromGlobal(global_agent_pos));
std::string tooltip (LLSLURL::buildSLURLfromPosGlobal(gAgent.getRegion()->getName(), global_agent_pos, false));
LLLocationHistoryItem item (location,
global_agent_pos, tooltip,TYPED_REGION_SURL);// we can add into history only TYPED location
//Touch it, if it is at list already, add new location otherwise
if ( !lh->touchItem(location) ) {
std::string tooltip = LLSLURL::buildSLURLfromPosGlobal(
gAgent.getRegion()->getName(), global_agent_pos, false);
lh->addItem(location, tooltip);
if ( !lh->touchItem(item) ) {
lh->addItem(item);
}
llinfos << "Saving after on teleport finish" << llendl;
lh->save();
lh->save();
if(mTeleportFinishConnection.connected())
mTeleportFinishConnection.disconnect();
}
void LLNavigationBar::onTeleportHistoryChanged()
@ -411,7 +470,9 @@ void LLNavigationBar::rebuildTeleportHistoryMenu()
else
type = LLTeleportHistoryMenuItem::TYPE_CURRENT;
LLTeleportHistoryMenuItem::Params item_params(type, hist_items[i].getTitle());
LLTeleportHistoryMenuItem::Params item_params;
item_params.label = item_params.name = hist_items[i].getTitle();
item_params.item_type = type;
item_params.on_click.function(boost::bind(&LLNavigationBar::onTeleportHistoryMenuItemClicked, this, i));
LLTeleportHistoryMenuItem* new_itemp = LLUICtrlFactory::create<LLTeleportHistoryMenuItem>(item_params);
//new_itemp->setFont()
@ -435,8 +496,8 @@ void LLNavigationBar::onRegionNameResponse(
// Teleport to the location.
LLVector3d region_pos = from_region_handle(region_handle);
LLVector3d global_pos = region_pos + (LLVector3d) local_coords;
llinfos << "Teleporting to: " << global_pos << llendl;
llinfos << "Teleporting to: " << LLSLURL::buildSLURLfromPosGlobal(region_name, global_pos, false) << llendl;
gAgent.teleportViaLocation(global_pos);
}
@ -474,35 +535,6 @@ void LLNavigationBar::invokeSearch(std::string search_text)
LLFloaterReg::showInstance("search", LLSD().insert("panel", "all").insert("id", LLSD(search_text)));
}
std::string LLNavigationBar::parseLocation(const std::string & location, S32* x, S32* y, S32* z) {
/*
* This regular expression extracts numbers from the following string
* construct: "(num1, num2, num3)", where num1, num2 and num3 are decimal
* numbers. Leading and trailing spaces are also caught by the expression.
*/
const boost::regex re("\\s*\\((\\d+),\\s*(\\d+),\\s*(\\d+)\\)\\s*");
boost::smatch m;
if (boost::regex_search(location, m, re)) {
// string representations of parsed by regex++ numbers
std::string xstr(m[1].first, m[1].second);
std::string ystr(m[2].first, m[2].second);
std::string zstr(m[3].first, m[3].second);
*x = atoi(xstr.c_str());
*y = atoi(ystr.c_str());
*z = atoi(zstr.c_str());
//erase commas in coordinates
std::string region_parcel = boost::regex_replace(location, re, "");
// cut region name
return region_parcel.substr(0, region_parcel.find_first_of(','));
}
*x = *y = *z = 0;
return location;
}
void LLNavigationBar::clearHistoryCache()
{
mCmbLocation->removeall();

View File

@ -41,6 +41,7 @@ class LLButton;
class LLLocationInputCtrl;
class LLMenuGL;
class LLSearchEditor;
class LLSearchComboBox;
/**
* Web browser-like navigation bar.
@ -69,12 +70,6 @@ private:
void rebuildTeleportHistoryMenu();
void showTeleportHistoryMenu();
void invokeSearch(std::string search_text);
/**
* Get region name and local coordinates from typed location
*/
static std::string parseLocation(const std::string & location, S32* x, S32* y, S32* z);
// callbacks
void onTeleportHistoryMenuItemClicked(const LLSD& userdata);
void onTeleportHistoryChanged();
@ -86,7 +81,7 @@ private:
void onLocationSelection();
void onLocationPrearrange(const LLSD& data);
void onSearchCommit();
void onTeleportFinished(const LLVector3d& global_agent_pos);
void onTeleportFinished(const LLVector3d& global_agent_pos, const std::string& typed_location);
void onRegionNameResponse(
std::string typed_location,
std::string region_name,
@ -94,17 +89,19 @@ private:
U64 region_handle, const std::string& url,
const LLUUID& snapshot_id, bool teleport);
void fillSearchComboBox();
static LLNavigationBar *sInstance;
LLMenuGL* mTeleportHistoryMenu;
LLButton* mBtnBack;
LLButton* mBtnForward;
LLButton* mBtnHome;
LLSearchEditor* mLeSearch;
LLSearchComboBox* mSearchComboBox;
LLLocationInputCtrl* mCmbLocation;
LLRect mDefaultNbRect;
LLRect mDefaultFpRect;
boost::signals2::connection mParcelMgrConnection;
boost::signals2::connection mTeleportFinishConnection;
bool mPurgeTPHistoryItems;
};

View File

@ -372,7 +372,6 @@ void LLPanelAvatarProfile::resetControls()
childSetVisible("status_me_panel", false);
childSetVisible("profile_me_buttons_panel", false);
childSetVisible("account_actions_panel", false);
childSetVisible("partner_edit_link", false);
}
void LLPanelAvatarProfile::resetData()
@ -539,7 +538,7 @@ void LLPanelAvatarProfile::fillAccountStatus(const LLAvatarData* avatar_data)
childSetValue("acc_status_text", caption_text);
}
void LLPanelAvatarProfile::onUrlTextboxClicked(std::string url)
void LLPanelAvatarProfile::onUrlTextboxClicked(const std::string& url)
{
LLWeb::loadURL(url);
}
@ -675,4 +674,3 @@ void LLPanelAvatarMeProfile::onStatusMessageChanged()
{
updateData();
}

View File

@ -166,7 +166,7 @@ protected:
*/
virtual void fillAccountStatus(const LLAvatarData* avatar_data);
void onUrlTextboxClicked(std::string url);
void onUrlTextboxClicked(const std::string& url);
void onHomepageTextboxClicked();
void onAddFriendButtonClick();
void onIMButtonClick();

View File

@ -0,0 +1,279 @@
/**
* @file llpanelblockedlist.cpp
* @brief Container for blocked Residents & Objects list
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
* Copyright (c) 2001-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llfloater.h"
#include "llfloaterreg.h"
#include "llscrolllistctrl.h"
#include "llpanelblockedlist.h"
// project include
#include "llfloateravatarpicker.h"
#include "llsidetray.h"
#include "llsidetraypanelcontainer.h"
static LLRegisterPanelClassWrapper<LLPanelBlockedList> t_panel_blocked_list("panel_block_list_sidetray");
//
// Constants
//
const std::string BLOCKED_PARAM_NAME = "blocked_to_select";
//-----------------------------------------------------------------------------
// LLPanelBlockedList()
//-----------------------------------------------------------------------------
LLPanelBlockedList::LLPanelBlockedList()
: LLPanel()
{
mCommitCallbackRegistrar.add("Block.ClickPick", boost::bind(&LLPanelBlockedList::onPickBtnClick, this));
mCommitCallbackRegistrar.add("Block.ClickBlockByName", boost::bind(&LLPanelBlockedList::onBlockByNameClick, this));
mCommitCallbackRegistrar.add("Block.ClickRemove", boost::bind(&LLPanelBlockedList::onRemoveBtnClick, this));
}
LLPanelBlockedList::~LLPanelBlockedList()
{
LLMuteList::getInstance()->removeObserver(this);
}
BOOL LLPanelBlockedList::postBuild()
{
mBlockedList = getChild<LLScrollListCtrl>("blocked");
mBlockedList->setCommitOnSelectionChange(TRUE);
childSetCommitCallback("back", boost::bind(&LLPanelBlockedList::onBackBtnClick, this), NULL);
LLMuteList::getInstance()->addObserver(this);
refreshBlockedList();
return LLPanel::postBuild();
}
void LLPanelBlockedList::draw()
{
updateButtons();
LLPanel::draw();
}
void LLPanelBlockedList::onOpen(const LLSD& key)
{
if (key.has(BLOCKED_PARAM_NAME) && key[BLOCKED_PARAM_NAME].asUUID().notNull())
{
selectBlocked(key[BLOCKED_PARAM_NAME].asUUID());
}
}
void LLPanelBlockedList::selectBlocked(const LLUUID& mute_id)
{
mBlockedList->selectByID(mute_id);
}
void LLPanelBlockedList::showPanelAndSelect(const LLUUID& idToSelect)
{
LLSideTray::getInstance()->showPanel("panel_block_list_sidetray", LLSD().insert(BLOCKED_PARAM_NAME, idToSelect));
}
//////////////////////////////////////////////////////////////////////////
// Private Section
//////////////////////////////////////////////////////////////////////////
void LLPanelBlockedList::refreshBlockedList()
{
mBlockedList->deleteAllItems();
std::vector<LLMute> mutes = LLMuteList::getInstance()->getMutes();
std::vector<LLMute>::iterator it;
for (it = mutes.begin(); it != mutes.end(); ++it)
{
std::string display_name = it->getDisplayName();
mBlockedList->addStringUUIDItem(display_name, it->mID, ADD_BOTTOM, TRUE);
}
}
void LLPanelBlockedList::updateButtons()
{
bool hasSelected = NULL != mBlockedList->getFirstSelected();
childSetEnabled("Unblock", hasSelected);
}
void LLPanelBlockedList::onBackBtnClick()
{
LLSideTrayPanelContainer* parent = dynamic_cast<LLSideTrayPanelContainer*>(getParent());
if(parent)
{
parent->openPreviousPanel();
}
}
void LLPanelBlockedList::onRemoveBtnClick()
{
std::string name = mBlockedList->getSelectedItemLabel();
LLUUID id = mBlockedList->getStringUUIDSelectedItem();
LLMute mute(id);
mute.setFromDisplayName(name);
// now mute.mName has the suffix trimmed off
S32 last_selected = mBlockedList->getFirstSelectedIndex();
if (LLMuteList::getInstance()->remove(mute))
{
// Above removals may rebuild this dialog.
if (last_selected == mBlockedList->getItemCount())
{
// we were on the last item, so select the last item again
mBlockedList->selectNthItem(last_selected - 1);
}
else
{
// else select the item after the last item previously selected
mBlockedList->selectNthItem(last_selected);
}
}
}
void LLPanelBlockedList::onPickBtnClick()
{
const BOOL allow_multiple = FALSE;
const BOOL close_on_select = TRUE;
/*LLFloaterAvatarPicker* picker = */LLFloaterAvatarPicker::show(callbackBlockPicked, this, allow_multiple, close_on_select);
// *TODO: mantipov: should LLFloaterAvatarPicker be closed when panel is closed?
// old Floater dependency is not enable in panel
// addDependentFloater(picker);
}
void LLPanelBlockedList::onBlockByNameClick()
{
LLFloaterGetBlockedObjectName::show(&LLPanelBlockedList::callbackBlockByName);
}
//static
void LLPanelBlockedList::callbackBlockPicked(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* user_data)
{
if (names.empty() || ids.empty()) return;
LLMute mute(ids[0], names[0], LLMute::AGENT);
LLMuteList::getInstance()->add(mute);
showPanelAndSelect(mute.mID);
}
//static
void LLPanelBlockedList::callbackBlockByName(const std::string& text)
{
if (text.empty()) return;
LLMute mute(LLUUID::null, text, LLMute::BY_NAME);
BOOL success = LLMuteList::getInstance()->add(mute);
if (!success)
{
LLNotifications::instance().add("MuteByNameFailed");
}
}
//////////////////////////////////////////////////////////////////////////
// LLFloaterGetBlockedObjectName
//////////////////////////////////////////////////////////////////////////
// Constructor/Destructor
LLFloaterGetBlockedObjectName::LLFloaterGetBlockedObjectName(const LLSD& key)
: LLFloater(key)
, mGetObjectNameCallback(NULL)
{
}
// Destroys the object
LLFloaterGetBlockedObjectName::~LLFloaterGetBlockedObjectName()
{
gFocusMgr.releaseFocusIfNeeded( this );
}
BOOL LLFloaterGetBlockedObjectName::postBuild()
{
getChild<LLButton>("OK")-> setCommitCallback(boost::bind(&LLFloaterGetBlockedObjectName::applyBlocking, this));
getChild<LLButton>("Cancel")-> setCommitCallback(boost::bind(&LLFloaterGetBlockedObjectName::cancelBlocking, this));
center();
return LLFloater::postBuild();
}
BOOL LLFloaterGetBlockedObjectName::handleKeyHere(KEY key, MASK mask)
{
if (key == KEY_RETURN && mask == MASK_NONE)
{
applyBlocking();
return TRUE;
}
else if (key == KEY_ESCAPE && mask == MASK_NONE)
{
cancelBlocking();
return TRUE;
}
return LLFloater::handleKeyHere(key, mask);
}
// static
LLFloaterGetBlockedObjectName* LLFloaterGetBlockedObjectName::show(get_object_name_callback_t callback)
{
LLFloaterGetBlockedObjectName* floater = LLFloaterReg::showTypedInstance<LLFloaterGetBlockedObjectName>("mute_object_by_name");
floater->mGetObjectNameCallback = callback;
// *TODO: mantipov: should LLFloaterGetBlockedObjectName be closed when panel is closed?
// old Floater dependency is not enable in panel
// addDependentFloater(floater);
return floater;
}
//////////////////////////////////////////////////////////////////////////
// Private Section
void LLFloaterGetBlockedObjectName::applyBlocking()
{
if (mGetObjectNameCallback)
{
const std::string& text = childGetValue("object_name").asString();
mGetObjectNameCallback(text);
}
closeFloater();
}
void LLFloaterGetBlockedObjectName::cancelBlocking()
{
closeFloater();
}
//EOF

View File

@ -0,0 +1,115 @@
/**
* @file llpanelblockedlist.h
* @brief Container for blocked Residents & Objects list
*
* $LicenseInfo:firstyear=2002&license=viewergpl$
*
* Copyright (c) 2002-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LL_LLPANELBLOCKEDLIST_H
#define LL_LLPANELBLOCKEDLIST_H
#include "llpanel.h"
#include "llmutelist.h"
// #include <vector>
// class LLButton;
// class LLLineEditor;
// class LLMessageSystem;
// class LLUUID;
class LLScrollListCtrl;
class LLPanelBlockedList
: public LLPanel, public LLMuteListObserver
{
public:
LLPanelBlockedList();
~LLPanelBlockedList();
virtual BOOL postBuild();
virtual void draw();
virtual void onOpen(const LLSD& key);
void selectBlocked(const LLUUID& id);
/**
* Shows current Panel in side tray and select passed blocked item.
*
* @param idToSelect - LLUUID of blocked Resident or Object to be selected.
* If it is LLUUID::null, nothing will be selected.
*/
static void showPanelAndSelect(const LLUUID& idToSelect);
// LLMuteListObserver callback interface implementation.
/* virtual */ void onChange() { refreshBlockedList();}
private:
void refreshBlockedList();
void updateButtons();
// UI callbacks
void onBackBtnClick();
void onRemoveBtnClick();
void onPickBtnClick();
void onBlockByNameClick();
static void callbackBlockPicked(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* user_data);
static void callbackBlockByName(const std::string& text);
private:
LLScrollListCtrl* mBlockedList;
};
//-----------------------------------------------------------------------------
// LLFloaterGetBlockedObjectName()
//-----------------------------------------------------------------------------
// Class for handling mute object by name floater.
class LLFloaterGetBlockedObjectName : public LLFloater
{
friend class LLFloaterReg;
public:
typedef boost::function<void (const std::string&)> get_object_name_callback_t;
virtual BOOL postBuild();
virtual BOOL handleKeyHere(KEY key, MASK mask);
static LLFloaterGetBlockedObjectName* show(get_object_name_callback_t callback);
private:
LLFloaterGetBlockedObjectName(const LLSD& key);
virtual ~LLFloaterGetBlockedObjectName();
// UI Callbacks
void applyBlocking();
void cancelBlocking();
get_object_name_callback_t mGetObjectNameCallback;
};
#endif // LL_LLPANELBLOCKEDLIST_H

View File

@ -43,12 +43,12 @@
// newview
#include "llagent.h"
#include "llavataractions.h"
#include "llavatarlist.h"
#include "llcallingcard.h" // for LLAvatarTracker
#include "llfloateravatarpicker.h"
//#include "llfloaterminiinspector.h"
#include "llfriendcard.h"
#include "llavataractions.h"
#include "llgroupactions.h"
#include "llgrouplist.h"
#include "llrecentpeople.h"
@ -976,7 +976,6 @@ void LLPanelPeople::onRecentViewSortMenuItemClicked(const LLSD& userdata)
}
}
void LLPanelPeople::onCallButtonClicked()
{
// *TODO: not implemented yet

View File

@ -54,6 +54,11 @@ static const std::string XML_BTN_INFO = "info_btn";
static const std::string XML_BTN_TELEPORT = "teleport_btn";
static const std::string XML_BTN_SHOW_ON_MAP = "show_on_map_btn";
static const std::string PICK_ID("pick_id");
static const std::string PICK_CREATOR_ID("pick_creator_id");
static const std::string PICK_NAME("pick_name");
static LLRegisterPanelClassWrapper<LLPanelPicks> t_panel_picks("panel_picks");
//-----------------------------------------------------------------------------
@ -97,19 +102,8 @@ void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type)
gCacheName->getName(getAvatarId(),name,second_name);
childSetTextArg("pick_title", "[NAME]",name);
// to restore selection of the same item later
LLUUID pick_id_selected(LLUUID::null);
if (getSelectedPickItem()) pick_id_selected = getSelectedPickItem()->getPickId();
mPicksList->clear();
//*TODO move it somewhere else?
childSetEnabled(XML_BTN_NEW, false);
childSetEnabled(XML_BTN_DELETE, false);
childSetEnabled(XML_BTN_INFO, false);
childSetEnabled(XML_BTN_TELEPORT,!avatar_picks->picks_list.empty());
childSetEnabled(XML_BTN_SHOW_ON_MAP,!avatar_picks->picks_list.empty());
LLAvatarPicks::picks_list_t::const_iterator it = avatar_picks->picks_list.begin();
for(; avatar_picks->picks_list.end() != it; ++it)
{
@ -124,12 +118,18 @@ void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type)
LLAvatarPropertiesProcessor::instance().addObserver(getAvatarId(), picture);
picture->update();
mPicksList->addItem(picture);
if (pick_id_selected != LLUUID::null &&
pick_id == pick_id_selected) mPicksList->toggleSelection(picture);
LLSD pick_value = LLSD();
pick_value.insert(PICK_ID, pick_id);
pick_value.insert(PICK_NAME, pick_name);
pick_value.insert(PICK_CREATOR_ID, getAvatarId());
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->setMouseUpCallback(boost::bind(&LLPanelPicks::updateButtons, this));
}
LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(),this);
@ -140,10 +140,10 @@ void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type)
LLPickItem* LLPanelPicks::getSelectedPickItem()
{
std::list<LLPanel*> selected_items = mPicksList->getSelectedItems();
LLPanel* selected_item = mPicksList->getSelectedItem();
if (!selected_item) return NULL;
if (selected_items.empty()) return NULL;
return dynamic_cast<LLPickItem*>(selected_items.front());
return dynamic_cast<LLPickItem*>(selected_item);
}
BOOL LLPanelPicks::postBuild()
@ -193,6 +193,10 @@ void LLPanelPicks::onOpen(const LLSD& key)
{
childSetVisible("pick_title", !self);
childSetVisible("pick_title_agent", self);
mPopupMenu->setItemVisible("pick_delete", TRUE);
mPopupMenu->setItemVisible("pick_edit", TRUE);
mPopupMenu->setItemVisible("pick_separator", TRUE);
}
LLPanelProfileTab::onOpen(key);
@ -201,11 +205,11 @@ void LLPanelPicks::onOpen(const LLSD& key)
//static
void LLPanelPicks::onClickDelete()
{
LLPickItem* pick_item = getSelectedPickItem();
if (!pick_item) return;
LLSD pick_value = mPicksList->getSelectedValue();
if (pick_value.isUndefined()) return;
LLSD args;
args["PICK"] = pick_item->getPickName();
args["PICK"] = pick_value[PICK_NAME];
LLNotifications::instance().add("DeleteAvatarPick", args, LLSD(), boost::bind(&LLPanelPicks::callbackDelete, this, _1, _2));
}
@ -213,12 +217,12 @@ bool LLPanelPicks::callbackDelete(const LLSD& notification, const LLSD& response
{
S32 option = LLNotification::getSelectedOption(notification, response);
LLPickItem* pick_item = getSelectedPickItem();
LLSD pick_value = mPicksList->getSelectedValue();
if (0 == option)
{
LLAvatarPropertiesProcessor::instance().sendPickDelete(pick_item->getPickId());
mPicksList->removeItem(pick_item);
LLAvatarPropertiesProcessor::instance().sendPickDelete(pick_value[PICK_ID]);
mPicksList->removeItemByValue(pick_value);
}
updateButtons();
return false;
@ -265,32 +269,30 @@ void LLPanelPicks::onRightMouseDownItem(LLUICtrl* item, S32 x, S32 y, MASK mask)
void LLPanelPicks::onDoubleClickItem(LLUICtrl* item)
{
LLPickItem* pick_item = dynamic_cast<LLPickItem*>(item);
if (!pick_item) return;
LLSD pick_value = mPicksList->getSelectedValue();
if (pick_value.isUndefined()) return;
LLSD args;
args["PICK"] = pick_item->getPickName();
args["PICK"] = pick_value[PICK_NAME];
LLNotifications::instance().add("TeleportToPick", args, LLSD(), boost::bind(&LLPanelPicks::callbackTeleport, this, _1, _2));
}
void LLPanelPicks::updateButtons()
{
int picks_num = mPicksList->size();
childSetEnabled(XML_BTN_INFO, picks_num > 0);
bool has_selected = mPicksList->numSelected();
childSetEnabled(XML_BTN_INFO, has_selected);
if (getAvatarId() == gAgentID)
{
childSetEnabled(XML_BTN_NEW, picks_num < MAX_AVATAR_PICKS);
childSetEnabled(XML_BTN_DELETE, picks_num > 0);
//*TODO move somewhere this calls
// we'd better set them up earlier when a panel was being constructed
mPopupMenu->setItemVisible("pick_delete", TRUE);
mPopupMenu->setItemVisible("pick_edit", TRUE);
mPopupMenu->setItemVisible("pick_separator", TRUE);
childSetEnabled(XML_BTN_DELETE, has_selected);
}
//*TODO update buttons like Show on Map, Teleport etc.
childSetEnabled(XML_BTN_INFO, has_selected);
childSetEnabled(XML_BTN_TELEPORT, has_selected);
childSetEnabled(XML_BTN_SHOW_ON_MAP, has_selected);
}
void LLPanelPicks::setProfilePanel(LLPanelProfile* profile_panel)
@ -318,12 +320,12 @@ void LLPanelPicks::onClickNew()
void LLPanelPicks::onClickInfo()
{
LLPickItem* pick = getSelectedPickItem();
if (!pick) return;
LLSD selected_value = mPicksList->getSelectedValue();
if (selected_value.isUndefined()) return;
buildPickPanel();
mPickPanel->reset();
mPickPanel->init(pick->getCreatorId(), pick->getPickId());
mPickPanel->init(selected_value[PICK_CREATOR_ID], selected_value[PICK_ID]);
getProfilePanel()->togglePanel(mPickPanel);
}
@ -335,12 +337,12 @@ void LLPanelPicks::onClickBack()
void LLPanelPicks::onClickMenuEdit()
{
//*TODO, refactor - most of that is similar to onClickInfo
LLPickItem* pick = getSelectedPickItem();
if (!pick) return;
LLSD selected_value = mPicksList->getSelectedValue();
if (selected_value.isUndefined()) return;
buildPickPanel();
mPickPanel->reset();
mPickPanel->init(pick->getCreatorId(), pick->getPickId());
mPickPanel->init(selected_value[PICK_CREATOR_ID], selected_value[PICK_ID]);
mPickPanel->setEditMode(TRUE);
getProfilePanel()->togglePanel(mPickPanel);
}
@ -470,3 +472,17 @@ void LLPanelPicks::onClose()
getProfilePanel()->togglePanel(mPickPanel);
}
}
BOOL LLPickItem::postBuild()
{
setMouseEnterCallback(boost::bind(&LLPanelPick::childSetVisible, this, "hovered_icon", true));
setMouseLeaveCallback(boost::bind(&LLPanelPick::childSetVisible, this, "hovered_icon", false));
return TRUE;
}
void LLPickItem::setValue(const LLSD& value)
{
if (!value.isMap()) return;;
if (!value.has("selected")) return;
childSetVisible("selected_icon", value["selected"]);
}

View File

@ -152,6 +152,11 @@ public:
~LLPickItem();
/*virtual*/ BOOL postBuild();
/** setting on/off background icon to indicate selected state */
/*virtual*/ void setValue(const LLSD& value);
protected:
LLUUID mPickID;

View File

@ -49,6 +49,7 @@
#include "lltextbox.h"
#include "llaccordionctrl.h"
#include "llaccordionctrltab.h"
#include "llagent.h"
#include "llavatarpropertiesprocessor.h"
#include "llfloaterworldmap.h"
@ -81,6 +82,8 @@ LLPanelPlaceInfo::~LLPanelPlaceInfo()
{
LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mParcelID, this);
}
LLViewerParcelMgr::getInstance()->removeObserver(this);
}
BOOL LLPanelPlaceInfo::postBuild()
@ -98,26 +101,16 @@ BOOL LLPanelPlaceInfo::postBuild()
mParcelName = getChild<LLTextBox>("parcel_title");
mDescEditor = getChild<LLTextEditor>("description");
mMaturityRatingIcon = getChild<LLIconCtrl>("maturity");
mMaturityRatingText = getChild<LLTextBox>("maturity_value");
mParcelOwner = getChild<LLTextBox>("owner_value");
mLastVisited = getChild<LLTextBox>("last_visited_value");
mRatingIcon = getChild<LLIconCtrl>("rating_icon");
mRatingText = getChild<LLTextBox>("rating_value");
mVoiceIcon = getChild<LLIconCtrl>("voice_icon");
mVoiceText = getChild<LLTextBox>("voice_value");
mFlyIcon = getChild<LLIconCtrl>("fly_icon");
mFlyText = getChild<LLTextBox>("fly_value");
mPushIcon = getChild<LLIconCtrl>("push_icon");
mPushText = getChild<LLTextBox>("push_value");
mBuildIcon = getChild<LLIconCtrl>("build_icon");
mBuildText = getChild<LLTextBox>("build_value");
mScriptsIcon = getChild<LLIconCtrl>("scripts_icon");
mScriptsText = getChild<LLTextBox>("scripts_value");
mDamageIcon = getChild<LLIconCtrl>("damage_icon");
mDamageText = getChild<LLTextBox>("damage_value");
mRegionNameText = getChild<LLTextBox>("region_name");
@ -131,6 +124,16 @@ BOOL LLPanelPlaceInfo::postBuild()
mEstateOwnerText = getChild<LLTextBox>("estate_owner");
mCovenantText = getChild<LLTextEditor>("covenant");
mSalesPriceText = getChild<LLTextBox>("sales_price");
mAreaText = getChild<LLTextBox>("area");
mTrafficText = getChild<LLTextBox>("traffic");
mPrimitivesText = getChild<LLTextBox>("primitives");
mParcelScriptsText = getChild<LLTextBox>("parcel_scripts");
mTerraformLimitsText = getChild<LLTextBox>("terraform_limits");
mSubdivideText = getChild<LLTextEditor>("subdivide");
mResaleText = getChild<LLTextEditor>("resale");
mSaleToText = getChild<LLTextBox>("sale_to");
mOwner = getChild<LLTextBox>("owner");
mCreator = getChild<LLTextBox>("creator");
mCreated = getChild<LLTextBox>("created");
@ -253,7 +256,6 @@ void LLPanelPlaceInfo::resetLocation()
mLandmarkID.setNull();
mPosRegion.clearVec();
std::string not_available = getString("not_available");
mMaturityRatingIcon->setValue(not_available);
mMaturityRatingText->setValue(not_available);
mParcelOwner->setValue(not_available);
mLastVisited->setValue(not_available);
@ -268,19 +270,12 @@ void LLPanelPlaceInfo::resetLocation()
mSnapshotCtrl->setImageAssetID(LLUUID::null);
mSnapshotCtrl->setFallbackImageName("default_land_picture.j2c");
mRatingIcon->setValue(not_available);
mRatingText->setText(not_available);
mVoiceIcon->setValue(not_available);
mVoiceText->setText(not_available);
mFlyIcon->setValue(not_available);
mFlyText->setText(not_available);
mPushIcon->setValue(not_available);
mPushText->setText(not_available);
mBuildIcon->setValue(not_available);
mBuildText->setText(not_available);
mScriptsIcon->setValue(not_available);
mScriptsText->setText(not_available);
mDamageIcon->setValue(not_available);
mParcelScriptsText->setText(not_available);
mDamageText->setText(not_available);
mRegionNameText->setValue(not_available);
@ -293,6 +288,16 @@ void LLPanelPlaceInfo::resetLocation()
mEstateRatingText->setValue(not_available);
mEstateOwnerText->setValue(not_available);
mCovenantText->setValue(not_available);
mSalesPriceText->setValue(not_available);
mAreaText->setValue(not_available);
mTrafficText->setValue(not_available);
mPrimitivesText->setValue(not_available);
mParcelScriptsText->setValue(not_available);
mTerraformLimitsText->setValue(not_available);
mSubdivideText->setValue(not_available);
mResaleText->setValue(not_available);
mSaleToText->setValue(not_available);
}
//virtual
@ -312,7 +317,6 @@ void LLPanelPlaceInfo::setInfoType(INFO_TYPE type)
bool is_info_type_teleport_history = type == TELEPORT_HISTORY;
getChild<LLTextBox>("maturity_label")->setVisible(!is_info_type_agent);
mMaturityRatingIcon->setVisible(!is_info_type_agent);
mMaturityRatingText->setVisible(!is_info_type_agent);
getChild<LLTextBox>("owner_label")->setVisible(is_info_type_agent);
@ -326,6 +330,8 @@ void LLPanelPlaceInfo::setInfoType(INFO_TYPE type)
getChild<LLAccordionCtrl>("advanced_info_accordion")->setVisible(is_info_type_agent);
LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance();
switch(type)
{
case CREATE_LANDMARK:
@ -333,6 +339,15 @@ void LLPanelPlaceInfo::setInfoType(INFO_TYPE type)
break;
case AGENT:
if (parcel_mgr)
{
// If information is requested for current agent location
// start using LLViewerParcelMgr for land selection.
parcel_mgr->addObserver(this);
parcel_mgr->selectParcelAt(gAgent.getPositionGlobal());
}
// Fall through to PLACE case
case PLACE:
mCurrentTitle = getString("title_place");
@ -348,14 +363,22 @@ void LLPanelPlaceInfo::setInfoType(INFO_TYPE type)
case TELEPORT_HISTORY:
mCurrentTitle = getString("title_teleport_history");
// *TODO: Add last visited timestamp.
mLastVisited->setText(getString("unknown"));
break;
}
if (type != AGENT && parcel_mgr != NULL)
{
if (!parcel_mgr->selectionEmpty())
{
parcel_mgr->deselectUnused();
}
parcel_mgr->removeObserver(this);
}
if (type != PLACE)
toggleMediaPanel(FALSE);
mInfoType = type;
}
BOOL LLPanelPlaceInfo::isMediaPanelVisible()
@ -432,22 +455,16 @@ void LLPanelPlaceInfo::processParcelInfo(const LLParcelData& parcel_data)
// HACK: Flag 0x2 == adult region,
// Flag 0x1 == mature region, otherwise assume PG
std::string rating = LLViewerRegion::accessToString(SIM_ACCESS_PG);
std::string rating_icon = "places_rating_pg.tga";
if (parcel_data.flags & 0x2)
{
rating = LLViewerRegion::accessToString(SIM_ACCESS_ADULT);
rating_icon = "places_rating_adult.tga";
}
else if (parcel_data.flags & 0x1)
{
rating = LLViewerRegion::accessToString(SIM_ACCESS_MATURE);
rating_icon = "places_rating_mature.tga";
}
mMaturityRatingIcon->setValue(rating_icon);
mMaturityRatingText->setValue(rating);
mRatingIcon->setValue(rating_icon);
mRatingText->setValue(rating);
//update for_sale banner, here we should use DFQ_FOR_SALE instead of PF_FOR_SALE
@ -476,7 +493,7 @@ void LLPanelPlaceInfo::processParcelInfo(const LLParcelData& parcel_data)
mRegionName->setText(name);
}
if (mCurrentTitle != getString("title_landmark"))
if (mInfoType == CREATE_LANDMARK)
{
mTitleEditor->setText(parcel_data.name);
mNotesEditor->setText(LLStringUtil::null);
@ -517,10 +534,10 @@ void LLPanelPlaceInfo::displayParcelInfo(const LLVector3& pos_region,
void LLPanelPlaceInfo::displayAgentParcelInfo()
{
mPosRegion = gAgent.getPositionAgent();
mParcel = LLViewerParcelMgr::getInstance()->getFloatingParcelSelection();
LLViewerRegion* region = gAgent.getRegion();
LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
LLParcel* parcel = mParcel->getParcel();
LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
if (!region || !parcel)
return;
@ -547,13 +564,6 @@ void LLPanelPlaceInfo::displayAgentParcelInfo()
default:
parcel_data.flags = 0;
}
// Adding "For Sale" flag in remote parcel response format.
if (parcel->getForSale())
{
parcel_data.flags |= DFQ_FOR_SALE;
}
parcel_data.desc = parcel->getDesc();
parcel_data.name = parcel->getName();
parcel_data.sim_name = gAgent.getRegion()->getName();
@ -563,75 +573,68 @@ void LLPanelPlaceInfo::displayAgentParcelInfo()
parcel_data.global_y = global_pos.mdV[1];
parcel_data.global_z = global_pos.mdV[2];
mPosRegion = gAgent.getPositionAgent();
processParcelInfo(parcel_data);
std::string on = getString("on");
std::string off = getString("off");
// Processing parcel characteristics
if (parcel->getParcelFlagAllowVoice())
{
mVoiceIcon->setValue("places_voice_on.tga");
mVoiceText->setText(getString("on"));
mVoiceText->setText(on);
}
else
{
mVoiceIcon->setValue("places_voice_off.tga");
mVoiceText->setText(getString("off"));
mVoiceText->setText(off);
}
if (!region->getBlockFly() && parcel->getAllowFly())
{
mFlyIcon->setValue("places_fly_on.tga");
mFlyText->setText(getString("on"));
mFlyText->setText(on);
}
else
{
mFlyIcon->setValue("places_fly_off.tga");
mFlyText->setText(getString("off"));
mFlyText->setText(off);
}
if (region->getRestrictPushObject() || parcel->getRestrictPushObject())
{
mPushIcon->setValue("places_push_off.tga");
mPushText->setText(getString("off"));
mPushText->setText(off);
}
else
{
mPushIcon->setValue("places_push_on.tga");
mPushText->setText(getString("on"));
mPushText->setText(on);
}
if (parcel->getAllowModify())
{
mBuildIcon->setValue("places_build_on.tga");
mBuildText->setText(getString("on"));
mBuildText->setText(on);
}
else
{
mBuildIcon->setValue("places_build_off.tga");
mBuildText->setText(getString("off"));
mBuildText->setText(off);
}
if((region->getRegionFlags() & REGION_FLAGS_SKIP_SCRIPTS) ||
(region->getRegionFlags() & REGION_FLAGS_ESTATE_SKIP_SCRIPTS) ||
!parcel->getAllowOtherScripts())
{
mScriptsIcon->setValue("places_scripts_off.tga");
mScriptsText->setText(getString("off"));
mScriptsText->setText(off);
}
else
{
mScriptsIcon->setValue("places_scripts_on.tga");
mScriptsText->setText(getString("on"));
mScriptsText->setText(on);
}
if (region->getAllowDamage() || parcel->getAllowDamage())
{
mDamageIcon->setValue("places_damage_on.tga");
mDamageText->setText(getString("on"));
mDamageText->setText(on);
}
else
{
mDamageIcon->setValue("places_damage_off.tga");
mDamageText->setText(getString("off"));
mDamageText->setText(off);
}
mRegionNameText->setText(region->getName());
@ -656,7 +659,8 @@ void LLPanelPlaceInfo::displayAgentParcelInfo()
gCacheName->get(parcel->getGroupID(), TRUE,
boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, this, mRegionGroupText, _2, _3));
mParcelOwner->setText(mRegionGroupText->getText());
gCacheName->get(parcel->getGroupID(), TRUE,
boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, this, mParcelOwner, _2, _3));
}
else
{
@ -681,6 +685,98 @@ void LLPanelPlaceInfo::displayAgentParcelInfo()
}
mEstateRatingText->setText(region->getSimAccessString());
S32 area;
S32 claim_price;
S32 rent_price;
F32 dwell;
BOOL for_sale = parcel->getForSale();
LLViewerParcelMgr::getInstance()->getDisplayInfo(&area,
&claim_price,
&rent_price,
&for_sale,
&dwell);
if (for_sale)
{
// Adding "For Sale" flag in remote parcel response format.
parcel_data.flags |= DFQ_FOR_SALE;
const LLUUID& auth_buyer_id = parcel->getAuthorizedBuyerID();
if(auth_buyer_id.notNull())
{
gCacheName->get(auth_buyer_id, TRUE,
boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, this, mSaleToText, _2, _3));
// Show sales info to a specific person or a group he belongs to.
if (auth_buyer_id != gAgent.getID() && !gAgent.isInGroup(auth_buyer_id))
{
for_sale = FALSE;
}
}
else
{
mSaleToText->setText(getString("anyone"));
}
const U8* sign = (U8*)getString("price_text").c_str();
const U8* sqm = (U8*)getString("area_text").c_str();
mSalesPriceText->setText(llformat("%s%d ", sign, parcel->getSalePrice()));
mAreaText->setText(llformat("%d %s", area, sqm));
mTrafficText->setText(llformat("%.0f", dwell));
// Can't have more than region max tasks, regardless of parcel
// object bonus factor.
S32 primitives = llmin(llround(parcel->getMaxPrimCapacity() * parcel->getParcelPrimBonus()),
(S32)region->getMaxTasks());
const U8* available = (U8*)getString("available").c_str();
const U8* allocated = (U8*)getString("allocated").c_str();
mPrimitivesText->setText(llformat("%d %s, %d %s", primitives, available, parcel->getPrimCount(), allocated));
if (parcel->getAllowOtherScripts())
{
mParcelScriptsText->setText(getString("all_residents_text"));
}
else if (parcel->getAllowGroupScripts())
{
mParcelScriptsText->setText(getString("group_text"));
}
else
{
mParcelScriptsText->setText(off);
}
mTerraformLimitsText->setText(parcel->getAllowTerraform() ? on : off);
if (region->getRegionFlags() & REGION_FLAGS_ALLOW_PARCEL_CHANGES)
{
mSubdivideText->setText(getString("can_change"));
}
else
{
mSubdivideText->setText(getString("can_not_change"));
}
if (region->getRegionFlags() & REGION_FLAGS_BLOCK_LAND_RESELL)
{
mResaleText->setText(getString("can_not_resell"));
}
else
{
mResaleText->setText(getString("can_resell"));
}
}
getChild<LLAccordionCtrlTab>("sales_tab")->setVisible(for_sale);
}
// virtual
void LLPanelPlaceInfo::changed()
{
resetLocation();
displayAgentParcelInfo();
}
void LLPanelPlaceInfo::updateEstateName(const std::string& name)
@ -698,6 +794,22 @@ void LLPanelPlaceInfo::updateCovenantText(const std::string &text)
mCovenantText->setText(text);
}
void LLPanelPlaceInfo::updateLastVisitedText(const LLDate &date)
{
if (date.isNull())
{
mLastVisited->setText(getString("unknown"));
}
else
{
std::string timeStr = getString("acquired_date");
LLSD substitution;
substitution["datetime"] = (S32) date.secondsSinceEpoch();
LLStringUtil::format (timeStr, substitution);
mLastVisited->setText(timeStr);
}
}
void LLPanelPlaceInfo::onCommitTitleOrNote(LANDMARK_INFO_TYPE type)
{
LLInventoryItem* item = gInventory.getItem(mLandmarkID);
@ -785,6 +897,7 @@ void LLPanelPlaceInfo::createPick(const LLVector3d& global_pos)
LLAvatarPropertiesProcessor::instance().sendDataUpdate(&pick_data, APT_PICK_INFO);
}
// virtual
void LLPanelPlaceInfo::reshape(S32 width, S32 height, BOOL called_from_parent)
{
if (mMinHeight > 0 && mScrollingPanel != NULL)
@ -794,3 +907,22 @@ void LLPanelPlaceInfo::reshape(S32 width, S32 height, BOOL called_from_parent)
LLView::reshape(width, height, called_from_parent);
}
// virtual
void LLPanelPlaceInfo::handleVisibilityChange (BOOL new_visibility)
{
LLPanel::handleVisibilityChange(new_visibility);
LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance();
if (!parcel_mgr)
return;
// Remove land selection when panel hides.
if (!new_visibility)
{
if (!parcel_mgr->selectionEmpty())
{
parcel_mgr->deselectLand();
}
}
}

View File

@ -42,15 +42,17 @@
#include "llpanelmedia.h"
#include "llremoteparcelrequest.h"
#include "llviewerparcelmgr.h"
class LLButton;
class LLInventoryItem;
class LLLineEditor;
class LLParcelSelection;
class LLTextBox;
class LLTextEditor;
class LLTextureCtrl;
class LLPanelPlaceInfo : public LLPanel, LLRemoteParcelInfoObserver
class LLPanelPlaceInfo : public LLPanel, LLRemoteParcelInfoObserver, LLParcelObserver
{
public:
enum INFO_TYPE
@ -105,9 +107,13 @@ public:
// without sending a request to the server.
void displayAgentParcelInfo();
// Called on parcel selection change by LLViewerParcelMgr.
/*virtual*/ void changed();
void updateEstateName(const std::string& name);
void updateEstateOwnerName(const std::string& name);
void updateCovenantText(const std::string &text);
void updateLastVisitedText(const LLDate &date);
void nameUpdatedCallback(LLTextBox* text,
const std::string& first,
@ -115,6 +121,7 @@ public:
/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
/*virtual*/ void handleVisibilityChange (BOOL new_visibility);
private:
enum LANDMARK_INFO_TYPE
@ -131,30 +138,23 @@ private:
LLVector3 mPosRegion;
std::string mCurrentTitle;
S32 mMinHeight;
INFO_TYPE mInfoType;
LLTextBox* mTitle;
LLTextureCtrl* mSnapshotCtrl;
LLTextBox* mRegionName;
LLTextBox* mParcelName;
LLTextEditor* mDescEditor;
LLIconCtrl* mMaturityRatingIcon;
LLTextBox* mMaturityRatingText;
LLTextBox* mParcelOwner;
LLTextBox* mLastVisited;
LLIconCtrl* mRatingIcon;
LLTextBox* mRatingText;
LLIconCtrl* mVoiceIcon;
LLTextBox* mVoiceText;
LLIconCtrl* mFlyIcon;
LLTextBox* mFlyText;
LLIconCtrl* mPushIcon;
LLTextBox* mPushText;
LLIconCtrl* mBuildIcon;
LLTextBox* mBuildText;
LLIconCtrl* mScriptsIcon;
LLTextBox* mScriptsText;
LLIconCtrl* mDamageIcon;
LLTextBox* mDamageText;
LLTextBox* mRegionNameText;
@ -168,6 +168,16 @@ private:
LLTextBox* mEstateOwnerText;
LLTextEditor* mCovenantText;
LLTextBox* mSalesPriceText;
LLTextBox* mAreaText;
LLTextBox* mTrafficText;
LLTextBox* mPrimitivesText;
LLTextBox* mParcelScriptsText;
LLTextBox* mTerraformLimitsText;
LLTextEditor* mSubdivideText;
LLTextEditor* mResaleText;
LLTextBox* mSaleToText;
LLTextBox* mOwner;
LLTextBox* mCreator;
LLTextBox* mCreated;
@ -176,6 +186,8 @@ private:
LLPanel* mScrollingPanel;
LLPanel* mInfoPanel;
LLMediaPanel* mMediaPanel;
LLSafeHandle<LLParcelSelection> mParcel;
};
#endif // LL_LLPANELPLACEINFO_H

View File

@ -51,6 +51,7 @@
#include "llpanellandmarks.h"
#include "llpanelteleporthistory.h"
#include "llsidetray.h"
#include "llteleporthistorystorage.h"
#include "lltoggleablemenu.h"
#include "llviewerinventory.h"
#include "llviewermenu.h"
@ -172,8 +173,7 @@ void LLPanelPlaces::onOpen(const LLSD& key)
if (mPlaceInfoType == AGENT_INFO_TYPE)
{
mPlaceInfo->setInfoType(LLPanelPlaceInfo::AGENT);
mPlaceInfo->displayAgentParcelInfo();
mPosGlobal = gAgent.getPositionGlobal();
}
else if (mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE)
@ -212,14 +212,15 @@ void LLPanelPlaces::onOpen(const LLSD& key)
{
S32 index = key["id"].asInteger();
const LLTeleportHistory::slurl_list_t& hist_items =
LLTeleportHistory::getInstance()->getItems();
const LLTeleportHistoryStorage::slurl_list_t& hist_items =
LLTeleportHistoryStorage::getInstance()->getItems();
mPosGlobal = hist_items[index].mGlobalPos;
mPlaceInfo->setInfoType(LLPanelPlaceInfo::TELEPORT_HISTORY);
mPlaceInfo->updateLastVisitedText(hist_items[index].mDate);
mPlaceInfo->displayParcelInfo(get_pos_local_from_global(mPosGlobal),
hist_items[index].mRegionID,
LLUUID(),
mPosGlobal);
}
}

View File

@ -37,6 +37,7 @@
#include "llpanelteleporthistory.h"
#include "llsidetray.h"
#include "llworldmap.h"
#include "llteleporthistorystorage.h"
// Not yet implemented; need to remove buildPanel() from constructor when we switch
//static LLRegisterPanelClassWrapper<LLTeleportHistoryPanel> t_teleport_history("panel_teleport_history");
@ -56,7 +57,7 @@ LLTeleportHistoryPanel::~LLTeleportHistoryPanel()
BOOL LLTeleportHistoryPanel::postBuild()
{
mTeleportHistory = LLTeleportHistory::getInstance();
mTeleportHistory = LLTeleportHistoryStorage::getInstance();
if (mTeleportHistory)
{
mTeleportHistory->setHistoryChangedCallback(boost::bind(&LLTeleportHistoryPanel::showTeleportHistory, this));
@ -92,9 +93,7 @@ void LLTeleportHistoryPanel::onShowOnMap()
S32 index = itemp->getColumn(LIST_INDEX)->getValue().asInteger();
const LLTeleportHistory::slurl_list_t& hist_items = mTeleportHistory->getItems();
LLVector3d global_pos = hist_items[index].mGlobalPos;
LLVector3d global_pos = mTeleportHistory->getItems()[index].mGlobalPos;
if (!global_pos.isExactlyZero())
{
@ -153,7 +152,7 @@ void LLTeleportHistoryPanel::updateVerbs()
if (itemp)
{
index = itemp->getColumn(LIST_INDEX)->getValue().asInteger();
cur_item = mTeleportHistory->getCurrentItemIndex();
cur_item = mTeleportHistory->getItems().size() - 1;
}
mTeleportBtn->setEnabled(index != cur_item);
@ -162,13 +161,11 @@ void LLTeleportHistoryPanel::updateVerbs()
void LLTeleportHistoryPanel::showTeleportHistory()
{
const LLTeleportHistory::slurl_list_t& hist_items = mTeleportHistory->getItems();
const LLTeleportHistoryStorage::slurl_list_t& hist_items = mTeleportHistory->getItems();
mHistoryItems->deleteAllItems();
S32 cur_item = mTeleportHistory->getCurrentItemIndex();
for (LLTeleportHistory::slurl_list_t::const_iterator iter = hist_items.begin();
for (LLTeleportHistoryStorage::slurl_list_t::const_iterator iter = hist_items.begin();
iter != hist_items.end(); ++iter)
{
std::string landmark_title = (*iter).mTitle;
@ -181,7 +178,6 @@ void LLTeleportHistoryPanel::showTeleportHistory()
continue;
S32 index = iter - hist_items.begin();
LLSD row;
row["id"] = index;
@ -201,14 +197,12 @@ void LLTeleportHistoryPanel::showTeleportHistory()
index_column["value"] = index;
mHistoryItems->addElement(row, ADD_TOP);
if (cur_item == index)
{
LLScrollListItem* itemp = mHistoryItems->getItem(index);
((LLScrollListText*)itemp->getColumn(LIST_ITEM_TITLE))->setFontStyle(LLFontGL::BOLD);
}
}
// Consider last item (most recent) as current
LLScrollListItem* itemp = mHistoryItems->getItem((S32)hist_items.size() - 1);
((LLScrollListText*)itemp->getColumn(LIST_ITEM_TITLE))->setFontStyle(LLFontGL::BOLD);
updateVerbs();
}

View File

@ -39,6 +39,8 @@
#include "llpanelplacestab.h"
#include "llteleporthistory.h"
class LLTeleportHistoryStorage;
class LLTeleportHistoryPanel : public LLPanelPlacesTab
{
public:
@ -65,7 +67,7 @@ private:
LIST_INDEX
};
LLTeleportHistory* mTeleportHistory;
LLTeleportHistoryStorage* mTeleportHistory;
LLScrollListCtrl* mHistoryItems;
std::string mFilterSubString;
};

View File

@ -88,9 +88,12 @@ void LLScreenChannel::reshape(S32 width, S32 height, BOOL called_from_parent)
//--------------------------------------------------------------------------
void LLScreenChannel::addToast(LLToast::Params p)
{
bool store_toast = !mShowToasts && p.can_be_stored && mCanStoreToasts;
bool store_toast = false, show_toast = false;
if(!mShowToasts && !store_toast)
show_toast = mShowToasts || p.force_show;
store_toast = !show_toast && p.can_be_stored && mCanStoreToasts;
if(!show_toast && !store_toast)
{
mOnRejectToast(p);
return;
@ -106,7 +109,7 @@ void LLScreenChannel::addToast(LLToast::Params p)
new_toast_elem.toast->setOnToastHoverCallback(boost::bind(&LLScreenChannel::onToastHover, this, _1, _2));
}
if(mShowToasts)
if(show_toast)
{
mToastList.push_back(new_toast_elem);
showToasts();

View File

@ -0,0 +1,250 @@
/**
* @file llsearchcombobox.cpp
* @brief Search Combobox implementation
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
* Copyright (c) 2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llsearchcombobox.h"
#include "llkeyboard.h"
#include "lluictrlfactory.h"
static LLDefaultChildRegistry::Register<LLSearchComboBox> r1("search_combo_box");
class LLSearchHistoryBuilder
{
public:
LLSearchHistoryBuilder(LLSearchComboBox* combo_box, const std::string& filter);
virtual void buildSearchHistory();
virtual ~LLSearchHistoryBuilder(){}
protected:
virtual bool filterSearchHistory();
LLSearchComboBox* mComboBox;
std::string mFilter;
LLSearchHistory::search_history_list_t mFilteredSearchHistory;
};
LLSearchComboBox::Params::Params()
: search_button("search_button")
, dropdown_button_visible("dropdown_button_visible", false)
{
}
LLSearchComboBox::LLSearchComboBox(const Params&p)
: LLComboBox(p)
{
S32 btn_top = p.search_button.top_pad + p.search_button.rect.height;
S32 btn_right = p.search_button.rect.width + p.search_button.left_pad;
LLRect search_btn_rect(p.search_button.left_pad, btn_top, btn_right, p.search_button.top_pad);
LLButton::Params button_params(p.search_button);
button_params.name(std::string("search_btn"));
button_params.rect(search_btn_rect) ;
button_params.follows.flags(FOLLOWS_LEFT|FOLLOWS_TOP);
button_params.tab_stop(false);
button_params.click_callback.function(boost::bind(&LLSearchComboBox::onSelectionCommit, this));
mSearchButton = LLUICtrlFactory::create<LLButton>(button_params);
mTextEntry->addChild(mSearchButton);
setButtonVisible(p.dropdown_button_visible);
mTextEntry->setCommitCallback(boost::bind(&LLComboBox::onTextCommit, this, _2));
mTextEntry->setKeystrokeCallback(boost::bind(&LLComboBox::onTextEntry, this, _1), NULL);
setSelectionCallback(boost::bind(&LLSearchComboBox::onSelectionCommit, this));
setPrearrangeCallback(boost::bind(&LLSearchComboBox::onSearchPrearrange, this, _2));
}
void LLSearchComboBox::rebuildSearchHistory(const std::string& filter)
{
LLSearchHistoryBuilder builder(this, filter);
builder.buildSearchHistory();
}
void LLSearchComboBox::onSearchPrearrange(const LLSD& data)
{
std::string filter = data.asString();
rebuildSearchHistory(filter);
mList->mouseOverHighlightNthItem(-1); // Clear highlight on the last selected item.
}
void LLSearchComboBox::onTextEntry(LLLineEditor* line_editor)
{
KEY key = gKeyboard->currentKey();
if (line_editor->getText().empty())
{
prearrangeList(); // resets filter
hideList();
}
// Typing? (moving cursor should not affect showing the list)
else if (key != KEY_LEFT && key != KEY_RIGHT && key != KEY_HOME && key != KEY_END)
{
prearrangeList(line_editor->getText());
if (mList->getItemCount() != 0)
{
showList();
focusTextEntry();
}
else
{
// Hide the list if it's empty.
hideList();
}
}
LLComboBox::onTextEntry(line_editor);
}
void LLSearchComboBox::focusTextEntry()
{
// We can't use "mTextEntry->setFocus(TRUE)" instead because
// if the "select_on_focus" parameter is true it places the cursor
// at the beginning (after selecting text), thus screwing up updateSelection().
if (mTextEntry)
{
gFocusMgr.setKeyboardFocus(mTextEntry);
}
}
void LLSearchComboBox::hideList()
{
LLComboBox::hideList();
if (mTextEntry && hasFocus())
focusTextEntry();
}
LLSearchComboBox::~LLSearchComboBox()
{
}
void LLSearchComboBox::onSelectionCommit()
{
std::string search_query = getSimple();
LLStringUtil::trim(search_query);
if(search_query.empty())
{
mTextEntry->setText(search_query);
setControlValue(search_query);
return;
}
remove(search_query);
add(search_query, ADD_TOP);
mTextEntry->setText(search_query);
setControlValue(search_query);
LLUICtrl::onCommit();
}
BOOL LLSearchComboBox::remove(const std::string& name)
{
BOOL found = mList->selectItemByLabel(name, FALSE);
if (found)
{
LLScrollListItem* item = mList->getFirstSelected();
if (item)
{
LLComboBox::remove(mList->getItemIndex(item));
}
}
return found;
}
void LLSearchComboBox::clearHistory()
{
removeall();
setTextEntry(LLStringUtil::null);
}
LLSearchHistoryBuilder::LLSearchHistoryBuilder(LLSearchComboBox* combo_box, const std::string& filter)
: mComboBox(combo_box)
, mFilter(filter)
{
}
bool LLSearchHistoryBuilder::filterSearchHistory()
{
// *TODO: an STL algorithm would look nicer
mFilteredSearchHistory.clear();
std::string filter_copy = mFilter;
LLStringUtil::toLower(filter_copy);
LLSearchHistory::search_history_list_t history =
LLSearchHistory::getInstance()->getSearchHistoryList();
LLSearchHistory::search_history_list_t::const_iterator it = history.begin();
for ( ; it != history.end(); ++it)
{
std::string search_query = (*it).search_query;
LLStringUtil::toLower(search_query);
if (search_query.find(filter_copy) != std::string::npos)
mFilteredSearchHistory.push_back(*it);
}
return mFilteredSearchHistory.size();
}
void LLSearchHistoryBuilder::buildSearchHistory()
{
mFilteredSearchHistory.clear();
LLSearchHistory::search_history_list_t filtered_items;
LLSearchHistory::search_history_list_t* itemsp = NULL;
LLSearchHistory* sh = LLSearchHistory::getInstance();
if (mFilter.empty())
{
itemsp = &sh->getSearchHistoryList();
}
else
{
filterSearchHistory();
itemsp = &mFilteredSearchHistory;
itemsp->sort();
}
mComboBox->removeall();
LLSearchHistory::search_history_list_t::const_iterator it = itemsp->begin();
for ( ; it != itemsp->end(); it++)
{
LLSearchHistory::LLSearchHistoryItem item = *it;
mComboBox->add(item.search_query);
}
}

View File

@ -0,0 +1,108 @@
/**
* @file llsearchcombobox.h
* @brief LLSearchComboBox class definition
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
* Copyright (c) 2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LL_LLSEARCHCOMBOBOX_H
#define LL_LLSEARCHCOMBOBOX_H
#include "llcombobox.h"
#include "llsearchhistory.h"
/**
* Search control with text box for search queries and a drop down list
* with recent queries. Supports text auto-complete and filtering of drop down list
* according to typed text.
*/
class LLSearchComboBox : public LLComboBox
{
public:
struct Params : public LLInitParam::Block<Params, LLComboBox::Params>
{
Optional<LLButton::Params> search_button;
Optional<bool> dropdown_button_visible;
Params();
};
/**
* Removes an entry from combo box, case insensitive
*/
BOOL remove(const std::string& name);
/**
* Clears search history
*/
void clearHistory();
~LLSearchComboBox();
protected:
LLSearchComboBox(const Params&p);
friend class LLUICtrlFactory;
/**
* Handles typing in text box
*/
void onTextEntry(LLLineEditor* line_editor);
/**
* Hides drop down list and focuses text box
*/
void hideList();
/**
* Rebuilds search history, case insensitive
* If filter is an empty string - whole history will be added to combo box
* if filter is valid string - only matching entries will be added
*/
virtual void rebuildSearchHistory(const std::string& filter);
/**
* Callback for prearrange event
*/
void onSearchPrearrange(const LLSD& data);
/**
* Callback for text box or combo box commit
*/
void onSelectionCommit();
/**
* Sets focus to text box
*/
void focusTextEntry();
LLButton* mSearchButton;
};
#endif //LL_LLSEARCHCOMBOBOX_H

View File

@ -0,0 +1,154 @@
/**
* @file llsearchhistory.cpp
* @brief Search history container implementation
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
* Copyright (c) 2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llsearchhistory.h"
#include "llfile.h"
#include "llsdserialize.h"
#include "llxmlnode.h"
std::string LLSearchHistory::SEARCH_QUERY = "search_query";
std::string LLSearchHistory::SEARCH_HISTORY_FILE_NAME = "search_history.txt";
LLSearchHistory::LLSearchHistory()
{
}
bool LLSearchHistory::load()
{
// build filename for each user
std::string resolved_filename = getHistoryFilePath();
llifstream file(resolved_filename);
if (!file.is_open())
{
return false;
}
clearHistory();
// add each line in the file to the list
std::string line;
LLPointer<LLSDParser> parser = new LLSDNotationParser();
while (std::getline(file, line))
{
LLSD s_item;
std::istringstream iss(line);
if (parser->parse(iss, s_item, line.length()) == LLSDParser::PARSE_FAILURE)
{
break;
}
mSearchHistory.push_back(s_item);
}
file.close();
return true;
}
bool LLSearchHistory::save()
{
// build filename for each user
std::string resolved_filename = getHistoryFilePath();
// open a file for writing
llofstream file (resolved_filename);
if (!file.is_open())
{
return false;
}
search_history_list_t::const_iterator it = mSearchHistory.begin();
for (; mSearchHistory.end() != it; ++it)
{
file << LLSDOStreamer<LLSDNotationFormatter>((*it).toLLSD()) << std::endl;
}
file.close();
return true;
}
std::string LLSearchHistory::getHistoryFilePath()
{
return gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SEARCH_HISTORY_FILE_NAME);
}
void LLSearchHistory::addEntry(const std::string& search_query)
{
if(search_query.empty())
{
return;
}
search_history_list_t::iterator it =
find(mSearchHistory.begin(), mSearchHistory.end(), search_query);
if(mSearchHistory.end() != it)
{
mSearchHistory.erase(it);
}
LLSearchHistoryItem item(search_query);
mSearchHistory.push_front(item);
}
bool LLSearchHistory::LLSearchHistoryItem::operator < (const LLSearchHistory::LLSearchHistoryItem& right)
{
S32 result = LLStringUtil::compareInsensitive(search_query, right.search_query);
return result < 0;
}
bool LLSearchHistory::LLSearchHistoryItem::operator > (const LLSearchHistory::LLSearchHistoryItem& right)
{
S32 result = LLStringUtil::compareInsensitive(search_query, right.search_query);
return result > 0;
}
bool LLSearchHistory::LLSearchHistoryItem::operator==(const LLSearchHistory::LLSearchHistoryItem& right)
{
return 0 == LLStringUtil::compareInsensitive(search_query, right.search_query);
}
bool LLSearchHistory::LLSearchHistoryItem::operator==(const std::string& right)
{
return 0 == LLStringUtil::compareInsensitive(search_query, right);
}
LLSD LLSearchHistory::LLSearchHistoryItem::toLLSD() const
{
LLSD ret;
ret[SEARCH_QUERY] = search_query;
return ret;
}

View File

@ -0,0 +1,138 @@
/**
* @file llsearchhistory.h
* @brief Search history container definition
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
* Copyright (c) 2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LL_LLSEARCHHISTORY_H
#define LL_LLSEARCHHISTORY_H
#include "llsingleton.h"
/**
* Search history container able to save and load history from file.
* History is stored in chronological order, most recent at the beginning.
*/
class LLSearchHistory : public LLSingleton<LLSearchHistory>
{
public:
// Forward declaration
class LLSearchHistoryItem;
// Search history container
typedef std::list<LLSearchHistoryItem> search_history_list_t;
/**
* Saves search history to file
*/
bool save();
/**
* loads search history from file
*/
bool load();
/**
* Returns search history list
*/
search_history_list_t& getSearchHistoryList() { return mSearchHistory; }
/**
* Deletes all search history queries from list.
*/
void clearHistory() { mSearchHistory.clear(); }
/**
* Adds unique entry to front of search history list, case insensitive
* If entry is already in list, it will be deleted and added to front.
*/
void addEntry(const std::string& search_text);
LLSearchHistory();
/**
* Class for storing data about single search request.
*/
class LLSearchHistoryItem
{
public:
LLSearchHistoryItem()
{}
LLSearchHistoryItem(const std::string& query)
: search_query(query)
{}
LLSearchHistoryItem(const LLSD& item)
{
if(item.has(SEARCH_QUERY))
search_query = item[SEARCH_QUERY].asString();
}
std::string search_query;
/**
* Allows std::list sorting
*/
bool operator < (const LLSearchHistory::LLSearchHistoryItem& right);
/**
* Allows std::list sorting
*/
bool operator > (const LLSearchHistory::LLSearchHistoryItem& right);
bool operator==(const LLSearchHistoryItem& right);
bool operator==(const std::string& right);
/**
* Serializes search history item to LLSD
*/
LLSD toLLSD() const;
};
protected:
/**
* Returns path to search history file.
*/
std::string getHistoryFilePath();
static std::string SEARCH_HISTORY_FILE_NAME;
static std::string SEARCH_QUERY;
private:
search_history_list_t mSearchHistory;
};
class LLSearchComboBox;
#endif //LL_LLSEARCHHISTORY_H

View File

@ -241,6 +241,13 @@ LLSideTray::LLSideTray(Params& params)
,mMaxBarWidth(params.rect.width)
{
mCollapsed=params.collapsed;
LLUICtrl::CommitCallbackRegistry::Registrar& commit = LLUICtrl::CommitCallbackRegistry::currentRegistrar();
// 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));
}

View File

@ -899,6 +899,10 @@ bool idle_startup()
if (STATE_LOGIN_CLEANUP == LLStartUp::getStartupState())
{
// Move the progress view in front of the UI immediately when login is performed
// this allows not to see main menu after Alt+Tab was pressed while login. EXT-744.
gViewerWindow->moveProgressViewToFront();
//reset the values that could have come in from a slurl
if (!gLoginHandler.getWebLoginKey().isNull())
{

View File

@ -38,9 +38,9 @@
#include "llviewercontrol.h"
#include "llviewerwindow.h"
#include "llchiclet.h"
//---------------------------------------------------------------------------------
LLSysWellWindow::LLSysWellWindow(const LLSD& key) : LLFloater(LLSD()),
mSysWell(NULL),
LLSysWellWindow::LLSysWellWindow(const LLSD& key) : LLDockableFloater(NULL, key),
mChannel(NULL),
mScrollContainer(NULL),
mNotificationList(NULL)
@ -57,13 +57,9 @@ BOOL LLSysWellWindow::postBuild()
mNotificationList = getChild<LLScrollingPanelList>("notification_list");
mIMRowList = getChild<LLScrollingPanelList>("im_row_panel_list");
gViewerWindow->setOnBottomTrayWidthChanged(boost::bind(&LLSysWellWindow::adjustWindowPosition, this)); // *TODO: won't be necessary after docking is realized
mScrollContainer->setBorderVisible(FALSE);
mDockTongue = LLUI::getUIImage("windows/Flyout_Pointer.png");
return TRUE;
return LLDockableFloater::postBuild();
}
//---------------------------------------------------------------------------------
@ -82,7 +78,6 @@ void LLSysWellWindow::addItem(LLSysWellItem::Params p)
LLSysWellItem* new_item = new LLSysWellItem(p);
mNotificationList->addPanel(dynamic_cast<LLScrollingPanel*>(new_item));
reshapeWindow();
adjustWindowPosition(); // *TODO: won't be necessary after docking is realized
new_item->setOnItemCloseCallback(boost::bind(&LLSysWellWindow::onItemClose, this, _1));
new_item->setOnItemClickCallback(boost::bind(&LLSysWellWindow::onItemClick, this, _1));
@ -127,10 +122,6 @@ void LLSysWellWindow::removeItemByID(const LLUUID& id)
return;
reshapeWindow();
adjustWindowPosition(); // *TODO: won't be necessary after docking is realized
// hide chiclet window if there are no items left
setVisible(!isWindowEmpty());
}
//---------------------------------------------------------------------------------
@ -148,11 +139,20 @@ void LLSysWellWindow::onItemClose(LLSysWellItem* item)
removeItemByID(id);
if(mChannel)
mChannel->killToastByNotificationID(id);
// hide chiclet window if there are no items left
setVisible(!isWindowEmpty());
}
//---------------------------------------------------------------------------------
void LLSysWellWindow::toggleWindow()
{
if (getDockControl() == NULL)
{
setDockControl(new LLDockControl(
LLBottomTray::getInstance()->getSysWell(), this,
getDockTongue(), LLDockControl::TOP, isDocked()));
}
setVisible(!getVisible());
}
@ -162,28 +162,26 @@ void LLSysWellWindow::setVisible(BOOL visible)
// on Show adjust position of SysWell chiclet's window
if(visible)
{
if (LLBottomTray::instanceExists())
{
LLBottomTray::getInstance()->getSysWell()->setToggleState(TRUE);
}
if(mChannel)
mChannel->removeAndStoreAllVisibleToasts();
adjustWindowPosition(); // *TODO: won't be necessary after docking is realized
}
else
{
if (LLBottomTray::instanceExists())
{
LLBottomTray::getInstance()->getSysWell()->setToggleState(FALSE);
}
}
if(mChannel)
mChannel->setShowToasts(!visible);
LLFloater::setVisible(visible);
}
//---------------------------------------------------------------------------------
void LLSysWellWindow::adjustWindowPosition() // *TODO: won't be necessary after docking is realized
{
const S32 WINDOW_MARGIN = 5;
LLRect btm_rect = LLBottomTray::getInstance()->getRect();
LLRect this_rect = getRect();
setOrigin(btm_rect.mRight - this_rect.getWidth() - WINDOW_MARGIN, WINDOW_MARGIN);
}
//---------------------------------------------------------------------------------
void LLSysWellWindow::reshapeWindow()
{
@ -272,7 +270,6 @@ void LLSysWellWindow::addIMRow(const LLUUID& sessionId, S32 chicletCounter,
{
mIMRowList->addPanel(new RowPanel(this, sessionId, chicletCounter, name, otherParticipantId));
adjustWindowPosition(); // *TODO: won't be necessary after docking is realized
}
//---------------------------------------------------------------------------------
@ -286,14 +283,12 @@ void LLSysWellWindow::delIMRow(const LLUUID& sessionId)
// hide chiclet window if there are no items left
setVisible(!isWindowEmpty());
adjustWindowPosition(); // *TODO: won't be necessary after docking is realized
}
//---------------------------------------------------------------------------------
bool LLSysWellWindow::isWindowEmpty()
{
if(mIMRowList->getPanelList().size() == 0 && mNotificationList->getPanelList().size() == 0)
if(mIMRowList->getPanelList().size() == 0 && LLBottomTray::getInstance()->getSysWell()->getCounter() == 0)
{
return true;
}
@ -328,7 +323,7 @@ void LLSysWellWindow::sessionRemoved(const LLUUID& sessionId)
{
delIMRow(sessionId);
reshapeWindow();
mSysWell->updateUreadIMNotifications();
LLBottomTray::getInstance()->getSysWell()->updateUreadIMNotifications();
}
//---------------------------------------------------------------------------------
@ -396,5 +391,3 @@ void LLSysWellWindow::RowPanel::updatePanel(BOOL allow_modify)
}
//---------------------------------------------------------------------------------

View File

@ -35,7 +35,7 @@
#include "llsyswellitem.h"
#include "llfloater.h"
#include "lldockablefloater.h"
#include "llbutton.h"
#include "llscreenchannel.h"
#include "llscrollcontainer.h"
@ -46,7 +46,7 @@
class LLSysWellWindow : public LLFloater, LLIMSessionObserver
class LLSysWellWindow : public LLDockableFloater, LLIMSessionObserver
{
public:
LLSysWellWindow(const LLSD& key);
@ -58,7 +58,6 @@ public:
// change attributes
void setChannel(LLNotificationsUI::LLScreenChannel* channel) {mChannel = channel;}
void setSysWell(LLNotificationChiclet* sys_well) {mSysWell = sys_well;}
// Operating with items
void addItem(LLSysWellItem::Params p);
@ -93,9 +92,6 @@ private:
// pointer to a corresponding channel's instance
LLNotificationsUI::LLScreenChannel* mChannel;
LLNotificationChiclet* mSysWell;
LLUIImagePtr mDockTongue;
LLPanel* mTwinListPanel;
LLScrollContainer* mScrollContainer;
LLScrollingPanelList* mIMRowList;

View File

@ -37,8 +37,11 @@
#include "llsd.h"
#include "llsdserialize.h"
#include "lldir.h"
#include "llteleporthistory.h"
#include "llagent.h"
static LLTeleportHistoryStorage tpstorage;
// Max offset for two global positions to consider them as equal
const F64 MAX_GLOBAL_POS_OFFSET = 5.0f;
LLTeleportHistoryPersistentItem::LLTeleportHistoryPersistentItem(const LLSD& val)
{
@ -58,15 +61,42 @@ LLSD LLTeleportHistoryPersistentItem::toLLSD() const
return val;
}
struct LLSortItemsByDate
{
bool operator()(const LLTeleportHistoryPersistentItem& a, const LLTeleportHistoryPersistentItem& b)
{
return a.mDate < b.mDate;
}
};
LLTeleportHistoryStorage::LLTeleportHistoryStorage() :
mFilename("teleport_history.txt")
{
LLTeleportHistory *th = LLTeleportHistory::getInstance();
if (th)
th->setHistoryChangedCallback(boost::bind(&LLTeleportHistoryStorage::onTeleportHistoryChange, this));
load();
}
LLTeleportHistoryStorage::~LLTeleportHistoryStorage()
{
}
void LLTeleportHistoryStorage::onTeleportHistoryChange()
{
LLTeleportHistory *th = LLTeleportHistory::getInstance();
if (!th)
return;
const LLTeleportHistoryItem &item = th->getItems()[th->getCurrentItemIndex()];
addItem(item.mTitle, item.mGlobalPos);
save();
mHistoryChangedSignal();
}
void LLTeleportHistoryStorage::purgeItems()
{
mItems.clear();
@ -74,12 +104,45 @@ void LLTeleportHistoryStorage::purgeItems()
void LLTeleportHistoryStorage::addItem(const std::string title, const LLVector3d& global_pos)
{
mItems.push_back(LLTeleportHistoryPersistentItem(title, global_pos));
addItem(title, global_pos, LLDate::now());
}
bool LLTeleportHistoryStorage::compareByTitleAndGlobalPos(const LLTeleportHistoryPersistentItem& a, const LLTeleportHistoryPersistentItem& b)
{
return a.mTitle == b.mTitle && (a.mGlobalPos - b.mGlobalPos).length() < MAX_GLOBAL_POS_OFFSET;
}
void LLTeleportHistoryStorage::addItem(const std::string title, const LLVector3d& global_pos, const LLDate& date)
{
mItems.push_back(LLTeleportHistoryPersistentItem(title, global_pos, date));
LLTeleportHistoryPersistentItem item(title, global_pos, date);
slurl_list_t::iterator item_iter = std::find_if(mItems.begin(), mItems.end(),
boost::bind(&LLTeleportHistoryStorage::compareByTitleAndGlobalPos, this, _1, item));
// If there is such item already, remove it, since new item is more recent
if (item_iter != mItems.end())
{
mItems.erase(item_iter);
}
mItems.push_back(item);
// Check whether sorting is needed
if (mItems.size() > 1)
{
item_iter = mItems.end();
item_iter--;
item_iter--;
// If second to last item is more recent than last, then resort items
if (item_iter->mDate > item.mDate)
{
std::sort(mItems.begin(), mItems.end(), LLSortItemsByDate());
}
}
}
void LLTeleportHistoryStorage::removeItem(S32 idx)
@ -145,6 +208,8 @@ void LLTeleportHistoryStorage::load()
}
file.close();
std::sort(mItems.begin(), mItems.end(), LLSortItemsByDate());
}
void LLTeleportHistoryStorage::dump() const
@ -162,3 +227,30 @@ void LLTeleportHistoryStorage::dump() const
}
}
boost::signals2::connection LLTeleportHistoryStorage::setHistoryChangedCallback(history_callback_t cb)
{
return mHistoryChangedSignal.connect(cb);
}
void LLTeleportHistoryStorage::goToItem(S32 idx)
{
// Validate specified index.
if (idx < 0 || idx >= (S32)mItems.size())
{
llwarns << "Invalid teleport history index (" << idx << ") specified" << llendl;
dump();
return;
}
if (idx == (S32)mItems.size() - 1)
{
llwarns << "Will not teleport to the same location." << llendl;
dump();
return;
}
// Attempt to teleport to the requested item.
gAgent.teleportViaLocation(mItems[idx].mGlobalPos);
}

View File

@ -78,7 +78,10 @@ class LLTeleportHistoryStorage: public LLSingleton<LLTeleportHistoryStorage>
public:
typedef std::vector<LLTeleportHistoryPersistentItem> item_list_list_t;
typedef std::vector<LLTeleportHistoryPersistentItem> slurl_list_t;
typedef boost::function<void()> history_callback_t;
typedef boost::signals2::signal<void()> history_signal_t;
LLTeleportHistoryStorage();
~LLTeleportHistoryStorage();
@ -86,7 +89,7 @@ public:
/**
* @return history items.
*/
const item_list_list_t& getItems() const { return mItems; }
const slurl_list_t& getItems() const { return mItems; }
void purgeItems();
void addItem(const std::string title, const LLVector3d& global_pos);
@ -99,10 +102,34 @@ public:
void dump() const;
/**
* Set a callback to be called upon history changes.
*
* Multiple callbacks can be set.
*/
boost::signals2::connection setHistoryChangedCallback(history_callback_t cb);
/**
* Go to specific item in the history.
*
* The item is specified by its index (starting from 0).
*/
void goToItem(S32 idx);
private:
item_list_list_t mItems;
std::string mFilename;
void onTeleportHistoryChange();
bool compareByTitleAndGlobalPos(const LLTeleportHistoryPersistentItem& a, const LLTeleportHistoryPersistentItem& b);
slurl_list_t mItems;
std::string mFilename;
/**
* Signal emitted when the history gets changed.
*
* Invokes callbacks set with setHistoryChangedCallback().
*/
history_signal_t mHistoryChangedSignal;
};
#endif //LL_LLTELEPORTHISTORYSTORAGE_H

View File

@ -70,12 +70,16 @@ public:
bool enable_hide_btn;
bool is_modal;
bool is_tip;
bool force_show;
bool force_store;
Params() : can_fade(true),
can_be_stored(true),
is_modal(false),
is_tip(false),
enable_hide_btn(true),
force_show(false),
force_store(false),
panel(NULL),
timer_period(gSavedSettings.getS32("NotificationToastTime"))

View File

@ -40,7 +40,7 @@
#include "lliconctrl.h"
#include "llnotify.h"
#include "lltextbox.h"
#include "lltexteditor.h"
#include "lluiconstants.h"
#include "llui.h"
#include "llviewercontrol.h"
@ -53,6 +53,8 @@
#include "llfloaterinventory.h"
#include "llinventorytype.h"
const S32 LLToastGroupNotifyPanel::DEFAULT_MESSAGE_MAX_LINE_COUNT = 4;
LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification)
: LLToastPanel(notification),
mInventoryOffer(NULL)
@ -65,8 +67,6 @@ LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification
llwarns << "Group notice for unkown group: " << payload["group_id"].asUUID() << llendl;
}
static const LLUIColor textColor = LLUIColorTable::instance().getColor("GroupNotifyTextColor");
//group icon
LLIconCtrl* pGroupIcon = getChild<LLIconCtrl>("group_icon", TRUE);
pGroupIcon->setValue(groupData.mInsigniaID);
@ -78,23 +78,16 @@ LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification
LLTextBox* pTitleText = getChild<LLTextBox>("title");
pTitleText->setValue(from.str());
//message body
//message subject
const std::string& subject = payload["subject"].asString();
//message body
const std::string& message = payload["message"].asString();
LLTextEditor* pMessageText = getChild<LLTextEditor>("message");
pMessageText->setValue("");
pMessageText->setEnabled(FALSE);
LLStyle::Params date_style;
date_style.color = textColor;
date_style.font.name = "SANSSERIF";
LLStyle::Params header_style_params;
header_style_params.color = textColor;
header_style_params.font = LLFontGL::getFontSansSerifBig();
pMessageText->appendStyledText(subject + "\n",false,false,header_style_params);
LLTextBox* pSubjectText = getChild<LLTextBox>("subject");
pSubjectText->setValue(subject);
LLTextBox* pDateTimeText = getChild<LLTextBox>("datetime");
std::string timeStr = "["+LLTrans::getString("UTCTimeWeek")+"],["
+LLTrans::getString("UTCTimeDay")+"] ["
+LLTrans::getString("UTCTimeMth")+"] ["
@ -108,25 +101,38 @@ LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification
LLSD substitution;
substitution["datetime"] = (S32) notice_date.secondsSinceEpoch();
LLStringUtil::format(timeStr, substitution);
LLStyle::Params date_style_params;
date_style_params.color = textColor;
date_style_params.font = LLFontGL::getFontMonospace();
pMessageText->appendStyledText(timeStr, false, false, date_style);
pMessageText->appendColoredText(std::string("\n\n") + message, false,
false, textColor);
pDateTimeText->setValue(timeStr);
LLTextBox* pMessageText = getChild<LLTextBox>("message");
//If message is empty let it be invisible and not take place at the panel
if(message.size() != 0)
{
pMessageText->setVisible(TRUE);
pMessageText->setValue(message);
}
else
{
pMessageText->setVisible(FALSE);
}
//attachment
BOOL hasInventory = payload["inventory_offer"].isDefined();
//attachment text
LLTextBox * pAttachLink = getChild<LLTextBox>("attachment");
//attachment icon
LLIconCtrl* pAttachIcon = getChild<LLIconCtrl>("attachment_icon", TRUE);
//If attachment is empty let it be invisible and not take place at the panel
pAttachLink->setVisible(hasInventory);
pAttachIcon->setVisible(hasInventory);
if (hasInventory) {
pAttachLink->setValue(payload["inventory_name"]);
mInventoryOffer = new LLOfferInfo(payload["inventory_offer"]);
childSetActionTextbox("attachment", boost::bind(
&LLToastGroupNotifyPanel::onClickAttachment, this));
//attachment icon
LLIconCtrl* pAttachIcon = getChild<LLIconCtrl>("attachment_icon", TRUE);
LLUIImagePtr attachIconImg = get_item_icon(mInventoryOffer->mType,
LLInventoryType::IT_TEXTURE,
0, FALSE);
@ -137,8 +143,15 @@ LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification
LLButton* pOkBtn = getChild<LLButton>("btn_ok");
pOkBtn->setClickedCallback((boost::bind(&LLToastGroupNotifyPanel::onClickOk, this)));
setDefaultBtn(pOkBtn);
}
S32 maxLinesCount;
std::istringstream ss( getString("message_max_lines_count") );
if (!(ss >> maxLinesCount))
{
maxLinesCount = DEFAULT_MESSAGE_MAX_LINE_COUNT;
}
snapToMessageHeight(pMessageText, maxLinesCount);
}
// virtual
LLToastGroupNotifyPanel::~LLToastGroupNotifyPanel()

View File

@ -68,6 +68,8 @@ protected:
private:
static bool isAttachmentOpenable(LLAssetType::EType);
static const S32 DEFAULT_MESSAGE_MAX_LINE_COUNT;
LLButton* mSaveInventoryBtn;
LLUUID mGroupID;

View File

@ -34,9 +34,7 @@
#include "lltoastimpanel.h"
#include "llimpanel.h"
const S32 LLToastIMPanel::MAX_MESSAGE_HEIGHT = 50;
const S32 LLToastIMPanel::CAPTION_HEIGHT = 30;
const S32 LLToastIMPanel::TOP_PAD = 5;
const S32 LLToastIMPanel::DEFAULT_MESSAGE_MAX_LINE_COUNT = 6;
//--------------------------------------------------------------------------
LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) : LLToastPanel(p.notification),
@ -60,7 +58,13 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) : LLToastPanel(p.notif
mReplyBtn->setClickedCallback(boost::bind(&LLToastIMPanel::onClickReplyBtn, this));
snapToMessageHeight();
S32 maxLinesCount;
std::istringstream ss( getString("message_max_lines_count") );
if (!(ss >> maxLinesCount))
{
maxLinesCount = DEFAULT_MESSAGE_MAX_LINE_COUNT;
}
snapToMessageHeight(mMessage, maxLinesCount);
}
//--------------------------------------------------------------------------
@ -68,22 +72,6 @@ LLToastIMPanel::~LLToastIMPanel()
{
}
//--------------------------------------------------------------------------
void LLToastIMPanel::snapToMessageHeight()
{
S32 required_text_height = mMessage->getTextPixelHeight();
S32 text_height = llmin(required_text_height, MAX_MESSAGE_HEIGHT);
LLRect text_rect = mMessage->getRect();
LLRect btn_rect = mReplyBtn->getRect();
mMessage->reshape( text_rect.getWidth(), text_height, TRUE);
mMessage->setValue(mMessage->getText());
S32 panel_height = CAPTION_HEIGHT + text_height + btn_rect.getHeight() + TOP_PAD*5;
reshape( getRect().getWidth(), panel_height, TRUE);
}
//--------------------------------------------------------------------------
void LLToastIMPanel::onClickReplyBtn()
{

View File

@ -59,12 +59,9 @@ public:
virtual ~LLToastIMPanel();
private:
static const S32 MAX_MESSAGE_HEIGHT;
static const S32 CAPTION_HEIGHT;
static const S32 TOP_PAD;
static const S32 DEFAULT_MESSAGE_MAX_LINE_COUNT;
void onClickReplyBtn();
void snapToMessageHeight();
LLUUID mSessionID;
LLAvatarIconCtrl* mAvatar;

View File

@ -49,5 +49,36 @@ std::string LLToastPanel::getTitle()
return mNotification->getMessage();
}
//snap to the message height if it is visible
void LLToastPanel::snapToMessageHeight(LLTextBox* message, S32 maxLineCount)
{
//Add message height if it is visible
if (message->getVisible())
{
S32 heightDelta = 0;
S32 maxTextHeight = (S32)(message->getFont()->getLineHeight() * maxLineCount);
LLRect messageRect = message->getRect();
S32 oldTextHeight = messageRect.getHeight();
//Reshape the toast to give the message max height.
//This needed to calculate lines count according to specified text
heightDelta = maxTextHeight - oldTextHeight;
reshape( getRect().getWidth(), getRect().getHeight() + heightDelta);
message->setValue(message->getText());
//Knowing the height is set to max allowed, getTextPixelHeight returns needed text height
//Perhaps we need to pass maxLineCount as parameter to getTextPixelHeight to avoid previous reshape.
S32 requiredTextHeight = message->getTextPixelHeight();
S32 newTextHeight = llmin(requiredTextHeight, maxTextHeight);
//Calculate last delta height deducting previous heightDelta
heightDelta = newTextHeight - oldTextHeight - heightDelta;
//reshape the panel with new height
reshape( getRect().getWidth(), getRect().getHeight() + heightDelta);
message->setValue(message->getText());
}
}

View File

@ -34,6 +34,7 @@
#define LL_LLTOASTPANEL_H
#include "llpanel.h"
#include "lltextbox.h"
#include "llnotifications.h"
#include <string>
@ -53,6 +54,7 @@ public:
virtual const LLUUID& getID() { return mNotification->id();}
protected:
LLNotificationPtr mNotification;
void snapToMessageHeight(LLTextBox* message, S32 maxLineCount);
};
#endif /* LL_TOASTPANEL_H */

View File

@ -60,6 +60,7 @@
#include "llui.h"
#include "llviewermenu.h"
#include "llfirstuse.h"
#include "llpanelblockedlist.h"
#include "llscrolllistctrl.h"
#include "llscrolllistitem.h"
#include "llscrolllistcell.h"
@ -69,7 +70,6 @@
#include "lltoolgrab.h"
#include "llcombobox.h"
#include "llfloaterchat.h"
#include "llfloatermute.h"
#include "llimpanel.h"
#include "lllayoutstack.h"
@ -297,11 +297,8 @@ void LLToolBar::updateCommunicateList()
communicate_button->addSeparator(ADD_TOP);
communicate_button->add(getString("Redock Windows"), LLSD("redock"), ADD_TOP);
communicate_button->addSeparator(ADD_TOP);
LLFloaterMute* mute_instance = LLFloaterReg::getTypedInstance<LLFloaterMute>("mute");
if(mute_instance)
{
communicate_button->add(mute_instance->getShortTitle(), LLSD("mute list"), ADD_TOP);
}
communicate_button->add(getString("Blocked List"), LLSD("mute list"), ADD_TOP);
std::set<LLHandle<LLFloater> >::const_iterator floater_handle_it;
if (gIMMgr->getIMFloaterHandles().size() > 0)
@ -379,7 +376,7 @@ void LLToolBar::onClickCommunicate(LLUICtrl* ctrl, const LLSD& user_data)
}
else if (selected_option.asString() == "mute list")
{
LLFloaterReg::showInstance("mute");
LLPanelBlockedList::showPanelAndSelect(LLUUID::null);
}
else if (selected_option.isUndefined()) // user just clicked the communicate button, treat as toggle
{

View File

@ -78,7 +78,6 @@
#include "llfloaterlandholdings.h"
#include "llfloatermap.h"
#include "llfloatermemleak.h"
#include "llfloatermute.h"
#include "llfloaternamedesc.h"
#include "llfloaternotificationsconsole.h"
#include "llfloateropenobject.h"
@ -110,6 +109,7 @@
#include "llmediaremotectrl.h"
#include "llmoveview.h"
#include "llnearbychat.h"
#include "llpanelblockedlist.h"
#include "llpreviewanim.h"
#include "llpreviewgesture.h"
#include "llpreviewnotecard.h"
@ -177,8 +177,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("message_critical", "floater_critical.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTOS>);
LLFloaterReg::add("message_tos", "floater_tos.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTOS>);
LLFloaterReg::add("moveview", "floater_moveview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMove>);
LLFloaterReg::add("mute", "floater_mute.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMute>);
LLFloaterReg::add("mute_object", "floater_mute_object.xml", &LLFloaterMute::buildFloaterMuteObjectUI);
LLFloaterReg::add("mute_object_by_name", "floater_mute_object.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGetBlockedObjectName>);
LLFloaterReg::add("mini_map", "floater_map.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMap>);
LLFloaterReg::add("syswell_window", "floater_sys_well.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLSysWellWindow>);

View File

@ -120,6 +120,41 @@ LLViewerInventoryItem::~LLViewerInventoryItem()
{
}
BOOL LLViewerInventoryItem::extractSortFieldAndDisplayName(S32* sortField, std::string* displayName) const
{
using std::string;
using std::stringstream;
const char separator = getSeparator();
const string::size_type separatorPos = mName.find(separator, 0);
BOOL result = FALSE;
if (separatorPos < string::npos)
{
if (sortField)
{
/*
* The conversion from string to S32 is made this way instead of old plain
* atoi() to ensure portability. If on some other platform S32 will not be
* defined to be signed int, this conversion will still work because of
* operators overloading, but atoi() may fail.
*/
stringstream ss(mName.substr(0, separatorPos));
ss >> *sortField;
}
if (displayName)
{
*displayName = mName.substr(separatorPos + 1, string::npos);
}
result = TRUE;
}
return result;
}
void LLViewerInventoryItem::copyViewerItem(const LLViewerInventoryItem* other)
{
LLInventoryItem::copyItem(other);
@ -1102,7 +1137,70 @@ const std::string& LLViewerInventoryItem::getName() const
return linked_category->getName();
}
return LLInventoryItem::getName();
return getDisplayName();
}
const std::string& LLViewerInventoryItem::getDisplayName() const
{
std::string result;
BOOL hasSortField = extractSortFieldAndDisplayName(0, &result);
return mDisplayName = hasSortField ? result : LLInventoryItem::getName();
}
S32 LLViewerInventoryItem::getSortField() const
{
S32 result;
BOOL hasSortField = extractSortFieldAndDisplayName(&result, 0);
return hasSortField ? result : -1;
}
void LLViewerInventoryItem::setSortField(S32 sortField)
{
using std::string;
std::stringstream ss;
ss << sortField;
string newSortField = ss.str();
const char separator = getSeparator();
const string::size_type separatorPos = mName.find(separator, 0);
if (separatorPos < string::npos)
{
// the name of the LLViewerInventoryItem already consists of sort field and display name.
mName = newSortField + separator + mName.substr(separatorPos + 1, string::npos);
}
else
{
// there is no sort field in the name of LLViewerInventoryItem, we should add it
mName = newSortField + separator + mName;
}
}
void LLViewerInventoryItem::rename(const std::string& n)
{
using std::string;
string new_name(n);
LLStringUtil::replaceNonstandardASCII(new_name, ' ');
LLStringUtil::replaceChar(new_name, '|', ' ');
LLStringUtil::trim(new_name);
LLStringUtil::truncate(new_name, DB_INV_ITEM_NAME_STR_LEN);
const char separator = getSeparator();
const string::size_type separatorPos = mName.find(separator, 0);
if (separatorPos < string::npos)
{
mName.replace(separatorPos + 1, string::npos, new_name);
}
else
{
mName = new_name;
}
}
const LLPermissions& LLViewerInventoryItem::getPermissions() const

View File

@ -55,11 +55,18 @@ public:
protected:
~LLViewerInventoryItem( void ); // ref counted
BOOL extractSortFieldAndDisplayName(S32* sortField, std::string* displayName) const;
static char getSeparator() { return '@'; }
mutable std::string mDisplayName;
public:
virtual LLAssetType::EType getType() const;
virtual const LLUUID& getAssetUUID() const;
virtual const std::string& getName() const;
virtual const std::string& getDisplayName() const;
virtual S32 getSortField() const;
virtual void setSortField(S32 sortField);
virtual void rename(const std::string& new_name);
virtual const LLPermissions& getPermissions() const;
virtual const LLUUID& getCreatorUUID() const;
virtual const std::string& getDescription() const;

View File

@ -113,7 +113,6 @@
#include "llfloaterland.h"
#include "llfloaterlandholdings.h"
#include "llfloatermap.h"
#include "llfloatermute.h"
#include "llfloateropenobject.h"
#include "llfloaterperms.h"
#include "llfloaterpostprocess.h"
@ -147,6 +146,7 @@
#include "llfloaterinventory.h"
#include "llkeyboard.h"
#include "llpanellogin.h"
#include "llpanelblockedlist.h"
#include "llmenucommands.h"
#include "llmenugl.h"
#include "llmimetypes.h"
@ -2896,7 +2896,7 @@ class LLObjectMute : public view_listener_t
else
{
LLMuteList::getInstance()->add(mute);
LLFloaterReg::showInstance("mute");
LLPanelBlockedList::showPanelAndSelect(mute.mID);
}
return true;

View File

@ -82,7 +82,6 @@
#include "llfloaterregioninfo.h"
#include "llfloaterlandholdings.h"
#include "llurldispatcher.h"
#include "llfloatermute.h"
#include "llfloaterpostcard.h"
#include "llfloaterpreference.h"
#include "llfollowcam.h"
@ -138,6 +137,7 @@
#include "llgroupactions.h"
#include "llagentui.h"
#include "llsidetray.h"
#include "llpanelblockedlist.h"
#include "llpanelplaceinfo.h"
#include <boost/tokenizer.hpp>
@ -1001,9 +1001,7 @@ void inventory_offer_mute_callback(const LLUUID& blocked_id,
LLMute mute(blocked_id, from_name, type);
if (LLMuteList::getInstance()->add(mute))
{
LLFloaterReg::showInstance("mute");
LLFloaterMute* mute_instance = LLFloaterReg::getTypedInstance<LLFloaterMute>("mute");
if(mute_instance) mute_instance->selectMute(blocked_id);
LLPanelBlockedList::showPanelAndSelect(blocked_id);
}
// purge the message queue of any previously queued inventory offers from the same source.
@ -5576,7 +5574,7 @@ void process_covenant_reply(LLMessageSystem* msg, void**)
LLPanelLandCovenant::updateEstateName(estate_name);
LLFloaterBuyLand::updateEstateName(estate_name);
LLPanelPlaceInfo* panel = dynamic_cast<LLPanelPlaceInfo*>(LLSideTray::getInstance()->showPanel("panel_place_info", LLSD()));
LLPanelPlaceInfo* panel = LLSideTray::getInstance()->findChild<LLPanelPlaceInfo>("panel_place_info");
if (panel)
{
panel->updateEstateName(estate_name);
@ -5660,7 +5658,7 @@ void callbackCacheEstateOwnerName(const LLUUID& id,
LLPanelLandCovenant::updateEstateOwnerName(name);
LLFloaterBuyLand::updateEstateOwnerName(name);
LLPanelPlaceInfo* panel = dynamic_cast<LLPanelPlaceInfo*>(LLSideTray::getInstance()->showPanel("panel_place_info", LLSD()));
LLPanelPlaceInfo* panel = LLSideTray::getInstance()->findChild<LLPanelPlaceInfo>("panel_place_info");
if (panel)
{
panel->updateEstateOwnerName(name);

View File

@ -1596,8 +1596,6 @@ void LLViewerWindow::initWorldUI()
gFloaterView->setRect(floater_view_rect);
gNotifyBoxView->setRect(notify_view_rect);
// *Note: this is where gFloaterMute used to be initialized.
LLWorldMapView::initClass();
// Force gFloaterWorldMap to initialize
@ -1636,6 +1634,11 @@ void LLViewerWindow::initWorldUI()
navbar->showFavoritesPanel(FALSE);
}
if (!gSavedSettings.getBOOL("ShowCameraAndMoveControls"))
{
LLBottomTray::getInstance()->showCameraAndMoveControls(FALSE);
}
getRootView()->addChild(gStatusBar);
getRootView()->addChild(navbar);
@ -1668,6 +1671,9 @@ void LLViewerWindow::initWorldUI()
// put behind everything else in the UI
getRootView()->addChildInBack(gHUDView);
}
// this allows not to see UI elements created while UI initializing after Alt+Tab was pressed during login. EXT-744.
moveProgressViewToFront();
}
// Destroy the UI
@ -4417,8 +4423,7 @@ void LLViewerWindow::moveProgressViewToFront()
{
if( mProgressView && mRootView )
{
mRootView->removeChild( mProgressView );
mRootView->addChild( mProgressView );
mRootView->sendChildToFront(mProgressView);
}
}

View File

@ -93,6 +93,7 @@
<texture name="Info_Press" file_name="navbar/Info_Press.png" preload="false"/>
<texture name="ListItem_Select" file_name="widgets/ListItem_Select.png" preload="true" />
<texture name="ListItem_Over" file_name="widgets/ListItem_Over.png" preload="true" />
<texture name="menu_separator" file_name="navbar/FileMenu_Divider.png" scale.left="4" scale.top="166" scale.right="0" scale.bottom="0" />

View File

@ -15,4 +15,8 @@
<menu_item_call name="organize_offline" label="Organize Offline Friends">
<menu_item_call.on_click function="People.Friends.ViewSort.Action" userdata="organize_offline" />
</menu_item_call>
<menu_item_separator layout="topleft" />
<menu_item_call name="show_blocked_list" label="Show Blocked Residents &amp; Objects">
<menu_item_call.on_click function="SideTray.ShowPanel" parameter="panel_block_list_sidetray" />
</menu_item_call>
</menu>

View File

@ -15,4 +15,8 @@
<menu_item_call name="view_icons" label="View People Icons">
<menu_item_call.on_click function="People.Nearby.ViewSort.Action" userdata="view_icons" />
</menu_item_call>
<menu_item_separator layout="topleft" />
<menu_item_call name="show_blocked_list" label="Show Blocked Residents &amp; Objects">
<menu_item_call.on_click function="SideTray.ShowPanel" userdata="panel_block_list_sidetray" />
</menu_item_call>
</menu>

View File

@ -12,4 +12,8 @@
<menu_item_call name="view_icons" label="View People Icons">
<menu_item_call.on_click function="People.Recent.ViewSort.Action" userdata="view_icons" />
</menu_item_call>
<menu_item_separator layout="topleft" />
<menu_item_call name="show_blocked_list" label="Show Blocked Residents &amp; Objects">
<menu_item_call.on_click function="SideTray.ShowPanel" userdata="panel_block_list_sidetray" />
</menu_item_call>
</menu>

View File

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
background_visible="true"
follows="left|top|right|bottom"
height="305"
layout="topleft"
name="block_list_panel"
min_height="350"
min_width="240"
width="280">
<text
follows="top|left|right"
font="SansSerifHugeBold"
height="20"
layout="topleft"
left="10"
name="title_text"
text_color="white"
top="0"
width="250">
Blocked List
</text>
<button
follows="top|right"
height="25"
image_overlay="BackArrow_Off"
layout="topleft"
name="back"
right="-9"
tab_stop="false"
top="0"
width="25"/>
<scroll_list
follows="left|top|right|bottom"
height="200"
layout="topleft"
left="5"
name="blocked"
tool_tip="List of currently blocked residents"
top="30"
width="270" />
<button
follows="left|bottom"
height="20"
label="Block Resident..."
label_selected="Block Resident..."
layout="topleft"
left_delta="0"
name="Block resident..."
tool_tip="Pick a resident to block"
top_pad="4"
width="210">
<button.commit_callback
function="Block.ClickPick" />
</button>
<button
follows="left|bottom"
height="20"
label="Block object by name..."
label_selected="Block object by name..."
layout="topleft"
left_delta="0"
name="Block object by name..."
top_pad="4"
width="210" >
<button.commit_callback
function="Block.ClickBlockByName" />
</button>
<button
enabled="false"
follows="left|bottom"
height="20"
label="Unblock"
label_selected="Unblock"
layout="topleft"
left_delta="0"
name="Unblock"
tool_tip="Remove resident or object from blocked list"
top_pad="4"
width="210" >
<button.commit_callback
function="Block.ClickRemove" />
</button>
</panel>

View File

@ -266,7 +266,7 @@
top="2"
width="48">
<button
image_selected="bottom_tray_sys_notifications.tga"
image_selected="bottom_tray_sys_notifications_selected.tga"
image_unselected="bottom_tray_sys_notifications.tga"/>
<unread_notifications
width="20"

View File

@ -12,11 +12,45 @@
name="edit_profile_panel"
top="10"
width="255">
<string
name="CaptionTextAcctInfo">
[ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION]
</string>
<string
name="AcctTypeResident"
value="Resident" />
<string
name="AcctTypeTrial"
value="Trial" />
<string
name="AcctTypeCharterMember"
value="Charter Member" />
<string
name="AcctTypeEmployee"
value="Linden Lab Employee" />
<string
name="PaymentInfoUsed"
value="Payment Info Used" />
<string
name="PaymentInfoOnFile"
value="Payment Info On File" />
<string
name="NoPaymentInfoOnFile"
value="No Payment Info On File" />
<string
name="AgeVerified"
value="Age-verified" />
<string
name="NotAgeVerified"
value="Not Age-verified" />
<string
name="partner_edit_link_url">
http://www.secondlife.com/account/partners.php?lang=en
</string>
<scroll_container
<string
name="no_partner_text"
value="None" />
<scroll_container
color="DkGray2"
follows="left|top|right|bottom"
height="300"
@ -38,7 +72,7 @@
background_visible="true"
bg_alpha_color="DkGray2"
follows="left|top|right|bottom"
height="620"
height="750"
layout="topleft"
left="0"
name="data_panel"

View File

@ -1,8 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel background_visible="true" bevel_style="in" bg_alpha_color="0 0 0 0"
height="200" label="instant_message" layout="topleft" left="0"
height="155" label="instant_message" layout="topleft" left="0"
name="panel_group_notify" top="0" width="350">
<panel background_visible="true" bevel_style="in" bg_alpha_color="black"
<string
name="message_max_lines_count">
4
</string>
<panel follows="top" background_visible="true" bevel_style="in" bg_alpha_color="black"
height="50" label="header" layout="topleft" left="0" name="header"
top="0" width="350">
<icon follows="left|top|right|bottom" height="40" width="40" layout="topleft"
@ -13,21 +17,61 @@
Sender Name / Group Name
</text>
</panel>
<text_editor type="string" length="1" bg_readonly_color="0 0 0 0"
follows="left|top|right|bottom" height="70" hide_scrollbar="true"
hide_border="true" layout="topleft" top="55" left="25" name="message"
text_color="GroupNotifyTextColor" text_readonly_color="GroupNotifyTextColor" width="300" word_wrap="true">
Message
Body
</text_editor>
<icon follows="left|top|right|bottom" height="16" width="16"
layout="topleft" top="135" left="25" mouse_opaque="true" name="attachment_icon" />
<text
follows="top"
height="20"
layout="topleft"
left="25"
name="subject"
text_color="GroupNotifyTextColor"
font="SansSerifBig"
top="60"
use_ellipses="true"
value="subject"
width="300"
word_wrap="true">
subject
</text>
<text
follows="top"
height="20"
layout="topleft"
left="25"
name="datetime"
text_color="GroupNotifyTextColor"
font="SansSerif"
top="80"
use_ellipses="true"
value="datetime"
width="300"
word_wrap="true">
datetime
</text>
<text
follows="left|top|bottom|right"
height="0"
layout="topleft"
left="25"
name="message"
text_color="GroupNotifyTextColor"
top="100"
use_ellipses="true"
value="message"
width="300"
word_wrap="true"
visible="true" >
</text>
<icon
follows="left|bottom|right" height="15" width="15"
layout="topleft" bottom="122" left="25" mouse_opaque="true" name="attachment_icon" visible="true"
/>
<text font="SansSerif" font.style="UNDERLINE" font_shadow="hard"
type="string" length="1" follows="left|top|right|bottom" layout="topleft"
left="45" top="135" height="15" width="280" name="attachment"
text_color="GroupNotifyTextColor">
type="string" length="1" follows="left|bottom|right" layout="topleft"
left="45" bottom="122" height="15" width="280" name="attachment"
text_color="GroupNotifyTextColor" visible="true">
Attachment
</text>
<button label="OK" layout="topleft" top="170" left="140" height="20"
width="70" name="btn_ok" />
</panel>
</text>
<button label="OK" layout="topleft" bottom="145" left="140" height="20"
width="70" name="btn_ok" follows="bottom" />
</panel>

View File

@ -10,6 +10,10 @@
name="im_panel"
top="0"
width="350">
<string
name="message_max_lines_count">
6
</string>
<panel
background_visible="true"
bevel_style="in"
@ -56,7 +60,7 @@
width="50" />
</panel>
<text
follows="left|bottom|right"
follows="left|top|bottom|right"
height="60"
layout="topleft"
left="10"

View File

@ -107,8 +107,8 @@
<!-- picture_style="true" -->
<!-- top_delta="0" -->
<!-- width="168" /> -->
<search_editor
<search_combo_box
bevel_style="none"
border_style="line"
border.border_thickness="0"
@ -118,12 +118,15 @@
height="22"
label="Search"
layout="topleft"
left_pad="7"
right="-10"
mouse_opaque="false"
name="search_input"
name="search_combo_box"
tool_tip="Search"
top_delta="0"
width="200" />
width="200" >
<combo_editor
label="Search" />
</search_combo_box>
</panel>
<favorites_bar

View File

@ -8,6 +8,26 @@
name="picture_item"
top="0"
width="275">
<icon
height="120"
image_name="ListItem_Over"
left="0"
mouse_opaque="false"
name="hovered_icon"
top="0"
scale_image="true"
visible="false"
width="270"/>
<icon
height="120"
image_name="ListItem_Select"
left="0"
mouse_opaque="false"
name="selected_icon"
top="0"
scale_image="true"
visible="false"
width="270"/>
<texture_picker
allow_no_texture="true"
default_image_name="None"

View File

@ -57,6 +57,13 @@
label="Group Info"
border="true"
/>
<panel
class="panel_block_list_sidetray"
name="panel_block_list_sidetray"
filename="panel_block_list_sidetray.xml"
label="Blocked Residents &amp; Objects"
border="true"
/>
</panel_container>
</sidetray_tab>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<accordion_tab
header_collapse_img="accordion_collapsed.tga"
header_collapse_img_pressed="accordion_collapsed.tga"
header_expand_img="accordion_expanded.tga"
header_expand_img_pressed="accordion_expanded.tga" />

View File

@ -6,4 +6,5 @@
background_visible="false"
background_opaque="false"
item_pad="5"
keep_one_selected="true"
multi_select="false" />

View File

@ -43,7 +43,7 @@
label=""
pad_right="0"
tool_tip="My Location History"/>
<combo_list bg_writeable_color="MenuDefaultBgColor"/>
<combo_list bg_writeable_color="MenuDefaultBgColor" page_lines="10"/>
<combo_editor name="Combo Text Entry"
text_pad_left="20"
select_on_focus="false"

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<search_combo_box
allow_text_entry="true"
list_position="BELOW"
show_text_as_tentative="false"
dropdown_button_visible="false"
background_image="TextField_Search_Off"
background_image_disabled="TextField_Search_Disabled"
background_image_focused="TextField_Search_Active">
<combo_editor
select_on_focus="true"
text_pad_left="20"
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" />
<search_button label=""
top_pad="4"
left_pad="4"
width="13"
height="13"
image_unselected="Search"
image_selected="Search" />
</search_combo_box>