summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/newview/llpanelnearbymedia.cpp309
-rw-r--r--indra/newview/llpanelnearbymedia.h49
-rw-r--r--indra/newview/llpanelprimmediacontrols.h17
-rw-r--r--indra/newview/llviewermedia.cpp8
-rw-r--r--indra/newview/llviewermedia.h2
-rw-r--r--indra/newview/llviewermediafocus.cpp13
-rw-r--r--indra/newview/llviewermediafocus.h3
-rw-r--r--indra/newview/llviewerparcelmgr.cpp3
-rw-r--r--indra/newview/skins/default/xui/en/panel_nearby_media.xml618
9 files changed, 745 insertions, 277 deletions
diff --git a/indra/newview/llpanelnearbymedia.cpp b/indra/newview/llpanelnearbymedia.cpp
index 464ba97278..6a88c916d7 100644
--- a/indra/newview/llpanelnearbymedia.cpp
+++ b/indra/newview/llpanelnearbymedia.cpp
@@ -41,6 +41,7 @@
#include "llscrolllistctrl.h"
#include "llscrolllistitem.h"
#include "llscrolllistcell.h"
+#include "llslider.h"
#include "llsliderctrl.h"
#include "llagent.h"
#include "llagentui.h"
@@ -75,28 +76,26 @@ static const LLUUID PARCEL_AUDIO_LIST_ITEM_UUID = LLUUID("DF4B020D-8A24-4B95-AB5
LLPanelNearByMedia::LLPanelNearByMedia()
: mMediaList(NULL),
mEnableAllCtrl(NULL),
- mEnableParcelMediaCtrl(NULL),
mAllMediaDisabled(false),
mDebugInfoVisible(false),
mParcelMediaItem(NULL),
mParcelAudioItem(NULL)
{
- mParcelAudioAutoStart = gSavedSettings.getBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING);
+ mParcelAudioAutoStart = gSavedSettings.getBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING) &&
+ gSavedSettings.getBOOL("MediaTentativeAutoPlay");
mCommitCallbackRegistrar.add("MediaListCtrl.EnableAll", boost::bind(&LLPanelNearByMedia::onClickEnableAll, this));
mCommitCallbackRegistrar.add("MediaListCtrl.DisableAll", boost::bind(&LLPanelNearByMedia::onClickDisableAll, this));
mCommitCallbackRegistrar.add("MediaListCtrl.GoMediaPrefs", boost::bind(&LLPanelNearByMedia::onAdvancedButtonClick, this));
mCommitCallbackRegistrar.add("MediaListCtrl.MoreLess", boost::bind(&LLPanelNearByMedia::onMoreLess, this));
- mCommitCallbackRegistrar.add("ParcelMediaCtrl.ParcelMediaVolume", boost::bind(&LLPanelNearByMedia::onParcelMediaVolumeSlider, this));
- mCommitCallbackRegistrar.add("ParcelMediaCtrl.MuteParcelMedia", boost::bind(&LLPanelNearByMedia::onClickMuteParcelMedia, this));
- mCommitCallbackRegistrar.add("ParcelMediaCtrl.EnableParcelMedia", boost::bind(&LLPanelNearByMedia::onClickEnableParcelMedia, this));
- mCommitCallbackRegistrar.add("ParcelMediaCtrl.DisableParcelMedia", boost::bind(&LLPanelNearByMedia::onClickDisableParcelMedia, this));
- mCommitCallbackRegistrar.add("ParcelMediaCtrl.Play", boost::bind(&LLPanelNearByMedia::onClickParcelMediaPlay, this));
- mCommitCallbackRegistrar.add("ParcelMediaCtrl.Stop", boost::bind(&LLPanelNearByMedia::onClickParcelMediaStop, this));
- mCommitCallbackRegistrar.add("ParcelMediaCtrl.Pause", boost::bind(&LLPanelNearByMedia::onClickParcelMediaPause, this));
- mCommitCallbackRegistrar.add("ParcelAudioCtrl.Play", boost::bind(&LLPanelNearByMedia::onClickParcelAudioPlay, this));
- mCommitCallbackRegistrar.add("ParcelAudioCtrl.Stop", boost::bind(&LLPanelNearByMedia::onClickParcelAudioStop, this));
- mCommitCallbackRegistrar.add("ParcelAudioCtrl.Pause", boost::bind(&LLPanelNearByMedia::onClickParcelAudioPause, this));
+ mCommitCallbackRegistrar.add("SelectedMediaCtrl.Stop", boost::bind(&LLPanelNearByMedia::onClickSelectedMediaStop, this));
+ mCommitCallbackRegistrar.add("SelectedMediaCtrl.Play", boost::bind(&LLPanelNearByMedia::onClickSelectedMediaPlay, this));
+ mCommitCallbackRegistrar.add("SelectedMediaCtrl.Pause", boost::bind(&LLPanelNearByMedia::onClickSelectedMediaPause, this));
+ mCommitCallbackRegistrar.add("SelectedMediaCtrl.Mute", boost::bind(&LLPanelNearByMedia::onClickSelectedMediaMute, this));
+ mCommitCallbackRegistrar.add("SelectedMediaCtrl.Volume", boost::bind(&LLPanelNearByMedia::onCommitSelectedMediaVolume, this));
+ mCommitCallbackRegistrar.add("SelectedMediaCtrl.Zoom", boost::bind(&LLPanelNearByMedia::onClickSelectedMediaZoom, this));
+ mCommitCallbackRegistrar.add("SelectedMediaCtrl.Unzoom", boost::bind(&LLPanelNearByMedia::onClickSelectedMediaUnzoom, this));
+
LLUICtrlFactory::instance().buildPanel(this, "panel_nearby_media.xml");
}
@@ -121,18 +120,19 @@ BOOL LLPanelNearByMedia::postBuild()
mMediaList = getChild<LLScrollListCtrl>("media_list");
mEnableAllCtrl = getChild<LLUICtrl>("all_nearby_media_enable_btn");
mDisableAllCtrl = getChild<LLUICtrl>("all_nearby_media_disable_btn");
- mParcelMediaVolumeSlider = getChild<LLSliderCtrl>("parcel_media_volume");
- mParcelMediaMuteCtrl = getChild<LLButton>("parcel_media_mute");
- mEnableParcelMediaCtrl = getChild<LLUICtrl>("parcel_media_enable_btn");
- mDisableParcelMediaCtrl = getChild<LLUICtrl>("parcel_media_disable_btn");
mItemCountText = getChild<LLTextBox>("media_item_count");
- mParcelMediaPlayCtrl = getChild<LLButton>("parcel_media_play_btn");
- mParcelMediaPauseCtrl = getChild<LLButton>("parcel_media_pause_btn");
- mParcelMediaCtrl = getChild<LLUICtrl>("parcel_media_ctrls");
- mParcelAudioPlayCtrl = getChild<LLButton>("parcel_audio_play_btn");
- mParcelAudioPauseCtrl = getChild<LLButton>("parcel_audio_pause_btn");
- mParcelAudioCtrl = getChild<LLUICtrl>("parcel_audio_ctrls");
mShowCtrl = getChild<LLComboBox>("show_combo");
+
+ // Dynamic (selection-dependent) controls
+ mStopCtrl = getChild<LLUICtrl>("stop");
+ mPlayCtrl = getChild<LLUICtrl>("play");
+ mPauseCtrl = getChild<LLUICtrl>("pause");
+ mMuteCtrl = getChild<LLUICtrl>("mute");
+ mVolumeSliderCtrl = getChild<LLUICtrl>("volume_slider_ctrl");
+ mZoomCtrl = getChild<LLUICtrl>("zoom");
+ mUnzoomCtrl = getChild<LLUICtrl>("unzoom");
+ mVolumeSlider = getChild<LLSlider>("volume_slider");
+ mMuteBtn = getChild<LLButton>("mute_btn");
mEmptyNameString = getString("empty_item_text");
mParcelMediaName = getString("parcel_media_name");
@@ -142,7 +142,9 @@ BOOL LLPanelNearByMedia::postBuild()
mMediaList->setDoubleClickCallback(onZoomMedia, this);
mMediaList->sortByColumnIndex(PROXIMITY_COLUMN, TRUE);
mMediaList->sortByColumnIndex(VISIBILITY_COLUMN, FALSE);
+
refreshList();
+ updateControls();
updateColumns();
LLView* minimized_controls = getChildView("minimized_controls");
@@ -234,6 +236,7 @@ void LLPanelNearByMedia::draw()
mItemCountText->setValue(llformat(getString("media_item_count_format").c_str(), mMediaList->getItemCount()));
refreshList();
+ updateControls();
F32 alpha = mHoverTimer.getStarted()
? clamp_rescale(mHoverTimer.getElapsedTimeF32(), AUTO_CLOSE_FADE_TIME_START, AUTO_CLOSE_FADE_TIME_END, 1.f, 0.f)
@@ -527,10 +530,12 @@ void LLPanelNearByMedia::refreshParcelItems()
mMediaList->setNeedsSort(true);
}
}
- else if (NULL != mParcelMediaItem) {
- removeListItem(PARCEL_MEDIA_LIST_ITEM_UUID);
- mParcelMediaItem = NULL;
- mMediaList->setNeedsSort(true);
+ else {
+ if (NULL != mParcelMediaItem) {
+ removeListItem(PARCEL_MEDIA_LIST_ITEM_UUID);
+ mParcelMediaItem = NULL;
+ mMediaList->setNeedsSort(true);
+ }
}
// ... then update it
@@ -538,7 +543,7 @@ void LLPanelNearByMedia::refreshParcelItems()
{
std::string name, url, tooltip;
getNameAndUrlHelper(LLViewerParcelMedia::getParcelMedia(), name, url, "");
- if (name.empty())
+ if (name.empty() || name == url)
{
tooltip = url;
}
@@ -567,10 +572,12 @@ void LLPanelNearByMedia::refreshParcelItems()
mMediaList->setNeedsSort(true);
}
}
- else if (NULL != mParcelAudioItem) {
- removeListItem(PARCEL_AUDIO_LIST_ITEM_UUID);
- mParcelAudioItem = NULL;
- mMediaList->setNeedsSort(true);
+ else {
+ if (NULL != mParcelAudioItem) {
+ removeListItem(PARCEL_AUDIO_LIST_ITEM_UUID);
+ mParcelAudioItem = NULL;
+ mMediaList->setNeedsSort(true);
+ }
}
// ... then update it
@@ -716,12 +723,14 @@ void LLPanelNearByMedia::updateColumns()
{
if (!mDebugInfoVisible)
{
+ if (mMediaList->getColumn(CHECKBOX_COLUMN)) mMediaList->getColumn(VISIBILITY_COLUMN)->setWidth(-1);
if (mMediaList->getColumn(VISIBILITY_COLUMN)) mMediaList->getColumn(VISIBILITY_COLUMN)->setWidth(-1);
if (mMediaList->getColumn(PROXIMITY_COLUMN)) mMediaList->getColumn(PROXIMITY_COLUMN)->setWidth(-1);
if (mMediaList->getColumn(CLASS_COLUMN)) mMediaList->getColumn(CLASS_COLUMN)->setWidth(-1);
if (mMediaList->getColumn(DEBUG_COLUMN)) mMediaList->getColumn(DEBUG_COLUMN)->setWidth(-1);
}
else {
+ if (mMediaList->getColumn(CHECKBOX_COLUMN)) mMediaList->getColumn(VISIBILITY_COLUMN)->setWidth(20);
if (mMediaList->getColumn(VISIBILITY_COLUMN)) mMediaList->getColumn(VISIBILITY_COLUMN)->setWidth(20);
if (mMediaList->getColumn(PROXIMITY_COLUMN)) mMediaList->getColumn(PROXIMITY_COLUMN)->setWidth(30);
if (mMediaList->getColumn(CLASS_COLUMN)) mMediaList->getColumn(CLASS_COLUMN)->setWidth(20);
@@ -778,7 +787,7 @@ bool LLPanelNearByMedia::setDisabled(const LLUUID &row_id, bool disabled)
LLViewerMediaImpl* impl = LLViewerMedia::getMediaImplFromTextureID(row_id);
if(impl)
{
- impl->setDisabled(disabled);
+ impl->setDisabled(disabled, true);
return true;
}
}
@@ -794,23 +803,6 @@ void LLPanelNearByMedia::onZoomMedia(void* user_data)
LLViewerMediaFocus::getInstance()->focusZoomOnMedia(media_id);
}
-void LLPanelNearByMedia::onClickMuteParcelMedia()
-{
- if (LLViewerParcelMedia::getParcelMedia())
- {
- bool muted = mParcelMediaMuteCtrl->getValue();
- LLViewerParcelMedia::getParcelMedia()->setVolume(muted ? (F32)0 : mParcelMediaVolumeSlider->getValueF32() );
- }
-}
-
-void LLPanelNearByMedia::onParcelMediaVolumeSlider()
-{
- if (LLViewerParcelMedia::getParcelMedia())
- {
- LLViewerParcelMedia::getParcelMedia()->setVolume(mParcelMediaVolumeSlider->getValueF32());
- }
-}
-
void LLPanelNearByMedia::onClickParcelMediaPlay()
{
LLViewerParcelMedia::play(LLViewerParcelMgr::getInstance()->getAgentParcel());
@@ -941,7 +933,226 @@ void LLPanelNearByMedia::onMoreLess()
setShape(new_rect);
}
+
+void LLPanelNearByMedia::updateControls()
+{
+ LLUUID selected_media_id = mMediaList->getValue().asUUID();
+
+ if (selected_media_id == PARCEL_AUDIO_LIST_ITEM_UUID)
+ {
+ showTimeBasedControls(LLViewerMedia::isParcelAudioPlaying(),
+ false, // include_zoom
+ false, // is_zoomed
+ gSavedSettings.getBOOL("MuteMusic"),
+ gSavedSettings.getF32("AudioLevelMusic") );
+ }
+ else if (selected_media_id == PARCEL_MEDIA_LIST_ITEM_UUID)
+ {
+ if (!LLViewerMedia::hasParcelMedia())
+ {
+ // Shouldn't happen, but do this anyway
+ showDisabledControls();
+ }
+ else {
+ LLViewerMediaImpl* impl = LLViewerParcelMedia::getParcelMedia();
+ if (NULL == impl)
+ {
+ // Just means it hasn't started yet
+ showBasicControls(false, false, false);
+ }
+ else if (impl->isMediaTimeBased())
+ {
+ showTimeBasedControls(impl->isMediaPlaying(),
+ false, // include_zoom
+ false, // is_zoomed
+ impl->getVolume() == 0.0,
+ impl->getVolume() );
+ }
+ else {
+ // non-time-based parcel media
+ showBasicControls(LLViewerMedia::isParcelMediaPlaying(), false, false);
+ }
+ }
+ }
+ else {
+ LLViewerMediaImpl* impl = LLViewerMedia::getMediaImplFromTextureID(selected_media_id);
+ if (NULL == impl)
+ {
+ showDisabledControls();
+ }
+ else {
+ if (impl->isMediaTimeBased())
+ {
+ showTimeBasedControls(impl->isMediaPlaying(),
+ ! impl->isParcelMedia(), // include_zoom
+ LLViewerMediaFocus::getInstance()->isZoomed(),
+ impl->getVolume() == 0.0,
+ impl->getVolume());
+ }
+ else {
+ showBasicControls(!impl->isMediaDisabled(),
+ ! impl->isParcelMedia(), // include_zoom
+ LLViewerMediaFocus::getInstance()->isZoomed());
+ }
+ }
+ }
+}
+
+void LLPanelNearByMedia::showBasicControls(bool playing, bool include_zoom, bool is_zoomed)
+{
+ mStopCtrl->setVisible(playing);
+ mPlayCtrl->setVisible(!playing);
+ mPauseCtrl->setVisible(false);
+ mMuteCtrl->setVisible(false);
+ mVolumeSliderCtrl->setVisible(false);
+ mZoomCtrl->setVisible(include_zoom && !is_zoomed);
+ mUnzoomCtrl->setVisible(include_zoom && is_zoomed);
+ mStopCtrl->setEnabled(true);
+ mZoomCtrl->setEnabled(true);
+}
+
+void LLPanelNearByMedia::showTimeBasedControls(bool playing, bool include_zoom, bool is_zoomed, bool muted, F32 volume)
+{
+ mStopCtrl->setVisible(true);
+ mPlayCtrl->setVisible(!playing);
+ mPauseCtrl->setVisible(playing);
+ mMuteCtrl->setVisible(true);
+ mVolumeSliderCtrl->setVisible(true);
+ mZoomCtrl->setVisible(include_zoom);
+ mZoomCtrl->setVisible(include_zoom && !is_zoomed);
+ mUnzoomCtrl->setVisible(include_zoom && is_zoomed);
+ mStopCtrl->setEnabled(true);
+ mZoomCtrl->setEnabled(true);
+ mMuteBtn->setValue(muted);
+ mVolumeSlider->setValue(volume);
+}
+
+void LLPanelNearByMedia::showDisabledControls()
+{
+ mStopCtrl->setVisible(true);
+ mPlayCtrl->setVisible(false);
+ mPauseCtrl->setVisible(false);
+ mMuteCtrl->setVisible(false);
+ mVolumeSliderCtrl->setVisible(false);
+ mZoomCtrl->setVisible(true);
+ mUnzoomCtrl->setVisible(false);
+ mStopCtrl->setEnabled(false);
+ mZoomCtrl->setEnabled(false);
+}
+
+void LLPanelNearByMedia::onClickSelectedMediaStop()
+{
+ setDisabled(mMediaList->getValue().asUUID(), true);
+}
+
+void LLPanelNearByMedia::onClickSelectedMediaPlay()
+{
+ LLUUID selected_media_id = mMediaList->getValue().asUUID();
+
+ // First enable it
+ setDisabled(selected_media_id, false);
+
+ // Special code to make play "unpause" if time-based and playing
+ if (selected_media_id != PARCEL_AUDIO_LIST_ITEM_UUID)
+ {
+ LLViewerMediaImpl *impl = (selected_media_id == PARCEL_MEDIA_LIST_ITEM_UUID) ?
+ ((LLViewerMediaImpl*)LLViewerParcelMedia::getParcelMedia()) : LLViewerMedia::getMediaImplFromTextureID(selected_media_id);
+ if (NULL != impl && impl->isMediaTimeBased() && impl->isMediaPaused())
+ {
+ // Aha! It's really time-based media that's paused, so unpause
+ impl->play();
+ return;
+ }
+ else if (impl->isParcelMedia())
+ {
+ LLViewerParcelMedia::play(LLViewerParcelMgr::getInstance()->getAgentParcel());
+ }
+ }
+}
+
+void LLPanelNearByMedia::onClickSelectedMediaPause()
+{
+ LLUUID selected_media_id = mMediaList->getValue().asUUID();
+ if (selected_media_id == PARCEL_AUDIO_LIST_ITEM_UUID)
+ {
+ onClickParcelAudioPause();
+ }
+ else if (selected_media_id == PARCEL_MEDIA_LIST_ITEM_UUID)
+ {
+ onClickParcelMediaPause();
+ }
+ else {
+ LLViewerMediaImpl* impl = LLViewerMedia::getMediaImplFromTextureID(selected_media_id);
+ if (NULL != impl && impl->isMediaTimeBased() && impl->isMediaPlaying())
+ {
+ impl->pause();
+ }
+ }
+}
+
+void LLPanelNearByMedia::onClickSelectedMediaMute()
+{
+ LLUUID selected_media_id = mMediaList->getValue().asUUID();
+ if (selected_media_id == PARCEL_AUDIO_LIST_ITEM_UUID)
+ {
+ gSavedSettings.setBOOL("MuteMusic", mMuteBtn->getValue());
+ }
+ else {
+ LLViewerMediaImpl* impl = (selected_media_id == PARCEL_MEDIA_LIST_ITEM_UUID) ?
+ ((LLViewerMediaImpl*)LLViewerParcelMedia::getParcelMedia()) : LLViewerMedia::getMediaImplFromTextureID(selected_media_id);
+ if (NULL != impl && impl->isMediaTimeBased())
+ {
+ F32 volume = impl->getVolume();
+ if(volume > 0.0)
+ {
+ impl->setVolume(0.0);
+ }
+ else if (mVolumeSlider->getValueF32() == 0.0)
+ {
+ impl->setVolume(1.0);
+ mVolumeSlider->setValue(1.0);
+ }
+ else
+ {
+ impl->setVolume(mVolumeSlider->getValueF32());
+ }
+ }
+ }
+}
+
+void LLPanelNearByMedia::onCommitSelectedMediaVolume()
+{
+ LLUUID selected_media_id = mMediaList->getValue().asUUID();
+ if (selected_media_id == PARCEL_AUDIO_LIST_ITEM_UUID)
+ {
+ F32 vol = mVolumeSlider->getValueF32();
+ gSavedSettings.setF32("AudioLevelMusic", vol);
+ }
+ else {
+ LLViewerMediaImpl* impl = (selected_media_id == PARCEL_MEDIA_LIST_ITEM_UUID) ?
+ ((LLViewerMediaImpl*)LLViewerParcelMedia::getParcelMedia()) : LLViewerMedia::getMediaImplFromTextureID(selected_media_id);
+ if (NULL != impl && impl->isMediaTimeBased())
+ {
+ impl->setVolume(mVolumeSlider->getValueF32());
+ }
+ }
+}
+
+void LLPanelNearByMedia::onClickSelectedMediaZoom()
+{
+ LLUUID selected_media_id = mMediaList->getValue().asUUID();
+ if (selected_media_id == PARCEL_AUDIO_LIST_ITEM_UUID || selected_media_id == PARCEL_MEDIA_LIST_ITEM_UUID)
+ return;
+ LLViewerMediaFocus::getInstance()->focusZoomOnMedia(selected_media_id);
+}
+
+void LLPanelNearByMedia::onClickSelectedMediaUnzoom()
+{
+ LLViewerMediaFocus::getInstance()->unZoom();
+}
+
+
// static
void LLPanelNearByMedia::getNameAndUrlHelper(LLViewerMediaImpl* impl, std::string& name, std::string & url, const std::string &defaultName)
{
diff --git a/indra/newview/llpanelnearbymedia.h b/indra/newview/llpanelnearbymedia.h
index 654a8544af..eedfd447de 100644
--- a/indra/newview/llpanelnearbymedia.h
+++ b/indra/newview/llpanelnearbymedia.h
@@ -38,6 +38,7 @@
class LLPanelNearbyMedia;
class LLButton;
class LLScrollListCtrl;
+class LLSlider;
class LLSliderCtrl;
class LLCheckBoxCtrl;
class LLTextBox;
@@ -134,23 +135,37 @@ private:
bool shouldShow(LLViewerMediaImpl* impl);
+ void showBasicControls(bool playing, bool include_zoom, bool is_zoomed);
+ void showTimeBasedControls(bool playing, bool include_zoom, bool is_zoomed, bool muted, F32 volume);
+ void showDisabledControls();
+ void updateControls();
+
+ void onClickSelectedMediaStop();
+ void onClickSelectedMediaPlay();
+ void onClickSelectedMediaPause();
+ void onClickSelectedMediaMute();
+ void onCommitSelectedMediaVolume();
+ void onClickSelectedMediaZoom();
+ void onClickSelectedMediaUnzoom();
+
LLUICtrl* mNearbyMediaPanel;
- LLScrollListCtrl* mMediaList;
+ LLTextBox* mItemCountText;
+ LLScrollListCtrl* mMediaList;
LLUICtrl* mEnableAllCtrl;
LLUICtrl* mDisableAllCtrl;
- LLSliderCtrl* mParcelMediaVolumeSlider;
- LLButton* mParcelMediaMuteCtrl;
- LLUICtrl* mEnableParcelMediaCtrl;
- LLUICtrl* mDisableParcelMediaCtrl;
- LLTextBox* mItemCountText;
- LLUICtrl* mParcelMediaCtrl;
- LLUICtrl* mParcelMediaPlayCtrl;
- LLUICtrl* mParcelMediaPauseCtrl;
- LLUICtrl* mParcelAudioCtrl;
- LLUICtrl* mParcelAudioPlayCtrl;
- LLUICtrl* mParcelAudioPauseCtrl;
LLComboBox* mShowCtrl;
+ // Dynamic (selection-dependent) controls
+ LLUICtrl* mStopCtrl;
+ LLUICtrl* mPlayCtrl;
+ LLUICtrl* mPauseCtrl;
+ LLUICtrl* mMuteCtrl;
+ LLUICtrl* mVolumeSliderCtrl;
+ LLUICtrl* mZoomCtrl;
+ LLUICtrl* mUnzoomCtrl;
+ LLSlider* mVolumeSlider;
+ LLButton* mMuteBtn;
+
bool mAllMediaDisabled;
bool mDebugInfoVisible;
bool mParcelAudioAutoStart;
@@ -159,11 +174,11 @@ private:
std::string mParcelMediaName;
std::string mParcelAudioName;
- S32 mMoreHeight;
- S32 mLessHeight;
- LLFrameTimer mHoverTimer;
- LLScrollListItem* mParcelMediaItem;
- LLScrollListItem* mParcelAudioItem;
+ S32 mMoreHeight;
+ S32 mLessHeight;
+ LLFrameTimer mHoverTimer;
+ LLScrollListItem* mParcelMediaItem;
+ LLScrollListItem* mParcelAudioItem;
};
diff --git a/indra/newview/llpanelprimmediacontrols.h b/indra/newview/llpanelprimmediacontrols.h
index 743cec70a1..2e0de7866c 100644
--- a/indra/newview/llpanelprimmediacontrols.h
+++ b/indra/newview/llpanelprimmediacontrols.h
@@ -58,6 +58,16 @@ public:
void updateShape();
bool isMouseOver();
+
+ enum EZoomLevel
+ {
+ ZOOM_NONE = 0,
+ ZOOM_FAR,
+ ZOOM_MEDIUM,
+ ZOOM_NEAR
+ };
+
+ EZoomLevel getZoomLevel() const { return mCurrentZoom; }
void nextZoomLevel();
void resetZoomLevel(bool reset_camera = true);
void close();
@@ -66,13 +76,6 @@ public:
void setMediaFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal = LLVector3::zero);
- enum EZoomLevel
- {
- ZOOM_NONE = 0,
- ZOOM_FAR,
- ZOOM_MEDIUM,
- ZOOM_NEAR
- };
static const EZoomLevel kZoomLevels[];
static const int kNumZoomLevels;
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 7b5d1d9814..3fc578aa5e 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -939,12 +939,12 @@ void LLViewerMedia::setAllMediaEnabled(bool val)
// Also do Parcel Media and Parcel Audio
if (val)
{
- if (!LLViewerMedia::isParcelMediaPlaying())
+ if (!LLViewerMedia::isParcelMediaPlaying() && LLViewerMedia::hasParcelMedia())
{
LLViewerParcelMedia::play(LLViewerParcelMgr::getInstance()->getAgentParcel());
}
- if (!LLViewerMedia::isParcelAudioPlaying() && gAudiop)
+ if (!LLViewerMedia::isParcelAudioPlaying() && gAudiop && LLViewerMedia::hasParcelAudio())
{
gAudiop->startInternetStream(LLViewerMedia::getParcelAudioURL());
}
@@ -2246,7 +2246,7 @@ void LLViewerMediaImpl::resetPreviousMediaState()
//////////////////////////////////////////////////////////////////////////////////////////
//
-void LLViewerMediaImpl::setDisabled(bool disabled)
+void LLViewerMediaImpl::setDisabled(bool disabled, bool forcePlayOnEnable)
{
if(mIsDisabled != disabled)
{
@@ -2261,7 +2261,7 @@ void LLViewerMediaImpl::setDisabled(bool disabled)
else
{
// We just (re)enabled this media. Do a navigate if auto-play is in order.
- if(isAutoPlayable())
+ if(isAutoPlayable() || forcePlayOnEnable)
{
navigateTo(mMediaEntryURL, "", true, true);
}
diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h
index ec25744fa2..9dbffa78b3 100644
--- a/indra/newview/llviewermedia.h
+++ b/indra/newview/llviewermedia.h
@@ -230,7 +230,7 @@ public:
void setMediaFailed(bool val) { mMediaSourceFailed = val; }
void resetPreviousMediaState();
- void setDisabled(bool disabled);
+ void setDisabled(bool disabled, bool forcePlayOnEnable = false);
bool isMediaDisabled() const { return mIsDisabled; };
void setInNearbyMediaList(bool in_list) { mInNearbyMediaList = in_list; }
diff --git a/indra/newview/llviewermediafocus.cpp b/indra/newview/llviewermediafocus.cpp
index f508a3462a..88e7cfec86 100644
--- a/indra/newview/llviewermediafocus.cpp
+++ b/indra/newview/llviewermediafocus.cpp
@@ -559,6 +559,19 @@ void LLViewerMediaFocus::focusZoomOnMedia(LLUUID media_id)
}
}
+void LLViewerMediaFocus::unZoom()
+{
+ if(mMediaControls.get())
+ {
+ mMediaControls.get()->resetZoomLevel();
+ }
+}
+
+bool LLViewerMediaFocus::isZoomed() const
+{
+ return (mMediaControls.get() && mMediaControls.get()->getZoomLevel() != LLPanelPrimMediaControls::ZOOM_NONE);
+}
+
LLUUID LLViewerMediaFocus::getControlsMediaID()
{
if(getFocusedMediaImpl())
diff --git a/indra/newview/llviewermediafocus.h b/indra/newview/llviewermediafocus.h
index 002044ea2e..d9ddc7432b 100644
--- a/indra/newview/llviewermediafocus.h
+++ b/indra/newview/llviewermediafocus.h
@@ -85,6 +85,9 @@ public:
// Try to focus/zoom on the specified media (if it's on an object in world).
void focusZoomOnMedia(LLUUID media_id);
+ // Are we zoomed in?
+ bool isZoomed() const;
+ void unZoom();
// Return the ID of the media instance the controls are currently attached to (either focus or hover).
LLUUID getControlsMediaID();
diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp
index 0c0936c103..1f6bbcbae8 100644
--- a/indra/newview/llviewerparcelmgr.cpp
+++ b/indra/newview/llviewerparcelmgr.cpp
@@ -1800,7 +1800,8 @@ void optionally_start_music(const std::string& music_url)
nearby_media_panel->getParcelAudioAutoStart()) ||
// or they have expressed no opinion in the UI, but have autoplay on...
(!nearby_media_panel &&
- gSavedSettings.getBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING)))
+ gSavedSettings.getBOOL(LLViewerMedia::AUTO_PLAY_MEDIA_SETTING) &&
+ gSavedSettings.getBOOL("MediaTentativeAutoPlay")))
{
llinfos << "Starting parcel music " << music_url << llendl;
gAudiop->startInternetStream(music_url);
diff --git a/indra/newview/skins/default/xui/en/panel_nearby_media.xml b/indra/newview/skins/default/xui/en/panel_nearby_media.xml
index f332ab273d..4a71be370e 100644
--- a/indra/newview/skins/default/xui/en/panel_nearby_media.xml
+++ b/indra/newview/skins/default/xui/en/panel_nearby_media.xml
@@ -2,11 +2,11 @@
<panel
can_resize="true"
can_close="false"
- background_opaque="true"
- background_visible="true"
+ background_opaque="true"
+ background_visible="true"
layout="topleft"
width="270"
- height="290"
+ height="325"
name="nearby_media"
help_topic="nearby_media">
<string name="media_item_count_format">(%ld media items)</string>
@@ -14,241 +14,463 @@
<string name="parcel_media_name">Parcel Streaming Media</string>
<string name="parcel_audio_name">Parcel Streaming Audio</string>
<string name="playing_suffix">(playing)</string>
- <panel
- bevel_style="in"
- bg_alpha_color="0 0 0 0"
- bg_opaque_color="0 0 0 0.3"
- bg_opaque_image="Toast_Background"
- follows="left|right|top"
- top="0"
- height="30"
- name="minimized_controls"
- left="0">
- <button
- name="all_nearby_media_disable_btn"
- follows="left"
- tool_tip="Turn all nearby media off"
+ <panel
+ bevel_style="in"
+ bg_alpha_color="0 0 0 0"
+ bg_opaque_color="0 0 0 0.3"
+ bg_opaque_image="Toast_Background"
+ follows="left|right|top"
+ top="0"
+ height="30"
+ name="minimized_controls"
+ left="0">
+ <button
+ name="all_nearby_media_disable_btn"
+ follows="left"
+ tool_tip="Turn all nearby media off"
left="15"
width="60"
- height="22"
+ height="22"
label="Stop All">
- <button.commit_callback
- function="MediaListCtrl.DisableAll" />
- </button>
- <button
+ <button.commit_callback
+ function="MediaListCtrl.DisableAll" />
+ </button>
+ <button
name="all_nearby_media_enable_btn"
- follows="left"
+ follows="left"
tool_tip="Turn all nearby media on"
- left_pad="4"
+ left_pad="4"
width="60"
- height="22"
+ height="22"
label="Start All">
- <button.commit_callback
+ <button.commit_callback
function="MediaListCtrl.EnableAll" />
- </button>
- <button
+ </button>
+ <button
name="open_prefs_btn"
image_overlay="Icon_Gear_Foreground"
- image_disabled="PushButton_Disabled"
- image_disabled_selected="PushButton_Disabled"
- image_selected="PushButton_Selected"
- image_unselected="PushButton_Off"
- hover_glow_amount="0.15"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ hover_glow_amount="0.15"
tool_tip = "Bring up media prefs"
top_delta="0"
left_pad="4"
- height="22"
+ height="22"
min_width="28"
width="28">
- <button.commit_callback
+ <button.commit_callback
function="MediaListCtrl.GoMediaPrefs" />
- </button>
- <button
+ </button>
+ <button
name="more_less_btn"
follows="right"
tool_tip="Advanced Controls"
top_delta="0"
right="-10"
width="60"
- height="22"
+ height="22"
toggle="true"
label="More &gt;&gt;"
label_selected="Less &lt;&lt;">
- <button.commit_callback
+ <button.commit_callback
function="MediaListCtrl.MoreLess" />
- </button>
- </panel>
- <panel
+ </button>
+ </panel>
+ <panel
name="nearby_media_panel"
- bevel_style="in"
- border_style="line"
- bg_alpha_color="0 0 0 0"
- bg_opaque_color="0 0 0 0.3"
- follows="left|right|top|bottom"
+ bevel_style="in"
+ border_style="line"
+ bg_alpha_color="0 0 0 0"
+ bg_opaque_color="0 0 0 0.3"
+ follows="left|right|top|bottom"
top_delta="30"
- right="-1"
- left="0"
- height="230">
- <text
- type="string"
- length="1"
+ right="-1"
+ left="0"
+ height="295">
+ <text
+ type="string"
+ length="1"
follows="top|left"
font="SansSerif"
left="10"
width="100">
- Nearby Media
- </text>
-<!-- nix for now
- <text
- bottom_delta="1"
- type="string"
- follows="top|left|right"
- font="SansSerif"
- font.style="ITALIC"
- font.size="Small"
- name="media_item_count"
- left="115"
- right="-10">
- (?? media items)
- </text>
--->
- <text
- type="string"
- length="1"
+ Nearby Media
+ </text>
+ <!-- nix for now
+ <text
+ bottom_delta="1"
+ type="string"
+ follows="top|left|right"
+ font="SansSerif"
+ font.style="ITALIC"
+ font.size="Small"
+ name="media_item_count"
+ left="115"
+ right="-10">
+ (?? media items)
+ </text>
+ -->
+ <text
+ type="string"
+ length="1"
follows="top|left"
- font="SansSerif"
- top_pad="15"
+ font="SansSerif"
+ top_pad="15"
left="10"
width="40">
- Show:
- </text>
- <combo_box
- height="23"
- left="50"
+ Show:
+ </text>
+ <combo_box
+ height="23"
+ left="50"
width="140"
- top_delta="-5"
+ top_delta="-5"
follows="left|top"
- name="show_combo">
- <combo_box.item
- label="All"
- value="0"
- name="All" />
- <combo_box.item
- label="In this Parcel"
- value="2"
- name="WithinParcel" />
- <combo_box.item
- label="Outside this Parcel"
- value="3"
- name="OutsideParcel" />
- <combo_box.item
- label="On other Avatars"
- value="4"
- ame="OnOthers" />
- </combo_box>
- <scroll_list
- follows="left|top|bottom|right"
- column_padding="0"
+ name="show_combo">
+ <combo_box.item
+ label="All"
+ value="0"
+ name="All" />
+ <combo_box.item
+ label="In this Parcel"
+ value="2"
+ name="WithinParcel" />
+ <combo_box.item
+ label="Outside this Parcel"
+ value="3"
+ name="OutsideParcel" />
+ <combo_box.item
+ label="On other Avatars"
+ value="4"
+ ame="OnOthers" />
+ </combo_box>
+ <scroll_list
+ follows="left|top|bottom|right"
+ column_padding="0"
height="100"
- draw_heading="false"
- draw_stripes="true"
- bg_stripe_color="0.25 0.25 0.25 0.25"
- top_pad="8"
+ draw_heading="false"
+ draw_stripes="true"
+ bg_stripe_color="0.25 0.25 0.25 0.25"
+ top_pad="8"
+ left="10"
+ right="-10"
+ name="media_list">
+ <scroll_list.columns
+ type="checkbox"
+ width="-1"
+ label=""
+ name="media_checkbox_ctrl" />
+ <scroll_list.columns
+ sort_column="media_proximity"
+ width="-1"
+ label="Proximity"
+ name="media_proximity" />
+ <scroll_list.columns
+ sort_column="media_visibility"
+ width="-1"
+ label="Visible"
+ name="media_visibility" />
+ <scroll_list.columns
+ sort_column="media_class"
+ width="-1"
+ label="Class"
+ name="media_class" />
+ <scroll_list.columns
+ label="Name"
+ name="media_name" />
+ <scroll_list.columns
+ sort_column="media_debug"
+ width="-1"
+ label="Debug"
+ name="media_debug" />
+ </scroll_list>
+ <panel
+ bevel_style="in"
+ background_visible="true"
+ bg_alpha_color="0.0 0.0 0.0 1.0"
+ bg_opaque_color="0 0 0 0.3"
+ follows="left|right|bottom"
+ top_pad="5"
+ height="30"
+ left="10"
+ right="-10">
+ <layout_stack
+ name="media_controls"
+ follows="left|right|top"
+ animate="false"
+ height="75"
+ layout="topleft"
+ top="4"
left="10"
right="-10"
- name="media_list">
- <scroll_list.columns
- type="checkbox"
- width="20"
- label=""
- name="media_checkbox_ctrl" />
- <scroll_list.columns
- sort_column="media_proximity"
- width="-1"
- label="Proximity"
- name="media_proximity" />
- <scroll_list.columns
- sort_column="media_visibility"
- width="-1"
- label="Visible"
- name="media_visibility" />
- <scroll_list.columns
- sort_column="media_class"
- width="-1"
- label="Class"
- name="media_class" />
- <scroll_list.columns
- label="Name"
- name="media_name" />
- <scroll_list.columns
- sort_column="media_debug"
- width="-1"
- label="Debug"
- name="media_debug" />
- </scroll_list>
- <panel
- bevel_style="in"
- background_visible="true"
- bg_alpha_color="0.0 0.0 0.0 1.0"
- bg_opaque_color="0 0 0 0.3"
- follows="left|right|bottom"
+ border_size="0"
+ mouse_opaque="false"
+ orientation="horizontal">
+ <layout_panel
+ name="stop"
+ mouse_opaque="false"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="0"
+ height="22"
+ min_width="22"
+ width="22">
+ <button
+ name="stop_btn"
+ follows="top"
+ image_overlay="Stop_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ hover_glow_amount="0.15"
+ layout="topleft"
+ tool_tip="Stop selected media"
+ top="0"
+ height="22"
+ width="22">
+ <button.commit_callback
+ function="SelectedMediaCtrl.Stop" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="play"
+ mouse_opaque="false"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="0"
+ height="22"
+ min_width="22"
+ width="22">
+ <button
+ name="play_btn"
+ follows="top"
+ image_overlay="Play_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ hover_glow_amount="0.15"
+ layout="topleft"
+ tool_tip = "Play selected media"
+ top="0"
+ height="22"
+ width="22">
+ <button.commit_callback
+ function="SelectedMediaCtrl.Play" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="pause"
+ mouse_opaque="false"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="0"
+ min_width="22"
+ width="22">
+ <button
+ name="pause_btn"
+ follows="top"
+ image_overlay="Pause_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ hover_glow_amount="0.15"
+ layout="topleft"
+ top="0"
+ height="22"
+ width="22"
+ tool_tip = "Pause selected media">
+ <button.commit_callback
+ function="SelectedMediaCtrl.Pause" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="volume_slider_ctrl"
+ mouse_opaque="false"
+ auto_resize="true"
+ user_resize="false"
+ follows="left|right"
+ layout="topleft"
+ top="0"
+ height="22"
+ min_width="100"
+ width="200">
+ <slider_bar
+ name="volume_slider"
+ follows="left|right|top"
+ top="0"
+ height="22"
+ increment="0.01"
+ initial_value="0.5"
+ layout="topleft"
+ tool_tip="Audio volume for selected media"
+ width="200">
+ <slider_bar.commit_callback
+ function="SelectedMediaCtrl.Volume" />
+ </slider_bar>
+ </layout_panel>
+ <layout_panel
+ name="mute"
+ mouse_opaque="false"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="0"
+ height="72"
+ min_width="22"
+ width="22">
+ <button
+ name="mute_btn"
+ follows="top"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="AudioMute_Off"
+ image_unselected="Audio_Off"
+ hover_glow_amount="0.15"
+ is_toggle="true"
+ layout="topleft"
+ scale_image="false"
+ tool_tip="Mute audio on selected media"
+ top="0"
+ height="20"
+ width="22" >
+ <button.commit_callback
+ function="SelectedMediaCtrl.Mute" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="zoom"
+ mouse_opaque="false"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="0"
+ height="28"
+ min_width="22"
+ width="22">
+ <button
+ name="zoom_btn"
+ follows="top"
+ image_overlay="Zoom_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ hover_glow_amount="0.15"
+ top="0"
+ height="22"
+ layout="topleft"
+ tool_tip="Zoom into selected media"
+ width="22">
+ <button.commit_callback
+ function="SelectedMediaCtrl.Zoom" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="unzoom"
+ mouse_opaque="false"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="0"
+ min_width="21"
+ width="21" >
+ <button
+ name="unzoom_btn"
+ follows="top"
+ image_overlay="UnZoom_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ hover_glow_amount="0.15"
+ top="0"
+ height="22"
+ layout="topleft"
+ tool_tip ="Zoom back from selected media"
+ top_delta="-4"
+ width="21" >
+ <button.commit_callback
+ function="SelectedMediaCtrl.Unzoom" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="right_bookend"
+ width="0"
+ mouse_opaque="false"
+ user_resize="false" />
+ </layout_stack>
+ </panel>
+ <panel
+ bevel_style="in"
+ background_visible="true"
+ bg_alpha_color="0.0 0.0 0.0 1.0"
+ bg_opaque_color="0 0 0 0.3"
+ follows="left|right|bottom"
+ top_pad="5"
+ height="90"
+ left="10"
+ right="-10">
+ <check_box
+ name="media_enabled_btn"
+ control_name="AudioStreamingMedia"
+ value="true"
+ follows="left|bottom|right"
+ height="15"
+ tool_tip="Check this to enable all media"
+ label="All Media Enabled"
+ top="10"
+ left="10"/>
+ <check_box
+ name="media_auto_play_btn"
+ control_name="ParcelMediaAutoPlayEnable"
+ enabled_control="AudioStreamingMedia"
+ value="true"
+ follows="left|bottom|right"
+ height="15"
+ tool_tip="Check this to let media auto-play if it wants"
+ label="Allow Media to auto-play"
top_pad="5"
- height="90"
- left="10"
- right="-10">
- <check_box
- name="media_enabled_btn"
- control_name="AudioStreamingMedia"
- value="true"
- follows="left|bottom|right"
- height="15"
- tool_tip="Check this to enable all media"
- label="All Media Enabled"
- top="10"
- left="10"/>
- <check_box
- name="media_auto_play_btn"
- control_name="ParcelMediaAutoPlayEnable"
- enabled_control="AudioStreamingMedia"
- value="true"
- follows="left|bottom|right"
- height="15"
- tool_tip="Check this to let media auto-play if it wants"
- label="Allow Media to auto-play"
- top_pad="5"
- left="10"/>
-<!--
- <check_box
- name="media_show_within_parcel_btn"
- control_name="MediaShowWithinParcel"
- enabled_control="AudioStreamingMedia"
- value="true"
- follows="left|bottom|right"
- height="15"
- tool_tip="Uncheck this to hide media within the parcel you are standing in"
- label="Show media within current parcel"
- left="10"/>
--->
- <check_box
- name="media_show_outside_parcel_btn"
- control_name="MediaShowOutsideParcel"
- enabled_control="AudioStreamingMedia"
- value="true"
- follows="left|bottom|right"
- height="15"
- tool_tip="Uncheck this to hide media outside the parcel you are standing in"
- label="Show media outside current parcel"
- left="10"/>
- <check_box
- name="media_show_on_others_btn"
- control_name="MediaShowOnOthers"
- enabled_control="AudioStreamingMedia"
- value="true"
- follows="left|bottom|right"
- height="15"
- tool_tip="Uncheck this to hide media attached to other avatars nearby"
- label="Show media attached to other avatars"
- left="10"/>
- </panel>
+ left="10"/>
+ <!--
+ <check_box
+ name="media_show_within_parcel_btn"
+ control_name="MediaShowWithinParcel"
+ enabled_control="AudioStreamingMedia"
+ value="true"
+ follows="left|bottom|right"
+ height="15"
+ tool_tip="Uncheck this to hide media within the parcel you are standing in"
+ label="Show media within current parcel"
+ left="10"/>
+ -->
+ <check_box
+ name="media_show_outside_parcel_btn"
+ control_name="MediaShowOutsideParcel"
+ enabled_control="AudioStreamingMedia"
+ value="true"
+ follows="left|bottom|right"
+ height="15"
+ tool_tip="Uncheck this to hide media outside the parcel you are standing in"
+ label="Show media outside current parcel"
+ left="10"/>
+ <check_box
+ name="media_show_on_others_btn"
+ control_name="MediaShowOnOthers"
+ enabled_control="AudioStreamingMedia"
+ value="true"
+ follows="left|bottom|right"
+ height="15"
+ tool_tip="Uncheck this to hide media attached to other avatars nearby"
+ label="Show media attached to other avatars"
+ left="10"/>
</panel>
</panel>
+</panel>