PageRenderTime 71ms CodeModel.GetById 3ms app.highlight 61ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/newview/llpanelpick.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 617 lines | 448 code | 114 blank | 55 comment | 40 complexity | d051236df69d45791c06360ff17ad9e8 MD5 | raw file
  1/** 
  2 * @file llpanelpick.cpp
  3 * @brief LLPanelPick class implementation
  4 *
  5 * $LicenseInfo:firstyear=2004&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2010, Linden Research, Inc.
  8 * 
  9 * This library is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU Lesser General Public
 11 * License as published by the Free Software Foundation;
 12 * version 2.1 of the License only.
 13 * 
 14 * This library is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17 * Lesser General Public License for more details.
 18 * 
 19 * You should have received a copy of the GNU Lesser General Public
 20 * License along with this library; if not, write to the Free Software
 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 22 * 
 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 24 * $/LicenseInfo$
 25 */
 26
 27// Display of a "Top Pick" used both for the global top picks in the 
 28// Find directory, and also for each individual user's picks in their
 29// profile.
 30
 31#include "llviewerprecompiledheaders.h"
 32
 33#include "llpanelpick.h"
 34
 35#include "message.h"
 36
 37#include "llparcel.h"
 38
 39#include "llbutton.h"
 40#include "llfloaterreg.h"
 41#include "lliconctrl.h"
 42#include "lllineeditor.h"
 43#include "llpanel.h"
 44#include "llscrollcontainer.h"
 45#include "lltexteditor.h"
 46
 47#include "llagent.h"
 48#include "llagentpicksinfo.h"
 49#include "llavatarpropertiesprocessor.h"
 50#include "llfloaterworldmap.h"
 51#include "lltexturectrl.h"
 52#include "lluiconstants.h"
 53#include "llviewerparcelmgr.h"
 54#include "llviewerregion.h"
 55#include "llworldmap.h"
 56
 57
 58#define XML_PANEL_EDIT_PICK "panel_edit_pick.xml"
 59#define XML_PANEL_PICK_INFO "panel_pick_info.xml"
 60
 61#define XML_NAME		"pick_name"
 62#define XML_DESC		"pick_desc"
 63#define XML_SNAPSHOT	"pick_snapshot"
 64#define XML_LOCATION	"pick_location"
 65
 66#define XML_BTN_ON_TXTR "edit_icon"
 67#define XML_BTN_SAVE "save_changes_btn"
 68
 69//////////////////////////////////////////////////////////////////////////
 70//////////////////////////////////////////////////////////////////////////
 71//////////////////////////////////////////////////////////////////////////
 72
 73//static
 74LLPanelPickInfo* LLPanelPickInfo::create()
 75{
 76	LLPanelPickInfo* panel = new LLPanelPickInfo();
 77	panel->buildFromFile(XML_PANEL_PICK_INFO);
 78	return panel;
 79}
 80
 81LLPanelPickInfo::LLPanelPickInfo()
 82 : LLPanel()
 83 , LLAvatarPropertiesObserver()
 84 , LLRemoteParcelInfoObserver()
 85 , mAvatarId(LLUUID::null)
 86 , mSnapshotCtrl(NULL)
 87 , mPickId(LLUUID::null)
 88 , mParcelId(LLUUID::null)
 89 , mRequestedId(LLUUID::null)
 90 , mScrollingPanelMinHeight(0)
 91 , mScrollingPanelWidth(0)
 92 , mScrollingPanel(NULL)
 93 , mScrollContainer(NULL)
 94{
 95}
 96
 97LLPanelPickInfo::~LLPanelPickInfo()
 98{
 99	LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this);
