summaryrefslogtreecommitdiff
path: root/indra/newview/llpreviewtexture.cpp
diff options
context:
space:
mode:
authorJames Cook <james@lindenlab.com>2007-01-02 08:33:20 +0000
committerJames Cook <james@lindenlab.com>2007-01-02 08:33:20 +0000
commit420b91db29485df39fd6e724e782c449158811cb (patch)
treeb471a94563af914d3ed3edd3e856d21cb1b69945 /indra/newview/llpreviewtexture.cpp
Print done when done.
Diffstat (limited to 'indra/newview/llpreviewtexture.cpp')
-rw-r--r--indra/newview/llpreviewtexture.cpp365
1 files changed, 365 insertions, 0 deletions
diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp
new file mode 100644
index 0000000000..a50ded3b53
--- /dev/null
+++ b/indra/newview/llpreviewtexture.cpp
@@ -0,0 +1,365 @@
+/**
+ * @file llpreviewtexture.cpp
+ * @brief LLPreviewTexture class implementation
+ *
+ * Copyright (c) 2002-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpreviewtexture.h"
+
+#include "llviewerimage.h"
+#include "llviewerimagelist.h"
+#include "llresmgr.h"
+#include "llagent.h"
+#include "llbutton.h"
+#include "llui.h"
+#include "llinventoryview.h"
+#include "llinventory.h"
+#include "llviewerwindow.h"
+#include "lltextbox.h"
+#include "llimagetga.h"
+#include "llfilepicker.h"
+#include "llvieweruictrlfactory.h"
+
+const S32 PREVIEW_TEXTURE_MIN_WIDTH = 300;
+const S32 PREVIEW_TEXTURE_MIN_HEIGHT = 120;
+
+const S32 CLIENT_RECT_VPAD = 4;
+
+const F32 SECONDS_TO_SHOW_FILE_SAVED_MSG = 8.f;
+
+LLPreviewTexture::LLPreviewTexture(const std::string& name,
+ const LLRect& rect,
+ const std::string& title,
+ const LLUUID& item_uuid,
+ const LLUUID& object_id,
+ BOOL show_keep_discard)
+: LLPreview(name, rect, title, item_uuid, object_id, TRUE, PREVIEW_TEXTURE_MIN_WIDTH, PREVIEW_TEXTURE_MIN_HEIGHT ),
+ mLoadingFullImage( FALSE ),
+ mShowKeepDiscard(show_keep_discard),
+ mCopyToInv(FALSE),
+ mIsCopyable(FALSE),
+ mLastHeight(0),
+ mLastWidth(0)
+{
+ LLInventoryItem *item = getItem();
+ if(item)
+ {
+ mImageID = item->getAssetUUID();
+ const LLPermissions& perm = item->getPermissions();
+ U32 mask = PERM_NONE;
+ if(perm.getOwner() == gAgent.getID())
+ {
+ mask = perm.getMaskBase();
+ }
+ else if(gAgent.isInGroup(perm.getGroup()))
+ {
+ mask = perm.getMaskGroup();
+ }
+ else
+ {
+ mask = perm.getMaskEveryone();
+ }
+ if((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
+ {
+ mIsCopyable = TRUE;
+ }
+ }
+
+ init();
+
+ setTitle(title);
+
+ if (!getHost())
+ {
+ LLRect curRect = getRect();
+ translate(rect.mLeft - curRect.mLeft, rect.mTop - curRect.mTop);
+ }
+}
+
+
+// Note: uses asset_id as a dummy item id.
+LLPreviewTexture::LLPreviewTexture(
+ const std::string& name,
+ const LLRect& rect,
+ const std::string& title,
+ const LLUUID& asset_id,
+ BOOL copy_to_inv)
+ :
+ LLPreview(
+ name,
+ rect,
+ title,
+ asset_id,
+ LLUUID::null,
+ TRUE,
+ PREVIEW_TEXTURE_MIN_WIDTH,
+ PREVIEW_TEXTURE_MIN_HEIGHT ),
+ mImageID(asset_id),
+ mLoadingFullImage( FALSE ),
+ mShowKeepDiscard(FALSE),
+ mCopyToInv(copy_to_inv),
+ mIsCopyable(TRUE),
+ mLastHeight(0),
+ mLastWidth(0)
+{
+
+ init();
+
+ setTitle(title);
+
+ LLRect curRect = getRect();
+ translate(curRect.mLeft - rect.mLeft, curRect.mTop - rect.mTop);
+
+}
+
+
+LLPreviewTexture::~LLPreviewTexture()
+{
+ if( mLoadingFullImage )
+ {
+ getWindow()->decBusyCount();
+ }
+
+ mImage = NULL;
+}
+
+
+void LLPreviewTexture::init()
+{
+
+
+ if (mCopyToInv)
+ {
+ gUICtrlFactory->buildFloater(this,"floater_preview_embedded_texture.xml");
+
+ childSetAction("Copy To Inventory",LLPreview::onBtnCopyToInv,this);
+ }
+
+ else if (mShowKeepDiscard)
+ {
+ gUICtrlFactory->buildFloater(this,"floater_preview_texture_keep_discard.xml");
+
+ childSetAction("Keep",onKeepBtn,this);
+ childSetAction("Discard",onDiscardBtn,this);
+ }
+
+ else
+ {
+ gUICtrlFactory->buildFloater(this,"floater_preview_texture.xml");
+ }
+
+
+ if (!mCopyToInv)
+ {
+ LLInventoryItem* item = getItem();
+
+ childSetCommitCallback("desc", LLPreview::onText, this);
+ childSetText("desc", item->getDescription());
+ childSetPrevalidate("desc", &LLLineEditor::prevalidatePrintableNotPipe);
+ }
+}
+
+
+// virtual
+BOOL LLPreviewTexture::canSaveAs()
+{
+ return mIsCopyable && !mLoadingFullImage && mImage.notNull() && !mImage->isMissingAsset();
+}
+
+
+// virtual
+void LLPreviewTexture::saveAs()
+{
+ if( !mLoadingFullImage )
+ {
+ LLFilePicker& file_picker = LLFilePicker::instance();
+ if( !file_picker.getSaveFile( LLFilePicker::FFSAVE_TGA ) )
+ {
+ // User canceled save.
+ return;
+ }
+ mSaveFileName = file_picker.getFirstFile();
+ mLoadingFullImage = TRUE;
+ getWindow()->incBusyCount();
+ mImage->setLoadedCallback( LLPreviewTexture::onFileLoadedForSave,
+ 0,
+ TRUE,
+ new LLUUID( mItemUUID ) );
+ }
+}
+
+
+// static
+void LLPreviewTexture::onFileLoadedForSave(BOOL success,
+ LLViewerImage *src_vi,
+ LLImageRaw* src,
+ LLImageRaw* aux_src,
+ S32 discard_level,
+ BOOL final,
+ void* userdata)
+{
+ LLUUID* item_uuid = (LLUUID*) userdata;
+ LLPreviewTexture* self = NULL;
+ preview_map_t::iterator found_it = LLPreview::sInstances.find(*item_uuid);
+ if(found_it != LLPreview::sInstances.end())
+ {
+ self = (LLPreviewTexture*) found_it->second;
+ }
+
+ if( final || !success )
+ {
+ delete item_uuid;
+
+ if( self )
+ {
+ self->getWindow()->decBusyCount();
+ self->mLoadingFullImage = FALSE;
+ }
+ }
+
+ if( self && final && success )
+ {
+ LLPointer<LLImageTGA> image_tga = new LLImageTGA;
+ if( !image_tga->encode( src ) )
+ {
+ LLStringBase<char>::format_map_t args;
+ args["[FILE]"] = self->mSaveFileName;
+ gViewerWindow->alertXml("CannotEncodeFile", args);
+ }
+ else if( !image_tga->save( self->mSaveFileName ) )
+ {
+ LLStringBase<char>::format_map_t args;
+ args["[FILE]"] = self->mSaveFileName;
+ gViewerWindow->alertXml("CannotWriteFile", args);
+ }
+ else
+ {
+ self->mSavedFileTimer.reset();
+ self->mSavedFileTimer.setTimerExpirySec( SECONDS_TO_SHOW_FILE_SAVED_MSG );
+ }
+
+ self->mSaveFileName.clear();
+ }
+
+ if( self && !success )
+ {
+ gViewerWindow->alertXml("CannotDownloadFile");
+ }
+}
+
+
+// It takes a while until we get height and width information.
+// When we receive it, reshape the window accordingly.
+void LLPreviewTexture::updateAspectRatio()
+{
+ if (!mImage) return;
+
+ S32 image_height = llmax(1, mImage->getHeight(0));
+ S32 image_width = llmax(1, mImage->getWidth(0));
+ // Attempt to make the image 1:1 on screen.
+ // If that fails, cut width by half.
+ S32 client_width = image_width;
+ S32 horiz_pad = 2 * (LLPANEL_BORDER_WIDTH + PREVIEW_PAD) + PREVIEW_RESIZE_HANDLE_SIZE;
+ S32 screen_width = gViewerWindow->getWindowWidth();
+ S32 max_client_width = screen_width - horiz_pad;
+
+ while (client_width > max_client_width)
+ {
+ client_width /= 2;
+ }
+
+ // Demand width at least 128
+ if (client_width < 128)
+ {
+ client_width = 128;
+ }
+
+ S32 view_width = client_width + horiz_pad;
+
+ // Adjust the height based on the width computed above.
+ F32 inv_aspect_ratio = (F32) image_height / (F32) image_width;
+ S32 client_height = llround(client_width * inv_aspect_ratio);
+ S32 view_height =
+ PREVIEW_HEADER_SIZE + // header (includes top border)
+ client_height + 2 * CLIENT_RECT_VPAD + // texture plus uniform spacing (which leaves room for resize handle)
+ LLPANEL_BORDER_WIDTH; // bottom border
+
+ // set text on dimensions display (should be moved out of here and into a callback of some sort)
+ childSetTextArg("dimensions", "[WIDTH]", llformat("%d", mImage->mFullWidth));
+ childSetTextArg("dimensions", "[HEIGHT]", llformat("%d", mImage->mFullHeight));
+
+ // add space for dimensions
+ S32 info_height = 0;
+ LLRect dim_rect;
+ childGetRect("dimensions", dim_rect);
+ S32 dim_height = dim_rect.getHeight();
+ info_height += dim_height + CLIENT_RECT_VPAD;
+ view_height += info_height;
+
+ S32 button_height = 0;
+ if (mShowKeepDiscard || mCopyToInv) { //mCopyToInvBtn
+
+ // add space for buttons
+ view_height += BTN_HEIGHT + CLIENT_RECT_VPAD;
+ button_height = BTN_HEIGHT + PREVIEW_PAD;
+ }
+
+ LLRect window_rect(0, mRect.getHeight(), mRect.getWidth(), 0);
+ window_rect.mTop -= (PREVIEW_HEADER_SIZE + CLIENT_RECT_VPAD);
+ window_rect.mBottom += PREVIEW_BORDER + button_height + CLIENT_RECT_VPAD + info_height + CLIENT_RECT_VPAD;
+ LLMultiFloater* hostp = getHost();
+ if (hostp)
+ {
+ // try to keep aspect ratio when hosted, as hosting view can resize without user input
+ mClientRect.setLeftTopAndSize(window_rect.getCenterX() - (client_width / 2), window_rect.mTop, client_width, client_height);
+ }
+ else
+ {
+ mClientRect.setLeftTopAndSize(LLPANEL_BORDER_WIDTH + PREVIEW_PAD + 6,
+ mRect.getHeight() - (PREVIEW_HEADER_SIZE + CLIENT_RECT_VPAD),
+ mRect.getWidth() - horiz_pad,
+ mRect.getHeight() - (view_height - client_height) - 8);
+ }
+
+ if (mImage->mFullHeight > mLastHeight && mImage->mFullWidth > mLastWidth)
+ {
+ mLastWidth = image_width;
+ mLastHeight = image_height;
+
+ S32 old_top = mRect.mTop;
+ S32 old_left = mRect.mLeft;
+ if (hostp)
+ {
+ hostp->growToFit(this, view_width, view_height);
+ }
+ else
+ {
+ reshape( view_width, view_height );
+ S32 new_bottom = old_top - mRect.getHeight();
+ setOrigin( old_left, new_bottom );
+ }
+
+ // Try to keep whole view onscreen, don't allow partial offscreen.
+ gFloaterView->adjustToFitScreen(this, FALSE);
+ }
+}
+
+void LLPreviewTexture::loadAsset()
+{
+ mImage = gImageList.getImage(mImageID, MIPMAP_FALSE, FALSE);
+ mImage->setBoostLevel(LLViewerImage::BOOST_PREVIEW);
+ mAssetStatus = PREVIEW_ASSET_LOADING;
+}
+
+LLPreview::EAssetStatus LLPreviewTexture::getAssetStatus()
+{
+ if (mImage.notNull() && (mImage->mFullWidth * mImage->mFullHeight > 0))
+ {
+ mAssetStatus = PREVIEW_ASSET_LOADED;
+ }
+ return mAssetStatus;
+}