diff options
Diffstat (limited to 'indra')
145 files changed, 6107 insertions, 2867 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..e8a2d5539b 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  			{ @@ -1927,8 +1926,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 +2033,7 @@ void LLFolderView::removeItemID(const LLUUID& id)  LLFolderViewItem* LLFolderView::getItemByID(const LLUUID& id)  { -	if (id.isNull()) +	if (id == getListener()->getUUID())  	{  		return this;  	} @@ -2048,7 +2050,7 @@ LLFolderViewItem* LLFolderView::getItemByID(const LLUUID& id)  LLFolderViewFolder* LLFolderView::getFolderByID(const LLUUID& id)  { -	if (id.isNull()) +	if (id == getListener()->getUUID())  	{  		return this;  	} @@ -2173,7 +2175,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 +2185,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 +2498,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..e15365cf52 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());  	} @@ -1467,6 +1486,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 +1532,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 +1804,7 @@ void LLFolderViewFolder::destroyView()  		folderp->destroyView(); // removes entry from mFolders  	} -	deleteAllChildren(); +	//deleteAllChildren();  	if (mParentFolder)  	{ @@ -1843,8 +1904,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 +2046,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 +2072,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 +2138,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 +2382,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 +2414,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 +2692,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..6a3a6200e9 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,262 @@ 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); +	} +} + +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 +534,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 +695,28 @@ bool LLSidepanelInventory::canShare()  	LLPanelMainInventory* panel_main_inventory =  		mInventoryPanel->findChild<LLPanelMainInventory>("panel_main_inventory"); -	if (!panel_main_inventory) -	{ -		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); +	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()) )
 +	{
 +		return false;
 +	}
 + +	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 +729,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 +751,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 Binary files differnew file mode 100644 index 0000000000..5afe85d72d --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Inv_Gift.png diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Disabled.png b/indra/newview/skins/default/textures/icons/OutboxPush_Disabled.png Binary files differnew file mode 100644 index 0000000000..be58114aa1 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/OutboxPush_Disabled.png diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Off.png b/indra/newview/skins/default/textures/icons/OutboxPush_Off.png Binary files differnew file mode 100644 index 0000000000..e6b9480ab1 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/OutboxPush_Off.png diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_On.png b/indra/newview/skins/default/textures/icons/OutboxPush_On.png Binary files differnew file mode 100644 index 0000000000..ffda2e92d4 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/OutboxPush_On.png diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_On_Over.png b/indra/newview/skins/default/textures/icons/OutboxPush_On_Over.png Binary files differnew file mode 100644 index 0000000000..6b5911014f --- /dev/null +++ b/indra/newview/skins/default/textures/icons/OutboxPush_On_Over.png diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_On_Selected.png b/indra/newview/skins/default/textures/icons/OutboxPush_On_Selected.png Binary files differnew file mode 100644 index 0000000000..0e60b417b0 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/OutboxPush_On_Selected.png diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Over.png b/indra/newview/skins/default/textures/icons/OutboxPush_Over.png Binary files differnew file mode 100644 index 0000000000..9c26b92e73 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/OutboxPush_Over.png diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Press.png b/indra/newview/skins/default/textures/icons/OutboxPush_Press.png Binary files differnew file mode 100644 index 0000000000..3b5d462975 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/OutboxPush_Press.png diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_1.png b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_1.png Binary files differnew file mode 100644 index 0000000000..f85be047b0 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_1.png diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_2.png b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_2.png Binary files differnew file mode 100644 index 0000000000..cd4e482216 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_2.png diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_3.png b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_3.png Binary files differnew file mode 100644 index 0000000000..d212a871ce --- /dev/null +++ b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_3.png diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_4.png b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_4.png Binary files differnew file mode 100644 index 0000000000..e5b6023e36 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_4.png diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_5.png b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_5.png Binary files differnew file mode 100644 index 0000000000..e1911a092f --- /dev/null +++ b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_5.png diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_6.png b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_6.png Binary files differnew file mode 100644 index 0000000000..9e59f7843a --- /dev/null +++ b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_6.png diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Selected.png b/indra/newview/skins/default/textures/icons/OutboxPush_Selected.png Binary files differnew file mode 100644 index 0000000000..51e8bff646 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/OutboxPush_Selected.png diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Disabled.png b/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Disabled.png Binary files differnew file mode 100644 index 0000000000..300e2e69e1 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Disabled.png diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Over.png b/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Over.png Binary files differnew file mode 100644 index 0000000000..32fb236381 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Over.png diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Press.png b/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Press.png Binary files differnew file mode 100644 index 0000000000..827f343b1e --- /dev/null +++ b/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Press.png diff --git a/indra/newview/skins/default/textures/icons/Sync_Disabled.png b/indra/newview/skins/default/textures/icons/Sync_Disabled.png Binary files differnew file mode 100644 index 0000000000..ca2e8def97 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Sync_Disabled.png diff --git a/indra/newview/skins/default/textures/icons/Sync_Enabled.png b/indra/newview/skins/default/textures/icons/Sync_Enabled.png Binary files differnew file mode 100644 index 0000000000..bc236c8b98 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Sync_Enabled.png diff --git a/indra/newview/skins/default/textures/icons/Sync_Progress_1.png b/indra/newview/skins/default/textures/icons/Sync_Progress_1.png Binary files differnew file mode 100644 index 0000000000..624e556376 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Sync_Progress_1.png diff --git a/indra/newview/skins/default/textures/icons/Sync_Progress_2.png b/indra/newview/skins/default/textures/icons/Sync_Progress_2.png Binary files differnew file mode 100644 index 0000000000..5769803b3f --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Sync_Progress_2.png diff --git a/indra/newview/skins/default/textures/icons/Sync_Progress_3.png b/indra/newview/skins/default/textures/icons/Sync_Progress_3.png Binary files differnew file mode 100644 index 0000000000..92d4bfb020 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Sync_Progress_3.png diff --git a/indra/newview/skins/default/textures/icons/Sync_Progress_4.png b/indra/newview/skins/default/textures/icons/Sync_Progress_4.png Binary files differnew file mode 100644 index 0000000000..6d43eb3a9f --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Sync_Progress_4.png diff --git a/indra/newview/skins/default/textures/icons/Sync_Progress_5.png b/indra/newview/skins/default/textures/icons/Sync_Progress_5.png Binary files differnew file mode 100644 index 0000000000..766d063c99 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Sync_Progress_5.png diff --git a/indra/newview/skins/default/textures/icons/Sync_Progress_6.png b/indra/newview/skins/default/textures/icons/Sync_Progress_6.png Binary files differnew file mode 100644 index 0000000000..dfe7f68b72 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Sync_Progress_6.png 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 Binary files differnew file mode 100644 index 0000000000..5089c30312 --- /dev/null +++ b/indra/newview/skins/default/textures/widgets/Badge_Background.png diff --git a/indra/newview/skins/default/textures/widgets/Badge_Border.png b/indra/newview/skins/default/textures/widgets/Badge_Border.png Binary files differnew file mode 100644 index 0000000000..4b086a63fb --- /dev/null +++ b/indra/newview/skins/default/textures/widgets/Badge_Border.png diff --git a/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Off.png b/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Off.png Binary files differnew file mode 100644 index 0000000000..e603c44384 --- /dev/null +++ b/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Off.png diff --git a/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Selected.png b/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Selected.png Binary files differnew file mode 100644 index 0000000000..fbc164123f --- /dev/null +++ b/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Selected.png 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>  | 
