Esempio n. 1
0
void LLPanelRequestTools::refresh()
{
	std::string buffer = childGetValue("destination");
	LLCtrlListInterface *list = childGetListInterface("destination");
	if (!list) return;

	list->operateOnAll(LLCtrlListInterface::OP_DELETE);
	list->addSimpleElement(SELECTION);
	list->addSimpleElement(AGENT_REGION);
	for (LLWorld::region_list_t::iterator iter = gWorldp->mActiveRegionList.begin();
		 iter != gWorldp->mActiveRegionList.end(); ++iter)
	{
		LLViewerRegion* regionp = *iter;
		LLString name = regionp->getName();
//MK
		if (RRenabled && gAgent.mRRInterface.mContainsShowloc)
		{
			name = "(Hidden)";
		}
//mk
		if (!name.empty())
		{
			list->addSimpleElement(name);
		}
	}
	if(!buffer.empty())
	{
		list->selectByValue(buffer);
	}
	else
	{
		list->selectByValue(SELECTION);
	}
}
Esempio n. 2
0
LLSpeaker::LLSpeaker(const LLUUID& id, const LLString& name, const ESpeakerType type) : 
	mStatus(LLSpeaker::STATUS_TEXT_ONLY),
	mLastSpokeTime(0.f), 
	mSpeechVolume(0.f), 
	mHasSpoken(FALSE),
	mDotColor(LLColor4::white),
	mID(id),
	mTyping(FALSE),
	mSortIndex(0),
	mType(type),
	mIsModerator(FALSE),
	mModeratorMutedVoice(FALSE),
	mModeratorMutedText(FALSE)
{
	mHandle.init();
	sSpeakers.insert(std::make_pair(mHandle, this));
	if (name.empty() && type == SPEAKER_AGENT)
	{
		lookupName();
	}
	else
	{
		mDisplayName = name;
	}

	gVoiceClient->setUserVolume(id, gMuteListp->getSavedResidentVolume(id));

	mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
}
Esempio n. 3
0
LLView* LLSpinCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
{
	LLString name("spinner");
	node->getAttributeString("name", name);

	LLString label;
	node->getAttributeString("label", label);

	LLRect rect;
	createRect(node, rect, parent, LLRect());

	LLFontGL* font = LLView::selectFont(node);

	F32 initial_value = 0.f;
	node->getAttributeF32("initial_val", initial_value);

	F32 min_value = 0.f;
	node->getAttributeF32("min_val", min_value);

	F32 max_value = 1.f; 
	node->getAttributeF32("max_val", max_value);

	F32 increment = 0.1f;
	node->getAttributeF32("increment", increment);

	U32 precision = 3;
	node->getAttributeU32("decimal_digits", precision);
	
	S32 label_width = llmin(40, rect.getWidth() - 40);
	node->getAttributeS32("label_width", label_width);

	LLUICtrlCallback callback = NULL;

	if(label.empty())
	{
		label.assign( node->getValue() );
	}

	LLSpinCtrl* spinner = new LLSpinCtrl(name,
							rect,
							label,
							font,
							callback,
							NULL,
							initial_value, 
							min_value, 
							max_value, 
							increment,
							"",
							label_width);

	spinner->setPrecision(precision);

	spinner->initFromXML(node, parent);

	return spinner;
}
Esempio n. 4
0
void LLButton::setImageOverlay(const LLString &image_name, LLFontGL::HAlign alignment, const LLColor4& color)
{
	if (image_name.empty())
	{
		mImageOverlay = NULL;
	}
	else
	{
		mImageOverlay = LLUI::getUIImageByName(image_name);
		mImageOverlayAlignment = alignment;
		mImageOverlayColor = color;
	}
}
Esempio n. 5
0
void LLButton::addImageAttributeToXML(LLXMLNodePtr node, 
									  const LLString& image_name,
									  const LLUUID&	image_id,
									  const LLString& xml_tag_name) const
{
	if( !image_name.empty() )
	{
		node->createChild(xml_tag_name, TRUE)->setStringValue(image_name);
	}
	else if( image_id != LLUUID::null )
	{
		node->createChild(xml_tag_name + "_id", TRUE)->setUUIDValue(image_id);
	}
}
Esempio n. 6
0
void LLControlGroup::setValue(const LLString& name, const LLSD& val)
{
	if (name.empty())
	{
		return;
	}

	LLControlBase* control = getControl(name);
	
	if (control)
	{
		control->set(val);
	}
	else
	{
		CONTROL_ERRS << "Invalid control " << name << llendl;
	}
}
Esempio n. 7
0
// virtual
BOOL LLPreviewGesture::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
										 EDragAndDropType cargo_type,
										 void* cargo_data,
										 EAcceptance* accept,
										 LLString& tooltip_msg)
{
	BOOL handled = TRUE;
	switch(cargo_type)
	{
	case DAD_ANIMATION:
	case DAD_SOUND:
		{
			// TODO: Don't allow this if you can't transfer the sound/animation

			// make a script step
			LLInventoryItem* item = (LLInventoryItem*)cargo_data;
			if (item
				&& gInventory.getItem(item->getUUID()))
			{
				LLPermissions perm = item->getPermissions();
				if (!((perm.getMaskBase() & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED))
				{
					*accept = ACCEPT_NO;
					if (tooltip_msg.empty())
					{
						tooltip_msg.assign("Only animations and sounds\n"
											"with unrestricted permissions\n"
											"can be added to a gesture.");
					}
					break;
				}
				else if (drop)
				{
					LLScrollListItem* line = NULL;
					if (cargo_type == DAD_ANIMATION)
					{
						line = addStep("Animation");
						LLGestureStepAnimation* anim = (LLGestureStepAnimation*)line->getUserdata();
						anim->mAnimAssetID = item->getAssetUUID();
						anim->mAnimName = item->getName();
					}
					else if (cargo_type == DAD_SOUND)
					{
						line = addStep("Sound");
						LLGestureStepSound* sound = (LLGestureStepSound*)line->getUserdata();
						sound->mSoundAssetID = item->getAssetUUID();
						sound->mSoundName = item->getName();
					}
					updateLabel(line);
					mDirty = TRUE;
					refresh();
				}
				*accept = ACCEPT_YES_COPY_MULTI;
			}
			else
			{
				// Not in user's inventory means it was in object inventory
				*accept = ACCEPT_NO;
			}
			break;
		}
	default:
		*accept = ACCEPT_NO;
		if (tooltip_msg.empty())
		{
			tooltip_msg.assign("Only animations and sounds\n"
								"can be added to a gesture.");
		}
		break;
	}
	return handled;
}
Esempio n. 8
0
// Returns number of controls loaded, so 0 if failure
U32 LLControlGroup::loadFromFile(const LLString& filename, BOOL require_declaration, eControlType declare_as)
{
	LLString name;

	LLXmlTree xml_controls;

	if (!xml_controls.parseFile(filename))
	{
		llwarns << "Unable to open control file " << filename << llendl;
		return 0;
	}

	LLXmlTreeNode* rootp = xml_controls.getRoot();
	if (!rootp || !rootp->hasAttribute("version"))
	{
		llwarns << "No valid settings header found in control file " << filename << llendl;
		return 0;
	}

	U32		item = 0;
	U32		validitems = 0;
	S32 version;
	
	rootp->getAttributeS32("version", version);

	// Check file version
	if (version != CURRENT_VERSION)
	{
		llinfos << filename << " does not appear to be a version " << CURRENT_VERSION << " controls file" << llendl;
		return 0;
	}

	LLXmlTreeNode* child_nodep = rootp->getFirstChild();
	while(child_nodep)
	{
		name = child_nodep->getName();		
		
		BOOL declared = controlExists(name);

		if (require_declaration && !declared)
		{
			// Declaration required, but this name not declared.
			// Complain about non-empty names.
			if (!name.empty())
			{
				//read in to end of line
				llwarns << "LLControlGroup::loadFromFile() : Trying to set \"" << name << "\", setting doesn't exist." << llendl;
			}
			child_nodep = rootp->getNextChild();
			continue;
		}

		// Got an item.  Load it up.
		item++;

		// If not declared, assume it's a string
		if (!declared)
		{
			switch(declare_as)
			{
			case TYPE_COL4:
				declareColor4(name, LLColor4::white, "", NO_PERSIST);
				break;
			case TYPE_COL4U:
				declareColor4U(name, LLColor4U::white, "", NO_PERSIST);
				break;
			case TYPE_STRING:
			default:
				declareString(name, LLString::null, "", NO_PERSIST);
				break;
			}
		}

		// Control name has been declared in code.
		LLControlBase *control = getControl(name);

		llassert(control);

		mLoadedSettings.insert(name);
		
		switch(control->mType)
		{
		case TYPE_F32:
			{
				F32 initial = 0.f;

				child_nodep->getAttributeF32("value", initial);

				control->set(initial);
				validitems++;
			}
			break;
		case TYPE_S32:
			{
				S32 initial = 0;

				child_nodep->getAttributeS32("value", initial);

				control->set(initial);
				validitems++;
			}
			break;
		case TYPE_U32:
			{
				U32 initial = 0;
				child_nodep->getAttributeU32("value", initial);
				control->set((LLSD::Integer) initial);
				validitems++;
			}
			break;
		case TYPE_BOOLEAN:
			{
				BOOL initial = FALSE;

				child_nodep->getAttributeBOOL("value", initial);
				control->set(initial);

				validitems++;
			}
			break;
		case TYPE_STRING:
			{
				LLString string;
				child_nodep->getAttributeString("value", string);
				if (string == LLString::null)
				{
					string = "";
				}
				control->set(string);
				validitems++;
			}
			break;
		case TYPE_VEC3:
			{
				LLVector3 vector;

				child_nodep->getAttributeVector3("value", vector);
				control->set(vector.getValue());
				validitems++;
			}
			break;
		case TYPE_VEC3D:
			{
				LLVector3d vector;

				child_nodep->getAttributeVector3d("value", vector);

				control->set(vector.getValue());
				validitems++;
			}
			break;
		case TYPE_RECT:
			{
				//RN: hack to support reading rectangles from a string
				LLString rect_string;

				child_nodep->getAttributeString("value", rect_string);
				std::istringstream istream(rect_string);
				S32 left, bottom, width, height;

				istream >> left >> bottom >> width >> height;

				LLRect rect;
				rect.setOriginAndSize(left, bottom, width, height);

				control->set(rect.getValue());
				validitems++;
			}
			break;
		case TYPE_COL4U:
			{
				LLColor4U color;

				child_nodep->getAttributeColor4U("value", color);
				control->set(color.getValue());
				validitems++;
			}
			break;
		case TYPE_COL4:
			{
				LLColor4 color;
				
				child_nodep->getAttributeColor4("value", color);
				control->set(color.getValue());
				validitems++;
			}
			break;
		case TYPE_COL3:
			{
				LLVector3 color;
				
				child_nodep->getAttributeVector3("value", color);
                control->set(LLColor3(color.mV).getValue());
				validitems++;
			}
			break;
		}

		child_nodep = rootp->getNextChild();
	}

	return validitems;
}
Esempio n. 9
0
U32 LLControlGroup::loadFromFileLegacy(const LLString& filename, BOOL require_declaration, eControlType declare_as)
{
	U32		item = 0;
	U32		validitems = 0;
	llifstream file;
	S32 version;
	
	file.open(filename.c_str());		/*Flawfinder: ignore*/ 

	if (!file)
	{
		llinfos << "LLControlGroup::loadFromFile unable to open." << llendl;
		return 0;
	}

	// Check file version
	LLString name;
	file >> name;
	file >> version;
	if (name != "version" || version != CURRENT_VERSION)
	{
		llinfos << filename << " does not appear to be a version " << CURRENT_VERSION << " controls file" << llendl;
		return 0;
	}

	while (!file.eof())
	{
		file >> name;
		
		if (name.empty())
		{
			continue;
		}

		if (name.substr(0,2) == "//")
		{
			// This is a comment.
			char buffer[MAX_STRING];		/*Flawfinder: ignore*/
			file.getline(buffer, MAX_STRING);
			continue;
		}

		BOOL declared = mNameTable.find(name) != mNameTable.end();

		if (require_declaration && !declared)
		{
			// Declaration required, but this name not declared.
			// Complain about non-empty names.
			if (!name.empty())
			{
				//read in to end of line
				char buffer[MAX_STRING];		/*Flawfinder: ignore*/
				file.getline(buffer, MAX_STRING);
				llwarns << "LLControlGroup::loadFromFile() : Trying to set \"" << name << "\", setting doesn't exist." << llendl;
			}
			continue;
		}

		// Got an item.  Load it up.
		item++;

		// If not declared, assume it's a string
		if (!declared)
		{
			switch(declare_as)
			{
			case TYPE_COL4:
				declareColor4(name, LLColor4::white, LLString::null, NO_PERSIST);
				break;
			case TYPE_COL4U:
				declareColor4U(name, LLColor4U::white, LLString::null, NO_PERSIST);
				break;
			case TYPE_STRING:
			default:
				declareString(name, LLString::null, LLString::null, NO_PERSIST);
				break;
			}
		}

		// Control name has been declared in code.
		LLControlBase *control = getControl(name);

		llassert(control);

		mLoadedSettings.insert(name);
		
		switch(control->mType)
		{
		case TYPE_F32:
			{
				F32 initial;

				file >> initial;

				control->set(initial);
				validitems++;
			}
			break;
		case TYPE_S32:
			{
				S32 initial;

				file >> initial;

				control->set(initial);
				validitems++;
			}
			break;
		case TYPE_U32:
			{
				U32 initial;

				file >> initial;
				control->set((LLSD::Integer) initial);
				validitems++;
			}
			break;
		case TYPE_BOOLEAN:
			{
				char boolstring[256];		/*Flawfinder: ignore*/
				BOOL valid = FALSE;
				BOOL initial = FALSE;

				file >> boolstring;
				if (!strcmp("TRUE", boolstring))
				{
					initial = TRUE;
					valid = TRUE;
				}
				else if (!strcmp("FALSE", boolstring))
				{
					initial = FALSE;
					valid = TRUE;
				}

				if (valid)
				{
					control->set(initial);
				}
				else
				{
					llinfos << filename << "Item " << item << ": Invalid BOOL control " << name << ", " << boolstring << llendl; 
				}

				validitems++;
			}
			break;
		case TYPE_STRING:
			{
				LLString string;
				
				file >> string;
				
				control->set(string);
				validitems++;
			}
			break;
		case TYPE_VEC3:
			{
				F32 x, y, z;

				file >> x >> y >> z;

				LLVector3 vector(x, y, z);

				control->set(vector.getValue());
				validitems++;
			}
			break;
		case TYPE_VEC3D:
			{
				F64 x, y, z;

				file >> x >> y >> z;

				LLVector3d vector(x, y, z);

				control->set(vector.getValue());
				validitems++;
			}
			break;
		case TYPE_RECT:
			{
				S32 left, bottom, width, height;

				file >> left >> bottom >> width >> height;

				LLRect rect;
				rect.setOriginAndSize(left, bottom, width, height);

				control->set(rect.getValue());
				validitems++;
			}
			break;
		case TYPE_COL4U:
			{
				S32 red, green, blue, alpha;
				LLColor4U color;
				file >> red >> green >> blue >> alpha;
				color.setVec(red, green, blue, alpha);
				control->set(color.getValue());
				validitems++;
			}
			break;
		case TYPE_COL4:
			{
				LLColor4 color;
				file >> color.mV[VRED] >> color.mV[VGREEN]
					 >> color.mV[VBLUE] >> color.mV[VALPHA];
				control->set(color.getValue());
				validitems++;
			}
			break;
		case TYPE_COL3:
			{
				LLColor3 color;
				file >> color.mV[VRED] >> color.mV[VGREEN]
					 >> color.mV[VBLUE];
				control->set(color.getValue());
				validitems++;
			}
			break;
		}
	}

	file.close();

	return validitems;
}
Esempio n. 10
0
U32 LLControlGroup::saveToFile(const LLString& filename, BOOL nondefault_only)
{
	const char ENDL = '\n';

	llinfos << "Saving settings to file: " << filename << llendl;

	// place the objects in a temporary container that enforces a sort
	// order to ease manual editing of the file
	LLLinkedList< LLControlBase > controls;
	controls.setInsertBefore( &control_insert_before );
	LLString name;
	for (ctrl_name_table_t::iterator iter = mNameTable.begin();
		 iter != mNameTable.end(); iter++)
	{
		name = iter->first;
		if (name.empty())
		{
			CONTROL_ERRS << "Control with no name found!!!" << llendl;
			break;
		}

		LLControlBase* control = (LLControlBase *)iter->second;
		if (!control)
		{
			llwarns << "Tried to save invalid control: " << name << llendl;
		}

		if( control && control->mPersist )
		{
			if (!(nondefault_only && (control->mIsDefault)))
			{
				controls.addDataSorted( control );
			}
			else
			{
				// Debug spam
				// llinfos << "Skipping " << control->getName() << llendl;
			}
		}
	}

	llofstream file;
	file.open(filename.c_str());		/*Flawfinder: ignore*/

	if (!file.is_open())
	{
		// This is a warning because sometime we want to use settings files which can't be written...
		llwarns << "LLControlGroup::saveToFile unable to open file for writing" << llendl;
		return 0;
	}

	// Write file version
	file << "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>\n";
	file << "<settings version = \"" << CURRENT_VERSION << "\">\n";
    for( LLControlBase* control = controls.getFirstData();
		 control != NULL;
		 control = controls.getNextData() )
	{
		file << "\t<!--" << control->comment() << "-->" << ENDL;
		name = control->name();
		switch (control->type())
		{
			case TYPE_U32:
			{
				file << "\t<" << name << " value=\"" << (U32) control->get().asInteger() << "\"/>\n";
				break;
			}
			case TYPE_S32:
			{
				file << "\t<" << name << " value=\"" << (S32) control->get().asInteger() << "\"/>\n";
				break;
			}
			case TYPE_F32:
			{
				file << "\t<" << name << " value=\"" << (F32) control->get().asReal() << "\"/>\n";
				break;
			}
			case TYPE_VEC3:
			{
				LLVector3 vector(control->get());
				file << "\t<" << name << " value=\"" << vector.mV[VX] << " " << vector.mV[VY] << " " << vector.mV[VZ] << "\"/>\n";
				break;
			}
			case TYPE_VEC3D:
			{
				LLVector3d vector(control->get());
				file << "\t<" << name << " value=\"" << vector.mdV[VX] << " " << vector.mdV[VY] << " " << vector.mdV[VZ] << "\"/>\n";
				break;
			}
			case TYPE_RECT:
			{
				LLRect rect(control->get());
				file << "\t<" << name << " value=\"" << rect.mLeft << " " << rect.mBottom << " " << rect.getWidth() << " " << rect.getHeight() << "\"/>\n";
				break;
			}
			case TYPE_COL4:
			{
				LLColor4 color(control->get());
				file << "\t<" << name << " value=\"" << color.mV[VRED] << ", " << color.mV[VGREEN] << ", " << color.mV[VBLUE] << ", " << color.mV[VALPHA] << "\"/>\n";
				break;
			}
			case TYPE_COL3:
			{
				LLColor3 color(control->get());
				file << "\t<" << name << " value=\"" << color.mV[VRED] << ", " << color.mV[VGREEN] << ", " << color.mV[VBLUE] << "\"/>\n";
				break;
			}
			case TYPE_BOOLEAN:
			{
				file << "\t<" << name << " value=\"" << (control->get().asBoolean() ? "TRUE" : "FALSE") << "\"/>\n";			
				break;
			}
			case TYPE_STRING:
			{
				file << "\t<" << name << " value=\"" << LLSDXMLFormatter::escapeString(control->get().asString()) << "\"/>\n";
				break;
			}
			default:
			{
				CONTROL_ERRS << "LLControlGroup::saveToFile - unknown control type!" << llendl;
				break;
			}
		}

		// Debug spam
		// llinfos << name << " " << control->getValue().asString() << llendl;
	}// next

	file << "</settings>\n";
	file.close();

	return controls.getLength();
}
Esempio n. 11
0
void			LLButton::setImageDisabledSelected(const LLString &image_name)
{
	setImageDisabledSelected(image_name.empty() ? NULL : LLUI::getUIImageByName(image_name));
	mImageDisabledSelectedName = image_name;
}
Esempio n. 12
0
// static
LLView* LLButton::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
{
	LLString name("button");
	node->getAttributeString("name", name);

	LLString label = name;
	node->getAttributeString("label", label);

	LLString label_selected = label;
	node->getAttributeString("label_selected", label_selected);

	LLFontGL* font = selectFont(node);

	LLString	image_unselected;
	if (node->hasAttribute("image_unselected")) node->getAttributeString("image_unselected",image_unselected);
	
	LLString	image_selected;
	if (node->hasAttribute("image_selected")) node->getAttributeString("image_selected",image_selected);
	
	LLString	image_hover_selected;
	if (node->hasAttribute("image_hover_selected")) node->getAttributeString("image_hover_selected",image_hover_selected);
	
	LLString	image_hover_unselected;
	if (node->hasAttribute("image_hover_unselected")) node->getAttributeString("image_hover_unselected",image_hover_unselected);
	
	LLString	image_disabled_selected;
	if (node->hasAttribute("image_disabled_selected")) node->getAttributeString("image_disabled_selected",image_disabled_selected);
	
	LLString	image_disabled;
	if (node->hasAttribute("image_disabled")) node->getAttributeString("image_disabled",image_disabled);

	LLString	image_overlay;
	node->getAttributeString("image_overlay", image_overlay);

	LLFontGL::HAlign image_overlay_alignment = LLFontGL::HCENTER;
	LLString image_overlay_alignment_string;
	if (node->hasAttribute("image_overlay_alignment"))
	{
		node->getAttributeString("image_overlay_alignment", image_overlay_alignment_string);
		image_overlay_alignment = LLFontGL::hAlignFromName(image_overlay_alignment_string);
	}


	LLButton *button = new LLButton(name, 
			LLRect(),
			image_unselected,
			image_selected,
			"", 
			NULL, 
			parent,
			font,
			label,
			label_selected);

	node->getAttributeS32("pad_right", button->mRightHPad);
	node->getAttributeS32("pad_left", button->mLeftHPad);

	BOOL is_toggle = button->getIsToggle();
	node->getAttributeBOOL("toggle", is_toggle);
	button->setIsToggle(is_toggle);

	if(image_hover_selected != LLString::null) button->setImageHoverSelected(image_hover_selected);
	
	if(image_hover_unselected != LLString::null) button->setImageHoverUnselected(image_hover_unselected);
	
	if(image_disabled_selected != LLString::null) button->setImageDisabledSelected(image_disabled_selected );
	
	if(image_disabled != LLString::null) button->setImageDisabled(image_disabled);
	
	if(image_overlay != LLString::null) button->setImageOverlay(image_overlay, image_overlay_alignment);

	if (node->hasAttribute("halign"))
	{
		LLFontGL::HAlign halign = selectFontHAlign(node);
		button->setHAlign(halign);
	}

	if (node->hasAttribute("scale_image"))
	{
		BOOL	needsScale = FALSE;
		node->getAttributeBOOL("scale_image",needsScale);
		button->setScaleImage( needsScale );
	}

	if(label.empty())
	{
		button->setLabelUnselected(node->getTextContents());
	}
	if (label_selected.empty())
	{
		button->setLabelSelected(node->getTextContents());
	}
		
	if (node->hasAttribute("help_url")) 
	{
		LLString	help_url;
		node->getAttributeString("help_url",help_url);
		button->setHelpURLCallback(help_url);
	}

	button->initFromXML(node, parent);
	
	return button;
}
Esempio n. 13
0
void upload_new_resource(const LLString& src_filename, std::string name,
						 std::string desc, S32 compression_info,
						 LLAssetType::EType destination_folder_type,
						 LLInventoryType::EType inv_type,
						 U32 next_owner_perm,
						 const LLString& display_name,
						 LLAssetStorage::LLStoreAssetCallback callback,
						 void *userdata)
{	
	// Generate the temporary UUID.
	LLString filename = gDirUtilp->getTempFilename();
	LLTransactionID tid;
	LLAssetID uuid;
	
	LLStringBase<char>::format_map_t args;

	LLString ext = src_filename.substr(src_filename.find_last_of('.'));
	LLAssetType::EType asset_type = LLAssetType::AT_NONE;
	char error_message[MAX_STRING];		/* Flawfinder: ignore */	
	error_message[0] = '\0';
	LLString temp_str;

	BOOL error = FALSE;
	
	if (ext.empty())
	{
		LLString::size_type offset = filename.find_last_of(gDirUtilp->getDirDelimiter());
		if (offset != LLString::npos)
			offset++;
		LLString short_name = filename.substr(offset);
		
		// No extension
		snprintf(error_message,		/* Flawfinder: ignore */
				MAX_STRING,
				"No file extension for the file: '%s'\nPlease make sure the file has a correct file extension",
				short_name.c_str());
		args["[FILE]"] = short_name;
 		upload_error(error_message, "NofileExtension", filename, args);
		return;
	}
	else if( LLString::compareInsensitive(ext.c_str(),".bmp") == 0 )
	{
		asset_type = LLAssetType::AT_TEXTURE;
		if (!LLViewerImageList::createUploadFile(src_filename,
												 filename,
												 IMG_CODEC_BMP ))
		{
			snprintf(error_message, MAX_STRING, "Problem with file %s:\n\n%s\n",		/* Flawfinder: ignore */
					src_filename.c_str(), LLImageBase::getLastError().c_str());
			args["[FILE]"] = src_filename;
			args["[ERROR]"] = LLImageBase::getLastError();
			upload_error(error_message, "ProblemWithFile", filename, args);
			return;
		}
	}
	else if( LLString::compareInsensitive(ext.c_str(),".tga") == 0 )
	{
		asset_type = LLAssetType::AT_TEXTURE;
		if (!LLViewerImageList::createUploadFile(src_filename,
												 filename,
												 IMG_CODEC_TGA ))
		{
			snprintf(error_message, MAX_STRING, "Problem with file %s:\n\n%s\n",		/* Flawfinder: ignore */
					src_filename.c_str(), LLImageBase::getLastError().c_str());
			args["[FILE]"] = src_filename;
			args["[ERROR]"] = LLImageBase::getLastError();
			upload_error(error_message, "ProblemWithFile", filename, args);
			return;
		}
	}
	else if( LLString::compareInsensitive(ext.c_str(),".jpg") == 0 || LLString::compareInsensitive(ext.c_str(),".jpeg") == 0)
	{
		asset_type = LLAssetType::AT_TEXTURE;
		if (!LLViewerImageList::createUploadFile(src_filename,
												 filename,
												 IMG_CODEC_JPEG ))
		{
			snprintf(error_message, MAX_STRING, "Problem with file %s:\n\n%s\n",		/* Flawfinder: ignore */
					src_filename.c_str(), LLImageBase::getLastError().c_str());
			args["[FILE]"] = src_filename;
			args["[ERROR]"] = LLImageBase::getLastError();
			upload_error(error_message, "ProblemWithFile", filename, args);
			return;
		}
	}
	else if(LLString::compareInsensitive(ext.c_str(),".wav") == 0)
	{
		asset_type = LLAssetType::AT_SOUND;  // tag it as audio
		S32 encode_result = 0;

		S32 bitrate = 128;

		if (compression_info)
		{
			bitrate = compression_info;
		}
		llinfos << "Attempting to encode wav as an ogg file at " << bitrate << "kbps" << llendl;

		encode_result = encode_vorbis_file_at(src_filename.c_str(), filename.c_str(), bitrate*1000);
		
		if (LLVORBISENC_NOERR != encode_result)
		{
			switch(encode_result)
			{
				case LLVORBISENC_DEST_OPEN_ERR:
                    snprintf(error_message, MAX_STRING, "Couldn't open temporary compressed sound file for writing: %s\n", filename.c_str());		/* Flawfinder: ignore */
					args["[FILE]"] = filename;
					upload_error(error_message, "CannotOpenTemporarySoundFile", filename, args);
					break;

				default:	
				  snprintf(error_message, MAX_STRING, "Unknown vorbis encode failure on: %s\n", src_filename.c_str());		/* Flawfinder: ignore */
					args["[FILE]"] = src_filename;
					upload_error(error_message, "UnknownVorbisEncodeFailure", filename, args);
					break;	
			}	
			return;
		}
	}
	else if(LLString::compareInsensitive(ext.c_str(),".tmp") == 0)	 	
	{	 	
		// This is a generic .lin resource file	 	
         asset_type = LLAssetType::AT_OBJECT;	 	
         FILE* in = LLFile::fopen(src_filename.c_str(), "rb");		/* Flawfinder: ignore */	 	
         if (in)	 	
         {	 	
                 // read in the file header	 	
                 char buf[16384];		/* Flawfinder: ignore */ 	
                 S32 read;		/* Flawfinder: ignore */	 	
                 S32  version;	 	
                 if (fscanf(in, "LindenResource\nversion %d\n", &version))	 	
                 {	 	
                         if (2 == version)	 	
                         {
								// *NOTE: This buffer size is hard coded into scanf() below.
                                 char label[MAX_STRING];		/* Flawfinder: ignore */	 	
                                 char value[MAX_STRING];		/* Flawfinder: ignore */	 	
                                 S32  tokens_read;	 	
                                 while (fgets(buf, 1024, in))	 	
                                 {	 	
                                         label[0] = '\0';	 	
                                         value[0] = '\0';	 	
                                         tokens_read = sscanf(	/* Flawfinder: ignore */
											 buf,
											 "%254s %254s\n",
											 label, value);	 	

                                         llinfos << "got: " << label << " = " << value	 	
                                                         << llendl;	 	

                                         if (EOF == tokens_read)	 	
                                         {	 	
                                                 fclose(in);	 	
                                                 snprintf(error_message, MAX_STRING, "corrupt resource file: %s", src_filename.c_str());		/* Flawfinder: ignore */
												 args["[FILE]"] = src_filename;
												 upload_error(error_message, "CorruptResourceFile", filename, args);
                                                 return;
                                         }	 	

                                         if (2 == tokens_read)	 	
                                         {	 	
                                                 if (! strcmp("type", label))	 	
                                                 {	 	
                                                         asset_type = (LLAssetType::EType)(atoi(value));	 	
                                                 }	 	
                                         }	 	
                                         else	 	
                                         {	 	
                                                 if (! strcmp("_DATA_", label))	 	
                                                 {	 	
                                                         // below is the data section	 	
                                                         break;	 	
                                                 }	 	
                                         }	 	
                                         // other values are currently discarded	 	
                                 }	 	

                         }	 	
                         else	 	
                         {	 	
                                 fclose(in);	 	
                                 snprintf(error_message, MAX_STRING, "unknown linden resource file version in file: %s", src_filename.c_str());		/* Flawfinder: ignore */
								 args["[FILE]"] = src_filename;
								 upload_error(error_message, "UnknownResourceFileVersion", filename, args);
                                 return;
                         }	 	
                 }	 	
                 else	 	
                 {	 	
                         // this is an original binary formatted .lin file	 	
                         // start over at the beginning of the file	 	
                         fseek(in, 0, SEEK_SET);	 	

                         const S32 MAX_ASSET_DESCRIPTION_LENGTH = 256;	 	
                         const S32 MAX_ASSET_NAME_LENGTH = 64;	 	
                         S32 header_size = 34 + MAX_ASSET_DESCRIPTION_LENGTH + MAX_ASSET_NAME_LENGTH;	 	
                         S16     type_num;	 	

                         // read in and throw out most of the header except for the type	 	
                         fread(buf, header_size, 1, in);	 	
                         memcpy(&type_num, buf + 16, sizeof(S16));		/* Flawfinder: ignore */	 	
                         asset_type = (LLAssetType::EType)type_num;	 	
                 }	 	

                 // copy the file's data segment into another file for uploading	 	
                 FILE* out = LLFile::fopen(filename.c_str(), "wb");		/* Flawfinder: ignore */	
                 if (out)	 	
                 {	 	
                         while((read = fread(buf, 1, 16384, in)))		/* Flawfinder: ignore */	 	
                         {	 	
                                 fwrite(buf, 1, read, out);		/* Flawfinder: ignore */			 	
                         }	 	
                         fclose(out);	 	
                 }	 	
                 else	 	
                 {	 	
                         fclose(in);	 	
                         snprintf(error_message, MAX_STRING, "Unable to create output file: %s", filename.c_str());		/* Flawfinder: ignore */
						 args["[FILE]"] = filename;
						 upload_error(error_message, "UnableToCreateOutputFile", filename, args);
                         return;
                 }	 	

                 fclose(in);	 	
         }	 	
         else	 	
         {	 	
                 llinfos << "Couldn't open .lin file " << src_filename << llendl;	 	
         }	 	
	}
	else if (LLString::compareInsensitive(ext.c_str(),".bvh") == 0)
	{
		snprintf(error_message, MAX_STRING, "We do not currently support bulk upload of animation files\n");		/* Flawfinder: ignore */
		upload_error(error_message, "DoNotSupportBulkAnimationUpload", filename, args);
		return;
	}
	else
	{
		// Unknown extension
		snprintf(error_message, MAX_STRING, "Unknown file extension %s\nExpected .wav, .tga, .bmp, .jpg, .jpeg, or .bvh", ext.c_str());		/* Flawfinder: ignore */
		error = TRUE;;
	}

	// gen a new transaction ID for this asset
	tid.generate();

	if (!error)
	{
		uuid = tid.makeAssetID(gAgent.getSecureSessionID());
		// copy this file into the vfs for upload
		S32 file_size;
		apr_file_t* fp = ll_apr_file_open(filename, LL_APR_RB, &file_size);
		if (fp)
		{
			LLVFile file(gVFS, uuid, asset_type, LLVFile::WRITE);

			file.setMaxSize(file_size);

			const S32 buf_size = 65536;
			U8 copy_buf[buf_size];
			while ((file_size = ll_apr_file_read(fp, copy_buf, buf_size)))
			{
				file.write(copy_buf, file_size);
			}
			apr_file_close(fp);
		}
		else
		{
			snprintf(error_message, MAX_STRING, "Unable to access output file: %s", filename.c_str());		/* Flawfinder: ignore */
			error = TRUE;
		}
	}

	if (!error)
	{
		LLString t_disp_name = display_name;
		if (t_disp_name.empty())
		{
			t_disp_name = src_filename;
		}
		upload_new_resource(tid, asset_type, name, desc, compression_info, // tid
							destination_folder_type, inv_type, next_owner_perm,
							display_name, callback, userdata);
	}
	else
	{
		llwarns << error_message << llendl;
		LLStringBase<char>::format_map_t args;
		args["[ERROR_MESSAGE]"] = error_message;
		gViewerWindow->alertXml("ErrorMessage", args);
		if(LLFile::remove(filename.c_str()) == -1)
		{
			lldebugs << "unable to remove temp file" << llendl;
		}
		LLFilePicker::instance().reset();
	}
}
Esempio n. 14
0
void *updatethreadproc(void*)
{
	char tempDir[PATH_MAX] = "";		/* Flawfinder: ignore */
	FSRef tempDirRef;
	char temp[PATH_MAX];	/* Flawfinder: ignore */
	// *NOTE: This buffer length is used in a scanf() below.
	char deviceNode[1024] = "";	/* Flawfinder: ignore */
	FILE *downloadFile = NULL;
	OSStatus err;
	ProcessSerialNumber psn;
	char target[PATH_MAX];		/* Flawfinder: ignore */
	FSRef targetRef;
	FSRef targetParentRef;
	FSVolumeRefNum targetVol;
	FSRef trashFolderRef, tempFolderRef;
	Boolean replacingTarget = false;

	memset(&tempDirRef, 0, sizeof(tempDirRef));
	memset(&targetRef, 0, sizeof(targetRef));
	memset(&targetParentRef, 0, sizeof(targetParentRef));
	
	try
	{
		// Attempt to get a reference to the Second Life application bundle containing this updater.
		// Any failures during this process will cause us to default to updating /Applications/Second Life.app
		{
			FSRef myBundle;

			err = GetCurrentProcess(&psn);
			if(err == noErr)
			{
				err = GetProcessBundleLocation(&psn, &myBundle);
			}

			if(err == noErr)
			{
				// Sanity check:  Make sure the name of the item referenced by targetRef is "Second Life.app".
				FSRefMakePath(&myBundle, (UInt8*)target, sizeof(target));
				
				llinfos << "Updater bundle location: " << target << llendl;
			}
			
			// Our bundle should be in Second Life.app/Contents/Resources/AutoUpdater.app
			// so we need to go up 3 levels to get the path to the main application bundle.
			if(err == noErr)
			{
				err = FSGetParentRef(&myBundle, &targetRef);
			}
			if(err == noErr)
			{
				err = FSGetParentRef(&targetRef, &targetRef);
			}
			if(err == noErr)
			{
				err = FSGetParentRef(&targetRef, &targetRef);
			}
			
			// And once more to get the parent of the target
			if(err == noErr)
			{
				err = FSGetParentRef(&targetRef, &targetParentRef);
			}
			
			if(err == noErr)
			{
				FSRefMakePath(&targetRef, (UInt8*)target, sizeof(target));
				llinfos << "Path to target: " << target << llendl;
			}
			
			// Sanity check: make sure the target is a bundle with the right identifier
			if(err == noErr)
			{
				// Assume the worst...
				err = -1;

				if(isFSRefViewerBundle(&targetRef))
				{
					// This is the bundle we're looking for.
					err = noErr;
					replacingTarget = true;
				}
			}
			
			// Make sure the target's parent directory is writable.
			if(err == noErr)
			{
				if(!isDirWritable(targetParentRef))
				{
					// Parent directory isn't writable.
					llinfos << "Target parent directory not writable." << llendl;
					err = -1;
					replacingTarget = false;
				}
			}

			if(err != noErr)
			{
				Boolean isDirectory;
				llinfos << "Target search failed, defaulting to /Applications/" << gProductName << ".app." << llendl;
				
				// Set up the parent directory
				err = FSPathMakeRef((UInt8*)"/Applications", &targetParentRef, &isDirectory);
				if((err != noErr) || (!isDirectory))
				{
					// We're so hosed.
					llinfos << "Applications directory not found, giving up." << llendl;
					throw 0;
				}
				
				snprintf(target, sizeof(target), "/Applications/%s.app", gProductName);		

				memset(&targetRef, 0, sizeof(targetRef));
				err = FSPathMakeRef((UInt8*)target, &targetRef, NULL);
				if(err == fnfErr)
				{
					// This is fine, just means we're not replacing anything.
					err = noErr;
					replacingTarget = false;
				}
				else
				{
					replacingTarget = true;
				}

				// Make sure the target's parent directory is writable.
				if(err == noErr)
				{
					if(!isDirWritable(targetParentRef))
					{
						// Parent directory isn't writable.
						llinfos << "Target parent directory not writable." << llendl;
						err = -1;
						replacingTarget = false;
					}
				}

			}
			
			// If we haven't fixed all problems by this point, just bail.
			if(err != noErr)
			{
				llinfos << "Unable to pick a target, giving up." << llendl;
				throw 0;
			}
		}
		
		// Find the volID of the volume the target resides on
		{
			FSCatalogInfo info;
			err = FSGetCatalogInfo(
				&targetParentRef,
				kFSCatInfoVolume,
				&info,
				NULL, 
				NULL,  
				NULL);
				
			if(err != noErr)
				throw 0;
			
			targetVol = info.volume;
		}

		// Find the temporary items and trash folders on that volume.
		err = FSFindFolder(
			targetVol,
			kTrashFolderType,
			true,
			&trashFolderRef);

		if(err != noErr)
			throw 0;

		err = FSFindFolder(
			targetVol,
			kTemporaryFolderType,
			true,
			&tempFolderRef);
		
		if(err != noErr)
			throw 0;
		
		err = FSRefMakePath(&tempFolderRef, (UInt8*)temp, sizeof(temp));

		if(err != noErr)
			throw 0;
		
		temp[0] = '\0';
		strncat(temp, "/SecondLifeUpdate_XXXXXX", sizeof(temp) - 1);
		if(mkdtemp(temp) == NULL)
		{
			throw 0;
		}
		
		strcpy(tempDir, temp);		/* Flawfinder: ignore */
		
		llinfos << "tempDir is " << tempDir << llendl;

		err = FSPathMakeRef((UInt8*)tempDir, &tempDirRef, NULL);

		if(err != noErr)
			throw 0;
				
		chdir(tempDir);
		
		snprintf(temp, sizeof(temp), "SecondLife.dmg");		
		
		downloadFile = fopen(temp, "wb");		/* Flawfinder: ignore */
		if(downloadFile == NULL)
		{
			throw 0;
		}

		{
			CURL *curl = curl_easy_init();

			curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
	//		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &curl_download_callback);
			curl_easy_setopt(curl, CURLOPT_FILE, downloadFile);
			curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
			curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, &curl_progress_callback_func);
			curl_easy_setopt(curl, CURLOPT_URL,	gUpdateURL);
			curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
			
			sendProgress(0, 1, CFSTR("Downloading..."));
			
			CURLcode result = curl_easy_perform(curl);
			
			curl_easy_cleanup(curl);
			
			if(gCancelled)
			{
				llinfos << "User cancel, bailing out."<< llendl;
				throw 0;
			}
			
			if(result != CURLE_OK)
			{
				llinfos << "Error " << result << " while downloading disk image."<< llendl;
				throw 0;
			}
			
			fclose(downloadFile);
			downloadFile = NULL;
		}
		
		sendProgress(0, 0, CFSTR("Mounting image..."));
		LLFile::mkdir("mnt", 0700);
		
		// NOTE: we could add -private at the end of this command line to keep the image from showing up in the Finder,
		//		but if our cleanup fails, this makes it much harder for the user to unmount the image.
		LLString mountOutput;
		FILE* mounter = popen("hdiutil attach SecondLife.dmg -mountpoint mnt", "r");		/* Flawfinder: ignore */
		
		if(mounter == NULL)
		{
			llinfos << "Failed to mount disk image, exiting."<< llendl;
			throw 0;
		}
		
		// We need to scan the output from hdiutil to find the device node it uses to attach the disk image.
		// If we don't have this information, we can't detach it later.
		while(mounter != NULL)
		{
			size_t len = fread(temp, 1, sizeof(temp)-1, mounter);
			temp[len] = 0;
			mountOutput.append(temp);
			if(len < sizeof(temp)-1)
			{
				// End of file or error.
				if(pclose(mounter) != 0)
				{
					llinfos << "Failed to mount disk image, exiting."<< llendl;
					throw 0;
				}
				mounter = NULL;
			}
		}
		
		if(!mountOutput.empty())
		{
			const char *s = mountOutput.c_str();
			char *prefix = "/dev/";
			char *sub = strstr(s, prefix);
			
			if(sub != NULL)
			{
				sub += strlen(prefix);	/* Flawfinder: ignore */
				sscanf(sub, "%1023s", deviceNode);	/* Flawfinder: ignore */
			}
		}
		
		if(deviceNode[0] != 0)
		{
			llinfos << "Disk image attached on /dev/" << deviceNode << llendl;
		}
		else
		{
			llinfos << "Disk image device node not found!" << llendl;
		}
		
		// Get an FSRef to the new application on the disk image
		FSRef sourceRef;
		FSRef mountRef;
		snprintf(temp, sizeof(temp), "%s/mnt", tempDir);		

		llinfos << "Disk image mount point is: " << temp << llendl;

		err = FSPathMakeRef((UInt8 *)temp, &mountRef, NULL);
		if(err != noErr)
		{
			llinfos << "Couldn't make FSRef to disk image mount point." << llendl;
			throw 0;
		}

		err = findAppBundleOnDiskImage(&mountRef, &sourceRef);
		if(err != noErr)
		{
			llinfos << "Couldn't find application bundle on mounted disk image." << llendl;
			throw 0;
		}
		
		FSRef asideRef;
		char aside[MAX_PATH];		/* Flawfinder: ignore */
		
		// this will hold the name of the destination target
		HFSUniStr255 appNameUniStr;

		if(replacingTarget)
		{
			// Get the name of the target we're replacing
			err = FSGetCatalogInfo(&targetRef, 0, NULL, &appNameUniStr, NULL, NULL);
			if(err != noErr)
				throw 0;
			
			// Move aside old version (into work directory)
			err = FSMoveObject(&targetRef, &tempDirRef, &asideRef);
			if(err != noErr)
				throw 0;

			// Grab the path for later use.
			err = FSRefMakePath(&asideRef, (UInt8*)aside, sizeof(aside));
		}
		else
		{
			// Construct the name of the target based on the product name
			char appName[MAX_PATH];		/* Flawfinder: ignore */
			snprintf(appName, sizeof(appName), "%s.app", gProductName);		
			utf8str_to_HFSUniStr255( &appNameUniStr, appName );
		}
		
		sendProgress(0, 0, CFSTR("Copying files..."));
		
		llinfos << "Starting copy..." << llendl;

		// Copy the new version from the disk image to the target location.
		err = FSCopyObject(	
				&sourceRef,
				&targetParentRef,
				0,
				kFSCatInfoNone,
				kDupeActionStandard,
				&appNameUniStr,
				false,
				false,
				NULL,
				NULL,
				&targetRef,
				NULL);
		
		// Grab the path for later use.
		err = FSRefMakePath(&targetRef, (UInt8*)target, sizeof(target));
		if(err != noErr)
			throw 0;

		llinfos << "Copy complete. Target = " << target << llendl;

		if(err != noErr)
		{
			// Something went wrong during the copy.  Attempt to put the old version back and bail.
			(void)FSDeleteObjects(&targetRef);
			if(replacingTarget)
			{
				(void)FSMoveObject(&asideRef, &targetParentRef, NULL);
			}
			throw 0;
		}
		else
		{
			// The update has succeeded.  Clear the cache directory.

			sendProgress(0, 0, CFSTR("Clearing cache..."));
	
			llinfos << "Clearing cache..." << llendl;
			
			char mask[LL_MAX_PATH];		/* Flawfinder: ignore */
			snprintf(mask, LL_MAX_PATH, "%s*.*", gDirUtilp->getDirDelimiter().c_str());		
			gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""),mask);
			
			llinfos << "Clear complete." << llendl;

		}
	}
	catch(...)
	{
		if(!gCancelled)
			if(gFailure == noErr)
				gFailure = -1;
	}

	// Failures from here on out are all non-fatal and not reported.
	sendProgress(0, 3, CFSTR("Cleaning up..."));

	// Close disk image file if necessary
	if(downloadFile != NULL)
	{
		llinfos << "Closing download file." << llendl;

		fclose(downloadFile);
		downloadFile = NULL;
	}

	sendProgress(1, 3);
	// Unmount image
	if(deviceNode[0] != 0)
	{
		llinfos << "Detaching disk image." << llendl;

		snprintf(temp, sizeof(temp), "hdiutil detach '%s'", deviceNode);		
		system(temp);		/* Flawfinder: ignore */
	}

	sendProgress(2, 3);

	// Move work directory to the trash
	if(tempDir[0] != 0)
	{
//		chdir("/");
//		FSDeleteObjects(tempDirRef);

		llinfos << "Moving work directory to the trash." << llendl;

		err = FSMoveObject(&tempDirRef, &trashFolderRef, NULL);

//		snprintf(temp, sizeof(temp), "rm -rf '%s'", tempDir);
//		printf("%s\n", temp);
//		system(temp);
	}
	
	if(!gCancelled  && !gFailure && (target[0] != 0))
	{
		llinfos << "Touching application bundle." << llendl;

		snprintf(temp, sizeof(temp), "touch '%s'", target);		
		system(temp);		/* Flawfinder: ignore */

		llinfos << "Launching updated application." << llendl;

		snprintf(temp, sizeof(temp), "open '%s'", target);		
		system(temp);		/* Flawfinder: ignore */
	}

	sendDone();
	
	return(NULL);
}
Esempio n. 15
0
LLSpinCtrl::LLSpinCtrl(	const LLString& name, const LLRect& rect, const LLString& label, const LLFontGL* font,
	void (*commit_callback)(LLUICtrl*, void*),
	void* callback_user_data,
	F32 initial_value, F32 min_value, F32 max_value, F32 increment,
	const LLString& control_name,
	S32 label_width)
	:
	LLUICtrl(name, rect, TRUE, commit_callback, callback_user_data, FOLLOWS_LEFT | FOLLOWS_TOP ),
	mValue( initial_value ),
	mInitialValue( initial_value ),
	mMaxValue( max_value ),
	mMinValue( min_value ),
	mIncrement( increment ),
	mPrecision( 3 ),
	mLabelBox( NULL ),
	mTextEnabledColor( LLUI::sColorsGroup->getColor( "LabelTextColor" ) ),
	mTextDisabledColor( LLUI::sColorsGroup->getColor( "LabelDisabledColor" ) ),
	mbHasBeenSet( FALSE )
{
	S32 top = mRect.getHeight();
	S32 bottom = top - 2 * SPINCTRL_BTN_HEIGHT;
	S32 centered_top = top;
	S32 centered_bottom = bottom;
	S32 btn_left = 0;

	// Label
	if( !label.empty() )
	{
		LLRect label_rect( 0, centered_top, label_width, centered_bottom );
		mLabelBox = new LLTextBox( "SpinCtrl Label", label_rect, label.c_str(), font );
		addChild(mLabelBox);

		btn_left += label_rect.mRight + SPINCTRL_SPACING;
	}

	S32 btn_right = btn_left + SPINCTRL_BTN_WIDTH;
	
	// Spin buttons
	LLRect up_rect( btn_left, top, btn_right, top - SPINCTRL_BTN_HEIGHT );
	LLString out_id = "UIImgBtnSpinUpOutUUID";
	LLString in_id = "UIImgBtnSpinUpInUUID";
	mUpBtn = new LLButton(
		"SpinCtrl Up", up_rect,
		out_id,
		in_id,
		"",
		&LLSpinCtrl::onUpBtn, this, LLFontGL::sSansSerif );
	mUpBtn->setFollowsLeft();
	mUpBtn->setFollowsBottom();
	mUpBtn->setHeldDownCallback( &LLSpinCtrl::onUpBtn );
	mUpBtn->setTabStop(FALSE);
	addChild(mUpBtn);

	LLRect down_rect( btn_left, top - SPINCTRL_BTN_HEIGHT, btn_right, bottom );
	out_id = "UIImgBtnSpinDownOutUUID";
	in_id = "UIImgBtnSpinDownInUUID";
	mDownBtn = new LLButton(
		"SpinCtrl Down", down_rect,
		out_id,
		in_id,
		"",
		&LLSpinCtrl::onDownBtn, this, LLFontGL::sSansSerif );
	mDownBtn->setFollowsLeft();
	mDownBtn->setFollowsBottom();
	mDownBtn->setHeldDownCallback( &LLSpinCtrl::onDownBtn );
	mDownBtn->setTabStop(FALSE);
	addChild(mDownBtn);

	LLRect editor_rect( btn_right + 1, centered_top, mRect.getWidth(), centered_bottom );
	mEditor = new LLLineEditor( "SpinCtrl Editor", editor_rect, "",	font,
		MAX_STRING_LENGTH,
		&LLSpinCtrl::onEditorCommit, NULL, NULL, this,
		&LLLineEditor::prevalidateFloat );
	mEditor->setFollowsLeft();
	mEditor->setFollowsBottom();
	mEditor->setFocusReceivedCallback( &LLSpinCtrl::onEditorGainFocus );
	//RN: this seems to be a BAD IDEA, as it makes the editor behavior different when it has focus
	// than when it doesn't.  Instead, if you always have to double click to select all the text, 
	// it's easier to understand
	//mEditor->setSelectAllonFocusReceived(TRUE);
	mEditor->setIgnoreTab(TRUE);
	addChild(mEditor);

	updateEditor();
	setSpanChildren( TRUE );
}