PageRenderTime 49ms CodeModel.GetById 16ms app.highlight 29ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/newview/llprogressview.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 426 lines | 298 code | 69 blank | 59 comment | 48 complexity | 38227b99a123892cb6192111cc248cbf MD5 | raw file
  1/** 
  2 * @file llprogressview.cpp
  3 * @brief LLProgressView class implementation
  4 *
  5 * $LicenseInfo:firstyear=2002&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#include "llviewerprecompiledheaders.h"
 28
 29#include "llprogressview.h"
 30
 31#include "indra_constants.h"
 32#include "llmath.h"
 33#include "llgl.h"
 34#include "llrender.h"
 35#include "llui.h"
 36#include "llfontgl.h"
 37#include "lltimer.h"
 38#include "lltextbox.h"
 39#include "llglheaders.h"
 40
 41#include "llagent.h"
 42#include "llbutton.h"
 43#include "llfocusmgr.h"
 44#include "llnotifications.h"
 45#include "llprogressbar.h"
 46#include "llstartup.h"
 47#include "llviewercontrol.h"
 48#include "llviewertexturelist.h"
 49#include "llviewerwindow.h"
 50#include "llappviewer.h"
 51#include "llweb.h"
 52#include "lluictrlfactory.h"
 53#include "llpanellogin.h"
 54
 55LLProgressView* LLProgressView::sInstance = NULL;
 56
 57S32 gStartImageWidth = 1;
 58S32 gStartImageHeight = 1;
 59const F32 FADE_TO_WORLD_TIME = 1.0f;
 60
 61static LLRegisterPanelClassWrapper<LLProgressView> r("progress_view");
 62
 63// XUI: Translate
 64LLProgressView::LLProgressView() 
 65:	LLPanel(),
 66	mPercentDone( 0.f ),
 67	mMediaCtrl( NULL ),
 68	mMouseDownInActiveArea( false ),
 69	mUpdateEvents("LLProgressView"),
 70	mFadeToWorldTimer(),
 71	mFadeFromLoginTimer(),
 72	mStartupComplete(false)
 73{
 74	mUpdateEvents.listen("self", boost::bind(&LLProgressView::handleUpdate, this, _1));
 75}
 76
 77BOOL LLProgressView::postBuild()
 78{
 79	mProgressBar = getChild<LLProgressBar>("login_progress_bar");
 80
 81	// media control that is used to play intro video
 82	mMediaCtrl = getChild<LLMediaCtrl>("login_media_panel");
 83	mMediaCtrl->setVisible( false );		// hidden initially
 84	mMediaCtrl->addObserver( this );		// watch events
 85	
 86	LLViewerMedia::setOnlyAudibleMediaTextureID(mMediaCtrl->getTextureID());
 87
 88	mCancelBtn = getChild<LLButton>("cancel_btn");
 89	mCancelBtn->setClickedCallback(  LLProgressView::onCancelButtonClicked, NULL );
 90	mFadeToWorldTimer.stop();
 91	mFadeFromLoginTimer.stop();
 92
 93	getChild<LLTextBox>("title_text")->setText(LLStringExplicit(LLAppViewer::instance()->getSecondLifeTitle()));
 94
 95	getChild<LLTextBox>("message_text")->setClickedCallback(onClickMessage, this);
 96
 97	// hidden initially, until we need it
 98	LLPanel::setVisible(FALSE);
 99
100	LLNotifications::instance().getChannel("AlertModal")->connectChanged(boost::bind(&LLProgressView::onAlertModal, this, _1));
101
102	sInstance = this;
103	return TRUE;
104}
105
106
107LLProgressView::~LLProgressView()
108{
109	gFocusMgr.releaseFocusIfNeeded( this );
110
111	sInstance = NULL;
112}
113
114BOOL LLProgressView::handleHover(S32 x, S32 y, MASK mask)
115{
116	if( childrenHandleHover( x, y, mask ) == NULL )
117	{
118		gViewerWindow->setCursor(UI_CURSOR_WAIT);
119	}
120	return TRUE;
121}
122
123
124BOOL LLProgressView::handleKeyHere(KEY key, MASK mask)
125{
126	// Suck up all keystokes except CTRL-Q.
127	if( ('Q' == key) && (MASK_CONTROL == mask) )
128	{
129		LLAppViewer::instance()->userQuit();
130	}
131	return TRUE;
132}
133
134void LLProgressView::revealIntroPanel()
135{
136	// if user hasn't yet seen intro video
137	std::string intro_url = gSavedSettings.getString("PostFirstLoginIntroURL");
138	if ( intro_url.length() > 0 && 
139			gSavedSettings.getBOOL("BrowserJavascriptEnabled") &&
140			gSavedSettings.getBOOL("PostFirstLoginIntroViewed" ) == FALSE )
141	{
142		// hide the progress bar
143		getChild<LLView>("stack1")->setVisible(false);
144		
145		// navigate to intro URL and reveal widget 
146		mMediaCtrl->navigateTo( intro_url );	
147		mMediaCtrl->setVisible( TRUE );
148
149
150		// flag as having seen the new user post login intro
151		gSavedSettings.setBOOL("PostFirstLoginIntroViewed", TRUE );
152
153		mMediaCtrl->setFocus(TRUE);
154	}
155
156	mFadeFromLoginTimer.start();
157}
158
159void LLProgressView::setStartupComplete()
160{
161	mStartupComplete = true;
162
163	// if we are not showing a video, fade into world
164	if (!mMediaCtrl->getVisible())
165	{
166		mFadeFromLoginTimer.stop();
167		mFadeToWorldTimer.start();
168	}
169}
170
171void LLProgressView::setVisible(BOOL visible)
172{
173	// hiding progress view
174	if (getVisible() && !visible)
175	{
176		LLPanel::setVisible(FALSE);
177	}
178	// showing progress view
179	else if (visible && (!getVisible() || mFadeToWorldTimer.getStarted()))
180	{
181		setFocus(TRUE);
182		mFadeToWorldTimer.stop();
183		LLPanel::setVisible(TRUE);
184	} 
185}
186
187
188void LLProgressView::drawStartTexture(F32 alpha)
189{
190	gGL.pushMatrix();	
191	if (gStartTexture)
192	{
193		LLGLSUIDefault gls_ui;
194		gGL.getTexUnit(0)->bind(gStartTexture.get());
195		gGL.color4f(1.f, 1.f, 1.f, alpha);
196		F32 image_aspect = (F32)gStartImageWidth / (F32)gStartImageHeight;
197		S32 width = getRect().getWidth();
198		S32 height = getRect().getHeight();
199		F32 view_aspect = (F32)width / (F32)height;
200		// stretch image to maintain aspect ratio
201		if (image_aspect > view_aspect)
202		{
203			gGL.translatef(-0.5f * (image_aspect / view_aspect - 1.f) * width, 0.f, 0.f);
204			gGL.scalef(image_aspect / view_aspect, 1.f, 1.f);
205		}
206		else
207		{
208			gGL.translatef(0.f, -0.5f * (view_aspect / image_aspect - 1.f) * height, 0.f);
209			gGL.scalef(1.f, view_aspect / image_aspect, 1.f);
210		}
211		gl_rect_2d_simple_tex( getRect().getWidth(), getRect().getHeight() );
212		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
213	}
214	else
215	{
216		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
217		gGL.color4f(0.f, 0.f, 0.f, 1.f);
218		gl_rect_2d(getRect());
219	}
220	gGL.popMatrix();
221}
222
223
224void LLProgressView::draw()
225{
226	static LLTimer timer;
227
228	if (mFadeFromLoginTimer.getStarted())
229	{
230		F32 alpha = clamp_rescale(mFadeFromLoginTimer.getElapsedTimeF32(), 0.f, FADE_TO_WORLD_TIME, 0.f, 1.f);
231		LLViewDrawContext context(alpha);
232
233		if (!mMediaCtrl->getVisible())
234		{
235			drawStartTexture(alpha);
236		}
237		
238		LLPanel::draw();
239
240		if (mFadeFromLoginTimer.getElapsedTimeF32() > FADE_TO_WORLD_TIME )
241		{
242			mFadeFromLoginTimer.stop();
243			LLPanelLogin::closePanel();
244		}
245
246		return;
247	}
248
249	// handle fade out to world view when we're asked to
250	if (mFadeToWorldTimer.getStarted())
251	{
252		// draw fading panel
253		F32 alpha = clamp_rescale(mFadeToWorldTimer.getElapsedTimeF32(), 0.f, FADE_TO_WORLD_TIME, 1.f, 0.f);
254		LLViewDrawContext context(alpha);
255				
256		drawStartTexture(alpha);
257		LLPanel::draw();
258
259		// faded out completely - remove panel and reveal world
260		if (mFadeToWorldTimer.getElapsedTimeF32() > FADE_TO_WORLD_TIME )
261		{
262			mFadeToWorldTimer.stop();
263
264			LLViewerMedia::setOnlyAudibleMediaTextureID(LLUUID::null);
265
266			// Fade is complete, release focus
267			gFocusMgr.releaseFocusIfNeeded( this );
268
269			// turn off panel that hosts intro so we see the world
270			LLPanel::setVisible(FALSE);
271
272			// stop observing events since we no longer care
273			mMediaCtrl->remObserver( this );
274
275			// hide the intro
276			mMediaCtrl->setVisible( false );
277
278			// navigate away from intro page to something innocuous since 'unload' is broken right now
279			//mMediaCtrl->navigateTo( "about:blank" );
280
281			// FIXME: this causes a crash that i haven't been able to fix
282			mMediaCtrl->unloadMediaSource();	
283
284			gStartTexture = NULL;
285		}
286		return;
287	}
288
289	drawStartTexture(1.0f);
290	// draw children
291	LLPanel::draw();
292}
293
294void LLProgressView::setText(const std::string& text)
295{
296	getChild<LLUICtrl>("progress_text")->setValue(text);
297}
298
299void LLProgressView::setPercent(const F32 percent)
300{
301	mProgressBar->setValue(percent);
302}
303
304void LLProgressView::setMessage(const std::string& msg)
305{
306	mMessage = msg;
307	getChild<LLUICtrl>("message_text")->setValue(mMessage);
308}
309
310void LLProgressView::setCancelButtonVisible(BOOL b, const std::string& label)
311{
312	mCancelBtn->setVisible( b );
313	mCancelBtn->setEnabled( b );
314	mCancelBtn->setLabelSelected(label);
315	mCancelBtn->setLabelUnselected(label);
316}
317
318// static
319void LLProgressView::onCancelButtonClicked(void*)
320{
321	// Quitting viewer here should happen only when "Quit" button is pressed while starting up.
322	// Check for startup state is used here instead of teleport state to avoid quitting when
323	// cancel is pressed while teleporting inside region (EXT-4911)
324	if (LLStartUp::getStartupState() < STATE_STARTED)
325	{
326		LLAppViewer::instance()->requestQuit();
327	}
328	else
329	{
330		gAgent.teleportCancel();
331		sInstance->mCancelBtn->setEnabled(FALSE);
332		sInstance->setVisible(FALSE);
333	}
334}
335
336// static
337void LLProgressView::onClickMessage(void* data)
338{
339	LLProgressView* viewp = (LLProgressView*)data;
340	if ( viewp != NULL && ! viewp->mMessage.empty() )
341	{
342		std::string url_to_open( "" );
343
344		size_t start_pos;
345		start_pos = viewp->mMessage.find( "https://" );
346		if (start_pos == std::string::npos)
347			start_pos = viewp->mMessage.find( "http://" );
348		if (start_pos == std::string::npos)
349			start_pos = viewp->mMessage.find( "ftp://" );
350			
351		if ( start_pos != std::string::npos )
352		{
353			size_t end_pos = viewp->mMessage.find_first_of( " \n\r\t", start_pos );
354			if ( end_pos != std::string::npos )
355				url_to_open = viewp->mMessage.substr( start_pos, end_pos - start_pos );
356			else
357				url_to_open = viewp->mMessage.substr( start_pos );
358
359			LLWeb::loadURLExternal( url_to_open );
360		}
361	}
362}
363
364bool LLProgressView::handleUpdate(const LLSD& event_data)
365{
366	LLSD message = event_data.get("message");
367	LLSD desc = event_data.get("desc");
368	LLSD percent = event_data.get("percent");
369
370	if(message.isDefined())
371	{
372		setMessage(message.asString());
373	}
374
375	if(desc.isDefined())
376	{
377		setText(desc.asString());
378	}
379	
380	if(percent.isDefined())
381	{
382		setPercent(percent.asReal());
383	}
384	return false;
385}
386
387bool LLProgressView::onAlertModal(const LLSD& notify)
388{
389	// if the progress view is visible, it will obscure the notification window
390	// in this case, we want to auto-accept WebLaunchExternalTarget notifications
391	if (isInVisibleChain() && notify["sigtype"].asString() == "add")
392	{
393		LLNotificationPtr notifyp = LLNotifications::instance().find(notify["id"].asUUID());
394		if (notifyp && notifyp->getName() == "WebLaunchExternalTarget")
395		{
396			notifyp->respondWithDefault();
397		}
398	}
399	return false;
400}
401
402void LLProgressView::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
403{
404	// the intro web content calls javascript::window.close() when it's done
405	if( event == MEDIA_EVENT_CLOSE_REQUEST )
406	{
407		if (mStartupComplete)
408		{
409			//make sure other timer has stopped
410			mFadeFromLoginTimer.stop();
411			mFadeToWorldTimer.start();
412		}
413		else
414		{
415			// hide the media ctrl and wait for startup to be completed before fading to world
416			mMediaCtrl->setVisible(false);
417			if (mMediaCtrl->getMediaPlugin())
418			{
419				mMediaCtrl->getMediaPlugin()->stop();
420			}
421
422			// show the progress bar
423			getChild<LLView>("stack1")->setVisible(true);
424		}
425	}
426}