diff options
43 files changed, 3701 insertions, 1218 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index bef775cdb8..63b05f5a1d 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -219,7 +219,6 @@ set(viewer_SOURCE_FILES llfloateropenobject.cpp llfloaterpay.cpp llfloaterperms.cpp - llfloaterpostcard.cpp llfloaterpostprocess.cpp llfloaterpreference.cpp llfloaterproperties.cpp @@ -393,9 +392,17 @@ set(viewer_SOURCE_FILES llpanelplaceprofile.cpp llpanelplaces.cpp llpanelplacestab.cpp + llpanelpostprogress.cpp + llpanelpostresult.cpp llpanelprimmediacontrols.cpp llpanelprofile.cpp llpanelprofileview.cpp + llpanelsnapshot.cpp + llpanelsnapshotinventory.cpp + llpanelsnapshotlocal.cpp + llpanelsnapshotoptions.cpp + llpanelsnapshotpostcard.cpp + llpanelsnapshotprofile.cpp llpanelteleporthistory.cpp llpaneltiptoast.cpp llpanelvoiceeffect.cpp @@ -414,6 +421,7 @@ set(viewer_SOURCE_FILES llpopupview.cpp llpolymesh.cpp llpolymorph.cpp + llpostcard.cpp llpreview.cpp llpreviewanim.cpp llpreviewgesture.cpp @@ -603,6 +611,7 @@ set(viewer_SOURCE_FILES llwearablelist.cpp llwearabletype.cpp llweb.cpp + llwebprofile.cpp llwebsharing.cpp llwind.cpp llwindowlistener.cpp @@ -786,7 +795,6 @@ set(viewer_HEADER_FILES llfloateropenobject.h llfloaterpay.h llfloaterperms.h - llfloaterpostcard.h llfloaterpostprocess.h llfloaterpreference.h llfloaterproperties.h @@ -957,6 +965,7 @@ set(viewer_HEADER_FILES llpanelprimmediacontrols.h llpanelprofile.h llpanelprofileview.h + llpanelsnapshot.h llpanelteleporthistory.h llpaneltiptoast.h llpanelvoicedevicesettings.h @@ -975,6 +984,7 @@ set(viewer_HEADER_FILES llpolymesh.h llpolymorph.h llpopupview.h + llpostcard.h llpreview.h llpreviewanim.h llpreviewgesture.h @@ -1164,6 +1174,7 @@ set(viewer_HEADER_FILES llwearablelist.h llwearabletype.h llweb.h + llwebprofile.h llwebsharing.h llwind.h llwindowlistener.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 5c0ea2f774..9812b2868f 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4667,6 +4667,17 @@ <string>0.0.0</string> </map> + <key>LastSnapshotToProfileHeight</key> + <map> + <key>Comment</key> + <string>The height of the last profile snapshot, in px</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>768</integer> + </map> <key>LastSnapshotToEmailHeight</key> <map> <key>Comment</key> @@ -4678,6 +4689,17 @@ <key>Value</key> <integer>768</integer> </map> + <key>LastSnapshotToProfileWidth</key> + <map> + <key>Comment</key> + <string>The width of the last profile snapshot, in px</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>1024</integer> + </map> <key>LastSnapshotToEmailWidth</key> <map> <key>Comment</key> @@ -4733,17 +4755,6 @@ <key>Value</key> <integer>512</integer> </map> - <key>LastSnapshotType</key> - <map> - <key>Comment</key> - <string>Select this as next type of snapshot to take (0 = postcard, 1 = texture, 2 = local image)</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>0</integer> - </map> <key>LeftClickShowMenu</key> <map> <key>Comment</key> @@ -10608,6 +10619,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>SnapshotProfileLastResolution</key> + <map> + <key>Comment</key> + <string>Take next profile snapshot at this resolution</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>0</integer> + </map> <key>SnapshotPostcardLastResolution</key> <map> <key>Comment</key> diff --git a/indra/newview/llfloaterpostcard.cpp b/indra/newview/llfloaterpostcard.cpp deleted file mode 100644 index 3bcbb987f7..0000000000 --- a/indra/newview/llfloaterpostcard.cpp +++ /dev/null @@ -1,384 +0,0 @@ -/** - * @file llfloaterpostcard.cpp - * @brief Postcard send floater, allows setting name, e-mail address, etc. - * - * $LicenseInfo:firstyear=2004&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llfloaterpostcard.h" - -#include "llfontgl.h" -#include "llsys.h" -#include "llgl.h" -#include "v3dmath.h" -#include "lldir.h" - -#include "llagent.h" -#include "llui.h" -#include "lllineeditor.h" -#include "llbutton.h" -#include "lltexteditor.h" -#include "llfloaterreg.h" -#include "llnotificationsutil.h" -#include "llviewercontrol.h" -#include "llviewernetwork.h" -#include "lluictrlfactory.h" -#include "lluploaddialog.h" -#include "llviewerstats.h" -#include "llviewerwindow.h" -#include "llstatusbar.h" -#include "llviewerregion.h" -#include "lleconomy.h" -#include "message.h" - -#include "llimagejpeg.h" -#include "llimagej2c.h" -#include "llvfile.h" -#include "llvfs.h" -#include "llviewertexture.h" -#include "llassetuploadresponders.h" -#include "llagentui.h" - -#include <boost/regex.hpp> //boost.regex lib - -///---------------------------------------------------------------------------- -/// Local function declarations, constants, enums, and typedefs -///---------------------------------------------------------------------------- - -///---------------------------------------------------------------------------- -/// Class LLFloaterPostcard -///---------------------------------------------------------------------------- - -LLFloaterPostcard::LLFloaterPostcard(const LLSD& key) -: LLFloater(key), - mJPEGImage(NULL), - mViewerImage(NULL), - mHasFirstMsgFocus(false) -{ -} - -// Destroys the object -LLFloaterPostcard::~LLFloaterPostcard() -{ - mJPEGImage = NULL; // deletes image -} - -BOOL LLFloaterPostcard::postBuild() -{ - // pick up the user's up-to-date email address - gAgent.sendAgentUserInfoRequest(); - - childSetAction("cancel_btn", onClickCancel, this); - childSetAction("send_btn", onClickSend, this); - - getChildView("from_form")->setEnabled(FALSE); - - std::string name_string; - LLAgentUI::buildFullname(name_string); - getChild<LLUICtrl>("name_form")->setValue(LLSD(name_string)); - - // For the first time a user focusess to .the msg box, all text will be selected. - getChild<LLUICtrl>("msg_form")->setFocusChangedCallback(boost::bind(onMsgFormFocusRecieved, _1, this)); - - getChild<LLUICtrl>("to_form")->setFocus(TRUE); - - return TRUE; -} - -// static -LLFloaterPostcard* LLFloaterPostcard::showFromSnapshot(LLImageJPEG *jpeg, LLViewerTexture *img, const LLVector2 &image_scale, const LLVector3d& pos_taken_global) -{ - // Take the images from the caller - // It's now our job to clean them up - LLFloaterPostcard* instance = LLFloaterReg::showTypedInstance<LLFloaterPostcard>("postcard", LLSD(img->getID())); - - if (instance) // may be 0 if we're in mouselook mode - { - instance->mJPEGImage = jpeg; - instance->mViewerImage = img; - instance->mImageScale = image_scale; - instance->mPosTakenGlobal = pos_taken_global; - } - - return instance; -} - -void LLFloaterPostcard::draw() -{ - LLGLSUIDefault gls_ui; - LLFloater::draw(); - - if(!isMinimized() && mViewerImage.notNull() && mJPEGImage.notNull()) - { - // Force the texture to be 100% opaque when the floater is focused. - F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency(); - LLRect rect(getRect()); - - // first set the max extents of our preview - rect.translate(-rect.mLeft, -rect.mBottom); - rect.mLeft += 320; - rect.mRight -= 10; - rect.mTop -= 27; - rect.mBottom = rect.mTop - 130; - - // then fix the aspect ratio - F32 ratio = (F32)mJPEGImage->getWidth() / (F32)mJPEGImage->getHeight(); - if ((F32)rect.getWidth() / (F32)rect.getHeight() >= ratio) - { - rect.mRight = LLRect::tCoordType((F32)rect.mLeft + ((F32)rect.getHeight() * ratio)); - } - else - { - rect.mBottom = LLRect::tCoordType((F32)rect.mTop - ((F32)rect.getWidth() / ratio)); - } - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gl_rect_2d(rect, LLColor4(0.f, 0.f, 0.f, 1.f) % alpha); - rect.stretch(-1); - } - { - - glMatrixMode(GL_TEXTURE); - glPushMatrix(); - { - glScalef(mImageScale.mV[VX], mImageScale.mV[VY], 1.f); - glMatrixMode(GL_MODELVIEW); - gl_draw_scaled_image(rect.mLeft, - rect.mBottom, - rect.getWidth(), - rect.getHeight(), - mViewerImage.get(), - LLColor4::white % alpha); - } - glMatrixMode(GL_TEXTURE); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - } - } -} - -// static -void LLFloaterPostcard::onClickCancel(void* data) -{ - if (data) - { - LLFloaterPostcard *self = (LLFloaterPostcard *)data; - - self->closeFloater(false); - } -} - -class LLSendPostcardResponder : public LLAssetUploadResponder -{ -public: - LLSendPostcardResponder(const LLSD &post_data, - const LLUUID& vfile_id, - LLAssetType::EType asset_type): - LLAssetUploadResponder(post_data, vfile_id, asset_type) - { - } - // *TODO define custom uploadFailed here so it's not such a generic message - void uploadComplete(const LLSD& content) - { - // we don't care about what the server returns from this post, just clean up the UI - LLUploadDialog::modalUploadFinished(); - } -}; - -// static -void LLFloaterPostcard::onClickSend(void* data) -{ - if (data) - { - LLFloaterPostcard *self = (LLFloaterPostcard *)data; - - std::string from(self->getChild<LLUICtrl>("from_form")->getValue().asString()); - std::string to(self->getChild<LLUICtrl>("to_form")->getValue().asString()); - - boost::regex emailFormat("[A-Za-z0-9.%+-_]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}(,[ \t]*[A-Za-z0-9.%+-_]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})*"); - - if (to.empty() || !boost::regex_match(to, emailFormat)) - { - LLNotificationsUtil::add("PromptRecipientEmail"); - return; - } - - if (from.empty() || !boost::regex_match(from, emailFormat)) - { - LLNotificationsUtil::add("PromptSelfEmail"); - return; - } - - std::string subject(self->getChild<LLUICtrl>("subject_form")->getValue().asString()); - if(subject.empty() || !self->mHasFirstMsgFocus) - { - LLNotificationsUtil::add("PromptMissingSubjMsg", LLSD(), LLSD(), boost::bind(&LLFloaterPostcard::missingSubjMsgAlertCallback, self, _1, _2)); - return; - } - - if (self->mJPEGImage.notNull()) - { - self->sendPostcard(); - } - else - { - LLNotificationsUtil::add("ErrorProcessingSnapshot"); - } - } -} - -// static -void LLFloaterPostcard::uploadCallback(const LLUUID& asset_id, void *user_data, S32 result, LLExtStat ext_status) // StoreAssetData callback (fixed) -{ - LLFloaterPostcard *self = (LLFloaterPostcard *)user_data; - - LLUploadDialog::modalUploadFinished(); - - if (result) - { - LLSD args; - args["REASON"] = std::string(LLAssetStorage::getErrorString(result)); - LLNotificationsUtil::add("ErrorUploadingPostcard", args); - } - else - { - // only create the postcard once the upload succeeds - - // request the postcard - LLMessageSystem* msg = gMessageSystem; - msg->newMessage("SendPostcard"); - msg->nextBlock("AgentData"); - msg->addUUID("AgentID", gAgent.getID()); - msg->addUUID("SessionID", gAgent.getSessionID()); - msg->addUUID("AssetID", self->mAssetID); - msg->addVector3d("PosGlobal", self->mPosTakenGlobal); - msg->addString("To", self->getChild<LLUICtrl>("to_form")->getValue().asString()); - msg->addString("From", self->getChild<LLUICtrl>("from_form")->getValue().asString()); - msg->addString("Name", self->getChild<LLUICtrl>("name_form")->getValue().asString()); - msg->addString("Subject", self->getChild<LLUICtrl>("subject_form")->getValue().asString()); - msg->addString("Msg", self->getChild<LLUICtrl>("msg_form")->getValue().asString()); - msg->addBOOL("AllowPublish", FALSE); - msg->addBOOL("MaturePublish", FALSE); - gAgent.sendReliableMessage(); - } - - self->closeFloater(); -} - -// static -void LLFloaterPostcard::updateUserInfo(const std::string& email) -{ - LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("postcard"); - for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); - iter != inst_list.end(); ++iter) - { - LLFloater* instance = *iter; - const std::string& text = instance->getChild<LLUICtrl>("from_form")->getValue().asString(); - if (text.empty()) - { - // there's no text in this field yet, pre-populate - instance->getChild<LLUICtrl>("from_form")->setValue(LLSD(email)); - } - } -} - -void LLFloaterPostcard::onMsgFormFocusRecieved(LLFocusableElement* receiver, void* data) -{ - LLFloaterPostcard* self = (LLFloaterPostcard *)data; - if(self) - { - LLTextEditor* msgForm = self->getChild<LLTextEditor>("msg_form"); - if(msgForm && msgForm == receiver && msgForm->hasFocus() && !(self->mHasFirstMsgFocus)) - { - self->mHasFirstMsgFocus = true; - msgForm->setText(LLStringUtil::null); - } - } -} - -bool LLFloaterPostcard::missingSubjMsgAlertCallback(const LLSD& notification, const LLSD& response) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if(0 == option) - { - // User clicked OK - if((getChild<LLUICtrl>("subject_form")->getValue().asString()).empty()) - { - // Stuff the subject back into the form. - getChild<LLUICtrl>("subject_form")->setValue(getString("default_subject")); - } - - if(!mHasFirstMsgFocus) - { - // The user never switched focus to the messagee window. - // Using the default string. - getChild<LLUICtrl>("msg_form")->setValue(getString("default_message")); - } - - sendPostcard(); - } - return false; -} - -void LLFloaterPostcard::sendPostcard() -{ - mTransactionID.generate(); - mAssetID = mTransactionID.makeAssetID(gAgent.getSecureSessionID()); - LLVFile::writeFile(mJPEGImage->getData(), mJPEGImage->getDataSize(), gVFS, mAssetID, LLAssetType::AT_IMAGE_JPEG); - - // upload the image - std::string url = gAgent.getRegion()->getCapability("SendPostcard"); - if(!url.empty()) - { - llinfos << "Send Postcard via capability" << llendl; - LLSD body = LLSD::emptyMap(); - // the capability already encodes: agent ID, region ID - body["pos-global"] = mPosTakenGlobal.getValue(); - body["to"] = getChild<LLUICtrl>("to_form")->getValue().asString(); - body["from"] = getChild<LLUICtrl>("from_form")->getValue().asString(); - body["name"] = getChild<LLUICtrl>("name_form")->getValue().asString(); - body["subject"] = getChild<LLUICtrl>("subject_form")->getValue().asString(); - body["msg"] = getChild<LLUICtrl>("msg_form")->getValue().asString(); - LLHTTPClient::post(url, body, new LLSendPostcardResponder(body, mAssetID, LLAssetType::AT_IMAGE_JPEG)); - } - else - { - gAssetStorage->storeAssetData(mTransactionID, LLAssetType::AT_IMAGE_JPEG, &uploadCallback, (void *)this, FALSE); - } - - // give user feedback of the event - gViewerWindow->playSnapshotAnimAndSound(); - LLUploadDialog::modalUploadDialog(getString("upload_message")); - - // don't destroy the window until the upload is done - // this way we keep the information in the form - setVisible(FALSE); - - // also remove any dependency on another floater - // so that we can be sure to outlive it while we - // need to. - LLFloater* dependee = getDependee(); - if (dependee) - dependee->removeDependentFloater(this); -} diff --git a/indra/newview/llfloaterpostcard.h b/indra/newview/llfloaterpostcard.h deleted file mode 100644 index 472592154f..0000000000 --- a/indra/newview/llfloaterpostcard.h +++ /dev/null @@ -1,79 +0,0 @@ -/** - * @file llfloaterpostcard.h - * @brief Postcard send floater, allows setting name, e-mail address, etc. - * - * $LicenseInfo:firstyear=2004&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLFLOATERPOSTCARD_H -#define LL_LLFLOATERPOSTCARD_H - -#include "llfloater.h" -#include "llcheckboxctrl.h" - -#include "llpointer.h" - -class LLTextEditor; -class LLLineEditor; -class LLButton; -class LLViewerTexture; -class LLImageJPEG; - -class LLFloaterPostcard -: public LLFloater -{ -public: - LLFloaterPostcard(const LLSD& key); - virtual ~LLFloaterPostcard(); - - virtual BOOL postBuild(); - virtual void draw(); - - static LLFloaterPostcard* showFromSnapshot(LLImageJPEG *jpeg, LLViewerTexture *img, const LLVector2& img_scale, const LLVector3d& pos_taken_global); - - static void onClickCancel(void* data); - static void onClickSend(void* data); - - static void uploadCallback(const LLUUID& asset_id, - void *user_data, - S32 result, LLExtStat ext_status); - - static void updateUserInfo(const std::string& email); - - static void onMsgFormFocusRecieved(LLFocusableElement* receiver, void* data); - bool missingSubjMsgAlertCallback(const LLSD& notification, const LLSD& response); - - void sendPostcard(); - -private: - - LLPointer<LLImageJPEG> mJPEGImage; - LLPointer<LLViewerTexture> mViewerImage; - LLTransactionID mTransactionID; - LLAssetID mAssetID; - LLVector2 mImageScale; - LLVector3d mPosTakenGlobal; - bool mHasFirstMsgFocus; -}; - - -#endif // LL_LLFLOATERPOSTCARD_H diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 8105844b0d..c8c66931a1 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -42,6 +42,8 @@ #include "llcombobox.h" #include "lleconomy.h" #include "lllandmarkactions.h" +#include "llpanelsnapshot.h" +#include "llsidetraypanelcontainer.h" #include "llsliderctrl.h" #include "llspinctrl.h" #include "llviewercontrol.h" @@ -50,9 +52,7 @@ #include "llviewercamera.h" #include "llviewerwindow.h" #include "llviewermenufile.h" // upload_new_resource() -#include "llfloaterpostcard.h" #include "llcheckboxctrl.h" -#include "llradiogroup.h" #include "llslurl.h" #include "lltoolfocus.h" #include "lltoolmgr.h" @@ -76,18 +76,17 @@ #include "llimagej2c.h" #include "lllocalcliprect.h" #include "llnotificationsutil.h" +#include "llpostcard.h" #include "llresmgr.h" // LLLocale #include "llvfile.h" #include "llvfs.h" +#include "llwebprofile.h" #include "llwindow.h" ///---------------------------------------------------------------------------- /// Local function declarations, constants, enums, and typedefs ///---------------------------------------------------------------------------- -S32 LLFloaterSnapshot::sUIWinHeightLong = 530 ; -S32 LLFloaterSnapshot::sUIWinHeightShort = LLFloaterSnapshot::sUIWinHeightLong - 240 ; -S32 LLFloaterSnapshot::sUIWinWidth = 215 ; - +LLRect LLFloaterSnapshot::sThumbnailPlaceholderRect; LLSnapshotFloaterView* gSnapshotFloaterView = NULL; const F32 AUTO_SNAPSHOT_TIME_DELAY = 1.f; @@ -101,6 +100,9 @@ S32 BORDER_WIDTH = 6; const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte const S32 MAX_TEXTURE_SIZE = 512 ; //max upload texture size 512 * 512 +static std::string lastSnapshotWidthName(S32 shot_type); +static std::string lastSnapshotHeightName(S32 shot_type); + static LLDefaultChildRegistry::Register<LLSnapshotFloaterView> r("snapshot_floater_view"); ///---------------------------------------------------------------------------- @@ -108,6 +110,7 @@ static LLDefaultChildRegistry::Register<LLSnapshotFloaterView> r("snapshot_float ///---------------------------------------------------------------------------- class LLSnapshotLivePreview : public LLView { + LOG_CLASS(LLSnapshotLivePreview); public: enum ESnapshotType { @@ -154,6 +157,7 @@ public: F32 getAspect() ; LLRect getImageRect(); BOOL isImageScaled(); + const LLVector3d& getPosTakenGlobal() const { return mPosTakenGlobal; } void setSnapshotType(ESnapshotType type) { mSnapshotType = type; } void setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat type) { mSnapshotFormat = type; } @@ -161,10 +165,12 @@ public: void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; } void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE, F32 delay = 0.f); void saveWeb(); - LLFloaterPostcard* savePostcard(); void saveTexture(); BOOL saveLocal(); + LLPointer<LLImageFormatted> getFormattedImage() const { return mFormattedImage; } + LLPointer<LLImageRaw> getEncodedImage() const { return mPreviewImageEncoded; } + BOOL setThumbnailImageSize() ; void generateThumbnailImage(BOOL force_update = FALSE) ; void resetThumbnailImage() { mThumbnailImage = NULL ; } @@ -327,7 +333,8 @@ BOOL LLSnapshotLivePreview::isImageScaled() } void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail, F32 delay) -{ +{ + lldebugs << "updateSnapshot: mSnapshotUpToDate = " << mSnapshotUpToDate << llendl; if (mSnapshotUpToDate) { S32 old_image_index = mCurImageIndex; @@ -367,6 +374,7 @@ void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail { mSnapshotDelayTimer.start(); mSnapshotDelayTimer.setTimerExpirySec(delay); + LLFloaterSnapshot::preUpdate(); } if(new_thumbnail) { @@ -629,8 +637,10 @@ BOOL LLSnapshotLivePreview::setThumbnailImageSize() F32 window_aspect_ratio = ((F32)window_width) / ((F32)window_height); // UI size for thumbnail - S32 max_width = LLFloaterSnapshot::getUIWinWidth() - 20; - S32 max_height = 90; + // *FIXME: the rect does not change, so maybe there's no need to recalculate max w/h. + const LLRect& thumbnail_rect = LLFloaterSnapshot::getThumbnailPlaceholderRect(); + S32 max_width = thumbnail_rect.getWidth(); + S32 max_height = thumbnail_rect.getHeight(); if (window_aspect_ratio > (F32)max_width / max_height) { @@ -746,7 +756,15 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update) //static BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) { - LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)snapshot_preview; + LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)snapshot_preview; + +#if 1 // XXX tmp + if (previewp->mWidth[previewp->mCurImageIndex] == 0 || previewp->mHeight[previewp->mCurImageIndex] == 0) + { + llwarns << "Incorrect dimensions: " << previewp->mWidth[previewp->mCurImageIndex] << "x" << previewp->mHeight[previewp->mCurImageIndex] << llendl; + return FALSE; + } +#endif LLVector3 new_camera_pos = LLViewerCamera::getInstance()->getOrigin(); LLQuaternion new_camera_rot = LLViewerCamera::getInstance()->getQuaternion(); @@ -774,6 +792,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) // time to produce a snapshot + lldebugs << "producing snapshot" << llendl; if (!previewp->mPreviewImage) { previewp->mPreviewImage = new LLImageRaw; @@ -809,6 +828,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) if(previewp->getSnapshotType() == SNAPSHOT_TEXTURE) { + lldebugs << "Encoding new image of format J2C" << llendl; LLPointer<LLImageJ2C> formatted = new LLImageJ2C; LLPointer<LLImageRaw> scaled = new LLImageRaw( previewp->mPreviewImage->getData(), @@ -841,6 +861,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) { format = previewp->getSnapshotFormat(); } + lldebugs << "Encoding new image of format " << format << llendl; switch(format) { @@ -920,12 +941,15 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) { previewp->generateThumbnailImage() ; } + lldebugs << "done creating snapshot" << llendl; + LLFloaterSnapshot::postUpdate(); return TRUE; } void LLSnapshotLivePreview::setSize(S32 w, S32 h) { + lldebugs << "setSize(" << w << ", " << h << ")" << llendl; mWidth[mCurImageIndex] = w; mHeight[mCurImageIndex] = h; } @@ -936,40 +960,9 @@ void LLSnapshotLivePreview::getSize(S32& w, S32& h) const h = mHeight[mCurImageIndex]; } -LLFloaterPostcard* LLSnapshotLivePreview::savePostcard() -{ - if(mViewerImage[mCurImageIndex].isNull()) - { - //this should never happen!! - llwarns << "The snapshot image has not been generated!" << llendl ; - return NULL ; - } - - // calculate and pass in image scale in case image data only use portion - // of viewerimage buffer - LLVector2 image_scale(1.f, 1.f); - if (!isImageScaled()) - { - image_scale.setVec(llmin(1.f, (F32)mWidth[mCurImageIndex] / (F32)getCurrentImage()->getWidth()), llmin(1.f, (F32)mHeight[mCurImageIndex] / (F32)getCurrentImage()->getHeight())); - } - - LLImageJPEG* jpg = dynamic_cast<LLImageJPEG*>(mFormattedImage.get()); - if(!jpg) - { - llwarns << "Formatted image not a JPEG" << llendl; - return NULL; - } - LLFloaterPostcard* floater = LLFloaterPostcard::showFromSnapshot(jpg, mViewerImage[mCurImageIndex], image_scale, mPosTakenGlobal); - // relinquish lifetime of jpeg image to postcard floater - mFormattedImage = NULL; - mDataSize = 0; - updateSnapshot(FALSE, FALSE); - - return floater; -} - void LLSnapshotLivePreview::saveTexture() { + lldebugs << "saving texture: " << mPreviewImage->getWidth() << "x" << mPreviewImage->getHeight() << llendl; // gen a new uuid for this asset LLTransactionID tid; tid.generate(); @@ -982,6 +975,7 @@ void LLSnapshotLivePreview::saveTexture() mPreviewImage->getComponents()); scaled->biasedScaleToPowerOfTwo(512); + lldebugs << "scaled texture to " << scaled->getWidth() << "x" << scaled->getHeight() << llendl; if (formatted->encode(scaled, 0.0f)) { @@ -1020,9 +1014,10 @@ void LLSnapshotLivePreview::saveTexture() BOOL LLSnapshotLivePreview::saveLocal() { - BOOL success = gViewerWindow->saveImageNumbered(mFormattedImage); + BOOL success = gViewerWindow->saveImageNumbered(mFormattedImage, true); // Relinquish image memory. Save button will be disabled as a side-effect. + lldebugs << "resetting formatted image after saving to disk" << llendl; mFormattedImage = NULL; mDataSize = 0; updateSnapshot(FALSE, FALSE); @@ -1080,29 +1075,40 @@ public: mAvatarPauseHandles.clear(); } - static void onClickDiscard(void* data); - static void onClickKeep(void* data); - static void onCommitSave(LLUICtrl* ctrl, void* data); static void onClickNewSnapshot(void* data); static void onClickAutoSnap(LLUICtrl *ctrl, void* data); //static void onClickAdvanceSnap(LLUICtrl *ctrl, void* data); - static void onClickLess(void* data) ; static void onClickMore(void* data) ; static void onClickUICheck(LLUICtrl *ctrl, void* data); static void onClickHUDCheck(LLUICtrl *ctrl, void* data); static void onClickKeepOpenCheck(LLUICtrl *ctrl, void* data); +#if 0 static void onClickKeepAspectCheck(LLUICtrl *ctrl, void* data); - static void onCommitQuality(LLUICtrl* ctrl, void* data); +#endif + static void applyKeepAspectCheck(LLFloaterSnapshot* view, BOOL checked); static void onCommitResolution(LLUICtrl* ctrl, void* data) { updateResolution(ctrl, data); } static void updateResolution(LLUICtrl* ctrl, void* data, BOOL do_update = TRUE); static void onCommitFreezeFrame(LLUICtrl* ctrl, void* data); static void onCommitLayerTypes(LLUICtrl* ctrl, void*data); + static void onImageQualityChange(LLFloaterSnapshot* view, S32 quality_val); + static void onImageFormatChange(LLFloaterSnapshot* view); +#if 0 static void onCommitSnapshotType(LLUICtrl* ctrl, void* data); - static void onCommitSnapshotFormat(LLUICtrl* ctrl, void* data); static void onCommitCustomResolution(LLUICtrl *ctrl, void* data); +#endif + static void applyCustomResolution(LLFloaterSnapshot* view, S32 w, S32 h); + static void onSnapshotUploadFinished(LLSideTrayPanelContainer* panel_container, bool status); + static void onSendingPostcardFinished(LLSideTrayPanelContainer* panel_container, bool status); static void resetSnapshotSizeOnUI(LLFloaterSnapshot *view, S32 width, S32 height) ; static BOOL checkImageSize(LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL isWidthChanged, S32 max_value); + static LLPanelSnapshot* getActivePanel(LLFloaterSnapshot* floater, bool ok_if_not_found = true); + static LLSnapshotLivePreview::ESnapshotType getActiveSnapshotType(LLFloaterSnapshot* floater); + static LLFloaterSnapshot::ESnapshotFormat getImageFormat(LLFloaterSnapshot* floater); + static LLSpinCtrl* getWidthSpinner(LLFloaterSnapshot* floater); + static LLSpinCtrl* getHeightSpinner(LLFloaterSnapshot* floater); + static void enableAspectRatioCheckbox(LLFloaterSnapshot* floater, BOOL enable); + static LLSnapshotLivePreview* getPreviewView(LLFloaterSnapshot *floater); static void setResolution(LLFloaterSnapshot* floater, const std::string& comboname); static void updateControls(LLFloaterSnapshot* floater); @@ -1110,9 +1116,8 @@ public: static void updateResolutionTextEntry(LLFloaterSnapshot* floater); private: - static LLSnapshotLivePreview::ESnapshotType getTypeIndex(LLFloaterSnapshot* floater); + static LLSnapshotLivePreview::ESnapshotType getTypeIndex(const std::string& id); static LLSD getTypeName(LLSnapshotLivePreview::ESnapshotType index); - static ESnapshotFormat getFormatIndex(LLFloaterSnapshot* floater); static LLViewerWindow::ESnapshotType getLayerType(LLFloaterSnapshot* floater); static void comboSetCustom(LLFloaterSnapshot *floater, const std::string& comboname); static void checkAutoSnapshot(LLSnapshotLivePreview* floater, BOOL update_thumbnail = FALSE); @@ -1127,6 +1132,77 @@ public: }; // static +LLPanelSnapshot* LLFloaterSnapshot::Impl::getActivePanel(LLFloaterSnapshot* floater, bool ok_if_not_found) +{ + LLSideTrayPanelContainer* panel_container = floater->getChild<LLSideTrayPanelContainer>("panel_container"); + LLPanelSnapshot* active_panel = dynamic_cast<LLPanelSnapshot*>(panel_container->getCurrentPanel()); + if (!ok_if_not_found) + { + llassert_always(active_panel != NULL); + } + return active_panel; +} + +// static +LLSnapshotLivePreview::ESnapshotType LLFloaterSnapshot::Impl::getActiveSnapshotType(LLFloaterSnapshot* floater) +{ + LLSnapshotLivePreview::ESnapshotType type = LLSnapshotLivePreview::SNAPSHOT_WEB; + std::string name; + LLPanelSnapshot* spanel = getActivePanel(floater); + + if (spanel) + { + name = spanel->getName(); + } + + if (name == "panel_snapshot_postcard") + { + type = LLSnapshotLivePreview::SNAPSHOT_POSTCARD; + } + else if (name == "panel_snapshot_inventory") + { + type = LLSnapshotLivePreview::SNAPSHOT_TEXTURE; + } + else if (name == "panel_snapshot_local") + { + type = LLSnapshotLivePreview::SNAPSHOT_LOCAL; + } + + return type; +} + +// static +LLFloaterSnapshot::ESnapshotFormat LLFloaterSnapshot::Impl::getImageFormat(LLFloaterSnapshot* floater) +{ + LLPanelSnapshot* active_panel = getActivePanel(floater); + return active_panel ? active_panel->getImageFormat() : LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG; +} + +// static +LLSpinCtrl* LLFloaterSnapshot::Impl::getWidthSpinner(LLFloaterSnapshot* floater) +{ + LLPanelSnapshot* active_panel = getActivePanel(floater); + return active_panel ? active_panel->getWidthSpinner() : floater->getChild<LLSpinCtrl>("snapshot_width"); +} + +// static +LLSpinCtrl* LLFloaterSnapshot::Impl::getHeightSpinner(LLFloaterSnapshot* floater) +{ + LLPanelSnapshot* active_panel = getActivePanel(floater); + return active_panel ? active_panel->getHeightSpinner() : floater->getChild<LLSpinCtrl>("snapshot_height"); +} + +// static +void LLFloaterSnapshot::Impl::enableAspectRatioCheckbox(LLFloaterSnapshot* floater, BOOL enable) +{ + LLPanelSnapshot* active_panel = getActivePanel(floater); + if (active_panel) + { + active_panel->enableAspectRatioCheckbox(enable); + } +} + +// static LLSnapshotLivePreview* LLFloaterSnapshot::Impl::getPreviewView(LLFloaterSnapshot *floater) { LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)floater->impl.mPreviewHandle.get(); @@ -1134,12 +1210,10 @@ LLSnapshotLivePreview* LLFloaterSnapshot::Impl::getPreviewView(LLFloaterSnapshot } // static -LLSnapshotLivePreview::ESnapshotType LLFloaterSnapshot::Impl::getTypeIndex(LLFloaterSnapshot* floater) +LLSnapshotLivePreview::ESnapshotType LLFloaterSnapshot::Impl::getTypeIndex(const std::string& id) { LLSnapshotLivePreview::ESnapshotType index = LLSnapshotLivePreview::SNAPSHOT_POSTCARD; - LLSD value = floater->getChild<LLUICtrl>("snapshot_type_radio")->getValue(); - const std::string id = value.asString(); if (id == "postcard") { index = LLSnapshotLivePreview::SNAPSHOT_POSTCARD; @@ -1184,26 +1258,6 @@ LLSD LLFloaterSnapshot::Impl::getTypeName(LLSnapshotLivePreview::ESnapshotType i } // static -LLFloaterSnapshot::ESnapshotFormat LLFloaterSnapshot::Impl::getFormatIndex(LLFloaterSnapshot* floater) -{ - ESnapshotFormat index = SNAPSHOT_FORMAT_PNG; - if(floater->hasChild("local_format_combo")) - { - LLComboBox* local_format_combo = floater->findChild<LLComboBox>("local_format_combo"); - const std::string id = local_format_combo->getSelectedItemLabel(); - if (id == "PNG") - index = SNAPSHOT_FORMAT_PNG; - else if (id == "JPEG") - index = SNAPSHOT_FORMAT_JPEG; - else if (id == "BMP") - index = SNAPSHOT_FORMAT_BMP; - } - return index; -} - - - -// static LLViewerWindow::ESnapshotType LLFloaterSnapshot::Impl::getLayerType(LLFloaterSnapshot* floater) { LLViewerWindow::ESnapshotType type = LLViewerWindow::SNAPSHOT_TYPE_COLOR; @@ -1229,12 +1283,27 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp) { LLSnapshotLivePreview* previewp = getPreviewView(floaterp); - S32 delta_height = gSavedSettings.getBOOL("AdvanceSnapshot") ? 0 : floaterp->getUIWinHeightShort() - floaterp->getUIWinHeightLong() ; + bool advanced = gSavedSettings.getBOOL("AdvanceSnapshot"); + + // Show/hide advanced options. + LLPanel* advanced_options_panel = floaterp->getChild<LLPanel>("advanced_options_panel"); + floaterp->getChild<LLButton>("advanced_options_btn")->setToggleState(advanced); + if (advanced != advanced_options_panel->getVisible()) + { + S32 panel_width = advanced_options_panel->getRect().getWidth(); + floaterp->getChild<LLPanel>("advanced_options_panel")->setVisible(advanced); + S32 floater_width = floaterp->getRect().getWidth(); + floater_width += (advanced ? panel_width : -panel_width); + floaterp->reshape(floater_width, floaterp->getRect().getHeight()); + } - if(!gSavedSettings.getBOOL("AdvanceSnapshot")) //set to original window resolution + if(!advanced) //set to original window resolution { previewp->mKeepAspectRatio = TRUE; + floaterp->getChild<LLComboBox>("profile_size_combo")->setCurrentByIndex(0); + gSavedSettings.setS32("SnapshotProfileLastResolution", 0); + floaterp->getChild<LLComboBox>("postcard_size_combo")->setCurrentByIndex(0); gSavedSettings.setS32("SnapshotPostcardLastResolution", 0); @@ -1256,7 +1325,8 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp) floaterp->getParent()->setMouseOpaque(TRUE); // shrink to smaller layout - floaterp->reshape(floaterp->getRect().getWidth(), floaterp->getUIWinHeightLong() + delta_height); + // *TODO: unneeded? + floaterp->reshape(floaterp->getRect().getWidth(), floaterp->getRect().getHeight()); // can see and interact with fullscreen preview now if (previewp) @@ -1286,7 +1356,8 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp) else // turning off freeze frame mode { floaterp->getParent()->setMouseOpaque(FALSE); - floaterp->reshape(floaterp->getRect().getWidth(), floaterp->getUIWinHeightLong() + delta_height); + // *TODO: unneeded? + floaterp->reshape(floaterp->getRect().getWidth(), floaterp->getRect().getHeight()); if (previewp) { previewp->setVisible(FALSE); @@ -1315,43 +1386,39 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp) // static void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater) { - LLRadioGroup* snapshot_type_radio = floater->getChild<LLRadioGroup>("snapshot_type_radio"); - LLSnapshotLivePreview::ESnapshotType shot_type = (LLSnapshotLivePreview::ESnapshotType)gSavedSettings.getS32("LastSnapshotType"); - snapshot_type_radio->setSelectedByValue(getTypeName(shot_type), true); - + LLSnapshotLivePreview::ESnapshotType shot_type = getActiveSnapshotType(floater); ESnapshotFormat shot_format = (ESnapshotFormat)gSavedSettings.getS32("SnapshotFormat"); LLViewerWindow::ESnapshotType layer_type = getLayerType(floater); +#if 0 floater->getChildView("share_to_web")->setVisible( gSavedSettings.getBOOL("SnapshotSharingEnabled")); +#endif +#if 0 floater->getChildView("postcard_size_combo")->setVisible( FALSE); floater->getChildView("texture_size_combo")->setVisible( FALSE); floater->getChildView("local_size_combo")->setVisible( FALSE); +#endif + floater->getChild<LLComboBox>("profile_size_combo")->selectNthItem(gSavedSettings.getS32("SnapshotProfileLastResolution")); floater->getChild<LLComboBox>("postcard_size_combo")->selectNthItem(gSavedSettings.getS32("SnapshotPostcardLastResolution")); floater->getChild<LLComboBox>("texture_size_combo")->selectNthItem(gSavedSettings.getS32("SnapshotTextureLastResolution")); floater->getChild<LLComboBox>("local_size_combo")->selectNthItem(gSavedSettings.getS32("SnapshotLocalLastResolution")); +#if 0 floater->getChild<LLComboBox>("local_format_combo")->selectNthItem(gSavedSettings.getS32("SnapshotFormat")); +#endif // *TODO: Separate settings for Web images from postcards - floater->getChildView("send_btn")->setVisible( shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD || - shot_type == LLSnapshotLivePreview::SNAPSHOT_WEB); - floater->getChildView("upload_btn")->setVisible(shot_type == LLSnapshotLivePreview::SNAPSHOT_TEXTURE); - floater->getChildView("save_btn")->setVisible( shot_type == LLSnapshotLivePreview::SNAPSHOT_LOCAL); - floater->getChildView("keep_aspect_check")->setEnabled(shot_type != LLSnapshotLivePreview::SNAPSHOT_TEXTURE && !floater->impl.mAspectRatioCheckOff); + enableAspectRatioCheckbox(floater, shot_type != LLSnapshotLivePreview::SNAPSHOT_TEXTURE && !floater->impl.mAspectRatioCheckOff); floater->getChildView("layer_types")->setEnabled(shot_type == LLSnapshotLivePreview::SNAPSHOT_LOCAL); +#if 0 BOOL is_advance = gSavedSettings.getBOOL("AdvanceSnapshot"); BOOL is_local = shot_type == LLSnapshotLivePreview::SNAPSHOT_LOCAL; BOOL show_slider = (shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD || shot_type == LLSnapshotLivePreview::SNAPSHOT_WEB || (is_local && shot_format == LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG)); - floater->getChildView("more_btn")->setVisible( !is_advance); // the only item hidden in advanced mode - floater->getChildView("less_btn")->setVisible( is_advance); - floater->getChildView("type_label2")->setVisible( is_advance); - floater->getChildView("format_label")->setVisible( is_advance && is_local); - floater->getChildView("local_format_combo")->setVisible( is_advance && is_local); floater->getChildView("layer_types")->setVisible( is_advance); floater->getChildView("layer_type_label")->setVisible( is_advance); floater->getChildView("snapshot_width")->setVisible( is_advance); @@ -1363,47 +1430,59 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater) floater->getChildView("freeze_frame_check")->setVisible( is_advance); floater->getChildView("auto_snapshot_check")->setVisible( is_advance); floater->getChildView("image_quality_slider")->setVisible( is_advance && show_slider); +#endif + + LLPanelSnapshot* active_panel = getActivePanel(floater); + if (active_panel) + { + LLSpinCtrl* width_ctrl = getWidthSpinner(floater); + LLSpinCtrl* height_ctrl = getHeightSpinner(floater); - if (gSavedSettings.getBOOL("RenderUIInSnapshot") || gSavedSettings.getBOOL("RenderHUDInSnapshot")) - { //clamp snapshot resolution to window size when showing UI or HUD in snapshot + // Initialize spinners. + if (width_ctrl->getValue().asInteger() == 0) + { + S32 w = gSavedSettings.getS32(lastSnapshotWidthName(shot_type)); + lldebugs << "Initializing width spinner (" << width_ctrl->getName() << "): " << w << llendl; + width_ctrl->setValue(w); + } + if (height_ctrl->getValue().asInteger() == 0) + { + S32 h = gSavedSettings.getS32(lastSnapshotHeightName(shot_type)); + lldebugs << "Initializing height spinner (" << height_ctrl->getName() << "): " << h << llendl; + height_ctrl->setValue(h); + } - LLSpinCtrl* width_ctrl = floater->getChild<LLSpinCtrl>("snapshot_width"); - LLSpinCtrl* height_ctrl = floater->getChild<LLSpinCtrl>("snapshot_height"); + if (gSavedSettings.getBOOL("RenderUIInSnapshot") || gSavedSettings.getBOOL("RenderHUDInSnapshot")) + { //clamp snapshot resolution to window size when showing UI or HUD in snapshot + S32 width = gViewerWindow->getWindowWidthRaw(); + S32 height = gViewerWindow->getWindowHeightRaw(); - S32 width = gViewerWindow->getWindowWidthRaw(); - S32 height = gViewerWindow->getWindowHeightRaw(); + width_ctrl->setMaxValue(width); - width_ctrl->setMaxValue(width); - - height_ctrl->setMaxValue(height); + height_ctrl->setMaxValue(height); - if (width_ctrl->getValue().asInteger() > width) - { - width_ctrl->forceSetValue(width); + if (width_ctrl->getValue().asInteger() > width) + { + width_ctrl->forceSetValue(width); + } + if (height_ctrl->getValue().asInteger() > height) + { + height_ctrl->forceSetValue(height); + } } - if (height_ctrl->getValue().asInteger() > height) + else { - height_ctrl->forceSetValue(height); + width_ctrl->setMaxValue(6016); + height_ctrl->setMaxValue(6016); } } - else - { - LLSpinCtrl* width = floater->getChild<LLSpinCtrl>("snapshot_width"); - width->setMaxValue(6016); - LLSpinCtrl* height = floater->getChild<LLSpinCtrl>("snapshot_height"); - height->setMaxValue(6016); - } LLSnapshotLivePreview* previewp = getPreviewView(floater); BOOL got_bytes = previewp && previewp->getDataSize() > 0; BOOL got_snap = previewp && previewp->getSnapshotUpToDate(); // *TODO: Separate maximum size for Web images from postcards - floater->getChildView("send_btn")->setEnabled((shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD || - shot_type == LLSnapshotLivePreview::SNAPSHOT_WEB) && - got_snap && previewp->getDataSize() <= MAX_POSTCARD_DATASIZE); - floater->getChildView("upload_btn")->setEnabled(shot_type == LLSnapshotLivePreview::SNAPSHOT_TEXTURE && got_snap); - floater->getChildView("save_btn")->setEnabled(shot_type == LLSnapshotLivePreview::SNAPSHOT_LOCAL && got_snap); + //lldebugs << "Is snapshot up-to-date? " << got_snap << llendl; LLLocale locale(LLLocale::USER_LOCALE); std::string bytes_string; @@ -1411,9 +1490,25 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater) { LLResMgr::getInstance()->getIntegerString(bytes_string, (previewp->getDataSize()) >> 10 ); } + + // FIXME: move this to the panel code S32 upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); - floater->getChild<LLUICtrl>("texture")->setLabelArg("[AMOUNT]", llformat("%d",upload_cost)); - floater->getChild<LLUICtrl>("upload_btn")->setLabelArg("[AMOUNT]", llformat("%d",upload_cost)); + floater->getChild<LLUICtrl>("save_to_inventory_btn")->setLabelArg("[AMOUNT]", llformat("%d",upload_cost)); + + // Update displayed image resolution. + LLTextBox* image_res_tb = floater->getChild<LLTextBox>("image_res_text"); + image_res_tb->setVisible(got_snap); + if (got_snap) + { +#if 1 + LLPointer<LLImageRaw> img = previewp->getEncodedImage(); +#else + LLPointer<LLImageFormatted> fimg = previewp->getFormattedImage(); +#endif + image_res_tb->setTextArg("[WIDTH]", llformat("%d", img->getWidth())); + image_res_tb->setTextArg("[HEIGHT]", llformat("%d", img->getHeight())); + } + floater->getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : floater->getString("unknown")); floater->getChild<LLUICtrl>("file_size_label")->setColor( shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD @@ -1422,29 +1517,23 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater) switch(shot_type) { - // *TODO: Separate settings for Web images from postcards case LLSnapshotLivePreview::SNAPSHOT_WEB: + layer_type = LLViewerWindow::SNAPSHOT_TYPE_COLOR; + floater->getChild<LLUICtrl>("layer_types")->setValue("colors"); + setResolution(floater, "profile_size_combo"); + break; case LLSnapshotLivePreview::SNAPSHOT_POSTCARD: layer_type = LLViewerWindow::SNAPSHOT_TYPE_COLOR; floater->getChild<LLUICtrl>("layer_types")->setValue("colors"); - if(is_advance) - { - setResolution(floater, "postcard_size_combo"); - } + setResolution(floater, "postcard_size_combo"); break; case LLSnapshotLivePreview::SNAPSHOT_TEXTURE: layer_type = LLViewerWindow::SNAPSHOT_TYPE_COLOR; floater->getChild<LLUICtrl>("layer_types")->setValue("colors"); - if(is_advance) - { - setResolution(floater, "texture_size_combo"); - } + setResolution(floater, "texture_size_combo"); break; case LLSnapshotLivePreview::SNAPSHOT_LOCAL: - if(is_advance) - { - setResolution(floater, "local_size_combo"); - } + setResolution(floater, "local_size_combo"); break; default: break; @@ -1458,15 +1547,23 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater) previewp->setSnapshotFormat(shot_format); previewp->setSnapshotBufferType(layer_type); } + + LLPanelSnapshot* current_panel = Impl::getActivePanel(floater); + if (current_panel) + { + LLSD info; + info["have-snapshot"] = got_snap; + current_panel->updateControls(info); + } } // static void LLFloaterSnapshot::Impl::updateResolutionTextEntry(LLFloaterSnapshot* floater) { - LLSpinCtrl* width_spinner = floater->getChild<LLSpinCtrl>("snapshot_width"); - LLSpinCtrl* height_spinner = floater->getChild<LLSpinCtrl>("snapshot_height"); + LLSpinCtrl* width_spinner = getWidthSpinner(floater); + LLSpinCtrl* height_spinner = getHeightSpinner(floater); - if(getTypeIndex(floater) == LLSnapshotLivePreview::SNAPSHOT_TEXTURE) + if(getActiveSnapshotType(floater) == LLSnapshotLivePreview::SNAPSHOT_TEXTURE) { width_spinner->setAllowEdit(FALSE); height_spinner->setAllowEdit(FALSE); @@ -1489,81 +1586,6 @@ void LLFloaterSnapshot::Impl::checkAutoSnapshot(LLSnapshotLivePreview* previewp, } // static -void LLFloaterSnapshot::Impl::onClickDiscard(void* data) -{ - LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; - - if (view) - { - view->closeFloater(); - } -} - - -// static -void LLFloaterSnapshot::Impl::onCommitSave(LLUICtrl* ctrl, void* data) -{ - if (ctrl->getValue().asString() == "save as") - { - gViewerWindow->resetSnapshotLoc(); - } - onClickKeep(data); -} - -// static -void LLFloaterSnapshot::Impl::onClickKeep(void* data) -{ - LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; - LLSnapshotLivePreview* previewp = getPreviewView(view); - - if (previewp) - { - switch (previewp->getSnapshotType()) - { - case LLSnapshotLivePreview::SNAPSHOT_WEB: - previewp->saveWeb(); - break; - - case LLSnapshotLivePreview::SNAPSHOT_POSTCARD: - { - LLFloaterPostcard* floater = previewp->savePostcard(); - // if still in snapshot mode, put postcard floater in snapshot floaterview - // and link it to snapshot floater - if (floater && !gSavedSettings.getBOOL("CloseSnapshotOnKeep")) - { - gFloaterView->removeChild(floater); - gSnapshotFloaterView->addChild(floater); - view->addDependentFloater(floater, FALSE); - } - } - break; - - case LLSnapshotLivePreview::SNAPSHOT_TEXTURE: - previewp->saveTexture(); - break; - - case LLSnapshotLivePreview::SNAPSHOT_LOCAL: - previewp->saveLocal(); - break; - - default: - break; - } - - if (gSavedSettings.getBOOL("CloseSnapshotOnKeep")) - { - view->closeFloater(); - } - else - { - checkAutoSnapshot(previewp); - } - - updateControls(view); - } -} - -// static void LLFloaterSnapshot::Impl::onClickNewSnapshot(void* data) { LLSnapshotLivePreview* previewp = getPreviewView((LLFloaterSnapshot *)data); @@ -1590,32 +1612,19 @@ void LLFloaterSnapshot::Impl::onClickAutoSnap(LLUICtrl *ctrl, void* data) void LLFloaterSnapshot::Impl::onClickMore(void* data) { - gSavedSettings.setBOOL( "AdvanceSnapshot", TRUE ); + BOOL visible = gSavedSettings.getBOOL("AdvanceSnapshot"); - LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; + LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; if (view) { + gSavedSettings.setBOOL("AdvanceSnapshot", !visible); +#if 0 view->translate( 0, view->getUIWinHeightShort() - view->getUIWinHeightLong() ); view->reshape(view->getRect().getWidth(), view->getUIWinHeightLong()); +#endif updateControls(view) ; updateLayout(view) ; - if(getPreviewView(view)) - { - getPreviewView(view)->setThumbnailImageSize() ; - } - } -} -void LLFloaterSnapshot::Impl::onClickLess(void* data) -{ - gSavedSettings.setBOOL( "AdvanceSnapshot", FALSE ); - - LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; - if (view) - { - view->translate( 0, view->getUIWinHeightLong() - view->getUIWinHeightShort() ); - view->reshape(view->getRect().getWidth(), view->getUIWinHeightShort()); - updateControls(view) ; - updateLayout(view) ; + // *TODO: redundant? if(getPreviewView(view)) { getPreviewView(view)->setThumbnailImageSize() ; @@ -1655,17 +1664,24 @@ void LLFloaterSnapshot::Impl::onClickHUDCheck(LLUICtrl *ctrl, void* data) void LLFloaterSnapshot::Impl::onClickKeepOpenCheck(LLUICtrl* ctrl, void* data) { LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl; - gSavedSettings.setBOOL( "CloseSnapshotOnKeep", !check->get() ); } +#if 0 // static void LLFloaterSnapshot::Impl::onClickKeepAspectCheck(LLUICtrl* ctrl, void* data) { LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl; - gSavedSettings.setBOOL( "KeepAspectForSnapshot", check->get() ); - LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; + applyKeepAspectCheck(view, check->get()); +} +#endif + +// static +void LLFloaterSnapshot::Impl::applyKeepAspectCheck(LLFloaterSnapshot* view, BOOL checked) +{ + gSavedSettings.setBOOL("KeepAspectForSnapshot", checked); + if (view) { LLSnapshotLivePreview* previewp = getPreviewView(view) ; @@ -1688,20 +1704,6 @@ void LLFloaterSnapshot::Impl::onClickKeepAspectCheck(LLUICtrl* ctrl, void* data) } // static -void LLFloaterSnapshot::Impl::onCommitQuality(LLUICtrl* ctrl, void* data) -{ - LLSliderCtrl* slider = (LLSliderCtrl*)ctrl; - S32 quality_val = llfloor((F32)slider->getValue().asReal()); - - LLSnapshotLivePreview* previewp = getPreviewView((LLFloaterSnapshot *)data); - if (previewp) - { - previewp->setSnapshotQuality(quality_val); - } - checkAutoSnapshot(previewp, TRUE); -} - -// static void LLFloaterSnapshot::Impl::onCommitFreezeFrame(LLUICtrl* ctrl, void* data) { LLCheckBoxCtrl* check_box = (LLCheckBoxCtrl*)ctrl; @@ -1723,18 +1725,16 @@ void LLFloaterSnapshot::Impl::checkAspectRatio(LLFloaterSnapshot *view, S32 inde LLSnapshotLivePreview *previewp = getPreviewView(view) ; // Don't round texture sizes; textures are commonly stretched in world, profiles, etc and need to be "squashed" during upload, not cropped here -#if 0 - if(LLSnapshotLivePreview::SNAPSHOT_TEXTURE == getTypeIndex(view)) + if(LLSnapshotLivePreview::SNAPSHOT_TEXTURE == getActiveSnapshotType(view)) { previewp->mKeepAspectRatio = FALSE ; return ; } -#endif if(0 == index) //current window size { view->impl.mAspectRatioCheckOff = true ; - view->getChildView("keep_aspect_check")->setEnabled(FALSE) ; + enableAspectRatioCheckbox(view, FALSE); if(previewp) { @@ -1744,9 +1744,11 @@ void LLFloaterSnapshot::Impl::checkAspectRatio(LLFloaterSnapshot *view, S32 inde else if(-1 == index) //custom { view->impl.mAspectRatioCheckOff = false ; +#if 0 //if(LLSnapshotLivePreview::SNAPSHOT_TEXTURE != gSavedSettings.getS32("LastSnapshotType")) +#endif { - view->getChildView("keep_aspect_check")->setEnabled(TRUE) ; + enableAspectRatioCheckbox(view, TRUE); if(previewp) { @@ -1757,7 +1759,7 @@ void LLFloaterSnapshot::Impl::checkAspectRatio(LLFloaterSnapshot *view, S32 inde else { view->impl.mAspectRatioCheckOff = true ; - view->getChildView("keep_aspect_check")->setEnabled(FALSE) ; + enableAspectRatioCheckbox(view, FALSE); if(previewp) { @@ -1768,23 +1770,21 @@ void LLFloaterSnapshot::Impl::checkAspectRatio(LLFloaterSnapshot *view, S32 inde return ; } -static std::string lastSnapshotWidthName() +static std::string lastSnapshotWidthName(S32 shot_type) { - switch(gSavedSettings.getS32("LastSnapshotType")) + switch (shot_type) { - // *TODO: Separate settings for Web snapshots and postcards - case LLSnapshotLivePreview::SNAPSHOT_WEB: return "LastSnapshotToEmailWidth"; + case LLSnapshotLivePreview::SNAPSHOT_WEB: return "LastSnapshotToProfileWidth"; case LLSnapshotLivePreview::SNAPSHOT_POSTCARD: return "LastSnapshotToEmailWidth"; case LLSnapshotLivePreview::SNAPSHOT_TEXTURE: return "LastSnapshotToInventoryWidth"; default: return "LastSnapshotToDiskWidth"; } } -static std::string lastSnapshotHeightName() +static std::string lastSnapshotHeightName(S32 shot_type) { - switch(gSavedSettings.getS32("LastSnapshotType")) + switch (shot_type) { - // *TODO: Separate settings for Web snapshots and postcards - case LLSnapshotLivePreview::SNAPSHOT_WEB: return "LastSnapshotToEmailHeight"; + case LLSnapshotLivePreview::SNAPSHOT_WEB: return "LastSnapshotToProfileHeight"; case LLSnapshotLivePreview::SNAPSHOT_POSTCARD: return "LastSnapshotToEmailHeight"; case LLSnapshotLivePreview::SNAPSHOT_TEXTURE: return "LastSnapshotToInventoryHeight"; default: return "LastSnapshotToDiskHeight"; @@ -1799,10 +1799,12 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL if (!view || !combobox) { + llassert(view && combobox); return; } // save off all selected resolution values + gSavedSettings.setS32("SnapshotProfileLastResolution", view->getChild<LLComboBox>("profile_size_combo")->getCurrentIndex()); gSavedSettings.setS32("SnapshotPostcardLastResolution", view->getChild<LLComboBox>("postcard_size_combo")->getCurrentIndex()); gSavedSettings.setS32("SnapshotTextureLastResolution", view->getChild<LLComboBox>("texture_size_combo")->getCurrentIndex()); gSavedSettings.setS32("SnapshotLocalLastResolution", view->getChild<LLComboBox>("local_size_combo")->getCurrentIndex()); @@ -1824,16 +1826,44 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL if (width == 0 || height == 0) { // take resolution from current window size + lldebugs << "Setting preview res from window: " << gViewerWindow->getWindowWidthRaw() << "x" << gViewerWindow->getWindowHeightRaw() << llendl; previewp->setSize(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw()); } else if (width == -1 || height == -1) { // load last custom value - previewp->setSize(gSavedSettings.getS32(lastSnapshotWidthName()), gSavedSettings.getS32(lastSnapshotHeightName())); +#if 1 + LLPanelSnapshot* spanel = getActivePanel(view); + if (spanel) + { + lldebugs << "Loading typed res from panel " << spanel->getName() << llendl; + width = spanel->getTypedPreviewWidth(); + height = spanel->getTypedPreviewWidth(); + } + else + { + const S32 shot_type = getActiveSnapshotType(view); + lldebugs << "Loading saved res for shot_type " << shot_type << llendl; + width = gSavedSettings.getS32(lastSnapshotWidthName(shot_type)); + height = gSavedSettings.getS32(lastSnapshotHeightName(shot_type)); + } + + llassert(width > 0 && height > 0); + previewp->setSize(width, height); +#else + LLPanelSnapshot* spanel = getActivePanel(view); + if (spanel) + { + lldebugs << "Setting custom preview res : " << spanel->getTypedPreviewWidth() << "x" << spanel->getTypedPreviewHeight() << llendl; + previewp->setSize(spanel->getTypedPreviewWidth(), spanel->getTypedPreviewHeight()); + } + //previewp->setSize(gSavedSettings.getS32(lastSnapshotWidthName()), gSavedSettings.getS32(lastSnapshotHeightName())); +#endif } else { // use the resolution from the selected pre-canned drop-down choice + lldebugs << "Setting preview res selected from combo: " << width << "x" << height << llendl; previewp->setSize(width, height); } @@ -1853,10 +1883,10 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL resetSnapshotSizeOnUI(view, width, height) ; } - if(view->getChild<LLUICtrl>("snapshot_width")->getValue().asInteger() != width || view->getChild<LLUICtrl>("snapshot_height")->getValue().asInteger() != height) + if(getWidthSpinner(view)->getValue().asInteger() != width || getHeightSpinner(view)->getValue().asInteger() != height) { - view->getChild<LLUICtrl>("snapshot_width")->setValue(width); - view->getChild<LLUICtrl>("snapshot_height")->setValue(height); + getWidthSpinner(view)->setValue(width); + getHeightSpinner(view)->setValue(height); } if(original_width != width || original_height != height) @@ -1892,6 +1922,29 @@ void LLFloaterSnapshot::Impl::onCommitLayerTypes(LLUICtrl* ctrl, void*data) } } +// static +void LLFloaterSnapshot::Impl::onImageQualityChange(LLFloaterSnapshot* view, S32 quality_val) +{ + LLSnapshotLivePreview* previewp = getPreviewView(view); + if (previewp) + { + previewp->setSnapshotQuality(quality_val); + } + checkAutoSnapshot(previewp, TRUE); +} + +// static +void LLFloaterSnapshot::Impl::onImageFormatChange(LLFloaterSnapshot* view) +{ + if (view) + { + gSavedSettings.setS32("SnapshotFormat", getImageFormat(view)); + getPreviewView(view)->updateSnapshot(TRUE); + updateControls(view); + } +} + +#if 0 //static void LLFloaterSnapshot::Impl::onCommitSnapshotType(LLUICtrl* ctrl, void* data) { @@ -1903,9 +1956,10 @@ void LLFloaterSnapshot::Impl::onCommitSnapshotType(LLUICtrl* ctrl, void* data) updateControls(view); } } +#endif - -//static +#if 0 +//static. void LLFloaterSnapshot::Impl::onCommitSnapshotFormat(LLUICtrl* ctrl, void* data) { LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; @@ -1916,8 +1970,7 @@ void LLFloaterSnapshot::Impl::onCommitSnapshotFormat(LLUICtrl* ctrl, void* data) updateControls(view); } } - - +#endif // Sets the named size combo to "custom" mode. // static @@ -1931,6 +1984,10 @@ void LLFloaterSnapshot::Impl::comboSetCustom(LLFloaterSnapshot* floater, const s { gSavedSettings.setS32("SnapshotPostcardLastResolution", combo->getCurrentIndex()); } + else if(comboname == "profile_size_combo") + { + gSavedSettings.setS32("SnapshotProfileLastResolution", combo->getCurrentIndex()); + } else if(comboname == "texture_size_combo") { gSavedSettings.setS32("SnapshotTextureLastResolution", combo->getCurrentIndex()); @@ -2027,21 +2084,29 @@ BOOL LLFloaterSnapshot::Impl::checkImageSize(LLSnapshotLivePreview* previewp, S3 //static void LLFloaterSnapshot::Impl::resetSnapshotSizeOnUI(LLFloaterSnapshot *view, S32 width, S32 height) { - view->getChild<LLSpinCtrl>("snapshot_width")->forceSetValue(width); - view->getChild<LLSpinCtrl>("snapshot_height")->forceSetValue(height); - gSavedSettings.setS32(lastSnapshotWidthName(), width); - gSavedSettings.setS32(lastSnapshotHeightName(), height); + getWidthSpinner(view)->forceSetValue(width); + getHeightSpinner(view)->forceSetValue(height); + gSavedSettings.setS32(lastSnapshotWidthName(getActiveSnapshotType(view)), width); + gSavedSettings.setS32(lastSnapshotHeightName(getActiveSnapshotType(view)), height); } +#if 0 //static void LLFloaterSnapshot::Impl::onCommitCustomResolution(LLUICtrl *ctrl, void* data) { - LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; + LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; + S32 w = llfloor((F32)getWidthSpinner(view)->getValue().asReal()); + S32 h = llfloor((F32)getHeightSpinner(view)->getValue().asReal()); + applyCustomResolution(view, w, h); +} +#endif + +// static +void LLFloaterSnapshot::Impl::applyCustomResolution(LLFloaterSnapshot* view, S32 w, S32 h) +{ + lldebugs << "applyCustomResolution(" << w << ", " << h << ")" << llendl; if (view) { - S32 w = llfloor((F32)view->getChild<LLUICtrl>("snapshot_width")->getValue().asReal()); - S32 h = llfloor((F32)view->getChild<LLUICtrl>("snapshot_height")->getValue().asReal()); - LLSnapshotLivePreview* previewp = getPreviewView(view); if (previewp) { @@ -2073,7 +2138,7 @@ void LLFloaterSnapshot::Impl::onCommitCustomResolution(LLUICtrl *ctrl, void* dat } } #endif - previewp->setMaxImageSize((S32)((LLSpinCtrl *)ctrl)->getMaxValue()) ; + previewp->setMaxImageSize(getWidthSpinner(view)->getMaxValue()) ; // Check image size changes the value of height and width if(checkImageSize(previewp, w, h, w != curw, previewp->getMaxImageSize()) @@ -2085,19 +2150,33 @@ void LLFloaterSnapshot::Impl::onCommitCustomResolution(LLUICtrl *ctrl, void* dat previewp->setSize(w,h); checkAutoSnapshot(previewp, FALSE); previewp->updateSnapshot(FALSE, TRUE); + comboSetCustom(view, "profile_size_combo"); comboSetCustom(view, "postcard_size_combo"); comboSetCustom(view, "texture_size_combo"); comboSetCustom(view, "local_size_combo"); } } - gSavedSettings.setS32(lastSnapshotWidthName(), w); - gSavedSettings.setS32(lastSnapshotHeightName(), h); + gSavedSettings.setS32(lastSnapshotWidthName(getActiveSnapshotType(view)), w); + gSavedSettings.setS32(lastSnapshotHeightName(getActiveSnapshotType(view)), h); updateControls(view); } } +// static +void LLFloaterSnapshot::Impl::onSnapshotUploadFinished(LLSideTrayPanelContainer* panel_container, bool status) +{ + panel_container->openPanel("panel_post_result", LLSD().with("post-result", status).with("post-type", "profile")); +} + + +// static +void LLFloaterSnapshot::Impl::onSendingPostcardFinished(LLSideTrayPanelContainer* panel_container, bool status) +{ + panel_container->openPanel("panel_post_result", LLSD().with("post-result", status).with("post-type", "postcard")); +} + ///---------------------------------------------------------------------------- /// Class LLFloaterSnapshot ///---------------------------------------------------------------------------- @@ -2134,24 +2213,19 @@ BOOL LLFloaterSnapshot::postBuild() LLWebSharing::instance().init(); } +#if 0 childSetCommitCallback("snapshot_type_radio", Impl::onCommitSnapshotType, this); childSetCommitCallback("local_format_combo", Impl::onCommitSnapshotFormat, this); +#endif childSetAction("new_snapshot_btn", Impl::onClickNewSnapshot, this); - childSetAction("more_btn", Impl::onClickMore, this); - childSetAction("less_btn", Impl::onClickLess, this); - - childSetAction("upload_btn", Impl::onClickKeep, this); - childSetAction("send_btn", Impl::onClickKeep, this); - childSetCommitCallback("save_btn", Impl::onCommitSave, this); - childSetAction("discard_btn", Impl::onClickDiscard, this); - - childSetCommitCallback("image_quality_slider", Impl::onCommitQuality, this); - getChild<LLUICtrl>("image_quality_slider")->setValue(gSavedSettings.getS32("SnapshotQuality")); + childSetAction("advanced_options_btn", Impl::onClickMore, this); +#if 0 childSetCommitCallback("snapshot_width", Impl::onCommitCustomResolution, this); childSetCommitCallback("snapshot_height", Impl::onCommitCustomResolution, this); +#endif childSetCommitCallback("ui_check", Impl::onClickUICheck, this); getChild<LLUICtrl>("ui_check")->setValue(gSavedSettings.getBOOL("RenderUIInSnapshot")); @@ -2162,15 +2236,19 @@ BOOL LLFloaterSnapshot::postBuild() childSetCommitCallback("keep_open_check", Impl::onClickKeepOpenCheck, this); getChild<LLUICtrl>("keep_open_check")->setValue(!gSavedSettings.getBOOL("CloseSnapshotOnKeep")); +#if 0 childSetCommitCallback("keep_aspect_check", Impl::onClickKeepAspectCheck, this); - getChild<LLUICtrl>("keep_aspect_check")->setValue(gSavedSettings.getBOOL("KeepAspectForSnapshot")); +#endif + impl.enableAspectRatioCheckbox(this, gSavedSettings.getBOOL("KeepAspectForSnapshot")); childSetCommitCallback("layer_types", Impl::onCommitLayerTypes, this); getChild<LLUICtrl>("layer_types")->setValue("colors"); getChildView("layer_types")->setEnabled(FALSE); - getChild<LLUICtrl>("snapshot_width")->setValue(gSavedSettings.getS32(lastSnapshotWidthName())); - getChild<LLUICtrl>("snapshot_height")->setValue(gSavedSettings.getS32(lastSnapshotHeightName())); +#if 0 // leads to crash later if one of the settings values is 0 + impl.getWidthSpinner(this)->setValue(gSavedSettings.getS32(lastSnapshotWidthName())); + impl.getHeightSpinner(this)->setValue(gSavedSettings.getS32(lastSnapshotHeightName())); +#endif getChild<LLUICtrl>("freeze_frame_check")->setValue(gSavedSettings.getBOOL("UseFreezeFrame")); childSetCommitCallback("freeze_frame_check", Impl::onCommitFreezeFrame, this); @@ -2178,10 +2256,18 @@ BOOL LLFloaterSnapshot::postBuild() getChild<LLUICtrl>("auto_snapshot_check")->setValue(gSavedSettings.getBOOL("AutoSnapshot")); childSetCommitCallback("auto_snapshot_check", Impl::onClickAutoSnap, this); + childSetCommitCallback("profile_size_combo", Impl::onCommitResolution, this); childSetCommitCallback("postcard_size_combo", Impl::onCommitResolution, this); childSetCommitCallback("texture_size_combo", Impl::onCommitResolution, this); childSetCommitCallback("local_size_combo", Impl::onCommitResolution, this); + LLSideTrayPanelContainer* panel_container = getChild<LLSideTrayPanelContainer>("panel_container"); + LLWebProfile::setImageUploadResultCallback(boost::bind(&LLFloaterSnapshot::Impl::onSnapshotUploadFinished, panel_container, _1)); + LLPostCard::setPostResultCallback(boost::bind(&LLFloaterSnapshot::Impl::onSendingPostcardFinished, panel_container, _1)); + + // remember preview rect + sThumbnailPlaceholderRect = getChild<LLUICtrl>("thumbnail_placeholder")->getRect(); + // create preview window LLRect full_screen_rect = getRootView()->getRect(); LLSnapshotLivePreview::Params p; @@ -2221,9 +2307,8 @@ void LLFloaterSnapshot::draw() { if(previewp->getThumbnailImage()) { - LLRect thumbnail_rect = getChild<LLUICtrl>("thumbnail_placeholder")->getRect(); - - S32 offset_x = (getRect().getWidth() - previewp->getThumbnailWidth()) / 2 ; + LLRect& thumbnail_rect = sThumbnailPlaceholderRect; + S32 offset_x = thumbnail_rect.mLeft + (thumbnail_rect.getWidth() - previewp->getThumbnailWidth()) / 2 ; S32 offset_y = thumbnail_rect.mBottom + (thumbnail_rect.getHeight() - previewp->getThumbnailHeight()) / 2 ; glMatrixMode(GL_MODELVIEW); @@ -2256,6 +2341,44 @@ void LLFloaterSnapshot::onClose(bool app_quitting) getParent()->setMouseOpaque(FALSE); } +// virtual +S32 LLFloaterSnapshot::notify(const LLSD& info) +{ + // A child panel wants to change snapshot resolution. + if (info.has("combo-res-change")) + { + std::string combo_name = info["combo-res-change"]["control-name"].asString(); + impl.updateResolution(getChild<LLUICtrl>(combo_name), this); + return 1; + } + + if (info.has("custom-res-change")) + { + LLSD res = info["custom-res-change"]; + impl.applyCustomResolution(this, res["w"].asInteger(), res["h"].asInteger()); + return 1; + } + + if (info.has("keep-aspect-change")) + { + impl.applyKeepAspectCheck(this, info["keep-aspect-change"].asBoolean()); + return 1; + } + + if (info.has("image-quality-change")) + { + impl.onImageQualityChange(this, info["image-quality-change"].asInteger()); + return 1; + } + + if (info.has("image-format-change")) + { + impl.onImageFormatChange(this); + return 1; + } + + return 0; +} //static void LLFloaterSnapshot::update() @@ -2276,6 +2399,159 @@ void LLFloaterSnapshot::update() } } +// static +LLFloaterSnapshot* LLFloaterSnapshot::getInstance() +{ + return LLFloaterReg::getTypedInstance<LLFloaterSnapshot>("snapshot"); +} + +// static +void LLFloaterSnapshot::saveTexture() +{ + lldebugs << "saveTexture" << llendl; + + // FIXME: duplicated code + LLFloaterSnapshot* instance = LLFloaterReg::findTypedInstance<LLFloaterSnapshot>("snapshot"); + if (!instance) + { + llassert(instance != NULL); + return; + } + LLSnapshotLivePreview* previewp = Impl::getPreviewView(instance); + if (!previewp) + { + llassert(previewp != NULL); + return; + } + + previewp->saveTexture(); + instance->postSave(); +} + +// static +void LLFloaterSnapshot::saveLocal() +{ + lldebugs << "saveLocal" << llendl; + // FIXME: duplicated code + LLFloaterSnapshot* instance = LLFloaterReg::findTypedInstance<LLFloaterSnapshot>("snapshot"); + if (!instance) + { + llassert(instance != NULL); + return; + } + LLSnapshotLivePreview* previewp = Impl::getPreviewView(instance); + if (!previewp) + { + llassert(previewp != NULL); + return; + } + + previewp->saveLocal(); + instance->postSave(); +} + +// static +void LLFloaterSnapshot::preUpdate() +{ + // FIXME: duplicated code + LLFloaterSnapshot* instance = LLFloaterReg::findTypedInstance<LLFloaterSnapshot>("snapshot"); + if (instance) + { + instance->getChildView("refresh_icon")->setVisible(TRUE); // indicate refresh + } +} + +// static +void LLFloaterSnapshot::postUpdate() +{ + // FIXME: duplicated code + LLFloaterSnapshot* instance = LLFloaterReg::findTypedInstance<LLFloaterSnapshot>("snapshot"); + if (instance) + { + instance->getChildView("refresh_icon")->setVisible(FALSE); + } +} + +// static +void LLFloaterSnapshot::postSave() +{ + LLFloaterSnapshot* instance = LLFloaterReg::findTypedInstance<LLFloaterSnapshot>("snapshot"); + if (!instance) + { + llassert(instance != NULL); + return; + } + + instance->impl.updateControls(instance); +} + +// static +void LLFloaterSnapshot::postPanelSwitch() +{ + LLFloaterSnapshot* instance = getInstance(); + instance->impl.updateControls(instance); +} + +// static +LLPointer<LLImageFormatted> LLFloaterSnapshot::getImageData() +{ + // FIXME: May not work for textures. + + LLFloaterSnapshot* instance = LLFloaterReg::findTypedInstance<LLFloaterSnapshot>("snapshot"); + if (!instance) + { + llassert(instance != NULL); + return NULL; + } + + LLSnapshotLivePreview* previewp = Impl::getPreviewView(instance); + if (!previewp) + { + llassert(previewp != NULL); + return NULL; + } + + LLPointer<LLImageFormatted> img = previewp->getFormattedImage(); + if (!img.get()) + { + llwarns << "Empty snapshot image data" << llendl; + llassert(img.get() != NULL); + } + + return img; +} + +// static +const LLVector3d& LLFloaterSnapshot::getPosTakenGlobal() +{ + LLFloaterSnapshot* instance = LLFloaterReg::findTypedInstance<LLFloaterSnapshot>("snapshot"); + if (!instance) + { + llassert(instance != NULL); + return LLVector3d::zero; + } + + LLSnapshotLivePreview* previewp = Impl::getPreviewView(instance); + if (!previewp) + { + llassert(previewp != NULL); + return LLVector3d::zero; + } + + return previewp->getPosTakenGlobal(); +} + +// static +void LLFloaterSnapshot::setAgentEmail(const std::string& email) +{ + LLFloaterSnapshot* instance = LLFloaterReg::findTypedInstance<LLFloaterSnapshot>("snapshot"); + if (instance) + { + LLSideTrayPanelContainer* panel_container = instance->getChild<LLSideTrayPanelContainer>("panel_container"); + LLPanel* postcard_panel = panel_container->getPanelByName("panel_snapshot_postcard"); + postcard_panel->notify(LLSD().with("agent-email", email)); + } +} ///---------------------------------------------------------------------------- /// Class LLSnapshotFloaterView diff --git a/indra/newview/llfloatersnapshot.h b/indra/newview/llfloatersnapshot.h index c92d9efde5..de69824ad0 100644 --- a/indra/newview/llfloatersnapshot.h +++ b/indra/newview/llfloatersnapshot.h @@ -27,11 +27,15 @@ #ifndef LL_LLFLOATERSNAPSHOT_H #define LL_LLFLOATERSNAPSHOT_H +#include "llimage.h" #include "llfloater.h" +class LLSpinCtrl; class LLFloaterSnapshot : public LLFloater { + LOG_CLASS(LLFloaterSnapshot); + public: typedef enum e_snapshot_format { @@ -47,20 +51,29 @@ public: /*virtual*/ void draw(); /*virtual*/ void onOpen(const LLSD& key); /*virtual*/ void onClose(bool app_quitting); + /*virtual*/ S32 notify(const LLSD& info); static void update(); - - static S32 getUIWinHeightLong() {return sUIWinHeightLong ;} - static S32 getUIWinHeightShort() {return sUIWinHeightShort ;} - static S32 getUIWinWidth() {return sUIWinWidth ;} + + // TODO: create a snapshot model instead + static LLFloaterSnapshot* getInstance(); + static void saveTexture(); + static void saveLocal(); + static void preUpdate(); + static void postUpdate(); + static void postSave(); + static void postPanelSwitch(); + static LLPointer<LLImageFormatted> getImageData(); + static const LLVector3d& getPosTakenGlobal(); + static void setAgentEmail(const std::string& email); + + static const LLRect& getThumbnailPlaceholderRect() { return sThumbnailPlaceholderRect; } private: + static LLRect sThumbnailPlaceholderRect; + class Impl; Impl& impl; - - static S32 sUIWinHeightLong ; - static S32 sUIWinHeightShort ; - static S32 sUIWinWidth ; }; class LLSnapshotFloaterView : public LLFloaterView diff --git a/indra/newview/llpanelpostprogress.cpp b/indra/newview/llpanelpostprogress.cpp new file mode 100644 index 0000000000..9b7de2cb23 --- /dev/null +++ b/indra/newview/llpanelpostprogress.cpp @@ -0,0 +1,59 @@ +/** + * @file llpanelpostprogress.cpp + * @brief Displays progress of publishing a snapshot. + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the termsllpanelpostprogress of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloaterreg.h" +#include "llpanel.h" +#include "llsidetraypanelcontainer.h" + +/** + * Displays progress of publishing a snapshot. + */ +class LLPanelPostProgress +: public LLPanel +{ + LOG_CLASS(LLPanelPostProgress); + +public: + /*virtual*/ void onOpen(const LLSD& key); +}; + +static LLRegisterPanelClassWrapper<LLPanelPostProgress> panel_class("llpanelpostprogress"); + +// virtual +void LLPanelPostProgress::onOpen(const LLSD& key) +{ + if (key.has("post-type")) + { + std::string progress_text = getString(key["post-type"].asString() + "_" + "progress_str"); + getChild<LLTextBox>("progress_lbl")->setText(progress_text); + } + else + { + llwarns << "Invalid key" << llendl; + } +} diff --git a/indra/newview/llpanelpostresult.cpp b/indra/newview/llpanelpostresult.cpp new file mode 100644 index 0000000000..2b937d83b9 --- /dev/null +++ b/indra/newview/llpanelpostresult.cpp @@ -0,0 +1,90 @@ +/** + * @file llpanelpostresult.cpp + * @brief Result of publishing a snapshot (success/failure). + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloaterreg.h" +#include "llpanel.h" +#include "llsidetraypanelcontainer.h" + +/** + * Displays snapshot publishing result. + */ +class LLPanelPostResult +: public LLPanel +{ + LOG_CLASS(LLPanelPostResult); + +public: + LLPanelPostResult(); + + /*virtual*/ void onOpen(const LLSD& key); +private: + void onBack(); + void onClose(); +}; + +static LLRegisterPanelClassWrapper<LLPanelPostResult> panel_class("llpanelpostresult"); + +LLPanelPostResult::LLPanelPostResult() +{ + mCommitCallbackRegistrar.add("Snapshot.Result.Back", boost::bind(&LLPanelPostResult::onBack, this)); + mCommitCallbackRegistrar.add("Snapshot.Result.Close", boost::bind(&LLPanelPostResult::onClose, this)); +} + + +// virtual +void LLPanelPostResult::onOpen(const LLSD& key) +{ + if (key.isMap() && key.has("post-result") && key.has("post-type")) + { + bool ok = key["post-result"].asBoolean(); + std::string type = key["post-type"].asString(); + std::string result_text = getString(type + "_" + (ok ? "succeeded_str" : "failed_str")); + getChild<LLTextBox>("result_lbl")->setText(result_text); + } + else + { + llwarns << "Invalid key" << llendl; + } +} + +void LLPanelPostResult::onBack() +{ + LLSideTrayPanelContainer* parent = dynamic_cast<LLSideTrayPanelContainer*>(getParent()); + if (!parent) + { + llwarns << "Cannot find panel container" << llendl; + return; + } + + parent->openPreviousPanel(); +} + +void LLPanelPostResult::onClose() +{ + LLFloaterReg::hideInstance("snapshot"); +} diff --git a/indra/newview/llpanelsnapshot.cpp b/indra/newview/llpanelsnapshot.cpp new file mode 100644 index 0000000000..e89e62c750 --- /dev/null +++ b/indra/newview/llpanelsnapshot.cpp @@ -0,0 +1,109 @@ +/** + * @file llpanelsnapshot.cpp + * @brief Snapshot panel base class + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llpanelsnapshot.h" + +// libs +#include "llsliderctrl.h" +#include "llspinctrl.h" +#include "lltrans.h" + +// newview +#include "llsidetraypanelcontainer.h" + +LLFloaterSnapshot::ESnapshotFormat LLPanelSnapshot::getImageFormat() const +{ + return LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG; +} + +LLSpinCtrl* LLPanelSnapshot::getWidthSpinner() +{ + return getChild<LLSpinCtrl>(getWidthSpinnerName()); +} + +LLSpinCtrl* LLPanelSnapshot::getHeightSpinner() +{ + return getChild<LLSpinCtrl>(getHeightSpinnerName()); +} + +S32 LLPanelSnapshot::getTypedPreviewWidth() const +{ + return getChild<LLUICtrl>(getWidthSpinnerName())->getValue().asInteger(); +} + +S32 LLPanelSnapshot::getTypedPreviewHeight() const +{ + return getChild<LLUICtrl>(getHeightSpinnerName())->getValue().asInteger(); +} + +void LLPanelSnapshot::enableAspectRatioCheckbox(BOOL enable) +{ + getChild<LLUICtrl>(getAspectRatioCBName())->setEnabled(enable); +} + +LLSideTrayPanelContainer* LLPanelSnapshot::getParentContainer() +{ + LLSideTrayPanelContainer* parent = dynamic_cast<LLSideTrayPanelContainer*>(getParent()); + if (!parent) + { + llwarns << "Cannot find panel container" << llendl; + return NULL; + } + + return parent; +} + +void LLPanelSnapshot::updateImageQualityLevel() +{ + LLSliderCtrl* quality_slider = getChild<LLSliderCtrl>("image_quality_slider"); + S32 quality_val = llfloor((F32) quality_slider->getValue().asReal()); + + std::string quality_lvl; + + if (quality_val < 20) + { + quality_lvl = LLTrans::getString("snapshot_quality_very_low"); + } + else if (quality_val < 40) + { + quality_lvl = LLTrans::getString("snapshot_quality_low"); + } + else if (quality_val < 60) + { + quality_lvl = LLTrans::getString("snapshot_quality_medium"); + } + else if (quality_val < 80) + { + quality_lvl = LLTrans::getString("snapshot_quality_high"); + } + else + { + quality_lvl = LLTrans::getString("snapshot_quality_very_high"); + } + + getChild<LLTextBox>("image_quality_level")->setTextArg("[QLVL]", quality_lvl); +} diff --git a/indra/newview/llpanelsnapshot.h b/indra/newview/llpanelsnapshot.h new file mode 100644 index 0000000000..a227317d2f --- /dev/null +++ b/indra/newview/llpanelsnapshot.h @@ -0,0 +1,58 @@ +/** + * @file llpanelsnapshot.h + * @brief Snapshot panel base class + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLPANELSNAPSHOT_H +#define LL_LLPANELSNAPSHOT_H + +#include "llfloatersnapshot.h" + +class LLSideTrayPanelContainer; + +/** + * Snapshot panel base class. + */ +class LLPanelSnapshot: public LLPanel +{ +public: + virtual std::string getWidthSpinnerName() const = 0; + virtual std::string getHeightSpinnerName() const = 0; + virtual std::string getAspectRatioCBName() const = 0; + virtual std::string getImageSizeComboName() const = 0; + + virtual S32 getTypedPreviewWidth() const; + virtual S32 getTypedPreviewHeight() const; + virtual LLSpinCtrl* getWidthSpinner(); + virtual LLSpinCtrl* getHeightSpinner(); + virtual void enableAspectRatioCheckbox(BOOL enable); + virtual LLFloaterSnapshot::ESnapshotFormat getImageFormat() const; + virtual void updateControls(const LLSD& info) {} ///< Update controls from saved settings + +protected: + LLSideTrayPanelContainer* getParentContainer(); + void updateImageQualityLevel(); +}; + +#endif // LL_LLPANELSNAPSHOT_H diff --git a/indra/newview/llpanelsnapshotinventory.cpp b/indra/newview/llpanelsnapshotinventory.cpp new file mode 100644 index 0000000000..6419c37494 --- /dev/null +++ b/indra/newview/llpanelsnapshotinventory.cpp @@ -0,0 +1,152 @@ +/** + * @file llpanelsnapshotinventory.cpp + * @brief The panel provides UI for saving snapshot as an inventory texture. + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llcombobox.h" +#include "llsidetraypanelcontainer.h" +#include "llspinctrl.h" + +#include "llfloatersnapshot.h" // FIXME: replace with a snapshot storage model +#include "llpanelsnapshot.h" +#include "llviewercontrol.h" // gSavedSettings + +/** + * The panel provides UI for saving snapshot as an inventory texture. + */ +class LLPanelSnapshotInventory +: public LLPanelSnapshot +{ + LOG_CLASS(LLPanelSnapshotInventory); + +public: + LLPanelSnapshotInventory(); + /*virtual*/ BOOL postBuild(); + /*virtual*/ void onOpen(const LLSD& key); + +private: + void updateCustomResControls(); ///< Show/hide custom resolution controls (spinners and checkbox) + + /*virtual*/ std::string getWidthSpinnerName() const { return "inventory_snapshot_width"; } + /*virtual*/ std::string getHeightSpinnerName() const { return "inventory_snapshot_height"; } + /*virtual*/ std::string getAspectRatioCBName() const { return "inventory_keep_aspect_check"; } + /*virtual*/ std::string getImageSizeComboName() const { return "texture_size_combo"; } + /*virtual*/ void updateControls(const LLSD& info); + + void onResolutionComboCommit(LLUICtrl* ctrl); + void onCustomResolutionCommit(LLUICtrl* ctrl); + void onKeepAspectRatioCommit(LLUICtrl* ctrl); + void onSend(); + void onCancel(); +}; + +static LLRegisterPanelClassWrapper<LLPanelSnapshotInventory> panel_class("llpanelsnapshotinventory"); + +LLPanelSnapshotInventory::LLPanelSnapshotInventory() +{ + mCommitCallbackRegistrar.add("Inventory.Save", boost::bind(&LLPanelSnapshotInventory::onSend, this)); + mCommitCallbackRegistrar.add("Inventory.Cancel", boost::bind(&LLPanelSnapshotInventory::onCancel, this)); +} + +// virtual +BOOL LLPanelSnapshotInventory::postBuild() +{ + getChild<LLUICtrl>(getImageSizeComboName())->setCommitCallback(boost::bind(&LLPanelSnapshotInventory::onResolutionComboCommit, this, _1)); + getChild<LLUICtrl>(getWidthSpinnerName())->setCommitCallback(boost::bind(&LLPanelSnapshotInventory::onCustomResolutionCommit, this, _1)); + getChild<LLUICtrl>(getHeightSpinnerName())->setCommitCallback(boost::bind(&LLPanelSnapshotInventory::onCustomResolutionCommit, this, _1)); + getChild<LLUICtrl>(getAspectRatioCBName())->setCommitCallback(boost::bind(&LLPanelSnapshotInventory::onKeepAspectRatioCommit, this, _1)); + return TRUE; +} + +// virtual +void LLPanelSnapshotInventory::onOpen(const LLSD& key) +{ +#if 0 + getChild<LLComboBox>(getImageSizeComboName())->selectNthItem(0); // FIXME? has no effect +#endif + updateCustomResControls(); +} + +void LLPanelSnapshotInventory::updateCustomResControls() +{ + LLComboBox* combo = getChild<LLComboBox>(getImageSizeComboName()); + S32 selected_idx = combo->getFirstSelectedIndex(); + bool show = selected_idx == 0 || selected_idx == (combo->getItemCount() - 1); // Current Window or Custom selected + + getChild<LLUICtrl>(getWidthSpinnerName())->setVisible(show); + getChild<LLUICtrl>(getHeightSpinnerName())->setVisible(show); + getChild<LLUICtrl>(getAspectRatioCBName())->setVisible(show); +} + +// virtual +void LLPanelSnapshotInventory::updateControls(const LLSD& info) +{ + const bool have_snapshot = info.has("have-snapshot") ? info["have-snapshot"].asBoolean() : true; + getChild<LLUICtrl>("save_btn")->setEnabled(have_snapshot); +} + +void LLPanelSnapshotInventory::onResolutionComboCommit(LLUICtrl* ctrl) +{ + updateCustomResControls(); + + LLSD info; + info["combo-res-change"]["control-name"] = ctrl->getName(); + LLFloaterSnapshot::getInstance()->notify(info); +} + +void LLPanelSnapshotInventory::onCustomResolutionCommit(LLUICtrl* ctrl) +{ + LLSD info; + info["w"] = getChild<LLUICtrl>(getWidthSpinnerName())->getValue().asInteger();; + info["h"] = getChild<LLUICtrl>(getHeightSpinnerName())->getValue().asInteger();; + LLFloaterSnapshot::getInstance()->notify(LLSD().with("custom-res-change", info)); +} + +void LLPanelSnapshotInventory::onKeepAspectRatioCommit(LLUICtrl* ctrl) +{ + LLFloaterSnapshot::getInstance()->notify(LLSD().with("keep-aspect-change", ctrl->getValue().asBoolean())); +} + +void LLPanelSnapshotInventory::onSend() +{ + // Switch to upload progress display. + LLSideTrayPanelContainer* parent = getParentContainer(); + if (parent) + { + parent->openPanel("panel_post_progress", LLSD().with("post-type", "inventory")); + } + + LLFloaterSnapshot::saveTexture(); +} + +void LLPanelSnapshotInventory::onCancel() +{ + LLSideTrayPanelContainer* parent = getParentContainer(); + if (parent) + { + parent->openPreviousPanel(); + } +} diff --git a/indra/newview/llpanelsnapshotlocal.cpp b/indra/newview/llpanelsnapshotlocal.cpp new file mode 100644 index 0000000000..5dc32d228f --- /dev/null +++ b/indra/newview/llpanelsnapshotlocal.cpp @@ -0,0 +1,209 @@ +/** + * @file llpanelsnapshotlocal.cpp + * @brief The panel provides UI for saving snapshot to a local folder. + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llcombobox.h" +#include "llsidetraypanelcontainer.h" +#include "llsliderctrl.h" +#include "llspinctrl.h" + +#include "llfloatersnapshot.h" // FIXME: replace with a snapshot storage model +#include "llpanelsnapshot.h" +#include "llviewercontrol.h" // gSavedSettings + +/** + * The panel provides UI for saving snapshot to a local folder. + */ +class LLPanelSnapshotLocal +: public LLPanelSnapshot +{ + LOG_CLASS(LLPanelSnapshotLocal); + +public: + LLPanelSnapshotLocal(); + /*virtual*/ BOOL postBuild(); + /*virtual*/ void onOpen(const LLSD& key); + +private: + /*virtual*/ std::string getWidthSpinnerName() const { return "local_snapshot_width"; } + /*virtual*/ std::string getHeightSpinnerName() const { return "local_snapshot_height"; } + /*virtual*/ std::string getAspectRatioCBName() const { return "local_keep_aspect_check"; } + /*virtual*/ std::string getImageSizeComboName() const { return "local_size_combo"; } + /*virtual*/ LLFloaterSnapshot::ESnapshotFormat getImageFormat() const; + /*virtual*/ void updateControls(const LLSD& info); + + void updateCustomResControls(); ///< Show/hide custom resolution controls (spinners and checkbox) + + void onFormatComboCommit(LLUICtrl* ctrl); + void onResolutionComboCommit(LLUICtrl* ctrl); + void onCustomResolutionCommit(LLUICtrl* ctrl); + void onKeepAspectRatioCommit(LLUICtrl* ctrl); + void onQualitySliderCommit(LLUICtrl* ctrl); + void onSend(); + void onCancel(); +}; + +static LLRegisterPanelClassWrapper<LLPanelSnapshotLocal> panel_class("llpanelsnapshotlocal"); + +LLPanelSnapshotLocal::LLPanelSnapshotLocal() +{ + mCommitCallbackRegistrar.add("Local.Save", boost::bind(&LLPanelSnapshotLocal::onSend, this)); + mCommitCallbackRegistrar.add("Local.Cancel", boost::bind(&LLPanelSnapshotLocal::onCancel, this)); +} + +// virtual +BOOL LLPanelSnapshotLocal::postBuild() +{ + getChild<LLUICtrl>(getImageSizeComboName())->setCommitCallback(boost::bind(&LLPanelSnapshotLocal::onResolutionComboCommit, this, _1)); + getChild<LLUICtrl>(getWidthSpinnerName())->setCommitCallback(boost::bind(&LLPanelSnapshotLocal::onCustomResolutionCommit, this, _1)); + getChild<LLUICtrl>(getHeightSpinnerName())->setCommitCallback(boost::bind(&LLPanelSnapshotLocal::onCustomResolutionCommit, this, _1)); + getChild<LLUICtrl>(getAspectRatioCBName())->setCommitCallback(boost::bind(&LLPanelSnapshotLocal::onKeepAspectRatioCommit, this, _1)); + getChild<LLUICtrl>("image_quality_slider")->setCommitCallback(boost::bind(&LLPanelSnapshotLocal::onQualitySliderCommit, this, _1)); + getChild<LLUICtrl>("local_format_combo")->setCommitCallback(boost::bind(&LLPanelSnapshotLocal::onFormatComboCommit, this, _1)); + + updateControls(LLSD()); + + return TRUE; +} + +// virtual +void LLPanelSnapshotLocal::onOpen(const LLSD& key) +{ + updateCustomResControls(); +} + +// virtual +LLFloaterSnapshot::ESnapshotFormat LLPanelSnapshotLocal::getImageFormat() const +{ + LLFloaterSnapshot::ESnapshotFormat fmt = LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG; + + LLComboBox* local_format_combo = getChild<LLComboBox>("local_format_combo"); + const std::string id = local_format_combo->getSelectedItemLabel(); + if (id == "PNG") + { + fmt = LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG; + } + else if (id == "JPEG") + { + fmt = LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG; + } + else if (id == "BMP") + { + fmt = LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP; + } + + return fmt; +} + +// virtual +void LLPanelSnapshotLocal::updateControls(const LLSD& info) +{ + LLFloaterSnapshot::ESnapshotFormat fmt = + (LLFloaterSnapshot::ESnapshotFormat) gSavedSettings.getS32("SnapshotFormat"); + getChild<LLComboBox>("local_format_combo")->selectNthItem((S32) fmt); + + const bool show_quality_ctrls = (fmt == LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG); + getChild<LLUICtrl>("image_quality_slider")->setVisible(show_quality_ctrls); + getChild<LLUICtrl>("image_quality_level")->setVisible(show_quality_ctrls); + + getChild<LLUICtrl>("image_quality_slider")->setValue(gSavedSettings.getS32("SnapshotQuality")); + updateImageQualityLevel(); + + const bool have_snapshot = info.has("have-snapshot") ? info["have-snapshot"].asBoolean() : true; + getChild<LLUICtrl>("save_btn")->setEnabled(have_snapshot); +} + +void LLPanelSnapshotLocal::updateCustomResControls() +{ + LLComboBox* combo = getChild<LLComboBox>(getImageSizeComboName()); + S32 selected_idx = combo->getFirstSelectedIndex(); + bool enable = selected_idx == 0 || selected_idx == (combo->getItemCount() - 1); // Current Window or Custom selected + + getChild<LLUICtrl>(getWidthSpinnerName())->setEnabled(enable); + getChild<LLSpinCtrl>(getWidthSpinnerName())->setAllowEdit(enable); + getChild<LLUICtrl>(getHeightSpinnerName())->setEnabled(enable); + getChild<LLSpinCtrl>(getHeightSpinnerName())->setAllowEdit(enable); + getChild<LLUICtrl>(getAspectRatioCBName())->setEnabled(enable); +} + +void LLPanelSnapshotLocal::onFormatComboCommit(LLUICtrl* ctrl) +{ +#if 0 // redundant? + gSavedSettings.setS32("SnapshotFormat", ctrl->getValue().asInteger()); +#endif + + // will call updateControls() + LLFloaterSnapshot::getInstance()->notify(LLSD().with("image-format-change", true)); +} + +void LLPanelSnapshotLocal::onResolutionComboCommit(LLUICtrl* ctrl) +{ + updateCustomResControls(); + + LLSD info; + info["combo-res-change"]["control-name"] = ctrl->getName(); + LLFloaterSnapshot::getInstance()->notify(info); +} + +void LLPanelSnapshotLocal::onCustomResolutionCommit(LLUICtrl* ctrl) +{ + LLSD info; + info["w"] = getChild<LLUICtrl>(getWidthSpinnerName())->getValue().asInteger(); + info["h"] = getChild<LLUICtrl>(getHeightSpinnerName())->getValue().asInteger(); + LLFloaterSnapshot::getInstance()->notify(LLSD().with("custom-res-change", info)); +} + +void LLPanelSnapshotLocal::onKeepAspectRatioCommit(LLUICtrl* ctrl) +{ + LLFloaterSnapshot::getInstance()->notify(LLSD().with("keep-aspect-change", ctrl->getValue().asBoolean())); +} + +void LLPanelSnapshotLocal::onQualitySliderCommit(LLUICtrl* ctrl) +{ + updateImageQualityLevel(); + + LLSliderCtrl* slider = (LLSliderCtrl*)ctrl; + S32 quality_val = llfloor((F32)slider->getValue().asReal()); + LLSD info; + info["image-quality-change"] = quality_val; + LLFloaterSnapshot::getInstance()->notify(info); +} + +void LLPanelSnapshotLocal::onSend() +{ + LLFloaterSnapshot::saveLocal(); + onCancel(); +} + +void LLPanelSnapshotLocal::onCancel() +{ + LLSideTrayPanelContainer* parent = getParentContainer(); + if (parent) + { + parent->openPreviousPanel(); + } +} diff --git a/indra/newview/llpanelsnapshotoptions.cpp b/indra/newview/llpanelsnapshotoptions.cpp new file mode 100644 index 0000000000..8e5ff282b3 --- /dev/null +++ b/indra/newview/llpanelsnapshotoptions.cpp @@ -0,0 +1,94 @@ +/** + * @file llpanelsnapshotoptions.cpp + * @brief Snapshot posting options panel. + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llpanel.h" +#include "llsidetraypanelcontainer.h" + +#include "llfloatersnapshot.h" // FIXME: create a snapshot model + +/** + * Provides several ways to save a snapshot. + */ +class LLPanelSnapshotOptions +: public LLPanel +{ + LOG_CLASS(LLPanelSnapshotOptions); + +public: + LLPanelSnapshotOptions(); + +private: + void openPanel(const std::string& panel_name); + void onSaveToProfile(); + void onSaveToEmail(); + void onSaveToInventory(); + void onSaveToComputer(); +}; + +static LLRegisterPanelClassWrapper<LLPanelSnapshotOptions> panel_class("llpanelsnapshotoptions"); + +LLPanelSnapshotOptions::LLPanelSnapshotOptions() +{ + mCommitCallbackRegistrar.add("Snapshot.SaveToProfile", boost::bind(&LLPanelSnapshotOptions::onSaveToProfile, this)); + mCommitCallbackRegistrar.add("Snapshot.SaveToEmail", boost::bind(&LLPanelSnapshotOptions::onSaveToEmail, this)); + mCommitCallbackRegistrar.add("Snapshot.SaveToInventory", boost::bind(&LLPanelSnapshotOptions::onSaveToInventory, this)); + mCommitCallbackRegistrar.add("Snapshot.SaveToComputer", boost::bind(&LLPanelSnapshotOptions::onSaveToComputer, this)); +} + +void LLPanelSnapshotOptions::openPanel(const std::string& panel_name) +{ + LLSideTrayPanelContainer* parent = dynamic_cast<LLSideTrayPanelContainer*>(getParent()); + if (!parent) + { + llwarns << "Cannot find panel container" << llendl; + return; + } + + parent->openPanel(panel_name); + LLFloaterSnapshot::postPanelSwitch(); +} + +void LLPanelSnapshotOptions::onSaveToProfile() +{ + openPanel("panel_snapshot_profile"); +} + +void LLPanelSnapshotOptions::onSaveToEmail() +{ + openPanel("panel_snapshot_postcard"); +} + +void LLPanelSnapshotOptions::onSaveToInventory() +{ + openPanel("panel_snapshot_inventory"); +} + +void LLPanelSnapshotOptions::onSaveToComputer() +{ + openPanel("panel_snapshot_local"); +} diff --git a/indra/newview/llpanelsnapshotpostcard.cpp b/indra/newview/llpanelsnapshotpostcard.cpp new file mode 100644 index 0000000000..c2b83d5c19 --- /dev/null +++ b/indra/newview/llpanelsnapshotpostcard.cpp @@ -0,0 +1,336 @@ +/** + * @file llpanelsnapshotpostcard.cpp + * @brief Postcard sending panel. + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llcombobox.h" +#include "llnotificationsutil.h" +#include "llsidetraypanelcontainer.h" +#include "llsliderctrl.h" +#include "llspinctrl.h" +#include "lltexteditor.h" + +#include "llagent.h" +#include "llagentui.h" +#include "llfloatersnapshot.h" // FIXME: replace with a snapshot storage model +#include "llpanelsnapshot.h" +#include "llpostcard.h" +#include "llviewercontrol.h" // gSavedSettings +#include "llviewerwindow.h" + +#include <boost/regex.hpp> + +/** + * Sends postcard via email. + */ +class LLPanelSnapshotPostcard +: public LLPanelSnapshot +{ + LOG_CLASS(LLPanelSnapshotPostcard); + +public: + LLPanelSnapshotPostcard(); + /*virtual*/ BOOL postBuild(); + /*virtual*/ void onOpen(const LLSD& key); + /*virtual*/ S32 notify(const LLSD& info); + +private: + /*virtual*/ std::string getWidthSpinnerName() const { return "postcard_snapshot_width"; } + /*virtual*/ std::string getHeightSpinnerName() const { return "postcard_snapshot_height"; } + /*virtual*/ std::string getAspectRatioCBName() const { return "postcard_keep_aspect_check"; } + /*virtual*/ std::string getImageSizeComboName() const { return "postcard_size_combo"; } + /*virtual*/ void updateControls(const LLSD& info); + + void updateCustomResControls(); ///< Enable/disable custom resolution controls (spinners and checkbox) + bool missingSubjMsgAlertCallback(const LLSD& notification, const LLSD& response); + void sendPostcard(); + + void onMsgFormFocusRecieved(); + void onFormatComboCommit(LLUICtrl* ctrl); + void onResolutionComboCommit(LLUICtrl* ctrl); + void onCustomResolutionCommit(LLUICtrl* ctrl); + void onKeepAspectRatioCommit(LLUICtrl* ctrl); + void onQualitySliderCommit(LLUICtrl* ctrl); + void onTabButtonPress(S32 btn_idx); + void onSend(); + void onCancel(); + + bool mHasFirstMsgFocus; +}; + +static LLRegisterPanelClassWrapper<LLPanelSnapshotPostcard> panel_class("llpanelsnapshotpostcard"); + +LLPanelSnapshotPostcard::LLPanelSnapshotPostcard() +: mHasFirstMsgFocus(false) +{ + mCommitCallbackRegistrar.add("Postcard.Send", boost::bind(&LLPanelSnapshotPostcard::onSend, this)); + mCommitCallbackRegistrar.add("Postcard.Cancel", boost::bind(&LLPanelSnapshotPostcard::onCancel, this)); + mCommitCallbackRegistrar.add("Postcard.Message", boost::bind(&LLPanelSnapshotPostcard::onTabButtonPress, this, 0)); + mCommitCallbackRegistrar.add("Postcard.Settings", boost::bind(&LLPanelSnapshotPostcard::onTabButtonPress, this, 1)); + +} + +// virtual +BOOL LLPanelSnapshotPostcard::postBuild() +{ + // pick up the user's up-to-date email address + gAgent.sendAgentUserInfoRequest(); + + getChildView("from_form")->setEnabled(FALSE); + + std::string name_string; + LLAgentUI::buildFullname(name_string); + getChild<LLUICtrl>("name_form")->setValue(LLSD(name_string)); + + // For the first time a user focuses to .the msg box, all text will be selected. + getChild<LLUICtrl>("msg_form")->setFocusChangedCallback(boost::bind(&LLPanelSnapshotPostcard::onMsgFormFocusRecieved, this)); + + getChild<LLUICtrl>("to_form")->setFocus(TRUE); + + getChild<LLUICtrl>(getImageSizeComboName())->setCommitCallback(boost::bind(&LLPanelSnapshotPostcard::onResolutionComboCommit, this, _1)); + getChild<LLUICtrl>(getWidthSpinnerName())->setCommitCallback(boost::bind(&LLPanelSnapshotPostcard::onCustomResolutionCommit, this, _1)); + getChild<LLUICtrl>(getHeightSpinnerName())->setCommitCallback(boost::bind(&LLPanelSnapshotPostcard::onCustomResolutionCommit, this, _1)); + getChild<LLUICtrl>(getAspectRatioCBName())->setCommitCallback(boost::bind(&LLPanelSnapshotPostcard::onKeepAspectRatioCommit, this, _1)); + getChild<LLUICtrl>("image_quality_slider")->setCommitCallback(boost::bind(&LLPanelSnapshotPostcard::onQualitySliderCommit, this, _1)); + + getChild<LLButton>("message_btn")->setToggleState(TRUE); + + updateControls(LLSD()); + + return TRUE; +} + +// virtual +void LLPanelSnapshotPostcard::onOpen(const LLSD& key) +{ + gSavedSettings.setS32("SnapshotFormat", getImageFormat()); + updateCustomResControls(); +} + +// virtual +S32 LLPanelSnapshotPostcard::notify(const LLSD& info) +{ + if (!info.has("agent-email")) + { + llassert(info.has("agent-email")); + return 0; + } + + LLUICtrl* from_input = getChild<LLUICtrl>("from_form"); + const std::string& text = from_input->getValue().asString(); + if (text.empty()) + { + // there's no text in this field yet, pre-populate + from_input->setValue(info["agent-email"]); + } + + return 1; +} + +// virtual +void LLPanelSnapshotPostcard::updateControls(const LLSD& info) +{ + getChild<LLUICtrl>("image_quality_slider")->setValue(gSavedSettings.getS32("SnapshotQuality")); + updateImageQualityLevel(); + + const bool have_snapshot = info.has("have-snapshot") ? info["have-snapshot"].asBoolean() : true; + getChild<LLUICtrl>("send_btn")->setEnabled(have_snapshot); +} + +void LLPanelSnapshotPostcard::updateCustomResControls() +{ + LLComboBox* combo = getChild<LLComboBox>(getImageSizeComboName()); + S32 selected_idx = combo->getFirstSelectedIndex(); + bool enable = selected_idx == 0 || selected_idx == (combo->getItemCount() - 1); // Current Window or Custom selected + + getChild<LLUICtrl>(getWidthSpinnerName())->setEnabled(enable); + getChild<LLSpinCtrl>(getWidthSpinnerName())->setAllowEdit(enable); + getChild<LLUICtrl>(getHeightSpinnerName())->setEnabled(enable); + getChild<LLSpinCtrl>(getHeightSpinnerName())->setAllowEdit(enable); + getChild<LLUICtrl>(getAspectRatioCBName())->setEnabled(enable); +} + +bool LLPanelSnapshotPostcard::missingSubjMsgAlertCallback(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if(0 == option) + { + // User clicked OK + if((getChild<LLUICtrl>("subject_form")->getValue().asString()).empty()) + { + // Stuff the subject back into the form. + getChild<LLUICtrl>("subject_form")->setValue(getString("default_subject")); + } + + if (!mHasFirstMsgFocus) + { + // The user never switched focus to the message window. + // Using the default string. + getChild<LLUICtrl>("msg_form")->setValue(getString("default_message")); + } + + sendPostcard(); + } + return false; +} + + +void LLPanelSnapshotPostcard::sendPostcard() +{ + std::string from(getChild<LLUICtrl>("from_form")->getValue().asString()); + std::string to(getChild<LLUICtrl>("to_form")->getValue().asString()); + std::string subject(getChild<LLUICtrl>("subject_form")->getValue().asString()); + + LLSD postcard = LLSD::emptyMap(); + postcard["pos-global"] = LLFloaterSnapshot::getPosTakenGlobal().getValue(); + postcard["to"] = to; + postcard["from"] = from; + postcard["name"] = getChild<LLUICtrl>("name_form")->getValue().asString(); + postcard["subject"] = subject; + postcard["msg"] = getChild<LLUICtrl>("msg_form")->getValue().asString(); + LLPostCard::send(LLFloaterSnapshot::getImageData(), postcard); + LLFloaterSnapshot::postSave(); + + // Give user feedback of the event. + gViewerWindow->playSnapshotAnimAndSound(); + + // Switch to upload progress display. + LLSideTrayPanelContainer* parent = getParentContainer(); + if (parent) + { + parent->openPanel("panel_post_progress", LLSD().with("post-type", "postcard")); + } +} + +void LLPanelSnapshotPostcard::onMsgFormFocusRecieved() +{ + LLTextEditor* msg_form = getChild<LLTextEditor>("msg_form"); + if (msg_form->hasFocus() && !mHasFirstMsgFocus) + { + mHasFirstMsgFocus = true; + msg_form->setText(LLStringUtil::null); + } +} + +void LLPanelSnapshotPostcard::onFormatComboCommit(LLUICtrl* ctrl) +{ + // will call updateControls() + LLFloaterSnapshot::getInstance()->notify(LLSD().with("image-format-change", true)); +} + +void LLPanelSnapshotPostcard::onResolutionComboCommit(LLUICtrl* ctrl) +{ + updateCustomResControls(); + + LLSD info; + info["combo-res-change"]["control-name"] = ctrl->getName(); + LLFloaterSnapshot::getInstance()->notify(info); +} + +void LLPanelSnapshotPostcard::onCustomResolutionCommit(LLUICtrl* ctrl) +{ + LLSD info; + info["w"] = getChild<LLUICtrl>(getWidthSpinnerName())->getValue().asInteger(); + info["h"] = getChild<LLUICtrl>(getHeightSpinnerName())->getValue().asInteger(); + LLFloaterSnapshot::getInstance()->notify(LLSD().with("custom-res-change", info)); +} + +void LLPanelSnapshotPostcard::onKeepAspectRatioCommit(LLUICtrl* ctrl) +{ + LLFloaterSnapshot::getInstance()->notify(LLSD().with("keep-aspect-change", ctrl->getValue().asBoolean())); +} + +void LLPanelSnapshotPostcard::onQualitySliderCommit(LLUICtrl* ctrl) +{ + updateImageQualityLevel(); + + LLSliderCtrl* slider = (LLSliderCtrl*)ctrl; + S32 quality_val = llfloor((F32)slider->getValue().asReal()); + LLSD info; + info["image-quality-change"] = quality_val; + LLFloaterSnapshot::getInstance()->notify(info); // updates the "SnapshotQuality" setting +} + +void LLPanelSnapshotPostcard::onTabButtonPress(S32 btn_idx) +{ + static LLButton* sButtons[2] = { + getChild<LLButton>("message_btn"), + getChild<LLButton>("settings_btn"), + }; + + // Switch between Message and Settings tabs. + LLButton* clicked_btn = sButtons[btn_idx]; + LLButton* other_btn = sButtons[!btn_idx]; + LLSideTrayPanelContainer* container = + getChild<LLSideTrayPanelContainer>("postcard_panel_container"); + + container->selectTab(clicked_btn->getToggleState() ? btn_idx : !btn_idx); + //clicked_btn->setEnabled(FALSE); + other_btn->toggleState(); + //other_btn->setEnabled(TRUE); + + lldebugs << "Button #" << btn_idx << " (" << clicked_btn->getName() << ") clicked" << llendl; +} + +void LLPanelSnapshotPostcard::onSend() +{ + // Validate input. + std::string from(getChild<LLUICtrl>("from_form")->getValue().asString()); + std::string to(getChild<LLUICtrl>("to_form")->getValue().asString()); + + boost::regex email_format("[A-Za-z0-9.%+-_]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}(,[ \t]*[A-Za-z0-9.%+-_]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})*"); + + if (to.empty() || !boost::regex_match(to, email_format)) + { + LLNotificationsUtil::add("PromptRecipientEmail"); + return; + } + + if (from.empty() || !boost::regex_match(from, email_format)) + { + LLNotificationsUtil::add("PromptSelfEmail"); + return; + } + + std::string subject(getChild<LLUICtrl>("subject_form")->getValue().asString()); + if(subject.empty() || !mHasFirstMsgFocus) + { + LLNotificationsUtil::add("PromptMissingSubjMsg", LLSD(), LLSD(), boost::bind(&LLPanelSnapshotPostcard::missingSubjMsgAlertCallback, this, _1, _2)); + return; + } + + // Send postcard. + sendPostcard(); +} + +void LLPanelSnapshotPostcard::onCancel() +{ + LLSideTrayPanelContainer* parent = getParentContainer(); + if (parent) + { + parent->openPreviousPanel(); + } +} diff --git a/indra/newview/llpanelsnapshotprofile.cpp b/indra/newview/llpanelsnapshotprofile.cpp new file mode 100644 index 0000000000..80a379a5a0 --- /dev/null +++ b/indra/newview/llpanelsnapshotprofile.cpp @@ -0,0 +1,162 @@ +/** + * @file llpanelsnapshotprofile.cpp + * @brief Posts a snapshot to My Profile feed. + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +// libs +#include "llcombobox.h" +#include "llfloaterreg.h" +#include "llpanel.h" +#include "llspinctrl.h" + +// newview +#include "llfloatersnapshot.h" +#include "llpanelsnapshot.h" +#include "llsidetraypanelcontainer.h" +#include "llwebprofile.h" + +/** + * Posts a snapshot to My Profile feed. + */ +class LLPanelSnapshotProfile +: public LLPanelSnapshot +{ + LOG_CLASS(LLPanelSnapshotProfile); + +public: + LLPanelSnapshotProfile(); + + /*virtual*/ BOOL postBuild(); + /*virtual*/ void onOpen(const LLSD& key); + +private: + /*virtual*/ std::string getWidthSpinnerName() const { return "profile_snapshot_width"; } + /*virtual*/ std::string getHeightSpinnerName() const { return "profile_snapshot_height"; } + /*virtual*/ std::string getAspectRatioCBName() const { return "profile_keep_aspect_check"; } + /*virtual*/ std::string getImageSizeComboName() const { return "profile_size_combo"; } + /*virtual*/ void updateControls(const LLSD& info); + + void updateCustomResControls(); ///< Enable/disable custom resolution controls (spinners and checkbox) + + void onSend(); + void onCancel(); + void onResolutionComboCommit(LLUICtrl* ctrl); + void onCustomResolutionCommit(LLUICtrl* ctrl); + void onKeepAspectRatioCommit(LLUICtrl* ctrl); +}; + +static LLRegisterPanelClassWrapper<LLPanelSnapshotProfile> panel_class("llpanelsnapshotprofile"); + +LLPanelSnapshotProfile::LLPanelSnapshotProfile() +{ + mCommitCallbackRegistrar.add("PostToProfile.Send", boost::bind(&LLPanelSnapshotProfile::onSend, this)); + mCommitCallbackRegistrar.add("PostToProfile.Cancel", boost::bind(&LLPanelSnapshotProfile::onCancel, this)); +} + +// virtual +BOOL LLPanelSnapshotProfile::postBuild() +{ + getChild<LLUICtrl>(getImageSizeComboName())->setCommitCallback(boost::bind(&LLPanelSnapshotProfile::onResolutionComboCommit, this, _1)); + getChild<LLUICtrl>(getWidthSpinnerName())->setCommitCallback(boost::bind(&LLPanelSnapshotProfile::onCustomResolutionCommit, this, _1)); + getChild<LLUICtrl>(getHeightSpinnerName())->setCommitCallback(boost::bind(&LLPanelSnapshotProfile::onCustomResolutionCommit, this, _1)); + getChild<LLUICtrl>(getAspectRatioCBName())->setCommitCallback(boost::bind(&LLPanelSnapshotProfile::onKeepAspectRatioCommit, this, _1)); + return TRUE; +} + +// virtual +void LLPanelSnapshotProfile::onOpen(const LLSD& key) +{ + updateCustomResControls(); +} + +// virtual +void LLPanelSnapshotProfile::updateControls(const LLSD& info) +{ + const bool have_snapshot = info.has("have-snapshot") ? info["have-snapshot"].asBoolean() : true; + getChild<LLUICtrl>("post_btn")->setEnabled(have_snapshot); +} + +void LLPanelSnapshotProfile::updateCustomResControls() ///< Enable/disable custom resolution controls (spinners and checkbox) +{ + LLComboBox* combo = getChild<LLComboBox>(getImageSizeComboName()); + S32 selected_idx = combo->getFirstSelectedIndex(); + bool enable = selected_idx == 0 || selected_idx == (combo->getItemCount() - 1); // Current Window or Custom selected + + getChild<LLUICtrl>(getWidthSpinnerName())->setEnabled(enable); + getChild<LLSpinCtrl>(getWidthSpinnerName())->setAllowEdit(enable); + getChild<LLUICtrl>(getHeightSpinnerName())->setEnabled(enable); + getChild<LLSpinCtrl>(getHeightSpinnerName())->setAllowEdit(enable); + getChild<LLUICtrl>(getAspectRatioCBName())->setEnabled(enable); +} + +void LLPanelSnapshotProfile::onSend() +{ + std::string caption = getChild<LLUICtrl>("caption")->getValue().asString(); + bool add_location = getChild<LLUICtrl>("add_location_cb")->getValue().asBoolean(); + + LLWebProfile::uploadImage(LLFloaterSnapshot::getImageData(), caption, add_location); + LLFloaterSnapshot::postSave(); + + // Switch to upload progress display. + LLSideTrayPanelContainer* parent = getParentContainer(); + if (parent) + { + parent->openPanel("panel_post_progress", LLSD().with("post-type", "profile")); + } +} + +void LLPanelSnapshotProfile::onCancel() +{ + LLSideTrayPanelContainer* parent = getParentContainer(); + if (parent) + { + parent->openPreviousPanel(); + } +} + +void LLPanelSnapshotProfile::onResolutionComboCommit(LLUICtrl* ctrl) +{ + updateCustomResControls(); + + LLSD info; + info["combo-res-change"]["control-name"] = ctrl->getName(); + LLFloaterSnapshot::getInstance()->notify(info); +} + +void LLPanelSnapshotProfile::onCustomResolutionCommit(LLUICtrl* ctrl) +{ + S32 w = getChild<LLUICtrl>(getWidthSpinnerName())->getValue().asInteger(); + S32 h = getChild<LLUICtrl>(getHeightSpinnerName())->getValue().asInteger(); + LLSD info; + info["w"] = w; + info["h"] = h; + LLFloaterSnapshot::getInstance()->notify(LLSD().with("custom-res-change", info)); +} + +void LLPanelSnapshotProfile::onKeepAspectRatioCommit(LLUICtrl* ctrl) +{ + LLFloaterSnapshot::getInstance()->notify(LLSD().with("keep-aspect-change", ctrl->getValue().asBoolean())); +} diff --git a/indra/newview/llpostcard.cpp b/indra/newview/llpostcard.cpp new file mode 100644 index 0000000000..5f57f3a856 --- /dev/null +++ b/indra/newview/llpostcard.cpp @@ -0,0 +1,160 @@ +/** + * @file llpostcard.cpp + * @brief Sending postcards. + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llpostcard.h" + +#include "llvfile.h" +#include "llvfs.h" +#include "llviewerregion.h" + +#include "message.h" + +#include "llagent.h" +#include "llassetuploadresponders.h" + +/////////////////////////////////////////////////////////////////////////////// +// misc + +static void postcard_upload_callback(const LLUUID& asset_id, void *user_data, S32 result, LLExtStat ext_status) +{ + LLSD* postcard_data = (LLSD*)user_data; + + if (result) + { + // TODO: display the error messages in UI + llwarns << "Failed to send postcard: " << LLAssetStorage::getErrorString(result) << llendl; + LLPostCard::reportPostResult(false); + } + else + { + // only create the postcard once the upload succeeds + + // request the postcard + const LLSD& data = *postcard_data; + LLMessageSystem* msg = gMessageSystem; + msg->newMessage("SendPostcard"); + msg->nextBlock("AgentData"); + msg->addUUID("AgentID", gAgent.getID()); + msg->addUUID("SessionID", gAgent.getSessionID()); + msg->addUUID("AssetID", data["asset-id"].asUUID()); + msg->addVector3d("PosGlobal", LLVector3d(data["pos-global"])); + msg->addString("To", data["to"]); + msg->addString("From", data["from"]); + msg->addString("Name", data["name"]); + msg->addString("Subject", data["subject"]); + msg->addString("Msg", data["msg"]); + msg->addBOOL("AllowPublish", FALSE); + msg->addBOOL("MaturePublish", FALSE); + gAgent.sendReliableMessage(); + + LLPostCard::reportPostResult(true); + } + + delete postcard_data; +} + + +/////////////////////////////////////////////////////////////////////////////// +// LLPostcardSendResponder + +class LLPostcardSendResponder : public LLAssetUploadResponder +{ + LOG_CLASS(LLPostcardSendResponder); + +public: + LLPostcardSendResponder(const LLSD &post_data, + const LLUUID& vfile_id, + LLAssetType::EType asset_type): + LLAssetUploadResponder(post_data, vfile_id, asset_type) + { + } + + /*virtual*/ void uploadComplete(const LLSD& content) + { + llinfos << "Postcard sent" << llendl; + LL_DEBUGS("Snapshots") << "content: " << content << llendl; + LLPostCard::reportPostResult(true); + } + + /*virtual*/ void uploadFailure(const LLSD& content) + { + llwarns << "Sending postcard failed: " << content << llendl; + LLPostCard::reportPostResult(false); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// LLPostCard + +LLPostCard::result_callback_t LLPostCard::mResultCallback; + +// static +void LLPostCard::send(LLPointer<LLImageFormatted> image, const LLSD& postcard_data) +{ +#if 0 + static LLTransactionID transaction_id; + static LLAssetID asset_id; +#else + LLTransactionID transaction_id; + LLAssetID asset_id; +#endif + + transaction_id.generate(); + asset_id = transaction_id.makeAssetID(gAgent.getSecureSessionID()); + LLVFile::writeFile(image->getData(), image->getDataSize(), gVFS, asset_id, LLAssetType::AT_IMAGE_JPEG); + + // upload the image + std::string url = gAgent.getRegion()->getCapability("SendPostcard"); + if (!url.empty()) + { + llinfos << "Sending postcard via capability" << llendl; + // the capability already encodes: agent ID, region ID + LL_DEBUGS("Snapshots") << "url: " << url << llendl; + LL_DEBUGS("Snapshots") << "body: " << postcard_data << llendl; + LL_DEBUGS("Snapshots") << "data size: " << image->getDataSize() << llendl; + LLHTTPClient::post(url, postcard_data, + new LLPostcardSendResponder(postcard_data, asset_id, LLAssetType::AT_IMAGE_JPEG)); + } + else + { + llinfos << "Sending postcard" << llendl; + LLSD* data = new LLSD(postcard_data); + (*data)["asset-id"] = asset_id; + gAssetStorage->storeAssetData(transaction_id, LLAssetType::AT_IMAGE_JPEG, + &postcard_upload_callback, (void *)data, FALSE); + } +} + +// static +void LLPostCard::reportPostResult(bool ok) +{ + if (mResultCallback) + { + mResultCallback(ok); + } +} diff --git a/indra/newview/llpostcard.h b/indra/newview/llpostcard.h new file mode 100644 index 0000000000..0eb118b906 --- /dev/null +++ b/indra/newview/llpostcard.h @@ -0,0 +1,48 @@ +/** + * @file llpostcard.h + * @brief Sending postcards. + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLPOSTCARD_H +#define LL_LLPOSTCARD_H + +#include "llimage.h" +#include "lluuid.h" + +class LLPostCard +{ + LOG_CLASS(LLPostCard); + +public: + typedef boost::function<void(bool ok)> result_callback_t; + + static void send(LLPointer<LLImageFormatted> image, const LLSD& postcard_data); + static void setPostResultCallback(result_callback_t cb) { mResultCallback = cb; } + static void reportPostResult(bool ok); + +private: + static result_callback_t mResultCallback; +}; + +#endif // LL_LLPOSTCARD_H diff --git a/indra/newview/llsidetraypanelcontainer.cpp b/indra/newview/llsidetraypanelcontainer.cpp index 95a12c7c23..e340333c2c 100644 --- a/indra/newview/llsidetraypanelcontainer.cpp +++ b/indra/newview/llsidetraypanelcontainer.cpp @@ -62,6 +62,13 @@ void LLSideTrayPanelContainer::onOpen(const LLSD& key) getCurrentPanel()->onOpen(key); } +void LLSideTrayPanelContainer::openPanel(const std::string& panel_name, const LLSD& key) +{ + LLSD combined_key = key; + combined_key[PARAM_SUB_PANEL_NAME] = panel_name; + onOpen(combined_key); +} + void LLSideTrayPanelContainer::openPreviousPanel() { if(!mDefaultPanelName.empty()) diff --git a/indra/newview/llsidetraypanelcontainer.h b/indra/newview/llsidetraypanelcontainer.h index 14269b002b..93a85ed374 100644 --- a/indra/newview/llsidetraypanelcontainer.h +++ b/indra/newview/llsidetraypanelcontainer.h @@ -57,6 +57,11 @@ public: /*virtual*/ void onOpen(const LLSD& key); /** + * Opens given subpanel. + */ + void openPanel(const std::string& panel_name, const LLSD& key = LLSD::emptyMap()); + + /** * Opens previous panel from panel navigation history. */ void openPreviousPanel(); diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index c761969fcf..74c4f6d2dc 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -85,7 +85,6 @@ #include "llfloateropenobject.h" #include "llfloaterpay.h" #include "llfloaterperms.h" -#include "llfloaterpostcard.h" #include "llfloaterpostprocess.h" #include "llfloaterpreference.h" #include "llfloaterproperties.h" @@ -245,7 +244,6 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("people", "floater_people.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSidePanelContainer>); LLFloaterReg::add("places", "floater_places.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSidePanelContainer>); - LLFloaterReg::add("postcard", "floater_postcard.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPostcard>); LLFloaterReg::add("preferences", "floater_preferences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreference>); LLFloaterReg::add("prefs_proxy", "floater_preferences_proxy.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreferenceProxy>); LLFloaterReg::add("prefs_hardware_settings", "floater_hardware_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHardwareSettings>); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 41b4dc01e8..5afd481dda 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -50,6 +50,7 @@ #include "llvoavatar.h" #include "llvoavatarself.h" #include "llviewerregion.h" +#include "llwebprofile.h" #include "llwebsharing.h" // For LLWebSharing::setOpenIDCookie(), *TODO: find a better way to do this! #include "llfilepicker.h" #include "llnotifications.h" @@ -319,6 +320,10 @@ public: std::string cookie = content["set-cookie"].asString(); LLViewerMedia::getCookieStore()->setCookiesFromHost(cookie, mHost); + + // Set cookie for snapshot publishing. + std::string auth_cookie = cookie.substr(0, cookie.find(";")); // strip path + LLWebProfile::setAuthCookie(auth_cookie); } void completedRaw( @@ -1484,6 +1489,8 @@ void LLViewerMedia::setOpenIDCookie() std::string profile_url = getProfileURL(""); LLURL raw_profile_url( profile_url.c_str() ); + LL_DEBUGS("MediaAuth") << "Requesting " << profile_url << llendl; + LL_DEBUGS("MediaAuth") << "sOpenIDCookie = [" << sOpenIDCookie << "]" << llendl; LLHTTPClient::get(profile_url, new LLViewerMediaWebProfileResponder(raw_profile_url.getAuthority()), headers); diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index b9293b3b31..7e830e14bf 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -528,23 +528,7 @@ class LLFileTakeSnapshotToDisk : public view_listener_t { gViewerWindow->playSnapshotAnimAndSound(); - LLPointer<LLImageFormatted> formatted; - switch(LLFloaterSnapshot::ESnapshotFormat(gSavedSettings.getS32("SnapshotFormat"))) - { - case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG: - formatted = new LLImageJPEG(gSavedSettings.getS32("SnapshotQuality")); - break; - case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG: - formatted = new LLImagePNG; - break; - case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP: - formatted = new LLImageBMP; - break; - default: - llwarns << "Unknown Local Snapshot format" << llendl; - return true; - } - + LLPointer<LLImageFormatted> formatted = new LLImagePNG; formatted->enableOverSize() ; formatted->encode(raw, 0); formatted->disableOverSize() ; diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index a9ca70fd26..7cae19a1d2 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -59,9 +59,9 @@ #include "llfloaterland.h" #include "llfloaterregioninfo.h" #include "llfloaterlandholdings.h" -#include "llfloaterpostcard.h" #include "llfloaterpreference.h" #include "llfloatersidepanelcontainer.h" +#include "llfloatersnapshot.h" #include "llhudeffecttrail.h" #include "llhudmanager.h" #include "llinventoryfunctions.h" @@ -6470,7 +6470,7 @@ void process_user_info_reply(LLMessageSystem* msg, void**) msg->getString( "UserData", "DirectoryVisibility", dir_visibility); LLFloaterPreference::updateUserInfo(dir_visibility, im_via_email, email); - LLFloaterPostcard::updateUserInfo(email); + LLFloaterSnapshot::setAgentEmail(email); } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 6fcbc401af..c20bc5f02f 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -4020,10 +4020,11 @@ BOOL LLViewerWindow::mousePointOnLandGlobal(const S32 x, const S32 y, LLVector3d } // Saves an image to the harddrive as "SnapshotX" where X >= 1. -BOOL LLViewerWindow::saveImageNumbered(LLImageFormatted *image) +BOOL LLViewerWindow::saveImageNumbered(LLImageFormatted *image, bool force_picker) { if (!image) { + llwarns << "No image to save" << llendl; return FALSE; } @@ -4043,7 +4044,7 @@ BOOL LLViewerWindow::saveImageNumbered(LLImageFormatted *image) pick_type = LLFilePicker::FFSAVE_ALL; // ??? // Get a base file location if needed. - if ( ! isSnapshotLocSet()) + if (force_picker || !isSnapshotLocSet()) { std::string proposed_name( sSnapshotBaseName ); @@ -4083,6 +4084,7 @@ BOOL LLViewerWindow::saveImageNumbered(LLImageFormatted *image) } while( -1 != err ); // search until the file is not found (i.e., stat() gives an error). + llinfos << "Saving snapshot to " << filepath << llendl; return image->save(filepath); } diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index d10b06f121..0cb7f82b58 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -324,7 +324,7 @@ public: BOOL thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type) ; BOOL isSnapshotLocSet() const { return ! sSnapshotDir.empty(); } void resetSnapshotLoc() const { sSnapshotDir.clear(); } - BOOL saveImageNumbered(LLImageFormatted *image); + BOOL saveImageNumbered(LLImageFormatted *image, bool force_picker = false); // Reset the directory where snapshots are saved. // Client will open directory picker on next snapshot save. diff --git a/indra/newview/llwebprofile.cpp b/indra/newview/llwebprofile.cpp new file mode 100644 index 0000000000..bb8a9a491b --- /dev/null +++ b/indra/newview/llwebprofile.cpp @@ -0,0 +1,297 @@ +/** + * @file llwebprofile.cpp + * @brief Web profile access. + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llwebprofile.h" + +// libs +#include "llbufferstream.h" +#include "llhttpclient.h" +#include "llplugincookiestore.h" + +// newview +#include "llpanelprofile.h" // for getProfileURL(). FIXME: move the method to LLAvatarActions +#include "llviewermedia.h" // FIXME: don't use LLViewerMedia internals + +// third-party +#include "reader.h" // JSON + +/* + * Workflow: + * 1. LLViewerMedia::setOpenIDCookie() + * -> GET https://my-demo.secondlife.com/ via LLViewerMediaWebProfileResponder + * -> LLWebProfile::setAuthCookie() + * 2. LLWebProfile::uploadImage() + * -> GET "https://my-demo.secondlife.com/snapshots/s3_upload_config" via ConfigResponder + * 3. LLWebProfile::post() + * -> POST <config_url> via PostImageResponder + * -> redirect + * -> GET <redirect_url> via PostImageRedirectResponder + */ + +/////////////////////////////////////////////////////////////////////////////// +// LLWebProfileResponders::ConfigResponder + +class LLWebProfileResponders::ConfigResponder : public LLHTTPClient::Responder +{ + LOG_CLASS(LLWebProfileResponders::ConfigResponder); + +public: + ConfigResponder(LLPointer<LLImageFormatted> imagep) + : mImagep(imagep) + { + } + + /*virtual*/ void completedRaw( + U32 status, + const std::string& reason, + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) + { + LLBufferStream istr(channels, buffer.get()); + std::stringstream strstrm; + strstrm << istr.rdbuf(); + const std::string body = strstrm.str(); + + if (status != 200) + { + llwarns << "Failed to get upload config (" << status << ")" << llendl; + LLWebProfile::reportImageUploadStatus(false); + return; + } + + Json::Value root; + Json::Reader reader; + if (!reader.parse(body, root)) + { + llwarns << "Failed to parse upload config: " << reader.getFormatedErrorMessages() << llendl; + LLWebProfile::reportImageUploadStatus(false); + return; + } + + // *TODO: 404 = not supported by the grid + // *TODO: increase timeout or handle 499 Expired + + // Convert config to LLSD. + const Json::Value data = root["data"]; + const std::string upload_url = root["url"].asString(); + LLSD config; + config["acl"] = data["acl"].asString(); + config["AWSAccessKeyId"] = data["AWSAccessKeyId"].asString(); + config["Content-Type"] = data["Content-Type"].asString(); + config["key"] = data["key"].asString(); + config["policy"] = data["policy"].asString(); + config["success_action_redirect"] = data["success_action_redirect"].asString(); + config["signature"] = data["signature"].asString(); + config["add_loc"] = data.get("add_loc", "0").asString(); + config["caption"] = data.get("caption", "").asString(); + + // Do the actual image upload using the configuration. + LL_DEBUGS("Snapshots") << "Got upload config, POSTing image to " << upload_url << ", config=[" << config << "]" << llendl; + LLWebProfile::post(mImagep, config, upload_url); + } + +private: + LLPointer<LLImageFormatted> mImagep; +}; + +/////////////////////////////////////////////////////////////////////////////// +// LLWebProfilePostImageRedirectResponder +class LLWebProfileResponders::PostImageRedirectResponder : public LLHTTPClient::Responder +{ + LOG_CLASS(LLWebProfileResponders::PostImageRedirectResponder); + +public: + /*virtual*/ void completedRaw( + U32 status, + const std::string& reason, + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) + { + if (status != 200) + { + llwarns << "Failed to upload image: " << status << " " << reason << llendl; + LLWebProfile::reportImageUploadStatus(false); + return; + } + + LLBufferStream istr(channels, buffer.get()); + std::stringstream strstrm; + strstrm << istr.rdbuf(); + const std::string body = strstrm.str(); + llinfos << "Image uploaded." << llendl; + LL_DEBUGS("Snapshots") << "Uploading image succeeded. Response: [" << body << "]" << llendl; + LLWebProfile::reportImageUploadStatus(true); + } + +private: + LLPointer<LLImageFormatted> mImagep; +}; + + +/////////////////////////////////////////////////////////////////////////////// +// LLWebProfileResponders::PostImageResponder +class LLWebProfileResponders::PostImageResponder : public LLHTTPClient::Responder +{ + LOG_CLASS(LLWebProfileResponders::PostImageResponder); + +public: + /*virtual*/ void completedHeader(U32 status, const std::string& reason, const LLSD& content) + { + // Viewer seems to fail to follow a 303 redirect on POST request + // (URLRequest Error: 65, Send failed since rewinding of the data stream failed). + // Handle it manually. + if (status == 303) + { + LLSD headers = LLViewerMedia::getHeaders(); + headers["Cookie"] = LLWebProfile::getAuthCookie(); + const std::string& redir_url = content["location"]; + LL_DEBUGS("Snapshots") << "Got redirection URL: " << redir_url << llendl; + LLHTTPClient::get(redir_url, new LLWebProfileResponders::PostImageRedirectResponder, headers); + } + else + { + llwarns << "Unexpected POST status: " << status << " " << reason << llendl; + LL_DEBUGS("Snapshots") << "headers: [" << content << "]" << llendl; + LLWebProfile::reportImageUploadStatus(false); + } + } + + // Override just to suppress warnings. + /*virtual*/ void completedRaw(U32 status, const std::string& reason, + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) + { + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// LLWebProfile + +std::string LLWebProfile::sAuthCookie; +LLWebProfile::status_callback_t LLWebProfile::mStatusCallback; + +// static +void LLWebProfile::uploadImage(LLPointer<LLImageFormatted> image, const std::string& caption, bool add_location) +{ + // Get upload configuration data. + std::string config_url(getProfileURL(LLStringUtil::null) + "snapshots/s3_upload_config"); + config_url += "?caption=" + LLURI::escape(caption); + config_url += "&add_loc=" + std::string(add_location ? "1" : "0"); + + LL_DEBUGS("Snapshots") << "Requesting " << config_url << llendl; + LLSD headers = LLViewerMedia::getHeaders(); + headers["Cookie"] = getAuthCookie(); + LLHTTPClient::get(config_url, new LLWebProfileResponders::ConfigResponder(image), headers); +} + +// static +void LLWebProfile::setAuthCookie(const std::string& cookie) +{ + LL_DEBUGS("Snapshots") << "Setting auth cookie: " << cookie << llendl; + sAuthCookie = cookie; +} + +// static +void LLWebProfile::post(LLPointer<LLImageFormatted> image, const LLSD& config, const std::string& url) +{ + // *TODO: make sure it's a jpeg? + + const std::string boundary = "----------------------------0123abcdefab"; + + LLSD headers = LLViewerMedia::getHeaders(); + headers["Cookie"] = getAuthCookie(); + headers["Content-Type"] = "multipart/form-data; boundary=" + boundary; + + std::ostringstream body; + + // *NOTE: The order seems to matter. + body << "--" << boundary << "\r\n" + << "Content-Disposition: form-data; name=\"key\"\r\n\r\n" + << config["key"].asString() << "\r\n"; + + body << "--" << boundary << "\r\n" + << "Content-Disposition: form-data; name=\"AWSAccessKeyId\"\r\n\r\n" + << config["AWSAccessKeyId"].asString() << "\r\n"; + + body << "--" << boundary << "\r\n" + << "Content-Disposition: form-data; name=\"acl\"\r\n\r\n" + << config["acl"].asString() << "\r\n"; + + body << "--" << boundary << "\r\n" + << "Content-Disposition: form-data; name=\"Content-Type\"\r\n\r\n" + << config["Content-Type"].asString() << "\r\n"; + + body << "--" << boundary << "\r\n" + << "Content-Disposition: form-data; name=\"policy\"\r\n\r\n" + << config["policy"].asString() << "\r\n"; + + body << "--" << boundary << "\r\n" + << "Content-Disposition: form-data; name=\"signature\"\r\n\r\n" + << config["signature"].asString() << "\r\n"; + + body << "--" << boundary << "\r\n" + << "Content-Disposition: form-data; name=\"success_action_redirect\"\r\n\r\n" + << config["success_action_redirect"].asString() << "\r\n"; + + body << "--" << boundary << "\r\n" + << "Content-Disposition: form-data; name=\"file\"; filename=\"snapshot.jpg\"\r\n" + << "Content-Type: image/jpeg\r\n\r\n"; + + // Insert the image data. + // *FIX: Treating this as a string will probably screw it up ... + U8* image_data = image->getData(); + for (S32 i = 0; i < image->getDataSize(); ++i) + { + body << image_data[i]; + } + + body << "\r\n--" << boundary << "--\r\n"; + + // postRaw() takes ownership of the buffer and releases it later. + size_t size = body.str().size(); + U8 *data = new U8[size]; + memcpy(data, body.str().data(), size); + + // Send request, successful upload will trigger posting metadata. + LLHTTPClient::postRaw(url, data, size, new LLWebProfileResponders::PostImageResponder(), headers); +} + +// static +void LLWebProfile::reportImageUploadStatus(bool ok) +{ + if (mStatusCallback) + { + mStatusCallback(ok); + } +} + +// static +std::string LLWebProfile::getAuthCookie() +{ + return sAuthCookie; +} diff --git a/indra/newview/llwebprofile.h b/indra/newview/llwebprofile.h new file mode 100644 index 0000000000..10279bffac --- /dev/null +++ b/indra/newview/llwebprofile.h @@ -0,0 +1,69 @@ +/** + * @file llwebprofile.h + * @brief Web profile access. + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLWEBPROFILE_H +#define LL_LLWEBPROFILE_H + +#include "llimage.h" + +namespace LLWebProfileResponders +{ + class ConfigResponder; + class PostImageResponder; + class PostImageRedirectResponder; +}; + +/** + * @class LLWebProfile + * + * Manages interaction with, a web service allowing the upload of snapshot images + * taken within the viewer. + */ +class LLWebProfile +{ + LOG_CLASS(LLWebProfile); + +public: + typedef boost::function<void(bool ok)> status_callback_t; + + static void uploadImage(LLPointer<LLImageFormatted> image, const std::string& caption, bool add_location); + static void setAuthCookie(const std::string& cookie); + static void setImageUploadResultCallback(status_callback_t cb) { mStatusCallback = cb; } + +private: + friend class LLWebProfileResponders::ConfigResponder; + friend class LLWebProfileResponders::PostImageResponder; + friend class LLWebProfileResponders::PostImageRedirectResponder; + + static void post(LLPointer<LLImageFormatted> image, const LLSD& config, const std::string& url); + static void reportImageUploadStatus(bool ok); + static std::string getAuthCookie(); + + static std::string sAuthCookie; + static status_callback_t mStatusCallback; +}; + +#endif // LL_LLWEBPROFILE_H diff --git a/indra/newview/skins/default/textures/snapshot_download.png b/indra/newview/skins/default/textures/snapshot_download.png Binary files differnew file mode 100644 index 0000000000..c8c6236c96 --- /dev/null +++ b/indra/newview/skins/default/textures/snapshot_download.png diff --git a/indra/newview/skins/default/textures/snapshot_email.png b/indra/newview/skins/default/textures/snapshot_email.png Binary files differnew file mode 100644 index 0000000000..8a1a9bcde9 --- /dev/null +++ b/indra/newview/skins/default/textures/snapshot_email.png diff --git a/indra/newview/skins/default/textures/snapshot_inventory.png b/indra/newview/skins/default/textures/snapshot_inventory.png Binary files differnew file mode 100644 index 0000000000..56487ec443 --- /dev/null +++ b/indra/newview/skins/default/textures/snapshot_inventory.png diff --git a/indra/newview/skins/default/textures/snapshot_profile.png b/indra/newview/skins/default/textures/snapshot_profile.png Binary files differnew file mode 100644 index 0000000000..c8b90fb40b --- /dev/null +++ b/indra/newview/skins/default/textures/snapshot_profile.png diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index bb91d32c6c..0e1f711627 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -547,6 +547,10 @@ with the same filename but different name <texture name="Unknown_Icon" file_name="icons/unknown_icon.png" preload="true" /> <texture name="Snapshot_Off" file_name="bottomtray/Snapshot_Off.png" preload="true" scale.left="4" scale.top="19" scale.right="22" scale.bottom="4" /> + <texture name="Snapshot_Download" file_name="snapshot_download.png" preload="false" /> + <texture name="Snapshot_Email" file_name="snapshot_email.png" preload="false" /> + <texture name="Snapshot_Inventory" file_name="snapshot_inventory.png" preload="false" /> + <texture name="Snapshot_Profile" file_name="snapshot_profile.png" preload="false" /> <texture name="startup_logo" file_name="windows/startup_logo.png" preload="true" /> diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml index 91b4ed6954..bc48561196 100644 --- a/indra/newview/skins/default/xui/en/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml @@ -5,400 +5,254 @@ can_minimize="true" can_close="true" follows="left|top" - height="520" + height="600" layout="topleft" name="Snapshot" help_topic="snapshot" save_rect="true" save_visibility="true" title="SNAPSHOT PREVIEW" - width="245"> + width="470"> <floater.string name="unknown"> unknown </floater.string> - <radio_group - height="70" - label="Snapshot type" - layout="topleft" - left="10" - name="snapshot_type_radio" - top="20" - width="205"> -<!-- - <radio_item - height="16" - label="Share to Web" - layout="topleft" - name="share_to_web" - top_pad="0" /> ---> - <radio_item - height="16" - label="Email" - layout="topleft" - name="postcard" - top_pad="2" /> - <radio_item - height="16" - label="My inventory (L$[AMOUNT])" - layout="topleft" - name="texture" - top_pad="2" /> - <radio_item - height="16" - label="Save to my computer" - layout="topleft" - name="local" - top_pad="2" /> - </radio_group> - <ui_ctrl - height="90" - width="125" + <view_border + bevel_style="in" + follows="left|top" + height="21" + left="10" layout="topleft" - name="thumbnail_placeholder" - top_pad="6" + name="img_info_border" + top="22" + width="50" + /> + <icon + follows="top|left" + height="18" + image_name="Snapshot_Off" + layout="topleft" + left_delta="-5" + mouse_opaque="true" + name="refresh_icon" + top_delta="3" + visible="false" + width="36" /> + <button follows="left|top" - left="10" - /> - <text - type="string" - font="SansSerifSmall" - length="1" - follows="left|top" - height="14" - layout="topleft" - right="-5" - left_delta="0" - halign="right" - name="file_size_label" - top_pad="8" - width="195"> - [SIZE] KB - </text> - <button - follows="left|top" - height="22" - image_overlay="Refresh_Off" - layout="topleft" - left="10" - name="new_snapshot_btn" - width="23" /> - <button - follows="left|top" - height="23" - label="Send" - layout="topleft" - left_pad="5" - right="-5" - name="send_btn" - width="100" /> - <button - follows="left|top" - height="23" - label="Save (L$[AMOUNT])" - layout="topleft" - right="-5" - name="upload_btn" - top_delta="0" - width="110" /> - <flyout_button - follows="left|top" - height="23" - label="Save" - layout="topleft" - right="-5" - name="save_btn" - tool_tip="Save image to a file" - top_delta="0" - width="100"> - <flyout_button.item - label="Save" - name="save_item" - value="save" /> - <flyout_button.item - label="Save As..." - name="saveas_item" - value="save as" /> - </flyout_button> - <button - follows="left|top" - height="23" - label="More" - layout="topleft" - left="10" - name="more_btn" - tool_tip="Advanced options" - width="80" /> + height="22" + image_overlay="Refresh_Off" + layout="topleft" + left_delta="31" + name="new_snapshot_btn" + top_delta="-3" + width="23" /> <button follows="left|top" height="23" - label="Less" + image_overlay="TabIcon_Close_Off" + is_toggle="true" layout="topleft" - left_delta="0" - name="less_btn" + left="240" + name="advanced_options_btn" tool_tip="Advanced options" top_delta="0" - width="80" /> - <button - follows="left|top" - height="23" - label="Cancel" - layout="topleft" - right="-5" - left_pad="5" - name="discard_btn" - width="110" /> - <text - type="string" - length="1" - follows="top|left" - height="12" - layout="topleft" - left="10" - name="type_label2" - top_pad="5" - width="127"> - Size - </text> - <text - type="string" - length="1" - follows="top|left" - height="12" - layout="topleft" - left_pad="5" - name="format_label" - top_delta="0" - width="70"> - Format - </text> - <combo_box - height="23" - label="Resolution" - layout="topleft" - left="10" - name="postcard_size_combo" - width="120"> - <combo_box.item - label="Current Window" - name="CurrentWindow" - value="[i0,i0]" /> - <combo_box.item - label="640x480" - name="640x480" - value="[i640,i480]" /> - <combo_box.item - label="800x600" - name="800x600" - value="[i800,i600]" /> - <combo_box.item - label="1024x768" - name="1024x768" - value="[i1024,i768]" /> - <combo_box.item - label="Custom" - name="Custom" - value="[i-1,i-1]" /> - </combo_box> - <combo_box - height="23" - label="Resolution" - layout="topleft" - left_delta="0" - name="texture_size_combo" - top_delta="0" - width="127"> - <combo_box.item - label="Current Window" - name="CurrentWindow" - value="[i0,i0]" /> - <combo_box.item - label="Small (128x128)" - name="Small(128x128)" - value="[i128,i128]" /> - <combo_box.item - label="Medium (256x256)" - name="Medium(256x256)" - value="[i256,i256]" /> - <combo_box.item - label="Large (512x512)" - name="Large(512x512)" - value="[i512,i512]" /> - <combo_box.item - label="Custom" - name="Custom" - value="[i-1,i-1]" /> - </combo_box> - <combo_box - height="23" - label="Resolution" - layout="topleft" - left_delta="0" - name="local_size_combo" - top_delta="0" - width="127"> - <combo_box.item - label="Current Window" - name="CurrentWindow" - value="[i0,i0]" /> - <combo_box.item - label="320x240" - name="320x240" - value="[i320,i240]" /> - <combo_box.item - label="640x480" - name="640x480" - value="[i640,i480]" /> - <combo_box.item - label="800x600" - name="800x600" - value="[i800,i600]" /> - <combo_box.item - label="1024x768" - name="1024x768" - value="[i1024,i768]" /> - <combo_box.item - label="1280x1024" - name="1280x1024" - value="[i1280,i1024]" /> - <combo_box.item - label="1600x1200" - name="1600x1200" - value="[i1600,i1200]" /> - <combo_box.item - label="Custom" - name="Custom" - value="[i-1,i-1]" /> - </combo_box> - <combo_box - height="23" - label="Format" - layout="topleft" - left_pad="5" - name="local_format_combo" - width="70"> - <combo_box.item - label="PNG" - name="PNG" /> - <combo_box.item - label="JPEG" - name="JPEG" /> - <combo_box.item - label="BMP" - name="BMP" /> - </combo_box> - <spinner - allow_text_entry="false" - decimal_digits="0" - follows="left|top" - height="20" - increment="32" - label="Width" - label_width="40" - layout="topleft" - left="10" - max_val="6016" - min_val="32" - name="snapshot_width" - top_pad="10" - width="95" /> - <spinner - allow_text_entry="false" - decimal_digits="0" - follows="left|top" - height="20" - increment="32" - label="Height" - label_width="40" - layout="topleft" - left_pad="5" - max_val="6016" - min_val="32" - name="snapshot_height" - top_delta="0" - width="95" /> - <check_box - bottom_delta="20" - label="Constrain proportions" - layout="topleft" - left="10" - name="keep_aspect_check" /> - <slider - decimal_digits="0" - follows="left|top" - height="15" - increment="1" - initial_value="75" - label="Image quality" - label_width="124" - layout="topleft" - left_delta="0" - max_val="100" - name="image_quality_slider" - top_pad="5" - width="228" /> - <text - type="string" - length="1" + width="23" /> + <ui_ctrl + height="160" + width="250" + layout="topleft" + name="thumbnail_placeholder" + top="50" + follows="left|top" + left="10" + /> + <view_border + bevel_style="in" + height="21" + width="250" + layout="topleft" + name="img_info_border" + top_pad="3" + follows="left|top" + left_delta="0" + /> + <text + type="string" + font="SansSerifSmall" + length="1" + follows="left|top" + height="14" + layout="topleft" + left_delta="5" + halign="left" + name="image_res_text" + top_delta="5" + width="100"> + [WIDTH] x [HEIGHT] px + </text> + <text + follows="left|top" + font="SansSerifSmall" + height="14" + layout="topleft" + left="200" + length="1" + halign="right" + name="file_size_label" + top_delta="0" + type="string" + width="50"> + [SIZE] KB + </text> + <panel_container follows="left|top" - height="13" + height="360" layout="topleft" - left="10" - name="layer_type_label" - top_pad="5" - width="50"> - Capture: - </text> - <combo_box - height="23" - label="Image Layers" - layout="topleft" - left="30" - name="layer_types" - width="145"> - <combo_box.item - label="Colors" - name="Colors" - value="colors" /> - <combo_box.item - label="Depth" - name="Depth" - value="depth" /> - </combo_box> - <check_box - label="Interface" - layout="topleft" - left="30" + left="0" + name="panel_container" + default_panel_name="panel_snapshot_options" top_pad="10" - width="180" - name="ui_check" /> - <check_box - label="HUDs" - layout="topleft" - left="30" - top_pad="10" - width="180" - name="hud_check" /> - <check_box - label="Keep open after saving" - layout="topleft" - left="10" - top_pad="8" - width="180" - name="keep_open_check" /> - <check_box - label="Freeze frame (fullscreen)" + width="270"> + <panel + class="llpanelsnapshotoptions" + filename="panel_snapshot_options.xml" + follows="all" + layout="topleft" + left="0" + name="panel_snapshot_options" + top="0" /> + <panel + class="llpanelsnapshotprofile" + follows="all" + layout="topleft" + name="panel_snapshot_profile" + filename="panel_snapshot_profile.xml" /> + <panel + class="llpanelsnapshotpostcard" + follows="all" + layout="topleft" + name="panel_snapshot_postcard" + filename="panel_snapshot_postcard.xml" /> + <panel + class="llpanelsnapshotinventory" + follows="all" + layout="topleft" + name="panel_snapshot_inventory" + filename="panel_snapshot_inventory.xml" /> + <panel + class="llpanelsnapshotlocal" + follows="all" + layout="topleft" + name="panel_snapshot_local" + filename="panel_snapshot_local.xml" /> + <panel + class="llpanelpostprogress" + follows="all" + layout="topleft" + name="panel_post_progress" + filename="panel_post_progress.xml" /> + <panel + class="llpanelpostresult" + follows="all" + layout="topleft" + name="panel_post_result" + filename="panel_post_result.xml" /> + </panel_container> + <panel + height="295" layout="topleft" - left="10" - top_pad="8" - width="180" - name="freeze_frame_check" /> - <check_box - label="Auto-refresh" - layout="topleft" - left="10" - top_pad="8" - width="180" - name="auto_snapshot_check" /> + left="270" + name="advanced_options_panel" + top="20" + width="200"> + <text + type="string" + font="SansSerifSmall" + length="1" + follows="left|top" + height="14" + layout="topleft" + left="10" + halign="left" + name="advanced_options_label" + right="-10" + top="10"> + ADVANCED OPTIONS + </text> + <view_border + bevel_style="in" + follows="left|top|right" + height="1" + left="10" + layout="topleft" + name="advanced_options_hr" + right="-10" + top_pad="5" + /> + <text + type="string" + length="1" + follows="left|top" + height="13" + layout="topleft" + left="10" + name="layer_type_label" + top_pad="10" + width="50"> + Capture: + </text> + <combo_box + follows="left|top|right" + height="23" + label="Image Layers" + layout="topleft" + left="30" + name="layer_types" + right="-10"> + <combo_box.item + label="Colors" + name="Colors" + value="colors" /> + <combo_box.item + label="Depth" + name="Depth" + value="depth" /> + </combo_box> + <check_box + label="Interface" + layout="topleft" + left="30" + top_pad="10" + width="180" + name="ui_check" /> + <check_box + label="HUDs" + layout="topleft" + left="30" + top_pad="10" + width="180" + name="hud_check" /> + <check_box + label="Keep open after saving" + layout="topleft" + left="10" + top_pad="8" + width="180" + name="keep_open_check" /> + <check_box + label="Freeze frame (fullscreen)" + layout="topleft" + left="10" + top_pad="8" + width="180" + name="freeze_frame_check" /> + <check_box + label="Auto-refresh" + layout="topleft" + left="10" + top_pad="8" + width="180" + name="auto_snapshot_check" /> + </panel> </floater> diff --git a/indra/newview/skins/default/xui/en/panel_post_progress.xml b/indra/newview/skins/default/xui/en/panel_post_progress.xml new file mode 100644 index 0000000000..418e6e7527 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_post_progress.xml @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + height="380" + layout="topleft" + name="panel_post_progress" + width="490"> + <string + name="postcard_progress_str"> + Sending Email + </string> + <string + name="profile_progress_str"> + Posting + </string> + <string + name="inventory_progress_str"> + Saving to Inventory + </string> + <string + name="local_progress_str"> + Saving to Computer + </string> + <view_border + follows="left|top" + height="110" + layout="topleft" + left="40" + name="rect" + top="120" + width="190" + /> + <loading_indicator + follows="left|top" + height="40" + left_delta="75" + layout="topleft" + top_delta="20" + width="40" + /> + <text + follows="top|left" + font="SansSerifLargeBold" + halign="center" + height="20" + layout="topleft" + left_delta="-75" + length="1" + name="progress_lbl" + translate="false" + type="string" + top_pad="10" + width="190"> + Working + </text> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_post_result.xml b/indra/newview/skins/default/xui/en/panel_post_result.xml new file mode 100644 index 0000000000..4a64b8469b --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_post_result.xml @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + height="380" + layout="topleft" + name="panel_post_result" + width="490"> + <string + name="profile_succeeded_str"> + Your Profile Feed has been updated! + </string> + <string + name="postcard_succeeded_str"> + Email Sent! + </string> + <string + name="inventory_succeeded_str"> + Saved to Inventory! + </string> + <string + name="local_succeeded_str"> + Saved to Computer! + </string> + <string + name="profile_failed_str"> + Failed to update your Profile Feed. + </string> + <string + name="postcard_failed_str"> + Failed to send email. + </string> + <string + name="inventory_failed_str"> + Failed to save to inventory. + </string> + <string + name="local_failed_str"> + Failed to save to computer. + </string> + <text + follows="top|left|right" + font="SansSerif" + halign="center" + height="30" + layout="topleft" + left="20" + length="1" + name="result_lbl" + right="-20" + type="string" + top="100" + word_wrap="true"> + Result + </text> + <button + follows="left|top" + height="22" + label="Done, Close This Window" + layout="topleft" + left="10" + name="close_btn" + top_pad="10" + width="160"> + <commit_callback + function="Snapshot.Result.Close" /> + </button> + <button + follows="right|top" + height="22" + label="Main Menu" + layout="topleft" + name="back_btn" + right="-10" + top_delta="0" + width="80"> + <commit_callback + function="Snapshot.Result.Back" /> + </button> +</panel> diff --git a/indra/newview/skins/default/xui/en/floater_postcard.xml b/indra/newview/skins/default/xui/en/panel_postcard_message.xml index adc2433105..c2a3c70b6e 100644 --- a/indra/newview/skins/default/xui/en/floater_postcard.xml +++ b/indra/newview/skins/default/xui/en/panel_postcard_message.xml @@ -1,28 +1,9 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater - legacy_header_height="18" - can_minimize="false" - can_resize="true" +<panel height="380" layout="topleft" - min_height="380" - min_width="490" - name="Postcard" - help_topic="postcard" - title="EMAIL SNAPSHOT" + name="panel_postcard_message" width="490"> - <floater.string - name="default_subject"> - Postcard from [SECOND_LIFE]. - </floater.string> - <floater.string - name="default_message"> - Check this out! - </floater.string> - <floater.string - name="upload_message"> - Sending... - </floater.string> <text type="string" length="1" @@ -31,18 +12,19 @@ font="SansSerif" layout="topleft" left="12" - name="to_label"> + name="to_label" + top="10"> Recipient's Email: </text> <line_editor control_name="LastPostcardRecipient" - follows="left|top" + follows="left|top|right" height="20" layout="topleft" left_delta="148" name="to_form" - top_delta="-4" - width="150" /> + right="-10" + top_delta="-4" /> <text type="string" length="1" @@ -55,13 +37,13 @@ Your Email: </text> <line_editor - follows="left|top" + follows="left|top|right" height="20" layout="topleft" left_delta="148" name="from_form" - top_delta="-4" - width="150" /> + right="-10" + top_delta="-4" /> <text type="string" length="1" @@ -74,14 +56,14 @@ Your Name: </text> <line_editor - follows="left|top" + follows="left|top|right" height="20" layout="topleft" left_delta="148" max_length_bytes="100" name="name_form" - top_delta="-4" - width="150" /> + right="-10" + top_delta="-4" /> <text type="string" length="1" @@ -94,15 +76,15 @@ Subject: </text> <line_editor - follows="left|top" + follows="left|top|right" height="20" label="Type your subject here." layout="topleft" left_delta="148" max_length_bytes="100" name="subject_form" - top_delta="-4" - width="150" /> + right="-10" + top_delta="-4" /> <text type="string" length="1" @@ -123,9 +105,9 @@ left_delta="0" max_length="700" name="msg_form" - word_wrap="true" + right="-10" top_pad="10" - width="420"> + word_wrap="true"> Type your message here. </text_editor> <button @@ -136,7 +118,10 @@ name="cancel_btn" right="-10" top="350" - width="100" /> + width="100"> + <button.commit_callback + function="Postcard.Cancel" /> + </button> <button follows="right|bottom" height="23" @@ -145,5 +130,8 @@ left_delta="-106" name="send_btn" top_delta="0" - width="100" /> -</floater> + width="100"> + <button.commit_callback + function="Postcard.Send" /> + </button> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_postcard_settings.xml b/indra/newview/skins/default/xui/en/panel_postcard_settings.xml new file mode 100644 index 0000000000..84e3593798 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_postcard_settings.xml @@ -0,0 +1,102 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + height="380" + layout="topleft" + name="panel_postcard_settings" + width="490"> + <combo_box + follows="left|top|right" + height="23" + label="Resolution" + layout="topleft" + left="10" + name="postcard_size_combo" + right="-10" + top_pad="10"> + <combo_box.item + label="Current Window" + name="CurrentWindow" + value="[i0,i0]" /> + <combo_box.item + label="640x480" + name="640x480" + value="[i640,i480]" /> + <combo_box.item + label="800x600" + name="800x600" + value="[i800,i600]" /> + <combo_box.item + label="1024x768" + name="1024x768" + value="[i1024,i768]" /> + <combo_box.item + label="Custom" + name="Custom" + value="[i-1,i-1]" /> + </combo_box> + <spinner + allow_text_entry="false" + decimal_digits="0" + follows="left|top" + height="20" + increment="32" + label="Width" + label_width="40" + layout="topleft" + left="10" + max_val="6016" + min_val="32" + name="postcard_snapshot_width" + top_pad="10" + width="95" /> + <spinner + allow_text_entry="false" + decimal_digits="0" + follows="left|top" + height="20" + increment="32" + label="Height" + label_width="40" + layout="topleft" + left_pad="5" + max_val="6016" + min_val="32" + name="postcard_snapshot_height" + top_delta="0" + width="95" /> + <check_box + bottom_delta="20" + follows="left|top" + label="Constrain proportions" + layout="topleft" + left="10" + name="postcard_keep_aspect_check" /> + <slider + decimal_digits="0" + follows="left|top" + height="15" + increment="1" + initial_value="75" + label="Image quality" + label_width="80" + layout="topleft" + left="10" + max_val="100" + name="image_quality_slider" + top_pad="7" + width="200" /> + <text + type="string" + follows="left|top" + font="SansSerifSmall" + length="1" + height="14" + layout="topleft" + left_pad="-5" + halign="left" + name="image_quality_level" + top_delta="0" + width="60"> + ([QLVL]) + </text> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml new file mode 100644 index 0000000000..cb243fbc5b --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml @@ -0,0 +1,146 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + height="380" + layout="topleft" + name="panel_snapshot_inventory" + width="490"> + <icon + follows="top|left" + height="32" + image_name="Snapshot_Inventory" + layout="topleft" + left="12" + mouse_opaque="true" + name="title_icon" + top="3" + width="32" /> + <text + follows="top|left|right" + font="SansSerif" + height="20" + layout="topleft" + left_pad="12" + length="1" + name="title" + right="-10" + text_color="white" + type="string" + top_delta="8"> + Save to My Inventory + </text> + <view_border + bevel_style="in" + follows="left|top|right" + height="1" + left="10" + layout="topleft" + name="hr" + right="-10" + top_pad="5" + /> + <text + bottom="35" + follows="top|left|right" + font="SansSerif" + height="56" + layout="topleft" + left="12" + length="1" + name="hint_lbl" + top_pad="10" + type="string" + word_wrap="true"> + Saving an image to your inventory costs L$TBD. To save your image as a texture select one of the square formats. + </text> + <combo_box + follows="top|left|right" + height="23" + label="Resolution" + layout="topleft" + left_delta="0" + name="texture_size_combo" + right="-10" + top_pad="10"> + <combo_box.item + label="Current Window" + name="CurrentWindow" + value="[i0,i0]" /> + <combo_box.item + label="Small (128x128)" + name="Small(128x128)" + value="[i128,i128]" /> + <combo_box.item + label="Medium (256x256)" + name="Medium(256x256)" + value="[i256,i256]" /> + <combo_box.item + label="Large (512x512)" + name="Large(512x512)" + value="[i512,i512]" /> + <combo_box.item + label="Custom" + name="Custom" + value="[i-1,i-1]" /> + </combo_box> + <spinner + allow_text_entry="false" + decimal_digits="0" + follows="left|top" + height="20" + increment="32" + label="Width" + label_width="40" + layout="topleft" + left="10" + max_val="6016" + min_val="32" + name="inventory_snapshot_width" + top_pad="10" + width="95" /> + <spinner + allow_text_entry="false" + decimal_digits="0" + follows="left|top" + height="20" + increment="32" + label="Height" + label_width="40" + layout="topleft" + left_pad="5" + max_val="6016" + min_val="32" + name="inventory_snapshot_height" + top_delta="0" + width="95" /> + <check_box + bottom_delta="20" + follows="left|top" + label="Constrain proportions" + layout="topleft" + left="10" + name="inventory_keep_aspect_check" /> + <button + follows="right|bottom" + height="23" + label="Cancel" + layout="topleft" + name="cancel_btn" + right="-10" + top="350" + width="100"> + <button.commit_callback + function="Inventory.Cancel" /> + </button> + <button + follows="right|bottom" + height="23" + label="Save" + layout="topleft" + left_delta="-106" + name="save_btn" + top_delta="0" + width="100"> + <button.commit_callback + function="Inventory.Save" /> + </button> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_local.xml b/indra/newview/skins/default/xui/en/panel_snapshot_local.xml new file mode 100644 index 0000000000..fd2c735df7 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_snapshot_local.xml @@ -0,0 +1,191 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + height="380" + layout="topleft" + name="panel_snapshot_local" + width="490"> + <icon + follows="top|left" + height="32" + image_name="Snapshot_Download" + layout="topleft" + left="12" + mouse_opaque="true" + name="title_icon" + top="3" + width="32" /> + <text + follows="top|left|right" + font="SansSerif" + height="20" + layout="topleft" + left_pad="12" + length="1" + name="title" + right="-10" + text_color="white" + type="string" + top_delta="8"> + Save to My Computer + </text> + <view_border + bevel_style="in" + follows="left|top|right" + height="1" + left="10" + layout="topleft" + name="hr" + right="-10" + top_pad="5" + /> + <combo_box + follows="left|top|right" + height="23" + label="Resolution" + layout="topleft" + left_delta="0" + name="local_size_combo" + right="-10" + top_pad="10"> + <combo_box.item + label="Current Window" + name="CurrentWindow" + value="[i0,i0]" /> + <combo_box.item + label="320x240" + name="320x240" + value="[i320,i240]" /> + <combo_box.item + label="640x480" + name="640x480" + value="[i640,i480]" /> + <combo_box.item + label="800x600" + name="800x600" + value="[i800,i600]" /> + <combo_box.item + label="1024x768" + name="1024x768" + value="[i1024,i768]" /> + <combo_box.item + label="1280x1024" + name="1280x1024" + value="[i1280,i1024]" /> + <combo_box.item + label="1600x1200" + name="1600x1200" + value="[i1600,i1200]" /> + <combo_box.item + label="Custom" + name="Custom" + value="[i-1,i-1]" /> + </combo_box> + <spinner + allow_text_entry="false" + decimal_digits="0" + follows="left|top" + height="20" + increment="32" + label="Width" + label_width="40" + layout="topleft" + left="10" + max_val="6016" + min_val="32" + name="local_snapshot_width" + top_pad="10" + width="95" /> + <spinner + allow_text_entry="false" + decimal_digits="0" + follows="left|top" + height="20" + increment="32" + label="Height" + label_width="40" + layout="topleft" + left_pad="5" + max_val="6016" + min_val="32" + name="local_snapshot_height" + top_delta="0" + width="95" /> + <check_box + bottom_delta="20" + follows="left|top" + label="Constrain proportions" + layout="topleft" + left="10" + name="local_keep_aspect_check" /> + <combo_box + follows="left|top" + height="23" + label="Format" + layout="topleft" + left_delta="0" + name="local_format_combo" + top_pad="10" + width="120"> + <combo_box.item + label="PNG (Lossless)" + name="PNG" /> + <combo_box.item + label="JPEG" + name="JPEG" /> + <combo_box.item + label="BMP (Lossless)" + name="BMP" /> + </combo_box> + <slider + decimal_digits="0" + follows="left|top" + height="15" + increment="1" + initial_value="75" + label="Image quality" + label_width="80" + layout="topleft" + left="10" + max_val="100" + name="image_quality_slider" + top_pad="7" + width="200" /> + <text + type="string" + follows="left|top" + font="SansSerifSmall" + length="1" + height="14" + layout="topleft" + left_pad="-5" + halign="left" + name="image_quality_level" + top_delta="0" + width="60"> + ([QLVL]) + </text> + <button + follows="right|bottom" + height="23" + label="Cancel" + layout="topleft" + name="cancel_btn" + right="-10" + top="350" + width="100"> + <button.commit_callback + function="Local.Cancel" /> + </button> + <button + follows="right|bottom" + height="23" + label="Save" + layout="topleft" + left_delta="-106" + name="save_btn" + top_delta="0" + width="100"> + <button.commit_callback + function="Local.Save" /> + </button> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_options.xml b/indra/newview/skins/default/xui/en/panel_snapshot_options.xml new file mode 100644 index 0000000000..e6324f8923 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_snapshot_options.xml @@ -0,0 +1,80 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + follows="all" + height="240" + layout="topleft" + name="panel_snapshot_options" + width="490"> + <button + follows="left|top|right" + font="SansSerif" + halign="left" + height="38" + image_overlay="Snapshot_Profile" + image_overlay_alignment="left" + imgoverlay_label_space="10" + label="Post to My Profile Feed" + layout="topleft" + left="10" + name="save_to_profile_btn" + pad_left="5" + right="-5" + top="5"> + <button.commit_callback + function="Snapshot.SaveToProfile" /> + </button> + <button + follows="left|top|right" + font="SansSerif" + halign="left" + height="38" + image_overlay="Snapshot_Email" + image_overlay_alignment="left" + imgoverlay_label_space="10" + label="Email" + layout="topleft" + left_delta="0" + name="save_to_email_btn" + pad_left="5" + right="-5" + top_pad="10"> + <button.commit_callback + function="Snapshot.SaveToEmail" /> + </button> + <button + follows="left|top|right" + font="SansSerif" + halign="left" + height="38" + image_overlay="Snapshot_Inventory" + image_overlay_alignment="left" + imgoverlay_label_space="10" + label="Save to My Inventory (L$[AMOUNT])" + layout="topleft" + left_delta="0" + name="save_to_inventory_btn" + pad_left="5" + right="-5" + top_pad="10"> + <button.commit_callback + function="Snapshot.SaveToInventory" /> + </button> + <button + follows="left|top|right" + font="SansSerif" + halign="left" + height="38" + image_overlay="Snapshot_Download" + image_overlay_alignment="left" + imgoverlay_label_space="10" + label="Save to My Computer" + layout="topleft" + left_delta="0" + name="save_to_computer_btn" + pad_left="5" + right="-5" + top_pad="10"> + <button.commit_callback + function="Snapshot.SaveToComputer" /> + </button> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml new file mode 100644 index 0000000000..fc041e07bd --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml @@ -0,0 +1,107 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + height="380" + layout="topleft" + name="panel_snapshot_postcard" + width="490"> + <string + name="default_subject"> + Postcard from [SECOND_LIFE]. + </string> + <string + name="default_message"> + Check this out! + </string> + <string + name="upload_message"> + Sending... + </string> + <string + name="default_subject"> + Postcard from [SECOND_LIFE]. + </string> + <string + name="default_message"> + Check this out! + </string> + <icon + follows="top|left" + height="24" + image_name="Snapshot_Email" + layout="topleft" + left="12" + mouse_opaque="true" + name="title_icon" + top="5" + width="24" /> + <text + follows="top|left|right" + font="SansSerif" + height="20" + layout="topleft" + left_pad="12" + length="1" + name="title" + right="-10" + text_color="white" + type="string" + top_delta="6"> + Email + </text> + <button + follows="right|top" + height="23" + is_toggle="true" + label="Message" + layout="topleft" + name="message_btn" + right="-82" + top_delta="-7" + width="70"> + <button.commit_callback + function="Postcard.Message" /> + </button> + <button + follows="right|top" + height="23" + is_toggle="true" + label="Settings" + layout="topleft" + name="settings_btn" + top_delta="0" + right="-10" + width="70"> + <button.commit_callback + function="Postcard.Settings" /> + </button> + <view_border + bevel_style="in" + follows="left|top|right" + height="1" + left="10" + layout="topleft" + name="hr" + right="-10" + top_pad="5" + /> + <panel_container + follows="all" + height="340" + layout="topleft" + left="0" + name="postcard_panel_container" + default_panel_name="panel_postcard_message" + top_pad="10" + width="490"> + <panel + follows="all" + layout="topleft" + name="panel_postcard_message" + filename="panel_postcard_message.xml" /> + <panel + follows="all" + layout="topleft" + name="panel_postcard_settings" + filename="panel_postcard_settings.xml" /> + </panel_container> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_profile.xml b/indra/newview/skins/default/xui/en/panel_snapshot_profile.xml new file mode 100644 index 0000000000..e03508f5cc --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_snapshot_profile.xml @@ -0,0 +1,165 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + height="380" + layout="topleft" + name="panel_snapshot_profile" + width="490"> + <icon + follows="top|left" + height="32" + image_name="Snapshot_Profile" + layout="topleft" + left="12" + mouse_opaque="true" + name="title_icon" + top="3" + width="32" /> + <text + follows="top|left|right" + font="SansSerif" + height="20" + layout="topleft" + left_pad="12" + length="1" + name="title" + right="-10" + text_color="white" + type="string" + top_delta="8"> + Post to My Profile Feed + </text> + <view_border + bevel_style="in" + follows="left|top|right" + height="1" + left="10" + layout="topleft" + name="hr" + right="-10" + top_pad="5" + /> + <combo_box + follows="left|top" + height="23" + label="Resolution" + layout="topleft" + left_delta="0" + name="profile_size_combo" + top_pad="10" + width="250"> + <combo_box.item + label="Current Window" + name="CurrentWindow" + value="[i0,i0]" /> + <combo_box.item + label="640x480" + name="640x480" + value="[i640,i480]" /> + <combo_box.item + label="800x600" + name="800x600" + value="[i800,i600]" /> + <combo_box.item + label="1024x768" + name="1024x768" + value="[i1024,i768]" /> + <combo_box.item + label="Custom" + name="Custom" + value="[i-1,i-1]" /> + </combo_box> + <spinner + allow_text_entry="false" + decimal_digits="0" + follows="left|top" + height="20" + increment="32" + label="Width" + label_width="40" + layout="topleft" + left="10" + max_val="6016" + min_val="32" + name="profile_snapshot_width" + top_pad="10" + width="95" /> + <spinner + allow_text_entry="false" + decimal_digits="0" + follows="left|top" + height="20" + increment="32" + label="Height" + label_width="40" + layout="topleft" + left_pad="5" + max_val="6016" + min_val="32" + name="profile_snapshot_height" + top_delta="0" + width="95" /> + <check_box + bottom_delta="20" + label="Constrain proportions" + layout="topleft" + left="10" + name="profile_keep_aspect_check" /> + <text + length="1" + follows="top|left|right" + font="SansSerif" + height="16" + layout="topleft" + left="12" + name="caption_label" + right="-10" + top_pad="10" + type="string"> + Caption: + </text> + <text_editor + follows="all" + height="170" + layout="topleft" + left_delta="0" + length="1" + max_length="700" + name="caption" + right="-10" + top_pad="5" + type="string" + word_wrap="true"> + </text_editor> + <check_box + follows="left|bottom" + initial_value="true" + label="Include location" + layout="topleft" + left_delta="0" + name="add_location_cb" + top_pad="15" /> + <button + follows="right|bottom" + height="23" + label="Cancel" + layout="topleft" + name="cancel_btn" + right="-10" + top="350" + width="100"> + <button.commit_callback + function="PostToProfile.Cancel" /> + </button> + <button + follows="right|bottom" + height="23" + label="Post" + layout="topleft" + left_delta="-106" + name="post_btn" + top_delta="0" + width="100"> + <button.commit_callback + function="PostToProfile.Send" /> + </button> +</panel> diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index ec230773cc..befcc5dd87 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -3724,4 +3724,12 @@ Try enclosing path to the editor with double quotes. <string name="Wrap">Wrap</string> <string name="Preview">Preview</string> <string name="Normal">Normal</string> + + <!-- Snapshot image quality levels --> + <string name="snapshot_quality_very_low">Very Low</string> + <string name="snapshot_quality_low">Low</string> + <string name="snapshot_quality_medium">Medium</string> + <string name="snapshot_quality_high">High</string> + <string name="snapshot_quality_very_high">Very High</string> + </strings> |