diff options
Diffstat (limited to 'indra')
128 files changed, 3645 insertions, 1687 deletions
| diff --git a/indra/integration_tests/llui_libtest/llui_libtest.cpp b/indra/integration_tests/llui_libtest/llui_libtest.cpp index e0117eca06..54fc167adf 100644 --- a/indra/integration_tests/llui_libtest/llui_libtest.cpp +++ b/indra/integration_tests/llui_libtest/llui_libtest.cpp @@ -41,6 +41,7 @@  #include "lldir.h"  #include "llerrorcontrol.h"  #include "llfloater.h" +#include "llfontfreetype.h"  #include "llfontgl.h"  #include "lltrans.h"  #include "llui.h" diff --git a/indra/integration_tests/llui_libtest/llwidgetreg.cpp b/indra/integration_tests/llui_libtest/llwidgetreg.cpp index 4e59971f29..5a97f2aefd 100644 --- a/indra/integration_tests/llui_libtest/llwidgetreg.cpp +++ b/indra/integration_tests/llui_libtest/llwidgetreg.cpp @@ -42,6 +42,7 @@  #include "llmultisliderctrl.h"  #include "llprogressbar.h"  #include "llradiogroup.h" +#include "llsearcheditor.h"  #include "llscrollcontainer.h"  #include "llscrollingpanellist.h"  #include "llscrolllistctrl.h" @@ -53,7 +54,7 @@  #include "lltextbox.h"  #include "lltexteditor.h"  #include "llflyoutbutton.h" -#include "llsearcheditor.h" +#include "llfiltereditor.h"  #include "lllayoutstack.h"  void LLWidgetReg::initClass(bool register_widgets) @@ -65,11 +66,11 @@ void LLWidgetReg::initClass(bool register_widgets)  		LLDefaultChildRegistry::Register<LLButton> button("button");  		LLDefaultChildRegistry::Register<LLCheckBoxCtrl> check_box("check_box");  		LLDefaultChildRegistry::Register<LLComboBox> combo_box("combo_box"); +		LLDefaultChildRegistry::Register<LLFilterEditor> filter_editor("filter_editor");  		LLDefaultChildRegistry::Register<LLFlyoutButton> flyout_button("flyout_button");  		LLDefaultChildRegistry::Register<LLContainerView> container_view("container_view");  		LLDefaultChildRegistry::Register<LLIconCtrl> icon("icon");  		LLDefaultChildRegistry::Register<LLLineEditor> line_editor("line_editor"); -		LLDefaultChildRegistry::Register<LLSearchEditor> search_editor("search_editor");  		LLDefaultChildRegistry::Register<LLMenuItemSeparatorGL> menu_item_separator("menu_item_separator");  		LLDefaultChildRegistry::Register<LLMenuItemCallGL> menu_item_call_gl("menu_item_call");  		LLDefaultChildRegistry::Register<LLMenuItemCheckGL> menu_item_check_gl("menu_item_check"); @@ -83,6 +84,7 @@ void LLWidgetReg::initClass(bool register_widgets)  		LLDefaultChildRegistry::Register<LLProgressBar> progress_bar("progress_bar");  		LLDefaultChildRegistry::Register<LLRadioGroup> radio_group("radio_group");  		LLDefaultChildRegistry::Register<LLRadioCtrl> radio_item("radio_item"); +		LLDefaultChildRegistry::Register<LLSearchEditor> search_editor("search_editor");  		LLDefaultChildRegistry::Register<LLScrollContainer> scroll_container("scroll_container");  		LLDefaultChildRegistry::Register<LLScrollingPanelList> scrolling_panel_list("scrolling_panel_list");  		LLDefaultChildRegistry::Register<LLScrollListCtrl> scroll_list("scroll_list"); diff --git a/indra/llrender/CMakeLists.txt b/indra/llrender/CMakeLists.txt index 0e0fc6ce6c..aac650bec9 100644 --- a/indra/llrender/CMakeLists.txt +++ b/indra/llrender/CMakeLists.txt @@ -26,7 +26,7 @@ include_directories(  set(llrender_SOURCE_FILES      llcubemap.cpp -    llfont.cpp +    llfontfreetype.cpp      llfontgl.cpp      llfontbitmapcache.cpp      llfontregistry.cpp @@ -45,7 +45,7 @@ set(llrender_HEADER_FILES      llcubemap.h      llfontgl.h -    llfont.h +    llfontfreetype.h      llfontbitmapcache.h      llfontregistry.h      llgl.h diff --git a/indra/llrender/llfontbitmapcache.h b/indra/llrender/llfontbitmapcache.h index 4beea0d026..4a57052b91 100644 --- a/indra/llrender/llfontbitmapcache.h +++ b/indra/llrender/llfontbitmapcache.h @@ -36,7 +36,7 @@  #include <vector>  // Maintain a collection of bitmaps containing rendered glyphs. -// Generalizes the single-bitmap logic from LLFont and LLFontGL. +// Generalizes the single-bitmap logic from LLFontFreetype and LLFontGL.  class LLFontBitmapCache: public LLRefCount  {  public: diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp new file mode 100644 index 0000000000..91a95cdd25 --- /dev/null +++ b/indra/llrender/llfontfreetype.cpp @@ -0,0 +1,630 @@ +/**  + * @file llfontfreetype.cpp + * @brief Freetype font library wrapper + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + *  + * Copyright (c) 2002-2009, Linden Research, Inc. + *  + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + *  + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + *  + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + *  + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llfontfreetype.h" + +// Freetype stuff +#include <ft2build.h> + +// For some reason, this won't work if it's not wrapped in the ifdef +#ifdef FT_FREETYPE_H +#include FT_FREETYPE_H +#endif + +#include "llerror.h" +#include "llimage.h" +//#include "llimagej2c.h" +#include "llmath.h"	// Linden math +#include "llstring.h" +//#include "imdebug.h" +#include "llfontbitmapcache.h" +#include "llgl.h" + +FT_Render_Mode gFontRenderMode = FT_RENDER_MODE_NORMAL; + +LLFontManager *gFontManagerp = NULL; + +FT_Library gFTLibrary = NULL; + +//static +void LLFontManager::initClass() +{ +	gFontManagerp = new LLFontManager; +} + +//static +void LLFontManager::cleanupClass() +{ +	delete gFontManagerp; +	gFontManagerp = NULL; +} + +LLFontManager::LLFontManager() +{ +	int error; +	error = FT_Init_FreeType(&gFTLibrary); +	if (error) +	{ +		// Clean up freetype libs. +		llerrs << "Freetype initialization failure!" << llendl; +		FT_Done_FreeType(gFTLibrary); +	} +} + +LLFontManager::~LLFontManager() +{ +	FT_Done_FreeType(gFTLibrary); +} + + +LLFontGlyphInfo::LLFontGlyphInfo(U32 index) +:	mGlyphIndex(index), +	mXBitmapOffset(0), 	// Offset to the origin in the bitmap +	mYBitmapOffset(0), 	// Offset to the origin in the bitmap +	mXBearing(0),		// Distance from baseline to left in pixels +	mYBearing(0),		// Distance from baseline to top in pixels +	mWidth(0),			// In pixels +	mHeight(0),			// In pixels +	mXAdvance(0.f),		// In pixels +	mYAdvance(0.f),		// In pixels +	mIsRendered(FALSE), +	mMetricsValid(FALSE) +{ +} + +LLFontFreetype::LLFontFreetype() +:	mFontBitmapCachep(new LLFontBitmapCache), +	mValid(FALSE), +	mAscender(0.f), +	mDescender(0.f), +	mLineHeight(0.f), +	mIsFallback(FALSE), +	mFTFace(NULL), +	mRenderGlyphCount(0), +	mAddGlyphCount(0), +	mPointSize(0) +{ +} + + +LLFontFreetype::~LLFontFreetype() +{ +	// Clean up freetype libs. +	if (mFTFace) +		FT_Done_Face(mFTFace); +	mFTFace = NULL; + +	// Delete glyph info +	std::for_each(mCharGlyphInfoMap.begin(), mCharGlyphInfoMap.end(), DeletePairedPointer()); + +	// mFontBitmapCachep will be cleaned up by LLPointer destructor. +	// mFallbackFonts cleaned up by LLPointer destructor +} + +BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 components, BOOL is_fallback) +{ +	// Don't leak face objects.  This is also needed to deal with +	// changed font file names. +	if (mFTFace) +	{ +		FT_Done_Face(mFTFace); +		mFTFace = NULL; +	} + +	int error; + +	error = FT_New_Face( gFTLibrary, +						 filename.c_str(), +						 0, +						 &mFTFace ); + +    if (error) +	{ +		return FALSE; +	} + +	mIsFallback = is_fallback; +	F32 pixels_per_em = (point_size / 72.f)*vert_dpi; // Size in inches * dpi + +	error = FT_Set_Char_Size(mFTFace,    /* handle to face object           */ +							0,       /* char_width in 1/64th of points  */ +							(S32)(point_size*64),   /* char_height in 1/64th of points */ +							(U32)horz_dpi,     /* horizontal device resolution    */ +							(U32)vert_dpi);   /* vertical device resolution      */ + +	if (error) +	{ +		// Clean up freetype libs. +		FT_Done_Face(mFTFace); +		mFTFace = NULL; +		return FALSE; +	} + +	F32 y_max, y_min, x_max, x_min; +	F32 ems_per_unit = 1.f/ mFTFace->units_per_EM; +	F32 pixels_per_unit = pixels_per_em * ems_per_unit; + +	// Get size of bbox in pixels +	y_max = mFTFace->bbox.yMax * pixels_per_unit; +	y_min = mFTFace->bbox.yMin * pixels_per_unit; +	x_max = mFTFace->bbox.xMax * pixels_per_unit; +	x_min = mFTFace->bbox.xMin * pixels_per_unit; +	mAscender = mFTFace->ascender * pixels_per_unit; +	mDescender = -mFTFace->descender * pixels_per_unit; +	mLineHeight = mFTFace->height * pixels_per_unit; + +	S32 max_char_width = llround(0.5f + (x_max - x_min)); +	S32 max_char_height = llround(0.5f + (y_max - y_min)); + +	mFontBitmapCachep->init(components, max_char_width, max_char_height); + +	if (!mFTFace->charmap) +	{ +		//llinfos << " no unicode encoding, set whatever encoding there is..." << llendl; +		FT_Set_Charmap(mFTFace, mFTFace->charmaps[0]); +	} + +	if (!mIsFallback) +	{ +		// Add the default glyph +		addGlyph(0, 0); +	} + +	mName = filename; +	mPointSize = point_size; + +	return TRUE; +} + +void LLFontFreetype::setFallbackFonts(const font_vector_t &font) +{ +	mFallbackFonts = font; +} + +const LLFontFreetype::font_vector_t &LLFontFreetype::getFallbackFonts() const +{ +	return mFallbackFonts; +} + +F32 LLFontFreetype::getLineHeight() const +{ +	return mLineHeight; +} + +F32 LLFontFreetype::getAscenderHeight() const +{ +	return mAscender; +} + +F32 LLFontFreetype::getDescenderHeight() const +{ +	return mDescender; +} + +F32 LLFontFreetype::getXAdvance(llwchar wch) const +{ +	if (mFTFace == NULL) +		return 0.0; + +	llassert(!mIsFallback); +	U32 glyph_index; + +	// Return existing info only if it is current +	LLFontGlyphInfo* gi = getGlyphInfo(wch); +	if (gi && gi->mMetricsValid) +	{ +		return gi->mXAdvance; +	} + +	const LLFontFreetype* fontp = this; +	 +	// Initialize char to glyph map +	glyph_index = FT_Get_Char_Index(mFTFace, wch); +	if (glyph_index == 0) +	{ +		font_vector_t::const_iterator iter; +		for(iter = mFallbackFonts.begin(); (iter != mFallbackFonts.end()) && (glyph_index == 0); iter++) +		{ +			glyph_index = FT_Get_Char_Index((*iter)->mFTFace, wch); +			if(glyph_index) +			{ +				fontp = *iter; +			} +		} +	} +	 +	if (glyph_index) +	{ +		// This font has this glyph +		fontp->renderGlyph(glyph_index); + +		// Create the entry if it's not there +		char_glyph_info_map_t::iterator iter2 = mCharGlyphInfoMap.find(wch); +		if (iter2 == mCharGlyphInfoMap.end()) +		{ +			gi = new LLFontGlyphInfo(glyph_index); +			insertGlyphInfo(wch, gi); +		} +		else +		{ +			gi = iter2->second; +		} +		 +		gi->mWidth = fontp->mFTFace->glyph->bitmap.width; +		gi->mHeight = fontp->mFTFace->glyph->bitmap.rows; + +		// Convert these from 26.6 units to float pixels. +		gi->mXAdvance = fontp->mFTFace->glyph->advance.x / 64.f; +		gi->mYAdvance = fontp->mFTFace->glyph->advance.y / 64.f; +		gi->mMetricsValid = TRUE; +		return gi->mXAdvance; +	} +	else +	{ +		gi = get_if_there(mCharGlyphInfoMap, (llwchar)0, (LLFontGlyphInfo*)NULL); +		if (gi) +		{ +			return gi->mXAdvance; +		} +	} + +	// Last ditch fallback - no glyphs defined at all. +	return (F32)mFontBitmapCachep->getMaxCharWidth(); +} + +F32 LLFontFreetype::getXKerning(llwchar char_left, llwchar char_right) const +{ +	if (mFTFace == NULL) +		return 0.0; + +	llassert(!mIsFallback); +	LLFontGlyphInfo* left_glyph_info = get_if_there(mCharGlyphInfoMap, char_left, (LLFontGlyphInfo*)NULL); +	U32 left_glyph = left_glyph_info ? left_glyph_info->mGlyphIndex : 0; +	// Kern this puppy. +	LLFontGlyphInfo* right_glyph_info = get_if_there(mCharGlyphInfoMap, char_right, (LLFontGlyphInfo*)NULL); +	U32 right_glyph = right_glyph_info ? right_glyph_info->mGlyphIndex : 0; + +	FT_Vector  delta; + +	llverify(!FT_Get_Kerning(mFTFace, left_glyph, right_glyph, ft_kerning_unfitted, &delta)); + +	return delta.x*(1.f/64.f); +} + +BOOL LLFontFreetype::hasGlyph(llwchar wch) const +{ +	llassert(!mIsFallback); +	const LLFontGlyphInfo* gi = getGlyphInfo(wch); +	if (gi && gi->mIsRendered) +	{ +		return TRUE; +	} +	else +	{ +		return FALSE; +	} +} + +BOOL LLFontFreetype::addChar(llwchar wch) const +{ +	if (mFTFace == NULL) +		return FALSE; + +	llassert(!mIsFallback); +	//lldebugs << "Adding new glyph for " << wch << " to font" << llendl; + +	FT_UInt glyph_index; + +	// Initialize char to glyph map +	glyph_index = FT_Get_Char_Index(mFTFace, wch); +	if (glyph_index == 0) +	{ +		//llinfos << "Trying to add glyph from fallback font!" << llendl +		font_vector_t::const_iterator iter; +		for(iter = mFallbackFonts.begin(); iter != mFallbackFonts.end(); iter++) +		{ +			glyph_index = FT_Get_Char_Index((*iter)->mFTFace, wch); +			if (glyph_index) +			{ +				addGlyphFromFont(*iter, wch, glyph_index); +				return TRUE; +			} +		} +	} +	 +	char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.find(wch); +	if (iter == mCharGlyphInfoMap.end() || !(iter->second->mIsRendered)) +	{ +		BOOL result = addGlyph(wch, glyph_index); +		return result; +	} +	return FALSE; +} + +BOOL LLFontFreetype::addGlyph(llwchar wch, U32 glyph_index) const +{ +	return addGlyphFromFont(this, wch, glyph_index); +} + +BOOL LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index) const +{ +	if (mFTFace == NULL) +		return FALSE; + +	llassert(!mIsFallback); +	fontp->renderGlyph(glyph_index); +	S32 width = fontp->mFTFace->glyph->bitmap.width; +	S32 height = fontp->mFTFace->glyph->bitmap.rows; + +	S32 pos_x, pos_y; +	S32 bitmap_num; +	mFontBitmapCachep->nextOpenPos(width, pos_x, pos_y, bitmap_num); +	mAddGlyphCount++; + +	LLFontGlyphInfo* gi = new LLFontGlyphInfo(glyph_index); +	gi->mXBitmapOffset = pos_x; +	gi->mYBitmapOffset = pos_y; +	gi->mBitmapNum = bitmap_num; +	gi->mWidth = width; +	gi->mHeight = height; +	gi->mXBearing = fontp->mFTFace->glyph->bitmap_left; +	gi->mYBearing = fontp->mFTFace->glyph->bitmap_top; +	// Convert these from 26.6 units to float pixels. +	gi->mXAdvance = fontp->mFTFace->glyph->advance.x / 64.f; +	gi->mYAdvance = fontp->mFTFace->glyph->advance.y / 64.f; +	gi->mIsRendered = TRUE; +	gi->mMetricsValid = TRUE; + +	insertGlyphInfo(wch, gi); + +	llassert(fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO +	    || fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY); + +	if (fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO +	    || fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY) +	{ +		U8 *buffer_data = fontp->mFTFace->glyph->bitmap.buffer; +		S32 buffer_row_stride = fontp->mFTFace->glyph->bitmap.pitch; +		U8 *tmp_graydata = NULL; + +		if (fontp->mFTFace->glyph->bitmap.pixel_mode +		    == FT_PIXEL_MODE_MONO) +		{ +			// need to expand 1-bit bitmap to 8-bit graymap. +			tmp_graydata = new U8[width * height]; +			S32 xpos, ypos; +			for (ypos = 0; ypos < height; ++ypos) +			{ +				S32 bm_row_offset = buffer_row_stride * ypos; +				for (xpos = 0; xpos < width; ++xpos) +				{ +					U32 bm_col_offsetbyte = xpos / 8; +					U32 bm_col_offsetbit = 7 - (xpos % 8); +					U32 bit = +					!!(buffer_data[bm_row_offset +						       + bm_col_offsetbyte +					   ] & (1 << bm_col_offsetbit) ); +					tmp_graydata[width*ypos + xpos] = +						255 * bit; +				} +			} +			// use newly-built graymap. +			buffer_data = tmp_graydata; +			buffer_row_stride = width; +		} + +		switch (mFontBitmapCachep->getNumComponents()) +		{ +		case 1: +			mFontBitmapCachep->getImageRaw(bitmap_num)->setSubImage(pos_x, +																	pos_y, +																	width, +																	height, +																	buffer_data, +																	buffer_row_stride, +																	TRUE); +			break; +		case 2: +			setSubImageLuminanceAlpha(pos_x,	 +									  pos_y, +									  bitmap_num, +									  width, +									  height, +									  buffer_data, +									  buffer_row_stride); +			break; +		default: +			break; +		} + +		if (tmp_graydata) +			delete[] tmp_graydata; +	} else { +		// we don't know how to handle this pixel format from FreeType; +		// omit it from the font-image. +	} +	 +	return TRUE; +} + +LLFontGlyphInfo* LLFontFreetype::getGlyphInfo(llwchar wch) const +{ +	char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.find(wch); +	if (iter != mCharGlyphInfoMap.end()) +	{ +		return iter->second; +	} +	return NULL; +} + +void LLFontFreetype::insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const +{ +	char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.find(wch); +	if (iter != mCharGlyphInfoMap.end()) +	{ +		delete iter->second; +		iter->second = gi; +	} +	else +	{ +		mCharGlyphInfoMap[wch] = gi; +	} +} + +void LLFontFreetype::renderGlyph(U32 glyph_index) const +{ +	if (mFTFace == NULL) +		return; + +	int error = FT_Load_Glyph(mFTFace, glyph_index, FT_LOAD_DEFAULT ); +	llassert(!error); + +	error = FT_Render_Glyph(mFTFace->glyph, gFontRenderMode); + +	mRenderGlyphCount++; +	 +	llassert(!error); +} + +void LLFontFreetype::reset(F32 vert_dpi, F32 horz_dpi) +{ +	if (!mIsFallback) +	{ +		// This is the head of the list - need to rebuild ourself and all fallbacks. +		loadFace(mName, mPointSize, vert_dpi ,horz_dpi, mFontBitmapCachep->getNumComponents(), mIsFallback); + +		if (mFallbackFonts.empty()) +		{ +			llwarns << "LLFontGL::reset(), no fallback fonts present" << llendl; +		} +		else +		{ +			for(font_vector_t::iterator it = mFallbackFonts.begin(); +				it != mFallbackFonts.end(); +				++it) +			{ +				(*it)->reset(vert_dpi, horz_dpi); +			} +		} +	} +	resetBitmapCache();  +} + +void LLFontFreetype::resetBitmapCache() +{ +	// Iterate through glyphs and clear the mIsRendered flag +	for (char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.begin(); +		 iter != mCharGlyphInfoMap.end(); ++iter) +	{ +		iter->second->mIsRendered = FALSE; +		//FIXME: this is only strictly necessary when resetting the entire font,  +		//not just flushing the bitmap +		iter->second->mMetricsValid = FALSE; +	} +	mFontBitmapCachep->reset(); + +	// Add the empty glyph`5 +	addGlyph(0, 0); +} + +void LLFontFreetype::destroyGL() +{ +	mFontBitmapCachep->destroyGL(); +} + +BOOL LLFontFreetype::getIsFallback() const +{ +	return mIsFallback; +} + +const std::string &LLFontFreetype::getName() const +{ +	return mName; +} + +F32 LLFontFreetype::getPointSize() const +{ +	return mPointSize; +} + +const LLPointer<LLFontBitmapCache> LLFontFreetype::getFontBitmapCache() const +{ +	return mFontBitmapCachep; +} + +void LLFontFreetype::setStyle(U8 style) +{ +	mStyle = style; +} + +U8 LLFontFreetype::getStyle() const +{ +	return mStyle; +} + +void LLFontFreetype::setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32 width, U32 height, U8 *data, S32 stride) const +{ +	LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_num); + +	llassert(!mIsFallback); +	llassert(image_raw && (image_raw->getComponents() == 2)); + +	 +	U8 *target = image_raw->getData(); + +	if (!data) +	{ +		return; +	} + +	if (0 == stride) +		stride = width; + +	U32 i, j; +	U32 to_offset; +	U32 from_offset; +	U32 target_width = image_raw->getWidth(); +	for (i = 0; i < height; i++) +	{ +		to_offset = (y + i)*target_width + x; +		from_offset = (height - 1 - i)*stride; +		for (j = 0; j < width; j++) +		{ +			*(target + to_offset*2 + 1) = *(data + from_offset); +			to_offset++; +			from_offset++; +		} +	} +} + diff --git a/indra/llrender/llfontfreetype.h b/indra/llrender/llfontfreetype.h new file mode 100644 index 0000000000..0520ef2cd6 --- /dev/null +++ b/indra/llrender/llfontfreetype.h @@ -0,0 +1,380 @@ +/**  + * @file llfontfreetype.h + * @brief Font library wrapper + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + *  + * Copyright (c) 2002-2009, Linden Research, Inc. + *  + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + *  + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + *  + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + *  + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLFONTFREETYPE_H +#define LL_LLFONTFREETYPE_H + +#include <map> +#include "llpointer.h" +#include "llstl.h" + +#include "llimagegl.h" +#include "llfontbitmapcache.h" + +// Hack.  FT_Face is just a typedef for a pointer to a struct, +// but there's no simple forward declarations file for FreeType,  +// and the main include file is 200K.   +// We'll forward declare the struct here.  JC +struct FT_FaceRec_; +typedef struct FT_FaceRec_* LLFT_Face; + +class LLFontManager +{ +public: +	static void initClass(); +	static void cleanupClass(); + +private: +	LLFontManager(); +	~LLFontManager(); +}; + +class LLFontGlyphInfo +{ +public: +	LLFontGlyphInfo(U32 index); + +	U32 mGlyphIndex; + +	// Metrics +	S32 mWidth;			// In pixels +	S32 mHeight;		// In pixels +	F32 mXAdvance;		// In pixels +	F32 mYAdvance;		// In pixels +	BOOL mMetricsValid; // We have up-to-date metrics for this glyph + +	// Information for actually rendering +	BOOL mIsRendered;	// We actually have rendered this glyph +	S32 mXBitmapOffset; // Offset to the origin in the bitmap +	S32 mYBitmapOffset; // Offset to the origin in the bitmap +	S32 mXBearing;	// Distance from baseline to left in pixels +	S32 mYBearing;	// Distance from baseline to top in pixels +	S32 mBitmapNum; // Which bitmap in the bitmap cache contains this glyph +}; + +extern LLFontManager *gFontManagerp; + +class LLFontFreetype : public LLRefCount +{ +public: +	LLFontFreetype(); +	~LLFontFreetype(); + +	// is_fallback should be true for fallback fonts that aren't used +	// to render directly (Unicode backup, primarily) +	BOOL loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 components, BOOL is_fallback); + +	typedef std::vector<LLPointer<LLFontFreetype> > font_vector_t; + +	void setFallbackFonts(const font_vector_t &font); +	const font_vector_t &getFallbackFonts() const; + +	// Global font metrics - in units of pixels +	F32 getLineHeight() const; +	F32 getAscenderHeight() const; +	F32 getDescenderHeight() const; + + +// For a lowercase "g": +// +//	------------------------------ +//	                     ^     ^ +//						 |     | +//				xxx x    |Ascender +//	           x   x     v     | +//	---------   xxxx-------------- Baseline +//	^		       x	       | +//  | Descender    x           | +//	v			xxxx           |LineHeight +//  -----------------------    | +//                             v +//	------------------------------ + +	enum +	{ +		FIRST_CHAR = 32,  +		NUM_CHARS = 127 - 32,  +		LAST_CHAR_BASIC = 127, + +		// Need full 8-bit ascii range for spanish +		NUM_CHARS_FULL = 255 - 32, +		LAST_CHAR_FULL = 255 +	}; + +	F32 getXAdvance(llwchar wc) const; +	F32 getXKerning(llwchar char_left, llwchar char_right) const; // Get the kerning between the two characters + +	BOOL hasGlyph(llwchar wch) const;		// Has a glyph for this character +	BOOL addChar(llwchar wch) const;		// Add a new character to the font if necessary +	BOOL addGlyph(llwchar wch, U32 glyph_index) const;	// Add a new glyph to the existing font +	BOOL addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index) const;	// Add a glyph from this font to the other (returns the glyph_index, 0 if not found) + +	LLFontGlyphInfo* getGlyphInfo(llwchar wch) const; + +	void insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const; +	void renderGlyph(U32 glyph_index) const; + +	void reset(F32 vert_dpi, F32 horz_dpi); +	void resetBitmapCache(); + +	void destroyGL(); + +	BOOL getIsFallback() const; + +	const std::string& getName() const; + +	F32 getPointSize() const; + +	const LLPointer<LLFontBitmapCache> getFontBitmapCache() const; + +	void setStyle(U8 style); +	U8 getStyle() const; + +private: +	void setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32 width, U32 height, U8 *data, S32 stride = 0) const; + +	std::string mName; + +	U8 mStyle; + +	F32 mPointSize; +	F32 mAscender;			 +	F32 mDescender; +	F32 mLineHeight; + +	LLFT_Face mFTFace; + +	BOOL mIsFallback; +	font_vector_t mFallbackFonts; // A list of fallback fonts to look for glyphs in (for Unicode chars) + +	BOOL mValid; + +	typedef std::map<llwchar, LLFontGlyphInfo*> char_glyph_info_map_t; +	mutable char_glyph_info_map_t mCharGlyphInfoMap; // Information about glyph location in bitmap + +	mutable LLPointer<LLFontBitmapCache> mFontBitmapCachep; + +	mutable S32 mRenderGlyphCount; +	mutable S32 mAddGlyphCount; +}; + +#endif // LL_FONTFREETYPE_H +/**  + * @file llfontfreetype.h + * @brief Font library wrapper + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + *  + * Copyright (c) 2002-2009, Linden Research, Inc. + *  + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + *  + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + *  + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + *  + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLFONTFREETYPE_H +#define LL_LLFONTFREETYPE_H + +#include <map> +#include "llpointer.h" +#include "llstl.h" + +#include "llimagegl.h" +#include "llfontbitmapcache.h" + +// Hack.  FT_Face is just a typedef for a pointer to a struct, +// but there's no simple forward declarations file for FreeType,  +// and the main include file is 200K.   +// We'll forward declare the struct here.  JC +struct FT_FaceRec_; +typedef struct FT_FaceRec_* LLFT_Face; + +class LLFontManager +{ +public: +	static void initClass(); +	static void cleanupClass(); + +private: +	LLFontManager(); +	~LLFontManager(); +}; + +class LLFontGlyphInfo +{ +public: +	LLFontGlyphInfo(U32 index); + +	U32 mGlyphIndex; + +	// Metrics +	S32 mWidth;			// In pixels +	S32 mHeight;		// In pixels +	F32 mXAdvance;		// In pixels +	F32 mYAdvance;		// In pixels +	BOOL mMetricsValid; // We have up-to-date metrics for this glyph + +	// Information for actually rendering +	BOOL mIsRendered;	// We actually have rendered this glyph +	S32 mXBitmapOffset; // Offset to the origin in the bitmap +	S32 mYBitmapOffset; // Offset to the origin in the bitmap +	S32 mXBearing;	// Distance from baseline to left in pixels +	S32 mYBearing;	// Distance from baseline to top in pixels +	S32 mBitmapNum; // Which bitmap in the bitmap cache contains this glyph +}; + +extern LLFontManager *gFontManagerp; + +class LLFontFreetype : public LLRefCount +{ +public: +	LLFontFreetype(); +	~LLFontFreetype(); + +	// is_fallback should be true for fallback fonts that aren't used +	// to render directly (Unicode backup, primarily) +	BOOL loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 components, BOOL is_fallback); + +	typedef std::vector<LLPointer<LLFontFreetype> > font_vector_t; + +	void setFallbackFonts(const font_vector_t &font); +	const font_vector_t &getFallbackFonts() const; + +	// Global font metrics - in units of pixels +	F32 getLineHeight() const; +	F32 getAscenderHeight() const; +	F32 getDescenderHeight() const; + + +// For a lowercase "g": +// +//	------------------------------ +//	                     ^     ^ +//						 |     | +//				xxx x    |Ascender +//	           x   x     v     | +//	---------   xxxx-------------- Baseline +//	^		       x	       | +//  | Descender    x           | +//	v			xxxx           |LineHeight +//  -----------------------    | +//                             v +//	------------------------------ + +	enum +	{ +		FIRST_CHAR = 32,  +		NUM_CHARS = 127 - 32,  +		LAST_CHAR_BASIC = 127, + +		// Need full 8-bit ascii range for spanish +		NUM_CHARS_FULL = 255 - 32, +		LAST_CHAR_FULL = 255 +	}; + +	F32 getXAdvance(llwchar wc) const; +	F32 getXKerning(llwchar char_left, llwchar char_right) const; // Get the kerning between the two characters + +	BOOL hasGlyph(llwchar wch) const;		// Has a glyph for this character +	BOOL addChar(llwchar wch) const;		// Add a new character to the font if necessary +	BOOL addGlyph(llwchar wch, U32 glyph_index) const;	// Add a new glyph to the existing font +	BOOL addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index) const;	// Add a glyph from this font to the other (returns the glyph_index, 0 if not found) + +	LLFontGlyphInfo* getGlyphInfo(llwchar wch) const; + +	void insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const; +	void renderGlyph(U32 glyph_index) const; + +	void reset(F32 vert_dpi, F32 horz_dpi); +	void resetBitmapCache(); + +	void destroyGL(); + +	BOOL getIsFallback() const; + +	const std::string& getName() const; + +	F32 getPointSize() const; + +	const LLPointer<LLFontBitmapCache> getFontBitmapCache() const; + +	void setStyle(U8 style); +	U8 getStyle() const; + +private: +	void setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32 width, U32 height, U8 *data, S32 stride = 0) const; + +	std::string mName; + +	U8 mStyle; + +	F32 mPointSize; +	F32 mAscender;			 +	F32 mDescender; +	F32 mLineHeight; + +	LLFT_Face mFTFace; + +	BOOL mIsFallback; +	font_vector_t mFallbackFonts; // A list of fallback fonts to look for glyphs in (for Unicode chars) + +	BOOL mValid; + +	typedef std::map<llwchar, LLFontGlyphInfo*> char_glyph_info_map_t; +	mutable char_glyph_info_map_t mCharGlyphInfoMap; // Information about glyph location in bitmap + +	mutable LLPointer<LLFontBitmapCache> mFontBitmapCachep; + +	mutable S32 mRenderGlyphCount; +	mutable S32 mAddGlyphCount; +}; + +#endif // LL_FONTFREETYPE_H diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 0b57d86c78..32a008047c 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -35,7 +35,7 @@  #include "llfontgl.h"  // Linden library includes -#include "llfont.h" +#include "llfontfreetype.h"  #include "llfontbitmapcache.h"  #include "llfontregistry.h"  #include "llgl.h" @@ -73,54 +73,25 @@ const F32 PIXEL_CORRECTION_DISTANCE = 0.01f;  const F32 PAD_UVY = 0.5f; // half of vertical padding between glyphs in the glyph texture  const F32 DROP_SHADOW_SOFT_STRENGTH = 0.3f; -F32 llfont_round_x(F32 x) +static F32 llfont_round_x(F32 x)  {  	//return llfloor((x-LLFontGL::sCurOrigin.mX)/LLFontGL::sScaleX+0.5f)*LLFontGL::sScaleX+LLFontGL::sCurOrigin.mX;  	//return llfloor(x/LLFontGL::sScaleX+0.5f)*LLFontGL::sScaleY;  	return x;  } -F32 llfont_round_y(F32 y) +static F32 llfont_round_y(F32 y)  {  	//return llfloor((y-LLFontGL::sCurOrigin.mY)/LLFontGL::sScaleY+0.5f)*LLFontGL::sScaleY+LLFontGL::sCurOrigin.mY;  	//return llfloor(y+0.5f);  	return y;  } -// static -U8 LLFontGL::getStyleFromString(const std::string &style) -{ -	S32 ret = 0; -	if (style.find("NORMAL") != style.npos) -	{ -		ret |= NORMAL; -	} -	if (style.find("BOLD") != style.npos) -	{ -		ret |= BOLD; -	} -	if (style.find("ITALIC") != style.npos) -	{ -		ret |= ITALIC; -	} -	if (style.find("UNDERLINE") != style.npos) -	{ -		ret |= UNDERLINE; -	} -	return ret; -} -  LLFontGL::LLFontGL() -	: LLFont()  {  	clearEmbeddedChars();  } -LLFontGL::LLFontGL(const LLFontGL &source) -{ -	llerrs << "Not implemented!" << llendl; -} -  LLFontGL::~LLFontGL()  {  	clearEmbeddedChars(); @@ -128,293 +99,26 @@ LLFontGL::~LLFontGL()  void LLFontGL::reset()  { -	if (!mIsFallback) -	{ -		// This is the head of the list - need to rebuild ourself and all fallbacks. -		loadFace(mName,mPointSize,sVertDPI,sHorizDPI,mFontBitmapCachep->getNumComponents(),mIsFallback); -		if (mFallbackFontp==NULL) -		{ -			llwarns << "LLFontGL::reset(), no fallback fonts present" << llendl; -		} -		else -		{ -			for (LLFontList::iterator it = mFallbackFontp->begin(); -				 it != mFallbackFontp->end(); -				 ++it) -			{ -				(*it)->reset(); -			} -		} -	} -	resetBitmapCache();  -} - -// static  -std::string LLFontGL::getFontPathSystem() -{ -	std::string system_path; - -	// Try to figure out where the system's font files are stored. -	char *system_root = NULL; -#if LL_WINDOWS -	system_root = getenv("SystemRoot");	/* Flawfinder: ignore */ -	if (!system_root) -	{ -		llwarns << "SystemRoot not found, attempting to load fonts from default path." << llendl; -	} -#endif - -	if (system_root) -	{ -		system_path = llformat("%s/fonts/", system_root); -	} -	else -	{ -#if LL_WINDOWS -		// HACK for windows 98/Me -		system_path = "/WINDOWS/FONTS/"; -#elif LL_DARWIN -		// HACK for Mac OS X -		system_path = "/System/Library/Fonts/"; -#endif -	} -	return system_path; -} - - -// static  -std::string LLFontGL::getFontPathLocal() -{ -	std::string local_path; - -	// Backup files if we can't load from system fonts directory. -	// We could store this in an end-user writable directory to allow -	// end users to switch fonts. -	if (LLFontGL::sAppDir.length()) -	{ -		// use specified application dir to look for fonts -		local_path = LLFontGL::sAppDir + "/fonts/"; -	} -	else -	{ -		// assume working directory is executable directory -		local_path = "./fonts/"; -	} -	return local_path; -} - -bool findOrCreateFont(LLFontGL*& fontp, const LLFontDescriptor& desc) -{ -	// Don't delete existing fonts, if any, here, because they've -	// already been deleted by LLFontRegistry::clear() -	fontp = LLFontGL::getFont(desc); -	return (fontp != NULL); -} - -// static -void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, -								const std::string& app_dir, -								const std::vector<std::string>& xui_paths, -								bool create_gl_textures) -{ -	sVertDPI = (F32)llfloor(screen_dpi * y_scale); -	sHorizDPI = (F32)llfloor(screen_dpi * x_scale); -	sScaleX = x_scale; -	sScaleY = y_scale; -	sAppDir = app_dir; - -	// Font registry init -	if (!sFontRegistry) -	{ -		sFontRegistry = new LLFontRegistry(xui_paths, create_gl_textures); -		sFontRegistry->parseFontInfo("fonts.xml"); -	} -	else -	{ -		sFontRegistry->reset(); -	} -} - -// Force standard fonts to get generated up front. -// This is primarily for error detection purposes. -// Don't do this during initClass because it can be slow and we want to get -// the viewer window on screen first. JC -// static -bool LLFontGL::loadDefaultFonts() -{ -	bool succ = true; -	succ &= (NULL != getFontSansSerifSmall()); -	succ &= (NULL != getFontSansSerif()); -	succ &= (NULL != getFontSansSerifBig()); -	succ &= (NULL != getFontSansSerifHuge()); -	succ &= (NULL != getFontSansSerifBold()); -	succ &= (NULL != getFontMonospace()); -	succ &= (NULL != getFontExtChar()); -	return succ; -} - - - -// static -void LLFontGL::destroyDefaultFonts() -{ -	// Remove the actual fonts. -	delete sFontRegistry; -	sFontRegistry = NULL; -} - -//static  -void LLFontGL::destroyAllGL() -{ -	if (sFontRegistry) -	{ -		sFontRegistry->destroyGL(); -	} +	mFontFreetype->reset(sVertDPI, sHorizDPI);  }  void LLFontGL::destroyGL()  { -	mFontBitmapCachep->destroyGL(); -} - - - -LLFontGL &LLFontGL::operator=(const LLFontGL &source) -{ -	llerrs << "Not implemented" << llendl; -	return *this; -} - -BOOL LLFontGL::loadFace(const std::string& filename, -						const F32 point_size, const F32 vert_dpi, const F32 horz_dpi, -						const S32 components, BOOL is_fallback) -{ -	if (!LLFont::loadFace(filename, point_size, vert_dpi, horz_dpi, components, is_fallback)) -	{ -		return FALSE; -	} -	return TRUE; -} - -//static -LLFontGL* LLFontGL::getFontMonospace() -{ -	return getFont(LLFontDescriptor("Monospace","Monospace",0)); -} - -//static -LLFontGL* LLFontGL::getFontSansSerifSmall() -{ -	return getFont(LLFontDescriptor("SansSerif","Small",0)); -} - -//static -LLFontGL* LLFontGL::getFontSansSerif() -{ -	return getFont(LLFontDescriptor("SansSerif","Medium",0)); -} - -//static -LLFontGL* LLFontGL::getFontSansSerifBig() -{ -	return getFont(LLFontDescriptor("SansSerif","Large",0)); -} - -//static  -LLFontGL* LLFontGL::getFontSansSerifHuge() -{ -	return getFont(LLFontDescriptor("SansSerif","Huge",0)); -} - -//static  -LLFontGL* LLFontGL::getFontSansSerifBold() -{ -	return getFont(LLFontDescriptor("SansSerif","Medium",BOLD)); -} - -//static -LLFontGL* LLFontGL::getFontExtChar() -{ -	return getFontSansSerif(); -} - -//static  -LLFontGL* LLFontGL::getFont(const LLFontDescriptor& desc) -{ -	return sFontRegistry->getFont(desc); -} - -//static -LLFontGL* LLFontGL::getFontByName(const std::string& name) -{ -	// check for most common fonts first -	if (name == "SANSSERIF") -	{ -		return getFontSansSerif(); -	} -	else if (name == "SANSSERIF_SMALL") -	{ -		return getFontSansSerifSmall(); -	} -	else if (name == "SANSSERIF_BIG") -	{ -		return getFontSansSerifBig(); -	} -	else if (name == "SMALL" || name == "OCRA") -	{ -		// *BUG: Should this be "MONOSPACE"?  Do we use "OCRA" anymore? -		// Does "SMALL" mean "SERIF"? -		return getFontMonospace(); -	} -	else -	{ -		return NULL; -	} +	mFontFreetype->destroyGL();  } -BOOL LLFontGL::addChar(const llwchar wch) const +BOOL LLFontGL::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 components, BOOL is_fallback)  { -	if (!LLFont::addChar(wch)) +	if(mFontFreetype == reinterpret_cast<LLFontFreetype*>(NULL))  	{ -		return FALSE; +		mFontFreetype = new LLFontFreetype;  	} -	stop_glerror(); - -	LLFontGlyphInfo *glyph_info = getGlyphInfo(wch); -	U32 bitmap_num = glyph_info->mBitmapNum; -	LLImageGL *image_gl = mFontBitmapCachep->getImageGL(bitmap_num); -	LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_num); -	image_gl->setSubImage(image_raw, 0, 0, image_gl->getWidth(), image_gl->getHeight()); -	return TRUE; +	return mFontFreetype->loadFace(filename, point_size, vert_dpi, horz_dpi, components, is_fallback);  } - -S32 LLFontGL::renderUTF8(const std::string &text, const S32 offset,  -					 const F32 x, const F32 y, -					 const LLColor4 &color, -					 const HAlign halign, const VAlign valign, -					 U8 style, -					 ShadowType shadow, -					 const S32 max_chars, const S32 max_pixels, -					 F32* right_x, -					 BOOL use_ellipses) const -{ -	LLWString wstr = utf8str_to_wstring(text); -	return render(wstr, offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, FALSE, use_ellipses); -} - -S32 LLFontGL::render(const LLWString &wstr,  -					 const S32 begin_offset, -					 const F32 x, const F32 y, -					 const LLColor4 &color, -					 const HAlign halign, const VAlign valign, -					 U8 style, -					 ShadowType shadow, -					 const S32 max_chars, S32 max_pixels, -					 F32* right_x, -					 BOOL use_embedded, -					 BOOL use_ellipses) const +S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style,  +					 ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_embedded, BOOL use_ellipses) const  {  	if(!sDisplayFont) //do not display texts  	{ @@ -430,8 +134,9 @@ S32 LLFontGL::render(const LLWString &wstr,  	S32 scaled_max_pixels = max_pixels == S32_MAX ? S32_MAX : llceil((F32)max_pixels * sScaleX); -	// Strip off any style bits that are already accounted for by the font. -	style = style & (~getFontDesc().getStyle()); +	// determine which style flags need to be added programmatically by striping off the +	// style bits that are drawn by the underlying Freetype font +	U8 style_to_add = (style | mFontDescriptor.getStyle()) & ~mFontFreetype->getStyle();  	F32 drop_shadow_strength = 0.f;  	if (shadow != NO_SHADOW) @@ -483,13 +188,13 @@ S32 LLFontGL::render(const LLWString &wstr,  	switch (valign)  	{  	case TOP: -		cur_y -= mAscender; +		cur_y -= mFontFreetype->getAscenderHeight();  		break;  	case BOTTOM: -		cur_y += mDescender; +		cur_y += mFontFreetype->getDescenderHeight();  		break;  	case VCENTER: -		cur_y -= ((mAscender - mDescender)/2.f); +		cur_y -= ((mFontFreetype->getAscenderHeight() - mFontFreetype->getDescenderHeight())/2.f);  		break;  	case BASELINE:  		// Baseline, do nothing. @@ -517,10 +222,12 @@ S32 LLFontGL::render(const LLWString &wstr,  	F32 start_x = cur_x; -	F32 inv_width = 1.f / mFontBitmapCachep->getBitmapWidth(); -	F32 inv_height = 1.f / mFontBitmapCachep->getBitmapHeight(); +	const LLFontBitmapCache* font_bitmap_cache = mFontFreetype->getFontBitmapCache(); + +	F32 inv_width = 1.f / font_bitmap_cache->getBitmapWidth(); +	F32 inv_height = 1.f / font_bitmap_cache->getBitmapHeight(); -	const S32 LAST_CHARACTER = LLFont::LAST_CHAR_FULL; +	const S32 LAST_CHARACTER = LLFontFreetype::LAST_CHAR_FULL;  	BOOL draw_ellipses = FALSE; @@ -576,11 +283,11 @@ S32 LLFontGL::render(const LLWString &wstr,  			// snap origin to whole screen pixel  			const F32 ext_x = (F32)llround(cur_render_x + (EXT_X_BEARING * sScaleX)); -			const F32 ext_y = (F32)llround(cur_render_y + (EXT_Y_BEARING * sScaleY + mAscender - mLineHeight)); +			const F32 ext_y = (F32)llround(cur_render_y + (EXT_Y_BEARING * sScaleY + mFontFreetype->getAscenderHeight() - mFontFreetype->getLineHeight()));  			LLRectf uv_rect(0.f, 1.f, 1.f, 0.f);  			LLRectf screen_rect(ext_x, ext_y + ext_height, ext_x + ext_width, ext_y); -			drawGlyph(screen_rect, uv_rect, LLColor4::white, style, shadow, drop_shadow_strength); +			drawGlyph(screen_rect, uv_rect, LLColor4::white, style_to_add, shadow, drop_shadow_strength);  			if (!label.empty())  			{ @@ -609,19 +316,19 @@ S32 LLFontGL::render(const LLWString &wstr,  		}  		else  		{ -			if (!hasGlyph(wch)) +			if (!mFontFreetype->hasGlyph(wch))  			{  				addChar(wch);  			} -			const LLFontGlyphInfo* fgi= getGlyphInfo(wch); +			const LLFontGlyphInfo* fgi= mFontFreetype->getGlyphInfo(wch);  			if (!fgi)  			{  				llerrs << "Missing Glyph Info" << llendl;  				break;  			}  			// Per-glyph bitmap texture. -			LLImageGL *image_gl = mFontBitmapCachep->getImageGL(fgi->mBitmapNum); +			LLImageGL *image_gl = mFontFreetype->getFontBitmapCache()->getImageGL(fgi->mBitmapNum);  			if (last_bound_texture != image_gl)  			{  				gGL.getTexUnit(0)->bind(image_gl); @@ -646,7 +353,7 @@ S32 LLFontGL::render(const LLWString &wstr,  					    llround(cur_render_x + (F32)fgi->mXBearing) + (F32)fgi->mWidth,  					    llround(cur_render_y + (F32)fgi->mYBearing) - (F32)fgi->mHeight); -			drawGlyph(screen_rect, uv_rect, color, style, shadow, drop_shadow_strength); +			drawGlyph(screen_rect, uv_rect, color, style_to_add, shadow, drop_shadow_strength);  			chars_drawn++;  			cur_x += fgi->mXAdvance; @@ -656,11 +363,11 @@ S32 LLFontGL::render(const LLWString &wstr,  			if (next_char && (next_char < LAST_CHARACTER))  			{  				// Kern this puppy. -				if (!hasGlyph(next_char)) +				if (!mFontFreetype->hasGlyph(next_char))  				{  					addChar(next_char);  				} -				cur_x += getXKerning(wch, next_char); +				cur_x += mFontFreetype->getXKerning(wch, next_char);  			}  			// Round after kerning. @@ -680,12 +387,14 @@ S32 LLFontGL::render(const LLWString &wstr,  		*right_x = cur_x / sScaleX;  	} -	if (style & UNDERLINE) +	if (style_to_add & UNDERLINE)  	{ +		F32 descender = mFontFreetype->getDescenderHeight(); +  		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);  		gGL.begin(LLRender::LINES); -		gGL.vertex2f(start_x, cur_y - (mDescender)); -		gGL.vertex2f(cur_x, cur_y - (mDescender)); +		gGL.vertex2f(start_x, cur_y - (descender)); +		gGL.vertex2f(cur_x, cur_y - (descender));  		gGL.end();  	} @@ -703,7 +412,7 @@ S32 LLFontGL::render(const LLWString &wstr,  				cur_x / sScaleX, (F32)y,  				color,  				LEFT, valign, -				style, +				style_to_add,  				shadow,  				S32_MAX, max_pixels,  				right_x, @@ -716,6 +425,41 @@ S32 LLFontGL::render(const LLWString &wstr,  	return chars_drawn;  } +S32 LLFontGL::render(const LLWString &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color) const +{ +	return render(text, begin_offset, x, y, color, LEFT, BASELINE, NORMAL, NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE, FALSE); +} + +S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign,  VAlign valign, U8 style, ShadowType shadow, S32 max_chars, S32 max_pixels,  F32* right_x, BOOL use_ellipses) const +{ +	return render(utf8str_to_wstring(text), begin_offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, FALSE, use_ellipses); +} + +S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color) const +{ +	return renderUTF8(text, begin_offset, (F32)x, (F32)y, color, LEFT, BASELINE, NORMAL, NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE); +} + +S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow) const +{ +	return renderUTF8(text, begin_offset, (F32)x, (F32)y, color, halign, valign, style, shadow, S32_MAX, S32_MAX, NULL, FALSE); +} + +// font metrics - override for LLFontFreetype that returns units of virtual pixels +F32 LLFontGL::getLineHeight() const +{  +	return (F32)llround(mFontFreetype->getLineHeight() / sScaleY);  +} + +F32 LLFontGL::getAscenderHeight() const +{  +	return (F32)llround(mFontFreetype->getAscenderHeight() / sScaleY);  +} + +F32 LLFontGL::getDescenderHeight() const +{  +	return (F32)llround(mFontFreetype->getDescenderHeight() / sScaleY);  +}  S32 LLFontGL::getWidth(const std::string& utf8text) const  { @@ -728,13 +472,13 @@ S32 LLFontGL::getWidth(const llwchar* wchars) const  	return getWidth(wchars, 0, S32_MAX);  } -S32 LLFontGL::getWidth(const std::string& utf8text, const S32 begin_offset, const S32 max_chars) const +S32 LLFontGL::getWidth(const std::string& utf8text, S32 begin_offset, S32 max_chars) const  {  	LLWString wtext = utf8str_to_wstring(utf8text);  	return getWidth(wtext.c_str(), begin_offset, max_chars);  } -S32 LLFontGL::getWidth(const llwchar* wchars, const S32 begin_offset, const S32 max_chars, BOOL use_embedded) const +S32 LLFontGL::getWidth(const llwchar* wchars, S32 begin_offset, S32 max_chars, BOOL use_embedded) const  {  	F32 width = getWidthF32(wchars, begin_offset, max_chars, use_embedded);  	return llround(width); @@ -751,15 +495,15 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars) const  	return getWidthF32(wchars, 0, S32_MAX);  } -F32 LLFontGL::getWidthF32(const std::string& utf8text, const S32 begin_offset, const S32 max_chars ) const +F32 LLFontGL::getWidthF32(const std::string& utf8text, S32 begin_offset, S32 max_chars ) const  {  	LLWString wtext = utf8str_to_wstring(utf8text);  	return getWidthF32(wtext.c_str(), begin_offset, max_chars);  } -F32 LLFontGL::getWidthF32(const llwchar* wchars, const S32 begin_offset, const S32 max_chars, BOOL use_embedded) const +F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars, BOOL use_embedded) const  { -	const S32 LAST_CHARACTER = LLFont::LAST_CHAR_FULL; +	const S32 LAST_CHARACTER = LLFontFreetype::LAST_CHAR_FULL;  	F32 cur_x = 0;  	const S32 max_index = begin_offset + max_chars; @@ -783,7 +527,7 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, const S32 begin_offset, const S  		}  		else  		{ -			cur_x += getXAdvance(wch); +			cur_x += mFontFreetype->getXAdvance(wch);  			llwchar next_char = wchars[i+1];  			if (((i + 1) < max_chars)  @@ -791,7 +535,7 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, const S32 begin_offset, const S  				&& (next_char < LAST_CHARACTER))  			{  				// Kern this puppy. -				cur_x += getXKerning(wch, next_char); +				cur_x += mFontFreetype->getXKerning(wch, next_char);  			}  		}  		// Round after kerning. @@ -801,12 +545,8 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, const S32 begin_offset, const S  	return cur_x / sScaleX;  } - -  // Returns the max number of complete characters from text (up to max_chars) that can be drawn in max_pixels -S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_chars, -							   BOOL end_on_word_boundary, const BOOL use_embedded, -							   F32* drawn_pixels) const +S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_chars, BOOL end_on_word_boundary, BOOL use_embedded, F32* drawn_pixels) const  {  	if (!wchars || !wchars[0] || max_chars == 0)  	{ @@ -899,7 +639,7 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch  				}  			} -			cur_x += getXAdvance(wch); +			cur_x += mFontFreetype->getXAdvance(wch);  			if (scaled_max_pixels < cur_x)  			{ @@ -910,7 +650,7 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch  			if (((i+1) < max_chars) && wchars[i+1])  			{  				// Kern this puppy. -				cur_x += getXKerning(wch, wchars[i+1]); +				cur_x += mFontFreetype->getXKerning(wch, wchars[i+1]);  			}  		}  		// Round after kerning. @@ -929,7 +669,6 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch  	return i;  } -  S32	LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_len, S32 start_pos, S32 max_chars) const  {  	if (!wchars || !wchars[0] || max_chars == 0) @@ -948,7 +687,7 @@ S32	LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_  		llwchar wch = wchars[i];  		const embedded_data_t* ext_data = getEmbeddedCharData(wch); -		F32 char_width = ext_data ? getEmbeddedCharAdvance(ext_data) : getXAdvance(wch); +		F32 char_width = ext_data ? getEmbeddedCharAdvance(ext_data) : mFontFreetype->getXAdvance(wch);  		if( scaled_max_pixels < (total_width + char_width) )  		{ @@ -966,7 +705,7 @@ S32	LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_  		if ( i > 0 )  		{  			// kerning -			total_width += ext_data ? (EXT_KERNING * sScaleX) : getXKerning(wchars[i-1], wch); +			total_width += ext_data ? (EXT_KERNING * sScaleX) : mFontFreetype->getXKerning(wchars[i-1], wch);  		}  		// Round after kerning. @@ -976,8 +715,7 @@ S32	LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_  	return start_pos - drawable_chars;  } - -S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, const S32 begin_offset, F32 target_x, F32 max_pixels, S32 max_chars, BOOL round, BOOL use_embedded) const +S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 target_x, F32 max_pixels, S32 max_chars, BOOL round, BOOL use_embedded) const  {  	if (!wchars || !wchars[0] || max_chars == 0)  	{ @@ -1041,7 +779,7 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, const S32 begin_offset,  		}  		else  		{ -			F32 char_width = getXAdvance(wch); +			F32 char_width = mFontFreetype->getXAdvance(wch);  			if (round)  			{ @@ -1070,7 +808,7 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, const S32 begin_offset,  			{  				llwchar next_char = wchars[i + 1];  				// Kern this puppy. -				cur_x += getXKerning(wch, next_char); +				cur_x += mFontFreetype->getXKerning(wch, next_char);  			}  			// Round after kerning. @@ -1081,60 +819,370 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, const S32 begin_offset,  	return pos;  } +void LLFontGL::addEmbeddedChar( llwchar wc, LLTexture* image, const std::string& label ) const +{ +	LLWString wlabel = utf8str_to_wstring(label); +	addEmbeddedChar(wc, image, wlabel); +} -const LLFontGL::embedded_data_t* LLFontGL::getEmbeddedCharData(const llwchar wch) const +void LLFontGL::addEmbeddedChar( llwchar wc, LLTexture* image, const LLWString& wlabel ) const  { -	// Handle crappy embedded hack -	embedded_map_t::const_iterator iter = mEmbeddedChars.find(wch); +	embedded_data_t* ext_data = new embedded_data_t(image->getGLTexture(), wlabel); +	mEmbeddedChars[wc] = ext_data; +} + +void LLFontGL::removeEmbeddedChar(llwchar wc) const +{ +	embedded_map_t::iterator iter = mEmbeddedChars.find(wc);  	if (iter != mEmbeddedChars.end())  	{ -		return iter->second; +		delete iter->second; +		mEmbeddedChars.erase(wc);  	} -	return NULL;  } +BOOL LLFontGL::addChar(llwchar wch) const +{ +	if (!mFontFreetype->addChar(wch)) +	{ +		return FALSE; +	} + +	stop_glerror(); -F32 LLFontGL::getEmbeddedCharAdvance(const embedded_data_t* ext_data) const +	LLFontGlyphInfo *glyph_info = mFontFreetype->getGlyphInfo(wch); +	U32 bitmap_num = glyph_info->mBitmapNum; + +	const LLFontBitmapCache* font_bitmap_cache = mFontFreetype->getFontBitmapCache(); +	LLImageGL *image_gl = font_bitmap_cache->getImageGL(bitmap_num); +	LLImageRaw *image_raw = font_bitmap_cache->getImageRaw(bitmap_num); +	image_gl->setSubImage(image_raw, 0, 0, image_gl->getWidth(), image_gl->getHeight()); +	return TRUE; +} + +const LLFontDescriptor& LLFontGL::getFontDesc() const  { -	const LLWString& label = ext_data->mLabel; -	LLImageGL* ext_image = ext_data->mImage; +	return mFontDescriptor; +} -	F32 ext_width = (F32)ext_image->getWidth(); -	if( !label.empty() ) +// static +void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, const std::vector<std::string>& xui_paths, bool create_gl_textures) +{ +	sVertDPI = (F32)llfloor(screen_dpi * y_scale); +	sHorizDPI = (F32)llfloor(screen_dpi * x_scale); +	sScaleX = x_scale; +	sScaleY = y_scale; +	sAppDir = app_dir; + +	// Font registry init +	if (!sFontRegistry)  	{ -		ext_width += (EXT_X_BEARING + getFontExtChar()->getWidthF32(label.c_str())) * sScaleX; +		sFontRegistry = new LLFontRegistry(xui_paths, create_gl_textures); +		sFontRegistry->parseFontInfo("fonts.xml"); +	} +	else +	{ +		sFontRegistry->reset();  	} +} -	return (EXT_X_BEARING * sScaleX) + ext_width; +// Force standard fonts to get generated up front. +// This is primarily for error detection purposes. +// Don't do this during initClass because it can be slow and we want to get +// the viewer window on screen first. JC +// static +bool LLFontGL::loadDefaultFonts() +{ +	bool succ = true; +	succ &= (NULL != getFontSansSerifSmall()); +	succ &= (NULL != getFontSansSerif()); +	succ &= (NULL != getFontSansSerifBig()); +	succ &= (NULL != getFontSansSerifHuge()); +	succ &= (NULL != getFontSansSerifBold()); +	succ &= (NULL != getFontMonospace()); +	succ &= (NULL != getFontExtChar()); +	return succ;  } +// static +void LLFontGL::destroyDefaultFonts() +{ +	// Remove the actual fonts. +	delete sFontRegistry; +	sFontRegistry = NULL; +} -void LLFontGL::clearEmbeddedChars() +//static  +void LLFontGL::destroyAllGL()  { -	for_each(mEmbeddedChars.begin(), mEmbeddedChars.end(), DeletePairedPointer()); -	mEmbeddedChars.clear(); +	if (sFontRegistry) +	{ +		sFontRegistry->destroyGL(); +	}  } -void LLFontGL::addEmbeddedChar( llwchar wc, LLTexture* image, const std::string& label ) const +// static +U8 LLFontGL::getStyleFromString(const std::string &style)  { -	LLWString wlabel = utf8str_to_wstring(label); -	addEmbeddedChar(wc, image, wlabel); +	S32 ret = 0; +	if (style.find("NORMAL") != style.npos) +	{ +		ret |= NORMAL; +	} +	if (style.find("BOLD") != style.npos) +	{ +		ret |= BOLD; +	} +	if (style.find("ITALIC") != style.npos) +	{ +		ret |= ITALIC; +	} +	if (style.find("UNDERLINE") != style.npos) +	{ +		ret |= UNDERLINE; +	} +	return ret;  } -void LLFontGL::addEmbeddedChar( llwchar wc, LLTexture* image, const LLWString& wlabel ) const +// static +std::string LLFontGL::nameFromFont(const LLFontGL* fontp)  { -	embedded_data_t* ext_data = new embedded_data_t(image->getGLTexture(), wlabel); -	mEmbeddedChars[wc] = ext_data; +	return fontp->mFontDescriptor.getName();  } -void LLFontGL::removeEmbeddedChar( llwchar wc ) const +// static +std::string LLFontGL::nameFromHAlign(LLFontGL::HAlign align)  { -	embedded_map_t::iterator iter = mEmbeddedChars.find(wc); +	if (align == LEFT)			return std::string("left"); +	else if (align == RIGHT)	return std::string("right"); +	else if (align == HCENTER)	return std::string("center"); +	else return std::string(); +} + +// static +LLFontGL::HAlign LLFontGL::hAlignFromName(const std::string& name) +{ +	LLFontGL::HAlign gl_hfont_align = LLFontGL::LEFT; +	if (name == "left") +	{ +		gl_hfont_align = LLFontGL::LEFT; +	} +	else if (name == "right") +	{ +		gl_hfont_align = LLFontGL::RIGHT; +	} +	else if (name == "center") +	{ +		gl_hfont_align = LLFontGL::HCENTER; +	} +	//else leave left +	return gl_hfont_align; +} + +// static +std::string LLFontGL::nameFromVAlign(LLFontGL::VAlign align) +{ +	if (align == TOP)			return std::string("top"); +	else if (align == VCENTER)	return std::string("center"); +	else if (align == BASELINE)	return std::string("baseline"); +	else if (align == BOTTOM)	return std::string("bottom"); +	else return std::string(); +} + +// static +LLFontGL::VAlign LLFontGL::vAlignFromName(const std::string& name) +{ +	LLFontGL::VAlign gl_vfont_align = LLFontGL::BASELINE; +	if (name == "top") +	{ +		gl_vfont_align = LLFontGL::TOP; +	} +	else if (name == "center") +	{ +		gl_vfont_align = LLFontGL::VCENTER; +	} +	else if (name == "baseline") +	{ +		gl_vfont_align = LLFontGL::BASELINE; +	} +	else if (name == "bottom") +	{ +		gl_vfont_align = LLFontGL::BOTTOM; +	} +	//else leave baseline +	return gl_vfont_align; +} + +//static +LLFontGL* LLFontGL::getFontMonospace() +{ +	return getFont(LLFontDescriptor("Monospace","Monospace",0)); +} + +//static +LLFontGL* LLFontGL::getFontSansSerifSmall() +{ +	return getFont(LLFontDescriptor("SansSerif","Small",0)); +} + +//static +LLFontGL* LLFontGL::getFontSansSerif() +{ +	return getFont(LLFontDescriptor("SansSerif","Medium",0)); +} + +//static +LLFontGL* LLFontGL::getFontSansSerifBig() +{ +	return getFont(LLFontDescriptor("SansSerif","Large",0)); +} + +//static  +LLFontGL* LLFontGL::getFontSansSerifHuge() +{ +	return getFont(LLFontDescriptor("SansSerif","Huge",0)); +} + +//static  +LLFontGL* LLFontGL::getFontSansSerifBold() +{ +	return getFont(LLFontDescriptor("SansSerif","Medium",BOLD)); +} + +//static +LLFontGL* LLFontGL::getFontExtChar() +{ +	return getFontSansSerif(); +} + +//static  +LLFontGL* LLFontGL::getFont(const LLFontDescriptor& desc) +{ +	return sFontRegistry->getFont(desc); +} + +//static +LLFontGL* LLFontGL::getFontByName(const std::string& name) +{ +	// check for most common fonts first +	if (name == "SANSSERIF") +	{ +		return getFontSansSerif(); +	} +	else if (name == "SANSSERIF_SMALL") +	{ +		return getFontSansSerifSmall(); +	} +	else if (name == "SANSSERIF_BIG") +	{ +		return getFontSansSerifBig(); +	} +	else if (name == "SMALL" || name == "OCRA") +	{ +		// *BUG: Should this be "MONOSPACE"?  Do we use "OCRA" anymore? +		// Does "SMALL" mean "SERIF"? +		return getFontMonospace(); +	} +	else +	{ +		return NULL; +	} +} + +// static  +std::string LLFontGL::getFontPathSystem() +{ +	std::string system_path; + +	// Try to figure out where the system's font files are stored. +	char *system_root = NULL; +#if LL_WINDOWS +	system_root = getenv("SystemRoot");	/* Flawfinder: ignore */ +	if (!system_root) +	{ +		llwarns << "SystemRoot not found, attempting to load fonts from default path." << llendl; +	} +#endif + +	if (system_root) +	{ +		system_path = llformat("%s/fonts/", system_root); +	} +	else +	{ +#if LL_WINDOWS +		// HACK for windows 98/Me +		system_path = "/WINDOWS/FONTS/"; +#elif LL_DARWIN +		// HACK for Mac OS X +		system_path = "/System/Library/Fonts/"; +#endif +	} +	return system_path; +} + + +// static  +std::string LLFontGL::getFontPathLocal() +{ +	std::string local_path; + +	// Backup files if we can't load from system fonts directory. +	// We could store this in an end-user writable directory to allow +	// end users to switch fonts. +	if (LLFontGL::sAppDir.length()) +	{ +		// use specified application dir to look for fonts +		local_path = LLFontGL::sAppDir + "/fonts/"; +	} +	else +	{ +		// assume working directory is executable directory +		local_path = "./fonts/"; +	} +	return local_path; +} + +LLFontGL::LLFontGL(const LLFontGL &source) +{ +	llerrs << "Not implemented!" << llendl; +} + +LLFontGL &LLFontGL::operator=(const LLFontGL &source) +{ +	llerrs << "Not implemented" << llendl; +	return *this; +} + +const LLFontGL::embedded_data_t* LLFontGL::getEmbeddedCharData(llwchar wch) const +{ +	// Handle crappy embedded hack +	embedded_map_t::const_iterator iter = mEmbeddedChars.find(wch);  	if (iter != mEmbeddedChars.end())  	{ -		delete iter->second; -		mEmbeddedChars.erase(wc); +		return iter->second; +	} +	return NULL; +} + +F32 LLFontGL::getEmbeddedCharAdvance(const embedded_data_t* ext_data) const +{ +	const LLWString& label = ext_data->mLabel; +	LLImageGL* ext_image = ext_data->mImage; + +	F32 ext_width = (F32)ext_image->getWidth(); +	if( !label.empty() ) +	{ +		ext_width += (EXT_X_BEARING + getFontExtChar()->getWidthF32(label.c_str())) * sScaleX;  	} + +	return (EXT_X_BEARING * sScaleX) + ext_width; +} + +void LLFontGL::clearEmbeddedChars() +{ +	for_each(mEmbeddedChars.begin(), mEmbeddedChars.end(), DeletePairedPointer()); +	mEmbeddedChars.clear();  } @@ -1160,7 +1208,7 @@ void LLFontGL::renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect, F3  void LLFontGL::drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, ShadowType shadow, F32 drop_shadow_strength) const  {  	F32 slant_offset; -	slant_offset = ((style & ITALIC) ? ( -mAscender * 0.2f) : 0.f); +	slant_offset = ((style & ITALIC) ? ( -mFontFreetype->getAscenderHeight() * 0.2f) : 0.f);  	gGL.begin(LLRender::QUADS);  	{ @@ -1230,71 +1278,3 @@ void LLFontGL::drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, con  	}  	gGL.end();  } - -std::string LLFontGL::nameFromFont(const LLFontGL* fontp) -{ -	return fontp->getFontDesc().getName(); -} - -// static -std::string LLFontGL::nameFromHAlign(LLFontGL::HAlign align) -{ -	if (align == LEFT)			return std::string("left"); -	else if (align == RIGHT)	return std::string("right"); -	else if (align == HCENTER)	return std::string("center"); -	else return std::string(); -} - -// static -LLFontGL::HAlign LLFontGL::hAlignFromName(const std::string& name) -{ -	LLFontGL::HAlign gl_hfont_align = LLFontGL::LEFT; -	if (name == "left") -	{ -		gl_hfont_align = LLFontGL::LEFT; -	} -	else if (name == "right") -	{ -		gl_hfont_align = LLFontGL::RIGHT; -	} -	else if (name == "center") -	{ -		gl_hfont_align = LLFontGL::HCENTER; -	} -	//else leave left -	return gl_hfont_align; -} - -// static -std::string LLFontGL::nameFromVAlign(LLFontGL::VAlign align) -{ -	if (align == TOP)			return std::string("top"); -	else if (align == VCENTER)	return std::string("center"); -	else if (align == BASELINE)	return std::string("baseline"); -	else if (align == BOTTOM)	return std::string("bottom"); -	else return std::string(); -} - -// static -LLFontGL::VAlign LLFontGL::vAlignFromName(const std::string& name) -{ -	LLFontGL::VAlign gl_vfont_align = LLFontGL::BASELINE; -	if (name == "top") -	{ -		gl_vfont_align = LLFontGL::TOP; -	} -	else if (name == "center") -	{ -		gl_vfont_align = LLFontGL::VCENTER; -	} -	else if (name == "baseline") -	{ -		gl_vfont_align = LLFontGL::BASELINE; -	} -	else if (name == "bottom") -	{ -		gl_vfont_align = LLFontGL::BOTTOM; -	} -	//else leave baseline -	return gl_vfont_align; -} diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h index 2298db0ef3..42ed7a381f 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -35,21 +35,21 @@  #define LL_LLFONTGL_H  #include "llcoord.h" -#include "llfont.h"  #include "llfontregistry.h" +#include "llimagegl.h"  #include "llpointer.h"  #include "llrect.h"  #include "v2math.h"  class LLColor4; -class LLImageGL;  // Key used to request a font.  class LLFontDescriptor; +class LLFontFreetype;  // Structure used to store previously requested fonts.  class LLFontRegistry; -class LLFontGL : public LLFont +class LLFontGL  {  public:  	enum HAlign @@ -85,130 +85,72 @@ public:  		DROP_SHADOW,  		DROP_SHADOW_SOFT  	}; -	 -	// Takes a string with potentially several flags, i.e. "NORMAL|BOLD|ITALIC" -	static U8 getStyleFromString(const std::string &style);  	LLFontGL(); -	LLFontGL(const LLFontGL &source);  	~LLFontGL(); -	void init(); // Internal init, or reinitialization -	void reset(); // Reset a font after GL cleanup.  ONLY works on an already loaded font. -	LLFontGL &operator=(const LLFontGL &source); - -	static void initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, -								 const std::string& app_dir, -								 const std::vector<std::string>& xui_paths, -								 bool create_gl_textures = true); +	void reset(); // Reset a font after GL cleanup.  ONLY works on an already loaded font. -	// Load sans-serif, sans-serif-small, etc. -	// Slow, requires multiple seconds to load fonts. -	static bool loadDefaultFonts(); -	static void	destroyDefaultFonts(); -	static void destroyAllGL();  	void destroyGL(); -	/* virtual*/ BOOL loadFace(const std::string& filename, -							    const F32 point_size, const F32 vert_dpi, const F32 horz_dpi, -							    const S32 components, BOOL is_fallback); +	BOOL loadFace(const std::string& filename, F32 point_size, const F32 vert_dpi, const F32 horz_dpi, const S32 components, BOOL is_fallback); +	S32 render(const LLWString &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign = LEFT,  VAlign valign = BASELINE, U8 style = NORMAL, +	           ShadowType shadow = NO_SHADOW, S32 max_chars = S32_MAX, S32 max_pixels = S32_MAX, F32* right_x=NULL, BOOL use_embedded = FALSE, BOOL use_ellipses = FALSE) const; +	S32 render(const LLWString &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color) const; -	S32 renderUTF8(const std::string &text, const S32 begin_offset, -				   S32 x, S32 y, -				   const LLColor4 &color) const -	{ -		return renderUTF8(text, begin_offset, (F32)x, (F32)y, color, -							LEFT, BASELINE, NORMAL, NO_SHADOW, -							S32_MAX, S32_MAX, NULL, FALSE); -	} -	 -	S32 renderUTF8(const std::string &text, const S32 begin_offset, -				   S32 x, S32 y, -				   const LLColor4 &color, -				   HAlign halign, VAlign valign, U8 style = NORMAL, ShadowType shadow = NO_SHADOW) const -	{ -		return renderUTF8(text, begin_offset, (F32)x, (F32)y, color, -						  halign, valign, style, shadow, -						  S32_MAX, S32_MAX, NULL, FALSE); -	} -	  	// renderUTF8 does a conversion, so is slower! -	S32 renderUTF8(const std::string &text, -		S32 begin_offset, -		F32 x, F32 y, -		const LLColor4 &color, -		HAlign halign,  -		VAlign valign, -		U8 style, -		ShadowType shadow, -		S32 max_chars, -		S32 max_pixels,  -		F32* right_x, -		BOOL use_ellipses) const; - -	S32 render(const LLWString &text, const S32 begin_offset, -			   F32 x, F32 y, -			   const LLColor4 &color) const -	{ -		return render(text, begin_offset, x, y, color, -					  LEFT, BASELINE, NORMAL, NO_SHADOW, -					  S32_MAX, S32_MAX, NULL, FALSE, FALSE); -	} -	 +	S32 renderUTF8(const std::string &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign,  VAlign valign, U8 style, ShadowType shadow, S32 max_chars, S32 max_pixels,  F32* right_x, BOOL use_ellipses) const; +	S32 renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color) const; +	S32 renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style = NORMAL, ShadowType shadow = NO_SHADOW) const; -	S32 render(const LLWString &text, -		S32 begin_offset, -		F32 x, F32 y, -		const LLColor4 &color, -		HAlign halign = LEFT,  -		VAlign valign = BASELINE, -		U8 style = NORMAL, -		ShadowType shadow = NO_SHADOW, -		S32 max_chars = S32_MAX, -		S32 max_pixels = S32_MAX,  -		F32* right_x=NULL, -		BOOL use_embedded = FALSE, -		BOOL use_ellipses = FALSE) const; - -	// font metrics - override for LLFont that returns units of virtual pixels -	/*virtual*/ F32 getLineHeight() const		{ return (F32)llround(mLineHeight / sScaleY); } -	/*virtual*/ F32 getAscenderHeight() const	{ return (F32)llround(mAscender / sScaleY); } -	/*virtual*/ F32 getDescenderHeight() const	{ return (F32)llround(mDescender / sScaleY); } -	 -	virtual S32 getWidth(const std::string& utf8text) const; -	virtual S32 getWidth(const llwchar* wchars) const; -	virtual S32 getWidth(const std::string& utf8text, const S32 offset, const S32 max_chars ) const; -	virtual S32 getWidth(const llwchar* wchars, const S32 offset, const S32 max_chars, BOOL use_embedded = FALSE) const; +	// font metrics - override for LLFontFreetype that returns units of virtual pixels +	F32 getLineHeight() const; +	F32 getAscenderHeight() const; +	F32 getDescenderHeight() const; -	virtual F32 getWidthF32(const std::string& utf8text) const; -	virtual F32 getWidthF32(const llwchar* wchars) const; -	virtual F32 getWidthF32(const std::string& text, const S32 offset, const S32 max_chars ) const; -	virtual F32 getWidthF32(const llwchar* wchars, const S32 offset, const S32 max_chars, BOOL use_embedded = FALSE ) const; +	S32 getWidth(const std::string& utf8text) const; +	S32 getWidth(const llwchar* wchars) const; +	S32 getWidth(const std::string& utf8text, S32 offset, S32 max_chars ) const; +	S32 getWidth(const llwchar* wchars, S32 offset, S32 max_chars, BOOL use_embedded = FALSE) const; + +	F32 getWidthF32(const std::string& utf8text) const; +	F32 getWidthF32(const llwchar* wchars) const; +	F32 getWidthF32(const std::string& text, S32 offset, S32 max_chars ) const; +	F32 getWidthF32(const llwchar* wchars, S32 offset, S32 max_chars, BOOL use_embedded = FALSE ) const;  	// The following are called often, frequently with large buffers, so do not use a string interface  	// Returns the max number of complete characters from text (up to max_chars) that can be drawn in max_pixels -	virtual S32	maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_chars = S32_MAX, -								 BOOL end_on_word_boundary = FALSE, const BOOL use_embedded = FALSE, -								 F32* drawn_pixels = NULL) const; +	S32	maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_chars = S32_MAX, BOOL end_on_word_boundary = FALSE, BOOL use_embedded = FALSE, F32* drawn_pixels = NULL) const;  	// Returns the index of the first complete characters from text that can be drawn in max_pixels  	// given that the character at start_pos should be the last character (or as close to last as possible). -	virtual S32	firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_len, S32 start_pos=S32_MAX, S32 max_chars = S32_MAX) const; +	S32	firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_len, S32 start_pos=S32_MAX, S32 max_chars = S32_MAX) const;  	// Returns the index of the character closest to pixel position x (ignoring text to the right of max_pixels and max_chars) -	virtual S32 charFromPixelOffset(const llwchar* wchars, const S32 char_offset, -									F32 x, F32 max_pixels=F32_MAX, S32 max_chars = S32_MAX, -									BOOL round = TRUE, BOOL use_embedded = FALSE) const; +	S32 charFromPixelOffset(const llwchar* wchars, S32 char_offset, F32 x, F32 max_pixels=F32_MAX, S32 max_chars = S32_MAX, BOOL round = TRUE, BOOL use_embedded = FALSE) const; + +	void addEmbeddedChar( llwchar wc, LLTexture* image, const std::string& label) const; +	void addEmbeddedChar( llwchar wc, LLTexture* image, const LLWString& label) const; +	void removeEmbeddedChar( llwchar wc ) const; +	BOOL addChar(const llwchar wch) const; -	LLImageGL *getImageGL() const; +	const LLFontDescriptor& getFontDesc() const; -	void	   addEmbeddedChar( llwchar wc, LLTexture* image, const std::string& label) const; -	void	   addEmbeddedChar( llwchar wc, LLTexture* image, const LLWString& label) const; -	void	   removeEmbeddedChar( llwchar wc ) const; + +	static void initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, const std::vector<std::string>& xui_paths, bool create_gl_textures = true); + +	// Load sans-serif, sans-serif-small, etc. +	// Slow, requires multiple seconds to load fonts. +	static bool loadDefaultFonts(); +	static void	destroyDefaultFonts(); +	static void destroyAllGL(); + +	// Takes a string with potentially several flags, i.e. "NORMAL|BOLD|ITALIC" +	static U8 getStyleFromString(const std::string &style);  	static std::string nameFromFont(const LLFontGL* fontp); @@ -218,28 +160,7 @@ public:  	static std::string nameFromVAlign(LLFontGL::VAlign align);  	static LLFontGL::VAlign vAlignFromName(const std::string& name); -	static void setFontDisplay(BOOL flag) { sDisplayFont = flag ; } - -protected: -	struct embedded_data_t -	{ -		embedded_data_t(LLImageGL* image, const LLWString& label) : mImage(image), mLabel(label) {} -		LLPointer<LLImageGL> mImage; -		LLWString			 mLabel; -	}; -	const embedded_data_t* getEmbeddedCharData(const llwchar wch) const; -	F32 getEmbeddedCharAdvance(const embedded_data_t* ext_data) const; -	void clearEmbeddedChars(); -	void renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect, F32 slant_amt) const; -	void drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, ShadowType shadow, F32 drop_shadow_fade) const; - -public: -	static F32 sVertDPI; -	static F32 sHorizDPI; -	static F32 sScaleX; -	static F32 sScaleY; -	static BOOL     sDisplayFont ; -	static std::string sAppDir;			// For loading fonts +	static void setFontDisplay(BOOL flag) { sDisplayFont = flag; }  	static LLFontGL* getFontMonospace();  	static LLFontGL* getFontSansSerifSmall(); @@ -252,32 +173,50 @@ public:  	// Use with legacy names like "SANSSERIF_SMALL" or "OCRA"  	static LLFontGL* getFontByName(const std::string& name); +	static std::string getFontPathLocal(); +	static std::string getFontPathSystem(); + +	static LLCoordFont sCurOrigin; +	static std::vector<LLCoordFont> sOriginStack; +  	static LLColor4 sShadowColor; +	static F32 sVertDPI; +	static F32 sHorizDPI; +	static F32 sScaleX; +	static F32 sScaleY; +	static BOOL sDisplayFont ; +	static std::string sAppDir;			// For loading fonts + +private: +	friend class LLFontRegistry;  	friend class LLTextBillboard;  	friend class LLHUDText; -protected: -	/*virtual*/ BOOL addChar(const llwchar wch) const; +	LLFontGL(const LLFontGL &source); +	LLFontGL &operator=(const LLFontGL &source); -protected: -	typedef std::map<llwchar,embedded_data_t*> embedded_map_t; -	mutable embedded_map_t mEmbeddedChars; -	  	LLFontDescriptor mFontDescriptor; +	LLPointer<LLFontFreetype> mFontFreetype; -	// Registry holds all instantiated fonts. -	static LLFontRegistry* sFontRegistry; +	struct embedded_data_t +	{ +		embedded_data_t(LLImageGL* image, const LLWString& label) : mImage(image), mLabel(label) {} +		LLPointer<LLImageGL> mImage; +		LLWString			 mLabel; +	}; -public: -	static std::string getFontPathLocal(); -	static std::string getFontPathSystem(); +	typedef std::map<llwchar,embedded_data_t*> embedded_map_t; +	mutable embedded_map_t mEmbeddedChars; -	static LLCoordFont sCurOrigin; -	static std::vector<LLCoordFont> sOriginStack; +	const embedded_data_t* getEmbeddedCharData(llwchar wch) const; +	F32 getEmbeddedCharAdvance(const embedded_data_t* ext_data) const; +	void clearEmbeddedChars(); +	void renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect, F32 slant_amt) const; +	void drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, ShadowType shadow, F32 drop_shadow_fade) const; -	const LLFontDescriptor &getFontDesc() const { return mFontDescriptor; } -	void setFontDesc(const LLFontDescriptor& font_desc) { mFontDescriptor = font_desc; } +	// Registry holds all instantiated fonts. +	static LLFontRegistry* sFontRegistry;  };  #endif diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp index 3b5c62a5ea..553e7b8f9d 100644 --- a/indra/llrender/llfontregistry.cpp +++ b/indra/llrender/llfontregistry.cpp @@ -33,8 +33,9 @@  #include "linden_common.h"  #include "llgl.h" -#include "llfontregistry.h" +#include "llfontfreetype.h"  #include "llfontgl.h" +#include "llfontregistry.h"  #include <boost/tokenizer.hpp>  #include "llcontrol.h"  #include "lldir.h" @@ -382,7 +383,14 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)  	if (it != mFontMap.end())  	{  		llinfos << "-- matching font exists: " << nearest_exact_desc.getName() << " size " << nearest_exact_desc.getSize() << " style " << ((S32) nearest_exact_desc.getStyle()) << llendl; -		return it->second; +		 +		// copying underlying Freetype font, and storing in LLFontGL with requested font descriptor +		LLFontGL *font = new LLFontGL; +		font->mFontDescriptor = desc; +		font->mFontFreetype = it->second->mFontFreetype; +		mFontMap[desc] = font; + +		return font;  	}  	// Build list of font names to look for. @@ -410,10 +418,11 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)  		llwarns << "createFont failed, no file names specified" << llendl;  		return NULL;  	} -	LLFontList *fontlistp = new LLFontList; + +	LLFontFreetype::font_vector_t fontlist;  	LLFontGL *result = NULL; -	// Snarf all fonts we can into fontlistp.  First will get pulled +	// Snarf all fonts we can into fontlist.  First will get pulled  	// off the list and become the "head" font, set to non-fallback.  	// Rest will consitute the fallback list.  	BOOL is_first_found = TRUE; @@ -455,23 +464,28 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)  				is_first_found = false;  			}  			else -				fontlistp->addAtEnd(fontp); +			{ +				fontlist.push_back(fontp->mFontFreetype); +			}  		}  	} -	if (result && !fontlistp->empty()) + +	if (result && !fontlist.empty())  	{ -		result->setFallbackFont(fontlistp); +		result->mFontFreetype->setFallbackFonts(fontlist);  	} -	norm_desc.setStyle(match_desc->getStyle());  	if (result) -		result->setFontDesc(norm_desc); - -	if (!result) +	{ +		result->mFontFreetype->setStyle(match_desc->getStyle()); +		result->mFontDescriptor = desc; +	} +	else  	{  		llwarns << "createFont failed in some way" << llendl;  	} -	mFontMap[norm_desc] = result; + +	mFontMap[desc] = result;  	return result;  } @@ -511,21 +525,19 @@ void LLFontRegistry::destroyGL()  	}  } -LLFontGL *LLFontRegistry::getFont(const LLFontDescriptor& orig_desc) +LLFontGL *LLFontRegistry::getFont(const LLFontDescriptor& desc)  { -	LLFontDescriptor norm_desc = orig_desc.normalize(); - -	font_reg_map_t::iterator it = mFontMap.find(norm_desc); +	font_reg_map_t::iterator it = mFontMap.find(desc);  	if (it != mFontMap.end())  		return it->second;  	else  	{ -		LLFontGL *fontp = createFont(orig_desc); +		LLFontGL *fontp = createFont(desc);  		if (!fontp)  		{ -			llwarns << "getFont failed, name " << orig_desc.getName() -					<<" style=[" << ((S32) orig_desc.getStyle()) << "]" -					<< " size=[" << orig_desc.getSize() << "]" << llendl; +			llwarns << "getFont failed, name " << desc.getName() +					<<" style=[" << ((S32) desc.getStyle()) << "]" +					<< " size=[" << desc.getSize() << "]" << llendl;  		}  		return fontp;  	} @@ -653,3 +665,8 @@ void LLFontRegistry::dump()  		}  	}  } + +const string_vec_t& LLFontRegistry::getUltimateFallbackList() const  +{  +	return mUltimateFallbackList; +} diff --git a/indra/llrender/llfontregistry.h b/indra/llrender/llfontregistry.h index 198ca0b920..4da4ca48bb 100644 --- a/indra/llrender/llfontregistry.h +++ b/indra/llrender/llfontregistry.h @@ -98,7 +98,7 @@ public:  	void dump(); -	const string_vec_t& getUltimateFallbackList() const { return mUltimateFallbackList; } +	const string_vec_t& getUltimateFallbackList() const;  private:  	LLFontGL *createFont(const LLFontDescriptor& desc); diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index e62d875a01..edd3fe2beb 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -37,6 +37,7 @@ set(llui_SOURCE_FILES      lldraghandle.cpp      lleditmenuhandler.cpp      llf32uictrl.cpp +    llfiltereditor.cpp      llfloater.cpp      llfloaterreg.cpp      llflyoutbutton.cpp  @@ -59,6 +60,7 @@ set(llui_SOURCE_FILES      llresizebar.cpp      llresizehandle.cpp      llresmgr.cpp +    llrngwriter.cpp      llscrollbar.cpp      llscrollcontainer.cpp      llscrollingpanellist.cpp @@ -67,7 +69,7 @@ set(llui_SOURCE_FILES      llscrolllistctrl.cpp      llscrolllistitem.cpp      llsdparam.cpp -    llsearcheditor.cpp  +    llsearcheditor.cpp      llslider.cpp      llsliderctrl.cpp      llspinctrl.cpp @@ -109,11 +111,13 @@ set(llui_HEADER_FILES      lldraghandle.h      lleditmenuhandler.h      llf32uictrl.h +    llfiltereditor.h       llfloater.h      llfloaterreg.h      llflyoutbutton.h       llfocusmgr.h      llfunctorregistry.h +    llhandle.h      llhtmlhelp.h      lliconctrl.h      llinitparam.h @@ -134,6 +138,7 @@ set(llui_HEADER_FILES      llresizebar.h      llresizehandle.h      llresmgr.h +    llrngwriter.h      llsearcheditor.h       llscrollbar.h      llscrollcontainer.h diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 9ad27e7c41..fc3af34951 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -62,7 +62,7 @@ S32 BTN_HEIGHT		= 0;  LLButton::Params::Params()  :	label_selected("label_selected"),				// requires is_toggle true -	label_dropshadow("label_shadow", true), +	label_shadow("label_shadow", true),  	auto_resize("auto_resize", false),  	image_unselected("image_unselected"),  	image_selected("image_selected"), @@ -133,7 +133,7 @@ LLButton::LLButton(const LLButton::Params& p)  	mImageOverlayAlignment(LLFontGL::hAlignFromName(p.image_overlay_alignment)),  	mIsToggle(p.is_toggle),  	mScaleImage(p.scale_image), -	mDropShadowedText(p.label_dropshadow), +	mDropShadowedText(p.label_shadow),  	mAutoResize(p.auto_resize),  	mHAlign(p.font_halign),  	mLeftHPad(p.pad_left), diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index 3fa62cc351..e387c91a17 100644 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -74,7 +74,7 @@ public:  	{  		// text label  		Optional<std::string>	label_selected; -		Optional<bool>			label_dropshadow; +		Optional<bool>			label_shadow;  		Optional<bool>			auto_resize;  		// images @@ -105,9 +105,9 @@ public:  		// callbacks  		Optional<CommitCallbackParam>	click_callback, // alias -> commit_callback -															mouse_down_callback, -															mouse_up_callback, -															mouse_held_callback; +										mouse_down_callback, +										mouse_up_callback, +										mouse_held_callback;  		// misc  		Optional<bool>			is_toggle, diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index 5caad1919a..51f9d6bd18 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -141,7 +141,7 @@ LLComboBox::LLComboBox(const LLComboBox::Params& p)  		LLScrollListItem::Params item_params = *it;  		if (it->label.isProvided())  		{ -			item_params.cells.add().value(it->label()); +			item_params.columns.add().value(it->label());  		}  		mList->addRow(item_params); diff --git a/indra/llui/llconsole.h b/indra/llui/llconsole.h index 65149b217f..56e1614948 100644 --- a/indra/llui/llconsole.h +++ b/indra/llui/llconsole.h @@ -58,7 +58,8 @@ public:  		Optional<S32>	font_size_index;  		Params()  		:	max_lines("max_lines", LLUI::sSettingGroups["config"]->getS32("ConsoleMaxLines")), -			persist_time("persist_time", 0.f) // forever +			persist_time("persist_time", 0.f), // forever +			font_size_index("font_size_index")  		{  			mouse_opaque(false);  		} diff --git a/indra/llui/lldraghandle.cpp b/indra/llui/lldraghandle.cpp index 8ecbdb98e1..6e8e37ded3 100644 --- a/indra/llui/lldraghandle.cpp +++ b/indra/llui/lldraghandle.cpp @@ -317,6 +317,23 @@ BOOL LLDragHandle::handleHover(S32 x, S32 y, MASK mask)  		S32 delta_x = screen_x - mDragLastScreenX;  		S32 delta_y = screen_y - mDragLastScreenY; +		// if dragging a docked floater we want to undock +		if (((LLFloater*)getParent())->isDocked()) +		{ +			const S32 SLOP = 12; + +			if (delta_y <= -SLOP ||  +				delta_y >= SLOP) +			{ +				((LLFloater*)getParent())->setDocked(false, false); +				return TRUE; +			} +			else +			{ +				return FALSE; +			} +		} +  		LLRect original_rect = getParent()->getRect();  		LLRect translated_rect = getParent()->getRect();  		translated_rect.translate(delta_x, delta_y); diff --git a/indra/llui/lldraghandle.h b/indra/llui/lldraghandle.h index 86eef7c42c..88ec1d21f8 100644 --- a/indra/llui/lldraghandle.h +++ b/indra/llui/lldraghandle.h @@ -53,7 +53,8 @@ public:  		Optional<LLUIColor> drag_shadow_color;  		Params()  -		:	drag_highlight_color("drag_highlight_color", LLUIColorTable::instance().getColor("DefaultHighlightLight")), +		:	label("label"),	 +			drag_highlight_color("drag_highlight_color", LLUIColorTable::instance().getColor("DefaultHighlightLight")),  			drag_shadow_color("drag_shadow_color", LLUIColorTable::instance().getColor("DefaultShadowDark"))  		{  			mouse_opaque(true); diff --git a/indra/llui/llfiltereditor.cpp b/indra/llui/llfiltereditor.cpp new file mode 100644 index 0000000000..0f36483fc2 --- /dev/null +++ b/indra/llui/llfiltereditor.cpp @@ -0,0 +1,110 @@ +/**  + * @file llfiltereditor.cpp + * @brief LLFilterEditor implementation + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + *  + * Copyright (c) 2001-2009, Linden Research, Inc. + *  + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + *  + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + *  + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + *  + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +// Text editor widget to let users enter a single line. + +#include "linden_common.h" +  +#include "llfiltereditor.h" + +LLFilterEditor::LLFilterEditor(const LLFilterEditor::Params& p) +:	LLUICtrl(p) +{ +	LLLineEditor::Params line_editor_p(p); +	line_editor_p.name("filter edit box"); +	line_editor_p.rect(getLocalRect()); +	line_editor_p.follows.flags(FOLLOWS_ALL); +	line_editor_p.text_pad_right(getRect().getHeight()); +	line_editor_p.keystroke_callback(boost::bind(&LLUICtrl::onCommit, this)); + +	mFilterEditor = LLUICtrlFactory::create<LLLineEditor>(line_editor_p); +	addChild(mFilterEditor); + +	S32 btn_width = getRect().getHeight(); // button is square, and as tall as search editor +	LLRect clear_btn_rect(getRect().getWidth() - btn_width, getRect().getHeight(), getRect().getWidth(), 0); +	LLButton::Params button_params(p.clear_filter_button); +	button_params.name(std::string("clear filter")); +	button_params.rect(clear_btn_rect) ; +	button_params.follows.flags(FOLLOWS_RIGHT|FOLLOWS_TOP); +	button_params.tab_stop(false); +	button_params.click_callback.function(boost::bind(&LLFilterEditor::onClearFilter, this, _2)); + +	mClearFilterButton = LLUICtrlFactory::create<LLButton>(button_params); +	mFilterEditor->addChild(mClearFilterButton); +} + +//virtual +void LLFilterEditor::setValue(const LLSD& value ) +{ +	mFilterEditor->setValue(value); +} + +//virtual +LLSD LLFilterEditor::getValue() const +{ +	return mFilterEditor->getValue(); +} + +//virtual +BOOL LLFilterEditor::setTextArg( const std::string& key, const LLStringExplicit& text ) +{ +	return mFilterEditor->setTextArg(key, text); +} + +//virtual +BOOL LLFilterEditor::setLabelArg( const std::string& key, const LLStringExplicit& text ) +{ +	return mFilterEditor->setLabelArg(key, text); +} + +//virtual +void LLFilterEditor::clear() +{ +	if (mFilterEditor) +	{ +		mFilterEditor->clear(); +	} +} + +void LLFilterEditor::draw() +{ +	mClearFilterButton->setVisible(!mFilterEditor->getWText().empty()); + +	LLUICtrl::draw(); +} + +void LLFilterEditor::onClearFilter(const LLSD& data) +{ +	setText(LLStringUtil::null); +	onCommit(); +} + diff --git a/indra/llui/llfiltereditor.h b/indra/llui/llfiltereditor.h new file mode 100644 index 0000000000..4240fd770c --- /dev/null +++ b/indra/llui/llfiltereditor.h @@ -0,0 +1,86 @@ +/**  + * @file llfiltereditor.h + * @brief Text editor widget that represents a filter operation + * + * Features:  + *		Text entry of a single line (text, delete, left and right arrow, insert, return). + *		Callbacks either on every keystroke or just on the return key. + *		Focus (allow multiple text entry widgets) + *		Clipboard (cut, copy, and paste) + *		Horizontal scrolling to allow strings longer than widget size allows  + *		Pre-validation (limit which keys can be used) + *		Optional line history so previous entries can be recalled by CTRL UP/DOWN + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + *  + * Copyright (c) 2001-2009, Linden Research, Inc. + *  + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + *  + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + *  + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + *  + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_FILTEREDITOR_H +#define LL_FILTEREDITOR_H + +#include "lllineeditor.h" +#include "llbutton.h" + +class LLFilterEditor : public LLUICtrl +{ +public: +	struct Params : public LLInitParam::Block<Params, LLLineEditor::Params> +	{ +		Optional<LLButton::Params> clear_filter_button; + +		Params() +		: clear_filter_button("clear_filter_button") +		{ +			name = "filter_editor"; +		} +	}; + +protected: +	LLFilterEditor(const Params&); +	friend class LLUICtrlFactory; +public: +	virtual ~LLFilterEditor() {} + +	/*virtual*/ void	draw(); + +	void setText(const LLStringExplicit &new_text) { mFilterEditor->setText(new_text); } + +	// LLUICtrl interface +	virtual void	setValue(const LLSD& value ); +	virtual LLSD	getValue() const; +	virtual BOOL	setTextArg( const std::string& key, const LLStringExplicit& text ); +	virtual BOOL	setLabelArg( const std::string& key, const LLStringExplicit& text ); +	virtual void	clear(); + +private: +	void onClearFilter(const LLSD& data); + +	LLLineEditor* mFilterEditor; +	LLButton* mClearFilterButton; +}; + +#endif  // LL_FILTEREDITOR_H diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 153e025385..a397278a2b 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -71,15 +71,8 @@ std::string	LLFloater::sButtonActiveImageNames[BUTTON_COUNT] =  	"minimize.tga",	//BUTTON_MINIMIZE  	"tearoffbox.tga",	//BUTTON_TEAR_OFF  	"closebox.tga",		//BUTTON_EDIT -}; - -std::string	LLFloater::sButtonInactiveImageNames[BUTTON_COUNT] =  -{ -	"close_inactive_blue.tga",	//BUTTON_CLOSE -	"restore_inactive.tga",	//BUTTON_RESTORE -	"minimize_inactive.tga",	//BUTTON_MINIMIZE -	"tearoffbox.tga",	//BUTTON_TEAR_OFF -	"close_inactive_blue.tga",	//BUTTON_EDIT +	"Icon_Dock_Foreground", +	"Icon_Undock_Foreground"  };  std::string	LLFloater::sButtonPressedImageNames[BUTTON_COUNT] =  @@ -89,6 +82,8 @@ std::string	LLFloater::sButtonPressedImageNames[BUTTON_COUNT] =  	"minimize_pressed.tga",	//BUTTON_MINIMIZE  	"tearoff_pressed.tga",	//BUTTON_TEAR_OFF  	"close_in_blue.tga",		//BUTTON_EDIT +	"Icon_Dock_Press", +	"Icon_Undock_Press"  };  std::string	LLFloater::sButtonNames[BUTTON_COUNT] =  @@ -98,6 +93,8 @@ std::string	LLFloater::sButtonNames[BUTTON_COUNT] =  	"llfloater_minimize_btn",	//BUTTON_MINIMIZE  	"llfloater_tear_off_btn",	//BUTTON_TEAR_OFF  	"llfloater_edit_btn",		//BUTTON_EDIT +	"llfloater_dock_btn", +	"llfloater_undock_btn"  };  std::string LLFloater::sButtonToolTips[BUTTON_COUNT] = {}; @@ -114,6 +111,8 @@ std::string LLFloater::sButtonToolTipsIndex[BUTTON_COUNT]=  	"BUTTON_MINIMIZE",//LLTrans::getString("BUTTON_MINIMIZE"),	//"Minimize",	//BUTTON_MINIMIZE  	"BUTTON_TEAR_OFF",//LLTrans::getString("BUTTON_TEAR_OFF"),	//"Tear Off",	//BUTTON_TEAR_OFF  	"BUTTON_EDIT", //LLTrans::getString("BUTTON_EDIT"), //	"Edit",		//BUTTON_EDIT +	"BUTTON_DOCK", +	"BUTTON_UNDOCK"  };  LLFloater::click_callback LLFloater::sButtonCallbacks[BUTTON_COUNT] = @@ -123,6 +122,8 @@ LLFloater::click_callback LLFloater::sButtonCallbacks[BUTTON_COUNT] =  	LLFloater::onClickMinimize, //BUTTON_MINIMIZE  	LLFloater::onClickTearOff,	//BUTTON_TEAR_OFF  	LLFloater::onClickEdit,	//BUTTON_EDIT +	LLFloater::onClickDock, +	LLFloater::onClickDock  };  LLMultiFloater* LLFloater::sHostp = NULL; @@ -189,6 +190,29 @@ bool LLFloater::KeyCompare::equate(const LLSD& a, const LLSD& b)  //************************************ +LLFloater::Params::Params() +:	title("title"), +	short_title("short_title"), +	single_instance("single_instance", false), +	auto_tile("auto_tile", false), +	can_resize("can_resize", false), +	can_minimize("can_minimize", true), +	can_close("can_close", true), +	can_drag_on_left("can_drag_on_left", false), +	can_tear_off("can_tear_off", true), +	save_rect("save_rect", false), +	save_visibility("save_visibility", false), +	open_callback("open_callback"), +	close_callback("close_callback"), +	can_dock("can_dock", false) +{ +	name = "floater"; +	// defaults that differ from LLPanel: +	background_visible = true; +	visible = false; +} + +  //static   const LLFloater::Params& LLFloater::getDefaultParams()  { @@ -217,6 +241,8 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p)  		mEditing(FALSE),  		mButtonScale(1.0f),  		mAutoFocus(TRUE), // automatically take focus when opened +		mCanDock(false), +		mDocked(false),  		mHasBeenDraggedWhileMinimized(FALSE),  		mPreviousMinimizedBottom(0),  		mPreviousMinimizedLeft(0), @@ -289,6 +315,11 @@ void LLFloater::initFloater()  		mButtonsEnabled[BUTTON_MINIMIZE] = TRUE;  	} +	if(mCanDock) +	{ +		mButtonsEnabled[BUTTON_DOCK] = TRUE; +	} +  	buildButtons();  	// Floaters are created in the invisible state	 @@ -1305,6 +1336,36 @@ void LLFloater::setFrontmost(BOOL take_focus)  	}  } +void LLFloater::setCanDock(bool b) +{ +	if(b != mCanDock) +	{ +		mCanDock = b; +		if(mCanDock) +		{ +			mButtonsEnabled[BUTTON_DOCK] = !mDocked; +			mButtonsEnabled[BUTTON_UNDOCK] = mDocked; +		} +		else +		{ +			mButtonsEnabled[BUTTON_DOCK] = FALSE; +			mButtonsEnabled[BUTTON_UNDOCK] = FALSE; +		} +	} +	updateButtons(); +} + +void LLFloater::setDocked(bool docked, bool pop_on_undock) +{ +	if(docked != mDocked && mCanDock) +	{ +		mDocked = docked; +		mButtonsEnabled[BUTTON_DOCK] = !mDocked; +		mButtonsEnabled[BUTTON_UNDOCK] = mDocked; +		updateButtons(); +	} +} +  //static  void LLFloater::setEditModeEnabled(BOOL enable)  { @@ -1381,6 +1442,15 @@ void LLFloater::onClickEdit(LLFloater* self)  	self->mEditing = self->mEditing ? FALSE : TRUE;  } +// static +void LLFloater::onClickDock(LLFloater* self) +{ +	if(self && self->mCanDock) +	{ +		self->setDocked(!self->mDocked, true); +	} +} +  // static   LLFloater* LLFloater::getClosableFloaterFromFocus()  { @@ -2522,6 +2592,7 @@ void LLFloater::initFromParams(const LLFloater::Params& p)  	setCanTearOff(p.can_tear_off);  	setCanMinimize(p.can_minimize);  	setCanClose(p.can_close); +	setCanDock(p.can_dock);  	mDragOnLeft = p.can_drag_on_left;  	mResizable = p.can_resize; diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index b1d33f48e9..f6c6dcf277 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -102,6 +102,8 @@ public:  		BUTTON_MINIMIZE,  		BUTTON_TEAR_OFF,  		BUTTON_EDIT, +		BUTTON_DOCK, +		BUTTON_UNDOCK,  		BUTTON_COUNT  	}; @@ -120,7 +122,7 @@ public:  	{  		Optional<close_callback_t> function;  	}; -	 	 +  	struct Params   	:	public LLInitParam::Block<Params, LLPanel::Params>  	{ @@ -135,31 +137,13 @@ public:  								can_drag_on_left,  								can_tear_off,  								save_rect, -								save_visibility; +								save_visibility, +								can_dock;  		Optional<OpenCallbackParam> open_callback;  		Optional<CloseCallbackParam> close_callback; -		Params() : -			title("title"), -			short_title("short_title"), -			single_instance("single_instance", false), -			auto_tile("auto_tile", false), -			can_resize("can_resize", false), -			can_minimize("can_minimize", true), -			can_close("can_close", true), -			can_drag_on_left("can_drag_on_left", false), -			can_tear_off("can_tear_off", true), -			save_rect("save_rect", false), -			save_visibility("save_visibility", false), -		    open_callback("open_callback"), -			close_callback("close_callback") -		{ -			name = "floater"; -			// defaults that differ from LLPanel: -			background_visible = true; -			visible = false; -		} +		Params();  	};  	// use this to avoid creating your own default LLFloater::Param instance @@ -267,6 +251,12 @@ public:  	const LLSD& 	getKey() { return mKey; }  	BOOL		 	matchesKey(const LLSD& key) { return mSingleInstance || KeyCompare::equate(key, mKey); } +	bool            isDockable() const { return mCanDock; } +	void            setCanDock(bool b); + +	bool            isDocked() const { return mDocked; } +	virtual void    setDocked(bool docked, bool pop_on_undock = true); +  	// Return a closeable floater, if any, given the current focus.  	static LLFloater* getClosableFloaterFromFocus();  @@ -283,6 +273,7 @@ public:  	static void		onClickMinimize(LLFloater* floater);  	static void		onClickTearOff(LLFloater* floater);  	static void		onClickEdit(LLFloater* floater); +	static void     onClickDock(LLFloater* floater);  	static void		setFloaterHost(LLMultiFloater* hostp) {sHostp = hostp; }  	static void		setEditModeEnabled(BOOL enable); @@ -378,11 +369,13 @@ private:  	LLHandle<LLFloater> mHostHandle;  	LLHandle<LLFloater> mLastHostHandle; +	bool            mCanDock; +	bool            mDocked; +  	static LLMultiFloater* sHostp;  	static BOOL		sEditModeEnabled;  	static BOOL		sQuitting;  	static std::string	sButtonActiveImageNames[BUTTON_COUNT]; -	static std::string	sButtonInactiveImageNames[BUTTON_COUNT];  	static std::string	sButtonPressedImageNames[BUTTON_COUNT];  	static std::string	sButtonNames[BUTTON_COUNT];  	static std::string	sButtonToolTips[BUTTON_COUNT]; diff --git a/indra/llui/llhandle.h b/indra/llui/llhandle.h new file mode 100644 index 0000000000..10a7fd4544 --- /dev/null +++ b/indra/llui/llhandle.h @@ -0,0 +1,171 @@ +/**  +* @file llhandle.h +* @brief "Handle" to an object (usually a floater) whose lifetime you don't +* control. +* +* $LicenseInfo:firstyear=2001&license=viewergpl$ +*  +* Copyright (c) 2001-2009, Linden Research, Inc. +*  +* Second Life Viewer Source Code +* The source code in this file ("Source Code") is provided by Linden Lab +* to you under the terms of the GNU General Public License, version 2.0 +* ("GPL"), unless you have obtained a separate licensing agreement +* ("Other License"), formally executed by you and Linden Lab.  Terms of +* the GPL can be found in doc/GPL-license.txt in this distribution, or +* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 +*  +* There are special exceptions to the terms and conditions of the GPL as +* it is applied to this Source Code. View the full text of the exception +* in the file doc/FLOSS-exception.txt in this software distribution, or +* online at +* http://secondlifegrid.net/programs/open_source/licensing/flossexception +*  +* By copying, modifying or distributing this software, you acknowledge +* that you have read and understood your obligations described above, +* and agree to abide by those obligations. +*  +* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +* COMPLETENESS OR PERFORMANCE. +* $/LicenseInfo$ +*/ +#ifndef LLHANDLE_H +#define LLHANDLE_H + +#include "llpointer.h" + +template <typename T> +class LLTombStone : public LLRefCount +{ +public: +	LLTombStone(T* target = NULL) : mTarget(target) {} + +	void setTarget(T* target) { mTarget = target; } +	T* getTarget() const { return mTarget; } +private: +	T* mTarget; +}; + +//	LLHandles are used to refer to objects whose lifetime you do not control or influence.   +//	Calling get() on a handle will return a pointer to the referenced object or NULL,  +//	if the object no longer exists.  Note that during the lifetime of the returned pointer,  +//	you are assuming that the object will not be deleted by any action you perform,  +//	or any other thread, as normal when using pointers, so avoid using that pointer outside of +//	the local code block. +//  +//  https://wiki.lindenlab.com/mediawiki/index.php?title=LLHandle&oldid=79669 + +template <typename T> +class LLHandle +{ +public: +	LLHandle() : mTombStone(sDefaultTombStone) {} +	const LLHandle<T>& operator =(const LLHandle<T>& other)   +	{  +		mTombStone = other.mTombStone; +		return *this;  +	} + +	bool isDead() const  +	{  +		return mTombStone->getTarget() == NULL;  +	} + +	void markDead()  +	{  +		mTombStone = sDefaultTombStone;  +	} + +	T* get() const +	{ +		return mTombStone->getTarget(); +	} + +	friend bool operator== (const LLHandle<T>& lhs, const LLHandle<T>& rhs) +	{ +		return lhs.mTombStone == rhs.mTombStone; +	} +	friend bool operator!= (const LLHandle<T>& lhs, const LLHandle<T>& rhs) +	{ +		return !(lhs == rhs); +	} +	friend bool	operator< (const LLHandle<T>& lhs, const LLHandle<T>& rhs) +	{ +		return lhs.mTombStone < rhs.mTombStone; +	} +	friend bool	operator> (const LLHandle<T>& lhs, const LLHandle<T>& rhs) +	{ +		return lhs.mTombStone > rhs.mTombStone; +	} +protected: + +protected: +	LLPointer<LLTombStone<T> > mTombStone; + +private: +	static LLPointer<LLTombStone<T> > sDefaultTombStone; +}; + +// initialize static "empty" tombstone pointer +template <typename T> LLPointer<LLTombStone<T> > LLHandle<T>::sDefaultTombStone = new LLTombStone<T>(); + + +template <typename T> +class LLRootHandle : public LLHandle<T> +{ +public: +	LLRootHandle(T* object) { bind(object); } +	LLRootHandle() {}; +	~LLRootHandle() { unbind(); } + +	// this is redundant, since a LLRootHandle *is* an LLHandle +	LLHandle<T> getHandle() { return LLHandle<T>(*this); } + +	void bind(T* object)  +	{  +		// unbind existing tombstone +		if (LLHandle<T>::mTombStone.notNull()) +		{ +			if (LLHandle<T>::mTombStone->getTarget() == object) return; +			LLHandle<T>::mTombStone->setTarget(NULL); +		} +		// tombstone reference counted, so no paired delete +		LLHandle<T>::mTombStone = new LLTombStone<T>(object); +	} + +	void unbind()  +	{ +		LLHandle<T>::mTombStone->setTarget(NULL); +	} + +	//don't allow copying of root handles, since there should only be one +private: +	LLRootHandle(const LLRootHandle& other) {}; +}; + +// Use this as a mixin for simple classes that need handles and when you don't +// want handles at multiple points of the inheritance hierarchy +template <typename T> +class LLHandleProvider +{ +protected: +	typedef LLHandle<T> handle_type_t; +	LLHandleProvider()  +	{ +		// provided here to enforce T deriving from LLHandleProvider<T> +	}  + +	LLHandle<T> getHandle()  +	{  +		// perform lazy binding to avoid small tombstone allocations for handle +		// providers whose handles are never referenced +		mHandle.bind(static_cast<T*>(this));  +		return mHandle;  +	} + +private: +	LLRootHandle<T> mHandle; +}; + +#endif diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index f1e7d791d4..702d8e4a39 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -120,7 +120,8 @@ struct LLLayoutStack::LayoutPanel  LLLayoutStack::Params::Params()  :	orientation("orientation", std::string("vertical")), -	animate("animate", TRUE), +	animate("animate", true), +	clip("clip", true),  	border_size("border_size", LLCachedControl<S32>(*LLUI::sSettingGroups["config"], "UIResizeBarHeight", 0))  {  	name="stack"; @@ -132,7 +133,8 @@ LLLayoutStack::LLLayoutStack(const LLLayoutStack::Params& p)  	mMinHeight(0),  	mPanelSpacing(p.border_size),  	mOrientation((p.orientation() == "vertical") ? VERTICAL : HORIZONTAL), -	mAnimate(p.animate) +	mAnimate(p.animate), +	mClip(p.clip)  {}  LLLayoutStack::~LLLayoutStack() @@ -163,7 +165,7 @@ void LLLayoutStack::draw()  		LLPanel* panelp = (*panel_it)->mPanel; -		LLLocalClipRect clip(clip_rect); +		LLLocalClipRect clip(clip_rect, mClip);  		// only force drawing invisible children if visible amount is non-zero  		drawChild(panelp, 0, 0, !clip_rect.isNull());  	} diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h index 480bdb5c17..9459b9990c 100644 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -43,7 +43,8 @@ public:  	{  		Optional<std::string>	orientation;  		Optional<S32>			border_size; -		Optional<bool>	animate; +		Optional<bool>			animate; +		Optional<bool>			clip;  		// mMinWidth and mMinHeight are calculated, not set in XML  		Params(); @@ -100,6 +101,7 @@ private:  	S32 mPanelSpacing;  	bool mAnimate; +	bool mClip;  }; // end class LLLayoutStack  #endif diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 43c22cbf5d..f94eb7fcc3 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -91,7 +91,11 @@ void LLLineEditor::PrevalidateNamedFuncs::declareValues()  LLLineEditor::Params::Params()  :	max_length_bytes("max_length", 254), +    keystroke_callback("keystroke_callback"), +	prevalidate_callback("prevalidate_callback"),  	background_image("background_image"), +	background_image_disabled("background_image_disabled"), +	background_image_focused("background_image_focused"),  	select_on_focus("select_on_focus", false),  	handle_edit_keys_directly("handle_edit_keys_directly", false),  	commit_on_focus_lost("commit_on_focus_lost", true), @@ -100,9 +104,8 @@ LLLineEditor::Params::Params()  	text_color("text_color"),  	text_readonly_color("text_readonly_color"),  	text_tentative_color("text_tentative_color"), -	bg_readonly_color("bg_readonly_color"), -	bg_writeable_color("bg_writeable_color"), -	bg_focus_color("bg_focus_color"), +	highlight_color("highlight_color"), +	preedit_bg_color("preedit_bg_color"),  	border(""),  	is_unicode("is_unicode"),  	drop_shadow_visible("drop_shadow_visible"), @@ -145,18 +148,18 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)  	mSelectAllonFocusReceived( p.select_on_focus ),  	mPassDelete(FALSE),  	mReadOnly(FALSE), -	mImage( NULL ), +	mBgImage( p.background_image ), +	mBgImageDisabled( p.background_image_disabled ), +	mBgImageFocused( p.background_image_focused ),  	mReplaceNewlinesWithSpaces( TRUE ),  	mLabel(p.label),  	mCursorColor(p.cursor_color()),  	mFgColor(p.text_color()),  	mReadOnlyFgColor(p.text_readonly_color()),  	mTentativeFgColor(p.text_tentative_color()), -	mWriteableBgColor(p.bg_writeable_color()), -	mReadOnlyBgColor(p.bg_readonly_color()), -	mFocusBgColor(p.bg_focus_color()), -	mGLFont(p.font), -	mGLFontStyle(LLFontGL::getStyleFromString(p.font.style)) +	mHighlightColor(p.highlight_color()), +	mPreeditBgColor(p.preedit_bg_color()), +	mGLFont(p.font)  {  	llassert( mMaxLengthBytes > 0 ); @@ -183,11 +186,6 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)  	mBorder = LLUICtrlFactory::create<LLViewBorder>(border_p);  	addChild( mBorder ); -	if(p.background_image.isProvided()) -	{ -		mImage = p.background_image; -	} -  	// clamp text padding to current editor size  	updateTextPadding();  	setCursor(mText.length()); @@ -237,6 +235,7 @@ void LLLineEditor::onFocusLost()  	LLUICtrl::onFocusLost();  } +// virtual  void LLLineEditor::onCommit()  {  	// put current line into the line history @@ -247,6 +246,33 @@ void LLLineEditor::onCommit()  	selectAll();  } +// Returns TRUE if user changed value at all +// virtual +BOOL LLLineEditor::isDirty() const +{ +	return mText.getString() != mPrevText; +} + +// Clear dirty state +// virtual +void LLLineEditor::resetDirty() +{ +	mPrevText = mText.getString(); +}		 + +// assumes UTF8 text +// virtual +void LLLineEditor::setValue(const LLSD& value ) +{ +	setText(value.asString()); +} + +//virtual +LLSD LLLineEditor::getValue() const +{ +	return LLSD(getText()); +} +  // line history support  void LLLineEditor::updateHistory() @@ -1497,6 +1523,33 @@ void LLLineEditor::doDelete()  } +void LLLineEditor::drawBackground() +{ +	bool has_focus = hasFocus(); +	LLUIImage* image; +	if ( mReadOnly ) +	{ +		image = mBgImageDisabled; +	} +	else if ( has_focus ) +	{ +		image = mBgImageFocused; +	} +	else +	{ +		image = mBgImage; +	} +	 +	// optionally draw programmatic border +	if (has_focus) +	{ +		image->drawBorder(0, 0, getRect().getWidth(), getRect().getHeight(), +						  gFocusMgr.getFocusColor(), +						  gFocusMgr.getFocusFlashWidth()); +	} +	image->draw(getLocalRect()); +} +  void LLLineEditor::draw()  {  	S32 text_len = mText.length(); @@ -1527,34 +1580,8 @@ void LLLineEditor::draw()  	LLRect background( 0, getRect().getHeight(), getRect().getWidth(), 0 );  	background.stretch( -mBorderThickness ); -	LLColor4 bg_color = mReadOnlyBgColor.get(); - -#if 1 // for when we're ready for image art. -	if( hasFocus()) -	{ -		mImage->drawBorder(0, 0, getRect().getWidth(), getRect().getHeight(), gFocusMgr.getFocusColor(), gFocusMgr.getFocusFlashWidth()); -	} -	mImage->draw(getLocalRect()); -#else // the old programmer art. -	// drawing solids requires texturing be disabled -	{ -		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); -		// draw background for text -		if( !mReadOnly ) -		{ -			if( gFocusMgr.getKeyboardFocus() == this ) -			{ -				bg_color = mFocusBgColor.get(); -			} -			else -			{ -				bg_color = mWriteableBgColor.get(); -			} -		} -		gl_rect_2d(background, bg_color); -	} -#endif - +	drawBackground(); +	  	// draw text  	// With viewer-2 art files, input region is 2 pixels up @@ -1600,7 +1627,8 @@ void LLLineEditor::draw()  						background.mBottom + preedit_standout_position,  						preedit_pixels_right - preedit_standout_gap - 1,  						background.mBottom + preedit_standout_position - preedit_standout_thickness, -						(text_color * preedit_standout_brightness + bg_color * (1 - preedit_standout_brightness)).setAlpha(1.0f)); +						(text_color * preedit_standout_brightness  +						 + mPreeditBgColor * (1 - preedit_standout_brightness)).setAlpha(1.0f));  				}  				else  				{ @@ -1608,7 +1636,8 @@ void LLLineEditor::draw()  						background.mBottom + preedit_marker_position,  						preedit_pixels_right - preedit_marker_gap - 1,  						background.mBottom + preedit_marker_position - preedit_marker_thickness, -						(text_color * preedit_marker_brightness + bg_color * (1 - preedit_marker_brightness)).setAlpha(1.0f)); +						(text_color * preedit_marker_brightness +						 + mPreeditBgColor * (1 - preedit_marker_brightness)).setAlpha(1.0f));  				}  			}  		} @@ -1641,7 +1670,7 @@ void LLLineEditor::draw()  				rendered_pixels_right, text_bottom,  				text_color,  				LLFontGL::LEFT, LLFontGL::BOTTOM, -				mGLFontStyle, +				0,  				LLFontGL::NO_SHADOW,  				select_left - mScrollHPos,  				mMaxHPixels - llround(rendered_pixels_right), @@ -1650,7 +1679,7 @@ void LLLineEditor::draw()  		if( (rendered_pixels_right < (F32)mMaxHPixels) && (rendered_text < text_len) )  		{ -			LLColor4 color(1.f - bg_color.mV[0], 1.f - bg_color.mV[1], 1.f - bg_color.mV[2], 1.f); +			LLColor4 color = mHighlightColor;  			// selected middle  			S32 width = mGLFont->getWidth(mText.getWString().c_str(), mScrollHPos + rendered_text, select_right - mScrollHPos - rendered_text);  			width = llmin(width, mMaxHPixels - llround(rendered_pixels_right)); @@ -1661,7 +1690,7 @@ void LLLineEditor::draw()  				rendered_pixels_right, text_bottom,  				LLColor4( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], 1 ),  				LLFontGL::LEFT, LLFontGL::BOTTOM, -				mGLFontStyle, +				0,  				LLFontGL::NO_SHADOW,  				select_right - mScrollHPos - rendered_text,  				mMaxHPixels - llround(rendered_pixels_right), @@ -1676,7 +1705,7 @@ void LLLineEditor::draw()  				rendered_pixels_right, text_bottom,  				text_color,  				LLFontGL::LEFT, LLFontGL::BOTTOM, -				mGLFontStyle, +				0,  				LLFontGL::NO_SHADOW,  				S32_MAX,  				mMaxHPixels - llround(rendered_pixels_right), @@ -1690,7 +1719,7 @@ void LLLineEditor::draw()  			rendered_pixels_right, text_bottom,  			text_color,  			LLFontGL::LEFT, LLFontGL::BOTTOM, -			mGLFontStyle, +			0,  			LLFontGL::NO_SHADOW,  			S32_MAX,  			mMaxHPixels - llround(rendered_pixels_right), @@ -1728,7 +1757,7 @@ void LLLineEditor::draw()  					mGLFont->render(mText, getCursor(), (F32)(cursor_left + lineeditor_cursor_thickness / 2), text_bottom,   						LLColor4( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], 1 ),  						LLFontGL::LEFT, LLFontGL::BOTTOM, -						mGLFontStyle, +						0,  						LLFontGL::NO_SHADOW,  						1);  				} @@ -1754,7 +1783,7 @@ void LLLineEditor::draw()  							label_color,  							LLFontGL::LEFT,  							LLFontGL::BOTTOM, -							mGLFontStyle, +							0,  							LLFontGL::NO_SHADOW,  							S32_MAX,  							mMaxHPixels - llround(rendered_pixels_right), @@ -1779,7 +1808,7 @@ void LLLineEditor::draw()  							label_color,  							LLFontGL::LEFT,  							LLFontGL::BOTTOM, -							mGLFontStyle, +							0,  							LLFontGL::NO_SHADOW,  							S32_MAX,  							mMaxHPixels - llround(rendered_pixels_right), diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index 4362cff2fe..0986ce5a87 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -84,7 +84,9 @@ public:  		Optional<LLViewBorder::Params>	border; -		Optional<LLUIImage*>			background_image; +		Optional<LLUIImage*>			background_image, +										background_image_disabled, +										background_image_focused;  		Optional<bool>					select_on_focus,  										handle_edit_keys_directly, @@ -96,10 +98,9 @@ public:  										text_color,  										text_readonly_color,  										text_tentative_color, -										bg_readonly_color, -										bg_writeable_color, -										bg_focus_color; - +										highlight_color, +										preedit_bg_color; +		  		Optional<S32>					text_pad_left,  										text_pad_right; @@ -107,7 +108,7 @@ public:  										drop_shadow_visible,	  										border_drop_shadow_visible,  										bg_visible; - +		  		Params();  	};  protected: @@ -163,12 +164,12 @@ public:  	virtual void 	setRect(const LLRect& rect);  	virtual BOOL	acceptsTextInput() const;  	virtual void	onCommit(); -	virtual BOOL	isDirty() const { return mText.getString() != mPrevText; }	// Returns TRUE if user changed value at all -	virtual void	resetDirty() { mPrevText = mText.getString(); }		// Clear dirty state +	virtual BOOL	isDirty() const;	// Returns TRUE if user changed value at all +	virtual void	resetDirty();		// Clear dirty state  	// assumes UTF8 text -	virtual void	setValue(const LLSD& value ) { setText(value.asString()); } -	virtual LLSD	getValue() const { return LLSD(getText()); } +	virtual void	setValue(const LLSD& value ); +	virtual LLSD	getValue() const;  	virtual BOOL	setTextArg( const std::string& key, const LLStringExplicit& text );  	virtual BOOL	setLabelArg( const std::string& key, const LLStringExplicit& text ); @@ -197,16 +198,10 @@ public:  	void setFgColor( const LLColor4& c )			{ mFgColor = c; }  	void setReadOnlyFgColor( const LLColor4& c )	{ mReadOnlyFgColor = c; }  	void setTentativeFgColor(const LLColor4& c)		{ mTentativeFgColor = c; } -	void setWriteableBgColor( const LLColor4& c )	{ mWriteableBgColor = c; } -	void setReadOnlyBgColor( const LLColor4& c )	{ mReadOnlyBgColor = c; } -	void setFocusBgColor(const LLColor4& c)			{ mFocusBgColor = c; }  	const LLColor4& getFgColor() const			{ return mFgColor.get(); }  	const LLColor4& getReadOnlyFgColor() const	{ return mReadOnlyFgColor.get(); }  	const LLColor4& getTentativeFgColor() const { return mTentativeFgColor.get(); } -	const LLColor4& getWriteableBgColor() const	{ return mWriteableBgColor.get(); } -	const LLColor4& getReadOnlyBgColor() const	{ return mReadOnlyBgColor.get(); } -	const LLColor4& getFocusBgColor() const		{ return mFocusBgColor.get(); }  	void			setIgnoreArrowKeys(BOOL b)		{ mIgnoreArrowKeys = b; }  	void			setIgnoreTab(BOOL b)			{ mIgnoreTab = b; } @@ -266,6 +261,9 @@ private:  	BOOL			handleControlKey(KEY key, MASK mask);  	S32				handleCommitKey(KEY key, MASK mask);  	void			updateTextPadding(); +	 +	// Draw the background image depending on enabled/focused state. +	void			drawBackground();  	//  	// private data members @@ -294,7 +292,6 @@ protected:  	LLViewBorder* mBorder;  	const LLFontGL*	mGLFont; -	U8          mGLFontStyle;  	S32			mMaxLengthBytes;			// Max length of the UTF8 string in bytes  	S32			mCursorPos;					// I-beam is just after the mCursorPos-th character.  	S32			mScrollHPos;				// Horizontal offset from the start of mText.  Used for scrolling. @@ -326,9 +323,8 @@ protected:  	LLUIColor	mFgColor;  	LLUIColor	mReadOnlyFgColor;  	LLUIColor	mTentativeFgColor; -	LLUIColor	mWriteableBgColor; -	LLUIColor	mReadOnlyBgColor; -	LLUIColor	mFocusBgColor; +	LLUIColor	mHighlightColor;		// background for selected text +	LLUIColor	mPreeditBgColor;		// preedit marker background color  	S32			mBorderThickness; @@ -349,7 +345,9 @@ protected:  private:  	// Instances that by default point to the statics but can be overidden in XML. -	LLPointer<LLUIImage> mImage; +	LLPointer<LLUIImage> mBgImage; +	LLPointer<LLUIImage> mBgImageDisabled; +	LLPointer<LLUIImage> mBgImageFocused;  	BOOL        mReplaceNewlinesWithSpaces; // if false, will replace pasted newlines with paragraph symbol. diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index ade88d2714..fdb4bdd5c1 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -49,12 +49,12 @@  #include "llmath.h"  #include "llrender.h"  #include "llfocusmgr.h" -#include "llfont.h"  #include "llcoord.h"  #include "llwindow.h"  #include "llcriticaldamp.h"  #include "lluictrlfactory.h" +#include "llbutton.h"  #include "llfontgl.h"  #include "llresmgr.h"  #include "llui.h" @@ -1453,6 +1453,7 @@ void LLMenuItemBranchDownGL::draw( void )  	setHover(FALSE);  } +  class LLMenuScrollItem : public LLMenuItemCallGL  {  public: @@ -1461,10 +1462,18 @@ public:  		ARROW_DOWN,  		ARROW_UP  	}; +	struct ArrowTypes : public LLInitParam::TypeValuesHelper<EArrowType, ArrowTypes> +	{ +		static void declareValues() +		{ +			declare("up", ARROW_UP); +			declare("down", ARROW_DOWN); +		} +	};  	struct Params : public LLInitParam::Block<Params, LLMenuItemCallGL::Params>  	{ -		Optional<EArrowType> arrow_type; +		Optional<EArrowType, ArrowTypes> arrow_type;  		Optional<CommitCallbackParam> scroll_callback;  	}; diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index 7d5cc25e1e..262f75f1e1 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -380,6 +380,7 @@ public:  		Params()  		:	jump_key("jump_key", KEY_NONE), +			horizontal_layout("horizontal_layout"),  			can_tear_off("tear_off", false),  			drop_shadow("drop_shadow", true),  			bg_visible("bg_visible", true), diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 50fee41029..2b6ae1f67e 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -384,7 +384,7 @@ LLNotificationTemplate::LLNotificationTemplate() :  }  LLNotification::LLNotification(const LLNotification::Params& p) :  -	mTimestamp(p.timestamp),  +	mTimestamp(p.time_stamp),   	mSubstitutions(p.substitutions),  	mPayload(p.payload),  	mExpiresAt(0), diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 512886790c..63eae7278f 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -294,7 +294,7 @@ public:  		Optional<LLSD>							payload;  		Optional<ENotificationPriority>			priority;  		Optional<LLSD>							form_elements; -		Optional<LLDate>						timestamp; +		Optional<LLDate>						time_stamp;  		Optional<LLNotificationContext*>		context;  		struct Functor : public LLInitParam::Choice<Functor> @@ -312,19 +312,23 @@ public:  		Params()  		:	name("name"),  			priority("priority", NOTIFICATION_PRIORITY_UNSPECIFIED), -			timestamp("time_stamp") +			time_stamp("time_stamp"), +			payload("payload"), +			form_elements("form_elements")  		{ -			timestamp = LLDate::now(); +			time_stamp = LLDate::now();  		}  		Params(const std::string& _name)  -			:	name("name"), -				priority("priority", NOTIFICATION_PRIORITY_UNSPECIFIED), -				timestamp("time_stamp") +		:	name("name"), +			priority("priority", NOTIFICATION_PRIORITY_UNSPECIFIED), +			time_stamp("time_stamp"), +			payload("payload"), +			form_elements("form_elements")  		{  			functor.name = _name;  			name = _name; -			timestamp = LLDate::now(); +			time_stamp = LLDate::now();  		}  	}; diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index 116096b7b3..9fb38bc316 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -43,6 +43,7 @@  #include "llerror.h"  #include "lltimer.h" +#include "llbutton.h"  #include "llmenugl.h"  //#include "llstatusbar.h"  #include "llui.h" @@ -53,7 +54,6 @@  #include "lluictrl.h"  #include "lluictrlfactory.h"  #include "llviewborder.h" -#include "llbutton.h"  #include "lltabcontainer.h"  static LLDefaultChildRegistry::Register<LLPanel> r1("panel", &LLPanel::fromXML); @@ -65,6 +65,7 @@ const LLPanel::Params& LLPanel::getDefaultParams()  LLPanel::Params::Params()  :	has_border("border", false), +	border(""),  	bg_opaque_color("bg_opaque_color"),  	bg_alpha_color("bg_alpha_color"),  	background_visible("background_visible", false), @@ -430,7 +431,7 @@ void LLPanel::initFromParams(const LLPanel::Params& p)  		it != p.strings().end();  		++it)  	{ -		mUIStrings[it->name] = it->text; +		mUIStrings[it->name] = it->value;  	}  	setLabel(p.label()); diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h index 381cba2db3..4140e3aa93 100644 --- a/indra/llui/llpanel.h +++ b/indra/llui/llpanel.h @@ -37,8 +37,6 @@  #include "llcallbackmap.h"  #include "lluictrl.h" -#include "llbutton.h" -#include "lllineeditor.h"  #include "llviewborder.h"  #include "lluistring.h"  #include "v4color.h" @@ -49,6 +47,7 @@ const S32 LLPANEL_BORDER_WIDTH = 1;  const BOOL BORDER_YES = TRUE;  const BOOL BORDER_NO = FALSE; +class LLButton;  /*   * General purpose concrete view base class. @@ -62,11 +61,11 @@ public:  	struct LocalizedString : public LLInitParam::Block<LocalizedString>  	{  		Mandatory<std::string>	name; -		Mandatory<std::string>	text; +		Mandatory<std::string>	value;  		LocalizedString()  		:	name("name"), -			text("value") +			value("value")  		{}  	}; diff --git a/indra/llui/llprogressbar.cpp b/indra/llui/llprogressbar.cpp index 7a34cc6792..c8b6e814e1 100644 --- a/indra/llui/llprogressbar.cpp +++ b/indra/llui/llprogressbar.cpp @@ -50,10 +50,7 @@ static LLDefaultChildRegistry::Register<LLProgressBar> r("progress_bar");  LLProgressBar::Params::Params()  :	image_bar("image_bar"),  	image_fill("image_fill"), -	image_shadow("image_shadow"),  	color_bar("color_bar"), -	color_bar2("color_bar2"), -	color_shadow("color_shadow"),  	color_bg("color_bg")  {} @@ -61,12 +58,9 @@ LLProgressBar::Params::Params()  LLProgressBar::LLProgressBar(const LLProgressBar::Params& p)   :	LLView(p),  	mImageBar(p.image_bar), -	mImageShadow(p.image_shadow),  	mImageFill(p.image_fill),  	mColorBackground(p.color_bg()),  	mColorBar(p.color_bar()), -	mColorBar2(p.color_bar2()), -	mColorShadow(p.color_shadow()),  	mPercentDone(0.f)  {} @@ -85,10 +79,10 @@ void LLProgressBar::draw()  	F32 alpha = 0.5f + 0.5f*0.5f*(1.f + (F32)sin(3.f*timer.getElapsedTimeF32()));  	LLColor4 bar_color = mColorBar.get(); -	bar_color.mV[3] = alpha; +	bar_color.mV[VALPHA] *= alpha; // modulate alpha  	LLRect progress_rect = getLocalRect();  	progress_rect.mRight = llround(getRect().getWidth() * (mPercentDone / 100.f)); -	mImageFill->draw(progress_rect); +	mImageFill->draw(progress_rect, bar_color);  }  void LLProgressBar::setPercent(const F32 percent) diff --git a/indra/llui/llprogressbar.h b/indra/llui/llprogressbar.h index 5c2f73ef9e..b6a5b0400d 100644 --- a/indra/llui/llprogressbar.h +++ b/indra/llui/llprogressbar.h @@ -43,12 +43,9 @@ public:  	struct Params : public LLInitParam::Block<Params, LLView::Params>  	{  		Optional<LLUIImage*>	image_bar, -								image_fill, -								image_shadow; +								image_fill;  		Optional<LLUIColor>		color_bar, -								color_bar2, -								color_shadow,  								color_bg;  		Params(); @@ -65,10 +62,7 @@ private:  	LLPointer<LLUIImage>	mImageBar;  	LLUIColor	mColorBar; -	LLUIColor	mColorBar2; -	LLPointer<LLUIImage>	mImageShadow; -	LLUIColor    mColorShadow;  	LLUIColor    mColorBackground;  	LLPointer<LLUIImage>	mImageFill; diff --git a/indra/llui/llresizehandle.cpp b/indra/llui/llresizehandle.cpp index 90f51b9919..7449c339a0 100644 --- a/indra/llui/llresizehandle.cpp +++ b/indra/llui/llresizehandle.cpp @@ -45,7 +45,9 @@  const S32 RESIZE_BORDER_WIDTH = 3;  LLResizeHandle::Params::Params() -:	corner("corner") +:	corner("corner"), +	min_width("min_width"), +	min_height("min_height")  {  	name = "resize_handle";  } diff --git a/indra/llui/llrngwriter.cpp b/indra/llui/llrngwriter.cpp new file mode 100644 index 0000000000..cf23e3af15 --- /dev/null +++ b/indra/llui/llrngwriter.cpp @@ -0,0 +1,315 @@ +/**  + * @file llrngwriter.cpp + * @brief Generates Relax NG schema from param blocks + * + * $LicenseInfo:firstyear=2003&license=viewergpl$ + *  + * Copyright (c) 2003-2009, Linden Research, Inc. + *  + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + *  + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + *  + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + *  + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llrngwriter.h" +#include "lluicolor.h" +#include "lluictrlfactory.h" + +// +// LLRNGWriter - writes Relax NG schema files based on a param block +// +LLRNGWriter::LLRNGWriter() +{ +	// register various callbacks for inspecting the contents of a param block +	registerInspectFunc<bool>(boost::bind(&LLRNGWriter::writeAttribute, this, "boolean", _1, _2, _3, _4)); +	registerInspectFunc<std::string>(boost::bind(&LLRNGWriter::writeAttribute, this, "string", _1, _2, _3, _4)); +	registerInspectFunc<U8>(boost::bind(&LLRNGWriter::writeAttribute, this, "unsignedByte", _1, _2, _3, _4)); +	registerInspectFunc<S8>(boost::bind(&LLRNGWriter::writeAttribute, this, "signedByte", _1, _2, _3, _4)); +	registerInspectFunc<U16>(boost::bind(&LLRNGWriter::writeAttribute, this, "unsignedShort", _1, _2, _3, _4)); +	registerInspectFunc<S16>(boost::bind(&LLRNGWriter::writeAttribute, this, "signedShort", _1, _2, _3, _4)); +	registerInspectFunc<U32>(boost::bind(&LLRNGWriter::writeAttribute, this, "unsignedInt", _1, _2, _3, _4)); +	registerInspectFunc<S32>(boost::bind(&LLRNGWriter::writeAttribute, this, "integer", _1, _2, _3, _4)); +	registerInspectFunc<F32>(boost::bind(&LLRNGWriter::writeAttribute, this, "float", _1, _2, _3, _4)); +	registerInspectFunc<F64>(boost::bind(&LLRNGWriter::writeAttribute, this, "double", _1, _2, _3, _4)); +	registerInspectFunc<LLColor4>(boost::bind(&LLRNGWriter::writeAttribute, this, "string", _1, _2, _3, _4)); +	registerInspectFunc<LLUIColor>(boost::bind(&LLRNGWriter::writeAttribute, this, "string", _1, _2, _3, _4)); +	registerInspectFunc<LLUUID>(boost::bind(&LLRNGWriter::writeAttribute, this, "string", _1, _2, _3, _4)); +	registerInspectFunc<LLSD>(boost::bind(&LLRNGWriter::writeAttribute, this, "string", _1, _2, _3, _4)); +} + +void LLRNGWriter::writeRNG(const std::string& type_name, LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const std::string& xml_namespace) +{ +	mGrammarNode = node; +	mGrammarNode->setName("grammar"); +	mGrammarNode->createChild("xmlns", true)->setStringValue("http://relaxng.org/ns/structure/1.0"); +	mGrammarNode->createChild("datatypeLibrary", true)->setStringValue("http://www.w3.org/2001/XMLSchema-datatypes"); +	mGrammarNode->createChild("ns", true)->setStringValue(xml_namespace); + +	node = mGrammarNode->createChild("start", false); +	node = node->createChild("ref", false); +	node->createChild("name", true)->setStringValue(type_name); + +	addDefinition(type_name, block); +} + +void LLRNGWriter::addDefinition(const std::string& type_name, const LLInitParam::BaseBlock& block) +{ +	if (mDefinedElements.find(type_name) != mDefinedElements.end()) return; +	mDefinedElements.insert(type_name); + +	LLXMLNodePtr node = mGrammarNode->createChild("define", false); +	node->createChild("name", true)->setStringValue(type_name); + +	mElementNode = node->createChild("element", false); +	mElementNode->createChild("name", true)->setStringValue(type_name); +	mChildrenNode = mElementNode->createChild("zeroOrMore", false)->createChild("choice", false); + +	mAttributesWritten.first = mElementNode; +	mAttributesWritten.second.clear(); +	mElementsWritten.clear(); + +	block.inspectBlock(*this); + +	// add includes for all possible children +	const std::type_info* type = *LLWidgetTypeRegistry::instance().getValue(type_name); +	const widget_registry_t* widget_registryp = LLChildRegistryRegistry::instance().getValue(type); +	 +	// add include declarations for all valid children +	for (widget_registry_t::Registrar::registry_map_t::const_iterator it = widget_registryp->currentRegistrar().beginItems(); +		it != widget_registryp->currentRegistrar().endItems(); +		++it) +	{ +		std::string child_name = it->first; +		if (child_name == type_name) +		{ +			continue; +		} +		 +		LLXMLNodePtr old_element_node = mElementNode; +		LLXMLNodePtr old_child_node = mChildrenNode; +		addDefinition(child_name, (*LLDefaultParamBlockRegistry::instance().getValue(type))()); +		mElementNode = old_element_node; +		mChildrenNode = old_child_node; + +		mChildrenNode->createChild("ref", false)->createChild("name", true)->setStringValue(child_name); +	} + +	if (mChildrenNode->mChildren.isNull()) +	{ +		// remove unused children node +		mChildrenNode->mParent->mParent->deleteChild(mChildrenNode->mParent); +	} +} + +void LLRNGWriter::writeAttribute(const std::string& type, const Parser::name_stack_t& stack, S32 min_count, S32 max_count, const std::vector<std::string>* possible_values) +{ +	if (max_count == 0) return; + +	name_stack_t non_empty_names; +	std::string attribute_name; +	for (name_stack_t::const_iterator it = stack.begin(); +		it != stack.end(); +		++it) +	{ +		const std::string& name = it->first; +		if (!name.empty()) +		{ +			non_empty_names.push_back(*it); +		} +	} + +	if (non_empty_names.empty()) return; + +	for (name_stack_t::const_iterator it = non_empty_names.begin(); +		it != non_empty_names.end(); +		++it) +	{ +		if (!attribute_name.empty()) +		{ +			attribute_name += "."; +		} +		attribute_name += it->first; +	} + +	// singular attribute, e.g. <foo bar="1"/> +	if (non_empty_names.size() == 1 && max_count == 1) +	{ +		if (mAttributesWritten.second.find(attribute_name) == mAttributesWritten.second.end()) +		{ +			LLXMLNodePtr node = createCardinalityNode(mElementNode, min_count, max_count)->createChild("attribute", false); +			node->createChild("name", true)->setStringValue(attribute_name); +			node->createChild("data", false)->createChild("type", true)->setStringValue(type); + +			mAttributesWritten.second.insert(attribute_name); +		} +	} +	// compound attribute +	else +	{ +		std::string element_name; + +		// traverse all but last element, leaving that as an attribute name +		name_stack_t::const_iterator end_it = non_empty_names.end(); +		end_it--; + +		for (name_stack_t::const_iterator it = non_empty_names.begin(); +			it != end_it; +			++it) +		{ +			if (it != non_empty_names.begin()) +			{ +				element_name += "."; +			} +			element_name += it->first; +		} + +		elements_map_t::iterator found_it = mElementsWritten.find(element_name); +		// <choice> +		//   <group> +		//     <optional> +		//	     <attribute name="foo.bar"><data type="string"/></attribute> +		//     </optional> +		//     <optional> +		//       <attribute name="foo.baz"><data type="integer"/></attribute> +		//     </optional> +		//   </group> +		//   <element name="foo"> +		//     <optional> +		//       <attribute name="bar"><data type="string"/></attribute> +		//     </optional> +		//     <optional> +		//       <attribute name="baz"><data type="string"/></attribute> +		//     </optional> +		//   </element> +		//   <element name="outer.foo"> +		//     <ref name="foo"/> +		//   </element> +		// </choice> + +		if (found_it != mElementsWritten.end()) +		{ +			// reuse existing element +			LLXMLNodePtr choice_node = found_it->second.first; + +			// attribute with this name not already written? +			if (found_it->second.second.find(attribute_name) == found_it->second.second.end()) +			{ +				// append to <group> +				LLXMLNodePtr node = choice_node->mChildren->head; +				node = createCardinalityNode(node, min_count, max_count)->createChild("attribute", false); +				node->createChild("name", true)->setStringValue(attribute_name); +				addTypeNode(node, type, possible_values); + +				// append to <element> +				node = choice_node->mChildren->head->mNext->mChildren->head; +				node = createCardinalityNode(node, min_count, max_count)->createChild("attribute", false); +				node->createChild("name", true)->setStringValue(non_empty_names.back().first); +				addTypeNode(node, type, possible_values); + +				// append to <element> +				//node = choice_node->mChildren->head->mNext->mNext->mChildren->head; +				//node = createCardinalityNode(node, min_count, max_count)->createChild("attribute", false); +				//node->createChild("name", true)->setStringValue(non_empty_names.back().first); +				//addTypeNode(node, type, possible_values); + +				found_it->second.second.insert(attribute_name); +			} +		} +		else +		{ +			LLXMLNodePtr choice_node = mElementNode->createChild("choice", false); + +			LLXMLNodePtr node = choice_node->createChild("group", false); +			node = createCardinalityNode(node, min_count, max_count)->createChild("attribute", false); +			node->createChild("name", true)->setStringValue(attribute_name); +			addTypeNode(node, type, possible_values); + +			node = choice_node->createChild("optional", false); +			node = node->createChild("element", false); +			node->createChild("name", true)->setStringValue(element_name); +			node = createCardinalityNode(node, min_count, max_count)->createChild("attribute", false); +			node->createChild("name", true)->setStringValue(non_empty_names.back().first); +			addTypeNode(node, type, possible_values); +			 +			//node = choice_node->createChild("optional", false); +			//node = node->createChild("element", false); +			//node->createChild("name", true)->setStringValue(mDefinitionName + "." + element_name); +			//node = createCardinalityNode(node, min_count, max_count)->createChild("attribute", false); +			//node->createChild("name", true)->setStringValue(non_empty_names.back().first); +			//addTypeNode(node, type, possible_values); + +			attribute_data_t& attribute_data = mElementsWritten[element_name]; +			attribute_data.first = choice_node; +			attribute_data.second.insert(attribute_name); +		} +	} +} + +void LLRNGWriter::addTypeNode(LLXMLNodePtr parent_node, const std::string& type, const std::vector<std::string>* possible_values) +{ +	if (possible_values) +	{ +		LLXMLNodePtr enum_node = parent_node->createChild("choice", false); +		for (std::vector<std::string>::const_iterator it = possible_values->begin(); +			it != possible_values->end(); +			++it) +		{ +			enum_node->createChild("value", false)->setStringValue(*it); +		} +	} +	else +	{ +		parent_node->createChild("data", false)->createChild("type", true)->setStringValue(type); +	} +} + +LLXMLNodePtr LLRNGWriter::createCardinalityNode(LLXMLNodePtr parent_node, S32 min_count, S32 max_count) +{ +	// unlinked by default, meaning this attribute is forbidden +	LLXMLNodePtr count_node = new LLXMLNode(); +	if (min_count == 0) +	{ +		if (max_count == 1) +		{ +			count_node = parent_node->createChild("optional", false); +		} +		else if (max_count > 1) +		{ +			count_node = parent_node->createChild("zeroOrMore", false); +		}	 +	} +	else if (min_count >= 1) +	{ +		if (max_count == 1 && min_count == 1) +		{ +			// just add raw element, will count as 1 and only 1 +			count_node = parent_node; +		} +		else +		{ +			count_node = parent_node->createChild("oneOrMore", false); +		} +	} +	return count_node; +} diff --git a/indra/llui/llrngwriter.h b/indra/llui/llrngwriter.h new file mode 100644 index 0000000000..66807577b5 --- /dev/null +++ b/indra/llui/llrngwriter.h @@ -0,0 +1,69 @@ +/**  + * @file llrngwriter.h + * @brief Generates Relax NG schema files from a param block + * + * $LicenseInfo:firstyear=2003&license=viewergpl$ + *  + * Copyright (c) 2003-2009, Linden Research, Inc. + *  + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + *  + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + *  + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + *  + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LLRNGWRITER_H +#define LLRNGWRITER_H + +#include "llinitparam.h" +#include "llxmlnode.h" + +class LLRNGWriter : public LLInitParam::Parser +{ +	LOG_CLASS(LLRNGWriter); +public: +	void writeRNG(const std::string& name, LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const std::string& xml_namespace); +	void addDefinition(const std::string& type_name, const LLInitParam::BaseBlock& block); + +	/*virtual*/ std::string getCurrentElementName() { return LLStringUtil::null; } + +	LLRNGWriter(); + +private: +	LLXMLNodePtr createCardinalityNode(LLXMLNodePtr parent_node, S32 min_count, S32 max_count); +	void addTypeNode(LLXMLNodePtr parent_node, const std::string& type, const std::vector<std::string>* possible_values); + +	void writeAttribute(const std::string& type, const Parser::name_stack_t&, S32 min_count, S32 max_count, const std::vector<std::string>* possible_values); +	LLXMLNodePtr	mElementNode; +	LLXMLNodePtr	mChildrenNode; +	LLXMLNodePtr	mGrammarNode; +	std::string		mDefinitionName; + +	typedef std::pair<LLXMLNodePtr, std::set<std::string> >  attribute_data_t; +	typedef std::map<std::string, attribute_data_t> elements_map_t; +	typedef std::set<std::string> defined_elements_t; + +	defined_elements_t	mDefinedElements; +	attribute_data_t	mAttributesWritten; +	elements_map_t		mElementsWritten; +}; + +#endif //LLRNGWRITER_H diff --git a/indra/llui/llscrolllistcell.cpp b/indra/llui/llscrolllistcell.cpp index 4e6de24160..cd43e194d2 100644 --- a/indra/llui/llscrolllistcell.cpp +++ b/indra/llui/llscrolllistcell.cpp @@ -177,7 +177,6 @@ LLScrollListText::LLScrollListText(const LLScrollListCell::Params& p)  	mFont(p.font),  	mColor(p.color),  	mUseColor(p.color.isProvided()), -	mFontStyle(LLFontGL::NORMAL),  	mFontAlignment(p.font_halign),  	mVisible(p.visible),  	mHighlightCount( 0 ), @@ -240,6 +239,13 @@ void LLScrollListText::setText(const LLStringExplicit& text)  	mText = text;  } +void LLScrollListText::setFontStyle(const U8 font_style) +{ +	LLFontDescriptor new_desc(mFont->getFontDesc()); +	new_desc.setStyle(font_style); +	mFont = LLFontGL::getFont(new_desc); +} +  //virtual  void LLScrollListText::setValue(const LLSD& text)  { @@ -308,7 +314,7 @@ void LLScrollListText::draw(const LLColor4& color, const LLColor4& highlight_col  						display_color,  						mFontAlignment,  						LLFontGL::BOTTOM,  -						mFontStyle, +						0,  						LLFontGL::NO_SHADOW,  						string_chars,   						getWidth(), diff --git a/indra/llui/llscrolllistcell.h b/indra/llui/llscrolllistcell.h index 2ab13f7618..9d3fa65f64 100644 --- a/indra/llui/llscrolllistcell.h +++ b/indra/llui/llscrolllistcell.h @@ -145,14 +145,13 @@ public:  	/*virtual*/ BOOL	isText() const;  	void			setText(const LLStringExplicit& text); -	void			setFontStyle(const U8 font_style) { mFontStyle = font_style; } +	void			setFontStyle(const U8 font_style);  private:  	LLUIString		mText;  	const LLFontGL*	mFont;  	LLColor4		mColor;  	U8				mUseColor; -	U8				mFontStyle;  	LLFontGL::HAlign mFontAlignment;  	BOOL			mVisible;  	S32				mHighlightCount; diff --git a/indra/llui/llscrolllistcolumn.h b/indra/llui/llscrolllistcolumn.h index 712ea56454..23318fd7c4 100644 --- a/indra/llui/llscrolllistcolumn.h +++ b/indra/llui/llscrolllistcolumn.h @@ -121,7 +121,7 @@ public:  			Alternative<F32>		relative_width;  			Width() -			:	dynamic_width("dynamicwidth", false), +			:	dynamic_width("dynamic_width", false),  				pixel_width("width"),  				relative_width("relative_width", -1.f)  			{ diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 84a725ce02..e8627586ea 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -102,11 +102,11 @@ struct SortScrollListItem  //---------------------------------------------------------------------------  LLScrollListCtrl::Contents::Contents() -:	columns("columns"), -	rows("rows") +:	columns("column"), +	rows("row")  { -	addSynonym(columns, "column"); -	addSynonym(rows, "row"); +	addSynonym(columns, "columns"); +	addSynonym(rows, "rows");  }  LLScrollListCtrl::Params::Params() @@ -126,10 +126,11 @@ LLScrollListCtrl::Params::Params()  	bg_selected_color("bg_selected_color"),  	fg_disable_color("fg_disable_color"),  	bg_writeable_color("bg_writeable_color"), -	bg_read_only_color("bg_read_only_color"), +	bg_readonly_color("bg_readonly_color"),  	bg_stripe_color("bg_stripe_color"),  	hovered_color("hovered_color"), -	highlighted_color("highlighted_color") +	highlighted_color("highlighted_color"), +	contents("")  {  	name = "scroll_list";  	mouse_opaque = true; @@ -170,7 +171,7 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p)  	mBackgroundVisible(p.background_visible),  	mDrawStripes(p.draw_stripes),  	mBgWriteableColor(p.bg_writeable_color()), -	mBgReadOnlyColor(p.bg_read_only_color()), +	mBgReadOnlyColor(p.bg_readonly_color()),  	mBgSelectedColor(p.bg_selected_color()),  	mBgStripeColor(p.bg_stripe_color()),  	mFgSelectedColor(p.fg_selected_color()), @@ -1082,12 +1083,12 @@ LLScrollListItem* LLScrollListCtrl::addSeparator(EAddPosition pos)  {  	LLScrollListItem::Params separator_params;  	separator_params.enabled(false); -	LLScrollListCell::Params cell_params; -	cell_params.type = "icon"; -	cell_params.value = "menu_separator"; -	cell_params.color = LLColor4(0.f, 0.f, 0.f, 0.7f); -	cell_params.font_halign = LLFontGL::HCENTER; -	separator_params.cells.add(cell_params); +	LLScrollListCell::Params column_params; +	column_params.type = "icon"; +	column_params.value = "menu_separator"; +	column_params.color = LLColor4(0.f, 0.f, 0.f, 0.7f); +	column_params.font_halign = LLFontGL::HCENTER; +	separator_params.columns.add(column_params);  	return addRow( separator_params, pos );  } @@ -1249,7 +1250,7 @@ LLScrollListItem* LLScrollListCtrl::addStringUUIDItem(const std::string& item_te  		LLScrollListItem::Params item_p;  		item_p.enabled(enabled);  		item_p.value(id); -		item_p.cells.add().value(item_text).type("text"); +		item_p.columns.add().value(item_text).type("text");  		return addRow( item_p, pos );  	} @@ -2635,8 +2636,8 @@ LLScrollListItem* LLScrollListCtrl::addRow(const LLScrollListItem::Params& item_  	// Add any columns we don't already have  	S32 col_index = 0; -	for(LLInitParam::ParamIterator<LLScrollListCell::Params>::const_iterator itor = item_p.cells().begin(); -		itor != item_p.cells().end(); +	for(LLInitParam::ParamIterator<LLScrollListCell::Params>::const_iterator itor = item_p.columns().begin(); +		itor != item_p.columns().end();  		++itor)  	{  		LLScrollListCell::Params cell_p = *itor; @@ -2687,7 +2688,7 @@ LLScrollListItem* LLScrollListCtrl::addRow(const LLScrollListItem::Params& item_  		col_index++;  	} -	if (item_p.cells().empty()) +	if (item_p.columns().empty())  	{  		if (mColumns.empty())  		{ @@ -2742,7 +2743,7 @@ LLScrollListItem* LLScrollListCtrl::addSimpleElement(const std::string& value, E  	LLScrollListItem::Params item_params;  	item_params.value(entry_id); -	item_params.cells.add() +	item_params.columns.add()  		.value(value)  		.font(LLFontGL::getFontSansSerifSmall()); diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h index 60cd9239e2..c1800419be 100644 --- a/indra/llui/llscrolllistctrl.h +++ b/indra/llui/llscrolllistctrl.h @@ -99,7 +99,7 @@ public:  							bg_selected_color,  							fg_disable_color,  							bg_writeable_color, -							bg_read_only_color, +							bg_readonly_color,  							bg_stripe_color,  							hovered_color,  							highlighted_color; diff --git a/indra/llui/llscrolllistitem.h b/indra/llui/llscrolllistitem.h index 4237d5b304..c2b7effbc7 100644 --- a/indra/llui/llscrolllistitem.h +++ b/indra/llui/llscrolllistitem.h @@ -68,7 +68,7 @@ public:  		Ignored				type;   		Ignored				length;  -		Multiple<LLScrollListCell::Params> cells; +		Multiple<LLScrollListCell::Params> columns;  		Params()  		:	enabled("enabled", true), @@ -76,9 +76,9 @@ public:  			name("name"),  			type("type"),  			length("length"), -			cells("columns") +			columns("columns")  		{ -			addSynonym(cells, "column"); +			addSynonym(columns, "column");  			addSynonym(value, "id");  		}  	}; diff --git a/indra/llui/llsearcheditor.cpp b/indra/llui/llsearcheditor.cpp index 64583071a6..3516712dc9 100644 --- a/indra/llui/llsearcheditor.cpp +++ b/indra/llui/llsearcheditor.cpp @@ -1,6 +1,6 @@  /**  - * @file lllineeditor.cpp - * @brief LLLineEditor base class + * @file llsearcheditor.cpp + * @brief LLSearchEditor implementation   *   * $LicenseInfo:firstyear=2001&license=viewergpl$   *  @@ -36,89 +36,63 @@  #include "llsearcheditor.h" -//static LLDefaultChildRegistry::Register<LLSearchEditor> r2("search_editor"); -  LLSearchEditor::LLSearchEditor(const LLSearchEditor::Params& p)  :	LLUICtrl(p)  { -	LLLineEditor::Params line_editor_p(p); -	line_editor_p.name("search edit box"); -	line_editor_p.rect(getLocalRect()); -	line_editor_p.follows.flags(FOLLOWS_ALL); -	line_editor_p.text_pad_right(getRect().getHeight()); -	line_editor_p.keystroke_callback(boost::bind(&LLSearchEditor::onSearchEdit, this, _1)); - -	mSearchEdit = LLUICtrlFactory::create<LLLineEditor>(line_editor_p); -	addChild(mSearchEdit); - -	S32 btn_width = getRect().getHeight(); // button is square, and as tall as search editor -	LLRect clear_btn_rect(getRect().getWidth() - btn_width, getRect().getHeight(), getRect().getWidth(), 0); -	LLButton::Params button_params(p.clear_search_button); -	button_params.name(std::string("clear search")); -	button_params.rect(clear_btn_rect) ; +	const S32 fudge = 2; +	S32 btn_height = getRect().getHeight() - (fudge * 2); + +	LLLineEditor::Params line_editor_params(p); +	line_editor_params.name("filter edit box"); +	line_editor_params.rect(getLocalRect()); +	line_editor_params.follows.flags(FOLLOWS_ALL); +	line_editor_params.text_pad_left(btn_height + fudge); +	line_editor_params.commit_callback.function(boost::bind(&LLUICtrl::onCommit, this)); + +	mSearchEditor = LLUICtrlFactory::create<LLLineEditor>(line_editor_params); +	addChild(mSearchEditor); + +	LLRect search_btn_rect(fudge, fudge + btn_height, fudge + btn_height, fudge); +	LLButton::Params button_params(p.search_button); +	button_params.name(std::string("clear filter")); +	button_params.rect(search_btn_rect) ;  	button_params.follows.flags(FOLLOWS_RIGHT|FOLLOWS_TOP);  	button_params.tab_stop(false); -	button_params.click_callback.function(boost::bind(&LLSearchEditor::onClearSearch, this, _2)); +	button_params.click_callback.function(boost::bind(&LLUICtrl::onCommit, this)); -	mClearSearchButton = LLUICtrlFactory::create<LLButton>(button_params); -	mSearchEdit->addChild(mClearSearchButton); +	mSearchButton = LLUICtrlFactory::create<LLButton>(button_params); +	mSearchEditor->addChild(mSearchButton);  }  //virtual  void LLSearchEditor::setValue(const LLSD& value )  { -	mSearchEdit->setValue(value); +	mSearchEditor->setValue(value);  }  //virtual  LLSD LLSearchEditor::getValue() const  { -	return mSearchEdit->getValue(); +	return mSearchEditor->getValue();  }  //virtual  BOOL LLSearchEditor::setTextArg( const std::string& key, const LLStringExplicit& text )  { -	return mSearchEdit->setTextArg(key, text); +	return mSearchEditor->setTextArg(key, text);  }  //virtual  BOOL LLSearchEditor::setLabelArg( const std::string& key, const LLStringExplicit& text )  { -	return mSearchEdit->setLabelArg(key, text); +	return mSearchEditor->setLabelArg(key, text);  }  //virtual  void LLSearchEditor::clear()  { -	if (mSearchEdit) +	if (mSearchEditor)  	{ -		mSearchEdit->clear(); +		mSearchEditor->clear();  	}  } - -void LLSearchEditor::draw() -{ -	mClearSearchButton->setVisible(!mSearchEdit->getWText().empty()); - -	LLUICtrl::draw(); -} - - -void LLSearchEditor::onSearchEdit(LLLineEditor* caller ) -{ -	if (mSearchCallback) -	{ -		mSearchCallback(caller->getText()); -	} -} - -void LLSearchEditor::onClearSearch(const LLSD& data) -{ -	setText(LLStringUtil::null); -	if (mSearchCallback) -	{ -		mSearchCallback(LLStringUtil::null); -	} -} - diff --git a/indra/llui/llsearcheditor.h b/indra/llui/llsearcheditor.h index d8c5093fbf..368b68baa3 100644 --- a/indra/llui/llsearcheditor.h +++ b/indra/llui/llsearcheditor.h @@ -39,28 +39,21 @@   * $/LicenseInfo$   */ -#ifndef LL_LLSEARCHEDITOR_H -#define LL_LLSEARCHEDITOR_H +#ifndef LL_SEARCHEDITOR_H +#define LL_SEARCHEDITOR_H  #include "lllineeditor.h"  #include "llbutton.h" -#include <boost/function.hpp> - -/* - * @brief A line editor with a button to clear it and a callback to call on every edit event. - */  class LLSearchEditor : public LLUICtrl  {  public:  	struct Params : public LLInitParam::Block<Params, LLLineEditor::Params>  	{ -		Optional<boost::function<void(const std::string&, void*)> > search_callback; -		 -		Optional<LLButton::Params> clear_search_button; +		Optional<LLButton::Params> search_button;  		Params() -		: clear_search_button("clear_search_button") +		: search_button("search_button")  		{  			name = "search_editor";  		} @@ -69,15 +62,11 @@ public:  protected:  	LLSearchEditor(const Params&);  	friend class LLUICtrlFactory; +  public:  	virtual ~LLSearchEditor() {} -	/*virtual*/ void	draw(); - -	void setText(const LLStringExplicit &new_text) { mSearchEdit->setText(new_text); } - -	typedef boost::function<void (const std::string& search_string)> search_callback_t; -	void setSearchCallback(search_callback_t cb) { mSearchCallback = cb; } +	void setText(const LLStringExplicit &new_text) { mSearchEditor->setText(new_text); }  	// LLUICtrl interface  	virtual void	setValue(const LLSD& value ); @@ -87,12 +76,8 @@ public:  	virtual void	clear();  private: -	void onSearchEdit(LLLineEditor* caller ); -	void onClearSearch(const LLSD& data); - -	LLLineEditor* mSearchEdit; -	LLButton* mClearSearchButton; -	search_callback_t mSearchCallback; +	LLLineEditor* mSearchEditor; +	LLButton* mSearchButton;  }; -#endif  // LL_LLSEARCHEDITOR_H +#endif  // LL_SEARCHEDITOR_H diff --git a/indra/llui/llstyle.h b/indra/llui/llstyle.h index 1a94fcf2c6..32ddded2c8 100644 --- a/indra/llui/llstyle.h +++ b/indra/llui/llstyle.h @@ -34,7 +34,6 @@  #define LL_LLSTYLE_H  #include "v4color.h" -#include "llfont.h"  #include "llui.h"  class LLFontGL; diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 3d5b5caead..29c30004ef 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -108,6 +108,7 @@ LLTabContainer::Params::Params()  	tab_min_width("tab_min_width"),  	tab_max_width("tab_max_width"),  	hide_tabs("hide_tabs", false), +	tab_padding_right("tab_padding_right"),  	tab_top_image_unselected("tab_top_image_unselected"),  	tab_top_image_selected("tab_top_image_selected"),  	tab_bottom_image_unselected("tab_bottom_image_unselected"), diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h index ac8232bbb1..78592a0f9a 100644 --- a/indra/llui/lltabcontainer.h +++ b/indra/llui/lltabcontainer.h @@ -122,6 +122,10 @@ public:  		TabPanelParams()  		:	panel("panel", NULL), +			label("label"), +			select_tab("select_tab"), +			is_placeholder("is_placeholder"), +			indent("indent"),  			insert_at("insert_at", END)  		{}  	}; diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp index 56019171e1..3dd8d21f6b 100644 --- a/indra/llui/lltextbox.cpp +++ b/indra/llui/lltextbox.cpp @@ -82,8 +82,7 @@ LLTextBox::LLTextBox(const LLTextBox::Params& p)  	mHAlign(p.font_halign),  	mLineSpacing(p.line_spacing),  	mWordWrap( p.word_wrap ), -	mDidWordWrap(FALSE), -	mFontStyle(LLFontGL::getStyleFromString(p.font.style)) +	mDidWordWrap(FALSE)  {  	setText( p.text() );  } @@ -382,7 +381,7 @@ void LLTextBox::drawText( S32 x, S32 y, const LLColor4& color )  	{  		mFontGL->render(mText.getWString(), 0, (F32)x, (F32)y, color,  						mHAlign, mVAlign,  -						mFontStyle, +						0,  						mShadowType,  						S32_MAX, getRect().getWidth(), NULL, TRUE, mUseEllipses);  	} @@ -395,7 +394,7 @@ void LLTextBox::drawText( S32 x, S32 y, const LLColor4& color )  			S32 line_length = *iter;  			mFontGL->render(mText.getWString(), cur_pos, (F32)x, (F32)y, color,  							mHAlign, mVAlign, -							mFontStyle, +							0,  							mShadowType,  							line_length, getRect().getWidth(), NULL, TRUE, mUseEllipses );  			cur_pos += line_length + 1; diff --git a/indra/llui/lltextbox.h b/indra/llui/lltextbox.h index 53d57ff785..d807fe7639 100644 --- a/indra/llui/lltextbox.h +++ b/indra/llui/lltextbox.h @@ -143,7 +143,6 @@ private:  	BOOL			mWordWrap;  	BOOL            mDidWordWrap; -	U8				mFontStyle; // style bit flags for font  	LLFontGL::ShadowType mShadowType;  	BOOL			mBorderDropShadowVisible;  	BOOL			mUseEllipses; diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 421ba32168..adeaf0a279 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -36,6 +36,7 @@  #include "lltexteditor.h" +#include "llfontfreetype.h" // for LLFontFreetype::FIRST_CHAR  #include "llfontgl.h"  #include "llrender.h"  #include "llui.h" @@ -227,6 +228,29 @@ private:  /////////////////////////////////////////////////////////////////// +LLTextEditor::Params::Params() +:	default_text("default_text"), +	max_text_length("max_length", 255), +	read_only("read_only", false), +	embedded_items("embedded_items", false), +	hide_scrollbar("hide_scrollbar", false), +	hide_border("hide_border", false), +	word_wrap("word_wrap", false), +	ignore_tab("ignore_tab", true), +	track_bottom("track_bottom", false), +	takes_non_scroll_clicks("takes_non_scroll_clicks", true), +	cursor_color("cursor_color"), +	default_color("default_color"), +	text_color("text_color"), +	text_readonly_color("text_readonly_color"), +	bg_readonly_color("bg_readonly_color"), +	bg_writeable_color("bg_writeable_color"), +	bg_focus_color("bg_focus_color"), +	length("length"),		// ignored +	type("type"),			// ignored +	is_unicode("is_unicode")// ignored +{} +  LLTextEditor::LLTextEditor(const LLTextEditor::Params& p)  	:	LLUICtrl(p, LLTextViewModelPtr(new LLTextViewModel)),  	mMaxTextByteLength( p.max_text_length ), @@ -254,7 +278,7 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p)  	mHideScrollbarForShortDocs( FALSE ),  	mTakesNonScrollClicks( p.takes_non_scroll_clicks ),  	mTrackBottom( p.track_bottom ), -	mAllowEmbeddedItems( p.allow_embedded_items ), +	mAllowEmbeddedItems( p.embedded_items ),  	mHandleEditKeysDirectly( FALSE ),  	mMouseDownX(0),  	mMouseDownY(0), @@ -263,8 +287,7 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p)  	mScrollNeeded(FALSE),  	mLastSelectionY(-1),  	mTabsToNextField(p.ignore_tab), -	mGLFont(p.font), -	mGLFontStyle(LLFontGL::getStyleFromString(p.font.style)) +	mGLFont(p.font)  {  	static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0); @@ -1930,7 +1953,7 @@ void LLTextEditor::pasteHelper(bool is_primary)  		for( S32 i = 0; i < len; i++ )  		{  			llwchar wc = clean_string[i]; -			if( (wc < LLFont::FIRST_CHAR) && (wc != LF) ) +			if( (wc < LLFontFreetype::FIRST_CHAR) && (wc != LF) )  			{  				clean_string[i] = LL_UNKNOWN_CHAR;  			} @@ -3101,7 +3124,7 @@ void LLTextEditor::drawClippedSegment(const LLWString &text, S32 seg_start, S32  		S32 start = seg_start;  		S32 end = llmin( selection_left, seg_end );  		S32 length =  end - start; -		font->render(text, start, x, y_top, color, LLFontGL::LEFT, LLFontGL::TOP, mGLFontStyle, LLFontGL::NO_SHADOW, length, S32_MAX, right_x, mAllowEmbeddedItems); +		font->render(text, start, x, y_top, color, LLFontGL::LEFT, LLFontGL::TOP, 0, LLFontGL::NO_SHADOW, length, S32_MAX, right_x, mAllowEmbeddedItems);  	}  	x = *right_x; @@ -3114,7 +3137,7 @@ void LLTextEditor::drawClippedSegment(const LLWString &text, S32 seg_start, S32  		font->render(text, start, x, y_top,  					 LLColor4( 1.f - color.mV[0], 1.f - color.mV[1], 1.f - color.mV[2], 1.f ), -					 LLFontGL::LEFT, LLFontGL::TOP, mGLFontStyle, LLFontGL::NO_SHADOW, length, S32_MAX, right_x, mAllowEmbeddedItems); +					 LLFontGL::LEFT, LLFontGL::TOP, 0, LLFontGL::NO_SHADOW, length, S32_MAX, right_x, mAllowEmbeddedItems);  	}  	x = *right_x;  	if( selection_right < seg_end ) @@ -3123,7 +3146,7 @@ void LLTextEditor::drawClippedSegment(const LLWString &text, S32 seg_start, S32  		S32 start = llmax( selection_right, seg_start );  		S32 end = seg_end;  		S32 length = end - start; -		font->render(text, start, x, y_top, color, LLFontGL::LEFT, LLFontGL::TOP, mGLFontStyle, LLFontGL::NO_SHADOW, length, S32_MAX, right_x, mAllowEmbeddedItems); +		font->render(text, start, x, y_top, color, LLFontGL::LEFT, LLFontGL::TOP, 0, LLFontGL::NO_SHADOW, length, S32_MAX, right_x, mAllowEmbeddedItems);  	}   } diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index 5e423f8548..4da91cc1d7 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -63,7 +63,7 @@ public:  		Optional<S32>			max_text_length;  		Optional<bool>			read_only, -								allow_embedded_items, +								embedded_items,  								hide_scrollbar,  								word_wrap,  								ignore_tab, @@ -86,30 +86,7 @@ public:  								length,  								is_unicode; - -		Params() -		:	max_text_length("max_length", 255), -			read_only("read_only", false), -			allow_embedded_items("embedded_items", false), -			hide_scrollbar("hide_scrollbar", false), -			hide_border("hide_border", false), -			word_wrap("word_wrap", false), -			ignore_tab("ignore_tab", true), -			track_bottom("track_bottom", false), -			takes_non_scroll_clicks("takes_non_scroll_clicks", true), -			cursor_color("cursor_color"), -			default_color("default_color"), -			text_color("text_color"), -			text_readonly_color("text_readonly_color"), -			bg_readonly_color("bg_readonly_color"), -			bg_writeable_color("bg_writeable_color"), -			bg_focus_color("bg_focus_color"), -			length("length"), -			type("type"), -			is_unicode("is_unicode") -		{} -			 -			 +		Params();  	};  	void initFromParams(const Params&); @@ -524,7 +501,6 @@ private:  	S32				mMaxTextByteLength;		// Maximum length mText is allowed to be in bytes  	const LLFontGL*	mGLFont; -	U8              mGLFontStyle; // the font style from xml  	class LLViewBorder*	mBorder; diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index 7eaa118222..6906f0befb 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -58,8 +58,9 @@  #include "llwindow.h"  // for registration -#include "llsearcheditor.h" +#include "llfiltereditor.h"  #include "llflyoutbutton.h" +#include "llsearcheditor.h"  // for XUIParse  #include "llquaternion.h" @@ -88,9 +89,10 @@ std::list<std::string> gUntranslated;  /*static*/ std::vector<std::string> LLUI::sXUIPaths; -// register searcheditor here -static LLDefaultChildRegistry::Register<LLSearchEditor> register_search_editor("search_editor"); +// register filtereditor here +static LLDefaultChildRegistry::Register<LLFilterEditor> register_filter_editor("filter_editor");  static LLDefaultChildRegistry::Register<LLFlyoutButton> register_flyout_button("flyout_button"); +static LLDefaultChildRegistry::Register<LLSearchEditor> register_search_editor("search_editor");  // @@ -1963,6 +1965,17 @@ namespace LLInitParam  		declare("blue", LLColor4::blue);  	} +	template<> +	class ParamCompare<const LLFontGL*> +	{ +	public: +		static bool equals(const LLFontGL* a, const LLFontGL* b) +		{ +			return !(a->getFontDesc() < b->getFontDesc()) +				&& !(b->getFontDesc() < a->getFontDesc()); +		} +	}; +  	TypedParam<const LLFontGL*>::TypedParam(BlockDescriptor& descriptor, const char* name, const LLFontGL*const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)  	:	super_t(descriptor, name, value, func, min_count, max_count),  		name(""), diff --git a/indra/llui/llui.h b/indra/llui/llui.h index 9399eff2ab..413733a50b 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -39,7 +39,6 @@  #include "llrect.h"  #include "llcontrol.h"  #include "llcoord.h" -//#include "llhtmlhelp.h"  #include "llgl.h"			// *TODO: break this dependency  #include <stack>  #include "lluiimage.h"		// *TODO: break this dependency, need to add #include "lluiimage.h" to all widgets that hold an Optional<LLUIImage*> in their paramblocks @@ -49,6 +48,8 @@  #include "lluicolortable.h"  #include <boost/signals2.hpp>  #include "lllazyvalue.h" +#include "llhandle.h"		// *TODO: remove this dependency, added as a  +							// convenience when LLHandle moved to llhandle.h  // LLUIFactory  #include "llsd.h" @@ -433,139 +434,7 @@ public:  	LLLocalClipRect(const LLRect& rect, BOOL enabled = TRUE);  }; -template <typename T> -class LLTombStone : public LLRefCount -{ -public: -	LLTombStone(T* target = NULL) : mTarget(target) {} -	 -	void setTarget(T* target) { mTarget = target; } -	T* getTarget() const { return mTarget; } -private: -	T* mTarget; -}; - -//	LLHandles are used to refer to objects whose lifetime you do not control or influence.   -//	Calling get() on a handle will return a pointer to the referenced object or NULL,  -//	if the object no longer exists.  Note that during the lifetime of the returned pointer,  -//	you are assuming that the object will not be deleted by any action you perform,  -//	or any other thread, as normal when using pointers, so avoid using that pointer outside of -//	the local code block. -//  -//  https://wiki.lindenlab.com/mediawiki/index.php?title=LLHandle&oldid=79669 - -template <typename T> -class LLHandle -{ -public: -	LLHandle() : mTombStone(sDefaultTombStone) {} -	const LLHandle<T>& operator =(const LLHandle<T>& other)   -	{  -		mTombStone = other.mTombStone; -		return *this;  -	} - -	bool isDead() const  -	{  -		return mTombStone->getTarget() == NULL;  -	} - -	void markDead()  -	{  -		mTombStone = sDefaultTombStone;  -	} - -	T* get() const -	{ -		return mTombStone->getTarget(); -	} - -	friend bool operator== (const LLHandle<T>& lhs, const LLHandle<T>& rhs) -	{ -		return lhs.mTombStone == rhs.mTombStone; -	} -	friend bool operator!= (const LLHandle<T>& lhs, const LLHandle<T>& rhs) -	{ -		return !(lhs == rhs); -	} -	friend bool	operator< (const LLHandle<T>& lhs, const LLHandle<T>& rhs) -	{ -		return lhs.mTombStone < rhs.mTombStone; -	} -	friend bool	operator> (const LLHandle<T>& lhs, const LLHandle<T>& rhs) -	{ -		return lhs.mTombStone > rhs.mTombStone; -	} -protected: - -protected: -	LLPointer<LLTombStone<T> > mTombStone; - -private: -	static LLPointer<LLTombStone<T> > sDefaultTombStone; -}; - -// initialize static "empty" tombstone pointer -template <typename T> LLPointer<LLTombStone<T> > LLHandle<T>::sDefaultTombStone = new LLTombStone<T>(); - - -template <typename T> -class LLRootHandle : public LLHandle<T> -{ -public: -	LLRootHandle(T* object) { bind(object); } -	LLRootHandle() {}; -	~LLRootHandle() { unbind(); } - -	// this is redundant, since a LLRootHandle *is* an LLHandle -	LLHandle<T> getHandle() { return LLHandle<T>(*this); } - -	void bind(T* object)  -	{  -		// unbind existing tombstone -		if (LLHandle<T>::mTombStone.notNull()) -		{ -			if (LLHandle<T>::mTombStone->getTarget() == object) return; -			LLHandle<T>::mTombStone->setTarget(NULL); -		} -		// tombstone reference counted, so no paired delete -		LLHandle<T>::mTombStone = new LLTombStone<T>(object); -	} - -	void unbind()  -	{ -		LLHandle<T>::mTombStone->setTarget(NULL); -	} - -	//don't allow copying of root handles, since there should only be one -private: -	LLRootHandle(const LLRootHandle& other) {}; -}; - -// Use this as a mixin for simple classes that need handles and when you don't -// want handles at multiple points of the inheritance hierarchy -template <typename T> -class LLHandleProvider -{ -protected: -	typedef LLHandle<T> handle_type_t; -	LLHandleProvider()  -	{ -		// provided here to enforce T deriving from LLHandleProvider<T> -	}  - -	LLHandle<T> getHandle()  -	{  -		// perform lazy binding to avoid small tombstone allocations for handle -		// providers whose handles are never referenced -		mHandle.bind(static_cast<T*>(this));  -		return mHandle;  -	} - -private: -	LLRootHandle<T> mHandle; -}; - +// Moved all LLHandle-related code to llhandle.h  //RN: maybe this needs to moved elsewhere?  class LLImageProviderInterface diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp index ebf594ff66..aae4a86d87 100644 --- a/indra/llui/lluictrl.cpp +++ b/indra/llui/lluictrl.cpp @@ -43,7 +43,7 @@ static LLDefaultChildRegistry::Register<LLUICtrl> r("ui_ctrl");  LLUICtrl::Params::Params()  :	tab_stop("tab_stop", true),  	label("label"), -	initial_value("initial_value"), +	initial_value("value"),  	init_callback("init_callback"),  	commit_callback("commit_callback"),  	validate_callback("validate_callback"), @@ -52,9 +52,7 @@ LLUICtrl::Params::Params()  	mouseleave_callback("mouseleave_callback"),  	control_name("control_name")  { -	addSynonym(initial_value, "initial_val"); -	// this is the canonical name for text contents of an xml node -	addSynonym(initial_value, "value"); +	addSynonym(initial_value, "initial_value");  }  LLFocusableElement::LLFocusableElement() diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h index 16fbbf79ea..cf6634f370 100644 --- a/indra/llui/lluictrl.h +++ b/indra/llui/lluictrl.h @@ -108,7 +108,7 @@ public:  	{  		Optional<commit_callback_t> function;  	}; -	 +  	struct EnableCallbackParam : public LLInitParam::Block<EnableCallbackParam, CallbackParam >  	{  		Optional<enable_callback_t> function; diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp index 9df22e39b4..3b2b56d48e 100644 --- a/indra/llui/lluictrlfactory.cpp +++ b/indra/llui/lluictrlfactory.cpp @@ -77,6 +77,7 @@ const S32 HPAD = 4;  const S32 VPAD = 4;  const S32 FLOATER_H_MARGIN = 15;  const S32 MIN_WIDGET_HEIGHT = 10; +const S32 MAX_STRING_ATTRIBUTE_SIZE = 40;  LLFastTimer::DeclareTimer FTM_WIDGET_CONSTRUCTION("Widget Construction");  LLFastTimer::DeclareTimer FTM_INIT_FROM_PARAMS("Widget InitFromParams"); @@ -449,177 +450,6 @@ void LLUICtrlFactory::popFactoryFunctions()  	}  } - -// -// LLRNGWriter - writes Relax NG schema files based on a param block -// -LLRNGWriter::LLRNGWriter() -{ -	// register various callbacks for inspecting the contents of a param block -	registerInspectFunc<bool>(boost::bind(&LLRNGWriter::writeAttribute, this, "boolean", _1, _2, _3, _4)); -	registerInspectFunc<std::string>(boost::bind(&LLRNGWriter::writeAttribute, this, "string", _1, _2, _3, _4)); -	registerInspectFunc<U8>(boost::bind(&LLRNGWriter::writeAttribute, this, "unsignedByte", _1, _2, _3, _4)); -	registerInspectFunc<S8>(boost::bind(&LLRNGWriter::writeAttribute, this, "signedByte", _1, _2, _3, _4)); -	registerInspectFunc<U16>(boost::bind(&LLRNGWriter::writeAttribute, this, "unsignedShort", _1, _2, _3, _4)); -	registerInspectFunc<S16>(boost::bind(&LLRNGWriter::writeAttribute, this, "signedShort", _1, _2, _3, _4)); -	registerInspectFunc<U32>(boost::bind(&LLRNGWriter::writeAttribute, this, "unsignedInt", _1, _2, _3, _4)); -	registerInspectFunc<S32>(boost::bind(&LLRNGWriter::writeAttribute, this, "integer", _1, _2, _3, _4)); -	registerInspectFunc<F32>(boost::bind(&LLRNGWriter::writeAttribute, this, "float", _1, _2, _3, _4)); -	registerInspectFunc<F64>(boost::bind(&LLRNGWriter::writeAttribute, this, "double", _1, _2, _3, _4)); -	registerInspectFunc<LLColor4>(boost::bind(&LLRNGWriter::writeAttribute, this, "string", _1, _2, _3, _4)); -	registerInspectFunc<LLUIColor>(boost::bind(&LLRNGWriter::writeAttribute, this, "string", _1, _2, _3, _4)); -	registerInspectFunc<LLUUID>(boost::bind(&LLRNGWriter::writeAttribute, this, "string", _1, _2, _3, _4)); -	registerInspectFunc<LLSD>(boost::bind(&LLRNGWriter::writeAttribute, this, "string", _1, _2, _3, _4)); -} - -void LLRNGWriter::writeRNG(const std::string& type_name, LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const std::string& xml_namespace) -{ -	mGrammarNode = node; -	mGrammarNode->setName("grammar"); -	mGrammarNode->createChild("xmlns", true)->setStringValue("http://relaxng/ns/structure/1.0"); -	mGrammarNode->createChild("datatypeLibrary", true)->setStringValue("http://www.w3.org/2001/XMLSchema-datatypes"); -	mGrammarNode->createChild("ns", true)->setStringValue(xml_namespace); - -	node = mGrammarNode->createChild("start", false); -	node = node->createChild("ref", false); -	node->createChild("name", true)->setStringValue(type_name); -	 -	node = mGrammarNode->createChild("define", false); -	node->createChild("name", true)->setStringValue(type_name); - -	mElementNode = node->createChild("element", false); -	mElementNode->createChild("name", true)->setStringValue(type_name); - -	block.inspectBlock(*this); -} - -void LLRNGWriter::writeAttribute(const std::string& type, const Parser::name_stack_t& stack, S32 min_count, S32 max_count, const std::vector<std::string>* possible_values) -{ -	name_stack_t non_empty_names; -	std::string attribute_name; -	for (name_stack_t::const_iterator it = stack.begin(); -		it != stack.end(); -		++it) -	{ -		const std::string& name = it->first; -		if (!name.empty()) -		{ -			non_empty_names.push_back(*it); -		} -	} - -	if (non_empty_names.empty()) return; - -	for (name_stack_t::const_iterator it = non_empty_names.begin(); -		it != non_empty_names.end(); -		++it) -	{ -		if (!attribute_name.empty()) -		{ -			attribute_name += "."; -		} -		attribute_name += it->first; -	} - -	// singular attribute -	if (non_empty_names.size() == 1) -	{ -		if (max_count == 1) -		{ -			LLXMLNodePtr node = getCardinalityNode(mElementNode, min_count, max_count)->createChild("attribute", false); -			node->createChild("name", true)->setStringValue(attribute_name); -			node->createChild("data", false)->createChild("type", true)->setStringValue(type); -		} -	} -	// compound attribute -	else -	{ -		std::string element_name; - -		// traverse all but last element, leaving that as an attribute name -		name_stack_t::const_iterator end_it = non_empty_names.end(); -		end_it--; - -		for (name_stack_t::const_iterator it = non_empty_names.begin(); -			it != end_it; -			++it) -		{ -			if (it != non_empty_names.begin()) -			{ -				element_name += "."; -			} -			element_name += it->first; -		} - -		elements_map_t::iterator found_it = mElementsWritten.find(element_name); -		if (found_it != mElementsWritten.end()) -		{ -			// reuse existing element -			LLXMLNodePtr choice_node = found_it->second; - -			LLXMLNodePtr node = choice_node->mChildren->head; -			node = getCardinalityNode(node, min_count, max_count)->createChild("attribute", false); -			node->createChild("name", true)->setStringValue(attribute_name); -			node->createChild("data", false)->createChild("type", true)->setStringValue(type); - -			node = choice_node->mChildren->head->mNext->mChildren->head; -			node = getCardinalityNode(node, min_count, max_count)->createChild("attribute", false); -			node->createChild("name", true)->setStringValue(non_empty_names.back().first); -			node->createChild("data", false)->createChild("type", true)->setStringValue(type); -		} -		else -		{ -			LLXMLNodePtr choice_node = mElementNode->createChild("choice", false); - -			LLXMLNodePtr node = choice_node->createChild("group", false); -			node = getCardinalityNode(node, min_count, max_count)->createChild("attribute", false); -			node->createChild("name", true)->setStringValue(attribute_name); -			node->createChild("data", false)->createChild("type", true)->setStringValue(type); - -			node = choice_node->createChild("element", false); -			node->createChild("name", true)->setStringValue(element_name); -			node = getCardinalityNode(node, min_count, max_count)->createChild("attribute", false); -			node->createChild("name", true)->setStringValue(non_empty_names.back().first); -			node->createChild("data", false)->createChild("type", true)->setStringValue(type); -			 -			node = choice_node->createChild("element", false); -			node->createChild("name", true)->setStringValue(type + "." + element_name); -			node->createChild("ref", true)->createChild("name", true)->setStringValue(element_name); - -			mElementsWritten[element_name] = choice_node; -		} -	} -} - -LLXMLNodePtr LLRNGWriter::getCardinalityNode(LLXMLNodePtr parent_node, S32 min_count, S32 max_count) -{ -	// unlinked by default, meaning this attribute is forbidden -	LLXMLNodePtr count_node = new LLXMLNode(); -	if (min_count >= 1) -	{ -		if (max_count == 1 && min_count == 1) -		{ -			// just add raw element, will count as 1 and only 1 -			count_node = mElementNode; -		} -		else -		{ -			count_node = mElementNode->createChild("oneOrMore", false); -		} -	} -	else -	{ -		if (max_count == 1) -		{ -			count_node = mElementNode->createChild("optional", false); -		} -		else if (max_count > 1) -		{ -			count_node = mElementNode->createChild("zeroOrMore", false); -		} -	} -	return count_node; -}  //  // LLXSDWriter  // @@ -811,7 +641,7 @@ void LLXSDWriter::addAttributeToSchema(LLXMLNodePtr type_declaration_node, const  		string_set_t& attributes_written = mAttributesWritten[type_declaration_node]; -		string_set_t::iterator found_it = std::lower_bound(attributes_written.begin(), attributes_written.end(), attribute_name); +		string_set_t::iterator found_it = attributes_written.lower_bound(attribute_name);  		// attribute not yet declared  		if (found_it == attributes_written.end() || attributes_written.key_comp()(attribute_name, *found_it)) @@ -997,142 +827,6 @@ void LLXUIParser::readXUI(LLXMLNodePtr node, LLInitParam::BaseBlock& block, bool  	}  } -void LLXUIParser::writeXUI(LLXMLNodePtr node, const LLInitParam::BaseBlock &block, const LLInitParam::BaseBlock* diff_block) -{ -	mLastWriteGeneration = -1; -	mWriteRootNode = node; -	block.serializeBlock(*this, Parser::name_stack_t(), diff_block); -} - -// go from a stack of names to a specific XML node -LLXMLNodePtr LLXUIParser::getNode(const name_stack_t& stack) -{ -	name_stack_t name_stack; - -	for (name_stack_t::const_iterator it = stack.begin(); -		it != stack.end(); -		++it) -	{ -		if (!it->first.empty()) -		{ -			name_stack.push_back(*it); -		} -	} - -	if (name_stack.empty() || mWriteRootNode.isNull()) return NULL; - -	std::string attribute_name = name_stack.front().first; - -	// heuristic to make font always attribute of parent node -	bool is_font = (attribute_name == "font"); -	// XML spec says that attributes have their whitespace normalized -	// on parse: http://www.w3.org/TR/REC-xml/#AVNormalize -	// Therefore text-oriented widgets that might have carriage returns -	// have their values serialized as text contents, not the -	// initial_value attribute. JC -	if (attribute_name == "initial_value") -	{ -		const char* root_node_name = mWriteRootNode->getName()->mString; -		if (!strcmp(root_node_name, "text")		// LLTextBox -			|| !strcmp(root_node_name, "text_editor")  -			|| !strcmp(root_node_name, "line_editor")) // for consistency -		{ -			// writeStringValue will write to this node -			return mWriteRootNode; -		} -	} - -	for (name_stack_t::const_iterator it = ++name_stack.begin(); -		it != name_stack.end(); -		++it) -	{ -		attribute_name += "."; -		attribute_name += it->first; -	} - -	// *NOTE: <string> elements for translation need to have whitespace -	// preserved like "initial_value" above, however, the <string> node -	// becomes an attribute of the containing floater or panel. -	// Because all <string> elements must have a "name" attribute, and -	// "name" is parsed first, just put the value into the last written -	// child. -	if (attribute_name == "string.value") -	{ -		// The caller of will shortly call writeStringValue(), which sets -		// this node's type to string, but we don't want to export type="string". -		// Set the default for this node to suppress the export. -		static LLXMLNodePtr default_node; -		if (default_node.isNull()) -		{ -			default_node = new LLXMLNode(); -			// Force the node to have a string type -			default_node->setStringValue( std::string() ); -		} -		mLastWrittenChild->setDefault(default_node); -		// mLastWrittenChild is the "string" node part of "string.value", -		// so the caller will call writeStringValue() into that node, -		// setting the node text contents. -		return mLastWrittenChild; -	} - -	LLXMLNodePtr attribute_node; - -	const char* attribute_cstr = attribute_name.c_str(); -	if (name_stack.size() != 1 -		&& !is_font) -	{ -		std::string child_node_name(mWriteRootNode->getName()->mString); -		child_node_name += "."; -		child_node_name += name_stack.front().first; - -		LLXMLNodePtr child_node; - -		if (mLastWriteGeneration == name_stack.front().second) -		{ -			child_node = mLastWrittenChild; -		} -		else -		{ -			mLastWriteGeneration = name_stack.front().second; -			child_node = mWriteRootNode->createChild(child_node_name.c_str(), false); -		} - -		mLastWrittenChild = child_node; - -		name_stack_t::const_iterator it = ++name_stack.begin(); -		std::string short_attribute_name(it->first); - -		for (++it; -			it != name_stack.end(); -			++it) -		{ -			short_attribute_name += "."; -			short_attribute_name += it->first; -		} - -		if (child_node->hasAttribute(short_attribute_name.c_str())) -		{ -			llerrs << "Attribute " << short_attribute_name << " already exists!" << llendl; -		} - -		attribute_node = child_node->createChild(short_attribute_name.c_str(), true); -	} -	else -	{ -		if (mWriteRootNode->hasAttribute(attribute_cstr)) -		{ -			mWriteRootNode->getAttribute(attribute_cstr, attribute_node); -		} -		else -		{ -			attribute_node = mWriteRootNode->createChild(attribute_name.c_str(), true); -		} -	} - -	return attribute_node; -} - -  bool LLXUIParser::readXUIImpl(LLXMLNodePtr nodep, const std::string& scope, LLInitParam::BaseBlock& block)  {  	typedef boost::tokenizer<boost::char_separator<char> > tokenizer; @@ -1152,8 +846,15 @@ bool LLXUIParser::readXUIImpl(LLXMLNodePtr nodep, const std::string& scope, LLIn  		// child nodes are not necessarily valid parameters (could be a child widget)  		// so don't complain once we've recursed  		bool silent = mCurReadDepth > 0; -		block.submitValue(mNameStack, *this, silent); -		mNameStack.pop_back(); +		if (!block.submitValue(mNameStack, *this, true)) +		{ +			mNameStack.pop_back(); +			block.submitValue(mNameStack, *this, silent); +		} +		else +		{ +			mNameStack.pop_back(); +		}  	}  	// then traverse children @@ -1271,6 +972,62 @@ bool LLXUIParser::readAttributes(LLXMLNodePtr nodep, LLInitParam::BaseBlock& blo  	return any_parsed;  } +void LLXUIParser::writeXUI(LLXMLNodePtr node, const LLInitParam::BaseBlock &block, const LLInitParam::BaseBlock* diff_block) +{ +	mWriteRootNode = node; +	block.serializeBlock(*this, Parser::name_stack_t(), diff_block); +	mOutNodes.clear(); +} + +// go from a stack of names to a specific XML node +LLXMLNodePtr LLXUIParser::getNode(const name_stack_t& stack) +{ +	name_stack_t name_stack; +	for (name_stack_t::const_iterator it = stack.begin(); +		it != stack.end(); +		++it) +	{ +		if (!it->first.empty()) +		{ +			name_stack.push_back(*it); +		} +	} + +	LLXMLNodePtr out_node = mWriteRootNode; + +	name_stack_t::const_iterator next_it = name_stack.begin(); +	for (name_stack_t::const_iterator it = name_stack.begin(); +		it != name_stack.end(); +		it = next_it) +	{ +		++next_it; +		if (it->first.empty()) +		{ +			continue; +		} + +		out_nodes_t::iterator found_it = mOutNodes.lower_bound(it->second); + +		// node with this name not yet written +		if (found_it == mOutNodes.end() || mOutNodes.key_comp()(found_it->first, it->second)) +		{ +			// make an attribute if we are the last element on the name stack +			bool is_attribute = next_it == name_stack.end(); +			LLXMLNodePtr new_node = new LLXMLNode(it->first.c_str(), is_attribute); +			out_node->addChild(new_node); +			mOutNodes.insert(found_it, std::make_pair(it->second, new_node)); +			out_node = new_node; +		} +		else +		{ +			out_node = found_it->second; +		} +	} + +	return (out_node == mWriteRootNode ? LLXMLNodePtr(NULL) : out_node); +} + +  bool LLXUIParser::readBoolValue(void* val_ptr)  {  	S32 value; @@ -1301,7 +1058,27 @@ bool LLXUIParser::writeStringValue(const void* val_ptr, const name_stack_t& stac  	LLXMLNodePtr node = getNode(stack);  	if (node.notNull())  	{ -		node->setStringValue(*((std::string*)val_ptr)); +		const std::string* string_val = reinterpret_cast<const std::string*>(val_ptr); +		if (string_val->find('\n') != std::string::npos  +			|| string_val->size() > MAX_STRING_ATTRIBUTE_SIZE) +		{ +			// don't write strings with newlines into attributes +			std::string attribute_name = node->getName()->mString; +			LLXMLNodePtr parent_node = node->mParent; +			parent_node->deleteChild(node); +			// write results in text contents of node +			if (attribute_name == "value") +			{ +				// "value" is implicit, just write to parent +				node = parent_node; +			} +			else +			{ +				// create a child that is not an attribute, but with same name +				node = parent_node->createChild(attribute_name.c_str(), false); +			} +		} +		node->setStringValue(*string_val);  		return true;  	}  	return false; @@ -1538,7 +1315,26 @@ bool LLXUIParser::writeSDValue(const void* val_ptr, const name_stack_t& stack)  	LLXMLNodePtr node = getNode(stack);  	if (node.notNull())  	{ -		node->setStringValue(((LLSD*)val_ptr)->asString()); +		std::string string_val = ((LLSD*)val_ptr)->asString(); +		if (string_val.find('\n') != std::string::npos || string_val.size() > MAX_STRING_ATTRIBUTE_SIZE) +		{ +			// don't write strings with newlines into attributes +			std::string attribute_name = node->getName()->mString; +			LLXMLNodePtr parent_node = node->mParent; +			parent_node->deleteChild(node); +			// write results in text contents of node +			if (attribute_name == "value") +			{ +				// "value" is implicit, just write to parent +				node = parent_node; +			} +			else +			{ +				node = parent_node->createChild(attribute_name.c_str(), false); +			} +		} + +		node->setStringValue(string_val);  		return true;  	}  	return false; diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h index 894c77888c..6374018ca6 100644 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -47,28 +47,6 @@ class LLPanel;  class LLFloater;  class LLView; -class LLRNGWriter : public LLInitParam::Parser -{ -	LOG_CLASS(LLRNGWriter); -public: -	void writeRNG(const std::string& name, LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const std::string& xml_namespace); - -	/*virtual*/ std::string getCurrentElementName() { return LLStringUtil::null; } - -	LLRNGWriter(); - -private: -	LLXMLNodePtr getCardinalityNode(LLXMLNodePtr parent_node, S32 min_count, S32 max_count); - -	void writeAttribute(const std::string& type, const Parser::name_stack_t&, S32 min_count, S32 max_count, const std::vector<std::string>* possible_values); -	LLXMLNodePtr mElementNode; -	LLXMLNodePtr mGrammarNode; - -	typedef std::map<std::string, LLXMLNodePtr> elements_map_t; -	elements_map_t	mElementsWritten; -}; - -  class LLXSDWriter : public LLInitParam::Parser  {  	LOG_CLASS(LLXSDWriter); @@ -161,6 +139,9 @@ private:  	LLXMLNodePtr					mCurReadNode;  	// Root of the widget XML sub-tree, for example, "line_editor"  	LLXMLNodePtr					mWriteRootNode; +	 +	typedef std::map<S32, LLXMLNodePtr>	out_nodes_t; +	out_nodes_t						mOutNodes;  	S32								mLastWriteGeneration;  	LLXMLNodePtr					mLastWrittenChild;  	S32								mCurReadDepth; @@ -489,7 +470,7 @@ LLChildRegistry<DERIVED>::Register<T>::Register(const char* tag, LLWidgetCreator  } -typedef boost::function<LLPanel* (void)> LLPannelClassCreatorFunc; +typedef boost::function<LLPanel* (void)> LLPanelClassCreatorFunc;  // local static instance for registering a particular panel class @@ -498,15 +479,15 @@ class LLRegisterPanelClass  {  public:  	// reigister with either the provided builder, or the generic templated builder -	void addPanelClass(const std::string& tag,LLPannelClassCreatorFunc func) +	void addPanelClass(const std::string& tag,LLPanelClassCreatorFunc func)  	{ -		mPannelClassesNames[tag] = func; +		mPanelClassesNames[tag] = func;  	}  	LLPanel* createPanelClass(const std::string& tag)  	{ -		param_name_map_t::iterator iT =  mPannelClassesNames.find(tag); -		if(iT == mPannelClassesNames.end()) +		param_name_map_t::iterator iT =  mPanelClassesNames.find(tag); +		if(iT == mPanelClassesNames.end())  			return 0;  		return iT->second();  	} @@ -518,9 +499,9 @@ public:  	}  private: -	typedef std::map< std::string, LLPannelClassCreatorFunc> param_name_map_t; +	typedef std::map< std::string, LLPanelClassCreatorFunc> param_name_map_t; -	param_name_map_t mPannelClassesNames; +	param_name_map_t mPanelClassesNames;  }; diff --git a/indra/llxml/llxmlnode.cpp b/indra/llxml/llxmlnode.cpp index 5d43ac11e4..07cc612a0a 100644 --- a/indra/llxml/llxmlnode.cpp +++ b/indra/llxml/llxmlnode.cpp @@ -922,7 +922,7 @@ void LLXMLNode::writeHeaderToFile(LLFILE *out_file)  	fprintf(out_file, "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>\n");  } -void LLXMLNode::writeToFile(LLFILE *out_file, const std::string& indent) +void LLXMLNode::writeToFile(LLFILE *out_file, const std::string& indent, bool use_type_decorations)  {  	if (isFullyDefault())  	{ @@ -931,7 +931,7 @@ void LLXMLNode::writeToFile(LLFILE *out_file, const std::string& indent)  	}  	std::ostringstream ostream; -	writeToOstream(ostream, indent); +	writeToOstream(ostream, indent, use_type_decorations);  	std::string outstring = ostream.str();  	size_t written = fwrite(outstring.c_str(), 1, outstring.length(), out_file);  	if (written != outstring.length()) @@ -940,7 +940,7 @@ void LLXMLNode::writeToFile(LLFILE *out_file, const std::string& indent)  	}  } -void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& indent) +void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& indent, bool use_type_decorations)  {  	if (isFullyDefault())  	{ @@ -956,77 +956,80 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i  	// stream the name  	output_stream << indent << "<" << mName->mString << "\n"; -	// ID -	if (mID != "") +	if (use_type_decorations)  	{ -		output_stream << indent << " id=\"" << mID << "\"\n"; -	} +		// ID +		if (mID != "") +		{ +			output_stream << indent << " id=\"" << mID << "\"\n"; +		} -	// Type -	if (!has_default_type) -	{ -		switch (mType) +		// Type +		if (!has_default_type)  		{ -		case TYPE_BOOLEAN: -			output_stream << indent << " type=\"boolean\"\n"; -			break; -		case TYPE_INTEGER: -			output_stream << indent << " type=\"integer\"\n"; -			break; -		case TYPE_FLOAT: -			output_stream << indent << " type=\"float\"\n"; -			break; -		case TYPE_STRING: -			output_stream << indent << " type=\"string\"\n"; -			break; -		case TYPE_UUID: -			output_stream << indent << " type=\"uuid\"\n"; -			break; -		case TYPE_NODEREF: -			output_stream << indent << " type=\"noderef\"\n"; -			break; -		default: -			// default on switch(enum) eliminates a warning on linux -			break; -		}; -	} +			switch (mType) +			{ +			case TYPE_BOOLEAN: +				output_stream << indent << " type=\"boolean\"\n"; +				break; +			case TYPE_INTEGER: +				output_stream << indent << " type=\"integer\"\n"; +				break; +			case TYPE_FLOAT: +				output_stream << indent << " type=\"float\"\n"; +				break; +			case TYPE_STRING: +				output_stream << indent << " type=\"string\"\n"; +				break; +			case TYPE_UUID: +				output_stream << indent << " type=\"uuid\"\n"; +				break; +			case TYPE_NODEREF: +				output_stream << indent << " type=\"noderef\"\n"; +				break; +			default: +				// default on switch(enum) eliminates a warning on linux +				break; +			}; +		} -	// Encoding -	if (!has_default_encoding) -	{ -		switch (mEncoding) +		// Encoding +		if (!has_default_encoding)  		{ -		case ENCODING_DECIMAL: -			output_stream << indent << " encoding=\"decimal\"\n"; -			break; -		case ENCODING_HEX: -			output_stream << indent << " encoding=\"hex\"\n"; -			break; -		/*case ENCODING_BASE32: -			output_stream << indent << " encoding=\"base32\"\n"; -			break;*/ -		default: -			// default on switch(enum) eliminates a warning on linux -			break; -		}; -	} +			switch (mEncoding) +			{ +			case ENCODING_DECIMAL: +				output_stream << indent << " encoding=\"decimal\"\n"; +				break; +			case ENCODING_HEX: +				output_stream << indent << " encoding=\"hex\"\n"; +				break; +			/*case ENCODING_BASE32: +				output_stream << indent << " encoding=\"base32\"\n"; +				break;*/ +			default: +				// default on switch(enum) eliminates a warning on linux +				break; +			}; +		} -	// Precision -	if (!has_default_precision && (mType == TYPE_INTEGER || mType == TYPE_FLOAT)) -	{ -		output_stream << indent << " precision=\"" << mPrecision << "\"\n"; -	} +		// Precision +		if (!has_default_precision && (mType == TYPE_INTEGER || mType == TYPE_FLOAT)) +		{ +			output_stream << indent << " precision=\"" << mPrecision << "\"\n"; +		} -	// Version -	if (mVersionMajor > 0 || mVersionMinor > 0) -	{ -		output_stream << indent << " version=\"" << mVersionMajor << "." << mVersionMinor << "\"\n"; -	} +		// Version +		if (mVersionMajor > 0 || mVersionMinor > 0) +		{ +			output_stream << indent << " version=\"" << mVersionMajor << "." << mVersionMinor << "\"\n"; +		} -	// Array length -	if (!has_default_length && mLength > 0) -	{ -		output_stream << indent << " length=\"" << mLength << "\"\n"; +		// Array length +		if (!has_default_length && mLength > 0) +		{ +			output_stream << indent << " length=\"" << mLength << "\"\n"; +		}  	}  	{ @@ -1039,12 +1042,13 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i  			if (child->mDefault.isNull() || child->mDefault->mValue != child->mValue)  			{  				std::string attr = child->mName->mString; -				if (attr == "id" || -					attr == "type" || -					attr == "encoding" || -					attr == "precision" || -					attr == "version" || -					attr == "length") +				if (use_type_decorations +					&& (attr == "id" || +						attr == "type" || +						attr == "encoding" || +						attr == "precision" || +						attr == "version" || +						attr == "length"))  				{  					continue; // skip built-in attributes  				} @@ -1074,7 +1078,7 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i  			std::string next_indent = indent + "    ";  			for (LLXMLNode* child = getFirstChild(); child; child = child->getNextSibling())  			{ -				child->writeToOstream(output_stream, next_indent); +				child->writeToOstream(output_stream, next_indent, use_type_decorations);  			}  		}  		if (!mValue.empty()) diff --git a/indra/llxml/llxmlnode.h b/indra/llxml/llxmlnode.h index cc9e5cb351..818d774f73 100644 --- a/indra/llxml/llxmlnode.h +++ b/indra/llxml/llxmlnode.h @@ -165,8 +165,8 @@ public:  	// Write XML to file with one attribute per line.  	// XML escapes values as they are written. -    void writeToFile(LLFILE *out_file, const std::string& indent = std::string()); -    void writeToOstream(std::ostream& output_stream, const std::string& indent = std::string()); +    void writeToFile(LLFILE *out_file, const std::string& indent = std::string(), bool use_type_decorations=true); +    void writeToOstream(std::ostream& output_stream, const std::string& indent = std::string(), bool use_type_decorations=true);      // Utility      void findName(const std::string& name, LLXMLNodeList &results); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index d06571fb7a..2e29a56e79 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -299,6 +299,7 @@ set(viewer_SOURCE_FILES      llpanelgroupnotices.cpp      llpanelgrouproles.cpp      llpanelinventory.cpp +    llpanelimcontrolpanel.cpp      llpanelland.cpp      llpanellandmarks.cpp      llpanellandmedia.cpp @@ -734,6 +735,7 @@ set(viewer_HEADER_FILES      llpanelgroupnotices.h      llpanelgrouproles.h      llpanelinventory.h +    llpanelimcontrolpanel.h      llpanelland.h      llpanellandmarks.h      llpanellandmedia.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index cb30cada70..ab9b018150 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -8091,7 +8091,7 @@        <key>Type</key>        <string>S32</string>        <key>Value</key> -      <real>1</real> +      <integer>4</integer>      </map>      <key>UIPreeditMarkerThickness</key>      <map> @@ -8135,7 +8135,7 @@        <key>Type</key>        <string>S32</string>        <key>Value</key> -      <real>2</real> +      <integer>4</integer>      </map>      <key>UIPreeditStandoutThickness</key>      <map> @@ -8146,7 +8146,7 @@        <key>Type</key>        <string>S32</string>        <key>Value</key> -      <real>2</real> +      <integer>2</integer>      </map>      <key>UIResizeBarHeight</key>      <map> diff --git a/indra/newview/llavatariconctrl.h b/indra/newview/llavatariconctrl.h index cb1e9584ba..e34f2ff474 100644 --- a/indra/newview/llavatariconctrl.h +++ b/indra/newview/llavatariconctrl.h @@ -46,9 +46,10 @@ public:  		Optional <LLUUID> avatar_id;  		Optional <bool> draw_tooltip;  		Params() +		:	avatar_id("avatar_id"), +			draw_tooltip("draw_tooltip", true)  		{  			name = "avatar_icon"; -			draw_tooltip = TRUE;  		}  	};  protected: diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h index 5835a4c6b4..dc73f187a7 100644 --- a/indra/newview/llavatarlistitem.h +++ b/indra/newview/llavatarlistitem.h @@ -57,7 +57,9 @@ public:  			{};  		} buttons; -        Params() : avatar_icon("avatar_icon",LLUUID()), user_name("user_name","") +        Params()  +		:	avatar_icon("avatar_icon"),  +			user_name("user_name")          {};  	}; diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index d84dd09812..963946e888 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -32,11 +32,14 @@  #include "llviewerprecompiledheaders.h" // must be first include  #include "llbottomtray.h" +  #include "llagent.h"  #include "llchiclet.h"  #include "llfloaterreg.h"  #include "llflyoutbutton.h" +#include "llimpanel.h"  #include "llkeyboard.h" +#include "lllineeditor.h"  #include "llgesturemgr.h"  #include "llanimationstates.h"  #include "llmultigesture.h" @@ -233,7 +236,13 @@ void LLBottomTray::onChicletClick(LLUICtrl* ctrl)  	LLIMChiclet* chiclet = dynamic_cast<LLIMChiclet*>(ctrl);  	if (chiclet)  	{ +		// Until you can type into an IM Window and have a conversation, +		// still show the old communicate window  		LLFloaterReg::showInstance("communicate", chiclet->getSessionId()); +		// DISABLED IN VIEWER-2 BRANCH UNTIL FEATURE IS DONE -- James +		//// Show after comm window so it is frontmost (and hence will not +		//// auto-hide) +		//LLIMFloater::show(chiclet->getSessionId());  	}  } diff --git a/indra/newview/llbottomtray.h b/indra/newview/llbottomtray.h index 330afeb647..08f5cb91d8 100644 --- a/indra/newview/llbottomtray.h +++ b/indra/newview/llbottomtray.h @@ -40,6 +40,7 @@  #include "llcombobox.h"  class LLChicletPanel; +class LLLineEditor;  class LLNotificationChiclet;  class LLTalkButton; diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp index 27ebccfe25..bb31b7f2e8 100644 --- a/indra/newview/llchatitemscontainerctrl.cpp +++ b/indra/newview/llchatitemscontainerctrl.cpp @@ -367,7 +367,7 @@ void	LLChatItemsContainerCtrl::updateLayout				(S32 width, S32 height)  	} -	//set sizes for first pannels and dragbars +	//set sizes for first panels and dragbars  	for(size_t i=0;i<mItems.size();++i)  	{  		LLRect panel_rect = mItems[i]->getRect(); diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 38a7494b5b..bfa4e06d2e 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -37,7 +37,7 @@  #include "llbottomtray.h"  #include "llgroupactions.h"  #include "lliconctrl.h" -#include "llimpanel.h" +#include "llimpanel.h"				// LLFloaterIMPanel  #include "llimview.h"  #include "llfloatergroupinfo.h"  #include "llmenugl.h" @@ -203,6 +203,7 @@ LLIMChiclet::LLIMChiclet(const Params& p)  , mSpeakerCtrl(NULL)  , mShowSpeaker(p.show_speaker)  , mPopupMenu(NULL) +, mDockTongueVisible(false)  {  	LLChicletAvatarIconCtrl::Params avatar_params = p.avatar_icon;  	mAvatarCtrl = LLUICtrlFactory::create<LLChicletAvatarIconCtrl>(avatar_params); @@ -227,6 +228,11 @@ LLIMChiclet::~LLIMChiclet()  } +void LLIMChiclet::setDockTongueVisible(bool visible) +{ +	mDockTongueVisible = visible; +} +  void LLIMChiclet::setCounter(S32 counter)  {  	mCounterCtrl->setCounter(counter); @@ -321,6 +327,13 @@ void LLIMChiclet::draw()  {  	LLUICtrl::draw();  	gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4(0.0f,0.0f,0.0f,1.f), FALSE); + +	if (mDockTongueVisible) +	{ +		LLUIImagePtr flyout_tongue = LLUI::getUIImage("windows/Flyout_Pointer.png"); +		// was previously AVATAR_WIDTH-16 and CHICLET_HEIGHT-6 +		flyout_tongue->draw( getRect().getWidth()-31, getRect().getHeight()-5); +	}  }  BOOL LLIMChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask) @@ -552,14 +565,6 @@ void LLChicletPanel::onChicletSizeChanged(LLChiclet* ctrl, const LLSD& param)  void LLChicletPanel::onChicletClick(LLUICtrl*ctrl,const LLSD¶m)  { -	LLIMChiclet* chiclet = dynamic_cast<LLIMChiclet*>(ctrl); -	if (chiclet) -	{ -		S32 x, y; -		LLRect rect = getRect(); -		localPointToScreen(rect.getCenterX(), 0, &x, &y); -		LLIMFloater::show(chiclet->getSessionId(), x); -	}  	mCommitSignal(ctrl,param);  } @@ -653,7 +658,7 @@ void LLChicletPanel::reshape(S32 width, S32 height, BOOL called_from_parent )  		width, height - scroll_button_rect.getHeight()));  	mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + SCROLL_BUTTON_PAD, -		height + 1, width - scroll_button_rect.getWidth() - SCROLL_BUTTON_PAD, 0)); +		height + 7, width - scroll_button_rect.getWidth() - SCROLL_BUTTON_PAD, 0));  	trimChiclets(); diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index e467ec012a..415ae59ca2 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -34,6 +34,7 @@  #define LL_LLCHICLET_H  #include "llavatariconctrl.h" +#include "llbutton.h"  #include "llpanel.h"  #include "lltextbox.h"  #include "lloutputmonitorctrl.h" @@ -266,6 +267,8 @@ public:  	*/  	virtual void setShowSpeaker(bool show); +	void setDockTongueVisible(bool visible); +  	/*  	 * Returns voice chat status control visibility.  	*/ @@ -332,6 +335,7 @@ protected:  	LLMenuGL* mPopupMenu;  	bool mShowSpeaker; +	bool mDockTongueVisible;  };  /* diff --git a/indra/newview/llfloaterinventory.cpp b/indra/newview/llfloaterinventory.cpp index d05a32dc88..cf78d7d34f 100644 --- a/indra/newview/llfloaterinventory.cpp +++ b/indra/newview/llfloaterinventory.cpp @@ -42,7 +42,7 @@  #include "llcallingcard.h"  #include "llfloaterreg.h"  #include "llsdserialize.h" -#include "llsearcheditor.h" +#include "llfiltereditor.h"  #include "llspinctrl.h"  #include "llui.h"  #include "message.h" @@ -530,10 +530,10 @@ BOOL LLFloaterInventory::postBuild()  	} -	mSearchEditor = getChild<LLSearchEditor>("inventory search editor"); -	if (mSearchEditor) +	mFilterEditor = getChild<LLFilterEditor>("inventory search editor"); +	if (mFilterEditor)  	{ -		mSearchEditor->setSearchCallback(boost::bind(&LLFloaterInventory::onSearchEdit, this, _1)); +		mFilterEditor->setCommitCallback(boost::bind(&LLFloaterInventory::onFilterEdit, this, _2));  	}  	// *TODO:Get the cost info from the server @@ -598,9 +598,9 @@ void LLFloaterInventory::draw()  		title << mFilterText;  		setTitle(title.str());  	} -	if (mActivePanel && mSearchEditor) +	if (mActivePanel && mFilterEditor)  	{ -		mSearchEditor->setText(mActivePanel->getFilterSubString()); +		mFilterEditor->setText(mActivePanel->getFilterSubString());  	}  	LLFloater::draw();  } @@ -673,9 +673,9 @@ void LLOpenFoldersWithSelection::doFolder(LLFolderViewFolder* folder)  void LLFloaterInventory::startSearch()  {  	// this forces focus to line editor portion of search editor -	if (mSearchEditor) +	if (mFilterEditor)  	{ -		mSearchEditor->focusFirstItem(TRUE); +		mFilterEditor->focusFirstItem(TRUE);  	}  } @@ -715,8 +715,8 @@ BOOL LLFloaterInventory::handleKeyHere(KEY key, MASK mask)  	if (root_folder)  	{  		// first check for user accepting current search results -		if (mSearchEditor  -			&& mSearchEditor->hasFocus() +		if (mFilterEditor  +			&& mFilterEditor->hasFocus()  		    && (key == KEY_RETURN   		    	|| key == KEY_DOWN)  		    && mask == MASK_NONE) @@ -966,7 +966,7 @@ void LLFloaterInventory::onClearSearch()  	}  } -void LLFloaterInventory::onSearchEdit(const std::string& search_string ) +void LLFloaterInventory::onFilterEdit(const std::string& search_string )  {  	if (search_string == "")  	{ diff --git a/indra/newview/llfloaterinventory.h b/indra/newview/llfloaterinventory.h index cd60407507..35ac1ab380 100644 --- a/indra/newview/llfloaterinventory.h +++ b/indra/newview/llfloaterinventory.h @@ -64,7 +64,7 @@ class LLScrollContainer;  class LLTextBox;  class LLIconCtrl;  class LLSaveFolderState; -class LLSearchEditor; +class LLFilterEditor;  class LLTabContainer;  class LLInventoryPanel : public LLPanel @@ -267,7 +267,7 @@ public:  	void onClearSearch();  	static void onFoldersByName(void *user_data);  	static BOOL checkFoldersByName(void *user_data); -	void onSearchEdit(const std::string& search_string ); +	void onFilterEdit(const std::string& search_string );  	static BOOL incrementalFind(LLFolderViewItem* first_item, const char *find_text, BOOL backward);  	void onFilterSelected(); @@ -291,7 +291,7 @@ public:  	LLFloaterInventoryFinder* getFinder() { return (LLFloaterInventoryFinder*)mFinderHandle.get(); }  protected: -	LLSearchEditor*				mSearchEditor; +	LLFilterEditor*				mFilterEditor;  	LLTabContainer*				mFilterTabs;  	LLHandle<LLFloater>			mFinderHandle;  	LLInventoryPanel*			mActivePanel; diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 08a042707d..149df61b35 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -1490,26 +1490,26 @@ void LLPanelLandObjects::processParcelObjectOwnersReply(LLMessageSystem *msg, vo  		if (is_group_owned)  		{ -			item_params.cells.add().type("icon").value(self->mIconGroup->getName()).column("type"); -			item_params.cells.add().value(OWNER_GROUP).font(FONT).column("online_status"); +			item_params.columns.add().type("icon").value(self->mIconGroup->getName()).column("type"); +			item_params.columns.add().value(OWNER_GROUP).font(FONT).column("online_status");  		}  		else if (is_online)  		{ -			item_params.cells.add().type("icon").value(self->mIconAvatarOnline->getName()).column("type"); -			item_params.cells.add().value(OWNER_ONLINE).font(FONT).column("online_status"); +			item_params.columns.add().type("icon").value(self->mIconAvatarOnline->getName()).column("type"); +			item_params.columns.add().value(OWNER_ONLINE).font(FONT).column("online_status");  		}  		else  // offline  		{ -			item_params.cells.add().type("icon").value(self->mIconAvatarOffline->getName()).column("type"); -			item_params.cells.add().value(OWNER_OFFLINE).font(FONT).column("online_status"); +			item_params.columns.add().type("icon").value(self->mIconAvatarOffline->getName()).column("type"); +			item_params.columns.add().value(OWNER_OFFLINE).font(FONT).column("online_status");  		}  		// Placeholder for name. -		item_params.cells.add().font(FONT).column("name"); +		item_params.columns.add().font(FONT).column("name");  		object_count_str = llformat("%d", object_count); -		item_params.cells.add().value(object_count_str).font(FONT).column("count"); -		item_params.cells.add().value(formatted_time((time_t)most_recent_time)).font(FONT).column("mostrecent"); +		item_params.columns.add().value(object_count_str).font(FONT).column("count"); +		item_params.columns.add().value(formatted_time((time_t)most_recent_time)).font(FONT).column("mostrecent");  		self->mOwnerList->addRow(item_params); diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp index 41e9ee3ccd..4870494b20 100644 --- a/indra/newview/llfloateruipreview.cpp +++ b/indra/newview/llfloateruipreview.cpp @@ -57,6 +57,7 @@  #include "lldraghandle.h"  #include "lllayoutstack.h"  #include "llviewermenu.h" +#include "llrngwriter.h"  // Boost (for linux/unix command-line execv)  #include <boost/tokenizer.hpp> @@ -354,6 +355,7 @@ void LLFloaterUIPreview::onLanguageComboSelect(LLUICtrl* ctrl)  void LLFloaterUIPreview::onClickExportSchema()  { +	gViewerWindow->setCursor(UI_CURSOR_WAIT);  	std::string template_path = gDirUtilp->getExpandedFilename(LL_PATH_DEFAULT_SKIN, "xui", "schema");  	typedef LLWidgetTypeRegistry::Registrar::registry_map_t::const_iterator registry_it; @@ -373,10 +375,12 @@ void LLFloaterUIPreview::onClickExportSchema()  		LLFILE* rng_file = LLFile::fopen(file_name.c_str(), "w");  		{  			LLXMLNode::writeHeaderToFile(rng_file); -			root_nodep->writeToFile(rng_file); +			const bool use_type_decorations = false; +			root_nodep->writeToFile(rng_file, std::string(), use_type_decorations);  		}  		fclose(rng_file);  	} +	gViewerWindow->setCursor(UI_CURSOR_ARROW);  } @@ -625,7 +629,8 @@ void LLFloaterUIPreview::displayFloater(BOOL click, S32 ID, bool save)  				std::string full_filename = append_new_to_xml_filename(path);  				LLFILE* floater_temp = LLFile::fopen(full_filename.c_str(), "w");  				LLXMLNode::writeHeaderToFile(floater_temp); -				floater_write->writeToFile(floater_temp); +				const bool use_type_decorations = false; +				floater_write->writeToFile(floater_temp, std::string(), use_type_decorations);  				fclose(floater_temp);  			}  		} @@ -647,7 +652,8 @@ void LLFloaterUIPreview::displayFloater(BOOL click, S32 ID, bool save)  				std::string full_filename = append_new_to_xml_filename(path);  				LLFILE* menu_temp = LLFile::fopen(full_filename.c_str(), "w");  				LLXMLNode::writeHeaderToFile(menu_temp); -				menu_write->writeToFile(menu_temp); +				const bool use_type_decorations = false; +				menu_write->writeToFile(menu_temp, std::string(), use_type_decorations);  				fclose(menu_temp);  			} @@ -671,7 +677,8 @@ void LLFloaterUIPreview::displayFloater(BOOL click, S32 ID, bool save)  				std::string full_filename = append_new_to_xml_filename(path);  				LLFILE* panel_temp = LLFile::fopen(full_filename.c_str(), "w");  				LLXMLNode::writeHeaderToFile(panel_temp); -				panel_write->writeToFile(panel_temp); +				const bool use_type_decorations = false; +				panel_write->writeToFile(panel_temp, std::string(), use_type_decorations);  				fclose(panel_temp);  			}  		} diff --git a/indra/newview/llfloateruipreview.h b/indra/newview/llfloateruipreview.h index 1307d60689..eca8c0a141 100644 --- a/indra/newview/llfloateruipreview.h +++ b/indra/newview/llfloateruipreview.h @@ -49,6 +49,7 @@ class LLColor;  class LLScrollListCtrl;  class LLComboBox;  class LLButton; +class LLLineEditor;  class LLXmlTreeNode;  class LLFloaterUIPreview;  class LLFadeEventTimer; diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h index 5c1760ce22..d52079fc06 100644 --- a/indra/newview/llfloaterworldmap.h +++ b/indra/newview/llfloaterworldmap.h @@ -49,6 +49,7 @@ class LLFriendObserver;  class LLInventoryModel;  class LLInventoryObserver;  class LLItemInfo; +class LLLineEditor;  class LLTabContainer;  class LLFloaterWorldMap : public LLFloater diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 43f3ea8d8f..a6a8da2a76 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -81,8 +81,9 @@ void LLFolderViewItem::cleanupClass()  // NOTE: Optimize this, we call it a *lot* when opening a large inventory  LLFolderViewItem::Params::Params() -:	folder_arrow_image("", LLUI::getUIImage("folder_arrow.tga")), -	selection_image("", LLUI::getUIImage("rounded_square.tga")) +:	icon("icon"), +	folder_arrow_image("folder_arrow_image", LLUI::getUIImage("folder_arrow.tga")), +	selection_image("selection_image", LLUI::getUIImage("rounded_square.tga"))  {  	mouse_opaque(true);  	follows.flags(FOLLOWS_LEFT|FOLLOWS_TOP|FOLLOWS_RIGHT); diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index 5b4f711099..248a8dbc4c 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -45,8 +45,10 @@  #include "llagent.h"  #include "llbutton.h" +#include "llbottomtray.h"  #include "llcallingcard.h"  #include "llchat.h" +#include "llchiclet.h"  #include "llconsole.h"  #include "llfloater.h"  #include "llfloatercall.h" @@ -57,9 +59,12 @@  #include "llinventorymodel.h"  #include "llfloaterinventory.h"  #include "llfloaterchat.h" +#include "lliconctrl.h" +#include "llimview.h"                  // for LLIMModel to get other avatar id in chat  #include "llkeyboard.h"  #include "lllineeditor.h"  #include "llnotify.h" +#include "llpanelimcontrolpanel.h"  #include "llrecentpeople.h"  #include "llresmgr.h"  #include "lltrans.h" @@ -2040,7 +2045,7 @@ bool LLFloaterIMPanel::onConfirmForceCloseError(const LLSD& notification, const  	}  	return false;  } - +	  std::map<LLUUID, LLIMFloater*> LLIMFloater::sIMFloaterMap; @@ -2048,23 +2053,183 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id,  					 const std::string title,  					 EInstantMessage dialog)  :	mSessionID(session_id), -	mIndex(0) +	mLastMessageIndex(-1), +	mDialog(dialog)  {  	LLUICtrlFactory::getInstance()->buildFloater(this, "floater_im_session.xml");  	sIMFloaterMap[mSessionID] = this; +	LLPanelIMControlPanel* im_control_panel = getChild<LLPanelIMControlPanel>("panel_im_control_panel"); + +	LLIMModel::LLIMSession* session = get_if_there(LLIMModel::instance().sSessionsMap, session_id, (LLIMModel::LLIMSession*)NULL); +	if(session) +	{ +		mOtherParticipantUUID = session->mOtherParticipantID; +		im_control_panel->setAvatarId(session->mOtherParticipantID); +	} + +	LLButton* slide_left = getChild<LLButton>("slide_left_btn"); +	slide_left->setVisible(im_control_panel->getVisible()); +	slide_left->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this)); + +	LLButton* slide_right = getChild<LLButton>("slide_right_btn"); +	slide_right->setVisible(!im_control_panel->getVisible()); +	slide_right->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this)); +  	setTitle(title); +	setDocked(true); + +	mInputEditor = getChild<LLLineEditor>("chat_editor"); + +	 +	mInputEditor->setMaxTextLength(1023); +	// enable line history support for instant message bar +	mInputEditor->setEnableLineHistory(TRUE); +	 +	mInputEditor->setFocusReceivedCallback( onInputEditorFocusReceived, this ); +	mInputEditor->setFocusLostCallback( onInputEditorFocusLost, this ); +	mInputEditor->setKeystrokeCallback( onInputEditorKeystroke, this ); +	mInputEditor->setCommitOnFocusLost( FALSE ); +	mInputEditor->setRevertOnEsc( FALSE ); +	mInputEditor->setReplaceNewlinesWithSpaces( FALSE ); + +	childSetCommitCallback("chat_editor", onSendMsg, this); +} + +/* static */ +void LLIMFloater::newIMCallback(const LLSD& data){ +	 +	if (data["num_unread"].asInteger() > 0) +	{ +		LLUUID session_id = data["session_id"].asUUID(); + +		LLIMFloater* floater = get_if_there(sIMFloaterMap, session_id, (LLIMFloater*)NULL); +		 +		if (floater == NULL) +		{ +			llwarns << "new_im_callback for non-existent session_id " << session_id << llendl; +			return; +		} + +        // update if visible, otherwise will be updated when opened +		if (floater->getVisible()) +		{ +			floater->updateMessages(); +		} +	} +} + +void LLIMFloater::onSendMsg( LLUICtrl* ctrl, void* userdata ) +{ +	LLIMFloater* self = (LLIMFloater*) userdata; +	self->sendMsg();  } +void LLIMFloater::sendMsg() +{ +	if (!gAgent.isGodlike()  +		&& (mDialog == IM_NOTHING_SPECIAL) +		&& mOtherParticipantUUID.isNull()) +	{ +		llinfos << "Cannot send IM to everyone unless you're a god." << llendl; +		return; +	} + +	if (mInputEditor) +	{ +		LLWString text = mInputEditor->getConvertedText(); +		if(!text.empty()) +		{ +			// Truncate and convert to UTF8 for transport +			std::string utf8_text = wstring_to_utf8str(text); +			utf8_text = utf8str_truncate(utf8_text, MAX_MSG_BUF_SIZE - 1); +			 +			LLIMModel::sendMessage(utf8_text, +								mSessionID, +								mOtherParticipantUUID, +								mDialog); + +			mInputEditor->setText(LLStringUtil::null); + +			updateMessages(); +		} +	} +} + + +  LLIMFloater::~LLIMFloater()  {  	sIMFloaterMap.erase(mSessionID);  } +//virtual +BOOL LLIMFloater::postBuild() +{ +	mHistoryEditor = getChild<LLViewerTextEditor>("im_text", true, false); +	mChiclet = LLBottomTray::getInstance()->getChicletPanel()->findChiclet<LLIMChiclet>(mSessionID); + +	if (!mChiclet) +	{ +		llwarns << "No chiclet found for the IMFloter" << llendl; +	} +	setDocked(false); +	return TRUE; +} + +const U32 UNDOCK_LEAP_HEIGHT = 12; +const U32 DOCK_ICON_HEIGHT = 6; -void LLIMFloater::show(const LLUUID& session_id, S32 center_x) +//virtual +void LLIMFloater::onFocusLost()  { +	// spec says close if docked to bottom tray and user has clicked away +	// (hence we are no longer focused) +	if (isDocked()) +	{ +		// app not quitting +		closeFloater(false); +	} +} + +//virtual +void LLIMFloater::setDocked(bool docked, bool pop_on_undock) +{ +	LLFloater::setDocked(docked); +	mChiclet->setDockTongueVisible(docked); +	if (docked) +	{ +		S32 x, y; +		mChiclet->localPointToScreen((mChiclet->getRect().getWidth())/2, 0, &x, &y); +		translate(x - getRect().getCenterX(), DOCK_ICON_HEIGHT - getRect().mBottom);	 +	} +	else if (pop_on_undock) +	{ +		// visually pop up a little bit to emphasize the undocking +		translate(0, UNDOCK_LEAP_HEIGHT); +	} +} + + +void LLIMFloater::onClose(bool app_quitting) +{ +	mChiclet->setDockTongueVisible(false); +	LLFloater::onClose(app_quitting); +} + +void LLIMFloater::onSlide() +{ +	LLPanel* im_control_panel = getChild<LLPanel>("panel_im_control_panel"); +	im_control_panel->setVisible(!im_control_panel->getVisible()); + +	getChild<LLButton>("slide_left_btn")->setVisible(im_control_panel->getVisible()); +	getChild<LLButton>("slide_right_btn")->setVisible(!im_control_panel->getVisible()); +} + +//static +LLIMFloater* LLIMFloater::show(const LLUUID& session_id) +{  	LLIMFloater* floater = get_if_there(sIMFloaterMap, session_id, (LLIMFloater*)NULL);  	if (floater == NULL) @@ -2078,28 +2243,25 @@ void LLIMFloater::show(const LLUUID& session_id, S32 center_x)  	{  		LLIMFloater* floater = (*iter).second;  		floater->setVisible(false); +		floater->mChiclet->setDockTongueVisible(false); +	  	} -	//floater->setVisibleAndFrontmost(true); +	floater->setVisibleAndFrontmost(true); -	floater->updateMessages(session_id); - -	floater->translate(center_x - floater->getRect().getCenterX(), gFloaterView->getRect().mBottom - floater->getRect().mBottom); +	if (floater->isDocked())  +	{ +		floater->mChiclet->setDockTongueVisible(true); +	} +	floater->updateMessages(); +	return floater;  } -void LLIMFloater::updateMessages(const LLUUID& session_id) +void LLIMFloater::updateMessages()  { -	LLTextEditor* text_editor = getChild<LLTextEditor>("im_text", true, false); - -	if (!text_editor)  -	{ -		llwarns << "Text editor not found! " << llendl; -		return; -	} - -	std::list<LLSD> messages = LLIMModel::instance().getMessages(mSessionID, mIndex); +	std::list<LLSD> messages = LLIMModel::instance().getMessages(mSessionID, mLastMessageIndex+1);  	if (messages.size())  	{ @@ -2112,10 +2274,45 @@ void LLIMFloater::updateMessages(const LLUUID& session_id)  			message << msg["from"].asString() << " : " << msg["time"].asString() << "\n   " << msg["message"].asString() << "\n";  -			mIndex = msg["index"].asInteger(); +			mLastMessageIndex = msg["index"].asInteger();  		} -		text_editor->setText(message.str()); +		mHistoryEditor->appendText(message.str(), false, false); +		mHistoryEditor->setCursorAndScrollToEnd();  	}  } +// static +void LLIMFloater::onInputEditorFocusReceived( LLFocusableElement* caller, void* userdata ) +{ +	LLIMFloater* self= (LLIMFloater*) userdata; +	self->mHistoryEditor->setCursorAndScrollToEnd(); +} + +// static +void LLIMFloater::onInputEditorFocusLost(LLFocusableElement* caller, void* userdata) +{ +	LLIMFloater* self = (LLIMFloater*) userdata; +	self->setTyping(FALSE); +} + +// static +void LLIMFloater::onInputEditorKeystroke(LLLineEditor* caller, void* userdata) +{ +	LLIMFloater* self = (LLIMFloater*)userdata; +	std::string text = self->mInputEditor->getText(); +	if (!text.empty()) +	{ +		self->setTyping(TRUE); +	} +	else +	{ +		// Deleting all text counts as stopping typing. +		self->setTyping(FALSE); +	} +} + +//just a stub for now +void LLIMFloater::setTyping(BOOL typing) +{ +} diff --git a/indra/newview/llimpanel.h b/indra/newview/llimpanel.h index 88f21864b5..e6bde5c93a 100644 --- a/indra/newview/llimpanel.h +++ b/indra/newview/llimpanel.h @@ -47,6 +47,7 @@ class LLInventoryItem;  class LLInventoryCategory;  class LLIMSpeakerMgr;  class LLPanelActiveSpeakers; +class LLIMChiclet;  class LLVoiceChannel : public LLVoiceClientStatusObserver  { @@ -359,6 +360,8 @@ private:  }; +// Individual IM window that appears at the bottom of the screen, +// optionally "docked" to the bottom tray.  class LLIMFloater : public LLFloater  {  public: @@ -367,14 +370,49 @@ public:  			  EInstantMessage dialog);  	virtual ~LLIMFloater(); +	 +	// LLView overrides +	/*virtual*/ BOOL postBuild(); + +	// Floater should close when user clicks away to other UI area, +	// hence causing focus loss. +	/*virtual*/ void onFocusLost(); + +	// LLFloater overrides +	/*virtual*/ void setDocked(bool docked,  bool pop_on_undock = true); + +	static LLIMFloater* show(const LLUUID& session_id); +	void onClose(bool app_quitting); -	static void show(const LLUUID& session_id, S32 center_x); -	void updateMessages(const LLUUID& session_id); +	// get new messages from LLIMModel +	void updateMessages(); +	static void onSendMsg( LLUICtrl*, void*); +	void sendMsg(); +	// callback for LLIMModel on new messages +	// route to specific floater if it is visible +	static void newIMCallback(const LLSD& data); +	  	static std::map<LLUUID, LLIMFloater*> sIMFloaterMap; +	 + +private: +	 +	static void		onInputEditorFocusReceived( LLFocusableElement* caller, void* userdata ); +	static void		onInputEditorFocusLost(LLFocusableElement* caller, void* userdata); +	static void		onInputEditorKeystroke(LLLineEditor* caller, void* userdata); +	void			setTyping(BOOL typing); +	void onSlide(); +	  	LLUUID mSessionID; -	U32 mIndex; +	S32 mLastMessageIndex; +	EInstantMessage mDialog; +	LLIMChiclet* mChiclet; +	LLUUID mOtherParticipantUUID; +	LLViewerTextEditor* mHistoryEditor; +	LLLineEditor* mInputEditor; +  }; diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 38335fe68f..0505baac41 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -113,14 +113,16 @@ void toast_callback(const LLSD& msg){  LLIMModel::LLIMModel()   {  	addChangedCallback(toast_callback); +	addChangedCallback(LLIMFloater::newIMCallback);  }  void LLIMModel::testMessages()  { -	static LLUUID bot1_id, bot1_session_id; -	if (bot1_id.isNull()) bot1_id.generate(); -	std::string from = "Bot1 TestLinden"; +	LLUUID bot1_id("d0426ec6-6535-4c11-a5d9-526bb0c654d9"); +	LLUUID bot1_session_id; +	std::string from = "IM Tester"; +  	bot1_session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, bot1_id);  	newSession(bot1_session_id, from, IM_NOTHING_SPECIAL, bot1_id);  	addMessage(bot1_session_id, from, "Test Message: Hi from testerbot land!"); @@ -158,7 +160,7 @@ bool LLIMModel::newSession(LLUUID session_id, std::string name, EInstantMessage  } -std::list<LLSD> LLIMModel::getMessages(LLUUID session_id, int index) +std::list<LLSD> LLIMModel::getMessages(LLUUID session_id, int start_index)  {  	std::list<LLSD> return_list; @@ -170,7 +172,7 @@ std::list<LLSD> LLIMModel::getMessages(LLUUID session_id, int index)  		return return_list;  	} -	int i = session->mMsgs.size() - index; +	int i = session->mMsgs.size() - start_index;  	for (std::list<LLSD>::iterator iter = session->mMsgs.begin();   		iter != session->mMsgs.end() && i > 0; diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 6a354dfe92..b3b821f2ac 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -53,11 +53,11 @@ public:  	struct LLIMSession  	{  		LLIMSession(std::string name, EInstantMessage type, LLUUID other_participant_id)  -			:mName(name), mType(type), mNumUnread(0), mOtherPraticipantID(other_participant_id) {} +			:mName(name), mType(type), mNumUnread(0), mOtherParticipantID(other_participant_id) {}  		std::string mName;  		EInstantMessage mType; -		LLUUID mOtherPraticipantID; +		LLUUID mOtherParticipantID;  		S32 mNumUnread;  		std::list<LLSD> mMsgs;  	}; @@ -70,7 +70,7 @@ public:  	boost::signals2::connection addChangedCallback( boost::function<void (const LLSD& data)> cb );  	bool newSession(LLUUID session_id, std::string name, EInstantMessage type, LLUUID other_participant_id); -	std::list<LLSD> getMessages(LLUUID session_id, int index = 0); +	std::list<LLSD> getMessages(LLUUID session_id, int start_index = 0);  	bool addMessage(LLUUID session_id, std::string from, std::string utf8_text);  	bool addToHistory(LLUUID session_id, std::string from, std::string utf8_text);       //used to get the name of the session, for use as the title diff --git a/indra/newview/llmenucommands.cpp b/indra/newview/llmenucommands.cpp index 0c652621f4..cfcb331912 100644 --- a/indra/newview/llmenucommands.cpp +++ b/indra/newview/llmenucommands.cpp @@ -51,6 +51,7 @@  #include "llfloaterworldmap.h"  #include "llgivemoney.h"  #include "llfloaterinventory.h" +#include "lllineeditor.h"  #include "llnotify.h"  #include "llstatusbar.h"  #include "llimview.h" diff --git a/indra/newview/llnameeditor.h b/indra/newview/llnameeditor.h index f9cabb5831..99e03a1166 100644 --- a/indra/newview/llnameeditor.h +++ b/indra/newview/llnameeditor.h @@ -50,6 +50,11 @@ public:  	{  		Optional<bool>		is_group;  		Optional<LLUUID>	name_id; + +		Params() +		:	is_group("is_group"), +			name_id("name_id") +		{}  	};  protected: diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp index d7066cb140..ffc3b2f37a 100644 --- a/indra/newview/llnamelistctrl.cpp +++ b/indra/newview/llnamelistctrl.cpp @@ -169,7 +169,7 @@ LLScrollListItem* LLNameListCtrl::addRow(const LLNameListCtrl::NameItem& name_it  	if (!item) return NULL;  	// use supplied name by default -	std::string fullname = name_item.display_name; +	std::string fullname = name_item.name;  	switch(name_item.target)  	{  	case GROUP: diff --git a/indra/newview/llnamelistctrl.h b/indra/newview/llnamelistctrl.h index 6692d4cff9..80feaea881 100644 --- a/indra/newview/llnamelistctrl.h +++ b/indra/newview/llnamelistctrl.h @@ -57,11 +57,11 @@ public:  	struct NameItem : public LLInitParam::Block<NameItem, LLScrollListItem::Params>  	{ -		Optional<std::string>				display_name; +		Optional<std::string>				name;  		Optional<ENameType, NameTypeNames>	target;  		NameItem() -		:	display_name("name"), +		:	name("name"),  			target("target", INDIVIDUAL)  		{}		  	}; diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp index fbeff2d628..c0bddd101e 100644 --- a/indra/newview/llnavigationbar.cpp +++ b/indra/newview/llnavigationbar.cpp @@ -45,6 +45,7 @@  #include "lllocationhistory.h"  #include "lllocationinputctrl.h"  #include "llteleporthistory.h" +#include "llsearcheditor.h"  #include "llslurl.h"  #include "llurlsimstring.h"  #include "llviewerinventory.h" @@ -204,12 +205,10 @@ BOOL LLNavigationBar::postBuild()  	mBtnHelp	= getChild<LLButton>("help_btn");  	mCmbLocation= getChild<LLLocationInputCtrl>("location_combo");  -	mLeSearch	= getChild<LLLineEditor>("search_input"); -	 -	LLButton* search_btn = getChild<LLButton>("search_btn"); +	mLeSearch	= getChild<LLSearchEditor>("search_input");  	if (!mBtnBack || !mBtnForward || !mBtnHome || !mBtnHelp || -		!mCmbLocation || !mLeSearch || !search_btn) +		!mCmbLocation || !mLeSearch)  	{  		llwarns << "Malformed navigation bar" << llendl;  		return FALSE; @@ -229,7 +228,6 @@ BOOL LLNavigationBar::postBuild()  	mCmbLocation->setSelectionCallback(boost::bind(&LLNavigationBar::onLocationSelection, this));  	mLeSearch->setCommitCallback(boost::bind(&LLNavigationBar::onSearchCommit, this)); -	search_btn->setClickedCallback(boost::bind(&LLNavigationBar::onSearchCommit, this));  	// Load the location field context menu  	mLocationContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_navbar.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); @@ -306,7 +304,7 @@ void LLNavigationBar::onHelpButtonClicked()  void LLNavigationBar::onSearchCommit()  { -	invokeSearch(mLeSearch->getText()); +	invokeSearch(mLeSearch->getValue().asString());  }  void LLNavigationBar::onTeleportHistoryMenuItemClicked(const LLSD& userdata) diff --git a/indra/newview/llnavigationbar.h b/indra/newview/llnavigationbar.h index 846040e506..a82dfc73ff 100644 --- a/indra/newview/llnavigationbar.h +++ b/indra/newview/llnavigationbar.h @@ -40,7 +40,7 @@ extern S32 NAVIGATION_BAR_HEIGHT;  class LLButton;  class LLLocationInputCtrl;  class LLMenuGL; -class LLLineEditor; +class LLSearchEditor;  /**   * Web browser-like navigation bar. @@ -97,7 +97,7 @@ private:  	LLButton*				mBtnForward;  	LLButton*				mBtnHome;  	LLButton*				mBtnHelp; -	LLLineEditor*			mLeSearch; +	LLSearchEditor*			mLeSearch;  	LLLocationInputCtrl*	mCmbLocation;  	bool					mPurgeTPHistoryItems;  }; diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp index 340cb8187d..955f50caf5 100644 --- a/indra/newview/lloutputmonitorctrl.cpp +++ b/indra/newview/lloutputmonitorctrl.cpp @@ -52,7 +52,8 @@ LLColor4	LLOutputMonitorCtrl::sColorBound;  //F32			LLOutputMonitorCtrl::sRectHeightRatio	= 0.f;  LLOutputMonitorCtrl::Params::Params() -:	image_mute("image_mute"), +:	draw_border("draw_border"), +	image_mute("image_mute"),  	image_off("image_off"),  	image_on("image_on"),  	image_level_1("image_level_1"), diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index 868d4d9200..bf6ecd6bf4 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -61,6 +61,7 @@ public:  	{  		Optional<LLUUID> agent_id;  		Params() +		:	agent_id("agent_id")  		{  			mouse_opaque(false);  			follows.flags(FOLLOWS_ALL); diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp new file mode 100644 index 0000000000..45fe625a13 --- /dev/null +++ b/indra/newview/llpanelimcontrolpanel.cpp @@ -0,0 +1,87 @@ +/**  + * @file llpanelavatar.cpp + * @brief LLPanelAvatar and related class implementations + * + * $LicenseInfo:firstyear=2004&license=viewergpl$ + *  + * Copyright (c) 2004-2009, Linden Research, Inc. + *  + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + *  + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + *  + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + *  + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llpanelimcontrolpanel.h" + +#include "llavataractions.h" +#include "llavatariconctrl.h" +#include "llbutton.h" + +static LLRegisterPanelClassWrapper<LLPanelIMControlPanel> t_im_control_panel("panel_im_control_panel"); + +LLPanelIMControlPanel::LLPanelIMControlPanel() +: LLPanel() +{ +} + +LLPanelIMControlPanel::~LLPanelIMControlPanel() +{ +} + +BOOL LLPanelIMControlPanel::postBuild() +{ +	childSetAction("view_profile_btn", boost::bind(&LLPanelIMControlPanel::onViewProfileButtonClicked, this)); +	childSetAction("add_friend_btn", boost::bind(&LLPanelIMControlPanel::onAddFriendButtonClicked, this)); +	childSetAction("call_btn", boost::bind(&LLPanelIMControlPanel::onCallButtonClicked, this)); +	childSetAction("share_btn", boost::bind(&LLPanelIMControlPanel::onShareButtonClicked, this)); + +	return TRUE; +} + +void LLPanelIMControlPanel::onViewProfileButtonClicked() +{ +	LLAvatarActions::showProfile(getChild<LLAvatarIconCtrl>("avatar_icon")->getAvatarId()); +} + +void LLPanelIMControlPanel::onAddFriendButtonClicked() +{ +	LLAvatarIconCtrl* avatar_icon = getChild<LLAvatarIconCtrl>("avatar_icon"); +	std::string full_name = avatar_icon->getFirstName() + " " + avatar_icon->getLastName(); +	LLAvatarActions::requestFriendshipDialog(avatar_icon->getAvatarId(), full_name); +} + +void LLPanelIMControlPanel::onCallButtonClicked() +{ +	// *TODO: Implement +} + +void LLPanelIMControlPanel::onShareButtonClicked() +{ +	// *TODO: Implement +} + +void LLPanelIMControlPanel::setAvatarId(const LLUUID& avatar_id) +{ +	getChild<LLAvatarIconCtrl>("avatar_icon")->setValue(avatar_id); +} diff --git a/indra/newview/llpanelimcontrolpanel.h b/indra/newview/llpanelimcontrolpanel.h new file mode 100644 index 0000000000..be3b2d3130 --- /dev/null +++ b/indra/newview/llpanelimcontrolpanel.h @@ -0,0 +1,55 @@ +/**  + * @file llpanelimcontrolpanel.h + * @brief LLPanelIMControlPanel and related class definitions + * + * $LicenseInfo:firstyear=2004&license=viewergpl$ + *  + * Copyright (c) 2004-2009, Linden Research, Inc. + *  + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + *  + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + *  + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + *  + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLPANELIMCONTROLPANEL_H +#define LL_LLPANELIMCONTROLPANEL_H + +#include "llpanel.h" + +class LLPanelIMControlPanel : public LLPanel +{ +public: +	LLPanelIMControlPanel(); +	~LLPanelIMControlPanel(); + +	BOOL postBuild(); + +	void setAvatarId(const LLUUID& avatar_id); + +private: +	void onViewProfileButtonClicked(); +	void onAddFriendButtonClicked(); +	void onCallButtonClicked(); +	void onShareButtonClicked(); +}; + +#endif // LL_LLPANELIMCONTROLPANEL_H diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index 453183ad74..0cbf10f7c2 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -33,6 +33,7 @@  #include "llpanellandmarks.h" +#include "llbutton.h"  #include "llfloaterreg.h"  #include "lllandmark.h" diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h index 540f938053..83a31eecda 100644 --- a/indra/newview/llpanellogin.h +++ b/indra/newview/llpanellogin.h @@ -37,6 +37,7 @@  #include "llpointer.h"			// LLPointer<>  #include "llwebbrowserctrl.h"	// LLWebBrowserCtrlObserver +class LLLineEditor;  class LLUIImage; diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index d2879a675f..d947003109 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -35,7 +35,7 @@  // libs  #include "llfloaterreg.h"  #include "llmenugl.h" -#include "llsearcheditor.h" +#include "llfiltereditor.h"  #include "lltabcontainer.h"  #include "lluictrlfactory.h" @@ -306,7 +306,7 @@ public:  LLPanelPeople::LLPanelPeople()  	:	LLPanel(),  		mFilterSubString(LLStringUtil::null), -		mSearchEditor(NULL), +		mFilterEditor(NULL),  		mTabContainer(NULL),  		mFriendList(NULL),  		mNearbyList(NULL), @@ -330,8 +330,8 @@ LLPanelPeople::~LLPanelPeople()  BOOL LLPanelPeople::postBuild()  { -	mSearchEditor = getChild<LLSearchEditor>("filter_input"); -	mSearchEditor->setSearchCallback(boost::bind(&LLPanelPeople::onSearchEdit, this, _1)); +	mFilterEditor = getChild<LLFilterEditor>("filter_input"); +	mFilterEditor->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2));  	mTabContainer = getChild<LLTabContainer>("tabs");  	mTabContainer->setCommitCallback(boost::bind(&LLPanelPeople::onTabSelected, this, _2)); @@ -609,7 +609,7 @@ void LLPanelPeople::reSelectedCurrentTab()  	mTabContainer->selectTab(mTabContainer->getCurrentPanelIndex());  } -void LLPanelPeople::onSearchEdit(const std::string& search_string) +void LLPanelPeople::onFilterEdit(const std::string& search_string)  {  	if (mFilterSubString == search_string)  		return; @@ -618,7 +618,7 @@ void LLPanelPeople::onSearchEdit(const std::string& search_string)  	LLStringUtil::toUpper(mFilterSubString);  	LLStringUtil::trimHead(mFilterSubString); -	mSearchEditor->setText(mFilterSubString); +	mFilterEditor->setText(mFilterSubString);  	// Apply new filter to all tabs.  	filterNearbyList(); diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index 1131790106..6c3b5e0664 100644 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -37,7 +37,7 @@  #include "llcallingcard.h" // for avatar tracker -class LLSearchEditor; +class LLFilterEditor;  class LLTabContainer;  class LLAvatarList;  class LLGroupList; @@ -77,7 +77,7 @@ private:  	void					reSelectedCurrentTab();  	// UI callbacks -	void					onSearchEdit(const std::string& search_string); +	void					onFilterEdit(const std::string& search_string);  	void					onTabSelected(const LLSD& param);  	void					onViewProfileButtonClicked();  	void					onAddFriendButtonClicked(); @@ -104,7 +104,7 @@ private:  								const std::vector<LLUUID>& ids,  								void*); -	LLSearchEditor*			mSearchEditor; +	LLFilterEditor*			mFilterEditor;  	LLTabContainer*			mTabContainer;  	LLAvatarList*			mFriendList;  	LLAvatarList*			mNearbyList; diff --git a/indra/newview/llpanelpick.cpp b/indra/newview/llpanelpick.cpp index 961c54d667..cda1a9e7e7 100644 --- a/indra/newview/llpanelpick.cpp +++ b/indra/newview/llpanelpick.cpp @@ -38,6 +38,7 @@  #include "llpanel.h"  #include "message.h"  #include "llagent.h" +#include "llbutton.h"  #include "llparcel.h"  #include "llviewerparcelmgr.h"  #include "lltexturectrl.h" diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index c162a9ba33..57c633dd74 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -32,7 +32,7 @@  #include "llviewerprecompiledheaders.h"  #include "llfloaterreg.h" -#include "llsearcheditor.h" +#include "llfiltereditor.h"  #include "lltabcontainer.h"  #include "lluictrlfactory.h" @@ -67,7 +67,7 @@ LLPanelPlaces::LLPanelPlaces()  	:	LLPanel(),  		mFilterSubString(LLStringUtil::null),  		mActivePanel(NULL), -		mSearchEditor(NULL), +		mFilterEditor(NULL),  		mPlaceInfo(NULL)  {  	gInventory.addObserver(this); @@ -92,10 +92,10 @@ BOOL LLPanelPlaces::postBuild()  		mTabContainer->setCommitCallback(boost::bind(&LLPanelPlaces::onTabSelected, this));  	} -	mSearchEditor = getChild<LLSearchEditor>("Filter"); -	if (mSearchEditor) +	mFilterEditor = getChild<LLFilterEditor>("Filter"); +	if (mFilterEditor)  	{ -		mSearchEditor->setSearchCallback(boost::bind(&LLPanelPlaces::onSearchEdit, this, _1)); +		mFilterEditor->setCommitCallback(boost::bind(&LLPanelPlaces::onFilterEdit, this, _2));  	}  	mPlaceInfo = getChild<LLPanelPlaceInfo>("panel_place_info", TRUE, FALSE); @@ -187,7 +187,7 @@ void LLPanelPlaces::onOpen(const LLSD& key)  	}  } -void LLPanelPlaces::onSearchEdit(const std::string& search_string) +void LLPanelPlaces::onFilterEdit(const std::string& search_string)  {  	if (mFilterSubString != search_string)  	{ @@ -196,7 +196,7 @@ void LLPanelPlaces::onSearchEdit(const std::string& search_string)  		LLStringUtil::toUpper(mFilterSubString);  		LLStringUtil::trimHead(mFilterSubString); -		mSearchEditor->setText(mFilterSubString); +		mFilterEditor->setText(mFilterSubString);  		mActivePanel->onSearchEdit(mFilterSubString);  	} @@ -208,7 +208,7 @@ void LLPanelPlaces::onTabSelected()  	if (!mActivePanel)  		return; -	onSearchEdit(mFilterSubString);	 +	onFilterEdit(mFilterSubString);	  	mActivePanel->updateVerbs();  } @@ -274,7 +274,7 @@ void LLPanelPlaces::togglePlaceInfoPanel(BOOL visible)  		return;  	mPlaceInfo->setVisible(visible); -	mSearchEditor->setVisible(!visible); +	mFilterEditor->setVisible(!visible);  	mTabContainer->setVisible(!visible);  	// Enable overflow button only for the information about agent's current location. diff --git a/indra/newview/llpanelplaces.h b/indra/newview/llpanelplaces.h index 6fbb7562c9..e2ba4f39cd 100644 --- a/indra/newview/llpanelplaces.h +++ b/indra/newview/llpanelplaces.h @@ -42,7 +42,7 @@  #include "llpanelplaceinfo.h"  class LLPanelPlacesTab; -class LLSearchEditor; +class LLFilterEditor;  class LLTabContainer;  class LLPanelPlaces : public LLPanel, LLInventoryObserver @@ -55,7 +55,7 @@ public:  	/*virtual*/ void changed(U32 mask);  	/*virtual*/ void onOpen(const LLSD& key); -	void onSearchEdit(const std::string& search_string); +	void onFilterEdit(const std::string& search_string);  	void onTabSelected();  	//void onAddLandmarkButtonClicked();  	//void onCopySLURLButtonClicked(); @@ -68,7 +68,7 @@ public:  	void onAgentParcelChange();  private: -	LLSearchEditor*			mSearchEditor; +	LLFilterEditor*			mFilterEditor;  	LLPanelPlacesTab*		mActivePanel;  	LLTabContainer*			mTabContainer;  	LLPanelPlaceInfo*		mPlaceInfo; diff --git a/indra/newview/llpanelplacestab.cpp b/indra/newview/llpanelplacestab.cpp index dc9119d2e3..e5b1f04064 100644 --- a/indra/newview/llpanelplacestab.cpp +++ b/indra/newview/llpanelplacestab.cpp @@ -31,12 +31,14 @@  #include "llviewerprecompiledheaders.h" +#include "llpanelplacestab.h" +  #include "llwindow.h"  #include "llnotifications.h" +#include "llbutton.h"  #include "llslurl.h" -#include "llpanelplacestab.h"  #include "llworldmap.h"  void LLPanelPlacesTab::setPanelPlacesButtons(LLPanelPlaces* panel) diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp index 37262b736e..abcff7cfb1 100644 --- a/indra/newview/llsidetray.cpp +++ b/indra/newview/llsidetray.cpp @@ -118,7 +118,7 @@ LLSideTrayTab::LLSideTrayTab(const Params& params):mAccordionCtrl(0)  {  	mImagePath = params.image_path;  	mTabTitle = params.tab_title; -	mDescription = params.tab_description; +	mDescription = params.description;  }  LLSideTrayTab::~LLSideTrayTab()  { diff --git a/indra/newview/llsidetray.h b/indra/newview/llsidetray.h index 7487c71bfc..7b1f4aee04 100644 --- a/indra/newview/llsidetray.h +++ b/indra/newview/llsidetray.h @@ -51,10 +51,11 @@ public:  		// image name  		Optional<std::string>		image_path;  		Optional<std::string>		tab_title; -		Optional<std::string>		tab_description; -		Params():image_path("image","") -				,tab_title("tab_title","no title") -				,tab_description("description","no description") +		Optional<std::string>		description; +		Params() +		:	image_path("image"), +			tab_title("tab_title","no title"), +			description("description","no description")  		{};  	};  protected: @@ -109,14 +110,14 @@ public:  		Optional<S32>				default_button_height;  		Optional<S32>				default_button_margin; -		Params(): -			collapsed("collapsed",false) -			,tab_btn_image_normal("tab_btn_image","sidebar_tab_left.tga") -			,tab_btn_image_selected("tab_btn_image_selected","button_enabled_selected_32x128.tga") -			,default_button_width("tab_btn_width",32) -			,default_button_height("tab_btn_height",32) -			,default_button_margin("tab_btn_margin",0) -			{}; +		Params() +		:	collapsed("collapsed",false), +			tab_btn_image_normal("tab_btn_image","sidebar_tab_left.tga"), +			tab_btn_image_selected("tab_btn_image_selected","button_enabled_selected_32x128.tga"), +			default_button_width("tab_btn_width",32), +			default_button_height("tab_btn_height",32), +			default_button_margin("tab_btn_margin",0) +		{};  	};  	static LLSideTray*	getInstance		(); diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 211a441d64..d792b972bb 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -60,7 +60,7 @@  #include "llscrollcontainer.h"  #include "lltoolmgr.h"  #include "lltoolpipette.h" -#include "llsearcheditor.h" +#include "llfiltereditor.h"  #include "lltool.h"  #include "llviewerwindow.h" @@ -130,7 +130,7 @@ public:  	void updateFilterPermMask();  	void commitIfImmediateSet(); -	void onSearchEdit(const std::string& search_string ); +	void onFilterEdit(const std::string& search_string );  	static void		onBtnSetToDefault( void* userdata );  	static void		onBtnSelect( void* userdata ); @@ -164,7 +164,7 @@ protected:  	std::string			mPendingName;  	BOOL				mActive; -	LLSearchEditor*		mSearchEdit; +	LLFilterEditor*		mFilterEdit;  	LLInventoryPanel*	mInventoryPanel;  	PermissionMask		mImmediateFilterPermMask;  	PermissionMask		mNonImmediateFilterPermMask; @@ -191,7 +191,7 @@ LLFloaterTexturePicker::LLFloaterTexturePicker(  	mTentativeLabel(NULL),  	mResolutionLabel(NULL),  	mActive( TRUE ), -	mSearchEdit(NULL), +	mFilterEdit(NULL),  	mImmediateFilterPermMask(immediate_filter_perm_mask),  	mNonImmediateFilterPermMask(non_immediate_filter_perm_mask),  	mContextConeOpacity(0.f) @@ -335,9 +335,9 @@ BOOL LLFloaterTexturePicker::handleKeyHere(KEY key, MASK mask)  {  	LLFolderView* root_folder = mInventoryPanel->getRootFolder(); -	if (root_folder && mSearchEdit) +	if (root_folder && mFilterEdit)  	{ -		if (mSearchEdit->hasFocus()  +		if (mFilterEdit->hasFocus()   			&& (key == KEY_RETURN || key == KEY_DOWN)   			&& mask == MASK_NONE)  		{ @@ -362,7 +362,7 @@ BOOL LLFloaterTexturePicker::handleKeyHere(KEY key, MASK mask)  		if (mInventoryPanel->hasFocus() && key == KEY_UP)  		{ -			mSearchEdit->focusFirstItem(TRUE); +			mFilterEdit->focusFirstItem(TRUE);  		}  	} @@ -404,8 +404,8 @@ BOOL LLFloaterTexturePicker::postBuild()  	childSetCommitCallback("show_folders_check", onShowFolders, this);  	childSetVisible("show_folders_check", FALSE); -	mSearchEdit = getChild<LLSearchEditor>("inventory search editor"); -	mSearchEdit->setSearchCallback(boost::bind(&LLFloaterTexturePicker::onSearchEdit, this, _1)); +	mFilterEdit = getChild<LLFilterEditor>("inventory search editor"); +	mFilterEdit->setCommitCallback(boost::bind(&LLFloaterTexturePicker::onFilterEdit, this, _2));  	mInventoryPanel = getChild<LLInventoryPanel>("inventory panel"); @@ -524,7 +524,7 @@ void LLFloaterTexturePicker::draw()  	childSetValue("Pipette", LLToolMgr::getInstance()->getCurrentTool() == LLToolPipette::getInstance());  	//RN: reset search bar to reflect actual search query (all caps, for example) -	mSearchEdit->setText(mInventoryPanel->getFilterSubString()); +	mFilterEdit->setText(mInventoryPanel->getFilterSubString());  	//BOOL allow_copy = FALSE;  	if( mOwner )  @@ -797,7 +797,7 @@ void LLFloaterTexturePicker::updateFilterPermMask()  	//mInventoryPanel->setFilterPermMask( getFilterPermMask() );  Commented out due to no-copy texture loss.  } -void LLFloaterTexturePicker::onSearchEdit(const std::string& search_string ) +void LLFloaterTexturePicker::onFilterEdit(const std::string& search_string )  {  	std::string upper_case_search_string = search_string;  	LLStringUtil::toUpper(upper_case_search_string); diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h index e30cdb2e97..0b232da62b 100644 --- a/indra/newview/lltexturectrl.h +++ b/indra/newview/lltexturectrl.h @@ -84,7 +84,7 @@ public:  		Params()  		:	image_id("image"), -			default_image_id("default_image"), +			default_image_id("default_image_id"),  			default_image_name("default_image_name"),  			allow_no_texture("allow_no_texture"),  			can_apply_immediately("can_apply_immediately"), diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp index 954418f7fb..9144f9c3e0 100644 --- a/indra/newview/lltoast.cpp +++ b/indra/newview/lltoast.cpp @@ -32,9 +32,11 @@  #include "llviewerprecompiledheaders.h" // must be first include -#include "llfocusmgr.h"  #include "lltoast.h" +#include "llbutton.h" +#include "llfocusmgr.h" +  using namespace LLNotificationsUI;  //-------------------------------------------------------------------------- diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index c43618d330..a7b57802c1 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -174,7 +174,7 @@ LLToastNotifyPanel::LLToastNotifyPanel(LLNotificationPtr& notification) : LLToas  		params.max_text_length(MAX_LENGTH);  		params.default_text(mMessage);  		params.font(sFont); -		params.allow_embedded_items(false); +		params.embedded_items(false);  		params.word_wrap(true);  		params.tab_stop(false);  		params.mouse_opaque(false); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 8f1b105ba6..74ded99124 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1719,7 +1719,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  				LLSD args;  				args["SUBJECT"] = subj;  				args["MESSAGE"] = mes; -				LLNotifications::instance().add(LLNotification::Params("GroupNotice").substitutions(args).payload(payload).timestamp(timestamp)); +				LLNotifications::instance().add(LLNotification::Params("GroupNotice").substitutions(args).payload(payload).time_stamp(timestamp));  			}  			// Also send down the old path for now. diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 24479485ef..3e86f48cc5 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -107,6 +107,7 @@  #include "llfloatertools.h"  #include "llfloaterworldmap.h"  #include "llfocusmgr.h" +#include "llfontfreetype.h"  #include "llgesturemgr.h"  #include "llglheaders.h"  #include "llhoverview.h" diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 7703211c3d..dc5936a435 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -1,4 +1,5 @@  <textures version="101"> +  <!-- Please add new files alphabetically to prevent merge conflicts. JC -->    <texture name="ScrollThumb_Horiz" file_name="widgets/ScrollThumb_Horiz.png" preload="true" scale.left="4" scale.top="10" scale.bottom="53" scale.right="4" />    <texture name="ScrollThumb_Vert" file_name="widgets/ScrollThumb_Vert.png" preload="true" scale.left="4" scale.top="53" scale.bottom="10" scale.right="4" /> @@ -469,7 +470,6 @@    <texture name="Icon_Gear_Background" file_name="windows/Icon_Gear_Background.png" preload="true"/>    <texture name="Icon_Gear_Foreground" file_name="windows/Icon_Gear_Foreground.png" preload="true"/>    <texture name="Icon_Gear_Press" file_name="windows/Icon_Gear_Press.png" preload="true"/> -      <texture name="Stepper_Down_Disabled" file_name="widgets/Stepper_Down_Disabled.png" preload="true"/>    <texture name="Stepper_Down_Off" file_name="widgets/Stepper_Down_Off.png" preload="true"/>    <texture name="Stepper_Down_Press" file_name="widgets/Stepper_Down_Press.png" preload="true"/> @@ -477,4 +477,5 @@    <texture name="Stepper_Up_Off" file_name="widgets/Stepper_Up_Off.png" preload="true"/>    <texture name="Stepper_Up_Press" file_name="widgets/Stepper_Up_Press.png" preload="true"/> +  <!-- Please add new files alphabetically to prevent merge conflicts. JC -->  </textures> diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml index 1fb0942461..cb3388ccbc 100644 --- a/indra/newview/skins/default/xui/en/floater_about_land.xml +++ b/indra/newview/skins/default/xui/en/floater_about_land.xml @@ -1147,7 +1147,7 @@ Go to World menu > About Land or select another parcel to show its details.                   name="online_status"                   width="-1" />                  <name_list.columns -                 dynamicwidth="true" +                 dynamic_width="true"                   label="Name"                   name="name" />                  <name_list.columns diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 0856a787f3..44c56e4207 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -2,25 +2,66 @@  <floater
   background_visible="true"
   follows="left|top|right|bottom"
 - height="200"
 + height="250"
   layout="topleft"
   left="0"
   name="panel_im"
   top="0"
 + can_dock="true"
 + can_minimize="false"
   visible="false" 
 - width="300">
 -  <text_editor
 -   enabled="false"
 -   type="string"
 -   length="1"
 -   top="20" 
 -   follows="left|top|right"
 -   font="SansSerif"
 -   height="175"
 -   layout="topleft"
 -   left="5"
 -   name="im_text"
 -   width="290"
 -   word_wrap="true">
 -  </text_editor>
 + width="315">
 +  <layout_stack follows="left|top|right|bottom"
 +                height="235"
 +                width="315"
 +                layout="topleft"
 +                orientation="horizontal"
 +                name="im_panels"
 +                top="16"
 +                left="2">
 +    <layout_panel
 +      class="panel_im_control_panel"
 +      name="panel_im_control_panel"
 +      filename="panel_im_control_panel.xml"
 +      layout="topleft"
 +      top_delta="-3"
 +      min_width="96" 
 +      width="96"
 +      height="225"
 +      label="IM Control Panel"
 +      user_resize="false" />
 +    <layout_panel height="235"
 +                  width="200"
 +                  left_delta="96" 
 +                  top="0"
 +                  user_resize="false">
 +      <button height="12"
 +              top="8" 
 +              label="<<"
 +              layout="topleft"
 +              width="35"
 +              name="slide_left_btn" />
 +      <button height="12"
 +              top="8"
 +              label=">>"
 +              layout="topleft"
 +              width="35"
 +              name="slide_right_btn" />
 +      <text_editor
 +       enabled="false"
 +       type="string"
 +       length="1"
 +       follows="left|top|right"
 +       font="SansSerif"
 +       height="185"
 +       layout="topleft"
 +       max_length="2147483647"
 +       name="im_text"
 +       width="195"
 +       word_wrap="true">
 +      </text_editor>
 +      <line_editor name="chat_editor" height="20" layout="topleft" width="190">
 +      </line_editor>
 +    </layout_panel>
 +  </layout_stack>
  </floater>
 diff --git a/indra/newview/skins/default/xui/en/floater_inspect.xml b/indra/newview/skins/default/xui/en/floater_inspect.xml index b11b3e4df5..b43cdca0d1 100644 --- a/indra/newview/skins/default/xui/en/floater_inspect.xml +++ b/indra/newview/skins/default/xui/en/floater_inspect.xml @@ -25,15 +25,15 @@       tool_tip="Select an object from this list to highlight it in-world"       top="20">          <scroll_list.columns -         dynamicwidth="true" +         dynamic_width="true"           label="Object Name"           name="object_name" />          <scroll_list.columns -         dynamicwidth="true" +         dynamic_width="true"           label="Owner Name"           name="owner_name" />          <scroll_list.columns -         dynamicwidth="true" +         dynamic_width="true"           label="Creator Name"           name="creator_name" />          <scroll_list.columns diff --git a/indra/newview/skins/default/xui/en/floater_inventory.xml b/indra/newview/skins/default/xui/en/floater_inventory.xml index eb05fe1883..6a54c187cb 100644 --- a/indra/newview/skins/default/xui/en/floater_inventory.xml +++ b/indra/newview/skins/default/xui/en/floater_inventory.xml @@ -23,7 +23,7 @@       name="Fetched">          Fetched      </floater.string> -    <search_editor +    <filter_editor       follows="left|top|right"       height="16"       label="Type here to search" diff --git a/indra/newview/skins/default/xui/en/floater_test_widgets.xml b/indra/newview/skins/default/xui/en/floater_test_widgets.xml index c6b158fe6f..c6c561b497 100644 --- a/indra/newview/skins/default/xui/en/floater_test_widgets.xml +++ b/indra/newview/skins/default/xui/en/floater_test_widgets.xml @@ -156,9 +156,9 @@     width="200">      Line Editor Sample Text    </line_editor> -  <!-- "search_editor" is a specialized line_editor that shows read-only +  <!-- "filter_editor" is a specialized line_editor that shows read-only         help text until the user clicks in the widget. --> -  <search_editor +  <filter_editor     follows="left|top|right"     height="20"     label="Type here to search" @@ -230,11 +230,11 @@     tool_tip="scroll list"      layout="topleft">      <scroll_list.columns -     dynamicwidth="true" +     dynamic_width="true"       name="first_column"       label="Column A"/>      <scroll_list.columns -     dynamicwidth="true" +     dynamic_width="true"       name="second_column"       label="Column B"/>    </scroll_list> diff --git a/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml index 8d85519610..dc048eb352 100644 --- a/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml +++ b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml @@ -86,7 +86,7 @@       name="show_folders_check"       top="20"       width="201" /> -    <search_editor +    <filter_editor       follows="left|top|right"       height="16"       label="Type here to search" diff --git a/indra/newview/skins/default/xui/en/floater_ui_preview.xml b/indra/newview/skins/default/xui/en/floater_ui_preview.xml index 6934fad495..bbb17dfb8f 100644 --- a/indra/newview/skins/default/xui/en/floater_ui_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_ui_preview.xml @@ -163,6 +163,15 @@           tool_tip="Closes the currently-displayed floater, if one exists"           top_delta="0"           width="85" /> +        <button +         follows="left|top" +         height="25" +         label="Export Schema" +         layout="topleft" +         left_pad="10" +         name="export_schema" +         top_delta="0" +         width="120" />          <scroll_list           bottom="525"           column_padding="0" @@ -185,7 +194,7 @@               name="file_column"               width="150" />              <scroll_list.columns -             dynamicwidth="true" +             dynamic_width="true"               label="Top-Level Node"               name="top_level_node_column" />          </scroll_list> diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml index 7ac068df4b..bbef5a8892 100644 --- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml +++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml @@ -13,6 +13,7 @@   width="1000">      <layout_stack       border_size="0" +     clip="false"        follows="left|right|bottom|top"       height="28"       layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_friends.xml b/indra/newview/skins/default/xui/en/panel_friends.xml index a151eed20f..3a35465df2 100644 --- a/indra/newview/skins/default/xui/en/panel_friends.xml +++ b/indra/newview/skins/default/xui/en/panel_friends.xml @@ -29,7 +29,7 @@           tool_tip="Online status"           width="20" />          <scroll_list.columns -         dynamicwidth="true" +         dynamic_width="true"           label="Name"           name="friend_name"           tool_tip="Name" /> diff --git a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml new file mode 100644 index 0000000000..5067b4c1d8 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 +<panel name="panel_im_control_panel"
 +       width="96"
 +       height="215"
 +       border="false">
 +
 +  <avatar_icon name="avatar_icon"
 +               width="96"
 +               height="96" />
 +
 +  <button name="view_profile_btn"
 +          label="View Profile"
 +          left_delta="3"
 +          width="90"
 +		  height="20" />
 +
 +  <button name="add_friend_btn"
 +          label="Add Friend"
 +          width="90"
 +          height="20" />
 +
 +  <button name="call_btn"
 +          label="Call"
 +          width="90"
 +          height="20" />
 +
 +  <button name="share_btn"
 +          label="Share"
 +          width="90"
 +          height="20" />
 +
 +</panel>
 diff --git a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml index 9d4c411201..c9a0b6bc38 100644 --- a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml @@ -101,37 +101,21 @@  <!--      top_delta="0" -->  <!--      width="168" /> --> -    <button -     follows="right|top" -     height="16" -     image_disabled="Search" -     image_disabled_selected="Search" -     image_selected="Search" -     image_unselected="Search" -     layout="topleft" -     left_pad="5" -     name="search_btn" -     picture_style="true" -     scale_image="false" -     tool_tip="Search" -     top_delta="2" -     width="16" /> -     -    <line_editor +    <search_editor       bevel_style="none"       border_style="line"       border.border_thickness="0"       commit_on_focus_lost="false"       follows="right|top"       halign="right" -     height="18" +     height="20"       label="Search All"       layout="topleft" -     left_pad="2" +     left_pad="5"       mouse_opaque="false"       name="search_input"       tool_tip="Search All" -     top_delta="-1" +     top_delta="0"       width="135" />       <button diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index 4fc47d1c42..29f5d3aee8 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -7,9 +7,10 @@    height="465"    follows="left|top|right|bottom"      background_visible="true" +  bg_alpha_color="0.3 0.3 0.3 1"    label="People"    name="people_panel"> - <search_editor +  <filter_editor      layout="topleft"      top="3"      left="15" diff --git a/indra/newview/skins/default/xui/en/panel_places.xml b/indra/newview/skins/default/xui/en/panel_places.xml index 61b0ac9b72..c91cb2394c 100644 --- a/indra/newview/skins/default/xui/en/panel_places.xml +++ b/indra/newview/skins/default/xui/en/panel_places.xml @@ -19,7 +19,7 @@       name="teleport_history_tab_title">          Teleport History      </panel.string> -    <search_editor +    <filter_editor       follows="left|top|right"       height="20"       label="Filter" diff --git a/indra/newview/skins/default/xui/en/panel_teleport_history.xml b/indra/newview/skins/default/xui/en/panel_teleport_history.xml index 330bc362d2..05ebcbb50b 100644 --- a/indra/newview/skins/default/xui/en/panel_teleport_history.xml +++ b/indra/newview/skins/default/xui/en/panel_teleport_history.xml @@ -6,7 +6,7 @@  	     multi_select="false" name="history_items" search_column="1"  	     sort_column="1" height="326" width="380" >  		<column name="landmark_icon" width="20" /> -		<column dynamicwidth="true" label="Region" name="region" /> +		<column dynamic_width="true" label="Region" name="region" />  		<column name="index" width="0" />  	</scroll_list>  </panel> diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index c6ee2ce364..149da313a2 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -82,6 +82,8 @@  	<string name="BUTTON_MINIMIZE">Minimize</string>  	<string name="BUTTON_TEAR_OFF">Tear Off</string>  	<string name="BUTTON_EDIT">Edit</string> +  <string name="BUTTON_DOCK">Dock</string> +  <string name="BUTTON_UNDOCK">Undock</string>  	<!-- searching - generic -->  	<string name="Searching">Searching...</string> diff --git a/indra/newview/skins/default/xui/en/widgets/filter_editor.xml b/indra/newview/skins/default/xui/en/widgets/filter_editor.xml new file mode 100644 index 0000000000..f77aa396ec --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/filter_editor.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 +<filter_editor select_on_focus="true"
 +               background="TextField_Search_Off" >
 +  <clear_filter_button label="" 
 +                       image_unselected="Icon_Close_Foreground"
 +                       image_selected="Icon_Close_Press" />
 +</filter_editor>
 diff --git a/indra/newview/skins/default/xui/en/widgets/line_editor.xml b/indra/newview/skins/default/xui/en/widgets/line_editor.xml index 168609d5d7..08205cacbc 100644 --- a/indra/newview/skins/default/xui/en/widgets/line_editor.xml +++ b/indra/newview/skins/default/xui/en/widgets/line_editor.xml @@ -1,5 +1,8 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<line_editor background_image="TextField_Off" +<line_editor +  background_image="TextField_Off" +  background_image_disabled="TextField_Disabled" +  background_image_focused="TextField_Active"               select_on_focus="false"               handle_edit_keys_directly="false"               commit_on_focus_lost="true" @@ -8,9 +11,8 @@               text_color="TextFgColor"               text_readonly_color="Green"               text_tentative_color="TextFgTentativeColor" -             bg_readonly_color="TextBgReadOnlyColor" -             bg_writeable_color="TextBgWriteableColor" -             bg_focus_color="TextBgFocusColor" +			 highlight_color="EmphasisColor" +			 preedit_bg_color="White"               mouse_opaque="true"               name="line_editor"               font="SansSerifSmall"> diff --git a/indra/newview/skins/default/xui/en/widgets/scroll_list.xml b/indra/newview/skins/default/xui/en/widgets/scroll_list.xml index 9e2c52acca..e3a53eee4d 100644 --- a/indra/newview/skins/default/xui/en/widgets/scroll_list.xml +++ b/indra/newview/skins/default/xui/en/widgets/scroll_list.xml @@ -4,7 +4,7 @@               bg_selected_color="ScrollSelectedBGColor"               fg_disable_color="ScrollDisabledColor"               bg_writeable_color="ScrollBgWriteableColor" -             bg_read_only_color="ScrollBgReadOnlyColor" +             bg_readonly_color="ScrollBgReadOnlyColor"               bg_stripe_color="ScrollBGStripeColor"               hovered_color="ScrollHoveredColor"               highlighted_color="ScrollHighlightedColor" diff --git a/indra/newview/skins/default/xui/en/widgets/search_editor.xml b/indra/newview/skins/default/xui/en/widgets/search_editor.xml index 67588d76ca..6f557e239d 100644 --- a/indra/newview/skins/default/xui/en/widgets/search_editor.xml +++ b/indra/newview/skins/default/xui/en/widgets/search_editor.xml @@ -1,7 +1,10 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<search_editor select_on_focus="true"> -  <clear_search_button image_unselected="TextField_Search_Off" -                       image_selected="TextField_Search_Active" -                       image_disabled="TextField_Search_Disabled" -                       image_color="TextFgTentativeColor"/> +<search_editor +  select_on_focus="true" +  background_image="TextField_Search_Off" +  background_image_disabled="TextField_Search_Disabled" +  background_image_focused="TextField_Search_Active" > +  <search_button label="" +	  image_unselected="Search" +	  image_selected="Search" />  </search_editor> diff --git a/indra/newview/skins/default/xui/en/widgets/simple_text_editor.xml b/indra/newview/skins/default/xui/en/widgets/simple_text_editor.xml index b39c2991a0..960c4e81e5 100644 --- a/indra/newview/skins/default/xui/en/widgets/simple_text_editor.xml +++ b/indra/newview/skins/default/xui/en/widgets/simple_text_editor.xml @@ -1,11 +1,23 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<simple_text_editor cursor_color="TextCursorColor" -                    default_color="TextDefaultColor" -                    text_color="TextFgColor" -                    text_readonly_color="TextFgReadOnlyColor" -                    bg_readonly_color="TextBgReadOnlyColor" -                    bg_writeable_color="TextBgWriteableColor" -                    bg_focus_color="TextBgFocusColor" -                    hide_border="true" -                    hide_scrollbar="false" -                    font="SansSerif"/> +<simple_text_editor +  mouse_opaque="true" +  font="SansSerifSmall" +  max_length="255"  +  embedded_items="false"  +  hide_scrollbar="false" +  hide_border="true" +  word_wrap="false"  +  ignore_tab="true" +  track_bottom="false"  +  takes_non_scroll_clicks="true"  +  cursor_color="TextCursorColor" +  default_color="TextDefaultColor" +  text_color="TextFgColor" +  text_readonly_color="TextFgReadOnlyColor" +  bg_readonly_color="TextBgReadOnlyColor" +  bg_writeable_color="TextBgWriteableColor" +  bg_focus_color="TextBgFocusColor"> +  <simple_text_editor.border +    bevel_style="in" +    follows="all" /> +</simple_text_editor> diff --git a/indra/newview/skins/default/xui/en/widgets/text_editor.xml b/indra/newview/skins/default/xui/en/widgets/text_editor.xml index a613c43f90..deaade04f8 100644 --- a/indra/newview/skins/default/xui/en/widgets/text_editor.xml +++ b/indra/newview/skins/default/xui/en/widgets/text_editor.xml @@ -1,19 +1,4 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<line_editor background_image="TextField_Off" -             select_on_focus="false" -             handle_edit_keys_directly="false" -             commit_on_focus_lost="true" -             ignore_tab="true" -             cursor_color="TextCursorColor" -             text_color="TextFgColor" -             text_readonly_color="TextFgReadOnlyColor" -             text_tentative_color="TextFgTentativeColor" -             bg_readonly_color="TextBgReadOnlyColor" -             bg_writeable_color="TextBgWriteableColor" -             bg_focus_color="TextBgFocusColor" -             mouse_opaque="true" -             name="line_editor" -             font="SansSerifSmall"> -  <line_editor.border bevel_style="in" -                      follows="all" /> -</line_editor> +<!-- Core parameters are in simple_text_editor.xml --> +<text_editor +  allow_html="false" /> | 
