diff options
author | James Cook <james@lindenlab.com> | 2007-01-02 08:33:20 +0000 |
---|---|---|
committer | James Cook <james@lindenlab.com> | 2007-01-02 08:33:20 +0000 |
commit | 420b91db29485df39fd6e724e782c449158811cb (patch) | |
tree | b471a94563af914d3ed3edd3e856d21cb1b69945 /indra/newview/llpreviewtexture.cpp |
Print done when done.
Diffstat (limited to 'indra/newview/llpreviewtexture.cpp')
-rw-r--r-- | indra/newview/llpreviewtexture.cpp | 365 |
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; +} |