100
101	if (mParcelId.notNull())
102	{
103		LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mParcelId, this);
104	}
105}
106
107void LLPanelPickInfo::onOpen(const LLSD& key)
108{
109	LLUUID avatar_id = key["avatar_id"];
110	if(avatar_id.isNull())
111	{
112		return;
113	}
114
115	if(getAvatarId().notNull())
116	{
117		LLAvatarPropertiesProcessor::getInstance()->removeObserver(
118			getAvatarId(), this);
119	}
120
121	setAvatarId(avatar_id);
122
123	resetData();
124	resetControls();
125
126	setPickId(key["pick_id"]);
127	setPickName(key["pick_name"]);
128	setPickDesc(key["pick_desc"]);
129	setSnapshotId(key["snapshot_id"]);
130
131	LLAvatarPropertiesProcessor::getInstance()->addObserver(
132		getAvatarId(), this);
133	LLAvatarPropertiesProcessor::getInstance()->sendPickInfoRequest(
134		getAvatarId(), getPickId());
135}
136
137BOOL LLPanelPickInfo::postBuild()
138{
139	mSnapshotCtrl = getChild<LLTextureCtrl>(XML_SNAPSHOT);
140
141	childSetAction("teleport_btn", boost::bind(&LLPanelPickInfo::onClickTeleport, this));
142	childSetAction("show_on_map_btn", boost::bind(&LLPanelPickInfo::onClickMap, this));
143	childSetAction("back_btn", boost::bind(&LLPanelPickInfo::onClickBack, this));
144
145	mScrollingPanel = getChild<LLPanel>("scroll_content_panel");
146	mScrollContainer = getChild<LLScrollContainer>("profile_scroll");
147
148	mScrollingPanelMinHeight = mScrollContainer->getScrolledViewRect().getHeight();
149	mScrollingPanelWidth = mScrollingPanel->getRect().getWidth();
150
151	return TRUE;
152}
153
154void LLPanelPickInfo::reshape(S32 width, S32 height, BOOL called_from_parent)
155{
156	LLPanel::reshape(width, height, called_from_parent);
157
158	if (!mScrollContainer || !mScrollingPanel)
159		return;
160
161	static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
162
163	S32 scroll_height = mScrollContainer->getRect().getHeight();
164	if (mScrollingPanelMinHeight >= scroll_height)
165	{
166		mScrollingPanel->reshape(mScrollingPanelWidth, mScrollingPanelMinHeight);
167	}
168	else
169	{
170		mScrollingPanel->reshape(mScrollingPanelWidth + scrollbar_size, scroll_height);
171	}
172}
173
174void LLPanelPickInfo::processProperties(void* data, EAvatarProcessorType type)
175{
176	if(APT_PICK_INFO != type)
177	{
178		return;
179	}
180	LLPickData* pick_info = static_cast<LLPickData*>(data);
181	if(!pick_info 
182		|| pick_info->creator_id != getAvatarId() 
183		|| pick_info->pick_id != getPickId())
184	{
185		return;
186	}
187
188	mParcelId = pick_info->parcel_id;
189	setSnapshotId(pick_info->snapshot_id);
190	setPickName(pick_info->name);
191	setPickDesc(pick_info->desc);
192	setPosGlobal(pick_info->pos_global);
193
194	// Send remote parcel info request to get parcel name and sim (region) name.
195	sendParcelInfoRequest();
196
197	// *NOTE dzaporozhan
198	// We want to keep listening to APT_PICK_INFO because user may 
199	// edit the Pick and we have to update Pick info panel.
200	// revomeObserver is called from onClickBack
201}
202
203void LLPanelPickInfo::sendParcelInfoRequest()
204{
205	if (mParcelId != mRequestedId)
206	{
207		LLRemoteParcelInfoProcessor::getInstance()->addObserver(mParcelId, this);
208		LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(mParcelId);
209
210		mRequestedId = mParcelId;
211	}
212}
213
214void LLPanelPickInfo::setExitCallback(const commit_callback_t& cb)
215{
216	getChild<LLButton>("back_btn")->setClickedCallback(cb);
217}
218
219void LLPanelPickInfo::processParcelInfo(const LLParcelData& parcel_data)
220{
221	setPickLocation(createLocationText(LLStringUtil::null, parcel_data.name,
222		parcel_data.sim_name, getPosGlobal()));
223
224	// We have received parcel info for the requested ID so clear it now.
225	mRequestedId.setNull();
226
227	if (mParcelId.notNull())
228	{
229		LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mParcelId, this);
230	}
231}
232
233void LLPanelPickInfo::setEditPickCallback(const commit_callback_t& cb)
234{
235	getChild<LLButton>("edit_btn")->setClickedCallback(cb);
236}
237
238// PROTECTED AREA
239
240void LLPanelPickInfo::resetControls()
241{
242	if(getAvatarId() == gAgent.getID())
243	{
244		getChildView("edit_btn")->setEnabled(TRUE);
245		getChildView("edit_btn")->setVisible( TRUE);
246	}
247	else
248	{
249		getChildView("edit_btn")->setEnabled(FALSE);
250		getChildView("edit_btn")->setVisible( FALSE);
251	}
252}
253
254void LLPanelPickInfo::resetData()
255{
256	setPickName(LLStringUtil::null);
257	setPickDesc(LLStringUtil::null);
258	setPickLocation(LLStringUtil::null);
259	setPickId(LLUUID::null);
260	setSnapshotId(LLUUID::null);
261	mPosGlobal.clearVec();
262	mParcelId.setNull();
263	mRequestedId.setNull();
264}
265
266// static
267std::string LLPanelPickInfo::createLocationText(const std::string& owner_name, const std::string& original_name, const std::string& sim_name, const LLVector3d& pos_global)
268{
269	std::string location_text;
270	location_text.append(owner_name);
271	if (!original_name.empty())
272	{
273		if (!location_text.empty()) location_text.append(", ");
274		location_text.append(original_name);
275
276	}
277	if (!sim_name.empty())
278	{
279		if (!location_text.empty()) location_text.append(", ");
280		location_text.append(sim_name);
281	}
282
283	if (!location_text.empty()) location_text.append(" ");
284
285	if (!pos_global.isNull())
286	{
287		S32 region_x = llround((F32)pos_global.mdV[VX]) % REGION_WIDTH_UNITS;
288		S32 region_y = llround((F32)pos_global.mdV[VY]) % REGION_WIDTH_UNITS;
289		S32 region_z = llround((F32)pos_global.mdV[VZ]);
290		location_text.append(llformat(" (%d, %d, %d)", region_x, region_y, region_z));
291	}
292	return location_text;
293}
294
295void LLPanelPickInfo::setSnapshotId(const LLUUID& id) 
296{ 
297	mSnapshotCtrl->setImageAssetID(id);
298	mSnapshotCtrl->setValid(TRUE);
299}
300
301void LLPanelPickInfo::setPickName(const std::string& name)
302{
303	getChild<LLUICtrl>(XML_NAME)->setValue(name);
304}
305
306void LLPanelPickInfo::setPickDesc(const std::string& desc)
307{
308	getChild<LLUICtrl>(XML_DESC)->setValue(desc);
309}
310
311void LLPanelPickInfo::setPickLocation(const std::string& location)
312{
313	getChild<LLUICtrl>(XML_LOCATION)->setValue(location);
314}
315
316void LLPanelPickInfo::onClickMap()
317{
318	LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal());
319	LLFloaterReg::showInstance("world_map", "center");
320}
321
322void LLPanelPickInfo::onClickTeleport()
323{
324	if (!getPosGlobal().isExactlyZero())
325	{
326		gAgent.teleportViaLocation(getPosGlobal());
327		LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal());
328	}
329}
330
331void LLPanelPickInfo::onClickBack()
332{
333	LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this);
334}
335
336//////////////////////////////////////////////////////////////////////////
337//////////////////////////////////////////////////////////////////////////
338//////////////////////////////////////////////////////////////////////////
339
340//static
341LLPanelPickEdit* LLPanelPickEdit::create()
342{
343	LLPanelPickEdit* panel = new LLPanelPickEdit();
344	panel->buildFromFile(XML_PANEL_EDIT_PICK);
345	return panel;
346}
347
348LLPanelPickEdit::LLPanelPickEdit()
349 : LLPanelPickInfo()
350 , mLocationChanged(false)
351 , mNeedData(true)
352 , mNewPick(false)
353{
354}
355
356LLPanelPickEdit::~LLPanelPickEdit()
357{
358}
359
360void LLPanelPickEdit::onOpen(const LLSD& key)
361{
362	LLUUID pick_id = key["pick_id"];
363	mNeedData = true;
364
365	// creating new Pick
366	if(pick_id.isNull())
367	{
368		mNewPick = true;
369
370		setAvatarId(gAgent.getID());
371
372		resetData();
373		resetControls();
374
375		setPosGlobal(gAgent.getPositionGlobal());
376
377		LLUUID parcel_id = LLUUID::null, snapshot_id = LLUUID::null;
378		std::string pick_name, pick_desc, region_name;
379
380		LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
381		if(parcel)
382		{
383			parcel_id = parcel->getID();
384			pick_name = parcel->getName();
385			pick_desc = parcel->getDesc();
386			snapshot_id = parcel->getSnapshotID();
387		}
388
389		LLViewerRegion* region = gAgent.getRegion();
390		if(region)
391		{
392			region_name = region->getName();
393		}
394
395		setParcelID(parcel_id);
396		getChild<LLUICtrl>("pick_name")->setValue(pick_name.empty() ? region_name : pick_name);
397		getChild<LLUICtrl>("pick_desc")->setValue(pick_desc);
398		setSnapshotId(snapshot_id);
399		setPickLocation(createLocationText(getLocationNotice(), pick_name, region_name, getPosGlobal()));
400
401		enableSaveButton(true);
402	}
403	// editing existing pick
404	else
405	{
406		mNewPick = false;
407		LLPanelPickInfo::onOpen(key);
408
409		enableSaveButton(false);
410	}
411
412	resetDirty();
413}
414
415void LLPanelPickEdit::setPickData(const LLPickData* pick_data)
416{
417	if(!pick_data)
418	{
419		return;
420	}
421
422	mNeedData = false;
423
424	setParcelID(pick_data->parcel_id);
425	getChild<LLUICtrl>("pick_name")->setValue(pick_data->name);
426	getChild<LLUICtrl>("pick_desc")->setValue(pick_data->desc);
427	setSnapshotId(pick_data->snapshot_id);
428	setPosGlobal(pick_data->pos_global);
429	setPickLocation(createLocationText(LLStringUtil::null, pick_data->name,
430			pick_data->sim_name, pick_data->pos_global));
431}
432
433BOOL LLPanelPickEdit::postBuild()
434{
435	LLPanelPickInfo::postBuild();
436
437	mSnapshotCtrl->setCommitCallback(boost::bind(&LLPanelPickEdit::onSnapshotChanged, this));
438
439	LLLineEditor* line_edit = getChild<LLLineEditor>("pick_name");
440	line_edit->setKeystrokeCallback(boost::bind(&LLPanelPickEdit::onPickChanged, this, _1), NULL);
441
442	LLTextEditor* text_edit = getChild<LLTextEditor>("pick_desc");
443	text_edit->setKeystrokeCallback(boost::bind(&LLPanelPickEdit::onPickChanged, this, _1));
444
445	childSetAction(XML_BTN_SAVE, boost::bind(&LLPanelPickEdit::onClickSave, this));
446	childSetAction("set_to_curr_location_btn", boost::bind(&LLPanelPickEdit::onClickSetLocation, this));
447
448	initTexturePickerMouseEvents();
449
450	return TRUE;
451}
452
453void LLPanelPickEdit::setSaveCallback(const commit_callback_t& cb)
454{
455	getChild<LLButton>("save_changes_btn")->setClickedCallback(cb);
456}
457
458void LLPanelPickEdit::setCancelCallback(const commit_callback_t& cb)
459{
460	getChild<LLButton>("cancel_btn")->setClickedCallback(cb);
461}
462
463void LLPanelPickEdit::resetDirty()
464{
465	LLPanelPickInfo::resetDirty();
466
467	getChild<LLLineEditor>("pick_name")->resetDirty();
468	getChild<LLTextEditor>("pick_desc")->resetDirty();
469	mSnapshotCtrl->resetDirty();
470	mLocationChanged = false;
471}
472
473BOOL LLPanelPickEdit::isDirty() const
474{
475	if( mNewPick
476		|| LLPanelPickInfo::isDirty()
477		|| mLocationChanged
478		|| mSnapshotCtrl->isDirty()
479		|| getChild<LLLineEditor>("pick_name")->isDirty()
480		|| getChild<LLTextEditor>("pick_desc")->isDirty())
481	{
482		return TRUE;
483	}
484	return FALSE;
485}
486
487// PROTECTED AREA
488
489void LLPanelPickEdit::sendUpdate()
490{
491	LLPickData pick_data;
492
493	// If we don't have a pick id yet, we'll need to generate one,
494	// otherwise we'll keep overwriting pick_id 00000 in the database.
495	if (getPickId().isNull()) 
496	{
497		getPickId().generate();
498	}
499
500	pick_data.agent_id = gAgent.getID();
501	pick_data.session_id = gAgent.getSessionID();
502	pick_data.pick_id = getPickId();
503	pick_data.creator_id = gAgent.getID();;
504
505	//legacy var  need to be deleted
506	pick_data.top_pick = FALSE; 
507	pick_data.parcel_id = mParcelId;
508	pick_data.name = getChild<LLUICtrl>(XML_NAME)->getValue().asString();
509	pick_data.desc = getChild<LLUICtrl>(XML_DESC)->getValue().asString();
510	pick_data.snapshot_id = mSnapshotCtrl->getImageAssetID();
511	pick_data.pos_global = getPosGlobal();
512	pick_data.sort_order = 0;
513	pick_data.enabled = TRUE;
514
515	LLAvatarPropertiesProcessor::instance().sendPickInfoUpdate(&pick_data);
516
517	if(mNewPick)
518	{
519		// Assume a successful create pick operation, make new number of picks
520		// available immediately. Actual number of picks will be requested in 
521		// LLAvatarPropertiesProcessor::sendPickInfoUpdate and updated upon server respond.
522		LLAgentPicksInfo::getInstance()->incrementNumberOfPicks();
523	}
524}
525
526void LLPanelPickEdit::onSnapshotChanged()
527{
528	enableSaveButton(true);
529}
530
531void LLPanelPickEdit::onPickChanged(LLUICtrl* ctrl)
532{
533	enableSaveButton(isDirty());
534}
535
536void LLPanelPickEdit::resetData()
537{
538	LLPanelPickInfo::resetData();
539	mLocationChanged = false;
540}
541
542void LLPanelPickEdit::enableSaveButton(bool enable)
543{
544	getChildView(XML_BTN_SAVE)->setEnabled(enable);
545}
546
547void LLPanelPickEdit::onClickSetLocation()
548{
549	// Save location for later use.
550	setPosGlobal(gAgent.getPositionGlobal());
551
552	std::string parcel_name, region_name;
553
554	LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
555	if (parcel)
556	{
557		mParcelId = parcel->getID();
558		parcel_name = parcel->getName();
559	}
560
561	LLViewerRegion* region = gAgent.getRegion();
562	if(region)
563	{
564		region_name = region->getName();
565	}
566
567	setPickLocation(createLocationText(getLocationNotice(), parcel_name, region_name, getPosGlobal()));
568
569	mLocationChanged = true;
570	enableSaveButton(TRUE);
571}
572
573void LLPanelPickEdit::onClickSave()
574{
575	sendUpdate();
576
577	mLocationChanged = false;
578
579	LLSD params;
580	params["action"] = "save_new_pick";
581	notifyParent(params);
582}
583
584std::string LLPanelPickEdit::getLocationNotice()
585{
586	static std::string notice = getString("location_notice");
587	return notice;
588}
589
590void LLPanelPickEdit::processProperties(void* data, EAvatarProcessorType type)
591{
592	if(mNeedData)
593	{
594		LLPanelPickInfo::processProperties(data, type);
595	}
596}
597
598// PRIVATE AREA
599
600void LLPanelPickEdit::initTexturePickerMouseEvents()
601{
602	text_icon = getChild<LLIconCtrl>(XML_BTN_ON_TXTR);
603	mSnapshotCtrl->setMouseEnterCallback(boost::bind(&LLPanelPickEdit::onTexturePickerMouseEnter, this, _1));
604	mSnapshotCtrl->setMouseLeaveCallback(boost::bind(&LLPanelPickEdit::onTexturePickerMouseLeave, this, _1));
605	
606	text_icon->setVisible(FALSE);
607}
608		
609void LLPanelPickEdit::onTexturePickerMouseEnter(LLUICtrl* ctrl)
610{
611        text_icon->setVisible(TRUE);
612}
613
614void LLPanelPickEdit::onTexturePickerMouseLeave(LLUICtrl* ctrl)
615{
616	text_icon->setVisible(FALSE);
617}