Example #1
0
void LLComboBox::createLineEditor(const LLComboBox::Params& p)
{
	static LLUICachedControl<S32> drop_shadow_button ("DropShadowButton", 0);
	LLRect rect = getLocalRect();
	if (mAllowTextEntry)
	{
		S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0;
		S32 shadow_size = drop_shadow_button;
		mButton->setRect(LLRect( getRect().getWidth() - llmax(8,arrow_width) - 2 * shadow_size,
								rect.mTop, rect.mRight, rect.mBottom));
		mButton->setTabStop(FALSE);
		mButton->setHAlign(LLFontGL::HCENTER);

		LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0);
		text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * drop_shadow_button;
		// clear label on button
		std::string cur_label = mButton->getLabelSelected();
		LLLineEditor::Params params = p.combo_editor;
		params.rect(text_entry_rect);
		params.default_text(LLStringUtil::null);
		params.max_length_bytes(mMaxChars);
		params.commit_callback.function(boost::bind(&LLComboBox::onTextCommit, this, _2));
		params.keystroke_callback(boost::bind(&LLComboBox::onTextEntry, this, _1));
		params.commit_on_focus_lost(false);
		params.follows.flags(FOLLOWS_ALL);
		params.label(mLabel);
		mTextEntry = LLUICtrlFactory::create<LLLineEditor> (params);
		mTextEntry->setText(cur_label);
		mTextEntry->setIgnoreTab(TRUE);
		addChild(mTextEntry);

		// clear label on button
		setLabel(LLStringUtil::null);

		mButton->setFollows(FOLLOWS_BOTTOM | FOLLOWS_TOP | FOLLOWS_RIGHT);
	}
	else
	{
		mButton->setRect(rect);
		mButton->setTabStop(TRUE);
		mButton->setHAlign(LLFontGL::LEFT);
		mButton->setLabel(mLabel.getString());
		
		if (mTextEntry)
		{
			mTextEntry->setVisible(FALSE);
		}
		mButton->setFollowsAll();
	}
}
LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p)
:	LLF32UICtrl(p),
	mLabelBox(NULL),
	mbHasBeenSet( FALSE ),
	mPrecision(p.decimal_digits),
	mTextEnabledColor(p.text_enabled_color()),
	mTextDisabledColor(p.text_disabled_color())
{
	static LLUICachedControl<S32> spinctrl_spacing ("UISpinctrlSpacing", 0);
	static LLUICachedControl<S32> spinctrl_btn_width ("UISpinctrlBtnWidth", 0);
	static LLUICachedControl<S32> spinctrl_btn_height ("UISpinctrlBtnHeight", 0);
	S32 centered_top = getRect().getHeight();
	S32 centered_bottom = getRect().getHeight() - 2 * spinctrl_btn_height;
	S32 btn_left = 0;
	// reserve space for spinner
	S32 label_width = llclamp(p.label_width(), 0, llmax(0, getRect().getWidth() - 40));

	// Label
	if( !p.label().empty() )
	{
		LLRect label_rect( 0, centered_top, label_width, centered_bottom );
		LLTextBox::Params params;
		params.wrap(p.label_wrap);
		params.name("SpinCtrl Label");
		params.rect(label_rect);
		params.initial_value(p.label());
		if (p.font.isProvided())
		{
			params.font(p.font);
		}
		mLabelBox = LLUICtrlFactory::create<LLTextBox> (params);
		addChild(mLabelBox);

		btn_left += label_rect.mRight + spinctrl_spacing;
	}

	S32 btn_right = btn_left + spinctrl_btn_width;
	
	// Spin buttons
	LLButton::Params up_button_params(p.up_button);
	up_button_params.rect = LLRect(btn_left, getRect().getHeight(), btn_right, getRect().getHeight() - spinctrl_btn_height);
	up_button_params.click_callback.function(boost::bind(&LLSpinCtrl::onUpBtn, this, _2));
	up_button_params.mouse_held_callback.function(boost::bind(&LLSpinCtrl::onUpBtn, this, _2));

	mUpBtn = LLUICtrlFactory::create<LLButton>(up_button_params);
	addChild(mUpBtn);

	LLButton::Params down_button_params(p.down_button);
	down_button_params.rect = LLRect(btn_left, getRect().getHeight() - spinctrl_btn_height, btn_right, getRect().getHeight() - 2 * spinctrl_btn_height);
	down_button_params.click_callback.function(boost::bind(&LLSpinCtrl::onDownBtn, this, _2));
	down_button_params.mouse_held_callback.function(boost::bind(&LLSpinCtrl::onDownBtn, this, _2));
	mDownBtn = LLUICtrlFactory::create<LLButton>(down_button_params);
	addChild(mDownBtn);

	LLRect editor_rect( btn_right + 1, centered_top, getRect().getWidth(), centered_bottom );
	LLLineEditor::Params params;
	params.name("SpinCtrl Editor");
	params.rect(editor_rect);
	if (p.font.isProvided())
	{
		params.font(p.font);
	}
	params.max_length.bytes(MAX_STRING_LENGTH);
	params.commit_callback.function((boost::bind(&LLSpinCtrl::onEditorCommit, this, _2)));
	
	//*NOTE: allow entering of any chars for LLCalc, proper input will be evaluated on commit
	
	params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM);
	mEditor = LLUICtrlFactory::create<LLLineEditor> (params);
	mEditor->setFocusReceivedCallback( boost::bind(&LLSpinCtrl::onEditorGainFocus, _1, this ));
	//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->setSelectAllonCommit(FALSE);
	addChild(mEditor);

	updateEditor();
	setUseBoundingRect( TRUE );
}
LLMultiSliderCtrl::LLMultiSliderCtrl(const LLMultiSliderCtrl::Params& p)
:	LLF32UICtrl(p),
	mLabelBox( NULL ),
	mEditor( NULL ),
	mTextBox( NULL ),
	mTextEnabledColor(p.text_color()),
	mTextDisabledColor(p.text_disabled_color())
{
	static LLUICachedControl<S32> multi_sliderctrl_spacing ("UIMultiSliderctrlSpacing", 0);

	S32 top = getRect().getHeight();
	S32 bottom = 0;
	S32 left = 0;

	S32 label_width = p.label_width;
	S32 text_width = p.text_width;

	// Label
	if( !p.label().empty() )
	{
		if (p.label_width == 0)
		{
			label_width = p.font()->getWidth(p.label);
		}
		LLRect label_rect( left, top, label_width, bottom );
		LLTextBox::Params params;
		params.name("MultiSliderCtrl Label");
		params.rect(label_rect);
		params.initial_value(p.label());
		params.font(p.font);
		mLabelBox = LLUICtrlFactory::create<LLTextBox> (params);
		addChild(mLabelBox);
	}

	S32 slider_right = getRect().getWidth();

	if (p.show_text)
	{
		if (!p.text_width.isProvided())
		{
			text_width = 0;
			// calculate the size of the text box (log max_value is number of digits - 1 so plus 1)
			if ( p.max_value() )
				text_width = p.font()->getWidth(std::string("0")) * ( static_cast < S32 > ( log10  ( p.max_value ) ) + p.decimal_digits + 1 );

			if ( p.increment < 1.0f )
				text_width += p.font()->getWidth(std::string("."));	// (mostly) take account of decimal point in value

			if ( p.min_value < 0.0f || p.max_value < 0.0f )
				text_width += p.font()->getWidth(std::string("-"));	// (mostly) take account of minus sign 

			// padding to make things look nicer
			text_width += 8;
		}
		S32 text_left = getRect().getWidth() - text_width;

		slider_right = text_left - multi_sliderctrl_spacing;

		LLRect text_rect( text_left, top, getRect().getWidth(), bottom );
		if( p.can_edit_text )
		{
			LLLineEditor::Params params;
			params.name("MultiSliderCtrl Editor");
			params.rect(text_rect);
			params.font(p.font);
			params.max_length_bytes(MAX_STRING_LENGTH);
			params.commit_callback.function(LLMultiSliderCtrl::onEditorCommit);
			params.prevalidate_callback(&LLTextValidate::validateFloat);
			params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM);
			mEditor = LLUICtrlFactory::create<LLLineEditor> (params);
			mEditor->setFocusReceivedCallback( boost::bind(LLMultiSliderCtrl::onEditorGainFocus, _1, this) );
			// don't do this, as selecting the entire text is single clicking in some cases
			// and double clicking in others
			//mEditor->setSelectAllonFocusReceived(TRUE);
			addChild(mEditor);
		}
		else
		{
			LLTextBox::Params params;
			params.name("MultiSliderCtrl Text");
			params.rect(text_rect);
			params.font(p.font);
			params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM);
			mTextBox = LLUICtrlFactory::create<LLTextBox> (params);
			addChild(mTextBox);
		}
	}

	S32 slider_left = label_width ? label_width + multi_sliderctrl_spacing : 0;
	LLRect slider_rect( slider_left, top, slider_right, bottom );
	LLMultiSlider::Params params;
	params.sliders = p.sliders;
	params.rect(slider_rect);
	params.commit_callback.function( LLMultiSliderCtrl::onSliderCommit );
	params.mouse_down_callback( p.mouse_down_callback );
	params.mouse_up_callback( p.mouse_up_callback );
	params.initial_value(p.initial_value());
	params.min_value(p.min_value);
	params.max_value(p.max_value);
	params.increment(p.increment);
	params.max_sliders(p.max_sliders);
	params.allow_overlap(p.allow_overlap);
	params.draw_track(p.draw_track);
	params.use_triangle(p.use_triangle);
	params.control_name(p.control_name);
	mMultiSlider = LLUICtrlFactory::create<LLMultiSlider> (params);
	addChild( mMultiSlider );
	mCurValue = mMultiSlider->getCurSliderValue();


	updateText();
}
LLLocationInputCtrl::LLLocationInputCtrl(const LLLocationInputCtrl::Params& p)
:	LLComboBox(p),
	mIconHPad(p.icon_hpad),
	mAddLandmarkHPad(p.add_landmark_hpad),
	mLocationContextMenu(NULL),
	mAddLandmarkBtn(NULL),
	mForSaleBtn(NULL),
	mInfoBtn(NULL),
	mLandmarkImageOn(NULL),
	mLandmarkImageOff(NULL),
	mIconMaturityGeneral(NULL),
	mIconMaturityAdult(NULL)
{
	// Lets replace default LLLineEditor with LLLocationLineEditor
	// to make needed escaping while copying and cutting url
	this->removeChild(mTextEntry);
	delete mTextEntry;

	// Can't access old mTextEntry fields as they are protected, so lets build new params
	// That is C&P from LLComboBox::createLineEditor function
	static LLUICachedControl<S32> drop_shadow_button ("DropShadowButton", 0);
	S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0;
	LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0);
	text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * drop_shadow_button;

	LLLineEditor::Params params = p.combo_editor;
	params.rect(text_entry_rect);
	params.default_text(LLStringUtil::null);
	params.max_length_bytes(p.max_chars);
	params.keystroke_callback(boost::bind(&LLComboBox::onTextEntry, this, _1));
	params.handle_edit_keys_directly(true);
	params.commit_on_focus_lost(false);
	params.follows.flags(FOLLOWS_ALL);
	mTextEntry = LLUICtrlFactory::create<LLURLLineEditor>(params);
	mTextEntry->setContextMenu(NULL);
	addChild(mTextEntry);
	// LLLineEditor is replaced with LLLocationLineEditor

	// "Place information" button.
	LLButton::Params info_params = p.info_button;
	mInfoBtn = LLUICtrlFactory::create<LLButton>(info_params);
	mInfoBtn->setClickedCallback(boost::bind(&LLLocationInputCtrl::onInfoButtonClicked, this));
	addChild(mInfoBtn);

	// "Add landmark" button.
	LLButton::Params al_params = p.add_landmark_button;

	// Image for unselected state will be set in updateAddLandmarkButton(),
	// it will be either mLandmarkOn or mLandmarkOff
	if (p.add_landmark_image_enabled())
	{
		mLandmarkImageOn = p.add_landmark_image_enabled;
	}
	if (p.add_landmark_image_disabled())
	{
		mLandmarkImageOff = p.add_landmark_image_disabled;
	}

	if(p.add_landmark_image_selected)
	{
		al_params.image_selected = p.add_landmark_image_selected;
	}
	if (p.add_landmark_image_hover())
	{
		al_params.image_hover_unselected = p.add_landmark_image_hover;
	}

	al_params.click_callback.function(boost::bind(&LLLocationInputCtrl::onAddLandmarkButtonClicked, this));
	mAddLandmarkBtn = LLUICtrlFactory::create<LLButton>(al_params);
	enableAddLandmarkButton(true);
	addChild(mAddLandmarkBtn);

	if (p.icon_maturity_general())
	{
		mIconMaturityGeneral = p.icon_maturity_general;
	}
	if (p.icon_maturity_adult())
	{
		mIconMaturityAdult = p.icon_maturity_adult;
	}

	LLIconCtrl::Params maturity_icon = p.maturity_icon;
	mMaturityIcon = LLUICtrlFactory::create<LLIconCtrl>(maturity_icon);
	addChild(mMaturityIcon);

	LLButton::Params for_sale_button = p.for_sale_button;
	for_sale_button.tool_tip = LLTrans::getString("LocationCtrlForSaleTooltip");
	for_sale_button.click_callback.function(
		boost::bind(&LLLocationInputCtrl::onForSaleButtonClicked, this));
	mForSaleBtn = LLUICtrlFactory::create<LLButton>( for_sale_button );
	addChild(mForSaleBtn);

	// Parcel property icons
	// Must be mouse-opaque so cursor stays as an arrow when hovering to
	// see tooltip.
	LLIconCtrl::Params voice_icon = p.voice_icon;
	voice_icon.tool_tip = LLTrans::getString("LocationCtrlVoiceTooltip");
	voice_icon.mouse_opaque = true;
	mParcelIcon[VOICE_ICON] = LLUICtrlFactory::create<LLIconCtrl>(voice_icon);
	mParcelIcon[VOICE_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, VOICE_ICON));
	addChild(mParcelIcon[VOICE_ICON]);

	LLIconCtrl::Params fly_icon = p.fly_icon;
	fly_icon.tool_tip = LLTrans::getString("LocationCtrlFlyTooltip");
	fly_icon.mouse_opaque = true;
	mParcelIcon[FLY_ICON] = LLUICtrlFactory::create<LLIconCtrl>(fly_icon);
	mParcelIcon[FLY_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, FLY_ICON));
	addChild(mParcelIcon[FLY_ICON]);

	LLIconCtrl::Params push_icon = p.push_icon;
	push_icon.tool_tip = LLTrans::getString("LocationCtrlPushTooltip");
	push_icon.mouse_opaque = true;
	mParcelIcon[PUSH_ICON] = LLUICtrlFactory::create<LLIconCtrl>(push_icon);
	mParcelIcon[PUSH_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, PUSH_ICON));
	addChild(mParcelIcon[PUSH_ICON]);

	LLIconCtrl::Params build_icon = p.build_icon;
	build_icon.tool_tip = LLTrans::getString("LocationCtrlBuildTooltip");
	build_icon.mouse_opaque = true;
	mParcelIcon[BUILD_ICON] = LLUICtrlFactory::create<LLIconCtrl>(build_icon);
	mParcelIcon[BUILD_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, BUILD_ICON));
	addChild(mParcelIcon[BUILD_ICON]);

	LLIconCtrl::Params scripts_icon = p.scripts_icon;
	scripts_icon.tool_tip = LLTrans::getString("LocationCtrlScriptsTooltip");
	scripts_icon.mouse_opaque = true;
	mParcelIcon[SCRIPTS_ICON] = LLUICtrlFactory::create<LLIconCtrl>(scripts_icon);
	mParcelIcon[SCRIPTS_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, SCRIPTS_ICON));
	addChild(mParcelIcon[SCRIPTS_ICON]);

	LLIconCtrl::Params damage_icon = p.damage_icon;
	damage_icon.tool_tip = LLTrans::getString("LocationCtrlDamageTooltip");
	damage_icon.mouse_opaque = true;
	mParcelIcon[DAMAGE_ICON] = LLUICtrlFactory::create<LLIconCtrl>(damage_icon);
	mParcelIcon[DAMAGE_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, DAMAGE_ICON));
	addChild(mParcelIcon[DAMAGE_ICON]);
	
	LLTextBox::Params damage_text = p.damage_text;
	damage_text.tool_tip = LLTrans::getString("LocationCtrlDamageTooltip");
	damage_text.mouse_opaque = true;
	mDamageText = LLUICtrlFactory::create<LLTextBox>(damage_text);
	addChild(mDamageText);
	
	// Register callbacks and load the location field context menu (NB: the order matters).
	LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Navbar.Action", boost::bind(&LLLocationInputCtrl::onLocationContextMenuItemClicked, this, _2));
	LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Navbar.EnableMenuItem", boost::bind(&LLLocationInputCtrl::onLocationContextMenuItemEnabled, this, _2));
		
	setPrearrangeCallback(boost::bind(&LLLocationInputCtrl::onLocationPrearrange, this, _2));
	getTextEntry()->setMouseUpCallback(boost::bind(&LLLocationInputCtrl::changeLocationPresentation, this));

	// Load the location field context menu
	mLocationContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_navbar.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
	if (!mLocationContextMenu)
	{
		llwarns << "Error loading navigation bar context menu" << llendl;
		
	}
	getTextEntry()->setRightMouseUpCallback(boost::bind(&LLLocationInputCtrl::onTextEditorRightClicked,this,_2,_3,_4));
	updateWidgetlayout();

	// Connecting signal for updating location on "Show Coordinates" setting change.
	LLControlVariable* coordinates_control = gSavedSettings.getControl("NavBarShowCoordinates").get();
	if (coordinates_control)
	{
		mCoordinatesControlConnection = coordinates_control->getSignal()->connect(boost::bind(&LLLocationInputCtrl::refreshLocation, this));
	}

	// Connecting signal for updating parcel icons on "Show Parcel Properties" setting change.
	LLControlVariable* parcel_properties_control = gSavedSettings.getControl("NavBarShowParcelProperties").get();
	if (parcel_properties_control)
	{
		mParcelPropertiesControlConnection = parcel_properties_control->getSignal()->connect(boost::bind(&LLLocationInputCtrl::refreshParcelIcons, this));
	}

	// - Make the "Add landmark" button updated when either current parcel gets changed
	//   or a landmark gets created or removed from the inventory.
	// - Update the location string on parcel change.
	mParcelMgrConnection = LLViewerParcelMgr::getInstance()->addAgentParcelChangedCallback(
		boost::bind(&LLLocationInputCtrl::onAgentParcelChange, this));
	// LLLocationHistory instance is being created before the location input control, so we have to update initial state of button manually.
	mButton->setEnabled(LLLocationHistory::instance().getItemCount() > 0);
	mLocationHistoryConnection = LLLocationHistory::getInstance()->setChangedCallback(
			boost::bind(&LLLocationInputCtrl::onLocationHistoryChanged, this,_1));

	mRemoveLandmarkObserver	= new LLRemoveLandmarkObserver(this);
	mAddLandmarkObserver	= new LLAddLandmarkObserver(this);
	gInventory.addObserver(mRemoveLandmarkObserver);
	gInventory.addObserver(mAddLandmarkObserver);

	mParcelChangeObserver = new LLParcelChangeObserver(this);
	LLViewerParcelMgr::getInstance()->addObserver(mParcelChangeObserver);

	mAddLandmarkTooltip = LLTrans::getString("LocationCtrlAddLandmarkTooltip");
	mEditLandmarkTooltip = LLTrans::getString("LocationCtrlEditLandmarkTooltip");
	getChild<LLView>("Location History")->setToolTip(LLTrans::getString("LocationCtrlComboBtnTooltip"));
	getChild<LLView>("Place Information")->setToolTip(LLTrans::getString("LocationCtrlInfoBtnTooltip"));
}