summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/llcommon/llfoldertype.cpp2
-rw-r--r--indra/llcommon/llfoldertype.h5
-rw-r--r--indra/llplugin/llpluginclassmedia.cpp2860
-rw-r--r--indra/llplugin/llpluginclassmedia.h851
-rw-r--r--indra/llui/CMakeLists.txt20
-rw-r--r--indra/llui/llaccordionctrltab.cpp2
-rw-r--r--indra/llui/llbadge.cpp274
-rw-r--r--indra/llui/llbadge.h159
-rw-r--r--indra/llui/llbadgeowner.cpp126
-rw-r--r--indra/llui/llbadgeowner.h61
-rw-r--r--indra/llui/llbutton.cpp71
-rw-r--r--indra/llui/llbutton.h16
-rw-r--r--indra/llui/lllayoutstack.cpp138
-rw-r--r--indra/llui/lllayoutstack.h36
-rw-r--r--indra/llui/llloadingindicator.h2
-rw-r--r--indra/llui/llpanel.cpp8
-rw-r--r--indra/llui/llpanel.h5
-rw-r--r--indra/llui/lluictrl.cpp36
-rw-r--r--indra/llui/lluictrl.h8
-rw-r--r--indra/llui/llview.cpp15
-rw-r--r--indra/llui/tests/llurlmatch_test.cpp2
-rw-r--r--indra/llxuixml/llinitparam.cpp2
-rw-r--r--indra/llxuixml/llinitparam.h7
-rw-r--r--indra/media_plugins/webkit/media_plugin_webkit.cpp36
-rw-r--r--indra/newview/CMakeLists.txt8
-rw-r--r--indra/newview/app_settings/keys.xml2
-rw-r--r--indra/newview/app_settings/settings.xml98
-rw-r--r--indra/newview/app_settings/settings_minimal.xml13
-rw-r--r--indra/newview/llagentwearables.cpp2
-rwxr-xr-xindra/newview/llavataractions.cpp69
-rw-r--r--indra/newview/llavataractions.h3
-rw-r--r--indra/newview/llfilteredwearablelist.cpp1
-rw-r--r--indra/newview/llfloaterhelpbrowser.cpp9
-rw-r--r--indra/newview/llfloaterhelpbrowser.h1
-rw-r--r--indra/newview/llfloaterwebcontent.cpp18
-rw-r--r--indra/newview/llfloaterwebcontent.h2
-rw-r--r--indra/newview/llfolderview.cpp96
-rw-r--r--indra/newview/llfolderview.h26
-rw-r--r--indra/newview/llfolderviewitem.cpp202
-rw-r--r--indra/newview/llfolderviewitem.h36
-rw-r--r--indra/newview/llinventorybridge.cpp48
-rw-r--r--indra/newview/llinventorybridge.h4
-rw-r--r--indra/newview/llinventoryfilter.cpp123
-rw-r--r--indra/newview/llinventoryfilter.h6
-rw-r--r--indra/newview/llinventoryfunctions.h24
-rw-r--r--indra/newview/llinventorymodel.cpp2
-rw-r--r--indra/newview/llinventorymodelbackgroundfetch.cpp2
-rw-r--r--indra/newview/llinventoryobserver.cpp28
-rw-r--r--indra/newview/llinventoryobserver.h22
-rw-r--r--indra/newview/llinventorypanel.cpp477
-rw-r--r--indra/newview/llinventorypanel.h50
-rw-r--r--indra/newview/llmediactrl.cpp18
-rw-r--r--indra/newview/lloutfitslist.cpp2
-rw-r--r--indra/newview/llpanelappearancetab.cpp1
-rw-r--r--indra/newview/llpanelimcontrolpanel.cpp95
-rw-r--r--indra/newview/llpanelimcontrolpanel.h8
-rw-r--r--indra/newview/llpanellandmarks.cpp7
-rw-r--r--indra/newview/llpanelmaininventory.cpp32
-rw-r--r--indra/newview/llpanelmaininventory.h4
-rw-r--r--indra/newview/llpanelmarketplaceinbox.cpp248
-rw-r--r--indra/newview/llpanelmarketplaceinbox.h78
-rw-r--r--indra/newview/llpanelmarketplaceinboxinventory.cpp167
-rw-r--r--indra/newview/llpanelmarketplaceinboxinventory.h77
-rw-r--r--indra/newview/llpanelmarketplaceoutbox.cpp209
-rw-r--r--indra/newview/llpanelmarketplaceoutbox.h82
-rw-r--r--indra/newview/llpanelobjectinventory.cpp62
-rw-r--r--indra/newview/llpaneloutfitedit.cpp2
-rw-r--r--indra/newview/llpanelwearing.cpp2
-rw-r--r--indra/newview/llplacesinventorypanel.cpp85
-rw-r--r--indra/newview/llplacesinventorypanel.h2
-rw-r--r--indra/newview/llpreviewgesture.cpp1
-rw-r--r--indra/newview/llprogressview.cpp88
-rw-r--r--indra/newview/llprogressview.h20
-rw-r--r--indra/newview/llsidepanelappearance.cpp1
-rw-r--r--indra/newview/llsidepanelinventory.cpp454
-rw-r--r--indra/newview/llsidepanelinventory.h31
-rw-r--r--indra/newview/llsidepanelinventorysubpanel.cpp4
-rw-r--r--indra/newview/llsidepanelinventorysubpanel.h2
-rw-r--r--indra/newview/llsidepaneliteminfo.cpp7
-rw-r--r--indra/newview/llsidepaneliteminfo.h2
-rw-r--r--indra/newview/llsidetray.cpp177
-rw-r--r--indra/newview/llsidetray.h13
-rw-r--r--indra/newview/llstartup.cpp15
-rw-r--r--indra/newview/lltexturectrl.cpp1
-rw-r--r--indra/newview/llviewerfoldertype.cpp4
-rw-r--r--indra/newview/llviewerhelp.cpp16
-rw-r--r--indra/newview/llviewerinventory.cpp2
-rw-r--r--indra/newview/llviewermedia.cpp62
-rw-r--r--indra/newview/llviewermenu.cpp1
-rw-r--r--indra/newview/llviewermessage.cpp117
-rw-r--r--indra/newview/llviewermessage.h2
-rw-r--r--indra/newview/llviewerprecompiledheaders.h6
-rw-r--r--indra/newview/llviewerwindow.cpp11
-rw-r--r--indra/newview/llviewerwindow.h1
-rw-r--r--indra/newview/skins/default/colors.xml11
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Gift.pngbin0 -> 1335 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OutboxPush_Disabled.pngbin0 -> 1848 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OutboxPush_Off.pngbin0 -> 1835 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OutboxPush_On.pngbin0 -> 1851 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OutboxPush_On_Over.pngbin0 -> 1863 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OutboxPush_On_Selected.pngbin0 -> 1912 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OutboxPush_Over.pngbin0 -> 1826 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OutboxPush_Press.pngbin0 -> 1891 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OutboxPush_Progress_1.pngbin0 -> 1848 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OutboxPush_Progress_2.pngbin0 -> 1807 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OutboxPush_Progress_3.pngbin0 -> 1819 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OutboxPush_Progress_4.pngbin0 -> 1894 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OutboxPush_Progress_5.pngbin0 -> 1921 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OutboxPush_Progress_6.pngbin0 -> 1853 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OutboxPush_Selected.pngbin0 -> 1894 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OutboxPush_Selected_Disabled.pngbin0 -> 1840 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OutboxPush_Selected_Over.pngbin0 -> 1870 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/OutboxPush_Selected_Press.pngbin0 -> 1912 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Sync_Disabled.pngbin0 -> 1187 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Sync_Enabled.pngbin0 -> 1168 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Sync_Progress_1.pngbin0 -> 1149 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Sync_Progress_2.pngbin0 -> 1147 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Sync_Progress_3.pngbin0 -> 1211 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Sync_Progress_4.pngbin0 -> 1205 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Sync_Progress_5.pngbin0 -> 1137 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Sync_Progress_6.pngbin0 -> 1164 bytes
-rw-r--r--indra/newview/skins/default/textures/textures.xml35
-rw-r--r--indra/newview/skins/default/textures/widgets/Badge_Background.pngbin0 -> 1352 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/Badge_Border.pngbin0 -> 1565 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/MarketplaceBtn_Off.pngbin0 -> 1067 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/MarketplaceBtn_Selected.pngbin0 -> 1086 bytes
-rw-r--r--indra/newview/skins/default/xui/en/floater_help_browser.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_media_browser.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_web_content.xml11
-rw-r--r--indra/newview/skins/default/xui/en/menu_inventory_add.xml4
-rw-r--r--indra/newview/skins/default/xui/en/panel_inbox_inventory.xml17
-rw-r--r--indra/newview/skins/default/xui/en/panel_outbox_inventory.xml17
-rw-r--r--indra/newview/skins/default/xui/en/panel_progress.xml8
-rw-r--r--indra/newview/skins/default/xui/en/panel_side_tray.xml1
-rw-r--r--indra/newview/skins/default/xui/en/sidepanel_inventory.xml230
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml2
-rw-r--r--indra/newview/skins/default/xui/en/widgets/badge.xml17
-rw-r--r--indra/newview/skins/default/xui/en/widgets/button.xml1
-rw-r--r--indra/newview/skins/default/xui/en/widgets/inbox_folder_view_folder.xml10
-rw-r--r--indra/newview/skins/default/xui/en/widgets/inbox_inventory_panel.xml2
-rw-r--r--indra/newview/skins/default/xui/en/widgets/inventory_panel.xml10
-rw-r--r--indra/newview/skins/default/xui/en/widgets/panel.xml3
-rw-r--r--indra/newview/skins/minimal/xui/en/floater_help_browser.xml11
-rw-r--r--indra/newview/skins/minimal/xui/en/floater_web_content.xml11
-rw-r--r--indra/newview/skins/minimal/xui/en/panel_im_control_panel.xml242
145 files changed, 6116 insertions, 2864 deletions
diff --git a/indra/llcommon/llfoldertype.cpp b/indra/llcommon/llfoldertype.cpp
index c2cfb7286e..f6d0f5bce8 100644
--- a/indra/llcommon/llfoldertype.cpp
+++ b/indra/llcommon/llfoldertype.cpp
@@ -93,6 +93,8 @@ LLFolderDictionary::LLFolderDictionary()
addEntry(LLFolderType::FT_MESH, new FolderEntry("mesh", TRUE));
addEntry(LLFolderType::FT_INBOX, new FolderEntry("inbox", TRUE));
+ addEntry(LLFolderType::FT_OUTBOX, new FolderEntry("outbox", TRUE));
+ addEntry(LLFolderType::FT_BASIC_ROOT, new FolderEntry("basic_rt", TRUE));
addEntry(LLFolderType::FT_NONE, new FolderEntry("-1", FALSE));
};
diff --git a/indra/llcommon/llfoldertype.h b/indra/llcommon/llfoldertype.h
index cb32cb075b..a0c847914f 100644
--- a/indra/llcommon/llfoldertype.h
+++ b/indra/llcommon/llfoldertype.h
@@ -83,8 +83,11 @@ public:
FT_MESH = 49,
FT_INBOX = 50,
+ FT_OUTBOX = 51,
- FT_COUNT = 51,
+ FT_BASIC_ROOT = 52,
+
+ FT_COUNT,
FT_NONE = -1
};
diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp
index 9f666369d4..d3d0403bbb 100644
--- a/indra/llplugin/llpluginclassmedia.cpp
+++ b/indra/llplugin/llpluginclassmedia.cpp
@@ -1,1436 +1,1424 @@
-/**
- * @file llpluginclassmedia.cpp
- * @brief LLPluginClassMedia handles a plugin which knows about the "media" message class.
- *
- * @cond
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- * @endcond
- */
-
-#include "linden_common.h"
-#include "indra_constants.h"
-
-#include "llpluginclassmedia.h"
-#include "llpluginmessageclasses.h"
-
-#include "llqtwebkit.h"
-
-static int LOW_PRIORITY_TEXTURE_SIZE_DEFAULT = 256;
-
-static int nextPowerOf2( int value )
-{
- int next_power_of_2 = 1;
- while ( next_power_of_2 < value )
- {
- next_power_of_2 <<= 1;
- }
-
- return next_power_of_2;
-}
-
-LLPluginClassMedia::LLPluginClassMedia(LLPluginClassMediaOwner *owner)
-{
- mOwner = owner;
- mPlugin = NULL;
- reset();
-
- //debug use
- mDeleteOK = true ;
-}
-
-
-LLPluginClassMedia::~LLPluginClassMedia()
-{
- llassert_always(mDeleteOK) ;
- reset();
-}
-
-bool LLPluginClassMedia::init(const std::string &launcher_filename, const std::string &plugin_dir, const std::string &plugin_filename, bool debug)
-{
- LL_DEBUGS("Plugin") << "launcher: " << launcher_filename << LL_ENDL;
- LL_DEBUGS("Plugin") << "dir: " << plugin_dir << LL_ENDL;
- LL_DEBUGS("Plugin") << "plugin: " << plugin_filename << LL_ENDL;
-
- mPlugin = new LLPluginProcessParent(this);
- mPlugin->setSleepTime(mSleepTime);
-
- // Queue up the media init message -- it will be sent after all the currently queued messages.
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "init");
- message.setValue("target", mTarget);
- sendMessage(message);
-
- mPlugin->init(launcher_filename, plugin_dir, plugin_filename, debug);
-
- return true;
-}
-
-
-void LLPluginClassMedia::reset()
-{
- if(mPlugin != NULL)
- {
- delete mPlugin;
- mPlugin = NULL;
- }
-
- mTextureParamsReceived = false;
- mRequestedTextureDepth = 0;
- mRequestedTextureInternalFormat = 0;
- mRequestedTextureFormat = 0;
- mRequestedTextureType = 0;
- mRequestedTextureSwapBytes = false;
- mRequestedTextureCoordsOpenGL = false;
- mTextureSharedMemorySize = 0;
- mTextureSharedMemoryName.clear();
- mDefaultMediaWidth = 0;
- mDefaultMediaHeight = 0;
- mNaturalMediaWidth = 0;
- mNaturalMediaHeight = 0;
- mSetMediaWidth = -1;
- mSetMediaHeight = -1;
- mRequestedMediaWidth = 0;
- mRequestedMediaHeight = 0;
- mRequestedTextureWidth = 0;
- mRequestedTextureHeight = 0;
- mFullMediaWidth = 0;
- mFullMediaHeight = 0;
- mTextureWidth = 0;
- mTextureHeight = 0;
- mMediaWidth = 0;
- mMediaHeight = 0;
- mDirtyRect = LLRect::null;
- mAutoScaleMedia = false;
- mRequestedVolume = 1.0f;
- mPriority = PRIORITY_NORMAL;
- mLowPrioritySizeLimit = LOW_PRIORITY_TEXTURE_SIZE_DEFAULT;
- mAllowDownsample = false;
- mPadding = 0;
- mLastMouseX = 0;
- mLastMouseY = 0;
- mStatus = LLPluginClassMediaOwner::MEDIA_NONE;
- mSleepTime = 1.0f / 100.0f;
- mCanCut = false;
- mCanCopy = false;
- mCanPaste = false;
- mMediaName.clear();
- mMediaDescription.clear();
- mBackgroundColor = LLColor4(1.0f, 1.0f, 1.0f, 1.0f);
-
- // media_browser class
- mNavigateURI.clear();
- mNavigateResultCode = -1;
- mNavigateResultString.clear();
- mHistoryBackAvailable = false;
- mHistoryForwardAvailable = false;
- mStatusText.clear();
- mProgressPercent = 0;
- mClickURL.clear();
- mClickNavType.clear();
- mClickTarget.clear();
- mClickUUID.clear();
- mStatusCode = 0;
-
- // media_time class
- mCurrentTime = 0.0f;
- mDuration = 0.0f;
- mCurrentRate = 0.0f;
- mLoadedDuration = 0.0f;
-}
-
-void LLPluginClassMedia::idle(void)
-{
- if(mPlugin)
- {
- mPlugin->idle();
- }
-
- if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL) || (mPlugin->isBlocked()) || (mOwner == NULL))
- {
- // Can't process a size change at this time
- }
- else if((mRequestedMediaWidth != mMediaWidth) || (mRequestedMediaHeight != mMediaHeight))
- {
- // Calculate the correct size for the media texture
- mRequestedTextureHeight = mRequestedMediaHeight;
- if(mPadding < 0)
- {
- // negative values indicate the plugin wants a power of 2
- mRequestedTextureWidth = nextPowerOf2(mRequestedMediaWidth);
- }
- else
- {
- mRequestedTextureWidth = mRequestedMediaWidth;
-
- if(mPadding > 1)
- {
- // Pad up to a multiple of the specified number of bytes per row
- int rowbytes = mRequestedTextureWidth * mRequestedTextureDepth;
- int pad = rowbytes % mPadding;
- if(pad != 0)
- {
- rowbytes += mPadding - pad;
- }
-
- if(rowbytes % mRequestedTextureDepth == 0)
- {
- mRequestedTextureWidth = rowbytes / mRequestedTextureDepth;
- }
- else
- {
- LL_WARNS("Plugin") << "Unable to pad texture width, padding size " << mPadding << "is not a multiple of pixel size " << mRequestedTextureDepth << LL_ENDL;
- }
- }
- }
-
-
- // Size change has been requested but not initiated yet.
- size_t newsize = mRequestedTextureWidth * mRequestedTextureHeight * mRequestedTextureDepth;
-
- // Add an extra line for padding, just in case.
- newsize += mRequestedTextureWidth * mRequestedTextureDepth;
-
- if(newsize != mTextureSharedMemorySize)
- {
- if(!mTextureSharedMemoryName.empty())
- {
- // Tell the plugin to remove the old memory segment
- mPlugin->removeSharedMemory(mTextureSharedMemoryName);
- mTextureSharedMemoryName.clear();
- }
-
- mTextureSharedMemorySize = newsize;
- mTextureSharedMemoryName = mPlugin->addSharedMemory(mTextureSharedMemorySize);
- if(!mTextureSharedMemoryName.empty())
- {
- void *addr = mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName);
-
- // clear texture memory to avoid random screen visual fuzz from uninitialized texture data
- memset( addr, 0x00, newsize );
-
- // We could do this to force an update, but textureValid() will still be returning false until the first roundtrip to the plugin,
- // so it may not be worthwhile.
- // mDirtyRect.setOriginAndSize(0, 0, mRequestedMediaWidth, mRequestedMediaHeight);
- }
- }
-
- // This is our local indicator that a change is in progress.
- mTextureWidth = -1;
- mTextureHeight = -1;
- mMediaWidth = -1;
- mMediaHeight = -1;
-
- // This invalidates any existing dirty rect.
- resetDirty();
-
- // Send a size change message to the plugin
- {
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change");
- message.setValue("name", mTextureSharedMemoryName);
- message.setValueS32("width", mRequestedMediaWidth);
- message.setValueS32("height", mRequestedMediaHeight);
- message.setValueS32("texture_width", mRequestedTextureWidth);
- message.setValueS32("texture_height", mRequestedTextureHeight);
- message.setValueReal("background_r", mBackgroundColor.mV[VX]);
- message.setValueReal("background_g", mBackgroundColor.mV[VY]);
- message.setValueReal("background_b", mBackgroundColor.mV[VZ]);
- message.setValueReal("background_a", mBackgroundColor.mV[VW]);
- mPlugin->sendMessage(message); // DO NOT just use sendMessage() here -- we want this to jump ahead of the queue.
-
- LL_DEBUGS("Plugin") << "Sending size_change" << LL_ENDL;
- }
- }
-
- if(mPlugin && mPlugin->isRunning())
- {
- // Send queued messages
- while(!mSendQueue.empty())
- {
- LLPluginMessage message = mSendQueue.front();
- mSendQueue.pop();
- mPlugin->sendMessage(message);
- }
- }
-}
-
-int LLPluginClassMedia::getTextureWidth() const
-{
- return nextPowerOf2(mTextureWidth);
-}
-
-int LLPluginClassMedia::getTextureHeight() const
-{
- return nextPowerOf2(mTextureHeight);
-}
-
-unsigned char* LLPluginClassMedia::getBitsData()
-{
- unsigned char *result = NULL;
- if((mPlugin != NULL) && !mTextureSharedMemoryName.empty())
- {
- result = (unsigned char*)mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName);
- }
- return result;
-}
-
-void LLPluginClassMedia::setSize(int width, int height)
-{
- if((width > 0) && (height > 0))
- {
- mSetMediaWidth = width;
- mSetMediaHeight = height;
- }
- else
- {
- mSetMediaWidth = -1;
- mSetMediaHeight = -1;
- }
-
- setSizeInternal();
-}
-
-void LLPluginClassMedia::setSizeInternal(void)
-{
- if((mSetMediaWidth > 0) && (mSetMediaHeight > 0))
- {
- mRequestedMediaWidth = mSetMediaWidth;
- mRequestedMediaHeight = mSetMediaHeight;
- }
- else if((mNaturalMediaWidth > 0) && (mNaturalMediaHeight > 0))
- {
- mRequestedMediaWidth = mNaturalMediaWidth;
- mRequestedMediaHeight = mNaturalMediaHeight;
- }
- else
- {
- mRequestedMediaWidth = mDefaultMediaWidth;
- mRequestedMediaHeight = mDefaultMediaHeight;
- }
-
- // Save these for size/interest calculations
- mFullMediaWidth = mRequestedMediaWidth;
- mFullMediaHeight = mRequestedMediaHeight;
-
- if(mAllowDownsample)
- {
- switch(mPriority)
- {
- case PRIORITY_SLIDESHOW:
- case PRIORITY_LOW:
- // Reduce maximum texture dimension to (or below) mLowPrioritySizeLimit
- while((mRequestedMediaWidth > mLowPrioritySizeLimit) || (mRequestedMediaHeight > mLowPrioritySizeLimit))
- {
- mRequestedMediaWidth /= 2;
- mRequestedMediaHeight /= 2;
- }
- break;
-
- default:
- // Don't adjust texture size
- break;
- }
- }
-
- if(mAutoScaleMedia)
- {
- mRequestedMediaWidth = nextPowerOf2(mRequestedMediaWidth);
- mRequestedMediaHeight = nextPowerOf2(mRequestedMediaHeight);
- }
-
- if(mRequestedMediaWidth > 2048)
- mRequestedMediaWidth = 2048;
-
- if(mRequestedMediaHeight > 2048)
- mRequestedMediaHeight = 2048;
-}
-
-void LLPluginClassMedia::setAutoScale(bool auto_scale)
-{
- if(auto_scale != mAutoScaleMedia)
- {
- mAutoScaleMedia = auto_scale;
- setSizeInternal();
- }
-}
-
-bool LLPluginClassMedia::textureValid(void)
-{
- if(
- !mTextureParamsReceived ||
- mTextureWidth <= 0 ||
- mTextureHeight <= 0 ||
- mMediaWidth <= 0 ||
- mMediaHeight <= 0 ||
- mRequestedMediaWidth != mMediaWidth ||
- mRequestedMediaHeight != mMediaHeight ||
- getBitsData() == NULL
- )
- return false;
-
- return true;
-}
-
-bool LLPluginClassMedia::getDirty(LLRect *dirty_rect)
-{
- bool result = !mDirtyRect.isEmpty();
-
- if(dirty_rect != NULL)
- {
- *dirty_rect = mDirtyRect;
- }
-
- return result;
-}
-
-void LLPluginClassMedia::resetDirty(void)
-{
- mDirtyRect = LLRect::null;
-}
-
-std::string LLPluginClassMedia::translateModifiers(MASK modifiers)
-{
- std::string result;
-
-
- if(modifiers & MASK_CONTROL)
- {
- result += "control|";
- }
-
- if(modifiers & MASK_ALT)
- {
- result += "alt|";
- }
-
- if(modifiers & MASK_SHIFT)
- {
- result += "shift|";
- }
-
- // TODO: should I deal with platform differences here or in callers?
- // TODO: how do we deal with the Mac "command" key?
-/*
- if(modifiers & MASK_SOMETHING)
- {
- result += "meta|";
- }
-*/
- return result;
-}
-
-void LLPluginClassMedia::jsExposeObjectEvent( bool expose )
-{
- if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
- {
- return;
- }
-
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_expose_object");
- message.setValueBoolean( "expose", expose );
- sendMessage( message );
-}
-
-void LLPluginClassMedia::jsValuesValidEvent( bool valid )
-{
- if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
- {
- return;
- }
-
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_values_valid");
- message.setValueBoolean( "valid", valid );
- sendMessage( message );
-}
-
-void LLPluginClassMedia::jsAgentLocationEvent( double x, double y, double z )
-{
- if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
- {
- return;
- }
-
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_location");
- message.setValueReal( "x", x );
- message.setValueReal( "y", y );
- message.setValueReal( "z", z );
- sendMessage( message );
-}
-
-void LLPluginClassMedia::jsAgentGlobalLocationEvent( double x, double y, double z )
-{
- if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
- {
- return;
- }
-
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_global_location");
- message.setValueReal( "x", x );
- message.setValueReal( "y", y );
- message.setValueReal( "z", z );
- sendMessage( message );
-}
-
-void LLPluginClassMedia::jsAgentOrientationEvent( double angle )
-{
- if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
- {
- return;
- }
-
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_orientation");
- message.setValueReal( "angle", angle );
-
- sendMessage( message );
-}
-
-void LLPluginClassMedia::jsAgentLanguageEvent( const std::string& language )
-{
- if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
- {
- return;
- }
-
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_language");
- message.setValue( "language", language );
- sendMessage( message );
-}
-
-void LLPluginClassMedia::jsAgentRegionEvent( const std::string& region )
-{
- if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
- {
- return;
- }
-
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_region");
- message.setValue( "region", region );
- sendMessage( message );
-}
-
-void LLPluginClassMedia::jsAgentMaturityEvent( const std::string& maturity )
-{
- if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
- {
- return;
- }
-
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_maturity");
- message.setValue( "maturity", maturity );
- sendMessage( message );
-}
-
-void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers)
-{
- if(type == MOUSE_EVENT_MOVE)
- {
- if(!mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked())
- {
- // Don't queue up mouse move events that can't be delivered.
- return;
- }
-
- if((x == mLastMouseX) && (y == mLastMouseY))
- {
- // Don't spam unnecessary mouse move events.
- return;
- }
-
- mLastMouseX = x;
- mLastMouseY = y;
- }
-
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "mouse_event");
- std::string temp;
- switch(type)
- {
- case MOUSE_EVENT_DOWN: temp = "down"; break;
- case MOUSE_EVENT_UP: temp = "up"; break;
- case MOUSE_EVENT_MOVE: temp = "move"; break;
- case MOUSE_EVENT_DOUBLE_CLICK: temp = "double_click"; break;
- }
- message.setValue("event", temp);
-
- message.setValueS32("button", button);
-
- message.setValueS32("x", x);
-
- // Incoming coordinates are OpenGL-style ((0,0) = lower left), so flip them here if the plugin has requested it.
- if(!mRequestedTextureCoordsOpenGL)
- {
- // TODO: Should I use mMediaHeight or mRequestedMediaHeight here?
- y = mMediaHeight - y;
- }
- message.setValueS32("y", y);
-
- message.setValue("modifiers", translateModifiers(modifiers));
-
- sendMessage(message);
-}
-
-bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data)
-{
- bool result = true;
-
- // FIXME:
- // HACK: we don't have an easy way to tell if the plugin is going to handle a particular keycode.
- // For now, return false for the ones the webkit plugin won't handle properly.
-
- switch(key_code)
- {
- case KEY_BACKSPACE:
- case KEY_TAB:
- case KEY_RETURN:
- case KEY_PAD_RETURN:
- case KEY_SHIFT:
- case KEY_CONTROL:
- case KEY_ALT:
- case KEY_CAPSLOCK:
- case KEY_ESCAPE:
- case KEY_PAGE_UP:
- case KEY_PAGE_DOWN:
- case KEY_END:
- case KEY_HOME:
- case KEY_LEFT:
- case KEY_UP:
- case KEY_RIGHT:
- case KEY_DOWN:
- case KEY_INSERT:
- case KEY_DELETE:
- // These will be handled
- break;
-
- default:
- // regular ASCII characters will also be handled
- if(key_code >= KEY_SPECIAL)
- {
- // Other "special" codes will not work properly.
- result = false;
- }
- break;
- }
-
-#if LL_DARWIN
- if(modifiers & MASK_ALT)
- {
- // Option-key modified characters should be handled by the unicode input path instead of this one.
- result = false;
- }
-#endif
-
- if(result)
- {
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "key_event");
- std::string temp;
- switch(type)
- {
- case KEY_EVENT_DOWN: temp = "down"; break;
- case KEY_EVENT_UP: temp = "up"; break;
- case KEY_EVENT_REPEAT: temp = "repeat"; break;
- }
- message.setValue("event", temp);
-
- message.setValueS32("key", key_code);
-
- message.setValue("modifiers", translateModifiers(modifiers));
- message.setValueLLSD("native_key_data", native_key_data);
-
- sendMessage(message);
- }
-
- return result;
-}
-
-void LLPluginClassMedia::scrollEvent(int x, int y, MASK modifiers)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "scroll_event");
-
- message.setValueS32("x", x);
- message.setValueS32("y", y);
- message.setValue("modifiers", translateModifiers(modifiers));
-
- sendMessage(message);
-}
-
-bool LLPluginClassMedia::textInput(const std::string &text, MASK modifiers, LLSD native_key_data)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "text_event");
-
- message.setValue("text", text);
- message.setValue("modifiers", translateModifiers(modifiers));
- message.setValueLLSD("native_key_data", native_key_data);
-
- sendMessage(message);
-
- return true;
-}
-
-void LLPluginClassMedia::loadURI(const std::string &uri)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "load_uri");
-
- message.setValue("uri", uri);
-
- sendMessage(message);
-}
-
-const char* LLPluginClassMedia::priorityToString(EPriority priority)
-{
- const char* result = "UNKNOWN";
- switch(priority)
- {
- case PRIORITY_UNLOADED: result = "unloaded"; break;
- case PRIORITY_STOPPED: result = "stopped"; break;
- case PRIORITY_HIDDEN: result = "hidden"; break;
- case PRIORITY_SLIDESHOW: result = "slideshow"; break;
- case PRIORITY_LOW: result = "low"; break;
- case PRIORITY_NORMAL: result = "normal"; break;
- case PRIORITY_HIGH: result = "high"; break;
- }
-
- return result;
-}
-
-void LLPluginClassMedia::setPriority(EPriority priority)
-{
- if(mPriority != priority)
- {
- mPriority = priority;
-
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_priority");
-
- std::string priority_string = priorityToString(priority);
- switch(priority)
- {
- case PRIORITY_UNLOADED:
- mSleepTime = 1.0f;
- break;
- case PRIORITY_STOPPED:
- mSleepTime = 1.0f;
- break;
- case PRIORITY_HIDDEN:
- mSleepTime = 1.0f;
- break;
- case PRIORITY_SLIDESHOW:
- mSleepTime = 1.0f;
- break;
- case PRIORITY_LOW:
- mSleepTime = 1.0f / 25.0f;
- break;
- case PRIORITY_NORMAL:
- mSleepTime = 1.0f / 50.0f;
- break;
- case PRIORITY_HIGH:
- mSleepTime = 1.0f / 100.0f;
- break;
- }
-
- message.setValue("priority", priority_string);
-
- sendMessage(message);
-
- if(mPlugin)
- {
- mPlugin->setSleepTime(mSleepTime);
- }
-
- LL_DEBUGS("PluginPriority") << this << ": setting priority to " << priority_string << LL_ENDL;
-
- // This may affect the calculated size, so recalculate it here.
- setSizeInternal();
- }
-}
-
-void LLPluginClassMedia::setLowPrioritySizeLimit(int size)
-{
- int power = nextPowerOf2(size);
- if(mLowPrioritySizeLimit != power)
- {
- mLowPrioritySizeLimit = power;
-
- // This may affect the calculated size, so recalculate it here.
- setSizeInternal();
- }
-}
-
-F64 LLPluginClassMedia::getCPUUsage()
-{
- F64 result = 0.0f;
-
- if(mPlugin)
- {
- result = mPlugin->getCPUUsage();
- }
-
- return result;
-}
-
-void LLPluginClassMedia::sendPickFileResponse(const std::string &file)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "pick_file_response");
- message.setValue("file", file);
- if(mPlugin && mPlugin->isBlocked())
- {
- // If the plugin sent a blocking pick-file request, the response should unblock it.
- message.setValueBoolean("blocking_response", true);
- }
- sendMessage(message);
-}
-
-void LLPluginClassMedia::sendAuthResponse(bool ok, const std::string &username, const std::string &password)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "auth_response");
- message.setValueBoolean("ok", ok);
- message.setValue("username", username);
- message.setValue("password", password);
- if(mPlugin && mPlugin->isBlocked())
- {
- // If the plugin sent a blocking pick-file request, the response should unblock it.
- message.setValueBoolean("blocking_response", true);
- }
- sendMessage(message);
-}
-
-void LLPluginClassMedia::cut()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_cut");
- sendMessage(message);
-}
-
-void LLPluginClassMedia::copy()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_copy");
- sendMessage(message);
-}
-
-void LLPluginClassMedia::paste()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_paste");
- sendMessage(message);
-}
-
-void LLPluginClassMedia::setUserDataPath(const std::string &user_data_path)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_user_data_path");
- message.setValue("path", user_data_path);
- sendMessage(message);
-}
-
-void LLPluginClassMedia::setLanguageCode(const std::string &language_code)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_language_code");
- message.setValue("language", language_code);
- sendMessage(message);
-}
-
-void LLPluginClassMedia::setPluginsEnabled(const bool enabled)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "plugins_enabled");
- message.setValueBoolean("enable", enabled);
- sendMessage(message);
-}
-
-void LLPluginClassMedia::setJavascriptEnabled(const bool enabled)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "javascript_enabled");
- message.setValueBoolean("enable", enabled);
- sendMessage(message);
-}
-
-void LLPluginClassMedia::setTarget(const std::string &target)
-{
- mTarget = target;
-}
-
-/* virtual */
-void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
-{
- std::string message_class = message.getClass();
-
- if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
- {
- std::string message_name = message.getName();
- if(message_name == "texture_params")
- {
- mRequestedTextureDepth = message.getValueS32("depth");
- mRequestedTextureInternalFormat = message.getValueU32("internalformat");
- mRequestedTextureFormat = message.getValueU32("format");
- mRequestedTextureType = message.getValueU32("type");
- mRequestedTextureSwapBytes = message.getValueBoolean("swap_bytes");
- mRequestedTextureCoordsOpenGL = message.getValueBoolean("coords_opengl");
-
- // These two are optional, and will default to 0 if they're not specified.
- mDefaultMediaWidth = message.getValueS32("default_width");
- mDefaultMediaHeight = message.getValueS32("default_height");
-
- mAllowDownsample = message.getValueBoolean("allow_downsample");
- mPadding = message.getValueS32("padding");
-
- setSizeInternal();
-
- mTextureParamsReceived = true;
- }
- else if(message_name == "updated")
- {
- if(message.hasValue("left"))
- {
- LLRect newDirtyRect;
- newDirtyRect.mLeft = message.getValueS32("left");
- newDirtyRect.mTop = message.getValueS32("top");
- newDirtyRect.mRight = message.getValueS32("right");
- newDirtyRect.mBottom = message.getValueS32("bottom");
-
- // The plugin is likely to have top and bottom switched, due to vertical flip and OpenGL coordinate confusion.
- // If they're backwards, swap them.
- if(newDirtyRect.mTop < newDirtyRect.mBottom)
- {
- S32 temp = newDirtyRect.mTop;
- newDirtyRect.mTop = newDirtyRect.mBottom;
- newDirtyRect.mBottom = temp;
- }
-
- if(mDirtyRect.isEmpty())
- {
- mDirtyRect = newDirtyRect;
- }
- else
- {
- mDirtyRect.unionWith(newDirtyRect);
- }
-
- LL_DEBUGS("Plugin") << "adjusted incoming rect is: ("
- << newDirtyRect.mLeft << ", "
- << newDirtyRect.mTop << ", "
- << newDirtyRect.mRight << ", "
- << newDirtyRect.mBottom << "), new dirty rect is: ("
- << mDirtyRect.mLeft << ", "
- << mDirtyRect.mTop << ", "
- << mDirtyRect.mRight << ", "
- << mDirtyRect.mBottom << ")"
- << LL_ENDL;
-
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CONTENT_UPDATED);
- }
-
-
- bool time_duration_updated = false;
- int previous_percent = mProgressPercent;
-
- if(message.hasValue("current_time"))
- {
- mCurrentTime = message.getValueReal("current_time");
- time_duration_updated = true;
- }
- if(message.hasValue("duration"))
- {
- mDuration = message.getValueReal("duration");
- time_duration_updated = true;
- }
-
- if(message.hasValue("current_rate"))
- {
- mCurrentRate = message.getValueReal("current_rate");
- }
-
- if(message.hasValue("loaded_duration"))
- {
- mLoadedDuration = message.getValueReal("loaded_duration");
- time_duration_updated = true;
- }
- else
- {
- // If the message doesn't contain a loaded_duration param, assume it's equal to duration
- mLoadedDuration = mDuration;
- }
-
- // Calculate a percentage based on the loaded duration and total duration.
- if(mDuration != 0.0f) // Don't divide by zero.
- {
- mProgressPercent = (int)((mLoadedDuration * 100.0f)/mDuration);
- }
-
- if(time_duration_updated)
- {
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_TIME_DURATION_UPDATED);
- }
-
- if(previous_percent != mProgressPercent)
- {
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED);
- }
- }
- else if(message_name == "media_status")
- {
- std::string status = message.getValue("status");
-
- LL_DEBUGS("Plugin") << "Status changed to: " << status << LL_ENDL;
-
- if(status == "loading")
- {
- mStatus = LLPluginClassMediaOwner::MEDIA_LOADING;
- }
- else if(status == "loaded")
- {
- mStatus = LLPluginClassMediaOwner::MEDIA_LOADED;
- }
- else if(status == "error")
- {
- mStatus = LLPluginClassMediaOwner::MEDIA_ERROR;
- }
- else if(status == "playing")
- {
- mStatus = LLPluginClassMediaOwner::MEDIA_PLAYING;
- }
- else if(status == "paused")
- {
- mStatus = LLPluginClassMediaOwner::MEDIA_PAUSED;
- }
- else if(status == "done")
- {
- mStatus = LLPluginClassMediaOwner::MEDIA_DONE;
- }
- else
- {
- // empty string or any unknown string
- mStatus = LLPluginClassMediaOwner::MEDIA_NONE;
- }
- }
- else if(message_name == "size_change_request")
- {
- S32 width = message.getValueS32("width");
- S32 height = message.getValueS32("height");
- std::string name = message.getValue("name");
-
- // TODO: check that name matches?
- mNaturalMediaWidth = width;
- mNaturalMediaHeight = height;
-
- setSizeInternal();
- }
- else if(message_name == "size_change_response")
- {
- std::string name = message.getValue("name");
-
- // TODO: check that name matches?
-
- mTextureWidth = message.getValueS32("texture_width");
- mTextureHeight = message.getValueS32("texture_height");
- mMediaWidth = message.getValueS32("width");
- mMediaHeight = message.getValueS32("height");
-
- // This invalidates any existing dirty rect.
- resetDirty();
-
- // TODO: should we verify that the plugin sent back the right values?
- // Two size changes in a row may cause them to not match, due to queueing, etc.
-
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_SIZE_CHANGED);
- }
- else if(message_name == "cursor_changed")
- {
- mCursorName = message.getValue("name");
-
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CURSOR_CHANGED);
- }
- else if(message_name == "edit_state")
- {
- if(message.hasValue("cut"))
- {
- mCanCut = message.getValueBoolean("cut");
- }
- if(message.hasValue("copy"))
- {
- mCanCopy = message.getValueBoolean("copy");
- }
- if(message.hasValue("paste"))
- {
- mCanPaste = message.getValueBoolean("paste");
- }
- }
- else if(message_name == "name_text")
- {
- mMediaName = message.getValue("name");
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAME_CHANGED);
- }
- else if(message_name == "pick_file")
- {
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PICK_FILE_REQUEST);
- }
- else if(message_name == "auth_request")
- {
- mAuthURL = message.getValue("url");
- mAuthRealm = message.getValue("realm");
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_AUTH_REQUEST);
- }
- else
- {
- LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
- }
- }
- else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER)
- {
- std::string message_name = message.getName();
- if(message_name == "navigate_begin")
- {
- mNavigateURI = message.getValue("uri");
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_BEGIN);
- }
- else if(message_name == "navigate_complete")
- {
- mNavigateURI = message.getValue("uri");
- mNavigateResultCode = message.getValueS32("result_code");
- mNavigateResultString = message.getValue("result_string");
- mHistoryBackAvailable = message.getValueBoolean("history_back_available");
- mHistoryForwardAvailable = message.getValueBoolean("history_forward_available");
-
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_COMPLETE);
- }
- else if(message_name == "progress")
- {
- mProgressPercent = message.getValueS32("percent");
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED);
- }
- else if(message_name == "status_text")
- {
- mStatusText = message.getValue("status");
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_STATUS_TEXT_CHANGED);
- }
- else if(message_name == "location_changed")
- {
- mLocation = message.getValue("uri");
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LOCATION_CHANGED);
- }
- else if(message_name == "click_href")
- {
- mClickURL = message.getValue("uri");
- mClickTarget = message.getValue("target");
- mClickUUID = message.getValue("uuid");
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_HREF);
- }
- else if(message_name == "click_nofollow")
- {
- mClickURL = message.getValue("uri");
- mClickNavType = message.getValue("nav_type");
- mClickTarget.clear();
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_NOFOLLOW);
- }
- else if(message_name == "navigate_error_page")
- {
- mStatusCode = message.getValueS32("status_code");
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_ERROR_PAGE);
- }
- else if(message_name == "cookie_set")
- {
- if(mOwner)
- {
- mOwner->handleCookieSet(this, message.getValue("cookie"));
- }
- }
- else if(message_name == "close_request")
- {
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLOSE_REQUEST);
- }
- else if(message_name == "geometry_change")
- {
- mClickUUID = message.getValue("uuid");
- mGeometryX = message.getValueS32("x");
- mGeometryY = message.getValueS32("y");
- mGeometryWidth = message.getValueS32("width");
- mGeometryHeight = message.getValueS32("height");
-
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_GEOMETRY_CHANGE);
- }
- else if(message_name == "link_hovered")
- {
- // text is not currently used -- the tooltip hover text is taken from the "title".
- mHoverLink = message.getValue("link");
- mHoverText = message.getValue("title");
- // message.getValue("text");
-
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LINK_HOVERED);
- }
- else
- {
- LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
- }
- }
- else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
- {
- std::string message_name = message.getName();
-
- // This class hasn't defined any incoming messages yet.
-// if(message_name == "message_name")
-// {
-// }
-// else
- {
- LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
- }
- }
-
-}
-
-/* virtual */
-void LLPluginClassMedia::pluginLaunchFailed()
-{
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED_LAUNCH);
-}
-
-/* virtual */
-void LLPluginClassMedia::pluginDied()
-{
- mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED);
-}
-
-void LLPluginClassMedia::mediaEvent(LLPluginClassMediaOwner::EMediaEvent event)
-{
- if(mOwner)
- {
- mOwner->handleMediaEvent(this, event);
- }
-}
-
-void LLPluginClassMedia::sendMessage(const LLPluginMessage &message)
-{
- if(mPlugin && mPlugin->isRunning())
- {
- mPlugin->sendMessage(message);
- }
- else
- {
- // The plugin isn't set up yet -- queue this message to be sent after initialization.
- mSendQueue.push(message);
- }
-}
-
-////////////////////////////////////////////////////////////
-// MARK: media_browser class functions
-bool LLPluginClassMedia::pluginSupportsMediaBrowser(void)
-{
- std::string version = mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER);
- return !version.empty();
-}
-
-void LLPluginClassMedia::focus(bool focused)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "focus");
-
- message.setValueBoolean("focused", focused);
-
- sendMessage(message);
-}
-
-void LLPluginClassMedia::clear_cache()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cache");
- sendMessage(message);
-}
-
-void LLPluginClassMedia::clear_cookies()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cookies");
- sendMessage(message);
-}
-
-void LLPluginClassMedia::set_cookies(const std::string &cookies)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_cookies");
- message.setValue("cookies", cookies);
- sendMessage(message);
-}
-
-void LLPluginClassMedia::enable_cookies(bool enable)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "enable_cookies");
- message.setValueBoolean("enable", enable);
- sendMessage(message);
-}
-
-void LLPluginClassMedia::proxy_setup(bool enable, const std::string &host, int port)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_setup");
-
- message.setValueBoolean("enable", enable);
- message.setValue("host", host);
- message.setValueS32("port", port);
-
- sendMessage(message);
-}
-
-void LLPluginClassMedia::browse_stop()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_stop");
- sendMessage(message);
-}
-
-void LLPluginClassMedia::browse_reload(bool ignore_cache)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_reload");
-
- message.setValueBoolean("ignore_cache", ignore_cache);
-
- sendMessage(message);
-}
-
-void LLPluginClassMedia::browse_forward()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_forward");
- sendMessage(message);
-}
-
-void LLPluginClassMedia::browse_back()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_back");
- sendMessage(message);
-}
-
-void LLPluginClassMedia::setBrowserUserAgent(const std::string& user_agent)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_user_agent");
-
- message.setValue("user_agent", user_agent);
-
- sendMessage(message);
-}
-
-void LLPluginClassMedia::proxyWindowOpened(const std::string &target, const std::string &uuid)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_window_opened");
-
- message.setValue("target", target);
- message.setValue("uuid", uuid);
-
- sendMessage(message);
-}
-
-void LLPluginClassMedia::proxyWindowClosed(const std::string &uuid)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_window_closed");
-
- message.setValue("uuid", uuid);
-
- sendMessage(message);
-}
-
-void LLPluginClassMedia::ignore_ssl_cert_errors(bool ignore)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "ignore_ssl_cert_errors");
- message.setValueBoolean("ignore", ignore);
- sendMessage(message);
-}
-
-void LLPluginClassMedia::addCertificateFilePath(const std::string& path)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "add_certificate_file_path");
- message.setValue("path", path);
- sendMessage(message);
-}
-
-void LLPluginClassMedia::crashPlugin()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "crash");
-
- sendMessage(message);
-}
-
-void LLPluginClassMedia::hangPlugin()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "hang");
-
- sendMessage(message);
-}
-
-
-////////////////////////////////////////////////////////////
-// MARK: media_time class functions
-bool LLPluginClassMedia::pluginSupportsMediaTime(void)
-{
- std::string version = mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME);
- return !version.empty();
-}
-
-void LLPluginClassMedia::stop()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "stop");
- sendMessage(message);
-}
-
-void LLPluginClassMedia::start(float rate)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "start");
-
- message.setValueReal("rate", rate);
-
- sendMessage(message);
-}
-
-void LLPluginClassMedia::pause()
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "pause");
- sendMessage(message);
-}
-
-void LLPluginClassMedia::seek(float time)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "seek");
-
- message.setValueReal("time", time);
-
- sendMessage(message);
-}
-
-void LLPluginClassMedia::setLoop(bool loop)
-{
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "set_loop");
-
- message.setValueBoolean("loop", loop);
-
- sendMessage(message);
-}
-
-void LLPluginClassMedia::setVolume(float volume)
-{
- if(volume != mRequestedVolume)
- {
- mRequestedVolume = volume;
-
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "set_volume");
-
- message.setValueReal("volume", volume);
-
- sendMessage(message);
- }
-}
-
-float LLPluginClassMedia::getVolume()
-{
- return mRequestedVolume;
-}
-
-void LLPluginClassMedia::initializeUrlHistory(const LLSD& url_history)
-{
- // Send URL history to plugin
- LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "init_history");
- message.setValueLLSD("history", url_history);
- sendMessage(message);
-
- LL_DEBUGS("Plugin") << "Sending history" << LL_ENDL;
-}
-
+/**
+ * @file llpluginclassmedia.cpp
+ * @brief LLPluginClassMedia handles a plugin which knows about the "media" message class.
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2008&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#include "linden_common.h"
+#include "indra_constants.h"
+
+#include "llpluginclassmedia.h"
+#include "llpluginmessageclasses.h"
+
+#include "llqtwebkit.h"
+
+static int LOW_PRIORITY_TEXTURE_SIZE_DEFAULT = 256;
+
+static int nextPowerOf2( int value )
+{
+ int next_power_of_2 = 1;
+ while ( next_power_of_2 < value )
+ {
+ next_power_of_2 <<= 1;
+ }
+
+ return next_power_of_2;
+}
+
+LLPluginClassMedia::LLPluginClassMedia(LLPluginClassMediaOwner *owner)
+{
+ mOwner = owner;
+ mPlugin = NULL;
+ reset();
+
+ //debug use
+ mDeleteOK = true ;
+}
+
+
+LLPluginClassMedia::~LLPluginClassMedia()
+{
+ llassert_always(mDeleteOK) ;
+ reset();
+}
+
+bool LLPluginClassMedia::init(const std::string &launcher_filename, const std::string &plugin_dir, const std::string &plugin_filename, bool debug)
+{
+ LL_DEBUGS("Plugin") << "launcher: " << launcher_filename << LL_ENDL;
+ LL_DEBUGS("Plugin") << "dir: " << plugin_dir << LL_ENDL;
+ LL_DEBUGS("Plugin") << "plugin: " << plugin_filename << LL_ENDL;
+
+ mPlugin = new LLPluginProcessParent(this);
+ mPlugin->setSleepTime(mSleepTime);
+
+ // Queue up the media init message -- it will be sent after all the currently queued messages.
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "init");
+ message.setValue("target", mTarget);
+ sendMessage(message);
+
+ mPlugin->init(launcher_filename, plugin_dir, plugin_filename, debug);
+
+ return true;
+}
+
+
+void LLPluginClassMedia::reset()
+{
+ if(mPlugin != NULL)
+ {
+ delete mPlugin;
+ mPlugin = NULL;
+ }
+
+ mTextureParamsReceived = false;
+ mRequestedTextureDepth = 0;
+ mRequestedTextureInternalFormat = 0;
+ mRequestedTextureFormat = 0;
+ mRequestedTextureType = 0;
+ mRequestedTextureSwapBytes = false;
+ mRequestedTextureCoordsOpenGL = false;
+ mTextureSharedMemorySize = 0;
+ mTextureSharedMemoryName.clear();
+ mDefaultMediaWidth = 0;
+ mDefaultMediaHeight = 0;
+ mNaturalMediaWidth = 0;
+ mNaturalMediaHeight = 0;
+ mSetMediaWidth = -1;
+ mSetMediaHeight = -1;
+ mRequestedMediaWidth = 0;
+ mRequestedMediaHeight = 0;
+ mRequestedTextureWidth = 0;
+ mRequestedTextureHeight = 0;
+ mFullMediaWidth = 0;
+ mFullMediaHeight = 0;
+ mTextureWidth = 0;
+ mTextureHeight = 0;
+ mMediaWidth = 0;
+ mMediaHeight = 0;
+ mDirtyRect = LLRect::null;
+ mAutoScaleMedia = false;
+ mRequestedVolume = 1.0f;
+ mPriority = PRIORITY_NORMAL;
+ mLowPrioritySizeLimit = LOW_PRIORITY_TEXTURE_SIZE_DEFAULT;
+ mAllowDownsample = false;
+ mPadding = 0;
+ mLastMouseX = 0;
+ mLastMouseY = 0;
+ mStatus = LLPluginClassMediaOwner::MEDIA_NONE;
+ mSleepTime = 1.0f / 100.0f;
+ mCanCut = false;
+ mCanCopy = false;
+ mCanPaste = false;
+ mMediaName.clear();
+ mMediaDescription.clear();
+ mBackgroundColor = LLColor4(1.0f, 1.0f, 1.0f, 1.0f);
+
+ // media_browser class
+ mNavigateURI.clear();
+ mNavigateResultCode = -1;
+ mNavigateResultString.clear();
+ mHistoryBackAvailable = false;
+ mHistoryForwardAvailable = false;
+ mStatusText.clear();
+ mProgressPercent = 0;
+ mClickURL.clear();
+ mClickNavType.clear();
+ mClickTarget.clear();
+ mClickUUID.clear();
+ mStatusCode = 0;
+
+ // media_time class
+ mCurrentTime = 0.0f;
+ mDuration = 0.0f;
+ mCurrentRate = 0.0f;
+ mLoadedDuration = 0.0f;
+}
+
+void LLPluginClassMedia::idle(void)
+{
+ if(mPlugin)
+ {
+ mPlugin->idle();
+ }
+
+ if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL) || (mPlugin->isBlocked()) || (mOwner == NULL))
+ {
+ // Can't process a size change at this time
+ }
+ else if((mRequestedMediaWidth != mMediaWidth) || (mRequestedMediaHeight != mMediaHeight))
+ {
+ // Calculate the correct size for the media texture
+ mRequestedTextureHeight = mRequestedMediaHeight;
+ if(mPadding < 0)
+ {
+ // negative values indicate the plugin wants a power of 2
+ mRequestedTextureWidth = nextPowerOf2(mRequestedMediaWidth);
+ }
+ else
+ {
+ mRequestedTextureWidth = mRequestedMediaWidth;
+
+ if(mPadding > 1)
+ {
+ // Pad up to a multiple of the specified number of bytes per row
+ int rowbytes = mRequestedTextureWidth * mRequestedTextureDepth;
+ int pad = rowbytes % mPadding;
+ if(pad != 0)
+ {
+ rowbytes += mPadding - pad;
+ }
+
+ if(rowbytes % mRequestedTextureDepth == 0)
+ {
+ mRequestedTextureWidth = rowbytes / mRequestedTextureDepth;
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "Unable to pad texture width, padding size " << mPadding << "is not a multiple of pixel size " << mRequestedTextureDepth << LL_ENDL;
+ }
+ }
+ }
+
+
+ // Size change has been requested but not initiated yet.
+ size_t newsize = mRequestedTextureWidth * mRequestedTextureHeight * mRequestedTextureDepth;
+
+ // Add an extra line for padding, just in case.
+ newsize += mRequestedTextureWidth * mRequestedTextureDepth;
+
+ if(newsize != mTextureSharedMemorySize)
+ {
+ if(!mTextureSharedMemoryName.empty())
+ {
+ // Tell the plugin to remove the old memory segment
+ mPlugin->removeSharedMemory(mTextureSharedMemoryName);
+ mTextureSharedMemoryName.clear();
+ }
+
+ mTextureSharedMemorySize = newsize;
+ mTextureSharedMemoryName = mPlugin->addSharedMemory(mTextureSharedMemorySize);
+ if(!mTextureSharedMemoryName.empty())
+ {
+ void *addr = mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName);
+
+ // clear texture memory to avoid random screen visual fuzz from uninitialized texture data
+ memset( addr, 0x00, newsize );
+
+ // We could do this to force an update, but textureValid() will still be returning false until the first roundtrip to the plugin,
+ // so it may not be worthwhile.
+ // mDirtyRect.setOriginAndSize(0, 0, mRequestedMediaWidth, mRequestedMediaHeight);
+ }
+ }
+
+ // This is our local indicator that a change is in progress.
+ mTextureWidth = -1;
+ mTextureHeight = -1;
+ mMediaWidth = -1;
+ mMediaHeight = -1;
+
+ // This invalidates any existing dirty rect.
+ resetDirty();
+
+ // Send a size change message to the plugin
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change");
+ message.setValue("name", mTextureSharedMemoryName);
+ message.setValueS32("width", mRequestedMediaWidth);
+ message.setValueS32("height", mRequestedMediaHeight);
+ message.setValueS32("texture_width", mRequestedTextureWidth);
+ message.setValueS32("texture_height", mRequestedTextureHeight);
+ message.setValueReal("background_r", mBackgroundColor.mV[VX]);
+ message.setValueReal("background_g", mBackgroundColor.mV[VY]);
+ message.setValueReal("background_b", mBackgroundColor.mV[VZ]);
+ message.setValueReal("background_a", mBackgroundColor.mV[VW]);
+ mPlugin->sendMessage(message); // DO NOT just use sendMessage() here -- we want this to jump ahead of the queue.
+
+ LL_DEBUGS("Plugin") << "Sending size_change" << LL_ENDL;
+ }
+ }
+
+ if(mPlugin && mPlugin->isRunning())
+ {
+ // Send queued messages
+ while(!mSendQueue.empty())
+ {
+ LLPluginMessage message = mSendQueue.front();
+ mSendQueue.pop();
+ mPlugin->sendMessage(message);
+ }
+ }
+}
+
+int LLPluginClassMedia::getTextureWidth() const
+{
+ return nextPowerOf2(mTextureWidth);
+}
+
+int LLPluginClassMedia::getTextureHeight() const
+{
+ return nextPowerOf2(mTextureHeight);
+}
+
+unsigned char* LLPluginClassMedia::getBitsData()
+{
+ unsigned char *result = NULL;
+ if((mPlugin != NULL) && !mTextureSharedMemoryName.empty())
+ {
+ result = (unsigned char*)mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName);
+ }
+ return result;
+}
+
+void LLPluginClassMedia::setSize(int width, int height)
+{
+ if((width > 0) && (height > 0))
+ {
+ mSetMediaWidth = width;
+ mSetMediaHeight = height;
+ }
+ else
+ {
+ mSetMediaWidth = -1;
+ mSetMediaHeight = -1;
+ }
+
+ setSizeInternal();
+}
+
+void LLPluginClassMedia::setSizeInternal(void)
+{
+ if((mSetMediaWidth > 0) && (mSetMediaHeight > 0))
+ {
+ mRequestedMediaWidth = mSetMediaWidth;
+ mRequestedMediaHeight = mSetMediaHeight;
+ }
+ else if((mNaturalMediaWidth > 0) && (mNaturalMediaHeight > 0))
+ {
+ mRequestedMediaWidth = mNaturalMediaWidth;
+ mRequestedMediaHeight = mNaturalMediaHeight;
+ }
+ else
+ {
+ mRequestedMediaWidth = mDefaultMediaWidth;
+ mRequestedMediaHeight = mDefaultMediaHeight;
+ }
+
+ // Save these for size/interest calculations
+ mFullMediaWidth = mRequestedMediaWidth;
+ mFullMediaHeight = mRequestedMediaHeight;
+
+ if(mAllowDownsample)
+ {
+ switch(mPriority)
+ {
+ case PRIORITY_SLIDESHOW:
+ case PRIORITY_LOW:
+ // Reduce maximum texture dimension to (or below) mLowPrioritySizeLimit
+ while((mRequestedMediaWidth > mLowPrioritySizeLimit) || (mRequestedMediaHeight > mLowPrioritySizeLimit))
+ {
+ mRequestedMediaWidth /= 2;
+ mRequestedMediaHeight /= 2;
+ }
+ break;
+
+ default:
+ // Don't adjust texture size
+ break;
+ }
+ }
+
+ if(mAutoScaleMedia)
+ {
+ mRequestedMediaWidth = nextPowerOf2(mRequestedMediaWidth);
+ mRequestedMediaHeight = nextPowerOf2(mRequestedMediaHeight);
+ }
+
+ if(mRequestedMediaWidth > 2048)
+ mRequestedMediaWidth = 2048;
+
+ if(mRequestedMediaHeight > 2048)
+ mRequestedMediaHeight = 2048;
+}
+
+void LLPluginClassMedia::setAutoScale(bool auto_scale)
+{
+ if(auto_scale != mAutoScaleMedia)
+ {
+ mAutoScaleMedia = auto_scale;
+ setSizeInternal();
+ }
+}
+
+bool LLPluginClassMedia::textureValid(void)
+{
+ if(
+ !mTextureParamsReceived ||
+ mTextureWidth <= 0 ||
+ mTextureHeight <= 0 ||
+ mMediaWidth <= 0 ||
+ mMediaHeight <= 0 ||
+ mRequestedMediaWidth != mMediaWidth ||
+ mRequestedMediaHeight != mMediaHeight ||
+ getBitsData() == NULL
+ )
+ return false;
+
+ return true;
+}
+
+bool LLPluginClassMedia::getDirty(LLRect *dirty_rect)
+{
+ bool result = !mDirtyRect.isEmpty();
+
+ if(dirty_rect != NULL)
+ {
+ *dirty_rect = mDirtyRect;
+ }
+
+ return result;
+}
+
+void LLPluginClassMedia::resetDirty(void)
+{
+ mDirtyRect = LLRect::null;
+}
+
+std::string LLPluginClassMedia::translateModifiers(MASK modifiers)
+{
+ std::string result;
+
+
+ if(modifiers & MASK_CONTROL)
+ {
+ result += "control|";
+ }
+
+ if(modifiers & MASK_ALT)
+ {
+ result += "alt|";
+ }
+
+ if(modifiers & MASK_SHIFT)
+ {
+ result += "shift|";
+ }
+
+ // TODO: should I deal with platform differences here or in callers?
+ // TODO: how do we deal with the Mac "command" key?
+/*
+ if(modifiers & MASK_SOMETHING)
+ {
+ result += "meta|";
+ }
+*/
+ return result;
+}
+
+void LLPluginClassMedia::jsEnableObject( bool enable )
+{
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_enable_object");
+ message.setValueBoolean( "enable", enable );
+ sendMessage( message );
+}
+
+void LLPluginClassMedia::jsAgentLocationEvent( double x, double y, double z )
+{
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_location");
+ message.setValueReal( "x", x );
+ message.setValueReal( "y", y );
+ message.setValueReal( "z", z );
+ sendMessage( message );
+}
+
+void LLPluginClassMedia::jsAgentGlobalLocationEvent( double x, double y, double z )
+{
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_global_location");
+ message.setValueReal( "x", x );
+ message.setValueReal( "y", y );
+ message.setValueReal( "z", z );
+ sendMessage( message );
+}
+
+void LLPluginClassMedia::jsAgentOrientationEvent( double angle )
+{
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_orientation");
+ message.setValueReal( "angle", angle );
+
+ sendMessage( message );
+}
+
+void LLPluginClassMedia::jsAgentLanguageEvent( const std::string& language )
+{
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_language");
+ message.setValue( "language", language );
+ sendMessage( message );
+}
+
+void LLPluginClassMedia::jsAgentRegionEvent( const std::string& region )
+{
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_region");
+ message.setValue( "region", region );
+ sendMessage( message );
+}
+
+void LLPluginClassMedia::jsAgentMaturityEvent( const std::string& maturity )
+{
+ if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() )
+ {
+ return;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_maturity");
+ message.setValue( "maturity", maturity );
+ sendMessage( message );
+}
+
+void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers)
+{
+ if(type == MOUSE_EVENT_MOVE)
+ {
+ if(!mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked())
+ {
+ // Don't queue up mouse move events that can't be delivered.
+ return;
+ }
+
+ if((x == mLastMouseX) && (y == mLastMouseY))
+ {
+ // Don't spam unnecessary mouse move events.
+ return;
+ }
+
+ mLastMouseX = x;
+ mLastMouseY = y;
+ }
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "mouse_event");
+ std::string temp;
+ switch(type)
+ {
+ case MOUSE_EVENT_DOWN: temp = "down"; break;
+ case MOUSE_EVENT_UP: temp = "up"; break;
+ case MOUSE_EVENT_MOVE: temp = "move"; break;
+ case MOUSE_EVENT_DOUBLE_CLICK: temp = "double_click"; break;
+ }
+ message.setValue("event", temp);
+
+ message.setValueS32("button", button);
+
+ message.setValueS32("x", x);
+
+ // Incoming coordinates are OpenGL-style ((0,0) = lower left), so flip them here if the plugin has requested it.
+ if(!mRequestedTextureCoordsOpenGL)
+ {
+ // TODO: Should I use mMediaHeight or mRequestedMediaHeight here?
+ y = mMediaHeight - y;
+ }
+ message.setValueS32("y", y);
+
+ message.setValue("modifiers", translateModifiers(modifiers));
+
+ sendMessage(message);
+}
+
+bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data)
+{
+ bool result = true;
+
+ // FIXME:
+ // HACK: we don't have an easy way to tell if the plugin is going to handle a particular keycode.
+ // For now, return false for the ones the webkit plugin won't handle properly.
+
+ switch(key_code)
+ {
+ case KEY_BACKSPACE:
+ case KEY_TAB:
+ case KEY_RETURN:
+ case KEY_PAD_RETURN:
+ case KEY_SHIFT:
+ case KEY_CONTROL:
+ case KEY_ALT:
+ case KEY_CAPSLOCK:
+ case KEY_ESCAPE:
+ case KEY_PAGE_UP:
+ case KEY_PAGE_DOWN:
+ case KEY_END:
+ case KEY_HOME:
+ case KEY_LEFT:
+ case KEY_UP:
+ case KEY_RIGHT:
+ case KEY_DOWN:
+ case KEY_INSERT:
+ case KEY_DELETE:
+ // These will be handled
+ break;
+
+ default:
+ // regular ASCII characters will also be handled
+ if(key_code >= KEY_SPECIAL)
+ {
+ // Other "special" codes will not work properly.
+ result = false;
+ }
+ break;
+ }
+
+#if LL_DARWIN
+ if(modifiers & MASK_ALT)
+ {
+ // Option-key modified characters should be handled by the unicode input path instead of this one.
+ result = false;
+ }
+#endif
+
+ if(result)
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "key_event");
+ std::string temp;
+ switch(type)
+ {
+ case KEY_EVENT_DOWN: temp = "down"; break;
+ case KEY_EVENT_UP: temp = "up"; break;
+ case KEY_EVENT_REPEAT: temp = "repeat"; break;
+ }
+ message.setValue("event", temp);
+
+ message.setValueS32("key", key_code);
+
+ message.setValue("modifiers", translateModifiers(modifiers));
+ message.setValueLLSD("native_key_data", native_key_data);
+
+ sendMessage(message);
+ }
+
+ return result;
+}
+
+void LLPluginClassMedia::scrollEvent(int x, int y, MASK modifiers)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "scroll_event");
+
+ message.setValueS32("x", x);
+ message.setValueS32("y", y);
+ message.setValue("modifiers", translateModifiers(modifiers));
+
+ sendMessage(message);
+}
+
+bool LLPluginClassMedia::textInput(const std::string &text, MASK modifiers, LLSD native_key_data)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "text_event");
+
+ message.setValue("text", text);
+ message.setValue("modifiers", translateModifiers(modifiers));
+ message.setValueLLSD("native_key_data", native_key_data);
+
+ sendMessage(message);
+
+ return true;
+}
+
+void LLPluginClassMedia::loadURI(const std::string &uri)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "load_uri");
+
+ message.setValue("uri", uri);
+
+ sendMessage(message);
+}
+
+const char* LLPluginClassMedia::priorityToString(EPriority priority)
+{
+ const char* result = "UNKNOWN";
+ switch(priority)
+ {
+ case PRIORITY_UNLOADED: result = "unloaded"; break;
+ case PRIORITY_STOPPED: result = "stopped"; break;
+ case PRIORITY_HIDDEN: result = "hidden"; break;
+ case PRIORITY_SLIDESHOW: result = "slideshow"; break;
+ case PRIORITY_LOW: result = "low"; break;
+ case PRIORITY_NORMAL: result = "normal"; break;
+ case PRIORITY_HIGH: result = "high"; break;
+ }
+
+ return result;
+}
+
+void LLPluginClassMedia::setPriority(EPriority priority)
+{
+ if(mPriority != priority)
+ {
+ mPriority = priority;
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_priority");
+
+ std::string priority_string = priorityToString(priority);
+ switch(priority)
+ {
+ case PRIORITY_UNLOADED:
+ mSleepTime = 1.0f;
+ break;
+ case PRIORITY_STOPPED:
+ mSleepTime = 1.0f;
+ break;
+ case PRIORITY_HIDDEN:
+ mSleepTime = 1.0f;
+ break;
+ case PRIORITY_SLIDESHOW:
+ mSleepTime = 1.0f;
+ break;
+ case PRIORITY_LOW:
+ mSleepTime = 1.0f / 25.0f;
+ break;
+ case PRIORITY_NORMAL:
+ mSleepTime = 1.0f / 50.0f;
+ break;
+ case PRIORITY_HIGH:
+ mSleepTime = 1.0f / 100.0f;
+ break;
+ }
+
+ message.setValue("priority", priority_string);
+
+ sendMessage(message);
+
+ if(mPlugin)
+ {
+ mPlugin->setSleepTime(mSleepTime);
+ }
+
+ LL_DEBUGS("PluginPriority") << this << ": setting priority to " << priority_string << LL_ENDL;
+
+ // This may affect the calculated size, so recalculate it here.
+ setSizeInternal();
+ }
+}
+
+void LLPluginClassMedia::setLowPrioritySizeLimit(int size)
+{
+ int power = nextPowerOf2(size);
+ if(mLowPrioritySizeLimit != power)
+ {
+ mLowPrioritySizeLimit = power;
+
+ // This may affect the calculated size, so recalculate it here.
+ setSizeInternal();
+ }
+}
+
+F64 LLPluginClassMedia::getCPUUsage()
+{
+ F64 result = 0.0f;
+
+ if(mPlugin)
+ {
+ result = mPlugin->getCPUUsage();
+ }
+
+ return result;
+}
+
+void LLPluginClassMedia::sendPickFileResponse(const std::string &file)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "pick_file_response");
+ message.setValue("file", file);
+ if(mPlugin && mPlugin->isBlocked())
+ {
+ // If the plugin sent a blocking pick-file request, the response should unblock it.
+ message.setValueBoolean("blocking_response", true);
+ }
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::sendAuthResponse(bool ok, const std::string &username, const std::string &password)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "auth_response");
+ message.setValueBoolean("ok", ok);
+ message.setValue("username", username);
+ message.setValue("password", password);
+ if(mPlugin && mPlugin->isBlocked())
+ {
+ // If the plugin sent a blocking pick-file request, the response should unblock it.
+ message.setValueBoolean("blocking_response", true);
+ }
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::cut()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_cut");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::copy()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_copy");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::paste()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_paste");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::setUserDataPath(const std::string &user_data_path)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_user_data_path");
+ message.setValue("path", user_data_path);
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::setLanguageCode(const std::string &language_code)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_language_code");
+ message.setValue("language", language_code);
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::setPluginsEnabled(const bool enabled)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "plugins_enabled");
+ message.setValueBoolean("enable", enabled);
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::setJavascriptEnabled(const bool enabled)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "javascript_enabled");
+ message.setValueBoolean("enable", enabled);
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::setTarget(const std::string &target)
+{
+ mTarget = target;
+}
+
+/* virtual */
+void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
+{
+ std::string message_class = message.getClass();
+
+ if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
+ {
+ std::string message_name = message.getName();
+ if(message_name == "texture_params")
+ {
+ mRequestedTextureDepth = message.getValueS32("depth");
+ mRequestedTextureInternalFormat = message.getValueU32("internalformat");
+ mRequestedTextureFormat = message.getValueU32("format");
+ mRequestedTextureType = message.getValueU32("type");
+ mRequestedTextureSwapBytes = message.getValueBoolean("swap_bytes");
+ mRequestedTextureCoordsOpenGL = message.getValueBoolean("coords_opengl");
+
+ // These two are optional, and will default to 0 if they're not specified.
+ mDefaultMediaWidth = message.getValueS32("default_width");
+ mDefaultMediaHeight = message.getValueS32("default_height");
+
+ mAllowDownsample = message.getValueBoolean("allow_downsample");
+ mPadding = message.getValueS32("padding");
+
+ setSizeInternal();
+
+ mTextureParamsReceived = true;
+ }
+ else if(message_name == "updated")
+ {
+ if(message.hasValue("left"))
+ {
+ LLRect newDirtyRect;
+ newDirtyRect.mLeft = message.getValueS32("left");
+ newDirtyRect.mTop = message.getValueS32("top");
+ newDirtyRect.mRight = message.getValueS32("right");
+ newDirtyRect.mBottom = message.getValueS32("bottom");
+
+ // The plugin is likely to have top and bottom switched, due to vertical flip and OpenGL coordinate confusion.
+ // If they're backwards, swap them.
+ if(newDirtyRect.mTop < newDirtyRect.mBottom)
+ {
+ S32 temp = newDirtyRect.mTop;
+ newDirtyRect.mTop = newDirtyRect.mBottom;
+ newDirtyRect.mBottom = temp;
+ }
+
+ if(mDirtyRect.isEmpty())
+ {
+ mDirtyRect = newDirtyRect;
+ }
+ else
+ {
+ mDirtyRect.unionWith(newDirtyRect);
+ }
+
+ LL_DEBUGS("Plugin") << "adjusted incoming rect is: ("
+ << newDirtyRect.mLeft << ", "
+ << newDirtyRect.mTop << ", "
+ << newDirtyRect.mRight << ", "
+ << newDirtyRect.mBottom << "), new dirty rect is: ("
+ << mDirtyRect.mLeft << ", "
+ << mDirtyRect.mTop << ", "
+ << mDirtyRect.mRight << ", "
+ << mDirtyRect.mBottom << ")"
+ << LL_ENDL;
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CONTENT_UPDATED);
+ }
+
+
+ bool time_duration_updated = false;
+ int previous_percent = mProgressPercent;
+
+ if(message.hasValue("current_time"))
+ {
+ mCurrentTime = message.getValueReal("current_time");
+ time_duration_updated = true;
+ }
+ if(message.hasValue("duration"))
+ {
+ mDuration = message.getValueReal("duration");
+ time_duration_updated = true;
+ }
+
+ if(message.hasValue("current_rate"))
+ {
+ mCurrentRate = message.getValueReal("current_rate");
+ }
+
+ if(message.hasValue("loaded_duration"))
+ {
+ mLoadedDuration = message.getValueReal("loaded_duration");
+ time_duration_updated = true;
+ }
+ else
+ {
+ // If the message doesn't contain a loaded_duration param, assume it's equal to duration
+ mLoadedDuration = mDuration;
+ }
+
+ // Calculate a percentage based on the loaded duration and total duration.
+ if(mDuration != 0.0f) // Don't divide by zero.
+ {
+ mProgressPercent = (int)((mLoadedDuration * 100.0f)/mDuration);
+ }
+
+ if(time_duration_updated)
+ {
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_TIME_DURATION_UPDATED);
+ }
+
+ if(previous_percent != mProgressPercent)
+ {
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED);
+ }
+ }
+ else if(message_name == "media_status")
+ {
+ std::string status = message.getValue("status");
+
+ LL_DEBUGS("Plugin") << "Status changed to: " << status << LL_ENDL;
+
+ if(status == "loading")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_LOADING;
+ }
+ else if(status == "loaded")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_LOADED;
+ }
+ else if(status == "error")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_ERROR;
+ }
+ else if(status == "playing")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_PLAYING;
+ }
+ else if(status == "paused")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_PAUSED;
+ }
+ else if(status == "done")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_DONE;
+ }
+ else
+ {
+ // empty string or any unknown string
+ mStatus = LLPluginClassMediaOwner::MEDIA_NONE;
+ }
+ }
+ else if(message_name == "size_change_request")
+ {
+ S32 width = message.getValueS32("width");
+ S32 height = message.getValueS32("height");
+ std::string name = message.getValue("name");
+
+ // TODO: check that name matches?
+ mNaturalMediaWidth = width;
+ mNaturalMediaHeight = height;
+
+ setSizeInternal();
+ }
+ else if(message_name == "size_change_response")
+ {
+ std::string name = message.getValue("name");
+
+ // TODO: check that name matches?
+
+ mTextureWidth = message.getValueS32("texture_width");
+ mTextureHeight = message.getValueS32("texture_height");
+ mMediaWidth = message.getValueS32("width");
+ mMediaHeight = message.getValueS32("height");
+
+ // This invalidates any existing dirty rect.
+ resetDirty();
+
+ // TODO: should we verify that the plugin sent back the right values?
+ // Two size changes in a row may cause them to not match, due to queueing, etc.
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_SIZE_CHANGED);
+ }
+ else if(message_name == "cursor_changed")
+ {
+ mCursorName = message.getValue("name");
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CURSOR_CHANGED);
+ }
+ else if(message_name == "edit_state")
+ {
+ if(message.hasValue("cut"))
+ {
+ mCanCut = message.getValueBoolean("cut");
+ }
+ if(message.hasValue("copy"))
+ {
+ mCanCopy = message.getValueBoolean("copy");
+ }
+ if(message.hasValue("paste"))
+ {
+ mCanPaste = message.getValueBoolean("paste");
+ }
+ }
+ else if(message_name == "name_text")
+ {
+ mMediaName = message.getValue("name");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAME_CHANGED);
+ }
+ else if(message_name == "pick_file")
+ {
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PICK_FILE_REQUEST);
+ }
+ else if(message_name == "auth_request")
+ {
+ mAuthURL = message.getValue("url");
+ mAuthRealm = message.getValue("realm");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_AUTH_REQUEST);
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
+ }
+ }
+ else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER)
+ {
+ std::string message_name = message.getName();
+ if(message_name == "navigate_begin")
+ {
+ mNavigateURI = message.getValue("uri");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_BEGIN);
+ }
+ else if(message_name == "navigate_complete")
+ {
+ mNavigateURI = message.getValue("uri");
+ mNavigateResultCode = message.getValueS32("result_code");
+ mNavigateResultString = message.getValue("result_string");
+ mHistoryBackAvailable = message.getValueBoolean("history_back_available");
+ mHistoryForwardAvailable = message.getValueBoolean("history_forward_available");
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_COMPLETE);
+ }
+ else if(message_name == "progress")
+ {
+ mProgressPercent = message.getValueS32("percent");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PROGRESS_UPDATED);
+ }
+ else if(message_name == "status_text")
+ {
+ mStatusText = message.getValue("status");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_STATUS_TEXT_CHANGED);
+ }
+ else if(message_name == "location_changed")
+ {
+ mLocation = message.getValue("uri");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LOCATION_CHANGED);
+ }
+ else if(message_name == "click_href")
+ {
+ mClickURL = message.getValue("uri");
+ mClickTarget = message.getValue("target");
+ mClickUUID = message.getValue("uuid");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_HREF);
+ }
+ else if(message_name == "click_nofollow")
+ {
+ mClickURL = message.getValue("uri");
+ mClickNavType = message.getValue("nav_type");
+ mClickTarget.clear();
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_NOFOLLOW);
+ }
+ else if(message_name == "navigate_error_page")
+ {
+ mStatusCode = message.getValueS32("status_code");
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_ERROR_PAGE);
+ }
+ else if(message_name == "cookie_set")
+ {
+ if(mOwner)
+ {
+ mOwner->handleCookieSet(this, message.getValue("cookie"));
+ }
+ }
+ else if(message_name == "close_request")
+ {
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLOSE_REQUEST);
+ }
+ else if(message_name == "geometry_change")
+ {
+ mClickUUID = message.getValue("uuid");
+ mGeometryX = message.getValueS32("x");
+ mGeometryY = message.getValueS32("y");
+ mGeometryWidth = message.getValueS32("width");
+ mGeometryHeight = message.getValueS32("height");
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_GEOMETRY_CHANGE);
+ }
+ else if(message_name == "link_hovered")
+ {
+ // text is not currently used -- the tooltip hover text is taken from the "title".
+ mHoverLink = message.getValue("link");
+ mHoverText = message.getValue("title");
+ // message.getValue("text");
+
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LINK_HOVERED);
+ }
+ else
+ {
+ LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
+ }
+ }
+ else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
+ {
+ std::string message_name = message.getName();
+
+ // This class hasn't defined any incoming messages yet.
+// if(message_name == "message_name")
+// {
+// }
+// else
+ {
+ LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL;
+ }
+ }
+
+}
+
+/* virtual */
+void LLPluginClassMedia::pluginLaunchFailed()
+{
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED_LAUNCH);
+}
+
+/* virtual */
+void LLPluginClassMedia::pluginDied()
+{
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED);
+}
+
+void LLPluginClassMedia::mediaEvent(LLPluginClassMediaOwner::EMediaEvent event)
+{
+ if(mOwner)
+ {
+ mOwner->handleMediaEvent(this, event);
+ }
+}
+
+void LLPluginClassMedia::sendMessage(const LLPluginMessage &message)
+{
+ if(mPlugin && mPlugin->isRunning())
+ {
+ mPlugin->sendMessage(message);
+ }
+ else
+ {
+ // The plugin isn't set up yet -- queue this message to be sent after initialization.
+ mSendQueue.push(message);
+ }
+}
+
+////////////////////////////////////////////////////////////
+// MARK: media_browser class functions
+bool LLPluginClassMedia::pluginSupportsMediaBrowser(void)
+{
+ std::string version = mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER);
+ return !version.empty();
+}
+
+void LLPluginClassMedia::focus(bool focused)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "focus");
+
+ message.setValueBoolean("focused", focused);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::clear_cache()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cache");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::clear_cookies()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cookies");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::set_cookies(const std::string &cookies)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_cookies");
+ message.setValue("cookies", cookies);
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::enable_cookies(bool enable)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "enable_cookies");
+ message.setValueBoolean("enable", enable);
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::proxy_setup(bool enable, const std::string &host, int port)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_setup");
+
+ message.setValueBoolean("enable", enable);
+ message.setValue("host", host);
+ message.setValueS32("port", port);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::browse_stop()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_stop");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::browse_reload(bool ignore_cache)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_reload");
+
+ message.setValueBoolean("ignore_cache", ignore_cache);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::browse_forward()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_forward");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::browse_back()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "browse_back");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::setBrowserUserAgent(const std::string& user_agent)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_user_agent");
+
+ message.setValue("user_agent", user_agent);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::proxyWindowOpened(const std::string &target, const std::string &uuid)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_window_opened");
+
+ message.setValue("target", target);
+ message.setValue("uuid", uuid);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::proxyWindowClosed(const std::string &uuid)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_window_closed");
+
+ message.setValue("uuid", uuid);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::ignore_ssl_cert_errors(bool ignore)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "ignore_ssl_cert_errors");
+ message.setValueBoolean("ignore", ignore);
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::addCertificateFilePath(const std::string& path)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "add_certificate_file_path");
+ message.setValue("path", path);
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::crashPlugin()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "crash");
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::hangPlugin()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "hang");
+
+ sendMessage(message);
+}
+
+
+////////////////////////////////////////////////////////////
+// MARK: media_time class functions
+bool LLPluginClassMedia::pluginSupportsMediaTime(void)
+{
+ std::string version = mPlugin->getMessageClassVersion(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME);
+ return !version.empty();
+}
+
+void LLPluginClassMedia::stop()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "stop");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::start(float rate)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "start");
+
+ message.setValueReal("rate", rate);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::pause()
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "pause");
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::seek(float time)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "seek");
+
+ message.setValueReal("time", time);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::setLoop(bool loop)
+{
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "set_loop");
+
+ message.setValueBoolean("loop", loop);
+
+ sendMessage(message);
+}
+
+void LLPluginClassMedia::setVolume(float volume)
+{
+ if(volume != mRequestedVolume)
+ {
+ mRequestedVolume = volume;
+
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME, "set_volume");
+
+ message.setValueReal("volume", volume);
+
+ sendMessage(message);
+ }
+}
+
+float LLPluginClassMedia::getVolume()
+{
+ return mRequestedVolume;
+}
+
+void LLPluginClassMedia::initializeUrlHistory(const LLSD& url_history)
+{
+ // Send URL history to plugin
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "init_history");
+ message.setValueLLSD("history", url_history);
+ sendMessage(message);
+
+ LL_DEBUGS("Plugin") << "Sending history" << LL_ENDL;
+}
+
diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h
index fea836aa68..f8ed89f644 100644
--- a/indra/llplugin/llpluginclassmedia.h
+++ b/indra/llplugin/llpluginclassmedia.h
@@ -1,426 +1,425 @@
-/**
- * @file llpluginclassmedia.h
- * @brief LLPluginClassMedia handles interaction with a plugin which knows about the "media" message class.
- *
- * @cond
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- * @endcond
- */
-
-#ifndef LL_LLPLUGINCLASSMEDIA_H
-#define LL_LLPLUGINCLASSMEDIA_H
-
-#include "llgltypes.h"
-#include "llpluginprocessparent.h"
-#include "llrect.h"
-#include "llpluginclassmediaowner.h"
-#include <queue>
-#include "v4color.h"
-
-class LLPluginClassMedia : public LLPluginProcessParentOwner
-{
- LOG_CLASS(LLPluginClassMedia);
-public:
- LLPluginClassMedia(LLPluginClassMediaOwner *owner);
- virtual ~LLPluginClassMedia();
-
- // local initialization, called by the media manager when creating a source
- virtual bool init(const std::string &launcher_filename,
- const std::string &plugin_dir,
- const std::string &plugin_filename,
- bool debug);
-
- // undoes everything init() didm called by the media manager when destroying a source
- virtual void reset();
-
- void idle(void);
-
- // All of these may return 0 or an actual valid value.
- // Callers need to check the return for 0, and not use the values in that case.
- int getWidth() const { return (mMediaWidth > 0) ? mMediaWidth : 0; };
- int getHeight() const { return (mMediaHeight > 0) ? mMediaHeight : 0; };
- int getNaturalWidth() const { return mNaturalMediaWidth; };
- int getNaturalHeight() const { return mNaturalMediaHeight; };
- int getSetWidth() const { return mSetMediaWidth; };
- int getSetHeight() const { return mSetMediaHeight; };
- int getBitsWidth() const { return (mTextureWidth > 0) ? mTextureWidth : 0; };
- int getBitsHeight() const { return (mTextureHeight > 0) ? mTextureHeight : 0; };
- int getTextureWidth() const;
- int getTextureHeight() const;
- int getFullWidth() const { return mFullMediaWidth; };
- int getFullHeight() const { return mFullMediaHeight; };
-
- // This may return NULL. Callers need to check for and handle this case.
- unsigned char* getBitsData();
-
- // gets the format details of the texture data
- // These may return 0 if they haven't been set up yet. The caller needs to detect this case.
- int getTextureDepth() const { return mRequestedTextureDepth; };
- int getTextureFormatInternal() const { return mRequestedTextureInternalFormat; };
- int getTextureFormatPrimary() const { return mRequestedTextureFormat; };
- int getTextureFormatType() const { return mRequestedTextureType; };
- bool getTextureFormatSwapBytes() const { return mRequestedTextureSwapBytes; };
- bool getTextureCoordsOpenGL() const { return mRequestedTextureCoordsOpenGL; };
-
- void setSize(int width, int height);
- void setAutoScale(bool auto_scale);
-
- void setBackgroundColor(LLColor4 color) { mBackgroundColor = color; };
-
- void setOwner(LLPluginClassMediaOwner *owner) { mOwner = owner; };
-
- // Returns true if all of the texture parameters (depth, format, size, and texture size) are set up and consistent.
- // This will initially be false, and will also be false for some time after setSize while the resize is processed.
- // Note that if this returns true, it is safe to use all the get() functions above without checking for invalid return values
- // until you call idle() again.
- bool textureValid(void);
-
- bool getDirty(LLRect *dirty_rect = NULL);
- void resetDirty(void);
-
- typedef enum
- {
- MOUSE_EVENT_DOWN,
- MOUSE_EVENT_UP,
- MOUSE_EVENT_MOVE,
- MOUSE_EVENT_DOUBLE_CLICK
- }EMouseEventType;
-
- void mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers);
-
- typedef enum
- {
- KEY_EVENT_DOWN,
- KEY_EVENT_UP,
- KEY_EVENT_REPEAT
- }EKeyEventType;
-
- bool keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data);
-
- void scrollEvent(int x, int y, MASK modifiers);
-
- // Javascript <-> viewer events
- void jsExposeObjectEvent( bool expose );
- void jsValuesValidEvent( bool valid );
- void jsAgentLocationEvent( double x, double y, double z );
- void jsAgentGlobalLocationEvent( double x, double y, double z );
- void jsAgentOrientationEvent( double angle );
- void jsAgentLanguageEvent( const std::string& language );
- void jsAgentRegionEvent( const std::string& region_name );
- void jsAgentMaturityEvent( const std::string& maturity );
-
- // Text may be unicode (utf8 encoded)
- bool textInput(const std::string &text, MASK modifiers, LLSD native_key_data);
-
- void loadURI(const std::string &uri);
-
- // "Loading" means uninitialized or any state prior to fully running (processing commands)
- bool isPluginLoading(void) { return mPlugin?mPlugin->isLoading():false; };
-
- // "Running" means the steady state -- i.e. processing messages
- bool isPluginRunning(void) { return mPlugin?mPlugin->isRunning():false; };
-
- // "Exited" means any regular or error state after "Running" (plugin may have crashed or exited normally)
- bool isPluginExited(void) { return mPlugin?mPlugin->isDone():false; };
-
- std::string getPluginVersion() { return mPlugin?mPlugin->getPluginVersion():std::string(""); };
-
- bool getDisableTimeout() { return mPlugin?mPlugin->getDisableTimeout():false; };
- void setDisableTimeout(bool disable) { if(mPlugin) mPlugin->setDisableTimeout(disable); };
-
- // Inherited from LLPluginProcessParentOwner
- /* virtual */ void receivePluginMessage(const LLPluginMessage &message);
- /* virtual */ void pluginLaunchFailed();
- /* virtual */ void pluginDied();
-
-
- typedef enum
- {
- PRIORITY_UNLOADED, // media plugin isn't even loaded.
- PRIORITY_STOPPED, // media is not playing, shouldn't need to update at all.
- PRIORITY_HIDDEN, // media is not being displayed or is out of view, don't need to do graphic updates, but may still update audio, playhead, etc.
- PRIORITY_SLIDESHOW, // media is in the far distance, updates very infrequently
- PRIORITY_LOW, // media is in the distance, may be rendered at reduced size
- PRIORITY_NORMAL, // normal (default) priority
- PRIORITY_HIGH // media has user focus and/or is taking up most of the screen
- }EPriority;
-
- static const char* priorityToString(EPriority priority);
- void setPriority(EPriority priority);
- void setLowPrioritySizeLimit(int size);
-
- F64 getCPUUsage();
-
- void sendPickFileResponse(const std::string &file);
-
- void sendAuthResponse(bool ok, const std::string &username, const std::string &password);
-
- // Valid after a MEDIA_EVENT_CURSOR_CHANGED event
- std::string getCursorName() const { return mCursorName; };
-
- LLPluginClassMediaOwner::EMediaStatus getStatus() const { return mStatus; }
-
- void cut();
- bool canCut() const { return mCanCut; };
-
- void copy();
- bool canCopy() const { return mCanCopy; };
-
- void paste();
- bool canPaste() const { return mCanPaste; };
-
- // These can be called before init(), and they will be queued and sent before the media init message.
- void setUserDataPath(const std::string &user_data_path);
- void setLanguageCode(const std::string &language_code);
- void setPluginsEnabled(const bool enabled);
- void setJavascriptEnabled(const bool enabled);
- void setTarget(const std::string &target);
-
- ///////////////////////////////////
- // media browser class functions
- bool pluginSupportsMediaBrowser(void);
-
- void focus(bool focused);
- void clear_cache();
- void clear_cookies();
- void set_cookies(const std::string &cookies);
- void enable_cookies(bool enable);
- void proxy_setup(bool enable, const std::string &host = LLStringUtil::null, int port = 0);
- void browse_stop();
- void browse_reload(bool ignore_cache = false);
- void browse_forward();
- void browse_back();
- void setBrowserUserAgent(const std::string& user_agent);
- void proxyWindowOpened(const std::string &target, const std::string &uuid);
- void proxyWindowClosed(const std::string &uuid);
- void ignore_ssl_cert_errors(bool ignore);
- void addCertificateFilePath(const std::string& path);
-
- // This is valid after MEDIA_EVENT_NAVIGATE_BEGIN or MEDIA_EVENT_NAVIGATE_COMPLETE
- std::string getNavigateURI() const { return mNavigateURI; };
-
- // These are valid after MEDIA_EVENT_NAVIGATE_COMPLETE
- S32 getNavigateResultCode() const { return mNavigateResultCode; };
- std::string getNavigateResultString() const { return mNavigateResultString; };
- bool getHistoryBackAvailable() const { return mHistoryBackAvailable; };
- bool getHistoryForwardAvailable() const { return mHistoryForwardAvailable; };
-
- // This is valid after MEDIA_EVENT_PROGRESS_UPDATED
- int getProgressPercent() const { return mProgressPercent; };
-
- // This is valid after MEDIA_EVENT_STATUS_TEXT_CHANGED
- std::string getStatusText() const { return mStatusText; };
-
- // This is valid after MEDIA_EVENT_LOCATION_CHANGED
- std::string getLocation() const { return mLocation; };
-
- // This is valid after MEDIA_EVENT_CLICK_LINK_HREF or MEDIA_EVENT_CLICK_LINK_NOFOLLOW
- std::string getClickURL() const { return mClickURL; };
-
- // This is valid after MEDIA_EVENT_CLICK_LINK_NOFOLLOW
- std::string getClickNavType() const { return mClickNavType; };
-
- // This is valid after MEDIA_EVENT_CLICK_LINK_HREF
- std::string getClickTarget() const { return mClickTarget; };
-
- // This is valid during MEDIA_EVENT_CLICK_LINK_HREF and MEDIA_EVENT_GEOMETRY_CHANGE
- std::string getClickUUID() const { return mClickUUID; };
-
- // This is valid after MEDIA_EVENT_NAVIGATE_ERROR_PAGE
- S32 getStatusCode() const { return mStatusCode; };
-
- // These are valid during MEDIA_EVENT_GEOMETRY_CHANGE
- S32 getGeometryX() const { return mGeometryX; };
- S32 getGeometryY() const { return mGeometryY; };
- S32 getGeometryWidth() const { return mGeometryWidth; };
- S32 getGeometryHeight() const { return mGeometryHeight; };
-
- // These are valid during MEDIA_EVENT_AUTH_REQUEST
- std::string getAuthURL() const { return mAuthURL; };
- std::string getAuthRealm() const { return mAuthRealm; };
-
- // These are valid during MEDIA_EVENT_LINK_HOVERED
- std::string getHoverText() const { return mHoverText; };
- std::string getHoverLink() const { return mHoverLink; };
-
- std::string getMediaName() const { return mMediaName; };
- std::string getMediaDescription() const { return mMediaDescription; };
-
- // Crash the plugin. If you use this outside of a testbed, you will be punished.
- void crashPlugin();
-
- // Hang the plugin. If you use this outside of a testbed, you will be punished.
- void hangPlugin();
-
- ///////////////////////////////////
- // media time class functions
- bool pluginSupportsMediaTime(void);
- void stop();
- void start(float rate = 0.0f);
- void pause();
- void seek(float time);
- void setLoop(bool loop);
- void setVolume(float volume);
- float getVolume();
-
- F64 getCurrentTime(void) const { return mCurrentTime; };
- F64 getDuration(void) const { return mDuration; };
- F64 getCurrentPlayRate(void) { return mCurrentRate; };
- F64 getLoadedDuration(void) const { return mLoadedDuration; };
-
- // Initialize the URL history of the plugin by sending
- // "init_history" message
- void initializeUrlHistory(const LLSD& url_history);
-
-protected:
-
- LLPluginClassMediaOwner *mOwner;
-
- // Notify this object's owner that an event has occurred.
- void mediaEvent(LLPluginClassMediaOwner::EMediaEvent event);
-
- void sendMessage(const LLPluginMessage &message); // Send message internally, either queueing or sending directly.
- std::queue<LLPluginMessage> mSendQueue; // Used to queue messages while the plugin initializes.
-
- void setSizeInternal(void);
-
- bool mTextureParamsReceived; // the mRequestedTexture* fields are only valid when this is true
- S32 mRequestedTextureDepth;
- LLGLenum mRequestedTextureInternalFormat;
- LLGLenum mRequestedTextureFormat;
- LLGLenum mRequestedTextureType;
- bool mRequestedTextureSwapBytes;
- bool mRequestedTextureCoordsOpenGL;
-
- std::string mTextureSharedMemoryName;
- size_t mTextureSharedMemorySize;
-
- // True to scale requested media up to the full size of the texture (i.e. next power of two)
- bool mAutoScaleMedia;
-
- // default media size for the plugin, from the texture_params message.
- int mDefaultMediaWidth;
- int mDefaultMediaHeight;
-
- // Size that has been requested by the plugin itself
- int mNaturalMediaWidth;
- int mNaturalMediaHeight;
-
- // Size that has been requested with setSize()
- int mSetMediaWidth;
- int mSetMediaHeight;
-
- // Full calculated media size (before auto-scale and downsample calculations)
- int mFullMediaWidth;
- int mFullMediaHeight;
-
- // Actual media size being set (after auto-scale)
- int mRequestedMediaWidth;
- int mRequestedMediaHeight;
-
- // Texture size calculated from actual media size
- int mRequestedTextureWidth;
- int mRequestedTextureHeight;
-
- // Size that the plugin has acknowledged
- int mTextureWidth;
- int mTextureHeight;
- int mMediaWidth;
- int mMediaHeight;
-
- float mRequestedVolume;
-
- // Priority of this media stream
- EPriority mPriority;
- int mLowPrioritySizeLimit;
-
- bool mAllowDownsample;
- int mPadding;
-
-
- LLPluginProcessParent *mPlugin;
-
- LLRect mDirtyRect;
-
- std::string translateModifiers(MASK modifiers);
-
- std::string mCursorName;
- int mLastMouseX;
- int mLastMouseY;
-
- LLPluginClassMediaOwner::EMediaStatus mStatus;
-
- F64 mSleepTime;
-
- bool mCanCut;
- bool mCanCopy;
- bool mCanPaste;
-
- std::string mMediaName;
- std::string mMediaDescription;
-
- LLColor4 mBackgroundColor;
-
- std::string mTarget;
-
- /////////////////////////////////////////
- // media_browser class
- std::string mNavigateURI;
- S32 mNavigateResultCode;
- std::string mNavigateResultString;
- bool mHistoryBackAvailable;
- bool mHistoryForwardAvailable;
- std::string mStatusText;
- int mProgressPercent;
- std::string mLocation;
- std::string mClickURL;
- std::string mClickNavType;
- std::string mClickTarget;
- std::string mClickUUID;
- S32 mGeometryX;
- S32 mGeometryY;
- S32 mGeometryWidth;
- S32 mGeometryHeight;
- S32 mStatusCode;
- std::string mAuthURL;
- std::string mAuthRealm;
- std::string mHoverText;
- std::string mHoverLink;
-
- /////////////////////////////////////////
- // media_time class
- F64 mCurrentTime;
- F64 mDuration;
- F64 mCurrentRate;
- F64 mLoadedDuration;
-
-//--------------------------------------
- //debug use only
- //
-private:
- bool mDeleteOK ;
-public:
- void setDeleteOK(bool flag) { mDeleteOK = flag ;}
-//--------------------------------------
-};
-
-#endif // LL_LLPLUGINCLASSMEDIA_H
+/**
+ * @file llpluginclassmedia.h
+ * @brief LLPluginClassMedia handles interaction with a plugin which knows about the "media" message class.
+ *
+ * @cond
+ * $LicenseInfo:firstyear=2008&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ * @endcond
+ */
+
+#ifndef LL_LLPLUGINCLASSMEDIA_H
+#define LL_LLPLUGINCLASSMEDIA_H
+
+#include "llgltypes.h"
+#include "llpluginprocessparent.h"
+#include "llrect.h"
+#include "llpluginclassmediaowner.h"
+#include <queue>
+#include "v4color.h"
+
+class LLPluginClassMedia : public LLPluginProcessParentOwner
+{
+ LOG_CLASS(LLPluginClassMedia);
+public:
+ LLPluginClassMedia(LLPluginClassMediaOwner *owner);
+ virtual ~LLPluginClassMedia();
+
+ // local initialization, called by the media manager when creating a source
+ virtual bool init(const std::string &launcher_filename,
+ const std::string &plugin_dir,
+ const std::string &plugin_filename,
+ bool debug);
+
+ // undoes everything init() didm called by the media manager when destroying a source
+ virtual void reset();
+
+ void idle(void);
+
+ // All of these may return 0 or an actual valid value.
+ // Callers need to check the return for 0, and not use the values in that case.
+ int getWidth() const { return (mMediaWidth > 0) ? mMediaWidth : 0; };
+ int getHeight() const { return (mMediaHeight > 0) ? mMediaHeight : 0; };
+ int getNaturalWidth() const { return mNaturalMediaWidth; };
+ int getNaturalHeight() const { return mNaturalMediaHeight; };
+ int getSetWidth() const { return mSetMediaWidth; };
+ int getSetHeight() const { return mSetMediaHeight; };
+ int getBitsWidth() const { return (mTextureWidth > 0) ? mTextureWidth : 0; };
+ int getBitsHeight() const { return (mTextureHeight > 0) ? mTextureHeight : 0; };
+ int getTextureWidth() const;
+ int getTextureHeight() const;
+ int getFullWidth() const { return mFullMediaWidth; };
+ int getFullHeight() const { return mFullMediaHeight; };
+
+ // This may return NULL. Callers need to check for and handle this case.
+ unsigned char* getBitsData();
+
+ // gets the format details of the texture data
+ // These may return 0 if they haven't been set up yet. The caller needs to detect this case.
+ int getTextureDepth() const { return mRequestedTextureDepth; };
+ int getTextureFormatInternal() const { return mRequestedTextureInternalFormat; };
+ int getTextureFormatPrimary() const { return mRequestedTextureFormat; };
+ int getTextureFormatType() const { return mRequestedTextureType; };
+ bool getTextureFormatSwapBytes() const { return mRequestedTextureSwapBytes; };
+ bool getTextureCoordsOpenGL() const { return mRequestedTextureCoordsOpenGL; };
+
+ void setSize(int width, int height);
+ void setAutoScale(bool auto_scale);
+
+ void setBackgroundColor(LLColor4 color) { mBackgroundColor = color; };
+
+ void setOwner(LLPluginClassMediaOwner *owner) { mOwner = owner; };
+
+ // Returns true if all of the texture parameters (depth, format, size, and texture size) are set up and consistent.
+ // This will initially be false, and will also be false for some time after setSize while the resize is processed.
+ // Note that if this returns true, it is safe to use all the get() functions above without checking for invalid return values
+ // until you call idle() again.
+ bool textureValid(void);
+
+ bool getDirty(LLRect *dirty_rect = NULL);
+ void resetDirty(void);
+
+ typedef enum
+ {
+ MOUSE_EVENT_DOWN,
+ MOUSE_EVENT_UP,
+ MOUSE_EVENT_MOVE,
+ MOUSE_EVENT_DOUBLE_CLICK
+ }EMouseEventType;
+
+ void mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers);
+
+ typedef enum
+ {
+ KEY_EVENT_DOWN,
+ KEY_EVENT_UP,
+ KEY_EVENT_REPEAT
+ }EKeyEventType;
+
+ bool keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data);
+
+ void scrollEvent(int x, int y, MASK modifiers);
+
+ // Javascript <-> viewer events
+ void jsEnableObject( bool enable );
+ void jsAgentLocationEvent( double x, double y, double z );
+ void jsAgentGlobalLocationEvent( double x, double y, double z );
+ void jsAgentOrientationEvent( double angle );
+ void jsAgentLanguageEvent( const std::string& language );
+ void jsAgentRegionEvent( const std::string& region_name );
+ void jsAgentMaturityEvent( const std::string& maturity );
+
+ // Text may be unicode (utf8 encoded)
+ bool textInput(const std::string &text, MASK modifiers, LLSD native_key_data);
+
+ void loadURI(const std::string &uri);
+
+ // "Loading" means uninitialized or any state prior to fully running (processing commands)
+ bool isPluginLoading(void) { return mPlugin?mPlugin->isLoading():false; };
+
+ // "Running" means the steady state -- i.e. processing messages
+ bool isPluginRunning(void) { return mPlugin?mPlugin->isRunning():false; };
+
+ // "Exited" means any regular or error state after "Running" (plugin may have crashed or exited normally)
+ bool isPluginExited(void) { return mPlugin?mPlugin->isDone():false; };
+
+ std::string getPluginVersion() { return mPlugin?mPlugin->getPluginVersion():std::string(""); };
+
+ bool getDisableTimeout() { return mPlugin?mPlugin->getDisableTimeout():false; };
+ void setDisableTimeout(bool disable) { if(mPlugin) mPlugin->setDisableTimeout(disable); };
+
+ // Inherited from LLPluginProcessParentOwner
+ /* virtual */ void receivePluginMessage(const LLPluginMessage &message);
+ /* virtual */ void pluginLaunchFailed();
+ /* virtual */ void pluginDied();
+
+
+ typedef enum
+ {
+ PRIORITY_UNLOADED, // media plugin isn't even loaded.
+ PRIORITY_STOPPED, // media is not playing, shouldn't need to update at all.
+ PRIORITY_HIDDEN, // media is not being displayed or is out of view, don't need to do graphic updates, but may still update audio, playhead, etc.
+ PRIORITY_SLIDESHOW, // media is in the far distance, updates very infrequently
+ PRIORITY_LOW, // media is in the distance, may be rendered at reduced size
+ PRIORITY_NORMAL, // normal (default) priority
+ PRIORITY_HIGH // media has user focus and/or is taking up most of the screen
+ }EPriority;
+
+ static const char* priorityToString(EPriority priority);
+ void setPriority(EPriority priority);
+ void setLowPrioritySizeLimit(int size);
+
+ F64 getCPUUsage();
+
+ void sendPickFileResponse(const std::string &file);
+
+ void sendAuthResponse(bool ok, const std::string &username, const std::string &password);
+
+ // Valid after a MEDIA_EVENT_CURSOR_CHANGED event
+ std::string getCursorName() const { return mCursorName; };
+
+ LLPluginClassMediaOwner::EMediaStatus getStatus() const { return mStatus; }
+
+ void cut();
+ bool canCut() const { return mCanCut; };
+
+ void copy();
+ bool canCopy() const { return mCanCopy; };
+
+ void paste();
+ bool canPaste() const { return mCanPaste; };
+
+ // These can be called before init(), and they will be queued and sent before the media init message.
+ void setUserDataPath(const std::string &user_data_path);
+ void setLanguageCode(const std::string &language_code);
+ void setPluginsEnabled(const bool enabled);
+ void setJavascriptEnabled(const bool enabled);
+ void setTarget(const std::string &target);
+
+ ///////////////////////////////////
+ // media browser class functions
+ bool pluginSupportsMediaBrowser(void);
+
+ void focus(bool focused);
+ void clear_cache();
+ void clear_cookies();
+ void set_cookies(const std::string &cookies);
+ void enable_cookies(bool enable);
+ void proxy_setup(bool enable, const std::string &host = LLStringUtil::null, int port = 0);
+ void browse_stop();
+ void browse_reload(bool ignore_cache = false);
+ void browse_forward();
+ void browse_back();
+ void setBrowserUserAgent(const std::string& user_agent);
+ void proxyWindowOpened(const std::string &target, const std::string &uuid);
+ void proxyWindowClosed(const std::string &uuid);
+ void ignore_ssl_cert_errors(bool ignore);
+ void addCertificateFilePath(const std::string& path);
+
+ // This is valid after MEDIA_EVENT_NAVIGATE_BEGIN or MEDIA_EVENT_NAVIGATE_COMPLETE
+ std::string getNavigateURI() const { return mNavigateURI; };
+
+ // These are valid after MEDIA_EVENT_NAVIGATE_COMPLETE
+ S32 getNavigateResultCode() const { return mNavigateResultCode; };
+ std::string getNavigateResultString() const { return mNavigateResultString; };
+ bool getHistoryBackAvailable() const { return mHistoryBackAvailable; };
+ bool getHistoryForwardAvailable() const { return mHistoryForwardAvailable; };
+
+ // This is valid after MEDIA_EVENT_PROGRESS_UPDATED
+ int getProgressPercent() const { return mProgressPercent; };
+
+ // This is valid after MEDIA_EVENT_STATUS_TEXT_CHANGED
+ std::string getStatusText() const { return mStatusText; };
+
+ // This is valid after MEDIA_EVENT_LOCATION_CHANGED
+ std::string getLocation() const { return mLocation; };
+
+ // This is valid after MEDIA_EVENT_CLICK_LINK_HREF or MEDIA_EVENT_CLICK_LINK_NOFOLLOW
+ std::string getClickURL() const { return mClickURL; };
+
+ // This is valid after MEDIA_EVENT_CLICK_LINK_NOFOLLOW
+ std::string getClickNavType() const { return mClickNavType; };
+
+ // This is valid after MEDIA_EVENT_CLICK_LINK_HREF
+ std::string getClickTarget() const { return mClickTarget; };
+
+ // This is valid during MEDIA_EVENT_CLICK_LINK_HREF and MEDIA_EVENT_GEOMETRY_CHANGE
+ std::string getClickUUID() const { return mClickUUID; };
+
+ // This is valid after MEDIA_EVENT_NAVIGATE_ERROR_PAGE
+ S32 getStatusCode() const { return mStatusCode; };
+
+ // These are valid during MEDIA_EVENT_GEOMETRY_CHANGE
+ S32 getGeometryX() const { return mGeometryX; };
+ S32 getGeometryY() const { return mGeometryY; };
+ S32 getGeometryWidth() const { return mGeometryWidth; };
+ S32 getGeometryHeight() const { return mGeometryHeight; };
+
+ // These are valid during MEDIA_EVENT_AUTH_REQUEST
+ std::string getAuthURL() const { return mAuthURL; };
+ std::string getAuthRealm() const { return mAuthRealm; };
+
+ // These are valid during MEDIA_EVENT_LINK_HOVERED
+ std::string getHoverText() const { return mHoverText; };
+ std::string getHoverLink() const { return mHoverLink; };
+
+ std::string getMediaName() const { return mMediaName; };
+ std::string getMediaDescription() const { return mMediaDescription; };
+
+ // Crash the plugin. If you use this outside of a testbed, you will be punished.
+ void crashPlugin();
+
+ // Hang the plugin. If you use this outside of a testbed, you will be punished.
+ void hangPlugin();
+
+ ///////////////////////////////////
+ // media time class functions
+ bool pluginSupportsMediaTime(void);
+ void stop();
+ void start(float rate = 0.0f);
+ void pause();
+ void seek(float time);
+ void setLoop(bool loop);
+ void setVolume(float volume);
+ float getVolume();
+
+ F64 getCurrentTime(void) const { return mCurrentTime; };
+ F64 getDuration(void) const { return mDuration; };
+ F64 getCurrentPlayRate(void) { return mCurrentRate; };
+ F64 getLoadedDuration(void) const { return mLoadedDuration; };
+
+ // Initialize the URL history of the plugin by sending
+ // "init_history" message
+ void initializeUrlHistory(const LLSD& url_history);
+
+protected:
+
+ LLPluginClassMediaOwner *mOwner;
+
+ // Notify this object's owner that an event has occurred.
+ void mediaEvent(LLPluginClassMediaOwner::EMediaEvent event);
+
+ void sendMessage(const LLPluginMessage &message); // Send message internally, either queueing or sending directly.
+ std::queue<LLPluginMessage> mSendQueue; // Used to queue messages while the plugin initializes.
+
+ void setSizeInternal(void);
+
+ bool mTextureParamsReceived; // the mRequestedTexture* fields are only valid when this is true
+ S32 mRequestedTextureDepth;
+ LLGLenum mRequestedTextureInternalFormat;
+ LLGLenum mRequestedTextureFormat;
+ LLGLenum mRequestedTextureType;
+ bool mRequestedTextureSwapBytes;
+ bool mRequestedTextureCoordsOpenGL;
+
+ std::string mTextureSharedMemoryName;
+ size_t mTextureSharedMemorySize;
+
+ // True to scale requested media up to the full size of the texture (i.e. next power of two)
+ bool mAutoScaleMedia;
+
+ // default media size for the plugin, from the texture_params message.
+ int mDefaultMediaWidth;
+ int mDefaultMediaHeight;
+
+ // Size that has been requested by the plugin itself
+ int mNaturalMediaWidth;
+ int mNaturalMediaHeight;
+
+ // Size that has been requested with setSize()
+ int mSetMediaWidth;
+ int mSetMediaHeight;
+
+ // Full calculated media size (before auto-scale and downsample calculations)
+ int mFullMediaWidth;
+ int mFullMediaHeight;
+
+ // Actual media size being set (after auto-scale)
+ int mRequestedMediaWidth;
+ int mRequestedMediaHeight;
+
+ // Texture size calculated from actual media size
+ int mRequestedTextureWidth;
+ int mRequestedTextureHeight;
+
+ // Size that the plugin has acknowledged
+ int mTextureWidth;
+ int mTextureHeight;
+ int mMediaWidth;
+ int mMediaHeight;
+
+ float mRequestedVolume;
+
+ // Priority of this media stream
+ EPriority mPriority;
+ int mLowPrioritySizeLimit;
+
+ bool mAllowDownsample;
+ int mPadding;
+
+
+ LLPluginProcessParent *mPlugin;
+
+ LLRect mDirtyRect;
+
+ std::string translateModifiers(MASK modifiers);
+
+ std::string mCursorName;
+ int mLastMouseX;
+ int mLastMouseY;
+
+ LLPluginClassMediaOwner::EMediaStatus mStatus;
+
+ F64 mSleepTime;
+
+ bool mCanCut;
+ bool mCanCopy;
+ bool mCanPaste;
+
+ std::string mMediaName;
+ std::string mMediaDescription;
+
+ LLColor4 mBackgroundColor;
+
+ std::string mTarget;
+
+ /////////////////////////////////////////
+ // media_browser class
+ std::string mNavigateURI;
+ S32 mNavigateResultCode;
+ std::string mNavigateResultString;
+ bool mHistoryBackAvailable;
+ bool mHistoryForwardAvailable;
+ std::string mStatusText;
+ int mProgressPercent;
+ std::string mLocation;
+ std::string mClickURL;
+ std::string mClickNavType;
+ std::string mClickTarget;
+ std::string mClickUUID;
+ S32 mGeometryX;
+ S32 mGeometryY;
+ S32 mGeometryWidth;
+ S32 mGeometryHeight;
+ S32 mStatusCode;
+ std::string mAuthURL;
+ std::string mAuthRealm;
+ std::string mHoverText;
+ std::string mHoverLink;
+
+ /////////////////////////////////////////
+ // media_time class
+ F64 mCurrentTime;
+ F64 mDuration;
+ F64 mCurrentRate;
+ F64 mLoadedDuration;
+
+//--------------------------------------
+ //debug use only
+ //
+private:
+ bool mDeleteOK ;
+public:
+ void setDeleteOK(bool flag) { mDeleteOK = flag ;}
+//--------------------------------------
+};
+
+#endif // LL_LLPLUGINCLASSMEDIA_H
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt
index 5914c3551a..0bbdcfd6ff 100644
--- a/indra/llui/CMakeLists.txt
+++ b/indra/llui/CMakeLists.txt
@@ -28,6 +28,8 @@ include_directories(
set(llui_SOURCE_FILES
llaccordionctrl.cpp
llaccordionctrltab.cpp
+ llbadge.cpp
+ llbadgeowner.cpp
llbutton.cpp
llcheckboxctrl.cpp
llclipboard.cpp
@@ -120,6 +122,8 @@ set(llui_HEADER_FILES
llaccordionctrl.h
llaccordionctrltab.h
+ llbadge.h
+ llbadgeowner.h
llbutton.h
llcallbackmap.h
llcheckboxctrl.h
@@ -247,11 +251,11 @@ target_link_libraries(llui
)
# Add tests
-if (LL_TESTS)
- include(LLAddBuildTest)
- SET(llui_TEST_SOURCE_FILES
- llurlmatch.cpp
- llurlentry.cpp
- )
- LL_ADD_PROJECT_UNIT_TESTS(llui "${llui_TEST_SOURCE_FILES}")
-endif (LL_TESTS) \ No newline at end of file
+if(LL_TESTS)
+ include(LLAddBuildTest)
+ SET(llui_TEST_SOURCE_FILES
+ llurlmatch.cpp
+ llurlentry.cpp
+ )
+ LL_ADD_PROJECT_UNIT_TESTS(llui "${llui_TEST_SOURCE_FILES}")
+endif(LL_TESTS)
diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp
index 9e4849c58b..6afe276379 100644
--- a/indra/llui/llaccordionctrltab.cpp
+++ b/indra/llui/llaccordionctrltab.cpp
@@ -1022,7 +1022,7 @@ void LLAccordionCtrlTab::updateLayout ( const LLRect& child_rect )
S32 panel_width = child_rect.getWidth();
static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
- if(mScrollbar->getVisible() != false)
+ if(mScrollbar && mScrollbar->getVisible() != false)
{
panel_top+=mScrollbar->getDocPos();
panel_width-=scrollbar_size;
diff --git a/indra/llui/llbadge.cpp b/indra/llui/llbadge.cpp
new file mode 100644
index 0000000000..c28a947a7f
--- /dev/null
+++ b/indra/llui/llbadge.cpp
@@ -0,0 +1,274 @@
+/**
+ * @file llbadge.cpp
+ * @brief Implementation for badges
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#define LLBADGE_CPP
+#include "llbadge.h"
+
+#include "lluictrlfactory.h"
+
+
+static LLDefaultChildRegistry::Register<LLBadge> r("badge");
+
+// Compiler optimization, generate extern template
+template class LLBadge* LLView::getChild<class LLBadge>(const std::string& name, BOOL recurse) const;
+
+
+LLBadge::Params::Params()
+ : image("image")
+ , border_image("border_image")
+ , border_color("border_color")
+ , image_color("image_color")
+ , label("label")
+ , label_color("label_color")
+ , location("location", LLRelPos::TOP_LEFT)
+ , location_percent_hcenter("location_percent_hcenter")
+ , location_percent_vcenter("location_percent_vcenter")
+ , padding_horiz("padding_horiz")
+ , padding_vert("padding_vert")
+{
+ // We set a name here so the name isn't necessary in any xml files that use badges
+ name = "badge";
+}
+
+bool LLBadge::Params::equals(const Params& a) const
+{
+ bool comp = true;
+
+ // skip owner in comparison on purpose
+
+ comp &= (border_image() == a.border_image());
+ comp &= (border_color() == a.border_color());
+ comp &= (image() == a.image());
+ comp &= (image_color() == a.image_color());
+ comp &= (label() == a.label());
+ comp &= (label_color() == a.label_color());
+ comp &= (location() == a.location());
+ comp &= (location_percent_hcenter() == a.location_percent_hcenter());
+ comp &= (location_percent_vcenter() == a.location_percent_vcenter());
+ comp &= (padding_horiz() == a.padding_horiz());
+ comp &= (padding_vert() == a.padding_vert());
+
+ return comp;
+}
+
+LLBadge::LLBadge(const LLBadge::Params& p)
+ : LLUICtrl(p)
+ , mOwner(p.owner)
+ , mBorderImage(p.border_image)
+ , mBorderColor(p.border_color)
+ , mGLFont(p.font)
+ , mImage(p.image)
+ , mImageColor(p.image_color)
+ , mLabel(p.label)
+ , mLabelColor(p.label_color)
+ , mLocation(p.location)
+ , mLocationPercentHCenter(0.5f)
+ , mLocationPercentVCenter(0.5f)
+ , mPaddingHoriz(p.padding_horiz)
+ , mPaddingVert(p.padding_vert)
+{
+ if (mImage.isNull())
+ {
+ llwarns << "Badge: " << getName() << " with no image!" << llendl;
+ }
+
+ //
+ // The following logic is to set the mLocationPercentHCenter and mLocationPercentVCenter
+ // based on the Location enum and our horizontal and vertical location percentages. The
+ // draw code then uses this on the owner rectangle to compute the screen location for
+ // the badge.
+ //
+
+ if (!LLRelPos::IsCenter(mLocation))
+ {
+ F32 h_center = p.location_percent_hcenter * 0.01f;
+ F32 v_center = p.location_percent_vcenter * 0.01f;
+
+ if (LLRelPos::IsRight(mLocation))
+ {
+ mLocationPercentHCenter = 0.5f * (1.0f + h_center);
+ }
+ else if (LLRelPos::IsLeft(mLocation))
+ {
+ mLocationPercentHCenter = 0.5f * (1.0f - h_center);
+ }
+
+ if (LLRelPos::IsTop(mLocation))
+ {
+ mLocationPercentVCenter = 0.5f * (1.0f + v_center);
+ }
+ else if (LLRelPos::IsBottom(mLocation))
+ {
+ mLocationPercentVCenter = 0.5f * (1.0f - v_center);
+ }
+ }
+}
+
+LLBadge::~LLBadge()
+{
+}
+
+void LLBadge::setLabel(const LLStringExplicit& label)
+{
+ mLabel = label;
+}
+
+//
+// This is a fallback function to render a rectangle for badges without a valid image
+//
+void renderBadgeBackground(F32 centerX, F32 centerY, F32 width, F32 height, const LLColor4U &color)
+{
+ gGL.pushUIMatrix();
+ gGL.loadUIIdentity();
+ gGL.setSceneBlendType(LLRender::BT_REPLACE);
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ gGL.color4ubv(color.mV);
+ gGL.texCoord2i(0, 0);
+
+ F32 x = LLFontGL::sCurOrigin.mX + centerX - width * 0.5f;
+ F32 y = LLFontGL::sCurOrigin.mY + centerY - height * 0.5f;
+
+ LLRectf screen_rect(llround(x),
+ llround(y),
+ llround(x) + width,
+ llround(y) + height);
+
+ LLVector3 vertices[4];
+ vertices[0] = LLVector3(screen_rect.mRight, screen_rect.mTop, 1.0f);
+ vertices[1] = LLVector3(screen_rect.mLeft, screen_rect.mTop, 1.0f);
+ vertices[2] = LLVector3(screen_rect.mLeft, screen_rect.mBottom, 1.0f);
+ vertices[3] = LLVector3(screen_rect.mRight, screen_rect.mBottom, 1.0f);
+
+ gGL.begin(LLRender::QUADS);
+ {
+ gGL.vertexBatchPreTransformed(vertices, 4);
+ }
+ gGL.end();
+
+ gGL.popUIMatrix();
+}
+
+
+// virtual
+void LLBadge::draw()
+{
+ if (!mLabel.empty())
+ {
+ LLView* owner_view = mOwner.get();
+
+ if (owner_view)
+ {
+ //
+ // Calculate badge position based on owner
+ //
+
+ LLRect owner_rect;
+ owner_view->localRectToOtherView(owner_view->getLocalRect(), & owner_rect, this);
+
+ F32 badge_center_x = owner_rect.mLeft + owner_rect.getWidth() * mLocationPercentHCenter;
+ F32 badge_center_y = owner_rect.mBottom + owner_rect.getHeight() * mLocationPercentVCenter;
+
+ //
+ // Calculate badge size based on label text
+ //
+
+ LLWString badge_label_wstring = mLabel;
+
+ S32 badge_label_begin_offset = 0;
+ S32 badge_char_length = S32_MAX;
+ S32 badge_pixel_length = S32_MAX;
+ F32 *right_position_out = NULL;
+ BOOL do_not_use_ellipses = false;
+
+ F32 badge_width = (2.0f * mPaddingHoriz) +
+ mGLFont->getWidthF32(badge_label_wstring.c_str(), badge_label_begin_offset, badge_char_length);
+
+ F32 badge_height = (2.0f * mPaddingVert) + mGLFont->getLineHeight();
+
+ //
+ // Draw button image, if available.
+ // Otherwise draw basic rectangular button.
+ //
+
+ F32 alpha = getDrawContext().mAlpha;
+
+ if (!mImage.isNull())
+ {
+ F32 badge_x = badge_center_x - badge_width * 0.5f;
+ F32 badge_y = badge_center_y - badge_height * 0.5f;
+
+ mImage->drawSolid((S32) badge_x, (S32) badge_y, (S32) badge_width, (S32) badge_height, mImageColor % alpha);
+
+ if (!mBorderImage.isNull())
+ {
+ mBorderImage->drawSolid((S32) badge_x, (S32) badge_y, (S32) badge_width, (S32) badge_height, mBorderColor % alpha);
+ }
+ }
+ else
+ {
+ lldebugs << "No image for badge " << getName() << " on owner " << owner_view->getName() << llendl;
+
+ renderBadgeBackground(badge_center_x, badge_center_y,
+ badge_width, badge_height,
+ mImageColor % alpha);
+ }
+
+ //
+ // Draw the label
+ //
+
+ mGLFont->render(badge_label_wstring, badge_label_begin_offset,
+ badge_center_x, badge_center_y,
+ mLabelColor % alpha,
+ LLFontGL::HCENTER, LLFontGL::VCENTER, // centered around the position
+ LLFontGL::NORMAL, // normal text (not bold, italics, etc.)
+ LLFontGL::DROP_SHADOW_SOFT,
+ badge_char_length, badge_pixel_length,
+ right_position_out, do_not_use_ellipses);
+ }
+ }
+}
+
+
+namespace LLInitParam
+{
+ void TypeValues<LLRelPos::Location>::declareValues()
+ {
+ declare("bottom", LLRelPos::BOTTOM);
+ declare("bottom_left", LLRelPos::BOTTOM_LEFT);
+ declare("bottom_right", LLRelPos::BOTTOM_RIGHT);
+ declare("center", LLRelPos::CENTER);
+ declare("left", LLRelPos::LEFT);
+ declare("right", LLRelPos::RIGHT);
+ declare("top", LLRelPos::TOP);
+ declare("top_left", LLRelPos::TOP_LEFT);
+ declare("top_right", LLRelPos::TOP_RIGHT);
+ }
+}
+
+
+// eof
diff --git a/indra/llui/llbadge.h b/indra/llui/llbadge.h
new file mode 100644
index 0000000000..0f923ef01b
--- /dev/null
+++ b/indra/llui/llbadge.h
@@ -0,0 +1,159 @@
+/**
+ * @file llbadge.h
+ * @brief Header for badges
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLBADGE_H
+#define LL_LLBADGE_H
+
+#include <string>
+
+#include "lluicolor.h"
+#include "lluictrl.h"
+#include "llstring.h"
+#include "lluiimage.h"
+#include "llview.h"
+
+//
+// Declarations
+//
+
+class LLUICtrlFactory;
+class LLFontGL;
+
+//
+// Relative Position Alignment
+//
+
+namespace LLRelPos
+{
+ enum Location
+ {
+ CENTER = 0,
+
+ LEFT = (1 << 0),
+ RIGHT = (1 << 1),
+
+ TOP = (1 << 2),
+ BOTTOM = (1 << 3),
+
+ BOTTOM_LEFT = (BOTTOM | LEFT),
+ BOTTOM_RIGHT = (BOTTOM | RIGHT),
+
+ TOP_LEFT = (TOP | LEFT),
+ TOP_RIGHT = (TOP | RIGHT),
+ };
+
+ inline bool IsBottom(Location relPos) { return (relPos & BOTTOM) == BOTTOM; }
+ inline bool IsCenter(Location relPos) { return (relPos == CENTER); }
+ inline bool IsLeft(Location relPos) { return (relPos & LEFT) == LEFT; }
+ inline bool IsRight(Location relPos) { return (relPos & RIGHT) == RIGHT; }
+ inline bool IsTop(Location relPos) { return (relPos & TOP) == TOP; }
+}
+
+// NOTE: This needs to occur before Optional<LLRelPos::Location> declaration for proper compilation.
+namespace LLInitParam
+{
+ template<>
+ struct TypeValues<LLRelPos::Location> : public TypeValuesHelper<LLRelPos::Location>
+ {
+ static void declareValues();
+ };
+}
+
+//
+// Classes
+//
+
+class LLBadge
+: public LLUICtrl
+{
+public:
+ struct Params
+ : public LLInitParam::Block<Params, LLUICtrl::Params>
+ {
+ Optional< LLHandle<LLView> > owner; // Mandatory in code but not in xml
+
+ Optional< LLUIImage* > border_image;
+ Optional< LLUIColor > border_color;
+
+ Optional< LLUIImage* > image;
+ Optional< LLUIColor > image_color;
+
+ Optional< std::string > label;
+ Optional< LLUIColor > label_color;
+
+ Optional< LLRelPos::Location > location;
+ Optional< U32 > location_percent_hcenter;
+ Optional< U32 > location_percent_vcenter;
+
+ Optional< F32 > padding_horiz;
+ Optional< F32 > padding_vert;
+
+ Params();
+
+ bool equals(const Params&) const;
+ };
+
+protected:
+ friend class LLUICtrlFactory;
+ LLBadge(const Params& p);
+
+public:
+
+ ~LLBadge();
+
+ virtual void draw();
+
+ const std::string getLabel() const { return wstring_to_utf8str(mLabel); }
+ void setLabel( const LLStringExplicit& label);
+
+private:
+ LLPointer< LLUIImage > mBorderImage;
+ LLUIColor mBorderColor;
+
+ const LLFontGL* mGLFont;
+
+ LLPointer< LLUIImage > mImage;
+ LLUIColor mImageColor;
+
+ LLUIString mLabel;
+ LLUIColor mLabelColor;
+
+ LLRelPos::Location mLocation;
+ F32 mLocationPercentHCenter;
+ F32 mLocationPercentVCenter;
+
+ LLHandle< LLView > mOwner;
+
+ F32 mPaddingHoriz;
+ F32 mPaddingVert;
+};
+
+// Build time optimization, generate once in .cpp file
+#ifndef LLBADGE_CPP
+extern template class LLBadge* LLView::getChild<class LLBadge>(const std::string& name, BOOL recurse) const;
+#endif
+
+#endif // LL_LLBADGE_H
diff --git a/indra/llui/llbadgeowner.cpp b/indra/llui/llbadgeowner.cpp
new file mode 100644
index 0000000000..77f15567bf
--- /dev/null
+++ b/indra/llui/llbadgeowner.cpp
@@ -0,0 +1,126 @@
+/**
+ * @file llbadgeowner.cpp
+ * @brief Class to manage badges attached to a UI control
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llbadgeowner.h"
+#include "llpanel.h"
+
+//
+// Classes
+//
+
+LLBadgeOwner::LLBadgeOwner(LLHandle< LLView > viewHandle)
+ : mBadge(NULL)
+ , mBadgeOwnerView(viewHandle)
+{
+}
+
+void LLBadgeOwner::initBadgeParams(const LLBadge::Params& p)
+{
+ if (!p.equals(LLUICtrlFactory::getDefaultParams<LLBadge>()))
+ {
+ mBadge = createBadge(p);
+ }
+}
+
+void LLBadgeOwner::setBadgeLabel(const LLStringExplicit& label)
+{
+ if (mBadge == NULL)
+ {
+ mBadge = createBadge(LLUICtrlFactory::getDefaultParams<LLBadge>());
+
+ addBadgeToParentPanel();
+ }
+
+ if (mBadge)
+ {
+ mBadge->setLabel(label);
+
+ //
+ // Push the badge to the front so it renders on top
+ //
+
+ LLView * parent = mBadge->getParent();
+
+ if (parent)
+ {
+ parent->sendChildToFront(mBadge);
+ }
+ }
+}
+
+void LLBadgeOwner::setBadgeVisibility(bool visible)
+{
+ if (mBadge)
+ {
+ mBadge->setVisible(visible);
+ }
+}
+
+void LLBadgeOwner::addBadgeToParentPanel()
+{
+ LLView * owner_view = mBadgeOwnerView.get();
+
+ if (mBadge && owner_view)
+ {
+ // Badge parent is badge owner by default
+ LLView * badge_parent = owner_view;
+
+ // Find the appropriate parent for the badge
+ LLView * parent = owner_view->getParent();
+
+ while (parent)
+ {
+ LLPanel * parent_panel = dynamic_cast<LLPanel *>(parent);
+
+ if (parent_panel && parent_panel->acceptsBadge())
+ {
+ badge_parent = parent;
+ break;
+ }
+
+ parent = parent->getParent();
+ }
+
+ if (badge_parent)
+ {
+ badge_parent->addChild(mBadge);
+ }
+ else
+ {
+ llwarns << "Unable to find parent panel for badge " << mBadge->getName() << " on " << owner_view->getName() << llendl;
+ }
+ }
+}
+
+LLBadge* LLBadgeOwner::createBadge(const LLBadge::Params& p)
+{
+ LLBadge::Params badge_params(p);
+ badge_params.owner = mBadgeOwnerView;
+
+ return LLUICtrlFactory::create<LLBadge>(badge_params);
+}
diff --git a/indra/llui/llbadgeowner.h b/indra/llui/llbadgeowner.h
new file mode 100644
index 0000000000..a2399189a5
--- /dev/null
+++ b/indra/llui/llbadgeowner.h
@@ -0,0 +1,61 @@
+/**
+ * @file llbadgeowner.h
+ * @brief Header for badge owners
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLBADGEOWNER_H
+#define LL_LLBADGEOWNER_H
+
+#include "llbadge.h"
+#include "llview.h"
+
+//
+// Classes
+//
+
+class LLBadgeOwner
+{
+public:
+
+ LLBadgeOwner(LLHandle< LLView > viewHandle);
+
+ void initBadgeParams(const LLBadge::Params& p);
+ void addBadgeToParentPanel();
+
+ bool badgeHasParent() const { return (mBadge && mBadge->getParent()); }
+
+ void setBadgeLabel(const LLStringExplicit& label);
+ void setBadgeVisibility(bool visible);
+
+private:
+
+ LLBadge* createBadge(const LLBadge::Params& p);
+
+private:
+
+ LLBadge* mBadge;
+ LLHandle< LLView > mBadgeOwnerView;
+};
+
+#endif // LL_LLBADGEOWNER_H
diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp
index 45ceaff696..7b015bd576 100644
--- a/indra/llui/llbutton.cpp
+++ b/indra/llui/llbutton.cpp
@@ -99,7 +99,9 @@ LLButton::Params::Params()
scale_image("scale_image", true),
hover_glow_amount("hover_glow_amount"),
commit_on_return("commit_on_return", true),
- use_draw_context_alpha("use_draw_context_alpha", true)
+ use_draw_context_alpha("use_draw_context_alpha", true),
+ badge("badge"),
+ handle_right_mouse("handle_right_mouse")
{
addSynonym(is_toggle, "toggle");
held_down_delay.seconds = 0.5f;
@@ -109,6 +111,7 @@ LLButton::Params::Params()
LLButton::LLButton(const LLButton::Params& p)
: LLUICtrl(p),
+ LLBadgeOwner(LLView::getHandle()),
mMouseDownFrame(0),
mMouseHeldDownCount(0),
mBorderEnabled( FALSE ),
@@ -160,8 +163,8 @@ LLButton::LLButton(const LLButton::Params& p)
mMouseDownSignal(NULL),
mMouseUpSignal(NULL),
mHeldDownSignal(NULL),
- mUseDrawContextAlpha(p.use_draw_context_alpha)
-
+ mUseDrawContextAlpha(p.use_draw_context_alpha),
+ mHandleRightMouse(p.handle_right_mouse)
{
static LLUICachedControl<S32> llbutton_orig_h_pad ("UIButtonOrigHPad", 0);
static Params default_params(LLUICtrlFactory::getDefaultParams<LLButton>());
@@ -244,6 +247,11 @@ LLButton::LLButton(const LLButton::Params& p)
{
setHeldDownCallback(initCommitCallback(p.mouse_held_callback));
}
+
+ if (p.badge.isProvided())
+ {
+ LLBadgeOwner::initBadgeParams(p.badge());
+ }
}
LLButton::~LLButton()
@@ -327,8 +335,12 @@ boost::signals2::connection LLButton::setHeldDownCallback( button_callback_t cb,
BOOL LLButton::postBuild()
{
autoResize();
- return TRUE;
+
+ addBadgeToParentPanel();
+
+ return LLUICtrl::postBuild();
}
+
BOOL LLButton::handleUnicodeCharHere(llwchar uni_char)
{
BOOL handled = FALSE;
@@ -447,7 +459,7 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask)
BOOL LLButton::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
- if (!childrenHandleRightMouseDown(x, y, mask))
+ if (mHandleRightMouse && !childrenHandleRightMouseDown(x, y, mask))
{
// Route future Mouse messages here preemptively. (Release on mouse up.)
gFocusMgr.setMouseCapture( this );
@@ -460,37 +472,42 @@ BOOL LLButton::handleRightMouseDown(S32 x, S32 y, MASK mask)
// if (pointInView(x, y))
// {
// }
+ // send the mouse down signal
+ LLUICtrl::handleRightMouseDown(x,y,mask);
+ // *TODO: Return result of LLUICtrl call above? Should defer to base class
+ // but this might change the mouse handling of existing buttons in a bad way
+ // if they are not mouse opaque.
}
- // send the mouse down signal
- LLUICtrl::handleRightMouseDown(x,y,mask);
- // *TODO: Return result of LLUICtrl call above? Should defer to base class
- // but this might change the mouse handling of existing buttons in a bad way
- // if they are not mouse opaque.
+
return TRUE;
}
BOOL LLButton::handleRightMouseUp(S32 x, S32 y, MASK mask)
{
- // We only handle the click if the click both started and ended within us
- if( hasMouseCapture() )
+ if (mHandleRightMouse)
{
- // Always release the mouse
- gFocusMgr.setMouseCapture( NULL );
+ // We only handle the click if the click both started and ended within us
+ if( hasMouseCapture() )
+ {
+ // Always release the mouse
+ gFocusMgr.setMouseCapture( NULL );
-// if (pointInView(x, y))
-// {
-// mRightMouseUpSignal(this, x,y,mask);
-// }
- }
- else
- {
- childrenHandleRightMouseUp(x, y, mask);
+ // if (pointInView(x, y))
+ // {
+ // mRightMouseUpSignal(this, x,y,mask);
+ // }
+ }
+ else
+ {
+ childrenHandleRightMouseUp(x, y, mask);
+ }
+
+ // send the mouse up signal
+ LLUICtrl::handleRightMouseUp(x,y,mask);
+ // *TODO: Return result of LLUICtrl call above? Should defer to base class
+ // but this might change the mouse handling of existing buttons in a bad way.
+ // if they are not mouse opaque.
}
- // send the mouse up signal
- LLUICtrl::handleRightMouseUp(x,y,mask);
- // *TODO: Return result of LLUICtrl call above? Should defer to base class
- // but this might change the mouse handling of existing buttons in a bad way.
- // if they are not mouse opaque.
return TRUE;
}
diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h
index 0cfc393e05..5968916006 100644
--- a/indra/llui/llbutton.h
+++ b/indra/llui/llbutton.h
@@ -27,6 +27,8 @@
#ifndef LL_LLBUTTON_H
#define LL_LLBUTTON_H
+#include "lluuid.h"
+#include "llbadgeowner.h"
#include "llcontrol.h"
#include "lluictrl.h"
#include "v4color.h"
@@ -52,15 +54,13 @@ S32 round_up(S32 grid, S32 value);
class LLUICtrlFactory;
-class LLUIImage;
-class LLUUID;
//
// Classes
//
class LLButton
-: public LLUICtrl
+: public LLUICtrl, public LLBadgeOwner
{
public:
struct Params
@@ -125,7 +125,11 @@ public:
Optional<F32> hover_glow_amount;
Optional<TimeIntervalParam> held_down_delay;
- Optional<bool> use_draw_context_alpha;
+ Optional<bool> use_draw_context_alpha;
+
+ Optional<LLBadge::Params> badge;
+
+ Optional<bool> handle_right_mouse;
Params();
};
@@ -249,7 +253,7 @@ public:
void setImageDisabledSelected(LLPointer<LLUIImage> image);
void setImageFlash(LLPointer<LLUIImage> image);
void setImagePressed(LLPointer<LLUIImage> image);
-
+
void setCommitOnReturn(BOOL commit) { mCommitOnReturn = commit; }
BOOL getCommitOnReturn() const { return mCommitOnReturn; }
@@ -357,6 +361,8 @@ private:
bool mForcePressedState;
LLFrameTimer mFlashingTimer;
+
+ bool mHandleRightMouse;
};
// Build time optimization, generate once in .cpp file
diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
index 9b6830a816..6a91ec56e4 100644
--- a/indra/llui/lllayoutstack.cpp
+++ b/indra/llui/lllayoutstack.cpp
@@ -49,6 +49,8 @@ void LLLayoutStack::OrientationNames::declareValues()
//
LLLayoutPanel::LLLayoutPanel(const Params& p)
: LLPanel(p),
+ mExpandedMinDimSpecified(false),
+ mExpandedMinDim(p.min_dim),
mMinDim(p.min_dim),
mMaxDim(p.max_dim),
mAutoResize(p.auto_resize),
@@ -58,6 +60,13 @@ LLLayoutPanel::LLLayoutPanel(const Params& p)
mVisibleAmt(1.f), // default to fully visible
mResizeBar(NULL)
{
+ // Set the expanded min dim if it is provided, otherwise it gets the p.min_dim value
+ if (p.expanded_min_dim.isProvided())
+ {
+ mExpandedMinDimSpecified = true;
+ mExpandedMinDim = p.expanded_min_dim();
+ }
+
// panels initialized as hidden should not start out partially visible
if (!getVisible())
{
@@ -78,20 +87,20 @@ LLLayoutPanel::~LLLayoutPanel()
delete mResizeBar;
mResizeBar = NULL;
}
-
+
F32 LLLayoutPanel::getCollapseFactor(LLLayoutStack::ELayoutOrientation orientation)
{
if (orientation == LLLayoutStack::HORIZONTAL)
{
F32 collapse_amt =
- clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, (F32)mMinDim / (F32)llmax(1, getRect().getWidth()));
+ clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, (F32)getRelevantMinDim() / (F32)llmax(1, getRect().getWidth()));
return mVisibleAmt * collapse_amt;
}
else
{
- F32 collapse_amt =
- clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, llmin(1.f, (F32)mMinDim / (F32)llmax(1, getRect().getHeight())));
- return mVisibleAmt * collapse_amt;
+ F32 collapse_amt =
+ clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, llmin(1.f, (F32)getRelevantMinDim() / (F32)llmax(1, getRect().getHeight())));
+ return mVisibleAmt * collapse_amt;
}
}
@@ -182,14 +191,14 @@ BOOL LLLayoutStack::postBuild()
}
bool LLLayoutStack::addChild(LLView* child, S32 tab_group)
- {
+{
LLLayoutPanel* panelp = dynamic_cast<LLLayoutPanel*>(child);
- if (panelp)
- {
+ if (panelp)
+ {
mPanels.push_back(panelp);
- }
+ }
return LLView::addChild(child, tab_group);
- }
+}
S32 LLLayoutStack::getDefaultHeight(S32 cur_height)
@@ -281,9 +290,9 @@ bool LLLayoutStack::getPanelMinSize(const std::string& panel_name, S32* min_dimp
{
LLLayoutPanel* panel = findEmbeddedPanelByName(panel_name);
- if (panel)
+ if (panel && min_dimp)
{
- if (min_dimp) *min_dimp = panel->mMinDim;
+ *min_dimp = panel->getRelevantMinDim();
}
return NULL != panel;
@@ -316,23 +325,23 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
e_panel_list_t::iterator panel_it;
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
{
- LLPanel* panelp = (*panel_it);
+ LLLayoutPanel* panelp = (*panel_it);
if (panelp->getVisible())
{
if (mAnimate)
{
if (!mAnimatedThisFrame)
{
- (*panel_it)->mVisibleAmt = lerp((*panel_it)->mVisibleAmt, 1.f, LLCriticalDamp::getInterpolant(mOpenTimeConstant));
- if ((*panel_it)->mVisibleAmt > 0.99f)
+ panelp->mVisibleAmt = lerp(panelp->mVisibleAmt, 1.f, LLCriticalDamp::getInterpolant(mOpenTimeConstant));
+ if (panelp->mVisibleAmt > 0.99f)
{
- (*panel_it)->mVisibleAmt = 1.f;
+ panelp->mVisibleAmt = 1.f;
}
}
}
else
{
- (*panel_it)->mVisibleAmt = 1.f;
+ panelp->mVisibleAmt = 1.f;
}
}
else // not visible
@@ -341,36 +350,36 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
{
if (!mAnimatedThisFrame)
{
- (*panel_it)->mVisibleAmt = lerp((*panel_it)->mVisibleAmt, 0.f, LLCriticalDamp::getInterpolant(mCloseTimeConstant));
- if ((*panel_it)->mVisibleAmt < 0.001f)
+ panelp->mVisibleAmt = lerp(panelp->mVisibleAmt, 0.f, LLCriticalDamp::getInterpolant(mCloseTimeConstant));
+ if (panelp->mVisibleAmt < 0.001f)
{
- (*panel_it)->mVisibleAmt = 0.f;
+ panelp->mVisibleAmt = 0.f;
}
}
}
else
{
- (*panel_it)->mVisibleAmt = 0.f;
+ panelp->mVisibleAmt = 0.f;
}
}
- if ((*panel_it)->mCollapsed)
+ if (panelp->mCollapsed)
{
- (*panel_it)->mCollapseAmt = lerp((*panel_it)->mCollapseAmt, 1.f, LLCriticalDamp::getInterpolant(mCloseTimeConstant));
+ panelp->mCollapseAmt = lerp(panelp->mCollapseAmt, 1.f, LLCriticalDamp::getInterpolant(mCloseTimeConstant));
}
else
{
- (*panel_it)->mCollapseAmt = lerp((*panel_it)->mCollapseAmt, 0.f, LLCriticalDamp::getInterpolant(mCloseTimeConstant));
+ panelp->mCollapseAmt = lerp(panelp->mCollapseAmt, 0.f, LLCriticalDamp::getInterpolant(mCloseTimeConstant));
}
if (mOrientation == HORIZONTAL)
{
// enforce minimize size constraint by default
- if (panelp->getRect().getWidth() < (*panel_it)->mMinDim)
+ if (panelp->getRect().getWidth() < panelp->getRelevantMinDim())
{
- panelp->reshape((*panel_it)->mMinDim, panelp->getRect().getHeight());
+ panelp->reshape(panelp->getRelevantMinDim(), panelp->getRect().getHeight());
}
- total_width += llround(panelp->getRect().getWidth() * (*panel_it)->getCollapseFactor(mOrientation));
+ total_width += llround(panelp->getRect().getWidth() * panelp->getCollapseFactor(mOrientation));
// want n-1 panel gaps for n panels
if (panel_it != mPanels.begin())
{
@@ -380,11 +389,11 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
else //VERTICAL
{
// enforce minimize size constraint by default
- if (panelp->getRect().getHeight() < (*panel_it)->mMinDim)
+ if (panelp->getRect().getHeight() < panelp->getRelevantMinDim())
{
- panelp->reshape(panelp->getRect().getWidth(), (*panel_it)->mMinDim);
+ panelp->reshape(panelp->getRect().getWidth(), panelp->getRelevantMinDim());
}
- total_height += llround(panelp->getRect().getHeight() * (*panel_it)->getCollapseFactor(mOrientation));
+ total_height += llround(panelp->getRect().getHeight() * panelp->getCollapseFactor(mOrientation));
if (panel_it != mPanels.begin())
{
total_height += mPanelSpacing;
@@ -403,34 +412,23 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
continue;
}
+ S32 relevant_dimension = (mOrientation == HORIZONTAL) ? (*panel_it)->getRect().getWidth() : (*panel_it)->getRect().getHeight();
+ S32 relevant_min = (*panel_it)->getRelevantMinDim();
+
// if currently resizing a panel or the panel is flagged as not automatically resizing
// only track total available headroom, but don't use it for automatic resize logic
if ((*panel_it)->mResizeBar->hasMouseCapture()
|| (!(*panel_it)->mAutoResize
&& !force_resize))
{
- if (mOrientation == HORIZONTAL)
- {
- shrink_headroom_total += (*panel_it)->getRect().getWidth() - (*panel_it)->mMinDim;
- }
- else //VERTICAL
- {
- shrink_headroom_total += (*panel_it)->getRect().getHeight() - (*panel_it)->mMinDim;
- }
+ shrink_headroom_total += relevant_dimension - relevant_min;
}
else
{
num_resizable_panels++;
- if (mOrientation == HORIZONTAL)
- {
- shrink_headroom_available += (*panel_it)->getRect().getWidth() - (*panel_it)->mMinDim;
- shrink_headroom_total += (*panel_it)->getRect().getWidth() - (*panel_it)->mMinDim;
- }
- else //VERTICAL
- {
- shrink_headroom_available += (*panel_it)->getRect().getHeight() - (*panel_it)->mMinDim;
- shrink_headroom_total += (*panel_it)->getRect().getHeight() - (*panel_it)->mMinDim;
- }
+
+ shrink_headroom_available += relevant_dimension - relevant_min;
+ shrink_headroom_total += relevant_dimension - relevant_min;
}
}
@@ -452,27 +450,28 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
{
- LLPanel* panelp = (*panel_it);
+ LLLayoutPanel* panelp = (*panel_it);
S32 cur_width = panelp->getRect().getWidth();
S32 cur_height = panelp->getRect().getHeight();
S32 new_width = cur_width;
- S32 new_height = cur_height;
+ S32 new_height = cur_height;
+ S32 relevant_min = panelp->getRelevantMinDim();
if (mOrientation == HORIZONTAL)
{
- new_width = llmax((*panel_it)->mMinDim, new_width);
+ new_width = llmax(relevant_min, new_width);
}
else
{
- new_height = llmax((*panel_it)->mMinDim, new_height);
+ new_height = llmax(relevant_min, new_height);
}
S32 delta_size = 0;
// if panel can automatically resize (not animating, and resize flag set)...
- if ((*panel_it)->getCollapseFactor(mOrientation) == 1.f
- && (force_resize || (*panel_it)->mAutoResize)
- && !(*panel_it)->mResizeBar->hasMouseCapture())
+ if (panelp->getCollapseFactor(mOrientation) == 1.f
+ && (force_resize || panelp->mAutoResize)
+ && !panelp->mResizeBar->hasMouseCapture())
{
if (mOrientation == HORIZONTAL)
{
@@ -481,8 +480,8 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
{
// shrink proportionally to amount over minimum
// so we can do this in one pass
- delta_size = (shrink_headroom_available > 0) ? llround((F32)pixels_to_distribute * ((F32)(cur_width - (*panel_it)->mMinDim) / (F32)shrink_headroom_available)) : 0;
- shrink_headroom_available -= (cur_width - (*panel_it)->mMinDim);
+ delta_size = (shrink_headroom_available > 0) ? llround((F32)pixels_to_distribute * ((F32)(cur_width - relevant_min) / (F32)shrink_headroom_available)) : 0;
+ shrink_headroom_available -= (cur_width - relevant_min);
}
else
{
@@ -491,7 +490,7 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
num_resizable_panels--;
}
pixels_to_distribute -= delta_size;
- new_width = llmax((*panel_it)->mMinDim, cur_width + delta_size);
+ new_width = llmax(relevant_min, cur_width + delta_size);
}
else
{
@@ -504,8 +503,8 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
{
// shrink proportionally to amount over minimum
// so we can do this in one pass
- delta_size = (shrink_headroom_available > 0) ? llround((F32)pixels_to_distribute * ((F32)(cur_height - (*panel_it)->mMinDim) / (F32)shrink_headroom_available)) : 0;
- shrink_headroom_available -= (cur_height - (*panel_it)->mMinDim);
+ delta_size = (shrink_headroom_available > 0) ? llround((F32)pixels_to_distribute * ((F32)(cur_height - relevant_min) / (F32)shrink_headroom_available)) : 0;
+ shrink_headroom_available -= (cur_height - relevant_min);
}
else
{
@@ -513,7 +512,7 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
num_resizable_panels--;
}
pixels_to_distribute -= delta_size;
- new_height = llmax((*panel_it)->mMinDim, cur_height + delta_size);
+ new_height = llmax(relevant_min, cur_height + delta_size);
}
else
{
@@ -566,19 +565,20 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
LLLayoutPanel* last_resizeable_panel = NULL;
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
{
- LLPanel* panelp = (*panel_it);
+ LLLayoutPanel* panelp = (*panel_it);
+ S32 relevant_min = panelp->getRelevantMinDim();
if (mOrientation == HORIZONTAL)
{
(*panel_it)->mResizeBar->setResizeLimits(
- (*panel_it)->mMinDim,
- (*panel_it)->mMinDim + shrink_headroom_total);
+ relevant_min,
+ relevant_min + shrink_headroom_total);
}
else //VERTICAL
{
(*panel_it)->mResizeBar->setResizeLimits(
- (*panel_it)->mMinDim,
- (*panel_it)->mMinDim + shrink_headroom_total);
+ relevant_min,
+ relevant_min + shrink_headroom_total);
}
// toggle resize bars based on panel visibility, resizability, etc
@@ -658,7 +658,7 @@ void LLLayoutStack::calcMinExtents()
{
if (mOrientation == HORIZONTAL)
{
- mMinWidth += (*panel_it)->mMinDim;
+ mMinWidth += (*panel_it)->getRelevantMinDim();
if (panel_it != mPanels.begin())
{
mMinWidth += mPanelSpacing;
@@ -666,7 +666,7 @@ void LLLayoutStack::calcMinExtents()
}
else //VERTICAL
{
- mMinHeight += (*panel_it)->mMinDim;
+ mMinHeight += (*panel_it)->getRelevantMinDim();
if (panel_it != mPanels.begin())
{
mMinHeight += mPanelSpacing;
@@ -688,7 +688,7 @@ void LLLayoutStack::createResizeBars()
LLResizeBar::Params resize_params;
resize_params.name("resize");
resize_params.resizing_view(lp);
- resize_params.min_size(lp->mMinDim);
+ resize_params.min_size(lp->getRelevantMinDim());
resize_params.side(side);
resize_params.snapping_enabled(false);
LLResizeBar* resize_bar = LLUICtrlFactory::create<LLResizeBar>(resize_params);
diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h
index 4ac8ef0ee9..d8ef0aeaca 100644
--- a/indra/llui/lllayoutstack.h
+++ b/indra/llui/lllayoutstack.h
@@ -30,10 +30,10 @@
#include "llpanel.h"
-class LLPanel;
class LLLayoutPanel;
+
class LLLayoutStack : public LLView, public LLInstanceTracker<LLLayoutStack>
{
public:
@@ -149,6 +149,7 @@ private:
F32 mCloseTimeConstant;
}; // end class LLLayoutStack
+
class LLLayoutPanel : public LLPanel
{
friend class LLLayoutStack;
@@ -156,13 +157,15 @@ friend class LLUICtrlFactory;
public:
struct Params : public LLInitParam::Block<Params, LLPanel::Params>
{
- Optional<S32> min_dim,
+ Optional<S32> expanded_min_dim,
+ min_dim,
max_dim;
Optional<bool> user_resize,
auto_resize;
Params()
- : min_dim("min_dim", 0),
+ : expanded_min_dim("expanded_min_dim", 0),
+ min_dim("min_dim", 0),
max_dim("max_dim", 0),
user_resize("user_resize", true),
auto_resize("auto_resize", true)
@@ -177,15 +180,36 @@ public:
~LLLayoutPanel();
void initFromParams(const Params& p);
- void setMinDim(S32 value) { mMinDim = value; }
+
+ S32 getMinDim() const { return mMinDim; }
+ void setMinDim(S32 value) { mMinDim = value; if (!mExpandedMinDimSpecified) mExpandedMinDim = value; }
+
+ S32 getMaxDim() const { return mMaxDim; }
void setMaxDim(S32 value) { mMaxDim = value; }
-protected:
- LLLayoutPanel(const Params& p) ;
+ S32 getExpandedMinDim() const { return mExpandedMinDim; }
+ void setExpandedMinDim(S32 value) { mExpandedMinDim = value; mExpandedMinDimSpecified = true; }
+
+ S32 getRelevantMinDim() const
+ {
+ S32 min_dim = mMinDim;
+
+ if (!mCollapsed)
+ {
+ min_dim = mExpandedMinDim;
+ }
+
+ return min_dim;
+ }
+protected:
+ LLLayoutPanel(const Params& p);
F32 getCollapseFactor(LLLayoutStack::ELayoutOrientation orientation);
+ bool mExpandedMinDimSpecified;
+ S32 mExpandedMinDim;
+
S32 mMinDim;
S32 mMaxDim;
BOOL mAutoResize;
diff --git a/indra/llui/llloadingindicator.h b/indra/llui/llloadingindicator.h
index 4c47cc267c..7c44478848 100644
--- a/indra/llui/llloadingindicator.h
+++ b/indra/llui/llloadingindicator.h
@@ -86,6 +86,8 @@ public:
*/
void start();
+ void reset() { mCurImageIdx = 0; }
+
private:
LLLoadingIndicator(const Params&);
void initFromParams(const Params&);
diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp
index b2383106a8..1dcdd79efa 100644
--- a/indra/llui/llpanel.cpp
+++ b/indra/llui/llpanel.cpp
@@ -87,7 +87,8 @@ LLPanel::Params::Params()
filename("filename"),
class_name("class"),
help_topic("help_topic"),
- visible_callback("visible_callback")
+ visible_callback("visible_callback"),
+ accepts_badge("accepts_badge")
{
name = "panel";
addSynonym(background_visible, "bg_visible");
@@ -113,7 +114,8 @@ LLPanel::LLPanel(const LLPanel::Params& p)
mCommitCallbackRegistrar(false),
mEnableCallbackRegistrar(false),
mXMLFilename(p.filename),
- mVisibleSignal(NULL)
+ mVisibleSignal(NULL),
+ mAcceptsBadge(p.accepts_badge)
// *NOTE: Be sure to also change LLPanel::initFromParams(). We have too
// many classes derived from LLPanel to retrofit them all to pass in params.
{
@@ -485,6 +487,8 @@ void LLPanel::initFromParams(const LLPanel::Params& p)
mBgAlphaImage = p.bg_alpha_image();
mBgOpaqueImageOverlay = p.bg_opaque_image_overlay;
mBgAlphaImageOverlay = p.bg_alpha_image_overlay;
+
+ mAcceptsBadge = p.accepts_badge;
}
static LLFastTimer::DeclareTimer FTM_PANEL_SETUP("Panel Setup");
diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h
index 7bbbeaf709..67674fab7e 100644
--- a/indra/llui/llpanel.h
+++ b/indra/llui/llpanel.h
@@ -89,6 +89,8 @@ public:
Multiple<LocalizedString> strings;
Optional<CommitCallbackParam> visible_callback;
+
+ Optional<bool> accepts_badge;
Params();
};
@@ -250,6 +252,8 @@ public:
boost::signals2::connection setVisibleCallback( const commit_signal_t::slot_type& cb );
+ bool acceptsBadge() const { return mAcceptsBadge; }
+
protected:
// Override to set not found list
LLButton* getDefaultButton() { return mDefaultBtn; }
@@ -264,6 +268,7 @@ protected:
static factory_stack_t sFactoryStack;
private:
+ bool mAcceptsBadge;
BOOL mBgVisible; // any background at all?
BOOL mBgOpaque; // use opaque color or image
LLUIColor mBgOpaqueColor;
diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp
index 0a06b5e74f..d58df5801b 100644
--- a/indra/llui/lluictrl.cpp
+++ b/indra/llui/lluictrl.cpp
@@ -68,6 +68,7 @@ LLUICtrl::ControlVisibility::ControlVisibility()
LLUICtrl::Params::Params()
: tab_stop("tab_stop", true),
chrome("chrome", false),
+ requests_front("requests_front", false),
label("label"),
initial_value("value"),
init_callback("init_callback"),
@@ -96,9 +97,10 @@ const LLUICtrl::Params& LLUICtrl::getDefaultParams()
LLUICtrl::LLUICtrl(const LLUICtrl::Params& p, const LLViewModelPtr& viewmodel)
: LLView(p),
- mTentative(FALSE),
mIsChrome(FALSE),
+ mRequestsFront(p.requests_front),
mTabStop(FALSE),
+ mTentative(FALSE),
mViewModel(viewmodel),
mControlVariable(NULL),
mEnabledControlVariable(NULL),
@@ -123,6 +125,8 @@ void LLUICtrl::initFromParams(const Params& p)
{
LLView::initFromParams(p);
+ mRequestsFront = p.requests_front;
+
setIsChrome(p.chrome);
setControlName(p.control_name);
if(p.enabled_controls.isProvided())
@@ -403,6 +407,36 @@ LLViewModel* LLUICtrl::getViewModel() const
return mViewModel;
}
+//virtual
+BOOL LLUICtrl::postBuild()
+{
+ //
+ // Find all of the children that want to be in front and move them to the front
+ //
+
+ if (getChildCount() > 0)
+ {
+ std::vector<LLUICtrl*> childrenToMoveToFront;
+
+ for (LLView::child_list_const_iter_t child_it = beginChild(); child_it != endChild(); ++child_it)
+ {
+ LLUICtrl* uictrl = dynamic_cast<LLUICtrl*>(*child_it);
+
+ if (uictrl && uictrl->mRequestsFront)
+ {
+ childrenToMoveToFront.push_back(uictrl);
+ }
+ }
+
+ for (std::vector<LLUICtrl*>::iterator it = childrenToMoveToFront.begin(); it != childrenToMoveToFront.end(); ++it)
+ {
+ sendChildToFront(*it);
+ }
+ }
+
+ return LLView::postBuild();
+}
+
bool LLUICtrl::setControlValue(const LLSD& value)
{
if (mControlVariable)
diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h
index b37e9f6b1b..09bed9b958 100644
--- a/indra/llui/lluictrl.h
+++ b/indra/llui/lluictrl.h
@@ -94,7 +94,8 @@ public:
{
Optional<std::string> label;
Optional<bool> tab_stop,
- chrome;
+ chrome,
+ requests_front;
Optional<LLSD> initial_value;
Optional<CommitCallbackParam> init_callback,
@@ -143,6 +144,8 @@ protected:
virtual LLViewModel* getViewModel() const;
// We shouldn't ever need to set this directly
//virtual void setViewModel(const LLViewModelPtr&);
+
+ virtual BOOL postBuild();
public:
// LLView interface
@@ -301,8 +304,9 @@ protected:
private:
- BOOL mTabStop;
BOOL mIsChrome;
+ BOOL mRequestsFront;
+ BOOL mTabStop;
BOOL mTentative;
LLRootHandle<LLUICtrl> mUICtrlHandle;
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 245126d178..8803d106ba 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -1299,15 +1299,7 @@ void LLView::drawChildren()
{
if (!mChildList.empty())
{
- static const LLRect* rootRect = NULL;
-
- if (!mParentView)
- {
- rootRect = &mRect;
- }
-
- LLRect screenRect;
-
+ LLView* rootp = LLUI::getRootView();
++sDepth;
for (child_list_reverse_iter_t child_iter = mChildList.rbegin(); child_iter != mChildList.rend();) // ++child_iter)
@@ -1317,9 +1309,8 @@ void LLView::drawChildren()
if (viewp->getVisible() && viewp->getRect().isValid())
{
- // Only draw views that are within the root view
- localRectToScreen(viewp->getRect(),&screenRect);
- if ( rootRect->overlaps(screenRect) && LLUI::sDirtyRect.overlaps(screenRect))
+ LLRect screen_rect = viewp->calcScreenRect();
+ if ( rootp->getLocalRect().overlaps(screen_rect) && LLUI::sDirtyRect.overlaps(screen_rect))
{
LLUI::pushMatrix();
{
diff --git a/indra/llui/tests/llurlmatch_test.cpp b/indra/llui/tests/llurlmatch_test.cpp
index e09ef33d49..3cd61e574e 100644
--- a/indra/llui/tests/llurlmatch_test.cpp
+++ b/indra/llui/tests/llurlmatch_test.cpp
@@ -95,7 +95,7 @@ namespace LLInitParam
{
const U8* my_addr = reinterpret_cast<const U8*>(this);
const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block);
- mEnclosingBlockOffset = (U16)(my_addr - block_addr);
+ mEnclosingBlockOffset = 0x7FFFffff & ((U32)(my_addr - block_addr));
}
bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, S32 generation){ return true; }
diff --git a/indra/llxuixml/llinitparam.cpp b/indra/llxuixml/llinitparam.cpp
index b3312798dd..c024fd405e 100644
--- a/indra/llxuixml/llinitparam.cpp
+++ b/indra/llxuixml/llinitparam.cpp
@@ -40,7 +40,7 @@ namespace LLInitParam
{
const U8* my_addr = reinterpret_cast<const U8*>(this);
const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block);
- mEnclosingBlockOffset = (U16)(my_addr - block_addr);
+ mEnclosingBlockOffset = 0x7FFFffff & ((U32)(my_addr - block_addr));
}
//
diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h
index a853999e94..35c889b69f 100644
--- a/indra/llxuixml/llinitparam.h
+++ b/indra/llxuixml/llinitparam.h
@@ -34,6 +34,8 @@
#include <boost/unordered_map.hpp>
#include <boost/shared_ptr.hpp>
+#include "llerror.h"
+
namespace LLInitParam
{
template<typename T> const T& defaultValue() { static T value; return value; }
@@ -302,8 +304,9 @@ namespace LLInitParam
private:
friend class BaseBlock;
- U16 mEnclosingBlockOffset;
- bool mIsProvided;
+ U32 mEnclosingBlockOffset:31;
+ U32 mIsProvided:1;
+
};
// various callbacks and constraints associated with an individual param
diff --git a/indra/media_plugins/webkit/media_plugin_webkit.cpp b/indra/media_plugins/webkit/media_plugin_webkit.cpp
index 27f3c7260e..fca071c628 100644
--- a/indra/media_plugins/webkit/media_plugin_webkit.cpp
+++ b/indra/media_plugins/webkit/media_plugin_webkit.cpp
@@ -1168,19 +1168,11 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
authResponse(message_in);
}
else
- if(message_name == "js_expose_object")
+ if(message_name == "js_enable_object")
{
#if LLQTWEBKIT_API_VERSION >= 9
- bool expose_object = message_in.getValueBoolean( "expose" );
- LLQtWebKit::getInstance()->setExposeObject( expose_object );
-#endif
- }
- else
- if(message_name == "js_values_valid")
- {
-#if LLQTWEBKIT_API_VERSION >= 9
- bool valid = message_in.getValueBoolean( "valid" );
- LLQtWebKit::getInstance()->setValuesValid( valid );
+ bool enable = message_in.getValueBoolean( "enable" );
+ LLQtWebKit::getInstance()->setSLObjectEnabled( enable );
#endif
}
else
@@ -1191,6 +1183,7 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
F32 y = message_in.getValueReal("y");
F32 z = message_in.getValueReal("z");
LLQtWebKit::getInstance()->setAgentLocation( x, y, z );
+ LLQtWebKit::getInstance()->emitLocation();
#endif
}
else
@@ -1201,6 +1194,7 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
F32 y = message_in.getValueReal("y");
F32 z = message_in.getValueReal("z");
LLQtWebKit::getInstance()->setAgentGlobalLocation( x, y, z );
+ LLQtWebKit::getInstance()->emitLocation();
#endif
}
else
@@ -1209,6 +1203,7 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
#if LLQTWEBKIT_API_VERSION >= 9
F32 angle = message_in.getValueReal("angle");
LLQtWebKit::getInstance()->setAgentOrientation( angle );
+ LLQtWebKit::getInstance()->emitLocation();
#endif
}
else
@@ -1217,14 +1212,25 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
#if LLQTWEBKIT_API_VERSION >= 9
const std::string& region = message_in.getValue("region");
LLQtWebKit::getInstance()->setAgentRegion( region );
+ LLQtWebKit::getInstance()->emitLocation();
#endif
}
else
- if(message_name == "js_agent_maturity")
+ if(message_name == "js_agent_maturity")
+ {
+#if LLQTWEBKIT_API_VERSION >= 9
+ const std::string& maturity = message_in.getValue("maturity");
+ LLQtWebKit::getInstance()->setAgentMaturity( maturity );
+ LLQtWebKit::getInstance()->emitMaturity();
+#endif
+ }
+ else
+ if(message_name == "js_agent_language")
{
#if LLQTWEBKIT_API_VERSION >= 9
- const std::string& maturity = message_in.getValue("maturity");
- LLQtWebKit::getInstance()->setAgentMaturity( maturity );
+ const std::string& language = message_in.getValue("language");
+ LLQtWebKit::getInstance()->setAgentLanguage( language );
+ LLQtWebKit::getInstance()->emitLanguage();
#endif
}
else
@@ -1384,3 +1390,5 @@ int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void
return 0;
}
+
+
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 367d3de0c9..da9a145423 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -363,6 +363,9 @@ set(viewer_SOURCE_FILES
llpanellogin.cpp
llpanelloginlistener.cpp
llpanelmaininventory.cpp
+ llpanelmarketplaceinbox.cpp
+ llpanelmarketplaceinboxinventory.cpp
+ llpanelmarketplaceoutbox.cpp
llpanelmediasettingsgeneral.cpp
llpanelmediasettingspermissions.cpp
llpanelmediasettingssecurity.cpp
@@ -913,6 +916,9 @@ set(viewer_HEADER_FILES
llpanellogin.h
llpanelloginlistener.h
llpanelmaininventory.h
+ llpanelmarketplaceinbox.h
+ llpanelmarketplaceinboxinventory.h
+ llpanelmarketplaceoutbox.h
llpanelmediasettingsgeneral.h
llpanelmediasettingspermissions.h
llpanelmediasettingssecurity.h
@@ -1470,7 +1476,7 @@ set(PACKAGE ON CACHE BOOL
"Add a package target that builds an installer package.")
if (WINDOWS)
- set_target_properties(${VIEWER_BINARY_NAME}
+ set_target_properties(${VIEWER_BINARY_NAME}
PROPERTIES
# *TODO -reenable this once we get server usage sorted out
#LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS /INCLUDE:\"__tcmalloc\""
diff --git a/indra/newview/app_settings/keys.xml b/indra/newview/app_settings/keys.xml
index d085475c6c..6e3673e7d9 100644
--- a/indra/newview/app_settings/keys.xml
+++ b/indra/newview/app_settings/keys.xml
@@ -181,7 +181,7 @@
<binding key="PAD_DIVIDE" mask="CTL_ALT_SHIFT" command="start_gesture"/>
</third_person>
- # Basic editing camera control
+ <!-- Basic editing camera control -->
<edit>
<binding key="A" mask="NONE" command="spin_around_cw"/>
<binding key="D" mask="NONE" command="spin_around_ccw"/>
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 01daf1ceb2..4b62e376b5 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -4180,6 +4180,28 @@
<key>Value</key>
<real>1.0</real>
</map>
+ <key>InventoryDisplayInbox</key>
+ <map>
+ <key>Comment</key>
+ <string>Override received items inventory inbox display</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>InventoryDisplayOutbox</key>
+ <map>
+ <key>Comment</key>
+ <string>Override merchant inventory outbox display</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>InventoryLinking</key>
<map>
<key>Comment</key>
@@ -4422,6 +4444,17 @@
<key>Value</key>
<real>2.0</real>
</map>
+ <key>LastInventoryInboxExpand</key>
+ <map>
+ <key>Comment</key>
+ <string>The last time the received items inbox was expanded.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string />
+ </map>
<key>LCDDestination</key>
<map>
<key>Comment</key>
@@ -6546,7 +6579,28 @@
<key>Value</key>
<integer>0</integer>
</map>
-
+ <key>PostFirstLoginIntroURL</key>
+ <map>
+ <key>Comment</key>
+ <string>URL of intro presenatation after first time users first login</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string></string>
+ </map>
+ <key>PostFirstLoginIntroViewed</key>
+ <map>
+ <key>Comment</key>
+ <string>Flag indicating if user has seen intro presenatation after first time users first login</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <string>0</string>
+ </map>
<key>PrecachingDelay</key>
<map>
<key>Comment</key>
@@ -7182,7 +7236,7 @@
</array>
</map>
- <key>RenderAnisotropic</key>
+ <key>RenderAnisotropic</key>
<map>
<key>Comment</key>
<string>Render textures using anisotropic filtering</string>
@@ -9627,7 +9681,7 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>0</integer>
+ <integer>1</integer>
</map>
<key>ShowSnapshotButton</key>
<map>
@@ -13346,5 +13400,43 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>WebProfileRect</key>
+ <map>
+ <key>Comment</key>
+ <string>Web profile dimensions</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Rect</string>
+ <key>Value</key>
+ <array>
+ <integer>0</integer>
+ <integer>650</integer>
+ <integer>490</integer>
+ <integer>0</integer>
+ </array>
+ </map>
+ <key>HelpFloaterOpen</key>
+ <map>
+ <key>Comment</key>
+ <string>Show Help Floater on login?</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>ShowHelpOnFirstLogin</key>
+ <map>
+ <key>Comment</key>
+ <string>Show Help Floater on first login</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
</map>
</llsd>
diff --git a/indra/newview/app_settings/settings_minimal.xml b/indra/newview/app_settings/settings_minimal.xml
index 70a75cb4ca..29e52ab054 100644
--- a/indra/newview/app_settings/settings_minimal.xml
+++ b/indra/newview/app_settings/settings_minimal.xml
@@ -459,5 +459,16 @@
<key>Value</key>
<integer>0</integer>
</map>
- </map>
+ <key>ShowHelpOnFirstLogin</key>
+ <map>
+ <key>Comment</key>
+ <string>Show Help Floater on first login</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ </map>
</llsd>
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index d426afb17c..36272f0c7c 100644
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -33,7 +33,6 @@
#include "llagentwearablesfetch.h"
#include "llappearancemgr.h"
#include "llcallbacklist.h"
-#include "llfolderview.h"
#include "llgesturemgr.h"
#include "llinventorybridge.h"
#include "llinventoryfunctions.h"
@@ -45,6 +44,7 @@
#include "llsidepanelappearance.h"
#include "llsidetray.h"
#include "lltexlayer.h"
+#include "lltooldraganddrop.h"
#include "llviewerregion.h"
#include "llvoavatarself.h"
#include "llwearable.h"
diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp
index 955f19c82c..8344b08bfb 100755
--- a/indra/newview/llavataractions.cpp
+++ b/indra/newview/llavataractions.cpp
@@ -49,6 +49,7 @@
#include "llfloaterpay.h"
#include "llfloaterwebcontent.h"
#include "llfloaterworldmap.h"
+#include "llfolderview.h"
#include "llgiveinventory.h"
#include "llinventorybridge.h"
#include "llinventorymodel.h" // for gInventory.findCategoryUUIDForType
@@ -69,6 +70,7 @@
#include "lltrans.h"
#include "llcallingcard.h"
#include "llslurl.h" // IDEVO
+#include "llsidepanelinventory.h"
// static
void LLAvatarActions::requestFriendshipDialog(const LLUUID& id, const std::string& name)
@@ -312,7 +314,9 @@ static void on_avatar_name_show_profile(const LLUUID& agent_id, const LLAvatarNa
std::string url = getProfileURL(username);
// PROFILES: open in webkit window
- LLWeb::loadWebURLInternal(url, "", agent_id.asString());
+ const bool show_chrome = false;
+ static LLCachedControl<LLRect> profile_rect(gSavedSettings, "WebProfileRect");
+ LLFloaterWebContent::create(url, "", agent_id.asString(), show_chrome, profile_rect);
}
// static
@@ -444,8 +448,6 @@ void LLAvatarActions::share(const LLUUID& id)
namespace action_give_inventory
{
- typedef std::set<LLUUID> uuid_set_t;
-
/**
* Returns a pointer to 'Add More' inventory panel of Edit Outfit SP.
*/
@@ -475,18 +477,16 @@ namespace action_give_inventory
/**
* Checks My Inventory visibility.
*/
+
static bool is_give_inventory_acceptable()
{
- LLInventoryPanel* active_panel = get_active_inventory_panel();
- if (!active_panel) return false;
-
// check selection in the panel
- const uuid_set_t inventory_selected_uuids = active_panel->getRootFolder()->getSelectionList();
+ const std::set<LLUUID> inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs();
if (inventory_selected_uuids.empty()) return false; // nothing selected
bool acceptable = false;
- uuid_set_t::const_iterator it = inventory_selected_uuids.begin();
- const uuid_set_t::const_iterator it_end = inventory_selected_uuids.end();
+ std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin();
+ const std::set<LLUUID>::const_iterator it_end = inventory_selected_uuids.end();
for (; it != it_end; ++it)
{
LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it);
@@ -529,12 +529,12 @@ namespace action_give_inventory
}
}
- static void build_items_string(const uuid_set_t& inventory_selected_uuids , std::string& items_string)
+ static void build_items_string(const std::set<LLUUID>& inventory_selected_uuids , std::string& items_string)
{
llassert(inventory_selected_uuids.size() > 0);
const std::string& separator = LLTrans::getString("words_separator");
- for (uuid_set_t::const_iterator it = inventory_selected_uuids.begin(); ; )
+ for (std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin(); ; )
{
LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it);
if (NULL != inv_cat)
@@ -570,10 +570,7 @@ namespace action_give_inventory
return;
}
- LLInventoryPanel* active_panel = get_active_inventory_panel();
- if (!active_panel) return;
-
- const uuid_set_t inventory_selected_uuids = active_panel->getRootFolder()->getSelectionList();
+ const std::set<LLUUID> inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs();
if (inventory_selected_uuids.empty())
{
return;
@@ -590,8 +587,8 @@ namespace action_give_inventory
// We souldn't open IM session, just calculate session ID for logging purpose. See EXT-6710
const LLUUID session_id = gIMMgr->computeSessionID(IM_NOTHING_SPECIAL, avatar_uuid);
- uuid_set_t::const_iterator it = inventory_selected_uuids.begin();
- const uuid_set_t::const_iterator it_end = inventory_selected_uuids.end();
+ std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin();
+ const std::set<LLUUID>::const_iterator it_end = inventory_selected_uuids.end();
const std::string& separator = LLTrans::getString("words_separator");
std::string noncopy_item_names;
@@ -654,10 +651,7 @@ namespace action_give_inventory
{
llassert(avatar_names.size() == avatar_uuids.size());
- LLInventoryPanel* active_panel = get_active_inventory_panel();
- if (!active_panel) return;
-
- const uuid_set_t inventory_selected_uuids = active_panel->getRootFolder()->getSelectionList();
+ const std::set<LLUUID> inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs();
if (inventory_selected_uuids.empty())
{
return;
@@ -678,6 +672,33 @@ namespace action_give_inventory
}
}
+
+
+//static
+std::set<LLUUID> LLAvatarActions::getInventorySelectedUUIDs()
+{
+ std::set<LLUUID> inventory_selected_uuids;
+
+ LLInventoryPanel* active_panel = action_give_inventory::get_active_inventory_panel();
+ if (active_panel)
+ {
+ inventory_selected_uuids = active_panel->getRootFolder()->getSelectionList();
+ }
+
+ if (inventory_selected_uuids.empty())
+ {
+ LLSidepanelInventory * sidepanel_inventory = LLSideTray::getInstance()->getPanel<LLSidepanelInventory>("sidepanel_inventory");
+ LLInventoryPanel * inbox = sidepanel_inventory->findChild<LLInventoryPanel>("inventory_inbox");
+ if (inbox)
+ {
+ inventory_selected_uuids = inbox->getRootFolder()->getSelectionList();
+ }
+
+ }
+
+ return inventory_selected_uuids;
+}
+
//static
void LLAvatarActions::shareWithAvatars()
{
@@ -705,12 +726,12 @@ bool LLAvatarActions::canShareSelectedItems(LLInventoryPanel* inv_panel /* = NUL
// check selection in the panel
LLFolderView* root_folder = inv_panel->getRootFolder();
- const uuid_set_t inventory_selected_uuids = root_folder->getSelectionList();
+ const std::set<LLUUID> inventory_selected_uuids = root_folder->getSelectionList();
if (inventory_selected_uuids.empty()) return false; // nothing selected
bool can_share = true;
- uuid_set_t::const_iterator it = inventory_selected_uuids.begin();
- const uuid_set_t::const_iterator it_end = inventory_selected_uuids.end();
+ std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin();
+ const std::set<LLUUID>::const_iterator it_end = inventory_selected_uuids.end();
for (; it != it_end; ++it)
{
LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it);
diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h
index 956fed7461..fbfd815f41 100644
--- a/indra/newview/llavataractions.h
+++ b/indra/newview/llavataractions.h
@@ -36,6 +36,7 @@
class LLInventoryPanel;
+
/**
* Friend-related actions (add, remove, offer teleport, etc)
*/
@@ -196,6 +197,8 @@ public:
*/
static bool canShareSelectedItems(LLInventoryPanel* inv_panel = NULL);
+ static std::set<LLUUID> getInventorySelectedUUIDs();
+
private:
static bool callbackAddFriendWithMessage(const LLSD& notification, const LLSD& response);
static bool handleRemove(const LLSD& notification, const LLSD& response);
diff --git a/indra/newview/llfilteredwearablelist.cpp b/indra/newview/llfilteredwearablelist.cpp
index cd5e779c4d..a29ccf2b6d 100644
--- a/indra/newview/llfilteredwearablelist.cpp
+++ b/indra/newview/llfilteredwearablelist.cpp
@@ -31,6 +31,7 @@
#include "llinventoryfunctions.h"
#include "llinventoryitemslist.h"
#include "llinventorymodel.h"
+#include "llviewerinventory.h"
LLFilteredWearableListManager::LLFilteredWearableListManager(LLInventoryItemsList* list, LLInventoryCollectFunctor* collector)
diff --git a/indra/newview/llfloaterhelpbrowser.cpp b/indra/newview/llfloaterhelpbrowser.cpp
index 627defd006..3012638d44 100644
--- a/indra/newview/llfloaterhelpbrowser.cpp
+++ b/indra/newview/llfloaterhelpbrowser.cpp
@@ -71,9 +71,18 @@ void LLFloaterHelpBrowser::buildURLHistory()
}
}
+void LLFloaterHelpBrowser::onOpen(const LLSD& key)
+{
+ gSavedSettings.setBOOL("HelpFloaterOpen", TRUE);
+}
+
//virtual
void LLFloaterHelpBrowser::onClose(bool app_quitting)
{
+ if (!app_quitting)
+ {
+ gSavedSettings.setBOOL("HelpFloaterOpen", FALSE);
+ }
// really really destroy the help browser when it's closed, it'll be recreated.
destroy(); // really destroy this dialog on closure, it's relatively heavyweight.
}
diff --git a/indra/newview/llfloaterhelpbrowser.h b/indra/newview/llfloaterhelpbrowser.h
index 2731c81b9c..afe0f4df69 100644
--- a/indra/newview/llfloaterhelpbrowser.h
+++ b/indra/newview/llfloaterhelpbrowser.h
@@ -42,6 +42,7 @@ class LLFloaterHelpBrowser :
/*virtual*/ BOOL postBuild();
/*virtual*/ void onClose(bool app_quitting);
+ /*virtual*/ void onOpen(const LLSD& key);
// inherited from LLViewerMediaObserver
/*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event);
diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp
index 058567492b..43eecbf048 100644
--- a/indra/newview/llfloaterwebcontent.cpp
+++ b/indra/newview/llfloaterwebcontent.cpp
@@ -99,7 +99,7 @@ void LLFloaterWebContent::initializeURLHistory()
}
//static
-void LLFloaterWebContent::create( const std::string &url, const std::string& target, const std::string& uuid )
+void LLFloaterWebContent::create( const std::string &url, const std::string& target, const std::string& uuid, bool show_chrome, const LLRect& preferred_media_size)
{
lldebugs << "url = " << url << ", target = " << target << ", uuid = " << uuid << llendl;
@@ -155,6 +155,20 @@ void LLFloaterWebContent::create( const std::string &url, const std::string& tar
// tell the browser instance to load the specified URL
browser->open_media(url, target);
LLViewerMedia::proxyWindowOpened(target, uuid);
+
+ browser->getChild<LLLayoutPanel>("status_bar")->setVisible(show_chrome);
+ browser->getChild<LLLayoutPanel>("nav_controls")->setVisible(show_chrome);
+
+ if (!show_chrome)
+ {
+ browser->setResizeLimits(100, 100);
+ }
+
+ if (!preferred_media_size.isEmpty())
+ {
+ //ignore x, y for now
+ browser->geometryChanged(browser->getRect().mLeft, browser->getRect().mBottom, preferred_media_size.getWidth(), preferred_media_size.getHeight());
+ }
}
}
@@ -210,7 +224,7 @@ void LLFloaterWebContent::geometryChanged(S32 x, S32 y, S32 width, S32 height)
lldebugs << "geometry change: " << geom << llendl;
- handleReshape(geom,false);
+ setShape(geom);
}
void LLFloaterWebContent::open_media(const std::string& web_url, const std::string& target)
diff --git a/indra/newview/llfloaterwebcontent.h b/indra/newview/llfloaterwebcontent.h
index ecc7e970d8..56b6ef12c8 100644
--- a/indra/newview/llfloaterwebcontent.h
+++ b/indra/newview/llfloaterwebcontent.h
@@ -46,7 +46,7 @@ public:
void initializeURLHistory();
- static void create(const std::string &url, const std::string& target, const std::string& uuid = LLStringUtil::null);
+ static void create(const std::string &url, const std::string& target, const std::string& uuid = LLStringUtil::null, bool show_chrome = true, const LLRect& preferred_media_size = LLRect() );
static void closeRequest(const std::string &uuid);
static void geometryChanged(const std::string &uuid, S32 x, S32 y, S32 width, S32 height);
diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp
index 3884b94b60..e90b6c1c3d 100644
--- a/indra/newview/llfolderview.cpp
+++ b/indra/newview/llfolderview.cpp
@@ -167,13 +167,23 @@ void LLCloseAllFoldersFunctor::doItem(LLFolderViewItem* item)
///----------------------------------------------------------------------------
/// Class LLFolderView
///----------------------------------------------------------------------------
+LLFolderView::Params::Params()
+: task_id("task_id"),
+ title("title"),
+ use_label_suffix("use_label_suffix"),
+ allow_multiselect("allow_multiselect", true),
+ show_load_status("show_load_status", true),
+ use_ellipses("use_ellipses", false)
+{
+}
+
// Default constructor
LLFolderView::LLFolderView(const Params& p)
: LLFolderViewFolder(p),
mScrollContainer( NULL ),
mPopupMenuHandle(),
- mAllowMultiSelect(TRUE),
+ mAllowMultiSelect(p.allow_multiselect),
mShowFolderHierarchy(FALSE),
mSourceID(p.task_id),
mRenameItem( NULL ),
@@ -194,10 +204,14 @@ LLFolderView::LLFolderView(const Params& p)
mDragAndDropThisFrame(FALSE),
mCallbackRegistrar(NULL),
mParentPanel(p.parent_panel),
- mUseEllipses(false),
+ mUseEllipses(p.use_ellipses),
mDraggingOverItem(NULL),
mStatusTextBox(NULL)
{
+ mRoot = this;
+
+ mShowLoadStatus = p.show_load_status();
+
LLRect rect = p.rect;
LLRect new_rect(rect.mLeft, rect.mBottom + getRect().getHeight(), rect.mLeft + getRect().getWidth(), rect.mBottom);
setRect( rect );
@@ -263,6 +277,7 @@ LLFolderView::LLFolderView(const Params& p)
menu->setBackgroundColor(LLUIColorTable::instance().getColor("MenuPopupBgColor"));
mPopupMenuHandle = menu->getHandle();
+ mListener->openItem();
}
// Destroys the object
@@ -308,15 +323,10 @@ void LLFolderView::setSortOrder(U32 order)
if (order != mSortOrder)
{
LLFastTimer t(FTM_SORT);
+
mSortOrder = order;
- for (folders_t::iterator iter = mFolders.begin();
- iter != mFolders.end();)
- {
- folders_t::iterator fit = iter++;
- (*fit)->sortBy(order);
- }
-
+ sortBy(order);
arrangeAll();
}
}
@@ -342,7 +352,7 @@ BOOL LLFolderView::addFolder( LLFolderViewFolder* folder)
{
recursiveIncrementNumDescendantsSelected(folder->numSelected());
}
- folder->setShowLoadStatus(true);
+ folder->setShowLoadStatus(mShowLoadStatus);
folder->setOrigin(0, 0);
folder->reshape(getRect().getWidth(), 0);
folder->setVisible(FALSE);
@@ -424,11 +434,7 @@ S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_gen
(folderp->getFiltered(filter_generation) || folderp->hasFilteredDescendants(filter_generation))); // passed filter or has descendants that passed filter
}
- // Need to call arrange regardless of visibility, since children's visibility
- // might need to be changed too (e.g. even though a folder is invisible, its
- // children also need to be set invisible for state-tracking purposes, e.g.
- // llfolderviewitem::filter).
- // if (folderp->getVisible())
+ if (folderp->getVisible())
{
S32 child_height = 0;
S32 child_width = 0;
@@ -764,7 +770,7 @@ void LLFolderView::sanitizeSelection()
}
// Don't allow invisible items (such as root folders) to be selected.
- if (item->getHidden())
+ if (item == getRoot())
{
items_to_remove.push_back(item);
}
@@ -787,7 +793,7 @@ void LLFolderView::sanitizeSelection()
parent_folder;
parent_folder = parent_folder->getParentFolder())
{
- if (parent_folder->potentiallyVisible() && !parent_folder->getHidden())
+ if (parent_folder->potentiallyVisible())
{
// give initial selection to first ancestor folder that potentially passes the filter
if (!new_selection)
@@ -806,13 +812,7 @@ void LLFolderView::sanitizeSelection()
}
else
{
- // nothing selected to start with, so pick "My Inventory" as best guess
- new_selection = getItemByID(gInventory.getRootFolderID());
- // ... except if it's hidden from the UI.
- if (new_selection && new_selection->getHidden())
- {
- new_selection = NULL;
- }
+ new_selection = NULL;
}
if (new_selection)
@@ -931,14 +931,15 @@ void LLFolderView::draw()
if (LLInventoryModelBackgroundFetch::instance().backgroundFetchActive() || mCompletedFilterGeneration < mFilter->getMinRequiredGeneration())
{
mStatusText = LLTrans::getString("Searching");
- //font->renderUTF8(mStatusText, 0, 2, 1, sSearchStatusColor, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE );
}
else
{
- LLStringUtil::format_map_t args;
- args["[SEARCH_TERM]"] = LLURI::escape(getFilter()->getFilterSubStringOrig());
- mStatusText = LLTrans::getString(getFilter()->getEmptyLookupMessage(), args);
- //font->renderUTF8(mStatusText, 0, 2, 1, sSearchStatusColor, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE );
+ if (getFilter())
+ {
+ LLStringUtil::format_map_t args;
+ args["[SEARCH_TERM]"] = LLURI::escape(getFilter()->getFilterSubStringOrig());
+ mStatusText = LLTrans::getString(getFilter()->getEmptyLookupMessage(), args);
+ }
}
mStatusTextBox->setValue(mStatusText);
mStatusTextBox->setVisible( TRUE );
@@ -962,7 +963,9 @@ void LLFolderView::draw()
}
- LLFolderViewFolder::draw();
+ // skip over LLFolderViewFolder::draw since we don't want the folder icon, label,
+ // and arrow for the root folder
+ LLView::draw();
mDragAndDropThisFrame = FALSE;
}
@@ -1642,11 +1645,7 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask )
LLFolderViewItem* parent_folder = last_selected->getParentFolder();
if (!last_selected->isOpen() && parent_folder && parent_folder->getParentFolder())
{
- // Don't change selectin to hidden folder. See EXT-5328.
- if (!parent_folder->getHidden())
- {
- setSelection(parent_folder, FALSE, TRUE);
- }
+ setSelection(parent_folder, FALSE, TRUE);
}
else
{
@@ -1911,7 +1910,14 @@ BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
// by the folder which is the hierarchy root.
if (!handled && !hasVisibleChildren())
{
- handled = mFolders.front()->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg);
+ if (mFolders.empty())
+ {
+ handled = handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg);
+ }
+ else
+ {
+ handled = mFolders.front()->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg);
+ }
}
if (handled)
@@ -1927,8 +1933,11 @@ void LLFolderView::deleteAllChildren()
closeRenamer();
LLView::deleteViewByHandle(mPopupMenuHandle);
mPopupMenuHandle = LLHandle<LLView>();
- mRenamer = NULL;
+ mScrollContainer = NULL;
mRenameItem = NULL;
+ mRenamer = NULL;
+ mStatusTextBox = NULL;
+
clearSelection();
LLView::deleteAllChildren();
}
@@ -2031,7 +2040,7 @@ void LLFolderView::removeItemID(const LLUUID& id)
LLFolderViewItem* LLFolderView::getItemByID(const LLUUID& id)
{
- if (id.isNull())
+ if (id == getListener()->getUUID())
{
return this;
}
@@ -2048,7 +2057,7 @@ LLFolderViewItem* LLFolderView::getItemByID(const LLUUID& id)
LLFolderViewFolder* LLFolderView::getFolderByID(const LLUUID& id)
{
- if (id.isNull())
+ if (id == getListener()->getUUID())
{
return this;
}
@@ -2173,7 +2182,7 @@ void LLFolderView::doIdle()
// filter to determine visiblity before arranging
filterFromRoot();
- // automatically show matching items, and select first one
+ // automatically show matching items, and select first one if we had a selection
// do this every frame until user puts keyboard focus into the inventory window
// signaling the end of the automatic update
// only do this when mNeedsFilter is set, meaning filtered items have
@@ -2183,7 +2192,7 @@ void LLFolderView::doIdle()
LLFastTimer t3(FTM_AUTO_SELECT);
// select new item only if a filtered item not currently selected
LLFolderViewItem* selected_itemp = mSelectedItems.empty() ? NULL : mSelectedItems.back();
- if ((!selected_itemp || !selected_itemp->getFiltered()) && !mAutoSelectOverride)
+ if ((selected_itemp && !selected_itemp->getFiltered()) && !mAutoSelectOverride)
{
// select first filtered item
LLSelectFirstFilteredItem filter;
@@ -2496,11 +2505,6 @@ BOOL LLFolderView::isFilterModified()
return mFilter->isNotDefault();
}
-BOOL LLFolderView::getAllowMultiSelect()
-{
- return mAllowMultiSelect;
-}
-
void delete_selected_item(void* user_data)
{
if(user_data)
diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h
index 1464a058d8..0b92548fd0 100644
--- a/indra/newview/llfolderview.h
+++ b/indra/newview/llfolderview.h
@@ -59,22 +59,6 @@ class LLUICtrl;
class LLTextBox;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLFolderViewFunctor
-//
-// Simple abstract base class for applying a functor to folders and
-// items in a folder view hierarchy. This is suboptimal for algorithms
-// that only work folders or only work on items, but I'll worry about
-// that later when it's determined to be too slow.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-class LLFolderViewFunctor
-{
-public:
- virtual ~LLFolderViewFunctor() {}
- virtual void doFolder(LLFolderViewFolder* folder) = 0;
- virtual void doItem(LLFolderViewItem* item) = 0;
-};
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLFolderView
//
// Th LLFolderView represents the root level folder view object. It
@@ -89,7 +73,12 @@ public:
Mandatory<LLPanel*> parent_panel;
Optional<LLUUID> task_id;
Optional<std::string> title;
- Optional<bool> use_label_suffix;
+ Optional<bool> use_label_suffix,
+ allow_multiselect,
+ show_load_status,
+ use_ellipses;
+
+ Params();
};
LLFolderView(const Params&);
virtual ~LLFolderView( void );
@@ -102,7 +91,6 @@ public:
// and resort the items if necessary.
void setSortOrder(U32 order);
void setFilterPermMask(PermissionMask filter_perm_mask);
- void setAllowMultiSelect(BOOL allow) { mAllowMultiSelect = allow; }
typedef boost::signals2::signal<void (const std::deque<LLFolderViewItem*>& items, BOOL user_action)> signal_t;
void setSelectCallback(const signal_t::slot_type& cb) { mSelectSignal.connect(cb); }
@@ -117,7 +105,6 @@ public:
//LLInventoryFilter::EFolderShow getShowFolderState();
U32 getSortOrder() const;
BOOL isFilterModified();
- BOOL getAllowMultiSelect();
// Close all folders in the view
void closeAllFolders();
@@ -238,7 +225,6 @@ public:
void setShowSingleSelection(BOOL show);
BOOL getShowSingleSelection() { return mShowSingleSelection; }
F32 getSelectionFadeElapsedTime() { return mMultiSelectionFadeTimer.getElapsedTimeF32(); }
- void setUseEllipses(bool use_ellipses) { mUseEllipses = use_ellipses; }
bool getUseEllipses() { return mUseEllipses; }
void addItemID(const LLUUID& id, LLFolderViewItem* itemp);
diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp
index e9d1ad3a9e..6e4f55fb2f 100644
--- a/indra/newview/llfolderviewitem.cpp
+++ b/indra/newview/llfolderviewitem.cpp
@@ -30,8 +30,10 @@
// viewer includes
#include "llfolderview.h" // Items depend extensively on LLFolderViews
#include "llfoldervieweventlistener.h"
+#include "llviewerfoldertype.h"
#include "llinventorybridge.h" // for LLItemBridge in LLInventorySort::operator()
#include "llinventoryfilter.h"
+#include "llinventoryfunctions.h"
#include "llinventorymodelbackgroundfetch.h"
#include "llpanel.h"
#include "llviewercontrol.h" // gSavedSettings
@@ -130,10 +132,14 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)
mIconOpen(p.icon_open),
mIconOverlay(p.icon_overlay),
mListener(p.listener),
- mHidden(false),
mShowLoadStatus(false)
{
+}
+
+BOOL LLFolderViewItem::postBuild()
+{
refresh();
+ return TRUE;
}
// Destroys the object
@@ -195,7 +201,7 @@ LLFolderViewItem* LLFolderViewItem::getPreviousOpenNode(BOOL include_children)
LLFolderViewItem* itemp = mParentFolder->getPreviousFromChild( this, include_children );
// Skip over items that are invisible or are hidden from the UI.
- while(itemp && (!itemp->getVisible() || itemp->getHidden()))
+ while(itemp && !itemp->getVisible())
{
LLFolderViewItem* next_itemp = itemp->mParentFolder->getPreviousFromChild( itemp, include_children );
if (itemp == next_itemp)
@@ -351,7 +357,10 @@ void LLFolderViewItem::arrangeAndSet(BOOL set_selection,
BOOL take_keyboard_focus)
{
LLFolderView* root = getRoot();
+ if (getParentFolder())
+ {
getParentFolder()->requestArrange();
+ }
if(set_selection)
{
setSelectionFromRoot(this, TRUE, take_keyboard_focus);
@@ -442,23 +451,20 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height, S32 filter_generation)
S32 LLFolderViewItem::getItemHeight()
{
- if (getHidden()) return 0;
-
return mItemHeight;
}
void LLFolderViewItem::filter( LLInventoryFilter& filter)
{
const BOOL previous_passed_filter = mPassedFilter;
- const BOOL passed_filter = mListener && filter.check(this);
+ const BOOL passed_filter = filter.check(this);
// If our visibility will change as a result of this filter, then
// we need to be rearranged in our parent folder
if (mParentFolder)
{
- if (getVisible() != passed_filter)
- mParentFolder->requestArrange();
- if (passed_filter != previous_passed_filter)
+ if (getVisible() != passed_filter
+ || previous_passed_filter != passed_filter )
mParentFolder->requestArrange();
}
@@ -863,11 +869,6 @@ BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
void LLFolderViewItem::draw()
{
- if (getHidden())
- {
- return;
- }
-
static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE);
static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE);
static LLUIColor sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE);
@@ -891,8 +892,8 @@ void LLFolderViewItem::draw()
// Draw open folder arrow
//
const bool up_to_date = mListener && mListener->isUpToDate();
- const bool possibly_has_children = ((up_to_date && hasVisibleChildren()) || // we fetched our children and some of them have passed the filter...
- (!up_to_date && mListener && mListener->hasChildren())); // ...or we know we have children but haven't fetched them (doesn't obey filter)
+ const bool possibly_has_children = ((up_to_date && hasVisibleChildren()) // we fetched our children and some of them have passed the filter...
+ || (!up_to_date && mListener && mListener->hasChildren())); // ...or we know we have children but haven't fetched them (doesn't obey filter)
if (possibly_has_children)
{
LLUIImage* arrow_image = default_params.folder_arrow_image;
@@ -1054,8 +1055,11 @@ void LLFolderViewItem::draw()
{
root_is_loading = LLInventoryModelBackgroundFetch::instance().libraryFetchInProgress();
}
- if ((mIsLoading && mTimeSinceRequestStart.getElapsedTimeF32() >= gSavedSettings.getF32("FolderLoadingMessageWaitTime")) ||
- (LLInventoryModelBackgroundFetch::instance().backgroundFetchActive() && root_is_loading && (mShowLoadStatus || mHidden)))
+ if ((mIsLoading
+ && mTimeSinceRequestStart.getElapsedTimeF32() >= gSavedSettings.getF32("FolderLoadingMessageWaitTime"))
+ || (LLInventoryModelBackgroundFetch::instance().backgroundFetchActive()
+ && root_is_loading
+ && mShowLoadStatus))
{
std::string load_string = " ( " + LLTrans::getString("LoadingData") + " ) ";
font->renderUTF8(load_string, 0, right_x, y, sSearchStatusColor,
@@ -1119,7 +1123,8 @@ LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ):
mLastCalculatedWidth(0),
mCompletedFilterGeneration(-1),
mMostFilteredDescendantGeneration(-1),
- mNeedsSort(false)
+ mNeedsSort(false),
+ mPassedFolderFilter(FALSE)
{
}
@@ -1131,6 +1136,17 @@ LLFolderViewFolder::~LLFolderViewFolder( void )
gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit()
}
+void LLFolderViewFolder::setFilteredFolder(bool filtered, S32 filter_generation)
+{
+ mPassedFolderFilter = filtered;
+ mLastFilterGeneration = filter_generation;
+}
+
+bool LLFolderViewFolder::getFilteredFolder(S32 filter_generation)
+{
+ return mPassedFolderFilter && mLastFilterGeneration >= getRoot()->getFilter()->getMinRequiredGeneration();
+}
+
// addToFolder() returns TRUE if it succeeds. FALSE otherwise
BOOL LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder, LLFolderView* root)
{
@@ -1157,8 +1173,6 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation)
mHasVisibleChildren = hasFilteredDescendants(filter_generation);
- LLInventoryFilter::EFolderShow show_folder_state = getRoot()->getFilter()->getShowFolderState();
-
// calculate height as a single item (without any children), and reshapes rectangle to match
LLFolderViewItem::arrange( width, height, filter_generation );
@@ -1190,8 +1204,10 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation)
}
else
{
- folderp->setVisible(show_folder_state == LLInventoryFilter::SHOW_ALL_FOLDERS || // always show folders?
- (folderp->getFiltered(filter_generation) || folderp->hasFilteredDescendants(filter_generation))); // passed filter or has descendants that passed filter
+ folderp->setVisible( folderp->getListener()
+ && (folderp->getFiltered(filter_generation)
+ || (folderp->getFilteredFolder(filter_generation)
+ && folderp->hasFilteredDescendants(filter_generation)))); // passed filter or has descendants that passed filter
}
if (folderp->getVisible())
@@ -1311,7 +1327,9 @@ void LLFolderViewFolder::setCompletedFilterGeneration(S32 generation, BOOL recur
mMostFilteredDescendantGeneration = llmin(mMostFilteredDescendantGeneration, generation);
mCompletedFilterGeneration = generation;
// only aggregate up if we are a lower (older) value
- if (recurse_up && mParentFolder && generation < mParentFolder->getCompletedFilterGeneration())
+ if (recurse_up
+ && mParentFolder
+ && generation < mParentFolder->getCompletedFilterGeneration())
{
mParentFolder->setCompletedFilterGeneration(generation, TRUE);
}
@@ -1336,21 +1354,19 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter)
// filter folder itself
if (getLastFilterGeneration() < filter_generation)
{
- if (getLastFilterGeneration() >= must_pass_generation && // folder has been compared to a valid precursor filter
- !mPassedFilter) // and did not pass the filter
+ if (getLastFilterGeneration() >= must_pass_generation // folder has been compared to a valid precursor filter
+ && !mPassedFilter) // and did not pass the filter
{
// go ahead and flag this folder as done
mLastFilterGeneration = filter_generation;
}
- else
+ else // filter self only on first pass through
{
- // filter self only on first pass through
+ // filter against folder rules
+ filterFolder(filter);
+ // and then item rules
LLFolderViewItem::filter( filter );
}
- if (mHidden)
- {
- setOpen();
- }
}
if (getRoot()->getDebugFilters())
@@ -1377,7 +1393,10 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter)
}
// when applying a filter, matching folders get their contents downloaded first
- if (filter.isNotDefault() && getFiltered(filter.getMinRequiredGeneration()) && (mListener && !gInventory.isCategoryComplete(mListener->getUUID())))
+ if (filter.isNotDefault()
+ && getFiltered(filter.getMinRequiredGeneration())
+ && (mListener
+ && !gInventory.isCategoryComplete(mListener->getUUID())))
{
LLInventoryModelBackgroundFetch::instance().start(mListener->getUUID());
}
@@ -1403,6 +1422,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter)
if (folder->getFiltered() || folder->hasFilteredDescendants(filter.getMinRequiredGeneration()))
{
mMostFilteredDescendantGeneration = filter_generation;
+ requestArrange();
}
// just skip it, it has already been filtered
continue;
@@ -1415,6 +1435,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter)
if (folder->getFiltered() || folder->hasFilteredDescendants(filter_generation))
{
mMostFilteredDescendantGeneration = filter_generation;
+ requestArrange();
if (getRoot()->needsAutoSelect() && autoopen_folders)
{
folder->setOpenArrangeRecursively(TRUE);
@@ -1436,6 +1457,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter)
if (item->getFiltered())
{
mMostFilteredDescendantGeneration = filter_generation;
+ requestArrange();
}
continue;
}
@@ -1454,6 +1476,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter)
if (item->getFiltered(filter.getMinRequiredGeneration()))
{
mMostFilteredDescendantGeneration = filter_generation;
+ requestArrange();
}
}
@@ -1467,6 +1490,31 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter)
}
}
+void LLFolderViewFolder::filterFolder(LLInventoryFilter& filter)
+{
+ const BOOL previous_passed_filter = mPassedFolderFilter;
+ const BOOL passed_filter = filter.checkFolder(this);
+
+ // If our visibility will change as a result of this filter, then
+ // we need to be rearranged in our parent folder
+ if (mParentFolder)
+ {
+ if (getVisible() != passed_filter
+ || previous_passed_filter != passed_filter )
+ {
+ mParentFolder->requestArrange();
+ }
+ }
+
+ setFilteredFolder(passed_filter, filter.getCurrentGeneration());
+ filter.decrementFilterCount();
+
+ if (getRoot()->getDebugFilters())
+ {
+ mStatusText = llformat("%d", mLastFilterGeneration);
+ }
+}
+
void LLFolderViewFolder::setFiltered(BOOL filtered, S32 filter_generation)
{
// if this folder is now filtered, but wasn't before
@@ -1488,6 +1536,23 @@ void LLFolderViewFolder::dirtyFilter()
LLFolderViewItem::dirtyFilter();
}
+BOOL LLFolderViewFolder::getFiltered()
+{
+ return getFilteredFolder(getRoot()->getFilter()->getMinRequiredGeneration())
+ && LLFolderViewItem::getFiltered();
+}
+
+BOOL LLFolderViewFolder::getFiltered(S32 filter_generation)
+{
+ return getFilteredFolder(filter_generation) && LLFolderViewItem::getFiltered(filter_generation);
+}
+
+BOOL LLFolderViewFolder::hasFilteredDescendants(S32 filter_generation)
+{
+ return mMostFilteredDescendantGeneration >= filter_generation;
+}
+
+
BOOL LLFolderViewFolder::hasFilteredDescendants()
{
return mMostFilteredDescendantGeneration >= getRoot()->getFilter()->getCurrentGeneration();
@@ -1743,7 +1808,7 @@ void LLFolderViewFolder::destroyView()
folderp->destroyView(); // removes entry from mFolders
}
- deleteAllChildren();
+ //deleteAllChildren();
if (mParentFolder)
{
@@ -1843,8 +1908,12 @@ void LLFolderViewFolder::sortBy(U32 order)
(*fit)->sortBy(order);
}
- mFolders.sort(mSortFunction);
- mItems.sort(mSortFunction);
+ // Don't sort the topmost folders (My Inventory and Library)
+ if (mListener->getUUID().notNull())
+ {
+ mFolders.sort(mSortFunction);
+ mItems.sort(mSortFunction);
+ }
if (order & LLInventoryFilter::SO_DATE)
{
@@ -1981,6 +2050,13 @@ BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item)
item->dirtyFilter();
requestArrange();
requestSort();
+ LLFolderViewFolder* parentp = getParentFolder();
+ while (parentp && parentp->mSortFunction.isByDate())
+ {
+ // parent folder doesn't have a time stamp yet, so get it from us
+ parentp->requestSort();
+ parentp = parentp->getParentFolder();
+ }
return TRUE;
}
@@ -2000,6 +2076,13 @@ BOOL LLFolderViewFolder::addFolder(LLFolderViewFolder* folder)
// rearrange all descendants too, as our indentation level might have changed
folder->requestArrange(TRUE);
requestSort();
+ LLFolderViewFolder* parentp = getParentFolder();
+ while (parentp && !parentp->mSortFunction.isByDate())
+ {
+ // parent folder doesn't have a time stamp yet, so get it from us
+ parentp->requestSort();
+ parentp = parentp->getParentFolder();
+ }
return TRUE;
}
@@ -2059,7 +2142,9 @@ void LLFolderViewFolder::setOpenArrangeRecursively(BOOL openitem, ERecurseType r
(*fit)->setOpenArrangeRecursively(openitem, RECURSE_DOWN); /* Flawfinder: ignore */
}
}
- if (mParentFolder && (recurse == RECURSE_UP || recurse == RECURSE_UP_DOWN))
+ if (mParentFolder
+ && (recurse == RECURSE_UP
+ || recurse == RECURSE_UP_DOWN))
{
mParentFolder->setOpenArrangeRecursively(openitem, RECURSE_UP);
}
@@ -2301,13 +2386,16 @@ void LLFolderViewFolder::draw()
bool possibly_has_children = false;
bool up_to_date = mListener && mListener->isUpToDate();
- if(!up_to_date && mListener && mListener->hasChildren()) // we know we have children but haven't fetched them (doesn't obey filter)
+ if(!up_to_date
+ && mListener->hasChildren()) // we know we have children but haven't fetched them (doesn't obey filter)
{
possibly_has_children = true;
}
- BOOL loading = ( mIsOpen && possibly_has_children && !up_to_date );
+ BOOL loading = (mIsOpen
+ && possibly_has_children
+ && !up_to_date );
if ( loading && !mIsLoading )
{
@@ -2330,6 +2418,41 @@ void LLFolderViewFolder::draw()
time_t LLFolderViewFolder::getCreationDate() const
{
+ // folders have no creation date try to create one from an item somewhere in our folder hierarchy
+ if (!mCreationDate)
+ {
+ for (items_t::const_iterator iit = mItems.begin();
+ iit != mItems.end(); ++iit)
+ {
+ LLFolderViewItem* itemp = (*iit);
+
+ const time_t item_creation_date = itemp->getCreationDate();
+
+ if (item_creation_date)
+ {
+ mCreationDate = item_creation_date;
+ break;
+ }
+ }
+
+ if (!mCreationDate)
+ {
+ for (folders_t::const_iterator fit = mFolders.begin();
+ fit != mFolders.end(); ++fit)
+ {
+ LLFolderViewFolder* folderp = (*fit);
+
+ const time_t folder_creation_date = folderp->getCreationDate();
+
+ if (folder_creation_date)
+ {
+ mCreationDate = folder_creation_date;
+ break;
+ }
+ }
+ }
+ }
+
return llmax<time_t>(mCreationDate, mSubtreeCreationDate);
}
@@ -2573,7 +2696,8 @@ bool LLInventorySort::operator()(const LLFolderViewItem* const& a, const LLFolde
{
// ignore sort order for landmarks in the Favorites folder.
// they should be always sorted as in Favorites bar. See EXT-719
- if (a->getSortGroup() == SG_ITEM && b->getSortGroup() == SG_ITEM
+ if (a->getSortGroup() == SG_ITEM
+ && b->getSortGroup() == SG_ITEM
&& a->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK
&& b->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK)
{
diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h
index fc941510ab..e2f94a2b63 100644
--- a/indra/newview/llfolderviewitem.h
+++ b/indra/newview/llfolderviewitem.h
@@ -66,6 +66,7 @@ public:
// Returns true if order has changed
bool updateSort(U32 order);
U32 getSort() { return mSortOrder; }
+ bool isByDate() { return mByDate; }
bool operator()(const LLFolderViewItem* const& a, const LLFolderViewItem* const& b);
private:
@@ -94,7 +95,7 @@ public:
Optional<LLUIImage*> icon_open; // used for folders
Optional<LLUIImage*> icon_overlay; // for links
Optional<LLFolderView*> root;
- Optional<LLFolderViewEventListener*> listener;
+ Mandatory<LLFolderViewEventListener*> listener;
Optional<LLUIImage*> folder_arrow_image;
Optional<S32> folder_indentation; // pixels
@@ -135,7 +136,7 @@ protected:
std::string mSearchableLabel;
S32 mLabelWidth;
bool mLabelWidthDirty;
- time_t mCreationDate;
+ mutable time_t mCreationDate;
LLFolderViewFolder* mParentFolder;
LLFolderViewEventListener* mListener;
BOOL mIsCurSelection;
@@ -157,7 +158,6 @@ protected:
BOOL mDragAndDropTarget;
BOOL mIsLoading;
LLTimer mTimeSinceRequestStart;
- bool mHidden;
bool mShowLoadStatus;
// helper function to change the selection from the root.
@@ -167,13 +167,15 @@ protected:
void extendSelectionFromRoot(LLFolderViewItem* selection);
// this is an internal method used for adding items to folders. A
- // no-op at this leve, but reimplemented in derived classes.
+ // no-op at this level, but reimplemented in derived classes.
virtual BOOL addItem(LLFolderViewItem*) { return FALSE; }
virtual BOOL addFolder(LLFolderViewFolder*) { return FALSE; }
static LLFontGL* getLabelFontForStyle(U8 style);
public:
+ BOOL postBuild();
+
// This function clears the currently selected item, and records
// the specified selected item appropriately for display and use
// in the UI. If open is TRUE, then folders are opened up along
@@ -202,11 +204,6 @@ public:
virtual S32 arrange( S32* width, S32* height, S32 filter_generation );
virtual S32 getItemHeight();
- // Hide the folder from the UI, such as if you want to hide the root
- // folder in an inventory panel.
- void setHidden(bool hidden) { mHidden = hidden; }
- bool getHidden() const { return mHidden; }
-
// applies filters to control visibility of inventory items
virtual void filter( LLInventoryFilter& filter);
@@ -366,6 +363,9 @@ public:
UNKNOWN, TRASH, NOT_TRASH
} ETrash;
+ typedef std::list<LLFolderViewItem*> items_t;
+ typedef std::list<LLFolderViewFolder*> folders_t;
+
private:
S32 mNumDescendantsSelected;
@@ -374,8 +374,6 @@ public: // Accessed needed by LLFolderViewItem
S32 numSelected(void) const { return mNumDescendantsSelected + (isSelected() ? 1 : 0); }
protected:
- typedef std::list<LLFolderViewItem*> items_t;
- typedef std::list<LLFolderViewFolder*> folders_t;
items_t mItems;
folders_t mFolders;
LLInventorySort mSortFunction;
@@ -392,6 +390,8 @@ protected:
S32 mCompletedFilterGeneration;
S32 mMostFilteredDescendantGeneration;
bool mNeedsSort;
+ bool mPassedFolderFilter;
+
public:
typedef enum e_recurse_type
{
@@ -425,13 +425,21 @@ public:
virtual void setCompletedFilterGeneration(S32 generation, BOOL recurse_up);
virtual S32 getCompletedFilterGeneration() { return mCompletedFilterGeneration; }
- BOOL hasFilteredDescendants(S32 filter_generation) { return mMostFilteredDescendantGeneration >= filter_generation; }
+ BOOL hasFilteredDescendants(S32 filter_generation);
BOOL hasFilteredDescendants();
// applies filters to control visibility of inventory items
virtual void filter( LLInventoryFilter& filter);
virtual void setFiltered(BOOL filtered, S32 filter_generation);
+ virtual BOOL getFiltered();
+ virtual BOOL getFiltered(S32 filter_generation);
+
virtual void dirtyFilter();
+
+ // folder-specific filtering (filter status propagates top down instead of bottom up)
+ void filterFolder(LLInventoryFilter& filter);
+ void setFilteredFolder(bool filtered, S32 filter_generation);
+ bool getFilteredFolder(S32 filter_generation);
// Passes selection information on to children and record
// selection information if necessary.
@@ -537,6 +545,10 @@ public:
time_t getCreationDate() const;
bool isTrash() const;
S32 getNumSelectedDescendants(void) const { return mNumDescendantsSelected; }
+
+ folders_t::const_iterator getFoldersBegin() const { return mFolders.begin(); }
+ folders_t::const_iterator getFoldersEnd() const { return mFolders.end(); }
+ folders_t::size_type getFoldersCount() const { return mFolders.size(); }
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 86c8a1a9b5..75d4c4e80d 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -40,6 +40,7 @@
#include "llfloateropenobject.h"
#include "llfloaterreg.h"
#include "llfloaterworldmap.h"
+#include "llfolderview.h"
#include "llfriendcard.h"
#include "llgesturemgr.h"
#include "llgiveinventory.h"
@@ -571,8 +572,8 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
}
}
- // Don't allow items to be pasted directly into the COF.
- if (!isCOFFolder())
+ // Don't allow items to be pasted directly into the COF or the inbox
+ if (!isCOFFolder() && !isInboxFolder())
{
items.push_back(std::string("Paste"));
}
@@ -781,6 +782,18 @@ BOOL LLInvFVBridge::isCOFFolder() const
return LLAppearanceMgr::instance().getIsInCOF(mUUID);
}
+BOOL LLInvFVBridge::isInboxFolder() const
+{
+ const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false);
+
+ if (inbox_id.isNull())
+ {
+ return FALSE;
+ }
+
+ return gInventory.isObjectDescendentOf(mUUID, inbox_id);
+}
+
BOOL LLInvFVBridge::isItemPermissive() const
{
return FALSE;
@@ -1786,6 +1799,10 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
}
else
{
+ if (gInventory.isObjectDescendentOf(inv_cat->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false)))
+ {
+ set_dad_inbox_object(inv_cat->getUUID());
+ }
// Reparent the folder and restamp children if it's moving
// into trash.
@@ -2525,6 +2542,7 @@ void LLFolderBridge::folderOptionsMenu()
{
mItems.push_back(std::string("Add To Outfit"));
}
+
mItems.push_back(std::string("Replace Outfit"));
}
if (is_ensemble)
@@ -2614,15 +2632,17 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
// Not sure what the right thing is to do here.
if (!isCOFFolder() && cat && (cat->getPreferredType() != LLFolderType::FT_OUTFIT))
{
- // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.
- if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat))
- mItems.push_back(std::string("New Folder"));
- mItems.push_back(std::string("New Script"));
- mItems.push_back(std::string("New Note"));
- mItems.push_back(std::string("New Gesture"));
- mItems.push_back(std::string("New Clothes"));
- mItems.push_back(std::string("New Body Parts"));
-
+ if (!isInboxFolder()) // don't allow creation in inbox
+ {
+ // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.
+ if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat))
+ mItems.push_back(std::string("New Folder"));
+ mItems.push_back(std::string("New Script"));
+ mItems.push_back(std::string("New Note"));
+ mItems.push_back(std::string("New Gesture"));
+ mItems.push_back(std::string("New Clothes"));
+ mItems.push_back(std::string("New Body Parts"));
+ }
#if SUPPORT_ENSEMBLES
// Changing folder types is an unfinished unsupported feature
// and can lead to unexpected behavior if enabled.
@@ -3161,6 +3181,12 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
// (move the item, restamp if into trash)
else
{
+ // set up observer to select item once drag and drop from inbox is complete
+ if (gInventory.isObjectDescendentOf(inv_item->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false)))
+ {
+ set_dad_inbox_object(inv_item->getUUID());
+ }
+
LLInvFVBridge::changeItemParent(
model,
(LLViewerInventoryItem*)inv_item,
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 1e849c8812..15629c0c75 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -139,6 +139,7 @@ protected:
BOOL isAgentInventory() const; // false if lost or in the inventory library
BOOL isCOFFolder() const; // true if COF or descendent of
+ BOOL isInboxFolder() const; // true if COF or descendent of marketplace inbox
virtual BOOL isItemPermissive() const;
static void changeItemParent(LLInventoryModel* model,
LLViewerInventoryItem* item,
@@ -584,6 +585,9 @@ protected:
};
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Recent Inventory Panel related classes
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Overridden version of the Inventory-Folder-View-Bridge for Folders
class LLRecentItemsFolderBridge : public LLFolderBridge
diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp
index dee15a1efd..d6278a5fda 100644
--- a/indra/newview/llinventoryfilter.cpp
+++ b/indra/newview/llinventoryfilter.cpp
@@ -107,6 +107,32 @@ BOOL LLInventoryFilter::check(const LLFolderViewItem* item)
return passed;
}
+bool LLInventoryFilter::checkFolder(const LLFolderViewFolder* folder)
+{
+ // we're showing all folders, overriding filter
+ if (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS)
+ {
+ return true;
+ }
+
+ const LLFolderViewEventListener* listener = folder->getListener();
+ const LLUUID folder_id = listener->getUUID();
+
+ if (mFilterOps.mFilterTypes & FILTERTYPE_CATEGORY)
+ {
+ // Can only filter categories for items in your inventory
+ // (e.g. versus in-world object contents).
+ const LLViewerInventoryCategory *cat = gInventory.getCategory(folder_id);
+ if (!cat)
+ return false;
+ LLFolderType::EType cat_type = cat->getPreferredType();
+ if (cat_type != LLFolderType::FT_NONE && (1LL << cat_type & mFilterOps.mFilterCategoryTypes) == U64(0))
+ return false;
+ }
+
+ return true;
+}
+
BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) const
{
const LLFolderViewEventListener* listener = item->getListener();
@@ -137,30 +163,6 @@ BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) con
}
}
-
- ////////////////////////////////////////////////////////////////////////////////
- // FILTERTYPE_CATEGORY
- // Pass if this item is a category of the filter type, or
- // if its parent is a category of the filter type.
- if (filterTypes & FILTERTYPE_CATEGORY)
- {
- // Can only filter categories for items in your inventory
- // (e.g. versus in-world object contents).
- if (!object) return FALSE;
-
- LLUUID cat_id = object_id;
- if (listener->getInventoryType() != LLInventoryType::IT_CATEGORY)
- {
- cat_id = object->getParentUUID();
- }
- const LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id);
- if (!cat)
- return FALSE;
- if ((1LL << cat->getPreferredType() & mFilterOps.mFilterCategoryTypes) == U64(0))
- return FALSE;
- }
-
-
////////////////////////////////////////////////////////////////////////////////
// FILTERTYPE_UUID
// Pass if this item is the target UUID or if it links to the target UUID
@@ -172,7 +174,6 @@ BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) con
return FALSE;
}
-
////////////////////////////////////////////////////////////////////////////////
// FILTERTYPE_DATE
// Pass if this item is within the date range.
@@ -293,15 +294,15 @@ BOOL LLInventoryFilter::isModifiedAndClear()
return ret;
}
-void LLInventoryFilter::setFilterObjectTypes(U64 types)
+void LLInventoryFilter::updateFilterTypes(U64 types, U64& current_types)
{
- if (mFilterOps.mFilterObjectTypes != types)
+ if (current_types != types)
{
// keep current items only if no type bits getting turned off
- BOOL fewer_bits_set = (mFilterOps.mFilterObjectTypes & ~types);
- BOOL more_bits_set = (~mFilterOps.mFilterObjectTypes & types);
+ bool fewer_bits_set = (current_types & ~types) != 0;
+ bool more_bits_set = (~current_types & types) != 0;
- mFilterOps.mFilterObjectTypes = types;
+ current_types = types;
if (more_bits_set && fewer_bits_set)
{
// neither less or more restrive, both simultaneously
@@ -318,62 +319,23 @@ void LLInventoryFilter::setFilterObjectTypes(U64 types)
setModified(FILTER_MORE_RESTRICTIVE);
}
}
+}
+
+void LLInventoryFilter::setFilterObjectTypes(U64 types)
+{
+ updateFilterTypes(types, mFilterOps.mFilterObjectTypes);
mFilterOps.mFilterTypes |= FILTERTYPE_OBJECT;
}
void LLInventoryFilter::setFilterCategoryTypes(U64 types)
{
- if (mFilterOps.mFilterCategoryTypes != types)
- {
- // keep current items only if no type bits getting turned off
- BOOL fewer_bits_set = (mFilterOps.mFilterCategoryTypes & ~types);
- BOOL more_bits_set = (~mFilterOps.mFilterCategoryTypes & types);
-
- mFilterOps.mFilterCategoryTypes = types;
- if (more_bits_set && fewer_bits_set)
- {
- // neither less or more restrive, both simultaneously
- // so we need to filter from scratch
- setModified(FILTER_RESTART);
- }
- else if (more_bits_set)
- {
- // target is only one of all requested types so more type bits == less restrictive
- setModified(FILTER_LESS_RESTRICTIVE);
- }
- else if (fewer_bits_set)
- {
- setModified(FILTER_MORE_RESTRICTIVE);
- }
- }
- mFilterOps.mFilterTypes |= FILTERTYPE_OBJECT;
+ updateFilterTypes(types, mFilterOps.mFilterCategoryTypes);
+ mFilterOps.mFilterTypes |= FILTERTYPE_CATEGORY;
}
void LLInventoryFilter::setFilterWearableTypes(U64 types)
{
- if (mFilterOps.mFilterWearableTypes != types)
- {
- // keep current items only if no type bits getting turned off
- BOOL fewer_bits_set = (mFilterOps.mFilterWearableTypes & ~types);
- BOOL more_bits_set = (~mFilterOps.mFilterWearableTypes & types);
-
- mFilterOps.mFilterWearableTypes = types;
- if (more_bits_set && fewer_bits_set)
- {
- // neither less or more restrive, both simultaneously
- // so we need to filter from scratch
- setModified(FILTER_RESTART);
- }
- else if (more_bits_set)
- {
- // target is only one of all requested types so more type bits == less restrictive
- setModified(FILTER_LESS_RESTRICTIVE);
- }
- else if (fewer_bits_set)
- {
- setModified(FILTER_MORE_RESTRICTIVE);
- }
- }
+ updateFilterTypes(types, mFilterOps.mFilterWearableTypes);
mFilterOps.mFilterTypes |= FILTERTYPE_WEARABLE;
}
@@ -898,11 +860,16 @@ void LLInventoryFilter::fromLLSD(LLSD& data)
}
}
-U32 LLInventoryFilter::getFilterObjectTypes() const
+U64 LLInventoryFilter::getFilterObjectTypes() const
{
return mFilterOps.mFilterObjectTypes;
}
+U64 LLInventoryFilter::getFilterCategoryTypes() const
+{
+ return mFilterOps.mFilterCategoryTypes;
+}
+
BOOL LLInventoryFilter::hasFilterString() const
{
return mFilterSubString.size() > 0;
diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h
index 39e6f797a2..f9460822f7 100644
--- a/indra/newview/llinventoryfilter.h
+++ b/indra/newview/llinventoryfilter.h
@@ -31,6 +31,7 @@
#include "llpermissionsflags.h"
class LLFolderViewItem;
+class LLFolderViewFolder;
class LLInventoryFilter
{
@@ -81,11 +82,13 @@ public:
// + Parameters
// +-------------------------------------------------------------------+
void setFilterObjectTypes(U64 types);
- U32 getFilterObjectTypes() const;
+ U64 getFilterObjectTypes() const;
+ U64 getFilterCategoryTypes() const;
BOOL isFilterObjectTypesWith(LLInventoryType::EType t) const;
void setFilterCategoryTypes(U64 types);
void setFilterUUID(const LLUUID &object_id);
void setFilterWearableTypes(U64 types);
+ void updateFilterTypes(U64 types, U64& current_types);
void setFilterSubString(const std::string& string);
const std::string& getFilterSubString(BOOL trim = FALSE) const;
@@ -110,6 +113,7 @@ public:
// + Execution And Results
// +-------------------------------------------------------------------+
BOOL check(const LLFolderViewItem* item);
+ bool checkFolder(const LLFolderViewFolder* folder);
BOOL checkAgainstFilterType(const LLFolderViewItem* item) const;
BOOL checkAgainstPermissions(const LLFolderViewItem* item) const;
BOOL checkAgainstFilterLinks(const LLFolderViewItem* item) const;
diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h
index cfe1747fd4..2016b92666 100644
--- a/indra/newview/llinventoryfunctions.h
+++ b/indra/newview/llinventoryfunctions.h
@@ -28,9 +28,9 @@
#ifndef LL_LLINVENTORYFUNCTIONS_H
#define LL_LLINVENTORYFUNCTIONS_H
-#include "llinventorytype.h"
-#include "llfolderview.h"
-#include "llfolderviewitem.h"
+#include "llinventorymodel.h"
+#include "llinventory.h"
+#include "llwearabletype.h"
/********************************************************************************
** **
@@ -417,6 +417,24 @@ public:
/** Inventory Collector Functions
** **
*******************************************************************************/
+class LLFolderViewItem;
+class LLFolderViewFolder;
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLFolderViewFunctor
+//
+// Simple abstract base class for applying a functor to folders and
+// items in a folder view hierarchy. This is suboptimal for algorithms
+// that only work folders or only work on items, but I'll worry about
+// that later when it's determined to be too slow.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLFolderViewFunctor
+{
+public:
+ virtual ~LLFolderViewFunctor() {}
+ virtual void doFolder(LLFolderViewFolder* folder) = 0;
+ virtual void doItem(LLFolderViewItem* item) = 0;
+};
class LLInventoryState
{
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 318beafe65..21d5de9a5b 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -2589,7 +2589,7 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**)
LLInventoryState::sWearNewClothing = FALSE;
}
- if (tid == LLInventoryState::sWearNewClothingTransactionID)
+ if (tid.notNull() && tid == LLInventoryState::sWearNewClothingTransactionID)
{
count = wearable_ids.size();
for (i = 0; i < count; ++i)
diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp
index 7b1ff102e7..afaf660cb7 100644
--- a/indra/newview/llinventorymodelbackgroundfetch.cpp
+++ b/indra/newview/llinventorymodelbackgroundfetch.cpp
@@ -31,7 +31,9 @@
#include "llappviewer.h"
#include "llcallbacklist.h"
#include "llinventorypanel.h"
+#include "llinventorymodel.h"
#include "llviewercontrol.h"
+#include "llviewerinventory.h"
#include "llviewermessage.h"
#include "llviewerregion.h"
#include "llviewerwindow.h"
diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp
index 6bf19e346d..ceba4a0191 100644
--- a/indra/newview/llinventoryobserver.cpp
+++ b/indra/newview/llinventoryobserver.cpp
@@ -601,6 +601,34 @@ void LLInventoryAddedObserver::changed(U32 mask)
}
}
+void LLInventoryCategoryAddedObserver::changed(U32 mask)
+{
+ if (!(mask & LLInventoryObserver::ADD))
+ {
+ return;
+ }
+
+ const LLInventoryModel::changed_items_t& changed_ids = gInventory.getChangedIDs();
+
+ for (LLInventoryModel::changed_items_t::const_iterator cit = changed_ids.begin(); cit != changed_ids.end(); ++cit)
+ {
+ LLViewerInventoryCategory* cat = gInventory.getCategory(*cit);
+
+ if (cat)
+ {
+ mAddedCategories.push_back(cat);
+ }
+ }
+
+ if (!mAddedCategories.empty())
+ {
+ done();
+
+ mAddedCategories.clear();
+ }
+}
+
+
LLInventoryTransactionObserver::LLInventoryTransactionObserver(const LLTransactionID& transaction_id) :
mTransactionID(transaction_id)
{
diff --git a/indra/newview/llinventoryobserver.h b/indra/newview/llinventoryobserver.h
index 2d9021961e..aa1eae84d7 100644
--- a/indra/newview/llinventoryobserver.h
+++ b/indra/newview/llinventoryobserver.h
@@ -219,6 +219,28 @@ protected:
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLInventoryCategoryAddedObserver
+//
+// Base class for doing something when a new category is created in the
+// inventory.
+// It does not watch for a certain UUID, rather it acts when anything is added
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLInventoryCategoryAddedObserver : public LLInventoryObserver
+{
+public:
+
+ typedef std::vector<LLViewerInventoryCategory*> cat_vec_t;
+
+ LLInventoryCategoryAddedObserver() : mAddedCategories() {}
+ /*virtual*/ void changed(U32 mask);
+
+protected:
+ virtual void done() = 0;
+
+ cat_vec_t mAddedCategories;
+};
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLInventoryTransactionObserver
//
// Base class for doing something when an inventory transaction completes.
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index 1dcb91ad4d..702e8d5a1f 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -35,6 +35,7 @@
#include "llavataractions.h"
#include "llfloaterinventory.h"
#include "llfloaterreg.h"
+#include "llfolderview.h"
#include "llimfloater.h"
#include "llimview.h"
#include "llinventorybridge.h"
@@ -42,7 +43,6 @@
#include "llinventorymodelbackgroundfetch.h"
#include "llsidepanelinventory.h"
#include "llsidetray.h"
-#include "llscrollcontainer.h"
#include "llviewerattachmenu.h"
#include "llviewerfoldertype.h"
#include "llvoavatarself.h"
@@ -131,9 +131,8 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) :
mInventory(p.inventory),
mAllowMultiSelect(p.allow_multi_select),
mShowItemLinkOverlays(p.show_item_link_overlays),
+ mShowLoadStatus(p.show_load_status),
mViewsInitialized(false),
- mStartFolderString(p.start_folder),
- mBuildDefaultHierarchy(true),
mInvFVBridgeBuilder(NULL)
{
mInvFVBridgeBuilder = &INVENTORY_BRIDGE_BUILDER;
@@ -146,11 +145,88 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) :
mCommitCallbackRegistrar.add("Inventory.AttachObject", boost::bind(&LLInventoryPanel::attachObject, this, _2));
mCommitCallbackRegistrar.add("Inventory.BeginIMSession", boost::bind(&LLInventoryPanel::beginIMSession, this));
mCommitCallbackRegistrar.add("Inventory.Share", boost::bind(&LLAvatarActions::shareWithAvatars));
+
+}
+
+void LLInventoryPanel::buildFolderView(const LLInventoryPanel::Params& params)
+{
+ // Determine the root folder in case specified, and
+ // build the views starting with that folder.
+
+ std::string start_folder_name(params.start_folder());
+
+ const LLFolderType::EType preferred_type = LLViewerFolderType::lookupTypeFromNewCategoryName(start_folder_name);
+
+ LLUUID root_id;
+
+ if ("LIBRARY" == params.start_folder())
+ {
+ root_id = gInventory.getLibraryRootFolderID();
+ }
+ // leslie -- temporary HACK to work around sim not creating inbox and outbox with proper system folder type
+ else if (preferred_type == LLFolderType::FT_INBOX)
+ {
+ LLInventoryModel::cat_array_t* cats;
+ LLInventoryModel::item_array_t* items;
+
+ gInventory.getDirectDescendentsOf(gInventory.getRootFolderID(), cats, items);
+
+ if (cats)
+ {
+ for (LLInventoryModel::cat_array_t::const_iterator cat_it = cats->begin(); cat_it != cats->end(); ++cat_it)
+ {
+ LLInventoryCategory* cat = *cat_it;
+
+ if (cat->getName() == "Received Items")
+ {
+ root_id = cat->getUUID();
+ }
+ }
+ }
+ }
+ // leslie -- temporary HACK to work around sim not creating inbox and outbox with proper system folder type
+ else if (preferred_type == LLFolderType::FT_OUTBOX)
+ {
+ LLInventoryModel::cat_array_t* cats;
+ LLInventoryModel::item_array_t* items;
+
+ gInventory.getDirectDescendentsOf(gInventory.getRootFolderID(), cats, items);
+
+ if (cats)
+ {
+ for (LLInventoryModel::cat_array_t::const_iterator cat_it = cats->begin(); cat_it != cats->end(); ++cat_it)
+ {
+ LLInventoryCategory* cat = *cat_it;
+
+ if (cat->getName() == "Merchant Outbox")
+ {
+ root_id = cat->getUUID();
+ }
+ }
+ }
+ }
+ // leslie -- end temporary HACK
+ else
+ {
+ root_id = (preferred_type != LLFolderType::FT_NONE)
+ ? gInventory.findCategoryUUIDForType(preferred_type, false, false)
+ : LLUUID::null;
+ }
- if (mStartFolderString != "")
+ if ((root_id == LLUUID::null) && !start_folder_name.empty())
{
- mBuildDefaultHierarchy = false;
+ llwarns << "No category found that matches start_folder: " << start_folder_name << llendl;
+ root_id = LLUUID::generateNewID();
}
+
+ LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(LLAssetType::AT_CATEGORY,
+ LLAssetType::AT_CATEGORY,
+ LLInventoryType::IT_CATEGORY,
+ this,
+ NULL,
+ root_id);
+
+ mFolderRoot = createFolderView(new_listener, params.use_label_suffix());
}
void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)
@@ -159,22 +235,7 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)
mCommitCallbackRegistrar.pushScope(); // registered as a widget; need to push callback scope ourselves
- // Create root folder
- {
- LLRect folder_rect(0,
- 0,
- getRect().getWidth(),
- 0);
- LLFolderView::Params p;
- p.name = getName();
- p.title = getLabel();
- p.rect = folder_rect;
- p.parent_panel = this;
- p.tool_tip = p.name;
- p.use_label_suffix = params.use_label_suffix;
- mFolderRoot = LLUICtrlFactory::create<LLFolderView>(p);
- mFolderRoot->setAllowMultiSelect(mAllowMultiSelect);
- }
+ buildFolderView(params);
mCommitCallbackRegistrar.popScope();
@@ -184,13 +245,9 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)
{
LLRect scroller_view_rect = getRect();
scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom);
- LLScrollContainer::Params p;
- p.name("Inventory Scroller");
- p.rect(scroller_view_rect);
- p.follows.flags(FOLLOWS_ALL);
- p.reserve_scroll_corner(true);
- p.tab_stop(true);
- mScroller = LLUICtrlFactory::create<LLScrollContainer>(p);
+ LLScrollContainer::Params scroller_params(params.scroll());
+ scroller_params.rect(scroller_view_rect);
+ mScroller = LLUICtrlFactory::create<LLScrollContainer>(scroller_params);
addChild(mScroller);
mScroller->addChild(mFolderRoot);
mFolderRoot->setScrollContainer(mScroller);
@@ -206,7 +263,7 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)
// Build view of inventory if we need default full hierarchy and inventory ready,
// otherwise wait for idle callback.
- if (mBuildDefaultHierarchy && mInventory->isInventoryUsable() && !mViewsInitialized)
+ if (mInventory->isInventoryUsable() && !mViewsInitialized)
{
initializeViews();
}
@@ -222,6 +279,9 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)
}
mFolderRoot->setSortOrder(getFilter()->getSortOrder());
+ // hide inbox
+ getFilter()->setFilterCategoryTypes(getFilter()->getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_INBOX));
+
// Initialize base class params.
LLPanel::initFromParams(params);
}
@@ -264,6 +324,15 @@ LLInventoryFilter* LLInventoryPanel::getFilter()
return NULL;
}
+const LLInventoryFilter* LLInventoryPanel::getFilter() const
+{
+ if (mFolderRoot)
+ {
+ return mFolderRoot->getFilter();
+ }
+ return NULL;
+}
+
void LLInventoryPanel::setFilterTypes(U64 types, LLInventoryFilter::EFilterType filter_type)
{
if (filter_type == LLInventoryFilter::FILTERTYPE_OBJECT)
@@ -272,6 +341,17 @@ void LLInventoryPanel::setFilterTypes(U64 types, LLInventoryFilter::EFilterType
getFilter()->setFilterCategoryTypes(types);
}
+U32 LLInventoryPanel::getFilterObjectTypes() const
+{
+ return mFolderRoot->getFilterObjectTypes();
+}
+
+U32 LLInventoryPanel::getFilterPermMask() const
+{
+ return mFolderRoot->getFilterPermissions();
+}
+
+
void LLInventoryPanel::setFilterPermMask(PermissionMask filter_perm_mask)
{
getFilter()->setFilterPermissions(filter_perm_mask);
@@ -287,6 +367,12 @@ void LLInventoryPanel::setFilterSubString(const std::string& string)
getFilter()->setFilterSubString(string);
}
+const std::string LLInventoryPanel::getFilterSubString()
+{
+ return mFolderRoot->getFilterSubString();
+}
+
+
void LLInventoryPanel::setSortOrder(U32 order)
{
getFilter()->setSortOrder(order);
@@ -298,6 +384,12 @@ void LLInventoryPanel::setSortOrder(U32 order)
}
}
+U32 LLInventoryPanel::getSortOrder() const
+{
+ return mFolderRoot->getSortOrder();
+}
+
+
void LLInventoryPanel::setSinceLogoff(BOOL sl)
{
getFilter()->setDateRangeLastLogoff(sl);
@@ -379,7 +471,8 @@ void LLInventoryPanel::modelChanged(U32 mask)
{
view_item->destroyView();
}
- buildNewViews(item_id);
+ view_item = buildNewViews(item_id);
+ view_folder = dynamic_cast<LLFolderViewFolder *>(view_item);
}
//////////////////////////////
@@ -432,11 +525,10 @@ void LLInventoryPanel::modelChanged(U32 mask)
//////////////////////////////
// STRUCTURE Operation
// This item already exists in both memory and UI. It was probably reparented.
- if (model_item && view_item)
+ else if (model_item && view_item)
{
- // Don't process the item if it's hanging from the root, since its
- // model_item's parent will be NULL.
- if (view_item->getRoot() != view_item->getParent())
+ // Don't process the item if it is the root
+ if (view_item->getRoot() != view_item)
{
LLFolderViewFolder* new_parent = (LLFolderViewFolder*)mFolderRoot->getItemByID(model_item->getParentUUID());
// Item has been moved.
@@ -461,7 +553,7 @@ void LLInventoryPanel::modelChanged(U32 mask)
//////////////////////////////
// REMOVE Operation
// This item has been removed from memory, but its associated UI element still exists.
- if (!model_item && view_item)
+ else if (!model_item && view_item)
{
// Remove the item's UI.
view_item->destroyView();
@@ -470,6 +562,12 @@ void LLInventoryPanel::modelChanged(U32 mask)
}
}
+LLFolderView* LLInventoryPanel::getRootFolder()
+{
+ return mFolderRoot;
+}
+
+
// static
void LLInventoryPanel::onIdle(void *userdata)
{
@@ -488,23 +586,16 @@ void LLInventoryPanel::onIdle(void *userdata)
}
}
+const LLUUID& LLInventoryPanel::getRootFolderID() const
+{
+ return mFolderRoot->getListener()->getUUID();
+}
+
void LLInventoryPanel::initializeViews()
{
if (!gInventory.isInventoryUsable()) return;
- // Determine the root folder in case specified, and
- // build the views starting with that folder.
- const LLFolderType::EType preferred_type = LLViewerFolderType::lookupTypeFromNewCategoryName(mStartFolderString);
-
- if ("LIBRARY" == mStartFolderString)
- {
- mStartFolderID = gInventory.getLibraryRootFolderID();
- }
- else
- {
- mStartFolderID = (preferred_type != LLFolderType::FT_NONE ? gInventory.findCategoryUUIDForType(preferred_type) : LLUUID::null);
- }
- rebuildViewsFor(mStartFolderID);
+ rebuildViewsFor(getRootFolderID());
mViewsInitialized = true;
@@ -529,132 +620,155 @@ void LLInventoryPanel::initializeViews()
}
}
-void LLInventoryPanel::rebuildViewsFor(const LLUUID& id)
+LLFolderViewItem* LLInventoryPanel::rebuildViewsFor(const LLUUID& id)
{
// Destroy the old view for this ID so we can rebuild it.
LLFolderViewItem* old_view = mFolderRoot->getItemByID(id);
- if (old_view && id.notNull())
+ if (old_view)
{
old_view->destroyView();
}
- buildNewViews(id);
+ return buildNewViews(id);
}
-void LLInventoryPanel::buildNewViews(const LLUUID& id)
+LLFolderView * LLInventoryPanel::createFolderView(LLInvFVBridge * bridge, bool useLabelSuffix)
{
- LLMemType mt(LLMemType::MTYPE_INVENTORY_BUILD_NEW_VIEWS);
- LLFolderViewItem* itemp = NULL;
- LLInventoryObject* objectp = gInventory.getObject(id);
- if (objectp)
+ LLRect folder_rect(0,
+ 0,
+ getRect().getWidth(),
+ 0);
+
+ LLFolderView::Params p;
+
+ p.name = getName();
+ p.title = getLabel();
+ p.rect = folder_rect;
+ p.parent_panel = this;
+ p.tool_tip = p.name;
+ p.listener = bridge;
+ p.use_label_suffix = useLabelSuffix;
+ p.allow_multiselect = mAllowMultiSelect;
+ p.show_load_status = mShowLoadStatus;
+
+ return LLUICtrlFactory::create<LLFolderView>(p);
+}
+
+LLFolderViewFolder * LLInventoryPanel::createFolderViewFolder(LLInvFVBridge * bridge)
+{
+ LLFolderViewFolder::Params params;
+
+ params.name = bridge->getDisplayName();
+ params.icon = bridge->getIcon();
+ params.icon_open = bridge->getOpenIcon();
+
+ if (mShowItemLinkOverlays) // if false, then links show up just like normal items
{
- const LLUUID &parent_id = objectp->getParentUUID();
- LLFolderViewFolder* parent_folder = (LLFolderViewFolder*)mFolderRoot->getItemByID(parent_id);
- if (id == mStartFolderID)
- {
- parent_folder = mFolderRoot;
- }
- else if ((mStartFolderID != LLUUID::null) && (!gInventory.isObjectDescendentOf(id, mStartFolderID)))
- {
- // This item exists outside the inventory's hierarchy, so don't add it.
- return;
- }
-
- if (objectp->getType() <= LLAssetType::AT_NONE ||
- objectp->getType() >= LLAssetType::AT_COUNT)
- {
- llwarns << "LLInventoryPanel::buildNewViews called with invalid objectp->mType : "
- << ((S32) objectp->getType()) << " name " << objectp->getName() << " UUID " << objectp->getUUID()
- << llendl;
- return;
- }
-
- if ((objectp->getType() == LLAssetType::AT_CATEGORY) &&
- (objectp->getActualType() != LLAssetType::AT_LINK_FOLDER))
- {
- LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(objectp->getType(),
- objectp->getType(),
- LLInventoryType::IT_CATEGORY,
- this,
- mFolderRoot,
- objectp->getUUID());
- if (new_listener)
- {
- LLFolderViewFolder::Params params;
- params.name = new_listener->getDisplayName();
- params.icon = new_listener->getIcon();
- params.icon_open = new_listener->getOpenIcon();
- if (mShowItemLinkOverlays) // if false, then links show up just like normal items
- {
- params.icon_overlay = LLUI::getUIImage("Inv_Link");
- }
- params.root = mFolderRoot;
- params.listener = new_listener;
- params.tool_tip = params.name;
- LLFolderViewFolder* folderp = LLUICtrlFactory::create<LLFolderViewFolder>(params);
- folderp->setItemSortOrder(mFolderRoot->getSortOrder());
- itemp = folderp;
-
- // Hide the root folder, so we can show the contents of a folder flat
- // but still have the parent folder present for listener-related operations.
- if (id == mStartFolderID)
- {
- folderp->setHidden(TRUE);
- }
- const LLViewerInventoryCategory *cat = dynamic_cast<LLViewerInventoryCategory *>(objectp);
- if (cat && getIsHiddenFolderType(cat->getPreferredType()))
- {
- folderp->setHidden(TRUE);
- }
- }
- }
- else
- {
- // Build new view for item.
- LLInventoryItem* item = (LLInventoryItem*)objectp;
- LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(item->getType(),
- item->getActualType(),
- item->getInventoryType(),
- this,
- mFolderRoot,
- item->getUUID(),
- item->getFlags());
-
- if (new_listener)
- {
- LLFolderViewItem::Params params;
- params.name = new_listener->getDisplayName();
- params.icon = new_listener->getIcon();
- params.icon_open = new_listener->getOpenIcon();
- if (mShowItemLinkOverlays) // if false, then links show up just like normal items
- {
- params.icon_overlay = LLUI::getUIImage("Inv_Link");
- }
- params.creation_date = new_listener->getCreationDate();
- params.root = mFolderRoot;
- params.listener = new_listener;
- params.rect = LLRect (0, 0, 0, 0);
- params.tool_tip = params.name;
- itemp = LLUICtrlFactory::create<LLFolderViewItem> (params);
- }
- }
+ params.icon_overlay = LLUI::getUIImage("Inv_Link");
+ }
+
+ params.root = mFolderRoot;
+ params.listener = bridge;
+ params.tool_tip = params.name;
- if (itemp)
- {
- itemp->addToFolder(parent_folder, mFolderRoot);
+ return LLUICtrlFactory::create<LLFolderViewFolder>(params);
+}
- // Don't add children of hidden folders unless this is the panel's root folder.
- if (itemp->getHidden() && (id != mStartFolderID))
- {
- return;
- }
+LLFolderViewItem * LLInventoryPanel::createFolderViewItem(LLInvFVBridge * bridge)
+{
+ LLFolderViewItem::Params params;
+
+ params.name = bridge->getDisplayName();
+ params.icon = bridge->getIcon();
+ params.icon_open = bridge->getOpenIcon();
+
+ if (mShowItemLinkOverlays) // if false, then links show up just like normal items
+ {
+ params.icon_overlay = LLUI::getUIImage("Inv_Link");
+ }
+
+ params.creation_date = bridge->getCreationDate();
+ params.root = mFolderRoot;
+ params.listener = bridge;
+ params.rect = LLRect (0, 0, 0, 0);
+ params.tool_tip = params.name;
+
+ return LLUICtrlFactory::create<LLFolderViewItem>(params);
+}
+
+LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id)
+{
+ LLInventoryObject const* objectp = gInventory.getObject(id);
+ LLUUID root_id = mFolderRoot->getListener()->getUUID();
+ LLFolderViewFolder* parent_folder = NULL;
+ LLFolderViewItem* itemp = NULL;
+
+ if (id == root_id)
+ {
+ parent_folder = mFolderRoot;
+ }
+ else if (objectp)
+ {
+ const LLUUID &parent_id = objectp->getParentUUID();
+ parent_folder = (LLFolderViewFolder*)mFolderRoot->getItemByID(parent_id);
+
+ if (parent_folder)
+ {
+ if (objectp->getType() <= LLAssetType::AT_NONE ||
+ objectp->getType() >= LLAssetType::AT_COUNT)
+ {
+ llwarns << "LLInventoryPanel::buildNewViews called with invalid objectp->mType : "
+ << ((S32) objectp->getType()) << " name " << objectp->getName() << " UUID " << objectp->getUUID()
+ << llendl;
+ return NULL;
+ }
+
+ if ((objectp->getType() == LLAssetType::AT_CATEGORY) &&
+ (objectp->getActualType() != LLAssetType::AT_LINK_FOLDER))
+ {
+ LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(objectp->getType(),
+ objectp->getType(),
+ LLInventoryType::IT_CATEGORY,
+ this,
+ mFolderRoot,
+ objectp->getUUID());
+ if (new_listener)
+ {
+ LLFolderViewFolder* folderp = createFolderViewFolder(new_listener);
+ folderp->setItemSortOrder(mFolderRoot->getSortOrder());
+ itemp = folderp;
+ }
+ }
+ else
+ {
+ // Build new view for item.
+ LLInventoryItem* item = (LLInventoryItem*)objectp;
+ LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(item->getType(),
+ item->getActualType(),
+ item->getInventoryType(),
+ this,
+ mFolderRoot,
+ item->getUUID(),
+ item->getFlags());
+
+ if (new_listener)
+ {
+ itemp = createFolderViewItem(new_listener);
+ }
+ }
+
+ if (itemp)
+ {
+ itemp->addToFolder(parent_folder, mFolderRoot);
+ }
}
}
// If this is a folder, add the children of the folder and recursively add any
// child folders.
- if ((id == mStartFolderID) ||
- (objectp && objectp->getType() == LLAssetType::AT_CATEGORY))
+ if (id.isNull()
+ || (objectp
+ && objectp->getType() == LLAssetType::AT_CATEGORY))
{
LLViewerInventoryCategory::cat_array_t* categories;
LLViewerInventoryItem::item_array_t* items;
@@ -671,7 +785,7 @@ void LLInventoryPanel::buildNewViews(const LLUUID& id)
}
}
- if(items)
+ if(items && parent_folder)
{
for (LLViewerInventoryItem::item_array_t::const_iterator item_iter = items->begin();
item_iter != items->end();
@@ -683,28 +797,25 @@ void LLInventoryPanel::buildNewViews(const LLUUID& id)
}
mInventory->unlockDirectDescendentArrays(id);
}
+
+ return itemp;
}
// bit of a hack to make sure the inventory is open.
void LLInventoryPanel::openStartFolderOrMyInventory()
{
- if (mStartFolderString != "")
+ // Find My Inventory folder and open it up by name
+ for (LLView *child = mFolderRoot->getFirstChild(); child; child = mFolderRoot->findNextSibling(child))
{
- mFolderRoot->openFolder(mStartFolderString);
- }
- else
- {
- // Find My Inventory folder and open it up by name
- for (LLView *child = mFolderRoot->getFirstChild(); child; child = mFolderRoot->findNextSibling(child))
+ LLFolderViewFolder *fchild = dynamic_cast<LLFolderViewFolder*>(child);
+ if (fchild
+ && fchild->getListener()
+ && fchild->getListener()->getUUID() == gInventory.getRootFolderID())
{
- LLFolderViewFolder *fchild = dynamic_cast<LLFolderViewFolder*>(child);
- if (fchild && fchild->getListener() &&
- (fchild->getListener()->getUUID() == gInventory.getRootFolderID()))
- {
- const std::string& child_name = child->getName();
- mFolderRoot->openFolder(child_name);
- break;
- }
+ const std::string& child_name = child->getName();
+ mFolderRoot->openFolder(child_name);
+ mFolderRoot->clearSelection(); // No need to keep it selected though!
+ break;
}
}
}
@@ -723,6 +834,12 @@ void LLInventoryPanel::openSelected()
bridge->openItem();
}
+void LLInventoryPanel::unSelectAll()
+{
+ mFolderRoot->setSelection(NULL, FALSE, FALSE);
+}
+
+
BOOL LLInventoryPanel::handleHover(S32 x, S32 y, MASK mask)
{
BOOL handled = LLView::handleHover(x, y, mask);
@@ -802,7 +919,7 @@ void LLInventoryPanel::setSelection(const LLUUID& obj_id, BOOL take_keyboard_foc
mFolderRoot->setSelectionByID(obj_id, take_keyboard_focus);
}
-void LLInventoryPanel::setSelectCallback(const LLFolderView::signal_t::slot_type& cb)
+void LLInventoryPanel::setSelectCallback(const boost::function<void (const std::deque<LLFolderViewItem*>& items, BOOL user_action)>& cb)
{
if (mFolderRoot)
{
@@ -1067,15 +1184,12 @@ LLInventoryPanel* LLInventoryPanel::getActiveInventoryPanel(BOOL auto_open)
void LLInventoryPanel::addHideFolderType(LLFolderType::EType folder_type)
{
- if (!getIsHiddenFolderType(folder_type))
- {
- mHiddenFolderTypes.push_back(folder_type);
- }
+ getFilter()->setFilterCategoryTypes(getFilter()->getFilterCategoryTypes() & ~(1ULL << folder_type));
}
BOOL LLInventoryPanel::getIsHiddenFolderType(LLFolderType::EType folder_type) const
{
- return (std::find(mHiddenFolderTypes.begin(), mHiddenFolderTypes.end(), folder_type) != mHiddenFolderTypes.end());
+ return !(getFilter()->getFilterCategoryTypes() & (1ULL << folder_type));
}
@@ -1092,6 +1206,13 @@ public:
struct Params : public LLInitParam::Block<Params, LLInventoryPanel::Params>
{};
+ void initFromParams(const Params& p)
+ {
+ LLInventoryPanel::initFromParams(p);
+ // turn on inbox for recent items
+ getFilter()->setFilterCategoryTypes(getFilter()->getFilterCategoryTypes() | (1ULL << LLFolderType::FT_INBOX));
+ }
+
protected:
LLInventoryRecentItemsPanel (const Params&);
friend class LLUICtrlFactory;
diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h
index 9da9f7d8ba..a4287a438e 100644
--- a/indra/newview/llinventorypanel.h
+++ b/indra/newview/llinventorypanel.h
@@ -33,11 +33,13 @@
#include "llfloater.h"
#include "llinventory.h"
#include "llinventoryfilter.h"
-#include "llfolderview.h"
#include "llinventorymodel.h"
+#include "llscrollcontainer.h"
#include "lluictrlfactory.h"
#include <set>
+class LLFolderView;
+class LLFolderViewFolder;
class LLFolderViewItem;
class LLInventoryFilter;
class LLInventoryModel;
@@ -46,7 +48,6 @@ class LLInventoryFVBridgeBuilder;
class LLMenuBarGL;
class LLCheckBoxCtrl;
class LLSpinCtrl;
-class LLScrollContainer;
class LLTextBox;
class LLIconCtrl;
class LLSaveFolderState;
@@ -83,6 +84,8 @@ public:
Optional<Filter> filter;
Optional<std::string> start_folder;
Optional<bool> use_label_suffix;
+ Optional<bool> show_load_status;
+ Optional<LLScrollContainer::Params> scroll;
Params()
: sort_order_setting("sort_order_setting"),
@@ -91,7 +94,9 @@ public:
show_item_link_overlays("show_item_link_overlays", false),
filter("filter"),
start_folder("start_folder"),
- use_label_suffix("use_label_suffix", true)
+ use_label_suffix("use_label_suffix", true),
+ show_load_status("show_load_status"),
+ scroll("scroll")
{}
};
@@ -123,16 +128,17 @@ public:
// Call this method to set the selection.
void openAllFolders();
void setSelection(const LLUUID& obj_id, BOOL take_keyboard_focus);
- void setSelectCallback(const LLFolderView::signal_t::slot_type& cb);
+ void setSelectCallback(const boost::function<void (const std::deque<LLFolderViewItem*>& items, BOOL user_action)>& cb);
void clearSelection();
LLInventoryFilter* getFilter();
+ const LLInventoryFilter* getFilter() const;
void setFilterTypes(U64 filter, LLInventoryFilter::EFilterType = LLInventoryFilter::FILTERTYPE_OBJECT);
- U32 getFilterObjectTypes() const { return mFolderRoot->getFilterObjectTypes(); }
+ U32 getFilterObjectTypes() const;
void setFilterPermMask(PermissionMask filter_perm_mask);
- U32 getFilterPermMask() const { return mFolderRoot->getFilterPermissions(); }
+ U32 getFilterPermMask() const;
void setFilterWearableTypes(U64 filter);
void setFilterSubString(const std::string& string);
- const std::string getFilterSubString() { return mFolderRoot->getFilterSubString(); }
+ const std::string getFilterSubString();
void setSinceLogoff(BOOL sl);
void setHoursAgo(U32 hours);
BOOL getSinceLogoff();
@@ -140,10 +146,9 @@ public:
void setShowFolderState(LLInventoryFilter::EFolderShow show);
LLInventoryFilter::EFolderShow getShowFolderState();
- void setAllowMultiSelect(BOOL allow) { mFolderRoot->setAllowMultiSelect(allow); }
// This method is called when something has changed about the inventory.
void modelChanged(U32 mask);
- LLFolderView* getRootFolder() { return mFolderRoot; }
+ LLFolderView* getRootFolder();
LLScrollContainer* getScrollableContainer() { return mScroller; }
void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action);
@@ -158,7 +163,7 @@ public:
static void dumpSelectionInformation(void* user_data);
void openSelected();
- void unSelectAll() { mFolderRoot->setSelection(NULL, FALSE, FALSE); }
+ void unSelectAll();
static void onIdle(void* user_data);
@@ -175,6 +180,7 @@ protected:
LLInvPanelComplObserver* mCompletionObserver;
BOOL mAllowMultiSelect;
BOOL mShowItemLinkOverlays; // Shows link graphic over inventory item icons
+ BOOL mShowLoadStatus;
LLFolderView* mFolderRoot;
LLScrollContainer* mScroller;
@@ -198,7 +204,7 @@ public:
static const std::string INHERIT_SORT_ORDER;
void setSortOrder(U32 order);
- U32 getSortOrder() const { return mFolderRoot->getSortOrder(); }
+ U32 getSortOrder() const;
private:
std::string mSortOrderSetting;
@@ -207,29 +213,27 @@ private:
//--------------------------------------------------------------------
public:
void addHideFolderType(LLFolderType::EType folder_type);
-protected:
- BOOL getIsHiddenFolderType(LLFolderType::EType folder_type) const;
-private:
- std::vector<LLFolderType::EType> mHiddenFolderTypes;
- //--------------------------------------------------------------------
- // Initialization routines for building up the UI ("views")
- //--------------------------------------------------------------------
public:
BOOL getIsViewsInitialized() const { return mViewsInitialized; }
- const LLUUID& getStartFolderID() const { return mStartFolderID; }
- const std::string& getStartFolderString() { return mStartFolderString; }
+ const LLUUID& getRootFolderID() const;
protected:
// Builds the UI. Call this once the inventory is usable.
void initializeViews();
- void rebuildViewsFor(const LLUUID& id); // Given the id and the parent, build all of the folder views.
- virtual void buildNewViews(const LLUUID& id);
+ LLFolderViewItem* rebuildViewsFor(const LLUUID& id); // Given the id and the parent, build all of the folder views.
+
+ virtual void buildFolderView(const LLInventoryPanel::Params& params);
+ LLFolderViewItem* buildNewViews(const LLUUID& id);
+ BOOL getIsHiddenFolderType(LLFolderType::EType folder_type) const;
+
+ virtual LLFolderView* createFolderView(LLInvFVBridge * bridge, bool useLabelSuffix);
+ virtual LLFolderViewFolder* createFolderViewFolder(LLInvFVBridge * bridge);
+ virtual LLFolderViewItem* createFolderViewItem(LLInvFVBridge * bridge);
private:
BOOL mBuildDefaultHierarchy; // default inventory hierarchy should be created in postBuild()
BOOL mViewsInitialized; // Views have been generated
// UUID of category from which hierarchy should be built. Set with the
// "start_folder" xml property. Default is LLUUID::null that means total Inventory hierarchy.
- std::string mStartFolderString;
LLUUID mStartFolderID;
};
diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp
index b3ad9efeb2..03ccabc994 100644
--- a/indra/newview/llmediactrl.cpp
+++ b/indra/newview/llmediactrl.cpp
@@ -38,6 +38,7 @@
#include "llviewermedia.h"
#include "llviewertexture.h"
#include "llviewerwindow.h"
+#include "lldebugmessagebox.h"
#include "llweb.h"
#include "llrender.h"
#include "llpluginclassmedia.h"
@@ -708,6 +709,8 @@ LLPluginClassMedia* LLMediaCtrl::getMediaPlugin()
//
void LLMediaCtrl::draw()
{
+ F32 alpha = getDrawContext().mAlpha;
+
if ( gRestoreGL == 1 )
{
LLRect r = getRect();
@@ -746,21 +749,11 @@ void LLMediaCtrl::draw()
}
}
-// if(mHidingInitialLoad)
-// {
-// // If we're hiding loading, don't draw at all.
-// draw_media = false;
-// }
-
bool background_visible = isBackgroundVisible();
bool background_opaque = isBackgroundOpaque();
if(draw_media)
{
- // alpha off for this
- LLGLSUIDefault gls_ui;
- LLGLDisable gls_alphaTest( GL_ALPHA_TEST );
-
gGL.pushUIMatrix();
{
if (mIgnoreUIScale)
@@ -775,7 +768,8 @@ void LLMediaCtrl::draw()
// scale texture to fit the space using texture coords
gGL.getTexUnit(0)->bind(media_texture);
- gGL.color4fv( LLColor4::white.mV );
+ LLColor4 media_color = LLColor4::white % alpha;
+ gGL.color4fv( media_color.mV );
F32 max_u = ( F32 )media_plugin->getWidth() / ( F32 )media_plugin->getTextureWidth();
F32 max_v = ( F32 )media_plugin->getHeight() / ( F32 )media_plugin->getTextureHeight();
@@ -827,7 +821,6 @@ void LLMediaCtrl::draw()
}
// draw the browser
- gGL.setSceneBlendType(LLRender::BT_REPLACE);
gGL.begin( LLRender::QUADS );
if (! media_plugin->getTextureCoordsOpenGL())
{
@@ -860,7 +853,6 @@ void LLMediaCtrl::draw()
gGL.vertex2i( x_offset + width, y_offset );
}
gGL.end();
- gGL.setSceneBlendType(LLRender::BT_ALPHA);
}
gGL.popUIMatrix();
diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp
index 6435126fc0..10887aa53a 100644
--- a/indra/newview/lloutfitslist.cpp
+++ b/indra/newview/lloutfitslist.cpp
@@ -364,8 +364,8 @@ LLOutfitsList::~LLOutfitsList()
if (gInventory.containsObserver(mCategoriesObserver))
{
gInventory.removeObserver(mCategoriesObserver);
- delete mCategoriesObserver;
}
+ delete mCategoriesObserver;
}
BOOL LLOutfitsList::postBuild()
diff --git a/indra/newview/llpanelappearancetab.cpp b/indra/newview/llpanelappearancetab.cpp
index 9910a3a2ac..8fa8867c69 100644
--- a/indra/newview/llpanelappearancetab.cpp
+++ b/indra/newview/llpanelappearancetab.cpp
@@ -31,6 +31,7 @@
#include "llinventoryfunctions.h"
#include "llinventorymodel.h"
+#include "llviewerinventory.h"
//virtual
bool LLPanelAppearanceTab::canTakeOffSelected()
diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp
index 0cc5dcda82..e370f2f622 100644
--- a/indra/newview/llpanelimcontrolpanel.cpp
+++ b/indra/newview/llpanelimcontrolpanel.cpp
@@ -71,7 +71,7 @@ void LLPanelChatControlPanel::onChange(EStatusType status, const std::string &ch
void LLPanelChatControlPanel::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state)
{
- updateButtons(new_state >= LLVoiceChannel::STATE_CALL_STARTED);
+ updateButtons(new_state);
}
void LLPanelChatControlPanel::updateCallButton()
@@ -96,11 +96,15 @@ void LLPanelChatControlPanel::updateCallButton()
getChildView("call_btn")->setEnabled(enable_connect);
}
-void LLPanelChatControlPanel::updateButtons(bool is_call_started)
+void LLPanelChatControlPanel::updateButtons(LLVoiceChannel::EState state)
{
+ bool is_call_started = state >= LLVoiceChannel::STATE_CALL_STARTED;
getChildView("end_call_btn_panel")->setVisible( is_call_started);
- getChildView("voice_ctrls_btn_panel")->setVisible( is_call_started);
+ getChildView("voice_ctrls_btn_panel")->setVisible( is_call_started && findChild<LLView>("voice_ctrls_btn_panel"));
getChildView("call_btn_panel")->setVisible( ! is_call_started);
+
+ getChildView("volume_ctrl_panel")->setVisible(state == LLVoiceChannel::STATE_CONNECTED);
+
updateCallButton();
}
@@ -135,7 +139,7 @@ void LLPanelChatControlPanel::setSessionId(const LLUUID& session_id)
mVoiceChannelStateChangeConnection = voice_channel->setStateChangedCallback(boost::bind(&LLPanelChatControlPanel::onVoiceChannelStateChanged, this, _1, _2));
//call (either p2p, group or ad-hoc) can be already in started state
- updateButtons(voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED);
+ updateButtons(voice_channel->getState());
}
}
@@ -156,6 +160,13 @@ BOOL LLPanelIMControlPanel::postBuild()
childSetAction("share_btn", boost::bind(&LLPanelIMControlPanel::onShareButtonClicked, this));
childSetAction("teleport_btn", boost::bind(&LLPanelIMControlPanel::onTeleportButtonClicked, this));
childSetAction("pay_btn", boost::bind(&LLPanelIMControlPanel::onPayButtonClicked, this));
+
+ childSetAction("mute_btn", boost::bind(&LLPanelIMControlPanel::onClickMuteVolume, this));
+ childSetAction("block_btn", boost::bind(&LLPanelIMControlPanel::onClickBlock, this));
+ childSetAction("unblock_btn", boost::bind(&LLPanelIMControlPanel::onClickUnblock, this));
+
+ getChild<LLUICtrl>("volume_slider")->setCommitCallback(boost::bind(&LLPanelIMControlPanel::onVolumeChange, this, _2));
+
getChildView("add_friend_btn")->setEnabled(!LLAvatarActions::isFriend(getChild<LLAvatarIconCtrl>("avatar_icon")->getAvatarId()));
setFocusReceivedCallback(boost::bind(&LLPanelIMControlPanel::onFocusReceived, this));
@@ -163,6 +174,79 @@ BOOL LLPanelIMControlPanel::postBuild()
return LLPanelChatControlPanel::postBuild();
}
+void LLPanelIMControlPanel::draw()
+{
+ bool is_muted = LLMuteList::getInstance()->isMuted(mAvatarID);
+
+ getChild<LLUICtrl>("block_btn_panel")->setVisible(!is_muted);
+ getChild<LLUICtrl>("unblock_btn_panel")->setVisible(is_muted);
+
+ if (getChildView("volume_ctrl_panel")->getVisible())
+ {
+
+ bool is_muted_voice = LLMuteList::getInstance()->isMuted(mAvatarID, LLMute::flagVoiceChat);
+
+ LLUICtrl* mute_btn = getChild<LLUICtrl>("mute_btn");
+ mute_btn->setValue( is_muted_voice );
+
+ LLUICtrl* volume_slider = getChild<LLUICtrl>("volume_slider");
+ volume_slider->setEnabled( !is_muted_voice );
+
+ F32 volume;
+
+ if (is_muted_voice)
+ {
+ // it's clearer to display their volume as zero
+ volume = 0.f;
+ }
+ else
+ {
+ // actual volume
+ volume = LLVoiceClient::getInstance()->getUserVolume(mAvatarID);
+ }
+ volume_slider->setValue( (F64)volume );
+ }
+
+ LLPanelChatControlPanel::draw();
+}
+
+void LLPanelIMControlPanel::onClickMuteVolume()
+{
+ // By convention, we only display and toggle voice mutes, not all mutes
+ LLMuteList* mute_list = LLMuteList::getInstance();
+ bool is_muted = mute_list->isMuted(mAvatarID, LLMute::flagVoiceChat);
+
+ LLMute mute(mAvatarID, getChild<LLTextBox>("avatar_name")->getText(), LLMute::AGENT);
+ if (!is_muted)
+ {
+ mute_list->add(mute, LLMute::flagVoiceChat);
+ }
+ else
+ {
+ mute_list->remove(mute, LLMute::flagVoiceChat);
+ }
+}
+
+void LLPanelIMControlPanel::onClickBlock()
+{
+ LLMute mute(mAvatarID, getChild<LLTextBox>("avatar_name")->getText(), LLMute::AGENT);
+
+ LLMuteList::getInstance()->add(mute);
+}
+
+void LLPanelIMControlPanel::onClickUnblock()
+{
+ LLMute mute(mAvatarID, getChild<LLTextBox>("avatar_name")->getText(), LLMute::AGENT);
+
+ LLMuteList::getInstance()->remove(mute);
+}
+
+void LLPanelIMControlPanel::onVolumeChange(const LLSD& data)
+{
+ F32 volume = (F32)data.asReal();
+ LLVoiceClient::getInstance()->setUserVolume(mAvatarID, volume);
+}
+
void LLPanelIMControlPanel::onTeleportButtonClicked()
{
LLAvatarActions::offerTeleport(mAvatarID);
@@ -262,6 +346,9 @@ void LLPanelIMControlPanel::onNameCache(const LLUUID& id, const std::string& ful
std::string avatar_name = full_name;
getChild<LLTextBox>("avatar_name")->setValue(avatar_name);
getChild<LLTextBox>("avatar_name")->setToolTip(avatar_name);
+
+ bool is_linden = LLStringUtil::endsWith(full_name, " Linden");
+ getChild<LLUICtrl>("mute_btn")->setEnabled( !is_linden);
}
}
diff --git a/indra/newview/llpanelimcontrolpanel.h b/indra/newview/llpanelimcontrolpanel.h
index 3bbe24ecb9..bba847b5d4 100644
--- a/indra/newview/llpanelimcontrolpanel.h
+++ b/indra/newview/llpanelimcontrolpanel.h
@@ -54,7 +54,7 @@ public:
virtual void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state);
- void updateButtons(bool is_call_started);
+ void updateButtons(LLVoiceChannel::EState state);
// Enables/disables call button depending on voice availability
void updateCallButton();
@@ -94,6 +94,12 @@ private:
void onPayButtonClicked();
void onFocusReceived();
+ void onClickMuteVolume();
+ void onClickBlock();
+ void onClickUnblock();
+ /*virtual*/ void draw();
+ void onVolumeChange(const LLSD& data);
+
LLUUID mAvatarID;
};
diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index c2729fa19b..a9cc247d1b 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -46,6 +46,7 @@
#include "llfolderviewitem.h"
#include "llinventorymodelbackgroundfetch.h"
#include "llinventorypanel.h"
+#include "llinventoryfunctions.h"
#include "lllandmarkactions.h"
#include "llmenubutton.h"
#include "llplacesinventorybridge.h"
@@ -529,7 +530,7 @@ void LLLandmarksPanel::setParcelID(const LLUUID& parcel_id)
// virtual
void LLLandmarksPanel::setErrorStatus(U32 status, const std::string& reason)
{
- llerrs<< "Can't handle remote parcel request."<< " Http Status: "<< status << ". Reason : "<< reason<<llendl;
+ llwarns << "Can't handle remote parcel request."<< " Http Status: "<< status << ". Reason : "<< reason<<llendl;
}
@@ -645,7 +646,7 @@ void LLLandmarksPanel::onAccordionExpandedCollapsed(const LLSD& param, LLPlacesI
// Start background fetch, mostly for My Inventory and Library
if (expanded)
{
- const LLUUID &cat_id = inventory_list->getStartFolderID();
+ const LLUUID &cat_id = inventory_list->getRootFolderID();
// Just because the category itself has been fetched, doesn't mean its child folders have.
/*
if (!gInventory.isCategoryComplete(cat_id))
@@ -1414,7 +1415,7 @@ static void filter_list(LLPlacesInventoryPanel* inventory_list, const std::strin
static bool category_has_descendents(LLPlacesInventoryPanel* inventory_list)
{
- LLViewerInventoryCategory* category = gInventory.getCategory(inventory_list->getStartFolderID());
+ LLViewerInventoryCategory* category = gInventory.getCategory(inventory_list->getRootFolderID());
if (category)
{
return category->getDescendentCount() > 0;
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index bc4998dd0c..1920cc2940 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -1,6 +1,6 @@
/**
- * @file llsidepanelmaininventory.cpp
- * @brief Implementation of llsidepanelmaininventory.
+ * @file llpanelmaininventory.cpp
+ * @brief Implementation of llpanelmaininventory.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
@@ -95,8 +95,8 @@ private:
/// LLPanelMainInventory
///----------------------------------------------------------------------------
-LLPanelMainInventory::LLPanelMainInventory()
- : LLPanel(),
+LLPanelMainInventory::LLPanelMainInventory(const LLPanel::Params& p)
+ : LLPanel(p),
mActivePanel(NULL),
mSavedFolderState(NULL),
mFilterText(""),
@@ -193,6 +193,9 @@ BOOL LLPanelMainInventory::postBuild()
mMenuAdd->getChild<LLMenuItemGL>("Upload Animation")->setLabelArg("[COST]", upload_cost);
mMenuAdd->getChild<LLMenuItemGL>("Bulk Upload")->setLabelArg("[COST]", upload_cost);
+ // Trigger callback for focus received so we can deselect items in inbox/outbox
+ LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLPanelMainInventory::onFocusReceived, this));
+
return TRUE;
}
@@ -572,6 +575,27 @@ void LLPanelMainInventory::updateItemcountText()
getChild<LLUICtrl>("ItemcountText")->setValue(text);
}
+void LLPanelMainInventory::onFocusReceived()
+{
+ LLSidepanelInventory * sidepanel_inventory = LLSideTray::getInstance()->getPanel<LLSidepanelInventory>("sidepanel_inventory");
+
+ LLInventoryPanel * inbox_panel = sidepanel_inventory->findChild<LLInventoryPanel>("inventory_inbox");
+
+ if (inbox_panel)
+ {
+ inbox_panel->clearSelection();
+ }
+
+ LLInventoryPanel * outbox_panel = sidepanel_inventory->findChild<LLInventoryPanel>("inventory_outbox");
+
+ if (outbox_panel)
+ {
+ outbox_panel->clearSelection();
+ }
+
+ sidepanel_inventory->updateVerbs();
+}
+
void LLPanelMainInventory::setFilterTextFromFilter()
{
mFilterText = mActivePanel->getFilter()->getFilterText();
diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h
index 2b2ee1c0c9..899931aa89 100644
--- a/indra/newview/llpanelmaininventory.h
+++ b/indra/newview/llpanelmaininventory.h
@@ -57,7 +57,7 @@ class LLPanelMainInventory : public LLPanel, LLInventoryObserver
public:
friend class LLFloaterInventoryFinder;
- LLPanelMainInventory();
+ LLPanelMainInventory(const LLPanel::Params& p = getDefaultParams());
~LLPanelMainInventory();
BOOL postBuild();
@@ -114,6 +114,8 @@ protected:
bool isSaveTextureEnabled(const LLSD& userdata);
void updateItemcountText();
+ void onFocusReceived();
+
private:
LLFloaterInventoryFinder* getFinder();
diff --git a/indra/newview/llpanelmarketplaceinbox.cpp b/indra/newview/llpanelmarketplaceinbox.cpp
new file mode 100644
index 0000000000..af74f8f261
--- /dev/null
+++ b/indra/newview/llpanelmarketplaceinbox.cpp
@@ -0,0 +1,248 @@
+/**
+ * @file llpanelmarketplaceinbox.cpp
+ * @brief Panel for marketplace inbox
+ *
+* $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpanelmarketplaceinbox.h"
+
+#include "llappviewer.h"
+#include "llbutton.h"
+#include "llinventorypanel.h"
+#include "llfolderview.h"
+#include "llsidepanelinventory.h"
+
+
+#define SUPPORTING_FRESH_ITEM_COUNT 0
+
+
+static LLRegisterPanelClassWrapper<LLPanelMarketplaceInbox> t_panel_marketplace_inbox("panel_marketplace_inbox");
+
+const LLPanelMarketplaceInbox::Params& LLPanelMarketplaceInbox::getDefaultParams()
+{
+ return LLUICtrlFactory::getDefaultParams<LLPanelMarketplaceInbox>();
+}
+
+// protected
+LLPanelMarketplaceInbox::LLPanelMarketplaceInbox(const Params& p)
+ : LLPanel(p)
+ , mInventoryPanel(NULL)
+{
+}
+
+LLPanelMarketplaceInbox::~LLPanelMarketplaceInbox()
+{
+}
+
+// virtual
+BOOL LLPanelMarketplaceInbox::postBuild()
+{
+ LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLPanelMarketplaceInbox::handleLoginComplete, this));
+
+ LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLPanelMarketplaceInbox::onFocusReceived, this));
+
+ return TRUE;
+}
+
+void LLPanelMarketplaceInbox::onSelectionChange()
+{
+ LLSidepanelInventory* sidepanel_inventory = dynamic_cast<LLSidepanelInventory*>(LLSideTray::getInstance()->getPanel("sidepanel_inventory"));
+
+ sidepanel_inventory->updateVerbs();
+}
+
+
+void LLPanelMarketplaceInbox::handleLoginComplete()
+{
+ // Set us up as the class to drive the badge value for the sidebar_inventory button
+ LLSideTray::getInstance()->setTabButtonBadgeDriver("sidebar_inventory", this);
+}
+
+void LLPanelMarketplaceInbox::setupInventoryPanel()
+{
+ LLView * inbox_inventory_placeholder = getChild<LLView>("inbox_inventory_placeholder");
+ LLView * inbox_inventory_parent = inbox_inventory_placeholder->getParent();
+
+ mInventoryPanel =
+ LLUICtrlFactory::createFromFile<LLInventoryPanel>("panel_inbox_inventory.xml",
+ inbox_inventory_parent,
+ LLInventoryPanel::child_registry_t::instance());
+
+ // Reshape the inventory to the proper size
+ LLRect inventory_placeholder_rect = inbox_inventory_placeholder->getRect();
+ mInventoryPanel->setShape(inventory_placeholder_rect);
+
+ // Set the sort order newest to oldest, and a selection change callback
+ mInventoryPanel->setSortOrder(LLInventoryFilter::SO_DATE);
+ mInventoryPanel->setSelectCallback(boost::bind(&LLPanelMarketplaceInbox::onSelectionChange, this));
+
+ // Set up the note to display when the inbox is empty
+ mInventoryPanel->getFilter()->setEmptyLookupMessage("InventoryInboxNoItems");
+
+ // Hide the placeholder text
+ inbox_inventory_placeholder->setVisible(FALSE);
+}
+
+void LLPanelMarketplaceInbox::onFocusReceived()
+{
+ LLSidepanelInventory * sidepanel_inventory = LLSideTray::getInstance()->getPanel<LLSidepanelInventory>("sidepanel_inventory");
+
+ if (sidepanel_inventory)
+ {
+ LLInventoryPanel * inv_panel = sidepanel_inventory->getActivePanel();
+
+ if (inv_panel)
+ {
+ inv_panel->clearSelection();
+ }
+
+ LLInventoryPanel * outbox_panel = sidepanel_inventory->findChild<LLInventoryPanel>("inventory_outbox");
+
+ if (outbox_panel)
+ {
+ outbox_panel->clearSelection();
+ }
+
+ sidepanel_inventory->updateVerbs();
+ }
+}
+
+BOOL LLPanelMarketplaceInbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, std::string& tooltip_msg)
+{
+ *accept = ACCEPT_NO;
+ return TRUE;
+}
+
+U32 LLPanelMarketplaceInbox::getFreshItemCount() const
+{
+#if SUPPORTING_FRESH_ITEM_COUNT
+
+ //
+ // NOTE: When turning this on, be sure to test the no inbox/outbox case because this code probably
+ // will return "2" for the Inventory and LIBRARY top-levels when that happens.
+ //
+
+ U32 fresh_item_count = 0;
+
+ if (mInventoryPanel)
+ {
+ const LLFolderViewFolder * inbox_folder = mInventoryPanel->getRootFolder();
+
+ if (inbox_folder)
+ {
+ LLFolderViewFolder::folders_t::const_iterator folders_it = inbox_folder->getFoldersBegin();
+ LLFolderViewFolder::folders_t::const_iterator folders_end = inbox_folder->getFoldersEnd();
+
+ for (; folders_it != folders_end; ++folders_it)
+ {
+ const LLFolderViewFolder * folder = *folders_it;
+
+ // TODO: Replace this check with new "fresh" flag
+ if (folder->getCreationDate() > 1500)
+ {
+ fresh_item_count++;
+ }
+ }
+ }
+ }
+
+ return fresh_item_count;
+#else
+ return getTotalItemCount();
+#endif
+}
+
+U32 LLPanelMarketplaceInbox::getTotalItemCount() const
+{
+ U32 item_count = 0;
+
+ if (mInventoryPanel)
+ {
+ const LLFolderViewFolder * inbox_folder = mInventoryPanel->getRootFolder();
+
+ if (inbox_folder)
+ {
+ item_count += inbox_folder->getFoldersCount();
+ }
+ }
+
+ return item_count;
+}
+
+std::string LLPanelMarketplaceInbox::getBadgeString() const
+{
+ std::string item_count_str("");
+
+ // If the inbox is visible, and the side panel is collapsed or expanded and not the inventory panel
+ if (getParent()->getVisible() &&
+ (LLSideTray::getInstance()->getCollapsed() || !LLSideTray::getInstance()->isPanelActive("sidepanel_inventory")))
+ {
+ U32 item_count = getFreshItemCount();
+
+ if (item_count)
+ {
+ item_count_str = llformat("%d", item_count);
+ }
+ }
+
+ return item_count_str;
+}
+
+void LLPanelMarketplaceInbox::draw()
+{
+ U32 item_count = getTotalItemCount();
+
+ LLView * fresh_new_count_view = getChildView("inbox_fresh_new_count");
+
+ if (item_count > 0)
+ {
+ std::string item_count_str = llformat("%d", item_count);
+
+ LLStringUtil::format_map_t args;
+ args["[NUM]"] = item_count_str;
+ getChild<LLButton>("inbox_btn")->setLabel(getString("InboxLabelWithArg", args));
+
+#if SUPPORTING_FRESH_ITEM_COUNT
+ // set green text to fresh item count
+ U32 fresh_item_count = getFreshItemCount();
+ fresh_new_count_view->setVisible((fresh_item_count > 0));
+
+ if (fresh_item_count > 0)
+ {
+ getChild<LLUICtrl>("inbox_fresh_new_count")->setTextArg("[NUM]", llformat("%d", fresh_item_count));
+ }
+#else
+ fresh_new_count_view->setVisible(FALSE);
+#endif
+ }
+ else
+ {
+ getChild<LLButton>("inbox_btn")->setLabel(getString("InboxLabelNoArg"));
+
+ fresh_new_count_view->setVisible(FALSE);
+ }
+
+ LLPanel::draw();
+}
diff --git a/indra/newview/llpanelmarketplaceinbox.h b/indra/newview/llpanelmarketplaceinbox.h
new file mode 100644
index 0000000000..4ecea29304
--- /dev/null
+++ b/indra/newview/llpanelmarketplaceinbox.h
@@ -0,0 +1,78 @@
+/**
+ * @file llpanelmarketplaceinbox.h
+ * @brief Panel for marketplace inbox
+ *
+* $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELMARKETPLACEINBOX_H
+#define LL_LLPANELMARKETPLACEINBOX_H
+
+#include "llpanel.h"
+#include "llsidetray.h"
+
+class LLInventoryPanel;
+
+class LLPanelMarketplaceInbox : public LLPanel, public LLSideTrayTabBadgeDriver
+{
+public:
+
+ struct Params : public LLInitParam::Block<Params, LLPanel::Params>
+ {
+ Params() {}
+ };
+
+ LOG_CLASS(LLPanelMarketplaceInbox);
+
+ // RN: for some reason you can't just use LLUICtrlFactory::getDefaultParams as a default argument in VC8
+ static const LLPanelMarketplaceInbox::Params& getDefaultParams();
+
+ LLPanelMarketplaceInbox(const Params& p = getDefaultParams());
+ ~LLPanelMarketplaceInbox();
+
+ /*virtual*/ BOOL postBuild();
+
+ /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, std::string& tooltip_msg);
+
+ /*virtual*/ void draw();
+
+ void setupInventoryPanel();
+
+ U32 getFreshItemCount() const;
+ U32 getTotalItemCount() const;
+
+ std::string getBadgeString() const;
+
+private:
+ void handleLoginComplete();
+
+ void onSelectionChange();
+
+ void onFocusReceived();
+
+private:
+ LLInventoryPanel* mInventoryPanel;
+};
+
+
+#endif //LL_LLPANELMARKETPLACEINBOX_H
+
diff --git a/indra/newview/llpanelmarketplaceinboxinventory.cpp b/indra/newview/llpanelmarketplaceinboxinventory.cpp
new file mode 100644
index 0000000000..b644f0e5cb
--- /dev/null
+++ b/indra/newview/llpanelmarketplaceinboxinventory.cpp
@@ -0,0 +1,167 @@
+/**
+ * @file llpanelmarketplaceinboxinventory.cpp
+ * @brief LLInboxInventoryPanel class definition
+ *
+ * $LicenseInfo:firstyear=2009&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpanelmarketplaceinboxinventory.h"
+
+#include "llfolderview.h"
+#include "llfoldervieweventlistener.h"
+#include "llinventorybridge.h"
+#include "llinventoryfunctions.h"
+#include "llpanellandmarks.h"
+#include "llplacesinventorybridge.h"
+#include "llviewerfoldertype.h"
+
+
+//
+// statics
+//
+
+static LLDefaultChildRegistry::Register<LLInboxInventoryPanel> r1("inbox_inventory_panel");
+static LLDefaultChildRegistry::Register<LLInboxFolderViewFolder> r2("inbox_folder_view_folder");
+
+
+//
+// LLInboxInventoryPanel Implementation
+//
+
+LLInboxInventoryPanel::LLInboxInventoryPanel(const LLInboxInventoryPanel::Params& p)
+ : LLInventoryPanel(p)
+{
+}
+
+LLInboxInventoryPanel::~LLInboxInventoryPanel()
+{
+}
+
+// virtual
+void LLInboxInventoryPanel::buildFolderView(const LLInventoryPanel::Params& params)
+{
+ // Determine the root folder in case specified, and
+ // build the views starting with that folder.
+
+ LLUUID root_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false);
+
+ // leslie -- temporary HACK to work around sim not creating inbox and outbox with proper system folder type
+ if (root_id.isNull())
+ {
+ std::string start_folder_name(params.start_folder());
+
+ LLInventoryModel::cat_array_t* cats;
+ LLInventoryModel::item_array_t* items;
+
+ gInventory.getDirectDescendentsOf(gInventory.getRootFolderID(), cats, items);
+
+ if (cats)
+ {
+ for (LLInventoryModel::cat_array_t::const_iterator cat_it = cats->begin(); cat_it != cats->end(); ++cat_it)
+ {
+ LLInventoryCategory* cat = *cat_it;
+
+ if (cat->getName() == start_folder_name)
+ {
+ root_id = cat->getUUID();
+ break;
+ }
+ }
+ }
+
+ if (root_id == LLUUID::null)
+ {
+ llwarns << "No category found that matches inbox inventory panel start_folder: " << start_folder_name << llendl;
+ }
+ }
+ // leslie -- end temporary HACK
+
+ if (root_id == LLUUID::null)
+ {
+ llwarns << "Inbox inventory panel has no root folder!" << llendl;
+ root_id = LLUUID::generateNewID();
+ }
+
+ LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(LLAssetType::AT_CATEGORY,
+ LLAssetType::AT_CATEGORY,
+ LLInventoryType::IT_CATEGORY,
+ this,
+ NULL,
+ root_id);
+
+ mFolderRoot = createFolderView(new_listener, params.use_label_suffix());
+}
+
+LLFolderViewFolder * LLInboxInventoryPanel::createFolderViewFolder(LLInvFVBridge * bridge)
+{
+ LLInboxFolderViewFolder::Params params;
+
+ params.name = bridge->getDisplayName();
+ params.icon = bridge->getIcon();
+ params.icon_open = bridge->getOpenIcon();
+
+ if (mShowItemLinkOverlays) // if false, then links show up just like normal items
+ {
+ params.icon_overlay = LLUI::getUIImage("Inv_Link");
+ }
+
+ params.root = mFolderRoot;
+ params.listener = bridge;
+ params.tool_tip = params.name;
+
+ return LLUICtrlFactory::create<LLInboxFolderViewFolder>(params);
+}
+
+
+//
+// LLInboxFolderViewFolder Implementation
+//
+
+LLInboxFolderViewFolder::LLInboxFolderViewFolder(const Params& p)
+ : LLFolderViewFolder(p)
+ , LLBadgeOwner(getHandle())
+ , mFresh(false)
+{
+ initBadgeParams(p.new_badge());
+}
+
+LLInboxFolderViewFolder::~LLInboxFolderViewFolder()
+{
+}
+
+// virtual
+void LLInboxFolderViewFolder::draw()
+{
+ if (!badgeHasParent())
+ {
+ addBadgeToParentPanel();
+ }
+
+ setBadgeVisibility(mFresh);
+
+ LLFolderViewFolder::draw();
+}
+
+
+// eof
diff --git a/indra/newview/llpanelmarketplaceinboxinventory.h b/indra/newview/llpanelmarketplaceinboxinventory.h
new file mode 100644
index 0000000000..8f198c41c1
--- /dev/null
+++ b/indra/newview/llpanelmarketplaceinboxinventory.h
@@ -0,0 +1,77 @@
+/**
+ * @file llpanelmarketplaceinboxinventory.h
+ * @brief LLInboxInventoryPanel class declaration
+ *
+ * $LicenseInfo:firstyear=2009&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_INBOXINVENTORYPANEL_H
+#define LL_INBOXINVENTORYPANEL_H
+
+
+#include "llbadgeowner.h"
+#include "llinventorypanel.h"
+#include "llfolderviewitem.h"
+
+class LLInboxInventoryPanel : public LLInventoryPanel
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLInventoryPanel::Params>
+ {
+ Params() {}
+ };
+
+ LLInboxInventoryPanel(const Params& p);
+ ~LLInboxInventoryPanel();
+
+ // virtual
+ void buildFolderView(const LLInventoryPanel::Params& params);
+
+ // virtual
+ class LLFolderViewFolder* createFolderViewFolder(LLInvFVBridge * bridge);
+};
+
+
+class LLInboxFolderViewFolder : public LLFolderViewFolder, public LLBadgeOwner
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLFolderViewFolder::Params>
+ {
+ Optional<LLBadge::Params> new_badge;
+
+ Params()
+ : new_badge("new_badge")
+ {
+ }
+ };
+
+ LLInboxFolderViewFolder(const Params& p);
+ ~LLInboxFolderViewFolder();
+
+ void draw();
+
+protected:
+ bool mFresh;
+};
+
+
+#endif //LL_INBOXINVENTORYPANEL_H
diff --git a/indra/newview/llpanelmarketplaceoutbox.cpp b/indra/newview/llpanelmarketplaceoutbox.cpp
new file mode 100644
index 0000000000..74d0de3b30
--- /dev/null
+++ b/indra/newview/llpanelmarketplaceoutbox.cpp
@@ -0,0 +1,209 @@
+/**
+ * @file llpanelmarketplaceoutbox.cpp
+ * @brief Panel for marketplace outbox
+ *
+* $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpanelmarketplaceoutbox.h"
+
+#include "llappviewer.h"
+#include "llbutton.h"
+#include "llcoros.h"
+#include "lleventcoro.h"
+#include "llinventorypanel.h"
+#include "llloadingindicator.h"
+#include "llpanelmarketplaceinbox.h"
+#include "llsidepanelinventory.h"
+#include "llsidetray.h"
+#include "lltimer.h"
+
+
+static LLRegisterPanelClassWrapper<LLPanelMarketplaceOutbox> t_panel_marketplace_outbox("panel_marketplace_outbox");
+
+const LLPanelMarketplaceOutbox::Params& LLPanelMarketplaceOutbox::getDefaultParams()
+{
+ return LLUICtrlFactory::getDefaultParams<LLPanelMarketplaceOutbox>();
+}
+
+// protected
+LLPanelMarketplaceOutbox::LLPanelMarketplaceOutbox(const Params& p)
+ : LLPanel(p)
+ , mInventoryPanel(NULL)
+ , mSyncButton(NULL)
+ , mSyncIndicator(NULL)
+ , mSyncInProgress(false)
+{
+}
+
+LLPanelMarketplaceOutbox::~LLPanelMarketplaceOutbox()
+{
+}
+
+// virtual
+BOOL LLPanelMarketplaceOutbox::postBuild()
+{
+ LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLPanelMarketplaceOutbox::handleLoginComplete, this));
+
+ LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLPanelMarketplaceOutbox::onFocusReceived, this));
+
+ return TRUE;
+}
+
+void LLPanelMarketplaceOutbox::handleLoginComplete()
+{
+ mSyncButton = getChild<LLButton>("outbox_sync_btn");
+ mSyncButton->setCommitCallback(boost::bind(&LLPanelMarketplaceOutbox::onSyncButtonClicked, this));
+ mSyncButton->setEnabled(!isOutboxEmpty());
+
+ mSyncIndicator = getChild<LLLoadingIndicator>("outbox_sync_indicator");
+}
+
+void LLPanelMarketplaceOutbox::onFocusReceived()
+{
+ LLSidepanelInventory * sidepanel_inventory = LLSideTray::getInstance()->getPanel<LLSidepanelInventory>("sidepanel_inventory");
+
+ if (sidepanel_inventory)
+ {
+ LLInventoryPanel * inv_panel = sidepanel_inventory->getActivePanel();
+
+ if (inv_panel)
+ {
+ inv_panel->clearSelection();
+ }
+
+ LLInventoryPanel * inbox_panel = sidepanel_inventory->findChild<LLInventoryPanel>("inventory_inbox");
+
+ if (inbox_panel)
+ {
+ inbox_panel->clearSelection();
+ }
+
+ sidepanel_inventory->updateVerbs();
+ }
+}
+
+void LLPanelMarketplaceOutbox::onSelectionChange()
+{
+ LLSidepanelInventory* sidepanel_inventory = dynamic_cast<LLSidepanelInventory*>(LLSideTray::getInstance()->getPanel("sidepanel_inventory"));
+
+ sidepanel_inventory->updateVerbs();
+}
+
+void LLPanelMarketplaceOutbox::setupInventoryPanel()
+{
+ LLView * outbox_inventory_placeholder = getChild<LLView>("outbox_inventory_placeholder");
+ LLView * outbox_inventory_parent = outbox_inventory_placeholder->getParent();
+
+ mInventoryPanel =
+ LLUICtrlFactory::createFromFile<LLInventoryPanel>("panel_outbox_inventory.xml",
+ outbox_inventory_parent,
+ LLInventoryPanel::child_registry_t::instance());
+
+ // Reshape the inventory to the proper size
+ LLRect inventory_placeholder_rect = outbox_inventory_placeholder->getRect();
+ mInventoryPanel->setShape(inventory_placeholder_rect);
+
+ // Set the sort order newest to oldest, and a selection change callback
+ mInventoryPanel->setSortOrder(LLInventoryFilter::SO_DATE);
+ mInventoryPanel->setSelectCallback(boost::bind(&LLPanelMarketplaceOutbox::onSelectionChange, this));
+
+ // Set up the note to display when the outbox is empty
+ mInventoryPanel->getFilter()->setEmptyLookupMessage("InventoryOutboxNoItems");
+
+ // Hide the placeholder text
+ outbox_inventory_placeholder->setVisible(FALSE);
+}
+
+bool LLPanelMarketplaceOutbox::isOutboxEmpty() const
+{
+ // TODO: Check for contents of outbox
+
+ return false;
+}
+
+bool LLPanelMarketplaceOutbox::isSyncInProgress() const
+{
+ return mSyncInProgress;
+}
+
+
+std::string gTimeDelayDebugFunc = "";
+
+void timeDelay(LLCoros::self& self, LLPanelMarketplaceOutbox* outboxPanel)
+{
+ waitForEventOn(self, "mainloop");
+
+ LLTimer delayTimer;
+ delayTimer.reset();
+ delayTimer.setTimerExpirySec(5.0f);
+
+ while (!delayTimer.hasExpired())
+ {
+ waitForEventOn(self, "mainloop");
+ }
+
+ outboxPanel->onSyncComplete();
+
+ gTimeDelayDebugFunc = "";
+}
+
+void LLPanelMarketplaceOutbox::onSyncButtonClicked()
+{
+ // TODO: Actually trigger sync to marketplace
+
+ mSyncInProgress = true;
+ updateSyncButtonStatus();
+
+ // Set a timer (for testing only)
+
+ gTimeDelayDebugFunc = LLCoros::instance().launch("LLPanelMarketplaceOutbox timeDelay", boost::bind(&timeDelay, _1, this));
+}
+
+void LLPanelMarketplaceOutbox::onSyncComplete()
+{
+ mSyncInProgress = false;
+
+ updateSyncButtonStatus();
+}
+
+void LLPanelMarketplaceOutbox::updateSyncButtonStatus()
+{
+ if (isSyncInProgress())
+ {
+ mSyncButton->setVisible(false);
+
+ mSyncIndicator->setVisible(true);
+ mSyncIndicator->reset();
+ mSyncIndicator->start();
+ }
+ else
+ {
+ mSyncIndicator->stop();
+ mSyncIndicator->setVisible(false);
+
+ mSyncButton->setVisible(true);
+ mSyncButton->setEnabled(!isOutboxEmpty());
+ }
+}
diff --git a/indra/newview/llpanelmarketplaceoutbox.h b/indra/newview/llpanelmarketplaceoutbox.h
new file mode 100644
index 0000000000..1b502127ef
--- /dev/null
+++ b/indra/newview/llpanelmarketplaceoutbox.h
@@ -0,0 +1,82 @@
+/**
+ * @file llpanelmarketplaceoutbox.h
+ * @brief Panel for marketplace outbox
+ *
+* $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELMARKETPLACEOUTBOX_H
+#define LL_LLPANELMARKETPLACEOUTBOX_H
+
+#include "llpanel.h"
+
+
+class LLButton;
+class LLInventoryPanel;
+class LLLoadingIndicator;
+
+
+class LLPanelMarketplaceOutbox : public LLPanel
+{
+public:
+
+ struct Params : public LLInitParam::Block<Params, LLPanel::Params>
+ {
+ Params() {}
+ };
+
+ LOG_CLASS(LLPanelMarketplaceOutbox);
+
+ // RN: for some reason you can't just use LLUICtrlFactory::getDefaultParams as a default argument in VC8
+ static const LLPanelMarketplaceOutbox::Params& getDefaultParams();
+
+ LLPanelMarketplaceOutbox(const Params& p = getDefaultParams());
+ ~LLPanelMarketplaceOutbox();
+
+ /*virtual*/ BOOL postBuild();
+
+ void setupInventoryPanel();
+
+ bool isOutboxEmpty() const;
+ bool isSyncInProgress() const;
+
+ void onSyncComplete();
+
+protected:
+ void onSyncButtonClicked();
+ void updateSyncButtonStatus();
+
+ void handleLoginComplete();
+ void onFocusReceived();
+ void onSelectionChange();
+
+private:
+ LLInventoryPanel * mInventoryPanel;
+
+ LLButton * mSyncButton;
+ LLLoadingIndicator * mSyncIndicator;
+ bool mSyncInProgress;
+};
+
+
+#endif //LL_LLPANELMARKETPLACEOUTBOX_H
+
diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp
index bfe6cab52f..e3b61f695a 100644
--- a/indra/newview/llpanelobjectinventory.cpp
+++ b/indra/newview/llpanelobjectinventory.cpp
@@ -44,6 +44,7 @@
#include "llcallbacklist.h"
#include "llbuycurrencyhtml.h"
#include "llfloaterreg.h"
+#include "llfolderview.h"
#include "llinventorybridge.h"
#include "llinventorydefines.h"
#include "llinventoryfilter.h"
@@ -58,8 +59,10 @@
#include "llselectmgr.h"
#include "llsidetray.h"
#include "llstatusbar.h"
+#include "lltooldraganddrop.h"
#include "lltrans.h"
#include "llviewerassettype.h"
+#include "llviewerinventory.h"
#include "llviewerregion.h"
#include "llviewerobjectlist.h"
#include "llviewermessage.h"
@@ -761,7 +764,7 @@ void LLTaskCategoryBridge::openItem()
BOOL LLTaskCategoryBridge::startDrag(EDragAndDropType* type, LLUUID* id) const
{
//llinfos << "LLTaskInvFVBridge::startDrag()" << llendl;
- if(mPanel)
+ if(mPanel && mUUID.notNull())
{
LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
if(object)
@@ -1349,79 +1352,81 @@ LLTaskInvFVBridge* LLTaskInvFVBridge::createObjectBridge(LLPanelObjectInventory*
LLTaskInvFVBridge* new_bridge = NULL;
const LLInventoryItem* item = dynamic_cast<LLInventoryItem*>(object);
const U32 itemflags = ( NULL == item ? 0 : item->getFlags() );
- LLAssetType::EType type = object->getType();
+ LLAssetType::EType type = object ? object->getType() : LLAssetType::AT_CATEGORY;
+ LLUUID object_id = object ? object->getUUID() : LLUUID::null;
+ std::string object_name = object ? object->getName() : std::string();
switch(type)
{
case LLAssetType::AT_TEXTURE:
new_bridge = new LLTaskTextureBridge(panel,
- object->getUUID(),
- object->getName());
+ object_id,
+ object_name);
break;
case LLAssetType::AT_SOUND:
new_bridge = new LLTaskSoundBridge(panel,
- object->getUUID(),
- object->getName());
+ object_id,
+ object_name);
break;
case LLAssetType::AT_LANDMARK:
new_bridge = new LLTaskLandmarkBridge(panel,
- object->getUUID(),
- object->getName());
+ object_id,
+ object_name);
break;
case LLAssetType::AT_CALLINGCARD:
new_bridge = new LLTaskCallingCardBridge(panel,
- object->getUUID(),
- object->getName());
+ object_id,
+ object_name);
break;
case LLAssetType::AT_SCRIPT:
// OLD SCRIPTS DEPRECATED - JC
llwarns << "Old script" << llendl;
//new_bridge = new LLTaskOldScriptBridge(panel,
- // object->getUUID(),
- // object->getName());
+ // object_id,
+ // object_name);
break;
case LLAssetType::AT_OBJECT:
new_bridge = new LLTaskObjectBridge(panel,
- object->getUUID(),
- object->getName(),
+ object_id,
+ object_name,
itemflags);
break;
case LLAssetType::AT_NOTECARD:
new_bridge = new LLTaskNotecardBridge(panel,
- object->getUUID(),
- object->getName());
+ object_id,
+ object_name);
break;
case LLAssetType::AT_ANIMATION:
new_bridge = new LLTaskAnimationBridge(panel,
- object->getUUID(),
- object->getName());
+ object_id,
+ object_name);
break;
case LLAssetType::AT_GESTURE:
new_bridge = new LLTaskGestureBridge(panel,
- object->getUUID(),
- object->getName());
+ object_id,
+ object_name);
break;
case LLAssetType::AT_CLOTHING:
case LLAssetType::AT_BODYPART:
new_bridge = new LLTaskWearableBridge(panel,
- object->getUUID(),
- object->getName(),
+ object_id,
+ object_name,
itemflags);
break;
case LLAssetType::AT_CATEGORY:
new_bridge = new LLTaskCategoryBridge(panel,
- object->getUUID(),
- object->getName());
+ object_id,
+ object_name);
break;
case LLAssetType::AT_LSL_TEXT:
new_bridge = new LLTaskLSLBridge(panel,
- object->getUUID(),
- object->getName());
+ object_id,
+ object_name);
break;
case LLAssetType::AT_MESH:
new_bridge = new LLTaskMeshBridge(panel,
- object->getUUID(),
- object->getName());
+ object_id,
+ object_name);
break;
default:
llinfos << "Unhandled inventory type (llassetstorage.h): "
@@ -1521,6 +1526,7 @@ void LLPanelObjectInventory::reset()
p.task_id = getTaskUUID();
p.parent_panel = this;
p.tool_tip= LLTrans::getString("PanelContentsTooltip");
+ p.listener = LLTaskInvFVBridge::createObjectBridge(this, NULL);
mFolders = LLUICtrlFactory::create<LLFolderView>(p);
// this ensures that we never say "searching..." or "no items found"
mFolders->getFilter()->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS);
diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp
index 62f582c343..35e2e96bab 100644
--- a/indra/newview/llpaneloutfitedit.cpp
+++ b/indra/newview/llpaneloutfitedit.cpp
@@ -36,7 +36,7 @@
#include "lloutfitobserver.h"
#include "llcofwearables.h"
#include "llfilteredwearablelist.h"
-#include "llfolderviewitem.h"
+#include "llfolderview.h"
#include "llinventory.h"
#include "llinventoryitemslist.h"
#include "llviewercontrol.h"
diff --git a/indra/newview/llpanelwearing.cpp b/indra/newview/llpanelwearing.cpp
index 911a9e5dda..0645fd8a54 100644
--- a/indra/newview/llpanelwearing.cpp
+++ b/indra/newview/llpanelwearing.cpp
@@ -174,8 +174,8 @@ LLPanelWearing::~LLPanelWearing()
if (gInventory.containsObserver(mCategoriesObserver))
{
gInventory.removeObserver(mCategoriesObserver);
- delete mCategoriesObserver;
}
+ delete mCategoriesObserver;
}
BOOL LLPanelWearing::postBuild()
diff --git a/indra/newview/llplacesinventorypanel.cpp b/indra/newview/llplacesinventorypanel.cpp
index 29e262199e..f7823f4fe8 100644
--- a/indra/newview/llplacesinventorypanel.cpp
+++ b/indra/newview/llplacesinventorypanel.cpp
@@ -35,6 +35,7 @@
#include "llinventoryfunctions.h"
#include "llpanellandmarks.h"
#include "llplacesinventorybridge.h"
+#include "llviewerfoldertype.h"
static LLDefaultChildRegistry::Register<LLPlacesInventoryPanel> r("places_inventory_panel");
@@ -56,72 +57,44 @@ LLPlacesInventoryPanel::~LLPlacesInventoryPanel()
delete mSavedFolderState;
}
-BOOL LLPlacesInventoryPanel::postBuild()
+void LLPlacesInventoryPanel::buildFolderView(const LLInventoryPanel::Params& params)
{
- LLInventoryPanel::postBuild();
+ // Determine the root folder in case specified, and
+ // build the views starting with that folder.
+ const LLFolderType::EType preferred_type = LLViewerFolderType::lookupTypeFromNewCategoryName(params.start_folder);
- // clear Contents();
- {
- mFolderRoot->destroyView();
- mFolderRoot->getParent()->removeChild(mFolderRoot);
- mFolderRoot->die();
-
- if( mScroller )
- {
- removeChild( mScroller );
- mScroller->die();
- mScroller = NULL;
- }
- mFolderRoot = NULL;
- }
-
-
- mCommitCallbackRegistrar.pushScope(); // registered as a widget; need to push callback scope ourselves
+ LLUUID root_id;
- // create root folder
+ if ("LIBRARY" == params.start_folder())
{
- LLRect folder_rect(0,
- 0,
- getRect().getWidth(),
- 0);
- LLPlacesFolderView::Params p;
- p.name = getName();
- p.title = getLabel();
- p.rect = folder_rect;
- p.parent_panel = this;
- mFolderRoot = (LLFolderView*)LLUICtrlFactory::create<LLPlacesFolderView>(p);
- mFolderRoot->setAllowMultiSelect(mAllowMultiSelect);
+ root_id = gInventory.getLibraryRootFolderID();
}
-
- mCommitCallbackRegistrar.popScope();
-
- mFolderRoot->setCallbackRegistrar(&mCommitCallbackRegistrar);
-
- // scroller
+ else
{
- LLRect scroller_view_rect = getRect();
- scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom);
- LLScrollContainer::Params p;
- p.name("Inventory Scroller");
- p.rect(scroller_view_rect);
- p.follows.flags(FOLLOWS_ALL);
- p.reserve_scroll_corner(true);
- p.tab_stop(true);
- mScroller = LLUICtrlFactory::create<LLScrollContainer>(p);
+ root_id = (preferred_type != LLFolderType::FT_NONE ? gInventory.findCategoryUUIDForType(preferred_type) : LLUUID::null);
}
- addChild(mScroller);
- mScroller->addChild(mFolderRoot);
-
- mFolderRoot->setScrollContainer(mScroller);
- mFolderRoot->addChild(mFolderRoot->mStatusTextBox);
-
- // cut subitems
- mFolderRoot->setUseEllipses(true);
-
- return TRUE;
+ LLRect folder_rect(0,
+ 0,
+ getRect().getWidth(),
+ 0);
+ LLPlacesFolderView::Params p;
+ p.name = getName();
+ p.title = getLabel();
+ p.rect = folder_rect;
+ p.listener = mInvFVBridgeBuilder->createBridge(LLAssetType::AT_CATEGORY,
+ LLAssetType::AT_CATEGORY,
+ LLInventoryType::IT_CATEGORY,
+ this,
+ NULL,
+ root_id);
+ p.parent_panel = this;
+ p.allow_multiselect = mAllowMultiSelect;
+ p.use_ellipses = true; // truncate inventory item text so remove horizontal scroller
+ mFolderRoot = (LLFolderView*)LLUICtrlFactory::create<LLPlacesFolderView>(p);
}
+
// save current folder open state
void LLPlacesInventoryPanel::saveFolderState()
{
diff --git a/indra/newview/llplacesinventorypanel.h b/indra/newview/llplacesinventorypanel.h
index 6641871a0b..f647e7f970 100644
--- a/indra/newview/llplacesinventorypanel.h
+++ b/indra/newview/llplacesinventorypanel.h
@@ -46,7 +46,7 @@ public:
LLPlacesInventoryPanel(const Params& p);
~LLPlacesInventoryPanel();
- /*virtual*/ BOOL postBuild();
+ /*virtual*/ void buildFolderView(const LLInventoryPanel::Params& params);
void saveFolderState();
void restoreFolderState();
diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp
index 9f5c55bad1..f47928b131 100644
--- a/indra/newview/llpreviewgesture.cpp
+++ b/indra/newview/llpreviewgesture.cpp
@@ -42,6 +42,7 @@
#include "llinventoryfunctions.h"
#include "llinventorymodel.h"
#include "llinventorymodelbackgroundfetch.h"
+#include "llkeyboard.h"
#include "llmultigesture.h"
#include "llnotificationsutil.h"
#include "llradiogroup.h"
diff --git a/indra/newview/llprogressview.cpp b/indra/newview/llprogressview.cpp
index 31fde5d58a..028891a90e 100644
--- a/indra/newview/llprogressview.cpp
+++ b/indra/newview/llprogressview.cpp
@@ -55,23 +55,18 @@ LLProgressView* LLProgressView::sInstance = NULL;
S32 gStartImageWidth = 1;
S32 gStartImageHeight = 1;
-const F32 FADE_IN_TIME = 1.f;
-
-const std::string ANIMATION_FILENAME = "Login Sequence ";
-const std::string ANIMATION_SUFFIX = ".jpg";
-const F32 TOTAL_LOGIN_TIME = 10.f; // seconds, wild guess at time from GL context to actual world view
-S32 gLastStartAnimationFrame = 0; // human-style indexing, first image = 1
-const S32 ANIMATION_FRAMES = 1; //13;
+const F32 FADE_TO_WORLD_TIME = 1.0f;
static LLRegisterPanelClassWrapper<LLProgressView> r("progress_view");
-
// XUI: Translate
LLProgressView::LLProgressView()
: LLPanel(),
mPercentDone( 0.f ),
+ mMediaCtrl( NULL ),
mMouseDownInActiveArea( false ),
- mUpdateEvents("LLProgressView")
+ mUpdateEvents("LLProgressView"),
+ mFadeToWorldTimer()
{
mUpdateEvents.listen("self", boost::bind(&LLProgressView::handleUpdate, this, _1));
}
@@ -80,9 +75,14 @@ BOOL LLProgressView::postBuild()
{
mProgressBar = getChild<LLProgressBar>("login_progress_bar");
+ // media control that is used to play intro video
+ mMediaCtrl = getChild<LLMediaCtrl>("login_media_panel");
+ mMediaCtrl->setVisible( false ); // hidden initially
+ mMediaCtrl->addObserver( this ); // watch events
+
mCancelBtn = getChild<LLButton>("cancel_btn");
mCancelBtn->setClickedCallback( LLProgressView::onCancelButtonClicked, NULL );
- mFadeTimer.stop();
+ mFadeToWorldTimer.stop();
getChild<LLTextBox>("title_text")->setText(LLStringExplicit(LLAppViewer::instance()->getSecondLifeTitle()));
@@ -125,24 +125,43 @@ BOOL LLProgressView::handleKeyHere(KEY key, MASK mask)
return TRUE;
}
+void LLProgressView::revealIntroPanel()
+{
+ // if user hasn't yet seen intro video
+ std::string intro_url = gSavedSettings.getString("PostFirstLoginIntroURL");
+ if ( intro_url.length() > 0 &&
+ gSavedSettings.getBOOL("PostFirstLoginIntroViewed" ) == FALSE )
+ {
+ // navigate to intro URL and reveal widget
+ mMediaCtrl->navigateTo( intro_url );
+ mMediaCtrl->setVisible( TRUE );
+
+ // flag as having seen the new user post login intro
+ gSavedSettings.setBOOL("PostFirstLoginIntroViewed", TRUE );
+ }
+ else
+ {
+ // start the timer that will control the fade through to the world view
+ mFadeToWorldTimer.start();
+ }
+}
+
void LLProgressView::setVisible(BOOL visible)
{
// hiding progress view
if (getVisible() && !visible)
{
- mFadeTimer.start();
+ LLPanel::setVisible(FALSE);
}
// showing progress view
- else if (visible && (!getVisible() || mFadeTimer.getStarted()))
+ else if (visible && (!getVisible() || mFadeToWorldTimer.getStarted()))
{
setFocus(TRUE);
- mFadeTimer.stop();
- mProgressTimer.start();
+ mFadeToWorldTimer.stop();
LLPanel::setVisible(TRUE);
}
}
-
void LLProgressView::draw()
{
static LLTimer timer;
@@ -153,7 +172,7 @@ void LLProgressView::draw()
{
LLGLSUIDefault gls_ui;
gGL.getTexUnit(0)->bind(gStartTexture.get());
- gGL.color4f(1.f, 1.f, 1.f, mFadeTimer.getStarted() ? clamp_rescale(mFadeTimer.getElapsedTimeF32(), 0.f, FADE_IN_TIME, 1.f, 0.f) : 1.f);
+ gGL.color4f(1.f, 1.f, 1.f, 1.f);
F32 image_aspect = (F32)gStartImageWidth / (F32)gStartImageHeight;
S32 width = getRect().getWidth();
S32 height = getRect().getHeight();
@@ -180,16 +199,36 @@ void LLProgressView::draw()
}
glPopMatrix();
- // Handle fade-in animation
- if (mFadeTimer.getStarted())
+ // handle fade out to world view when we're asked to
+ if (mFadeToWorldTimer.getStarted())
{
+ // draw fading panel
+ F32 alpha = clamp_rescale(mFadeToWorldTimer.getElapsedTimeF32(), 0.f, FADE_TO_WORLD_TIME, 1.f, 0.f);
+ LLViewDrawContext context(alpha);
LLPanel::draw();
- if (mFadeTimer.getElapsedTimeF32() > FADE_IN_TIME)
+
+ // faded out completely - remove panel and reveal world
+ if (mFadeToWorldTimer.getElapsedTimeF32() > FADE_TO_WORLD_TIME )
{
+ mFadeToWorldTimer.stop();
+
// Fade is complete, release focus
gFocusMgr.releaseFocusIfNeeded( this );
+
+ // turn off panel that hosts intro so we see the world
LLPanel::setVisible(FALSE);
- mFadeTimer.stop();
+
+ // stop observing events since we no longer care
+ mMediaCtrl->remObserver( this );
+
+ // hide the intro
+ mMediaCtrl->setVisible( false );
+
+ // navigate away from intro page to something innocuous since 'unload' is broken right now
+ //mMediaCtrl->navigateTo( "about:blank" );
+
+ // FIXME: this causes a crash that i haven't been able to fix
+ mMediaCtrl->unloadMediaSource();
gStartTexture = NULL;
}
@@ -307,3 +346,12 @@ bool LLProgressView::onAlertModal(const LLSD& notify)
}
return false;
}
+
+void LLProgressView::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
+{
+ if( event == MEDIA_EVENT_CLOSE_REQUEST )
+ {
+ // the intro web content calls javascript::window.close() when it's done
+ mFadeToWorldTimer.start();
+ }
+}
diff --git a/indra/newview/llprogressview.h b/indra/newview/llprogressview.h
index be1744f08a..73dd478e98 100644
--- a/indra/newview/llprogressview.h
+++ b/indra/newview/llprogressview.h
@@ -28,6 +28,7 @@
#define LL_LLPROGRESSVIEW_H
#include "llpanel.h"
+#include "llmediactrl.h"
#include "llframetimer.h"
#include "llevents.h"
@@ -35,7 +36,10 @@ class LLImageRaw;
class LLButton;
class LLProgressBar;
-class LLProgressView : public LLPanel
+class LLProgressView :
+ public LLPanel,
+ public LLViewerMediaObserver
+
{
public:
LLProgressView();
@@ -49,25 +53,35 @@ public:
/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask);
/*virtual*/ void setVisible(BOOL visible);
+ // inherited from LLViewerMediaObserver
+ /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event);
+
void setText(const std::string& text);
void setPercent(const F32 percent);
// Set it to NULL when you want to eliminate the message.
void setMessage(const std::string& msg);
+ // turns on (under certain circumstances) the into video after login
+ void revealIntroPanel();
+
void setCancelButtonVisible(BOOL b, const std::string& label);
static void onCancelButtonClicked( void* );
static void onClickMessage(void*);
bool onAlertModal(const LLSD& sd);
+ // note - this is not just hiding the intro panel - it also hides the parent panel
+ // and is used when the intro is finished and we want to show the world
+ void removeIntroPanel();
+
protected:
LLProgressBar* mProgressBar;
+ LLMediaCtrl* mMediaCtrl;
F32 mPercentDone;
std::string mMessage;
LLButton* mCancelBtn;
- LLFrameTimer mFadeTimer;
- LLFrameTimer mProgressTimer;
+ LLFrameTimer mFadeToWorldTimer;
LLRect mOutlineRect;
bool mMouseDownInActiveArea;
diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp
index 16729f045a..28ec11d1c7 100644
--- a/indra/newview/llsidepanelappearance.cpp
+++ b/indra/newview/llsidepanelappearance.cpp
@@ -32,6 +32,7 @@
#include "llagentcamera.h"
#include "llagentwearables.h"
#include "llappearancemgr.h"
+#include "llfolderview.h"
#include "llinventorypanel.h"
#include "llfiltereditor.h"
#include "llfloaterreg.h"
diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp
index 31ea542743..65655f82cd 100644
--- a/indra/newview/llsidepanelinventory.cpp
+++ b/indra/newview/llsidepanelinventory.cpp
@@ -29,33 +29,147 @@
#include "llagent.h"
#include "llappearancemgr.h"
+#include "llappviewer.h"
#include "llavataractions.h"
#include "llbutton.h"
+#include "lldate.h"
#include "llfirstuse.h"
+#include "llfoldertype.h"
+#include "llhttpclient.h"
#include "llinventorybridge.h"
#include "llinventoryfunctions.h"
+#include "llinventorymodel.h"
+#include "llinventorymodelbackgroundfetch.h"
+#include "llinventoryobserver.h"
#include "llinventorypanel.h"
+#include "lllayoutstack.h"
#include "lloutfitobserver.h"
#include "llpanelmaininventory.h"
+#include "llpanelmarketplaceinbox.h"
+#include "llpanelmarketplaceoutbox.h"
+#include "llselectmgr.h"
#include "llsidepaneliteminfo.h"
#include "llsidepaneltaskinfo.h"
+#include "llstring.h"
#include "lltabcontainer.h"
-#include "llselectmgr.h"
+#include "llviewermedia.h"
#include "llweb.h"
static LLRegisterPanelClassWrapper<LLSidepanelInventory> t_inventory("sidepanel_inventory");
-LLSidepanelInventory::LLSidepanelInventory()
- : LLPanel(),
- mItemPanel(NULL),
- mPanelMainInventory(NULL)
+//
+// Constants
+//
+
+static const char * const INBOX_EXPAND_TIME_SETTING = "LastInventoryInboxExpand";
+
+static const char * const INBOX_BUTTON_NAME = "inbox_btn";
+static const char * const OUTBOX_BUTTON_NAME = "outbox_btn";
+
+static const char * const INBOX_LAYOUT_PANEL_NAME = "inbox_layout_panel";
+static const char * const OUTBOX_LAYOUT_PANEL_NAME = "outbox_layout_panel";
+static const char * const MAIN_INVENTORY_LAYOUT_PANEL_NAME = "main_inventory_layout_panel";
+
+static const char * const INBOX_INVENTORY_PANEL = "inventory_inbox";
+static const char * const OUTBOX_INVENTORY_PANEL = "inventory_outbox";
+
+static const char * const INVENTORY_LAYOUT_STACK_NAME = "inventory_layout_stack";
+
+static const char * const MARKETPLACE_INBOX_PANEL = "marketplace_inbox";
+static const char * const MARKETPLACE_OUTBOX_PANEL = "marketplace_outbox";
+
+//
+// Helpers
+//
+
+class LLInboxOutboxAddedObserver : public LLInventoryCategoryAddedObserver
{
+public:
+ LLInboxOutboxAddedObserver(LLSidepanelInventory * sidepanelInventory)
+ : LLInventoryCategoryAddedObserver()
+ , mSidepanelInventory(sidepanelInventory)
+ {
+ }
+
+ void done()
+ {
+ for (cat_vec_t::iterator it = mAddedCategories.begin(); it != mAddedCategories.end(); ++it)
+ {
+ LLViewerInventoryCategory* added_category = *it;
+
+ LLFolderType::EType added_category_type = added_category->getPreferredType();
+
+ switch (added_category_type)
+ {
+ case LLFolderType::FT_INBOX:
+ mSidepanelInventory->observeInboxModifications(added_category->getUUID());
+ break;
+ case LLFolderType::FT_OUTBOX:
+ mSidepanelInventory->observeOutboxModifications(added_category->getUUID());
+ break;
+ case LLFolderType::FT_NONE:
+ // HACK until sim update to properly create folder with system type
+ if (added_category->getName() == "Received Items")
+ {
+ mSidepanelInventory->observeInboxModifications(added_category->getUUID());
+ }
+ else if (added_category->getName() == "Merchant Outbox")
+ {
+ mSidepanelInventory->observeOutboxModifications(added_category->getUUID());
+ }
+ default:
+ break;
+ }
+ }
+ }
+
+private:
+ LLSidepanelInventory * mSidepanelInventory;
+};
+//
+// Implementation
+//
+
+LLSidepanelInventory::LLSidepanelInventory()
+ : LLPanel()
+ , mItemPanel(NULL)
+ , mPanelMainInventory(NULL)
+ , mInboxEnabled(false)
+ , mOutboxEnabled(false)
+ , mCategoriesObserver(NULL)
+ , mInboxOutboxAddedObserver(NULL)
+{
//buildFromFile( "panel_inventory.xml"); // Called from LLRegisterPanelClass::defaultPanelClassBuilder()
}
LLSidepanelInventory::~LLSidepanelInventory()
{
+ if (mCategoriesObserver && gInventory.containsObserver(mCategoriesObserver))
+ {
+ gInventory.removeObserver(mCategoriesObserver);
+ }
+ delete mCategoriesObserver;
+
+ if (mInboxOutboxAddedObserver && gInventory.containsObserver(mInboxOutboxAddedObserver))
+ {
+ gInventory.removeObserver(mInboxOutboxAddedObserver);
+ }
+ delete mInboxOutboxAddedObserver;
+}
+
+void handleInventoryDisplayInboxChanged()
+{
+ LLSidepanelInventory* sidepanel_inventory = dynamic_cast<LLSidepanelInventory*>(LLSideTray::getInstance()->getPanel("sidepanel_inventory"));
+
+ sidepanel_inventory->enableInbox(gSavedSettings.getBOOL("InventoryDisplayInbox"));
+}
+
+void handleInventoryDisplayOutboxChanged()
+{
+ LLSidepanelInventory* sidepanel_inventory = dynamic_cast<LLSidepanelInventory*>(LLSideTray::getInstance()->getPanel("sidepanel_inventory"));
+
+ sidepanel_inventory->enableOutbox(gSavedSettings.getBOOL("InventoryDisplayOutbox"));
}
BOOL LLSidepanelInventory::postBuild()
@@ -85,7 +199,7 @@ BOOL LLSidepanelInventory::postBuild()
mOverflowBtn = mInventoryPanel->getChild<LLButton>("overflow_btn");
mOverflowBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onOverflowButtonClicked, this));
- mPanelMainInventory = mInventoryPanel->findChild<LLPanelMainInventory>("panel_main_inventory");
+ mPanelMainInventory = mInventoryPanel->getChild<LLPanelMainInventory>("panel_main_inventory");
mPanelMainInventory->setSelectCallback(boost::bind(&LLSidepanelInventory::onSelectionChange, this, _1, _2));
LLTabContainer* tabs = mPanelMainInventory->getChild<LLTabContainer>("inventory filter tabs");
tabs->setCommitCallback(boost::bind(&LLSidepanelInventory::updateVerbs, this));
@@ -103,7 +217,7 @@ BOOL LLSidepanelInventory::postBuild()
// UI elements from item panel
{
- mItemPanel = findChild<LLSidepanelItemInfo>("sidepanel__item_panel");
+ mItemPanel = getChild<LLSidepanelItemInfo>("sidepanel__item_panel");
LLButton* back_btn = mItemPanel->getChild<LLButton>("back_btn");
back_btn->setClickedCallback(boost::bind(&LLSidepanelInventory::onBackButtonClicked, this));
@@ -119,13 +233,263 @@ BOOL LLSidepanelInventory::postBuild()
}
}
+ // Marketplace inbox/outbox setup
+ {
+ LLLayoutStack* stack = getChild<LLLayoutStack>(INVENTORY_LAYOUT_STACK_NAME);
+
+ // Disable user_resize on main inventory panel by default
+ stack->setPanelUserResize(MAIN_INVENTORY_LAYOUT_PANEL_NAME, false);
+ stack->setPanelUserResize(INBOX_LAYOUT_PANEL_NAME, false);
+ stack->setPanelUserResize(OUTBOX_LAYOUT_PANEL_NAME, false);
+
+ // Collapse both inbox and outbox panels
+ stack->collapsePanel(getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME), true);
+ stack->collapsePanel(getChild<LLLayoutPanel>(OUTBOX_LAYOUT_PANEL_NAME), true);
+
+ // Set up button states and callbacks
+ LLButton * inbox_button = getChild<LLButton>(INBOX_BUTTON_NAME);
+ LLButton * outbox_button = getChild<LLButton>(OUTBOX_BUTTON_NAME);
+
+ inbox_button->setToggleState(false);
+ outbox_button->setToggleState(false);
+
+ inbox_button->setCommitCallback(boost::bind(&LLSidepanelInventory::onToggleInboxBtn, this));
+ outbox_button->setCommitCallback(boost::bind(&LLSidepanelInventory::onToggleOutboxBtn, this));
+
+ // Set the inbox and outbox visible based on debug settings (final setting comes from http request below)
+ enableInbox(gSavedSettings.getBOOL("InventoryDisplayInbox"));
+ enableOutbox(gSavedSettings.getBOOL("InventoryDisplayOutbox"));
+
+ // Trigger callback for after login so we can setup to track inbox and outbox changes after initial inventory load
+ LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLSidepanelInventory::handleLoginComplete, this));
+ }
+
+ gSavedSettings.getControl("InventoryDisplayInbox")->getCommitSignal()->connect(boost::bind(&handleInventoryDisplayInboxChanged));
+ gSavedSettings.getControl("InventoryDisplayOutbox")->getCommitSignal()->connect(boost::bind(&handleInventoryDisplayOutboxChanged));
+
return TRUE;
}
+void LLSidepanelInventory::handleLoginComplete()
+{
+ //
+ // Track inbox and outbox folder changes
+ //
+
+ const bool do_not_create_folder = false;
+ const bool do_not_find_in_library = false;
+
+ const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, do_not_create_folder, do_not_find_in_library);
+ const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, do_not_create_folder, do_not_find_in_library);
+
+ // Set up observer to listen for creation of inbox and outbox if at least one of them doesn't exist
+ if (inbox_id.isNull() || outbox_id.isNull())
+ {
+ observeInboxOutboxCreation();
+ }
+
+ // Set up observer for inbox changes, if we have an inbox already
+ if (!inbox_id.isNull())
+ {
+ observeInboxModifications(inbox_id);
+
+ // Enable the display of the inbox if it exists
+ enableInbox(true);
+ }
+
+ // Set up observer for outbox changes, if we have an outbox already
+ if (!outbox_id.isNull())
+ {
+ observeOutboxModifications(outbox_id);
+
+ // Enable the display of the outbox if it exists
+ //enableOutbox(true);
+ // leslie NOTE: Disabling outbox until we support it officially.
+ }
+}
+
+void LLSidepanelInventory::observeInboxOutboxCreation()
+{
+ //
+ // Set up observer to track inbox and outbox folder creation
+ //
+
+ if (mInboxOutboxAddedObserver == NULL)
+ {
+ mInboxOutboxAddedObserver = new LLInboxOutboxAddedObserver(this);
+
+ gInventory.addObserver(mInboxOutboxAddedObserver);
+ }
+}
+
+void LLSidepanelInventory::observeInboxModifications(const LLUUID& inboxID)
+{
+ //
+ // Track inbox and outbox folder changes
+ //
+
+ if (inboxID.isNull())
+ {
+ llwarns << "Attempting to track modifications to non-existant inbox" << llendl;
+ return;
+ }
+
+ if (mCategoriesObserver == NULL)
+ {
+ mCategoriesObserver = new LLInventoryCategoriesObserver();
+ gInventory.addObserver(mCategoriesObserver);
+ }
+
+ mCategoriesObserver->addCategory(inboxID, boost::bind(&LLSidepanelInventory::onInboxChanged, this, inboxID));
+
+ //
+ // Trigger a load for the entire contents of the Inbox
+ //
+
+ LLInventoryModelBackgroundFetch::instance().start(inboxID);
+
+ //
+ // Set up the inbox inventory view
+ //
+
+ LLPanelMarketplaceInbox * inbox = getChild<LLPanelMarketplaceInbox>(MARKETPLACE_INBOX_PANEL);
+ inbox->setupInventoryPanel();
+}
+
+
+void LLSidepanelInventory::observeOutboxModifications(const LLUUID& outboxID)
+{
+ //
+ // Track outbox folder changes
+ //
+
+ if (outboxID.isNull())
+ {
+ llwarns << "Attempting to track modifications to non-existant outbox" << llendl;
+ return;
+ }
+
+ if (mCategoriesObserver == NULL)
+ {
+ mCategoriesObserver = new LLInventoryCategoriesObserver();
+ gInventory.addObserver(mCategoriesObserver);
+ }
+
+ mCategoriesObserver->addCategory(outboxID, boost::bind(&LLSidepanelInventory::onOutboxChanged, this, outboxID));
+
+ //
+ // Set up the outbox inventory view
+ //
+
+ LLPanelMarketplaceOutbox * outbox = getChild<LLPanelMarketplaceOutbox>(MARKETPLACE_OUTBOX_PANEL);
+ outbox->setupInventoryPanel();
+}
+
+void LLSidepanelInventory::enableInbox(bool enabled)
+{
+ mInboxEnabled = enabled;
+ getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME)->setVisible(enabled);
+}
+
+void LLSidepanelInventory::enableOutbox(bool enabled)
+{
+ mOutboxEnabled = enabled;
+ getChild<LLLayoutPanel>(OUTBOX_LAYOUT_PANEL_NAME)->setVisible(enabled);
+}
+
+void LLSidepanelInventory::onInboxChanged(const LLUUID& inbox_id)
+{
+ // Trigger a load of the entire inbox so we always know the contents and their creation dates for sorting
+ LLInventoryModelBackgroundFetch::instance().start(inbox_id);
+
+ // Expand the inbox since we have fresh items
+ LLPanelMarketplaceInbox * inbox = findChild<LLPanelMarketplaceInbox>(MARKETPLACE_INBOX_PANEL);
+ if (inbox && (inbox->getFreshItemCount() > 0))
+ {
+ getChild<LLButton>(INBOX_BUTTON_NAME)->setToggleState(true);
+ onToggleInboxBtn();
+ }
+}
+
+void LLSidepanelInventory::onOutboxChanged(const LLUUID& outbox_id)
+{
+ // Perhaps use this to track outbox changes?
+}
+
+bool manageInboxOutboxPanels(LLLayoutStack * stack,
+ LLButton * pressedButton, LLLayoutPanel * pressedPanel,
+ LLButton * otherButton, LLLayoutPanel * otherPanel)
+{
+ bool expand = pressedButton->getToggleState();
+ bool otherExpanded = otherButton->getToggleState();
+
+ //
+ // NOTE: Ideally we could have two panel sizes stored for a collapsed and expanded minimum size.
+ // For now, leave this code disabled because it creates some bad artifacts when expanding
+ // and collapsing the inbox/outbox.
+ //
+ //S32 smallMinSize = (expand ? pressedPanel->getMinDim() : otherPanel->getMinDim());
+ //S32 pressedMinSize = (expand ? 2 * smallMinSize : smallMinSize);
+ //otherPanel->setMinDim(smallMinSize);
+ //pressedPanel->setMinDim(pressedMinSize);
+
+ if (expand && otherExpanded)
+ {
+ // Reshape pressedPanel to the otherPanel's height so we preserve the marketplace panel size
+ pressedPanel->reshape(pressedPanel->getRect().getWidth(), otherPanel->getRect().getHeight());
+
+ stack->collapsePanel(otherPanel, true);
+ otherButton->setToggleState(false);
+ }
+
+ stack->collapsePanel(pressedPanel, !expand);
+
+ // Enable user_resize on main inventory panel only when a marketplace box is expanded
+ stack->setPanelUserResize(MAIN_INVENTORY_LAYOUT_PANEL_NAME, expand);
+
+ return expand;
+}
+
+void LLSidepanelInventory::onToggleInboxBtn()
+{
+ LLLayoutStack* stack = getChild<LLLayoutStack>(INVENTORY_LAYOUT_STACK_NAME);
+ LLButton* pressedButton = getChild<LLButton>(INBOX_BUTTON_NAME);
+ LLLayoutPanel* pressedPanel = getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME);
+ LLButton* otherButton = getChild<LLButton>(OUTBOX_BUTTON_NAME);
+ LLLayoutPanel* otherPanel = getChild<LLLayoutPanel>(OUTBOX_LAYOUT_PANEL_NAME);
+
+ bool inboxExpanded = manageInboxOutboxPanels(stack, pressedButton, pressedPanel, otherButton, otherPanel);
+
+ if (inboxExpanded)
+ {
+ // Save current time as a setting for future new-ness tests
+ gSavedSettings.setString(INBOX_EXPAND_TIME_SETTING, LLDate::now().asString());
+ }
+}
+
+void LLSidepanelInventory::onToggleOutboxBtn()
+{
+ LLLayoutStack* stack = getChild<LLLayoutStack>(INVENTORY_LAYOUT_STACK_NAME);
+ LLButton* pressedButton = getChild<LLButton>(OUTBOX_BUTTON_NAME);
+ LLLayoutPanel* pressedPanel = getChild<LLLayoutPanel>(OUTBOX_LAYOUT_PANEL_NAME);
+ LLButton* otherButton = getChild<LLButton>(INBOX_BUTTON_NAME);
+ LLLayoutPanel* otherPanel = getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME);
+
+ manageInboxOutboxPanels(stack, pressedButton, pressedPanel, otherButton, otherPanel);
+}
+
void LLSidepanelInventory::onOpen(const LLSD& key)
{
LLFirstUse::newInventory(false);
+ // Expand the inbox if we have fresh items
+ LLPanelMarketplaceInbox * inbox = findChild<LLPanelMarketplaceInbox>(MARKETPLACE_INBOX_PANEL);
+ if (inbox && (inbox->getFreshItemCount() > 0))
+ {
+ getChild<LLButton>(INBOX_BUTTON_NAME)->setToggleState(true);
+ onToggleInboxBtn();
+ }
+
if(key.size() == 0)
return;
@@ -171,26 +535,29 @@ void LLSidepanelInventory::onShopButtonClicked()
void LLSidepanelInventory::performActionOnSelection(const std::string &action)
{
- LLPanelMainInventory *panel_main_inventory = mInventoryPanel->findChild<LLPanelMainInventory>("panel_main_inventory");
+ LLPanelMainInventory *panel_main_inventory = mInventoryPanel->getChild<LLPanelMainInventory>("panel_main_inventory");
LLFolderViewItem* current_item = panel_main_inventory->getActivePanel()->getRootFolder()->getCurSelectedItem();
if (!current_item)
{
- return;
+ LLInventoryPanel* inbox = findChild<LLInventoryPanel>("inventory_inbox");
+ if (inbox)
+ {
+ current_item = inbox->getRootFolder()->getCurSelectedItem();
+ }
+
+ if (!current_item)
+ {
+ return;
+ }
}
+
current_item->getListener()->performAction(panel_main_inventory->getActivePanel()->getModel(), action);
}
void LLSidepanelInventory::onWearButtonClicked()
{
- LLPanelMainInventory *panel_main_inventory = mInventoryPanel->findChild<LLPanelMainInventory>("panel_main_inventory");
- if (!panel_main_inventory)
- {
- llassert(panel_main_inventory != NULL);
- return;
- }
-
// Get selected items set.
- const std::set<LLUUID> selected_uuids_set = panel_main_inventory->getActivePanel()->getRootFolder()->getSelectionList();
+ const std::set<LLUUID> selected_uuids_set = LLAvatarActions::getInventorySelectedUUIDs();
if (selected_uuids_set.empty()) return; // nothing selected
// Convert the set to a vector.
@@ -329,31 +696,28 @@ bool LLSidepanelInventory::canShare()
LLPanelMainInventory* panel_main_inventory =
mInventoryPanel->findChild<LLPanelMainInventory>("panel_main_inventory");
- if (!panel_main_inventory)
+ LLInventoryPanel* inbox = findChild<LLInventoryPanel>("inventory_inbox");
+
+ // Avoid flicker in the Recent tab while inventory is being loaded.
+ if ( (!inbox || inbox->getRootFolder()->getSelectionList().empty())
+ && (panel_main_inventory && !panel_main_inventory->getActivePanel()->getRootFolder()->hasVisibleChildren()) )
{
- llwarns << "Failed to get the main inventory panel" << llendl;
return false;
}
- LLInventoryPanel* active_panel = panel_main_inventory->getActivePanel();
- // Avoid flicker in the Recent tab while inventory is being loaded.
- if (!active_panel->getRootFolder()->hasVisibleChildren()) return false;
-
- return LLAvatarActions::canShareSelectedItems(active_panel);
+ return ( (panel_main_inventory ? LLAvatarActions::canShareSelectedItems(panel_main_inventory->getActivePanel()) : false)
+ || (inbox ? LLAvatarActions::canShareSelectedItems(inbox) : false) );
}
+
bool LLSidepanelInventory::canWearSelected()
{
- LLPanelMainInventory* panel_main_inventory =
- mInventoryPanel->findChild<LLPanelMainInventory>("panel_main_inventory");
- if (!panel_main_inventory)
- {
- llassert(panel_main_inventory != NULL);
+ std::set<LLUUID> selected_uuids = LLAvatarActions::getInventorySelectedUUIDs();
+
+ if (selected_uuids.empty())
return false;
- }
- std::set<LLUUID> selected_uuids = panel_main_inventory->getActivePanel()->getRootFolder()->getSelectionList();
for (std::set<LLUUID>::const_iterator it = selected_uuids.begin();
it != selected_uuids.end();
++it)
@@ -366,11 +730,20 @@ bool LLSidepanelInventory::canWearSelected()
LLInventoryItem *LLSidepanelInventory::getSelectedItem()
{
- LLPanelMainInventory *panel_main_inventory = mInventoryPanel->findChild<LLPanelMainInventory>("panel_main_inventory");
+ LLPanelMainInventory *panel_main_inventory = mInventoryPanel->getChild<LLPanelMainInventory>("panel_main_inventory");
LLFolderViewItem* current_item = panel_main_inventory->getActivePanel()->getRootFolder()->getCurSelectedItem();
if (!current_item)
{
- return NULL;
+ LLInventoryPanel* inbox = findChild<LLInventoryPanel>("inventory_inbox");
+ if (inbox)
+ {
+ current_item = inbox->getRootFolder()->getCurSelectedItem();
+ }
+
+ if (!current_item)
+ {
+ return NULL;
+ }
}
const LLUUID &item_id = current_item->getListener()->getUUID();
LLInventoryItem *item = gInventory.getItem(item_id);
@@ -379,9 +752,20 @@ LLInventoryItem *LLSidepanelInventory::getSelectedItem()
U32 LLSidepanelInventory::getSelectedCount()
{
- LLPanelMainInventory *panel_main_inventory = mInventoryPanel->findChild<LLPanelMainInventory>("panel_main_inventory");
+ int count = 0;
+
+ LLPanelMainInventory *panel_main_inventory = mInventoryPanel->getChild<LLPanelMainInventory>("panel_main_inventory");
std::set<LLUUID> selection_list = panel_main_inventory->getActivePanel()->getRootFolder()->getSelectionList();
- return selection_list.size();
+ count += selection_list.size();
+
+ LLInventoryPanel* inbox = findChild<LLInventoryPanel>("inventory_inbox");
+ if (inbox)
+ {
+ selection_list = inbox->getRootFolder()->getSelectionList();
+ count += selection_list.size();
+ }
+
+ return count;
}
LLInventoryPanel *LLSidepanelInventory::getActivePanel()
diff --git a/indra/newview/llsidepanelinventory.h b/indra/newview/llsidepanelinventory.h
index 32c98bc034..9117e3bf27 100644
--- a/indra/newview/llsidepanelinventory.h
+++ b/indra/newview/llsidepanelinventory.h
@@ -30,6 +30,8 @@
#include "llpanel.h"
class LLFolderViewItem;
+class LLInboxOutboxAddedObserver;
+class LLInventoryCategoriesObserver;
class LLInventoryItem;
class LLInventoryPanel;
class LLPanelMainInventory;
@@ -42,6 +44,14 @@ public:
LLSidepanelInventory();
virtual ~LLSidepanelInventory();
+private:
+ void handleLoginComplete();
+
+public:
+ void observeInboxOutboxCreation();
+ void observeInboxModifications(const LLUUID& inboxID);
+ void observeOutboxModifications(const LLUUID& outboxID);
+
/*virtual*/ BOOL postBuild();
/*virtual*/ void onOpen(const LLSD& key);
@@ -56,6 +66,17 @@ public:
// checks can share selected item(s)
bool canShare();
+ void onToggleInboxBtn();
+ void onToggleOutboxBtn();
+
+ void enableInbox(bool enabled);
+ void enableOutbox(bool enabled);
+
+ bool isInboxEnabled() const { return mInboxEnabled; }
+ bool isOutboxEnabled() const { return mOutboxEnabled; }
+
+ void updateVerbs();
+
protected:
// Tracks highlighted (selected) item in inventory panel.
LLInventoryItem *getSelectedItem();
@@ -63,10 +84,12 @@ protected:
void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action);
// "wear", "teleport", etc.
void performActionOnSelection(const std::string &action);
- void updateVerbs();
bool canWearSelected(); // check whether selected items can be worn
+ void onInboxChanged(const LLUUID& inbox_id);
+ void onOutboxChanged(const LLUUID& outbox_id);
+
//
// UI Elements
//
@@ -85,6 +108,7 @@ protected:
void onTeleportButtonClicked();
void onOverflowButtonClicked();
void onBackButtonClicked();
+
private:
LLButton* mInfoBtn;
LLButton* mShareBtn;
@@ -94,6 +118,11 @@ private:
LLButton* mOverflowBtn;
LLButton* mShopBtn;
+ bool mInboxEnabled;
+ bool mOutboxEnabled;
+
+ LLInventoryCategoriesObserver* mCategoriesObserver;
+ LLInboxOutboxAddedObserver* mInboxOutboxAddedObserver;
};
#endif //LL_LLSIDEPANELINVENTORY_H
diff --git a/indra/newview/llsidepanelinventorysubpanel.cpp b/indra/newview/llsidepanelinventorysubpanel.cpp
index 37b10b592f..2918bb388a 100644
--- a/indra/newview/llsidepanelinventorysubpanel.cpp
+++ b/indra/newview/llsidepanelinventorysubpanel.cpp
@@ -46,8 +46,8 @@
///----------------------------------------------------------------------------
// Default constructor
-LLSidepanelInventorySubpanel::LLSidepanelInventorySubpanel()
- : LLPanel(),
+LLSidepanelInventorySubpanel::LLSidepanelInventorySubpanel(const LLPanel::Params& p)
+ : LLPanel(p),
mIsDirty(TRUE),
mIsEditing(FALSE),
mCancelBtn(NULL),
diff --git a/indra/newview/llsidepanelinventorysubpanel.h b/indra/newview/llsidepanelinventorysubpanel.h
index b2de7d3b0b..b5cf3aaf17 100644
--- a/indra/newview/llsidepanelinventorysubpanel.h
+++ b/indra/newview/llsidepanelinventorysubpanel.h
@@ -40,7 +40,7 @@ class LLInventoryItem;
class LLSidepanelInventorySubpanel : public LLPanel
{
public:
- LLSidepanelInventorySubpanel();
+ LLSidepanelInventorySubpanel(const LLPanel::Params& p = getDefaultParams());
virtual ~LLSidepanelInventorySubpanel();
/*virtual*/ void setVisible(BOOL visible);
diff --git a/indra/newview/llsidepaneliteminfo.cpp b/indra/newview/llsidepaneliteminfo.cpp
index fbd2f7ca83..1ce05da849 100644
--- a/indra/newview/llsidepaneliteminfo.cpp
+++ b/indra/newview/llsidepaneliteminfo.cpp
@@ -130,9 +130,10 @@ void LLObjectInventoryObserver::inventoryChanged(LLViewerObject* object,
static LLRegisterPanelClassWrapper<LLSidepanelItemInfo> t_item_info("sidepanel_item_info");
// Default constructor
-LLSidepanelItemInfo::LLSidepanelItemInfo()
- : mItemID(LLUUID::null)
- , mObjectInventoryObserver(NULL)
+LLSidepanelItemInfo::LLSidepanelItemInfo(const LLPanel::Params& p)
+ : LLSidepanelInventorySubpanel(p)
+ , mItemID(LLUUID::null)
+ , mObjectInventoryObserver(NULL)
{
mPropertiesObserver = new LLItemPropertiesObserver(this);
}
diff --git a/indra/newview/llsidepaneliteminfo.h b/indra/newview/llsidepaneliteminfo.h
index 25be145f64..12aaca923e 100644
--- a/indra/newview/llsidepaneliteminfo.h
+++ b/indra/newview/llsidepaneliteminfo.h
@@ -44,7 +44,7 @@ class LLPermissions;
class LLSidepanelItemInfo : public LLSidepanelInventorySubpanel
{
public:
- LLSidepanelItemInfo();
+ LLSidepanelItemInfo(const LLPanel::Params& p = getDefaultParams());
virtual ~LLSidepanelItemInfo();
/*virtual*/ BOOL postBuild();
diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp
index 631b244785..651897a217 100644
--- a/indra/newview/llsidetray.cpp
+++ b/indra/newview/llsidetray.cpp
@@ -30,6 +30,7 @@
#include "llagentcamera.h"
#include "llappviewer.h"
+#include "llbadge.h"
#include "llbottomtray.h"
#include "llfloaterreg.h"
#include "llfirstuse.h"
@@ -40,6 +41,7 @@
#include "llfocusmgr.h"
#include "llrootview.h"
#include "llnavigationbar.h"
+#include "llpanelmarketplaceinbox.h"
#include "llaccordionctrltab.h"
@@ -113,11 +115,14 @@ public:
Optional<std::string> image_selected;
Optional<std::string> tab_title;
Optional<std::string> description;
+ Optional<LLBadge::Params> badge;
+
Params()
: image("image"),
image_selected("image_selected"),
tab_title("tab_title","no title"),
- description("description","no description")
+ description("description","no description"),
+ badge("badge")
{};
};
protected:
@@ -140,7 +145,6 @@ public:
static LLSideTrayTab* createInstance ();
const std::string& getDescription () const { return mDescription;}
- const std::string& getTabTitle() const { return mTabTitle;}
void onOpen (const LLSD& key);
@@ -150,7 +154,10 @@ public:
BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
- LLPanel *getPanel();
+ LLPanel* getPanel();
+
+ LLButton* createButton(bool allowTearOff, LLUICtrl::commit_callback_t callback);
+
private:
std::string mTabTitle;
std::string mImage;
@@ -158,6 +165,9 @@ private:
std::string mDescription;
LLView* mMainPanel;
+
+ bool mHasBadge;
+ LLBadge::Params mBadgeParams;
};
LLSideTrayTab::LLSideTrayTab(const Params& p)
@@ -166,8 +176,10 @@ LLSideTrayTab::LLSideTrayTab(const Params& p)
mImage(p.image),
mImageSelected(p.image_selected),
mDescription(p.description),
- mMainPanel(NULL)
+ mMainPanel(NULL),
+ mBadgeParams(p.badge)
{
+ mHasBadge = p.badge.isProvided();
}
LLSideTrayTab::~LLSideTrayTab()
@@ -182,8 +194,6 @@ bool LLSideTrayTab::addChild(LLView* view, S32 tab_group)
//return res;
}
-
-
//virtual
BOOL LLSideTrayTab::postBuild()
{
@@ -196,7 +206,7 @@ BOOL LLSideTrayTab::postBuild()
getChild<LLButton>("undock")->setCommitCallback(boost::bind(&LLSideTrayTab::setDocked, this, false));
getChild<LLButton>("dock")->setCommitCallback(boost::bind(&LLSideTrayTab::setDocked, this, true));
- return true;
+ return LLPanel::postBuild();
}
static const S32 splitter_margin = 1;
@@ -523,18 +533,36 @@ public:
return FALSE;
}
+ void setBadgeDriver(LLSideTrayTabBadgeDriver* driver)
+ {
+ mBadgeDriver = driver;
+ }
+
protected:
LLSideTrayButton(const LLButton::Params& p)
- : LLButton(p)
- , mDragLastScreenX(0)
- , mDragLastScreenY(0)
+ : LLButton(p)
+ , mDragLastScreenX(0)
+ , mDragLastScreenY(0)
+ , mBadgeDriver(NULL)
{}
friend class LLUICtrlFactory;
+ void draw()
+ {
+ if (mBadgeDriver)
+ {
+ setBadgeLabel(mBadgeDriver->getBadgeString());
+ }
+
+ LLButton::draw();
+ }
+
private:
S32 mDragLastScreenX;
S32 mDragLastScreenY;
+
+ LLSideTrayTabBadgeDriver* mBadgeDriver;
};
//////////////////////////////////////////////////////////////////////////////
@@ -615,11 +643,31 @@ BOOL LLSideTray::postBuild()
return true;
}
+void LLSideTray::setTabButtonBadgeDriver(std::string tabName, LLSideTrayTabBadgeDriver* driver)
+{
+ mTabButtonBadgeDrivers[tabName] = driver;
+}
+
void LLSideTray::handleLoginComplete()
{
//reset tab to "home" tab if it was changesd during login process
selectTabByName("sidebar_home");
+ for (badge_map_t::iterator it = mTabButtonBadgeDrivers.begin(); it != mTabButtonBadgeDrivers.end(); ++it)
+ {
+ LLButton* button = mTabButtons[it->first];
+ LLSideTrayButton* side_button = dynamic_cast<LLSideTrayButton*>(button);
+
+ if (side_button)
+ {
+ side_button->setBadgeDriver(it->second);
+ }
+ else
+ {
+ llwarns << "Unable to find button " << it->first << " to set the badge driver. " << llendl;
+ }
+ }
+
detachTabs();
}
@@ -766,51 +814,6 @@ bool LLSideTray::selectTabByName(const std::string& name, bool keep_prev_visible
return true;
}
-LLButton* LLSideTray::createButton (const std::string& name,const std::string& image,const std::string& tooltip,
- LLUICtrl::commit_callback_t callback)
-{
- static LLSideTray::Params sidetray_params(LLUICtrlFactory::getDefaultParams<LLSideTray>());
-
- LLButton::Params bparams;
-
- LLRect rect;
- rect.setOriginAndSize(0, 0, sidetray_params.default_button_width, sidetray_params.default_button_height);
-
- bparams.name(name);
- bparams.follows.flags (FOLLOWS_LEFT | FOLLOWS_TOP);
- bparams.rect (rect);
- bparams.tab_stop(false);
- bparams.image_unselected(sidetray_params.tab_btn_image_normal);
- bparams.image_selected(sidetray_params.tab_btn_image_selected);
- bparams.image_disabled(sidetray_params.tab_btn_image_normal);
- bparams.image_disabled_selected(sidetray_params.tab_btn_image_selected);
-
- LLButton* button;
- if (name == "sidebar_openclose")
- {
- // "Open/Close" button shouldn't allow "tear off"
- // hence it is created as LLButton instance.
- button = LLUICtrlFactory::create<LLButton>(bparams);
- }
- else
- {
- button = LLUICtrlFactory::create<LLSideTrayButton>(bparams);
- }
-
- button->setClickedCallback(callback);
-
- button->setToolTip(tooltip);
-
- if(image.length())
- {
- button->setImageOverlay(image);
- }
-
- mButtonsPanel->addChildInBack(button);
-
- return button;
-}
-
bool LLSideTray::addChild(LLView* view, S32 tab_group)
{
LLSideTrayTab* tab_panel = dynamic_cast<LLSideTrayTab*>(view);
@@ -938,7 +941,56 @@ bool LLSideTray::addTab(LLSideTrayTab* tab)
return true;
}
-void LLSideTray::createButtons ()
+LLButton* LLSideTrayTab::createButton(bool allowTearOff, LLUICtrl::commit_callback_t callback)
+{
+ static LLSideTray::Params sidetray_params(LLUICtrlFactory::getDefaultParams<LLSideTray>());
+
+ LLRect rect;
+ rect.setOriginAndSize(0, 0, sidetray_params.default_button_width, sidetray_params.default_button_height);
+
+ LLButton::Params bparams;
+
+ // Append "_button" to the side tray tab name
+ std::string button_name = getName() + "_button";
+ bparams.name(button_name);
+ bparams.follows.flags (FOLLOWS_LEFT | FOLLOWS_TOP);
+ bparams.rect (rect);
+ bparams.tab_stop(false);
+ bparams.image_unselected(sidetray_params.tab_btn_image_normal);
+ bparams.image_selected(sidetray_params.tab_btn_image_selected);
+ bparams.image_disabled(sidetray_params.tab_btn_image_normal);
+ bparams.image_disabled_selected(sidetray_params.tab_btn_image_selected);
+
+ if (mHasBadge)
+ {
+ bparams.badge = mBadgeParams;
+ }
+
+ LLButton* button;
+ if (allowTearOff)
+ {
+ button = LLUICtrlFactory::create<LLSideTrayButton>(bparams);
+ }
+ else
+ {
+ // "Open/Close" button shouldn't allow "tear off"
+ // hence it is created as LLButton instance.
+ button = LLUICtrlFactory::create<LLButton>(bparams);
+ }
+
+ button->setClickedCallback(callback);
+
+ button->setToolTip(mTabTitle);
+
+ if(mImage.length())
+ {
+ button->setImageOverlay(mImage);
+ }
+
+ return button;
+}
+
+void LLSideTray::createButtons()
{
//create buttons for tabs
child_vector_const_iter_t child_it = mTabs.begin();
@@ -951,17 +1003,22 @@ void LLSideTray::createButtons ()
// The "OpenClose" button will open/close the whole panel
if (name == "sidebar_openclose")
{
- mCollapseButton = createButton(name,sidebar_tab->mImage,sidebar_tab->getTabTitle(),
- boost::bind(&LLSideTray::onToggleCollapse, this));
+ mCollapseButton = sidebar_tab->createButton(false, boost::bind(&LLSideTray::onToggleCollapse, this));
+
+ mButtonsPanel->addChildInBack(mCollapseButton);
+
LLHints::registerHintTarget("side_panel_btn", mCollapseButton->getHandle());
}
else
{
- LLButton* button = createButton(name,sidebar_tab->mImage,sidebar_tab->getTabTitle(),
- boost::bind(&LLSideTray::onTabButtonClick, this, name));
+ LLButton* button = sidebar_tab->createButton(true, boost::bind(&LLSideTray::onTabButtonClick, this, name));
+
+ mButtonsPanel->addChildInBack(button);
+
mTabButtons[name] = button;
}
}
+
LLHints::registerHintTarget("inventory_btn", mTabButtons["sidebar_inventory"]->getHandle());
}
diff --git a/indra/newview/llsidetray.h b/indra/newview/llsidetray.h
index 24882411f4..17158329dc 100644
--- a/indra/newview/llsidetray.h
+++ b/indra/newview/llsidetray.h
@@ -33,6 +33,13 @@
class LLAccordionCtrl;
class LLSideTrayTab;
+// Define an interface for side tab button badge values
+class LLSideTrayTabBadgeDriver
+{
+public:
+ virtual std::string getBadgeString() const = 0;
+};
+
// Deal with LLSideTrayTab being opaque. Generic do-nothing cast...
template <class T>
T tab_cast(LLSideTrayTab* tab) { return tab; }
@@ -166,6 +173,8 @@ public:
bool getCollapsed() { return mCollapsed; }
+ void setTabButtonBadgeDriver(std::string tabName, LLSideTrayTabBadgeDriver* driver);
+
public:
virtual ~LLSideTray(){};
@@ -204,8 +213,6 @@ protected:
void createButtons ();
- LLButton* createButton (const std::string& name,const std::string& image,const std::string& tooltip,
- LLUICtrl::commit_callback_t callback);
void arrange ();
void detachTabs ();
void reflectCollapseChange();
@@ -234,6 +241,8 @@ private:
LLPanel* mButtonsPanel;
typedef std::map<std::string,LLButton*> button_map_t;
button_map_t mTabButtons;
+ typedef std::map<std::string,LLSideTrayTabBadgeDriver*> badge_map_t;
+ badge_map_t mTabButtonBadgeDrivers;
child_vector_t mTabs;
child_vector_t mDetachedTabs;
tab_order_vector_t mOriginalTabOrder;
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 3c2ef37bb8..4dfcb85295 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -76,6 +76,7 @@
#include "lluserrelations.h"
#include "llversioninfo.h"
#include "llviewercontrol.h"
+#include "llviewerhelp.h"
#include "llvfs.h"
#include "llxorcipher.h" // saved password, MAC address
#include "llwindow.h"
@@ -1689,11 +1690,22 @@ bool idle_startup()
gViewerThrottle.setMaxBandwidth(FAST_RATE_BPS / 1024.f);
}
+ if (gSavedSettings.getBOOL("ShowHelpOnFirstLogin"))
+ {
+ gSavedSettings.setBOOL("HelpFloaterOpen", TRUE);
+ }
+
// Set the show start location to true, now that the user has logged
// on with this install.
gSavedSettings.setBOOL("ShowStartLocation", TRUE);
}
+ if (gSavedSettings.getBOOL("HelpFloaterOpen"))
+ {
+ // show default topic
+ LLViewerHelp::instance().showTopic("");
+ }
+
// We're successfully logged in.
gSavedSettings.setBOOL("FirstLoginThisInstall", FALSE);
@@ -1950,7 +1962,8 @@ bool idle_startup()
gViewerWindow->getWindow()->resetBusyCount();
gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW);
LL_DEBUGS("AppInit") << "Done releasing bitmap" << LL_ENDL;
- gViewerWindow->setShowProgress(FALSE);
+ gViewerWindow->revealIntroPanel();
+ //gViewerWindow->setShowProgress(FALSE); // reveal intro video now handles this
gViewerWindow->setProgressCancelButtonVisible(FALSE);
// We're not away from keyboard, even though login might have taken
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index 5b76537804..de22f2ae6b 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -420,7 +420,6 @@ BOOL LLFloaterTexturePicker::postBuild()
mInventoryPanel->setFilterPermMask(mImmediateFilterPermMask);
mInventoryPanel->setSelectCallback(boost::bind(&LLFloaterTexturePicker::onSelectionChange, this, _1, _2));
mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
- mInventoryPanel->setAllowMultiSelect(FALSE);
// Disable auto selecting first filtered item because it takes away
// selection from the item set by LLTextureCtrl owning this floater.
diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp
index 42f780a8a3..9101222393 100644
--- a/indra/newview/llviewerfoldertype.cpp
+++ b/indra/newview/llviewerfoldertype.cpp
@@ -128,8 +128,10 @@ LLViewerFolderDictionary::LLViewerFolderDictionary()
addEntry(LLFolderType::FT_MY_OUTFITS, new ViewerFolderEntry("My Outfits", "Inv_SysOpen", "Inv_SysClosed", TRUE));
addEntry(LLFolderType::FT_MESH, new ViewerFolderEntry("Meshes", "Inv_SysOpen", "Inv_SysClosed", FALSE));
-
addEntry(LLFolderType::FT_INBOX, new ViewerFolderEntry("Inbox", "Inv_SysOpen", "Inv_SysClosed", FALSE));
+ addEntry(LLFolderType::FT_OUTBOX, new ViewerFolderEntry("Outbox", "Inv_SysOpen", "Inv_SysClosed", FALSE));
+
+ addEntry(LLFolderType::FT_BASIC_ROOT, new ViewerFolderEntry("Basic Root", "Inv_SysOpen", "Inv_SysClosed", FALSE));
addEntry(LLFolderType::FT_NONE, new ViewerFolderEntry("New Folder", "Inv_FolderOpen", "Inv_FolderClosed", FALSE, "default"));
diff --git a/indra/newview/llviewerhelp.cpp b/indra/newview/llviewerhelp.cpp
index 9fe8c142b9..3a3d4f3881 100644
--- a/indra/newview/llviewerhelp.cpp
+++ b/indra/newview/llviewerhelp.cpp
@@ -101,8 +101,9 @@ void LLViewerHelp::showTopic(const std::string &topic)
// work out the URL for this topic and display it
showHelp();
+
std::string helpURL = LLViewerHelpUtil::buildHelpURL( help_topic );
- setRawURL( helpURL );
+ setRawURL(helpURL);
}
std::string LLViewerHelp::defaultTopic()
@@ -148,18 +149,7 @@ std::string LLViewerHelp::getTopicFromFocus()
// static
void LLViewerHelp::showHelp()
{
- LLFloaterHelpBrowser* helpbrowser = dynamic_cast<LLFloaterHelpBrowser*>(LLFloaterReg::getInstance("help_browser"));
- if (helpbrowser)
- {
- BOOL visible = TRUE;
- BOOL take_focus = TRUE;
- helpbrowser->setVisible(visible);
- helpbrowser->setFrontmost(take_focus);
- }
- else
- {
- llwarns << "Eep, help_browser floater not found" << llendl;
- }
+ LLFloaterReg::showInstance("help_browser");
}
// static
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 9e58acdcd3..22666cec0d 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1269,7 +1269,7 @@ void menu_create_inventory_item(LLFolderView* root, LLFolderBridge *bridge, cons
{
std::string type_name = userdata.asString();
- if (("category" == type_name) || ("current" == type_name) || ("outfit" == type_name) || ("my_otfts" == type_name))
+ if (("inbox" == type_name) || ("outbox" == type_name) || ("category" == type_name) || ("current" == type_name) || ("outfit" == type_name) || ("my_otfts" == type_name))
{
LLFolderType::EType preferred_type = LLFolderType::lookup(type_name);
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 1e53274cd6..1be58eae45 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -64,8 +64,10 @@
#include "llappviewer.h"
#include "lllogininstance.h"
//#include "llfirstuse.h"
+#include "llviewernetwork.h"
#include "llwindow.h"
+
#include "llfloatermediabrowser.h" // for handling window close requests and geometry change requests in media browser windows.
#include "llfloaterwebcontent.h" // for handling window close requests and geometry change requests in media browser windows.
@@ -1360,6 +1362,34 @@ void LLViewerMedia::removeCookie(const std::string &name, const std::string &dom
}
+class LLInventoryUserStatusResponder : public LLHTTPClient::Responder
+{
+public:
+ LLInventoryUserStatusResponder()
+ : LLCurl::Responder()
+ {
+ }
+
+ void completed(U32 status, const std::string& reason, const LLSD& content)
+ {
+ if (isGoodStatus(status))
+ {
+ // Complete success
+ gSavedSettings.setBOOL("InventoryDisplayInbox", true);
+ }
+ else if (status == 401)
+ {
+ // API is available for use but OpenID authorization failed
+ gSavedSettings.setBOOL("InventoryDisplayInbox", true);
+ }
+ else
+ {
+ // API in unavailable
+ llinfos << "Marketplace API is unavailable -- Inbox may be disabled, status = " << status << ", reason = " << reason << llendl;
+ }
+ }
+};
+
/////////////////////////////////////////////////////////////////////////////////////////
// static
void LLViewerMedia::setOpenIDCookie()
@@ -1406,6 +1436,25 @@ void LLViewerMedia::setOpenIDCookie()
LLHTTPClient::get(profile_url,
new LLViewerMediaWebProfileResponder(raw_profile_url.getAuthority()),
headers);
+
+ std::string url = "https://marketplace.secondlife.com/";
+
+ if (!LLGridManager::getInstance()->isInProductionGrid())
+ {
+ std::string gridLabel = LLGridManager::getInstance()->getGridLabel();
+ url = llformat("https://marketplace.%s.lindenlab.com/", utf8str_tolower(gridLabel).c_str());
+ }
+
+ url += "api/1/users/";
+ url += gAgent.getID().getString();
+ url += "/user_status";
+
+ headers = LLSD::emptyMap();
+ headers["Accept"] = "*/*";
+ headers["Cookie"] = sOpenIDCookie;
+ headers["User-Agent"] = getCurrentUserAgent();
+
+ LLHTTPClient::get(url, new LLInventoryUserStatusResponder(), headers);
}
}
@@ -2349,15 +2398,13 @@ void LLViewerMediaImpl::updateJavascriptObject()
if ( mMediaSource )
{
// flag to expose this information to internal browser or not.
- bool expose_javascript_object = gSavedSettings.getBOOL("BrowserEnableJSObject");
- mMediaSource->jsExposeObjectEvent( expose_javascript_object );
+ bool enable = gSavedSettings.getBOOL("BrowserEnableJSObject");
+ mMediaSource->jsEnableObject( enable );
- // indicate if the values we have are valid (currently do this blanket-fashion for
- // everything depending on whether you are logged in or not - this may require a
- // more granular approach once variables are added that ARE valid before login
+ // these values are only menaingful after login so don't set them before
bool logged_in = LLLoginInstance::getInstance()->authSuccess();
- mMediaSource->jsValuesValidEvent( logged_in );
-
+ if ( logged_in )
+ {
// current location within a region
LLVector3 agent_pos = gAgent.getPositionAgent();
double x = agent_pos.mV[ VX ];
@@ -2386,6 +2433,7 @@ void LLViewerMediaImpl::updateJavascriptObject()
region_name = region->getName();
};
mMediaSource->jsAgentRegionEvent( region_name );
+ }
// language code the viewer is set to
mMediaSource->jsAgentLanguageEvent( LLUI::getLanguage() );
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 55eea8fc69..a37f8ad0d8 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -108,6 +108,7 @@
#include "lltrans.h"
#include "lleconomy.h"
#include "lltoolgrab.h"
+#include "llwindow.h"
#include "boost/unordered_map.hpp"
using namespace LLVOAvatarDefines;
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 9f7559ad15..44b3a85f25 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -37,6 +37,7 @@
#include "lleconomy.h"
#include "lleventtimer.h"
#include "llfloaterreg.h"
+#include "llfolderview.h"
#include "llfollowcamparams.h"
#include "llinventorydefines.h"
#include "lllslconstants.h"
@@ -87,6 +88,7 @@
#include "lluri.h"
#include "llviewergenericmessage.h"
#include "llviewermenu.h"
+#include "llviewerinventory.h"
#include "llviewerjoystick.h"
#include "llviewerobjectlist.h"
#include "llviewerparcelmgr.h"
@@ -694,7 +696,7 @@ bool join_group_response(const LLSD& notification, const LLSD& response)
return false;
}
-static void highlight_inventory_items_in_panel(const std::vector<LLUUID>& items, LLInventoryPanel *inventory_panel)
+static void highlight_inventory_objects_in_panel(const std::vector<LLUUID>& items, LLInventoryPanel *inventory_panel)
{
if (NULL == inventory_panel) return;
@@ -708,7 +710,7 @@ static void highlight_inventory_items_in_panel(const std::vector<LLUUID>& items,
continue;
}
- LLInventoryItem* item = gInventory.getItem(item_id);
+ LLInventoryObject* item = gInventory.getObject(item_id);
llassert(item);
if (!item) {
continue;
@@ -787,7 +789,6 @@ class LLViewerInventoryMoveFromWorldObserver : public LLInventoryAddItemByAssetO
public:
LLViewerInventoryMoveFromWorldObserver()
: LLInventoryAddItemByAssetObserver()
- , mActivePanel(NULL)
{
}
@@ -798,13 +799,16 @@ private:
/*virtual */void onAssetAdded(const LLUUID& asset_id)
{
// Store active Inventory panel.
- mActivePanel = LLInventoryPanel::getActiveInventoryPanel();
+ if (LLInventoryPanel::getActiveInventoryPanel())
+ {
+ mActivePanel = LLInventoryPanel::getActiveInventoryPanel()->getHandle();
+ }
// Store selected items (without destination folder)
mSelectedItems.clear();
- if (mActivePanel)
+ if (LLInventoryPanel::getActiveInventoryPanel())
{
- mSelectedItems = mActivePanel->getRootFolder()->getSelectionList();
+ mSelectedItems = LLInventoryPanel::getActiveInventoryPanel()->getRootFolder()->getSelectionList();
}
mSelectedItems.erase(mMoveIntoFolderID);
}
@@ -815,12 +819,14 @@ private:
*/
void done()
{
+ LLInventoryPanel* active_panel = dynamic_cast<LLInventoryPanel*>(mActivePanel.get());
+
// if selection is not changed since watch started lets hightlight new items.
- if (mActivePanel && !isSelectionChanged())
+ if (active_panel && !isSelectionChanged())
{
LL_DEBUGS("Inventory_Move") << "Selecting new items..." << LL_ENDL;
- mActivePanel->clearSelection();
- highlight_inventory_items_in_panel(mAddedItems, mActivePanel);
+ active_panel->clearSelection();
+ highlight_inventory_objects_in_panel(mAddedItems, active_panel);
}
}
@@ -828,16 +834,16 @@ private:
* Returns true if selected inventory items were changed since moved inventory items were started to watch.
*/
bool isSelectionChanged()
- {
- const LLInventoryPanel * const current_active_panel = LLInventoryPanel::getActiveInventoryPanel();
+ {
+ LLInventoryPanel* active_panel = dynamic_cast<LLInventoryPanel*>(mActivePanel.get());
- if (NULL == mActivePanel || current_active_panel != mActivePanel)
+ if (NULL == active_panel)
{
return true;
}
// get selected items (without destination folder)
- selected_items_t selected_items = mActivePanel->getRootFolder()->getSelectionList();
+ selected_items_t selected_items = active_panel->getRootFolder()->getSelectionList();
selected_items.erase(mMoveIntoFolderID);
// compare stored & current sets of selected items
@@ -851,7 +857,7 @@ private:
return different_items.size() > 0;
}
- LLInventoryPanel *mActivePanel;
+ LLHandle<LLPanel> mActivePanel;
typedef std::set<LLUUID> selected_items_t;
selected_items_t mSelectedItems;
@@ -880,6 +886,75 @@ void set_dad_inventory_item(LLInventoryItem* inv_item, const LLUUID& into_folder
gInventoryMoveObserver->watchAsset(inv_item->getAssetUUID());
}
+
+/**
+ * Class to observe moving of items and to select them in inventory.
+ *
+ * Used currently for dragging from inbox to regular inventory folders
+ */
+
+class LLViewerInventoryMoveObserver : public LLInventoryObserver
+{
+public:
+
+ LLViewerInventoryMoveObserver(const LLUUID& object_id)
+ : LLInventoryObserver()
+ , mObjectID(object_id)
+ {
+ if (LLInventoryPanel::getActiveInventoryPanel())
+ {
+ mActivePanel = LLInventoryPanel::getActiveInventoryPanel()->getHandle();
+ }
+ }
+
+ virtual ~LLViewerInventoryMoveObserver() {}
+ virtual void changed(U32 mask);
+
+private:
+ LLUUID mObjectID;
+ LLHandle<LLPanel> mActivePanel;
+
+};
+
+void LLViewerInventoryMoveObserver::changed(U32 mask)
+{
+ LLInventoryPanel* active_panel = dynamic_cast<LLInventoryPanel*>(mActivePanel.get());
+
+ if (NULL == active_panel)
+ {
+ gInventory.removeObserver(this);
+ return;
+ }
+
+ if((mask & (LLInventoryObserver::STRUCTURE)) != 0)
+ {
+ const std::set<LLUUID>& changed_items = gInventory.getChangedIDs();
+
+ std::set<LLUUID>::const_iterator id_it = changed_items.begin();
+ std::set<LLUUID>::const_iterator id_end = changed_items.end();
+ for (;id_it != id_end; ++id_it)
+ {
+ if ((*id_it) == mObjectID)
+ {
+ active_panel->clearSelection();
+ std::vector<LLUUID> items;
+ items.push_back(mObjectID);
+ highlight_inventory_objects_in_panel(items, active_panel);
+ active_panel->getRootFolder()->scrollToShowSelection();
+
+ gInventory.removeObserver(this);
+ break;
+ }
+ }
+ }
+}
+
+void set_dad_inbox_object(const LLUUID& object_id)
+{
+ LLViewerInventoryMoveObserver* move_observer = new LLViewerInventoryMoveObserver(object_id);
+ gInventory.addObserver(move_observer);
+}
+
//unlike the FetchObserver for AgentOffer, we only make one
//instance of the AddedObserver for TaskOffers
//and it never dies. We do this because we don't know the UUID of
@@ -936,7 +1011,6 @@ protected:
//one global instance to bind them
LLOpenTaskOffer* gNewInventoryObserver=NULL;
-
class LLNewInventoryHintObserver : public LLInventoryAddedObserver
{
protected:
@@ -946,6 +1020,8 @@ protected:
}
};
+LLNewInventoryHintObserver* gNewInventoryHintObserver=NULL;
+
void start_new_inventory_observer()
{
if (!gNewInventoryObserver) //task offer observer
@@ -962,7 +1038,12 @@ void start_new_inventory_observer()
gInventory.addObserver(gInventoryMoveObserver);
}
- gInventory.addObserver(new LLNewInventoryHintObserver());
+ if (!gNewInventoryHintObserver)
+ {
+ // Observer is deleted by gInventory
+ gNewInventoryHintObserver = new LLNewInventoryHintObserver();
+ gInventory.addObserver(gNewInventoryHintObserver);
+ }
}
class LLDiscardAgentOffer : public LLInventoryFetchItemsObserver
@@ -4324,7 +4405,7 @@ void process_sound_trigger(LLMessageSystem *msg, void **)
{
return;
}
-
+
// Don't play sounds from gestures if they are not enabled.
if (object_id == owner_id && !gSavedSettings.getBOOL("EnableGestureSounds"))
{
@@ -6499,7 +6580,7 @@ void process_script_dialog(LLMessageSystem* msg, void**)
LLUUID owner_id;
if (gMessageSystem->getNumberOfBlocks("OwnerData") > 0)
{
- msg->getUUID("OwnerData", "OwnerID", owner_id);
+ msg->getUUID("OwnerData", "OwnerID", owner_id);
}
if (LLMuteList::getInstance()->isMuted(object_id) || LLMuteList::getInstance()->isMuted(owner_id))
diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h
index b4a9b8e677..9d09d9c01a 100644
--- a/indra/newview/llviewermessage.h
+++ b/indra/newview/llviewermessage.h
@@ -203,6 +203,8 @@ void open_inventory_offer(const uuid_vec_t& items, const std::string& from_name)
bool highlight_offered_object(const LLUUID& obj_id);
void set_dad_inventory_item(LLInventoryItem* inv_item, const LLUUID& into_folder_uuid);
+void set_dad_inbox_object(const LLUUID& object_id);
+
class LLOfferInfo : public LLNotificationResponderInterface
{
diff --git a/indra/newview/llviewerprecompiledheaders.h b/indra/newview/llviewerprecompiledheaders.h
index faa86d43dd..252183b6d7 100644
--- a/indra/newview/llviewerprecompiledheaders.h
+++ b/indra/newview/llviewerprecompiledheaders.h
@@ -33,6 +33,8 @@
// in viewer.
// It is used to precompile headers for improved build speed.
+#include <boost/coroutine/coroutine.hpp>
+
#include "linden_common.h"
// Work around stupid Microsoft STL warning
@@ -118,8 +120,8 @@
// Library includes from llvfs
#include "lldir.h"
-
-// Library includes from llmessage project
+
+// Library includes from llmessage project
#include "llcachename.h"
#endif
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index b1441cc281..cff166b825 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -1979,7 +1979,10 @@ void LLViewerWindow::shutdownViews()
// destroy the nav bar, not currently part of gViewerWindow
// *TODO: Make LLNavigationBar part of gViewerWindow
+ if (LLNavigationBar::instanceExists())
+ {
delete LLNavigationBar::getInstance();
+ }
// destroy menus after instantiating navbar above, as it needs
// access to gMenuHolder
@@ -4512,6 +4515,14 @@ void LLViewerWindow::setup3DViewport(S32 x_offset, S32 y_offset)
glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
}
+void LLViewerWindow::revealIntroPanel()
+{
+ if (mProgressView)
+ {
+ mProgressView->revealIntroPanel();
+ }
+}
+
void LLViewerWindow::setShowProgress(const BOOL show)
{
if (mProgressView)
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index df6928aa1d..ff49ed1f62 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -271,6 +271,7 @@ public:
void setProgressMessage(const std::string& msg);
void setProgressCancelButtonVisible( BOOL b, const std::string& label = LLStringUtil::null );
LLProgressView *getProgressView() const;
+ void revealIntroPanel();
void updateObjectUnderCursor();
diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml
index b0628dfe67..76965ad14b 100644
--- a/indra/newview/skins/default/colors.xml
+++ b/indra/newview/skins/default/colors.xml
@@ -133,6 +133,15 @@
name="AvatarListItemIconVoiceLeftColor"
reference="AvatarListItemIconOfflineColor" />
<color
+ name="BadgeImageColor"
+ value="0.44 0.69 0.56 1.0" />
+ <color
+ name="BadgeBorderColor"
+ value="0.9 0.9 0.9 1.0" />
+ <color
+ name="BadgeLabelColor"
+ reference="White" />
+ <color
name="ButtonBorderColor"
reference="Unused?" />
<color
@@ -760,7 +769,7 @@
<color
name="MenuBarProjectBgColor"
reference="MdBlue" />
-
+
<color
name="MeshImportTableNormalColor"
value="1 1 1 1"/>
diff --git a/indra/newview/skins/default/textures/icons/Inv_Gift.png b/indra/newview/skins/default/textures/icons/Inv_Gift.png
new file mode 100644
index 0000000000..5afe85d72d
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Gift.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Disabled.png b/indra/newview/skins/default/textures/icons/OutboxPush_Disabled.png
new file mode 100644
index 0000000000..be58114aa1
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OutboxPush_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Off.png b/indra/newview/skins/default/textures/icons/OutboxPush_Off.png
new file mode 100644
index 0000000000..e6b9480ab1
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OutboxPush_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_On.png b/indra/newview/skins/default/textures/icons/OutboxPush_On.png
new file mode 100644
index 0000000000..ffda2e92d4
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OutboxPush_On.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_On_Over.png b/indra/newview/skins/default/textures/icons/OutboxPush_On_Over.png
new file mode 100644
index 0000000000..6b5911014f
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OutboxPush_On_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_On_Selected.png b/indra/newview/skins/default/textures/icons/OutboxPush_On_Selected.png
new file mode 100644
index 0000000000..0e60b417b0
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OutboxPush_On_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Over.png b/indra/newview/skins/default/textures/icons/OutboxPush_Over.png
new file mode 100644
index 0000000000..9c26b92e73
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OutboxPush_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Press.png b/indra/newview/skins/default/textures/icons/OutboxPush_Press.png
new file mode 100644
index 0000000000..3b5d462975
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OutboxPush_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_1.png b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_1.png
new file mode 100644
index 0000000000..f85be047b0
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_1.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_2.png b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_2.png
new file mode 100644
index 0000000000..cd4e482216
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_2.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_3.png b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_3.png
new file mode 100644
index 0000000000..d212a871ce
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_3.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_4.png b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_4.png
new file mode 100644
index 0000000000..e5b6023e36
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_4.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_5.png b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_5.png
new file mode 100644
index 0000000000..e1911a092f
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_5.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_6.png b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_6.png
new file mode 100644
index 0000000000..9e59f7843a
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_6.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Selected.png b/indra/newview/skins/default/textures/icons/OutboxPush_Selected.png
new file mode 100644
index 0000000000..51e8bff646
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OutboxPush_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Disabled.png b/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Disabled.png
new file mode 100644
index 0000000000..300e2e69e1
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Over.png b/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Over.png
new file mode 100644
index 0000000000..32fb236381
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Over.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Press.png b/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Press.png
new file mode 100644
index 0000000000..827f343b1e
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Press.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Sync_Disabled.png b/indra/newview/skins/default/textures/icons/Sync_Disabled.png
new file mode 100644
index 0000000000..ca2e8def97
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Sync_Disabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Sync_Enabled.png b/indra/newview/skins/default/textures/icons/Sync_Enabled.png
new file mode 100644
index 0000000000..bc236c8b98
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Sync_Enabled.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Sync_Progress_1.png b/indra/newview/skins/default/textures/icons/Sync_Progress_1.png
new file mode 100644
index 0000000000..624e556376
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Sync_Progress_1.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Sync_Progress_2.png b/indra/newview/skins/default/textures/icons/Sync_Progress_2.png
new file mode 100644
index 0000000000..5769803b3f
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Sync_Progress_2.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Sync_Progress_3.png b/indra/newview/skins/default/textures/icons/Sync_Progress_3.png
new file mode 100644
index 0000000000..92d4bfb020
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Sync_Progress_3.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Sync_Progress_4.png b/indra/newview/skins/default/textures/icons/Sync_Progress_4.png
new file mode 100644
index 0000000000..6d43eb3a9f
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Sync_Progress_4.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Sync_Progress_5.png b/indra/newview/skins/default/textures/icons/Sync_Progress_5.png
new file mode 100644
index 0000000000..766d063c99
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Sync_Progress_5.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/Sync_Progress_6.png b/indra/newview/skins/default/textures/icons/Sync_Progress_6.png
new file mode 100644
index 0000000000..dfe7f68b72
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Sync_Progress_6.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index cc7cce99c9..c2757f2c94 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -72,8 +72,11 @@ with the same filename but different name
<texture name="BackButton_Over" file_name="icons/back_arrow_over.png" preload="false" scale.left="22" scale.top="12" scale.right="25" scale.bottom="12" />
<texture name="BackButton_Press" file_name="icons/back_arrow_press.png" preload="false" scale.left="22" scale.top="12" scale.right="25" scale.bottom="12" />
+ <texture name="Badge_Background" file_name="widgets/Badge_Background.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
+ <texture name="Badge_Border" file_name="widgets/Badge_Border.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" />
+
<texture name="Blank" file_name="Blank.png" preload="false" />
-
+
<texture name="BreadCrumbBtn_Left_Disabled" file_name="widgets/BreadCrumbBtn_Left_Disabled.png" preload="false"/>
<texture name="BreadCrumbBtn_Left_Off" file_name="widgets/BreadCrumbBtn_Left_Off.png" preload="false"/>
<texture name="BreadCrumbBtn_Left_Over" file_name="widgets/BreadCrumbBtn_Left_Over.png" preload="false"/>
@@ -88,7 +91,6 @@ with the same filename but different name
<texture name="BreadCrumbBtn_Right_Off" file_name="widgets/BreadCrumbBtn_Right_Off.png" preload="false"/>
<texture name="BreadCrumbBtn_Right_Over" file_name="widgets/BreadCrumbBtn_Right_Over.png" preload="false"/>
<texture name="BreadCrumbBtn_Right_Press" file_name="widgets/BreadCrumbBtn_Right_Press.png" preload="false"/>
-
<texture name="BuyArrow_Over" file_name="navbar/BuyArrow_Over.png" preload="true" scale.left="0" scale.top="1" scale.right="0" scale.bottom="0" />
<texture name="BuyArrow_Press" file_name="navbar/BuyArrow_Press.png" preload="true" scale.left="1" scale.top="1" scale.right="0" scale.bottom="0" />
@@ -266,6 +268,8 @@ with the same filename but different name
<texture name="Locked_Icon" file_name="icons/Locked_Icon.png" preload="false" />
+ <texture name="MarketplaceBtn_Off" file_name="widgets/MarketplaceBtn_Off.png" preload="true" scale.left="30" scale.top="19" scale.right="35" scale.bottom="4" />
+ <texture name="MarketplaceBtn_Selected" file_name="widgets/MarketplaceBtn_Selected.png" preload="true" scale.left="30" scale.top="19" scale.right="35" scale.bottom="4" />
<texture name="Microphone_On" file_name="icons/Microphone_On.png" preload="false" />
@@ -349,6 +353,23 @@ with the same filename but different name
<texture name="OptionsMenu_Off" file_name="icons/OptionsMenu_Off.png" preload="false" />
<texture name="OptionsMenu_Press" file_name="icons/OptionsMenu_Press.png" preload="false" />
+ <texture name="OutboxPush_Disabled" file_name="icons/OutboxPush_Disabled.png" preload="true" />
+ <texture name="OutboxPush_Off" file_name="icons/OutboxPush_Off.png" preload="true" />
+ <texture name="OutboxPush_On" file_name="icons/OutboxPush_On.png" preload="true" />
+ <texture name="OutboxPush_On_Over" file_name="icons/OutboxPush_On_Over.png" preload="true" />
+ <texture name="OutboxPush_Over" file_name="icons/OutboxPush_Over.png" preload="true" />
+ <texture name="OutboxPush_Press" file_name="icons/OutboxPush_Press.png" preload="true" />
+ <texture name="OutboxPush_Progress_1" file_name="icons/OutboxPush_Progress_1.png" preload="true" />
+ <texture name="OutboxPush_Progress_2" file_name="icons/OutboxPush_Progress_2.png" preload="true" />
+ <texture name="OutboxPush_Progress_3" file_name="icons/OutboxPush_Progress_3.png" preload="true" />
+ <texture name="OutboxPush_Progress_4" file_name="icons/OutboxPush_Progress_4.png" preload="true" />
+ <texture name="OutboxPush_Progress_5" file_name="icons/OutboxPush_Progress_5.png" preload="true" />
+ <texture name="OutboxPush_Progress_6" file_name="icons/OutboxPush_Progress_6.png" preload="true" />
+ <texture name="OutboxPush_Selected" file_name="icons/OutboxPush_Selected.png" preload="true" />
+ <texture name="OutboxPush_Selected_Disabled" file_name="icons/OutboxPush_Selected_Disabled.png" preload="true" />
+ <texture name="OutboxPush_Selected_Over" file_name="icons/OutboxPush_Selected_Over.png" preload="true" />
+ <texture name="OutboxPush_Selected_Press" file_name="icons/OutboxPush_Selected_Press.png" preload="true" />
+
<texture name="PanOrbit_Off" file_name="bottomtray/PanOrbit_Off.png" preload="false" />
<texture name="Parcel_Exp_Color" file_name="icons/Parcel_Exp_Color.png" preload="false" />
@@ -496,6 +517,15 @@ with the same filename but different name
<texture name="StopReload_Off" file_name="icons/StopReload_Off.png" preload="false" />
<texture name="StopReload_Over" file_name="icons/StopReload_Over.png" preload="false" />
+ <texture name="Sync_Disabled" file_name="icons/Sync_Disabled.png" preload="true" />
+ <texture name="Sync_Enabled" file_name="icons/Sync_Enabled.png" preload="true" />
+ <texture name="Sync_Progress_1" file_name="icons/Sync_Progress_1.png" preload="true" />
+ <texture name="Sync_Progress_2" file_name="icons/Sync_Progress_2.png" preload="true" />
+ <texture name="Sync_Progress_3" file_name="icons/Sync_Progress_3.png" preload="true" />
+ <texture name="Sync_Progress_4" file_name="icons/Sync_Progress_4.png" preload="true" />
+ <texture name="Sync_Progress_5" file_name="icons/Sync_Progress_5.png" preload="true" />
+ <texture name="Sync_Progress_6" file_name="icons/Sync_Progress_6.png" preload="true" />
+
<texture name="TabIcon_Appearance_Off" file_name="taskpanel/TabIcon_Appearance_Off.png" preload="false" />
<texture name="TabIcon_Appearance_Selected" file_name="taskpanel/TabIcon_Appearance_Selected.png" preload="false" />
<texture name="TabIcon_Close_Off" file_name="taskpanel/TabIcon_Close_Off.png" preload="false" />
@@ -649,6 +679,7 @@ with the same filename but different name
<texture name="inv_folder_mesh.tga"/>
<texture name="inv_item_mesh.tga"/>
+
<texture name="lag_status_critical.tga" />
<texture name="lag_status_good.tga" />
<texture name="lag_status_warning.tga" />
diff --git a/indra/newview/skins/default/textures/widgets/Badge_Background.png b/indra/newview/skins/default/textures/widgets/Badge_Background.png
new file mode 100644
index 0000000000..5089c30312
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/Badge_Background.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/Badge_Border.png b/indra/newview/skins/default/textures/widgets/Badge_Border.png
new file mode 100644
index 0000000000..4b086a63fb
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/Badge_Border.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Off.png b/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Off.png
new file mode 100644
index 0000000000..e603c44384
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Off.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Selected.png b/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Selected.png
new file mode 100644
index 0000000000..fbc164123f
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Selected.png
Binary files differ
diff --git a/indra/newview/skins/default/xui/en/floater_help_browser.xml b/indra/newview/skins/default/xui/en/floater_help_browser.xml
index 02e50ee584..de6d586f72 100644
--- a/indra/newview/skins/default/xui/en/floater_help_browser.xml
+++ b/indra/newview/skins/default/xui/en/floater_help_browser.xml
@@ -2,6 +2,8 @@
<floater
legacy_header_height="18"
can_resize="true"
+ left="10000"
+ bottom="10000"
height="600"
layout="topleft"
min_height="150"
diff --git a/indra/newview/skins/default/xui/en/floater_media_browser.xml b/indra/newview/skins/default/xui/en/floater_media_browser.xml
index 43729d7c9f..5a1f920398 100644
--- a/indra/newview/skins/default/xui/en/floater_media_browser.xml
+++ b/indra/newview/skins/default/xui/en/floater_media_browser.xml
@@ -5,7 +5,7 @@
height="440"
layout="topleft"
min_height="140"
- min_width="467"
+ min_width="0"
name="floater_about"
help_topic="floater_about"
save_rect="true"
diff --git a/indra/newview/skins/default/xui/en/floater_web_content.xml b/indra/newview/skins/default/xui/en/floater_web_content.xml
index e04a72cbc0..69e6057556 100644
--- a/indra/newview/skins/default/xui/en/floater_web_content.xml
+++ b/indra/newview/skins/default/xui/en/floater_web_content.xml
@@ -18,6 +18,7 @@
follows="left|right|top|bottom"
layout="topleft"
left="5"
+ animate="false"
name="stack1"
orientation="vertical"
top="20"
@@ -156,14 +157,20 @@
name="external_controls"
top_delta="0"
user_resize="false"
+ auto_resize="true"
width="585">
<web_browser
- bottom="-22"
+ bottom="-2"
follows="all"
layout="topleft"
left="0"
name="webbrowser"
top="0"/>
+ </layout_panel>
+ <layout_panel name="status_bar"
+ height="23"
+ auto_resize="false"
+ user_resize="false">
<text
type="string"
length="200"
@@ -174,7 +181,7 @@
name="statusbartext"
parse_urls="false"
text_color="0.4 0.4 0.4 1"
- top_pad="5"
+ top_pad="3"
width="495"/>
<progress_bar
color_bar="0.3 1.0 0.3 1"
diff --git a/indra/newview/skins/default/xui/en/menu_inventory_add.xml b/indra/newview/skins/default/xui/en/menu_inventory_add.xml
index b36b82ebd8..e0ccb18c08 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory_add.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory_add.xml
@@ -42,7 +42,7 @@
<menu_item_call.on_enable
function="File.EnableUpload" />
</menu_item_call>
- <menu_item_call
+ <menu_item_call
label="Model..."
layout="topleft"
name="Upload Model">
@@ -263,4 +263,4 @@
parameter="eyes" />
</menu_item_call>
</menu>
-</menu>
+</menu> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml b/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml
new file mode 100644
index 0000000000..d06190ec54
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<inbox_inventory_panel
+ name="inventory_inbox"
+ start_folder="Received Items"
+ follows="all" layout="topleft"
+ top="0" left="0" height="165" width="308"
+ top_pad="0"
+ bg_opaque_color="DkGray2"
+ bg_alpha_color="DkGray2"
+ background_visible="true"
+ background_opaque="true"
+ border="false"
+ bevel_style="none"
+ show_item_link_overlays="true"
+ >
+ <scroll reserve_scroll_corner="false" />
+</inbox_inventory_panel>
diff --git a/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml b/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml
new file mode 100644
index 0000000000..af32056428
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<inventory_panel
+ name="inventory_outbox"
+ start_folder="Outbox"
+ follows="all" layout="topleft"
+ top="0" left="0" height="165" width="308"
+ top_pad="0"
+ bg_opaque_color="DkGray2"
+ bg_alpha_color="DkGray2"
+ background_visible="true"
+ background_opaque="true"
+ border="false"
+ bevel_style="none"
+ show_item_link_overlays="true"
+ >
+ <scroll reserve_scroll_corner="false" />
+</inventory_panel>
diff --git a/indra/newview/skins/default/xui/en/panel_progress.xml b/indra/newview/skins/default/xui/en/panel_progress.xml
index 2868d91cc7..4535c56339 100644
--- a/indra/newview/skins/default/xui/en/panel_progress.xml
+++ b/indra/newview/skins/default/xui/en/panel_progress.xml
@@ -132,4 +132,12 @@
name="cancel_btn"
top="700"
width="90" />
+ <web_browser
+ follows="all"
+ layout="topleft"
+ left="0"
+ name="login_media_panel"
+ width="1024"
+ height="768"
+ top="0"/>
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_side_tray.xml b/indra/newview/skins/default/xui/en/panel_side_tray.xml
index 6ef93406ec..0f330a7b98 100644
--- a/indra/newview/skins/default/xui/en/panel_side_tray.xml
+++ b/indra/newview/skins/default/xui/en/panel_side_tray.xml
@@ -142,6 +142,7 @@
mouse_opaque="false"
background_visible="true"
>
+ <badge location="top_left" location_percent_vcenter="50" location_percent_hcenter="95" />
<panel
class="sidepanel_inventory"
name="sidepanel_inventory"
diff --git a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
index 8997c1a6d7..79a0ec7c72 100644
--- a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
+++ b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
@@ -9,7 +9,7 @@
min_width="240"
name="objects panel"
width="333">
- <panel
+ <panel
follows="all"
layout="topleft"
left="0"
@@ -19,24 +19,226 @@
height="570"
visible="true"
width="330">
- <panel
- class="panel_main_inventory"
- filename="panel_main_inventory.xml"
- follows="all"
- layout="topleft"
- left="0"
- name="panel_main_inventory"
- top="0"
- label=""
- height="545"
- width="330" />
+ <layout_stack
+ follows="left|right|top|bottom"
+ layout="topleft"
+ left="0"
+ top="0"
+ orientation="vertical"
+ name="inventory_layout_stack"
+ height="535"
+ width="330">
+ <layout_panel
+ name="main_inventory_layout_panel"
+ min_dim="150"
+ width="330"
+ follows="bottom|left|right"
+ user_resize="false"
+ height="480">
+ <panel
+ class="panel_main_inventory"
+ filename="panel_main_inventory.xml"
+ follows="all"
+ layout="topleft"
+ left="0"
+ name="panel_main_inventory"
+ top="0"
+ label=""
+ height="480"
+ width="330" />
+ </layout_panel>
+ <layout_panel
+ width="330"
+ auto_resize="true"
+ user_resize="false"
+ follows="bottom|left|right"
+ name="inbox_layout_panel"
+ visible="false"
+ min_dim="35"
+ max_dim="200"
+ expanded_min_dim="90"
+ height="200">
+ <panel
+ follows="all"
+ layout="topleft"
+ left="0"
+ name="marketplace_inbox"
+ class="panel_marketplace_inbox"
+ top="0"
+ label=""
+ height="200"
+ width="330">
+ <string name="InboxLabelWithArg">Received Items ([NUM])</string>
+ <string name="InboxLabelNoArg">Received Items</string>
+ <button
+ label="Received Items"
+ name="inbox_btn"
+ height="35"
+ width="308"
+ image_unselected="MarketplaceBtn_Off"
+ image_selected="MarketplaceBtn_Selected"
+ halign="left"
+ handle_right_mouse="false"
+ follows="top|left|right"
+ is_toggle="true"
+ tab_stop="false"
+ pad_left="35"
+ top="0"
+ left="10" />
+ <text
+ type="string"
+ length="1"
+ follows="right|top"
+ layout="topleft"
+ height="13"
+ top="10"
+ right="-20"
+ name="inbox_fresh_new_count"
+ font="SansSerifMedium"
+ halign="right"
+ text_color="EmphasisColor"
+ top_pad="0"
+ width="300">
+ [NUM] New
+ </text>
+ <panel
+ follows="all"
+ left="10"
+ bottom="200"
+ width="308"
+ top="35"
+ bg_opaque_color="InventoryBackgroundColor"
+ background_visible="true"
+ background_opaque="true"
+ tool_tip="Drag and drop items to your inventory to manage and use them"
+ >
+ <text
+ name="inbox_inventory_placeholder"
+ type="string"
+ follows="all"
+ layout="topleft"
+ top="0"
+ left="0"
+ width="308"
+ height="165"
+ wrap="true"
+ halign="center">
+ Purchases from the marketplace will be delivered here.
+ </text>
+ </panel>
+ </panel>
+ </layout_panel>
+ <layout_panel
+ width="330"
+ auto_resize="true"
+ user_resize="false"
+ follows="bottom|left|right"
+ name="outbox_layout_panel"
+ visible="false"
+ min_dim="35"
+ max_dim="200"
+ expanded_min_dim="90"
+ height="200">
+ <panel
+ follows="all"
+ layout="topleft"
+ left="10"
+ name="marketplace_outbox"
+ class="panel_marketplace_outbox"
+ top="0"
+ label=""
+ height="200"
+ width="310">
+ <button
+ label="Merchant Outbox"
+ is_toggle="true"
+ handle_right_mouse="false"
+ name="outbox_btn"
+ follows="top|left|right"
+ image_unselected="MarketplaceBtn_Off"
+ image_selected="MarketplaceBtn_Selected"
+ height="35"
+ tab_stop="false"
+ width="308"
+ halign="left"
+ pad_left="35"
+ top="0"
+ left="0" />
+ <button
+ image_unselected="OutboxPush_Off"
+ image_selected="OutboxPush_Selected"
+ image_hover_selected="OutboxPush_Selected_Over"
+ image_hover_unselected="OutboxPush_Over"
+ image_disabled_selected="OutboxPush_Selected_Disabled"
+ image_disabled="OutboxPush_Disabled"
+ image_pressed="OutboxPush_Press"
+ image_pressed_selected="OutboxPush_Selected_Press"
+ label=""
+ tool_tip="Push to my Marketplace Storefront"
+ is_toggle="false"
+ name="outbox_sync_btn"
+ follows="top|right"
+ tab_stop="false"
+ halign="center"
+ top="6"
+ left="-50"
+ height="23"
+ width="32"
+ enabled="false" />
+ <loading_indicator
+ follows="top|right"
+ name="outbox_sync_indicator"
+ top="6"
+ left="-50"
+ height="23"
+ width="32"
+ images_per_sec="1.15"
+ tab_stop="false"
+ visible="false">
+ <images>
+ <image name="OutboxPush_Progress_1"/>
+ <image name="OutboxPush_Progress_2"/>
+ <image name="OutboxPush_Progress_3"/>
+ <image name="OutboxPush_Progress_4"/>
+ <image name="OutboxPush_Progress_5"/>
+ <image name="OutboxPush_Progress_6"/>
+ </images>
+ </loading_indicator>
+ <panel
+ follows="all"
+ left="10"
+ bottom="200"
+ width="308"
+ top="35"
+ bg_opaque_color="InventoryBackgroundColor"
+ background_visible="true"
+ background_opaque="true"
+ tool_tip="Drag and drop items here to prepare them for sale on your storefront"
+ >
+ <text
+ name="outbox_inventory_placeholder"
+ type="string"
+ follows="all"
+ layout="topleft"
+ top="0"
+ left="0"
+ width="308"
+ height="165"
+ wrap="true"
+ halign="center">
+ Set up your merchant account to use this feature.
+ </text>
+ </panel>
+ </panel>
+ </layout_panel>
+ </layout_stack>
<panel
follows="bottom|left|right"
- height="25"
+ height="30"
layout="topleft"
name="button_panel"
left="9"
- top_pad="-2"
+ top_pad="7"
width="308">
<layout_stack
follows="bottom|left|right"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 09bff0a46c..def4079ba9 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2021,6 +2021,8 @@ Returns a string with the requested data about the region
<string name="PlacesNoMatchingItems">Didn't find what you're looking for? Try [secondlife:///app/search/places/[SEARCH_TERM] Search].</string>
<string name="FavoritesNoMatchingItems">Drag a landmark here to add it to your favorites.</string>
<string name="InventoryNoTexture">You do not have a copy of this texture in your inventory</string>
+ <string name="InventoryInboxNoItems">Items purchased through the marketplace will be delivered here.</string>
+ <string name="InventoryOutboxNoItems">Drag items here in preparation for listing on your marketplace storefront.</string>
<!-- use value="" because they have preceding spaces -->
<string name="no_transfer" value=" (no transfer)" />
<string name="no_modify" value=" (no modify)" />
diff --git a/indra/newview/skins/default/xui/en/widgets/badge.xml b/indra/newview/skins/default/xui/en/widgets/badge.xml
new file mode 100644
index 0000000000..f77c4b7178
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/badge.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- Additional attributes:
+ -->
+<badge border_image="Badge_Border"
+ border_color="BadgeBorderColor"
+ font="SansSerifSmall"
+ image="Badge_Background"
+ image_color="BadgeImageColor"
+ label_color="BadgeLabelColor"
+ location="top_left"
+ location_percent_hcenter="85"
+ location_percent_vcenter="85"
+ padding_horiz="7"
+ padding_vert="4"
+ requests_front="true"
+ >
+</badge>
diff --git a/indra/newview/skins/default/xui/en/widgets/button.xml b/indra/newview/skins/default/xui/en/widgets/button.xml
index 16241ed84e..302014eb24 100644
--- a/indra/newview/skins/default/xui/en/widgets/button.xml
+++ b/indra/newview/skins/default/xui/en/widgets/button.xml
@@ -25,5 +25,6 @@
pad_bottom="3"
height="23"
scale_image="true"
+ handle_right_mouse="true"
use_draw_context_alpha="true">
</button>
diff --git a/indra/newview/skins/default/xui/en/widgets/inbox_folder_view_folder.xml b/indra/newview/skins/default/xui/en/widgets/inbox_folder_view_folder.xml
new file mode 100644
index 0000000000..2c987b158d
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/inbox_folder_view_folder.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<inbox_folder_view_folder
+ folder_arrow_image="Folder_Arrow"
+ folder_indentation="8"
+ item_height="20"
+ item_top_pad="4"
+ selection_image="Rounded_Square"
+ >
+ <new_badge label="New" location="right" location_percent_hcenter="70" />
+</inbox_folder_view_folder>
diff --git a/indra/newview/skins/default/xui/en/widgets/inbox_inventory_panel.xml b/indra/newview/skins/default/xui/en/widgets/inbox_inventory_panel.xml
new file mode 100644
index 0000000000..830c27bdac
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/inbox_inventory_panel.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<inbox_inventory_panel show_load_status="false" />
diff --git a/indra/newview/skins/default/xui/en/widgets/inventory_panel.xml b/indra/newview/skins/default/xui/en/widgets/inventory_panel.xml
index 93875d66e6..00f4c43915 100644
--- a/indra/newview/skins/default/xui/en/widgets/inventory_panel.xml
+++ b/indra/newview/skins/default/xui/en/widgets/inventory_panel.xml
@@ -3,4 +3,12 @@
bg_opaque_color="InventoryBackgroundColor"
background_visible="true"
background_opaque="true"
- />
+ show_load_status="true"
+ >
+ <scroll
+ name="Inventory Scroller"
+ follows="all"
+ reserve_scroll_corner="true"
+ tab_stop="true"
+ />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/widgets/panel.xml b/indra/newview/skins/default/xui/en/widgets/panel.xml
index 9bf99fa363..47a210d9b7 100644
--- a/indra/newview/skins/default/xui/en/widgets/panel.xml
+++ b/indra/newview/skins/default/xui/en/widgets/panel.xml
@@ -10,4 +10,5 @@
bg_alpha_image_overlay="White"
background_visible="false"
background_opaque="false"
- chrome="false"/> \ No newline at end of file
+ chrome="false"
+ accepts_badge="true"/> \ No newline at end of file
diff --git a/indra/newview/skins/minimal/xui/en/floater_help_browser.xml b/indra/newview/skins/minimal/xui/en/floater_help_browser.xml
index cc551f7d58..477f210352 100644
--- a/indra/newview/skins/minimal/xui/en/floater_help_browser.xml
+++ b/indra/newview/skins/minimal/xui/en/floater_help_browser.xml
@@ -3,14 +3,13 @@
legacy_header_height="18"
can_resize="true"
can_minimize="false"
- height="360"
+ height="460"
layout="topleft"
min_height="360"
- left="645"
+ left="10000"
top="10"
- min_width="345"
+ min_width="335"
name="floater_help_browser"
- save_rect="true"
single_instance="true"
title="HOW TO"
width="335">
@@ -22,7 +21,7 @@
name="done_text">
</floater.string>
<layout_stack
- bottom="360"
+ bottom="460"
follows="left|right|top|bottom"
layout="topleft"
left="5"
@@ -38,7 +37,7 @@
user_resize="false"
width="325">
<web_browser
- trusted_content="true"
+ trusted_content="true"
bottom="-5"
follows="left|right|top|bottom"
layout="topleft"
diff --git a/indra/newview/skins/minimal/xui/en/floater_web_content.xml b/indra/newview/skins/minimal/xui/en/floater_web_content.xml
index 50cb5b14ce..1d9a967d5a 100644
--- a/indra/newview/skins/minimal/xui/en/floater_web_content.xml
+++ b/indra/newview/skins/minimal/xui/en/floater_web_content.xml
@@ -17,6 +17,7 @@
follows="left|right|top|bottom"
layout="topleft"
left="5"
+ animate="false"
name="stack1"
orientation="vertical"
top="20"
@@ -155,14 +156,20 @@
name="external_controls"
top_delta="0"
user_resize="false"
+ auto_resize="true"
width="585">
<web_browser
- bottom="-22"
+ bottom="-2"
follows="all"
layout="topleft"
left="0"
name="webbrowser"
top="0"/>
+ </layout_panel>
+ <layout_panel name="status_bar"
+ height="23"
+ auto_resize="false"
+ user_resize="false">
<text
type="string"
length="200"
@@ -173,7 +180,7 @@
name="statusbartext"
parse_urls="false"
text_color="0.4 0.4 0.4 1"
- top_pad="5"
+ top_pad="3"
width="495"/>
<progress_bar
color_bar="0.3 1.0 0.3 1"
diff --git a/indra/newview/skins/minimal/xui/en/panel_im_control_panel.xml b/indra/newview/skins/minimal/xui/en/panel_im_control_panel.xml
index be13bc1bb7..2cb77bcdf3 100644
--- a/indra/newview/skins/minimal/xui/en/panel_im_control_panel.xml
+++ b/indra/newview/skins/minimal/xui/en/panel_im_control_panel.xml
@@ -23,102 +23,172 @@
orientation="vertical"
top_pad="5"
width="145">
- <layout_panel
- auto_resize="false"
- follows="top|left|right"
- height="20"
- layout="topleft"
- left="2"
- min_height="20"
- width="140"
- name="view_profile_btn_panel"
- top="0"
- user_resize="false">
- <button
- follows="left|top|right"
- height="23"
- label="Profile"
- name="view_profile_btn"
+ <layout_panel
+ auto_resize="false"
+ follows="top|left|right"
+ height="20"
+ layout="topleft"
+ left="2"
+ min_height="20"
+ width="140"
+ name="view_profile_btn_panel"
top="0"
- width="140" />
- </layout_panel>
- <layout_panel
- auto_resize="false"
- follows="top|left|right"
- height="25"
- layout="topleft"
- min_height="25"
- width="140"
- name="add_friend_btn_panel"
- user_resize="false">
- <button
- follows="left|top|right"
- height="23"
- label="Add Friend"
- name="add_friend_btn"
- top="5"
- width="140" />
- </layout_panel>
- <layout_panel
- auto_resize="false"
- follows="top|left|right"
- height="25"
- layout="topleft"
- min_height="25"
- width="140"
- name="teleport_btn_panel"
- user_resize="false">
- <button
- auto_resize="false"
+ user_resize="false">
+ <button
+ follows="left|top|right"
+ height="23"
+ label="Profile"
+ name="view_profile_btn"
+ top="0"
+ width="140" />
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ follows="top|left|right"
+ height="25"
+ layout="topleft"
+ min_height="25"
+ width="140"
+ name="add_friend_btn_panel"
+ user_resize="false">
+ <button
follows="left|top|right"
height="23"
- label="Teleport"
- name="teleport_btn"
- tool_tip = "Offer to teleport this person"
+ label="Add Friend"
+ name="add_friend_btn"
+ top="5"
width="140" />
- </layout_panel>
- <layout_panel
+ </layout_panel>
+ <layout_panel
auto_resize="false"
follows="top|left|right"
height="25"
layout="topleft"
min_height="25"
width="140"
- name="call_btn_panel"
+ name="teleport_btn_panel"
user_resize="false">
- <button
- follows="left|top|right"
- height="23"
- label="Call"
- name="call_btn"
- width="140" />
- </layout_panel>
- <layout_panel
- auto_resize="false"
- follows="top|left|right"
- height="25"
- layout="topleft"
- min_height="25"
- width="140"
- name="end_call_btn_panel"
- user_resize="false"
- visible="false">
- <button
- follows="left|top|right"
- height="23"
- label="End Call"
- name="end_call_btn"
- width="140" />
- </layout_panel>
- <layout_panel
- mouse_opaque="false"
- auto_resize="true"
- follows="top|left"
- height="0"
- layout="topleft"
- min_height="0"
- width="140"
- name="spacer"
- user_resize="false" />
+ <button
+ auto_resize="false"
+ follows="left|top|right"
+ height="23"
+ label="Teleport"
+ name="teleport_btn"
+ tool_tip = "Offer to teleport this person"
+ width="140" />
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ follows="top|left|right"
+ height="25"
+ layout="topleft"
+ min_height="25"
+ width="140"
+ name="call_btn_panel"
+ user_resize="false">
+ <button
+ follows="left|top|right"
+ height="23"
+ label="Call"
+ name="call_btn"
+ width="140" />
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ follows="top|left|right"
+ height="25"
+ layout="topleft"
+ min_height="25"
+ width="140"
+ name="end_call_btn_panel"
+ user_resize="false"
+ visible="false">
+ <button
+ follows="left|top|right"
+ height="23"
+ label="End Call"
+ name="end_call_btn"
+ width="140" />
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ follows="top|left|right"
+ height="25"
+ layout="topleft"
+ min_height="25"
+ width="140"
+ name="block_btn_panel"
+ user_resize="false">
+ <button
+ follows="left|top|right"
+ height="23"
+ label="Block"
+ name="block_btn"
+ width="140" />
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ follows="top|left|right"
+ height="25"
+ layout="topleft"
+ min_height="25"
+ width="140"
+ name="unblock_btn_panel"
+ user_resize="false"
+ visible="false">
+ <button
+ follows="left|top|right"
+ height="23"
+ label="Unblock"
+ name="unblock_btn"
+ width="140" />
+ </layout_panel>
+ <layout_panel
+ auto_resize="false"
+ follows="top|left|right"
+ height="25"
+ layout="topleft"
+ min_height="54"
+ width="140"
+ name="volume_ctrl_panel"
+ visible="false"
+ user_resize="false">
+ <slider
+ follows="top|left"
+ height="23"
+ increment="0.01"
+ left="0"
+ max_val="0.95"
+ min_val="0.05"
+ name="volume_slider"
+ show_text="false"
+ tool_tip="Call Volume"
+ top_pad="32"
+ value="0.5"
+ width="125" />
+ <button
+ follows="top|left"
+ height="16"
+ image_disabled="Audio_Off"
+ image_disabled_selected="AudioMute_Off"
+ image_hover_selected="AudioMute_Over"
+ image_selected="AudioMute_Off"
+ image_unselected="Audio_Off"
+ is_toggle="true"
+ left_pad="0"
+ top_delta="4"
+ name="mute_btn"
+ width="16" />
+ </layout_panel>
+ <layout_panel
+ mouse_opaque="false"
+ auto_resize="true"
+ follows="top|left"
+ height="0"
+ layout="topleft"
+ min_height="0"
+ width="140"
+ name="spacer"
+ user_resize="false" />
</layout_stack>
</panel>