diff options
Diffstat (limited to 'indra/newview/llpaneleditwearable.cpp')
-rw-r--r-- | indra/newview/llpaneleditwearable.cpp | 247 |
1 files changed, 203 insertions, 44 deletions
diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index a1a9300ec2..85bddab02c 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -2,31 +2,25 @@ * @file llpaneleditwearable.cpp * @brief UI panel for editing of a particular wearable item. * - * $LicenseInfo:firstyear=2009&license=viewergpl$ - * - * Copyright (c) 2009-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * 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. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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 * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -47,6 +41,7 @@ #include "llvoavatarself.h" #include "lltexteditor.h" #include "lltextbox.h" +#include "llaccordionctrl.h" #include "llaccordionctrltab.h" #include "llagentwearables.h" #include "llscrollingpanelparam.h" @@ -61,6 +56,10 @@ #include "llagentcamera.h" #include "llmorphview.h" +#include "llcommandhandler.h" +#include "lltextutil.h" +#include "llappearancemgr.h" + // register panel with appropriate XML static LLRegisterPanelClassWrapper<LLPanelEditWearable> t_edit_wearable("panel_edit_wearable"); @@ -379,6 +378,31 @@ LLEditWearableDictionary::PickerControlEntry::PickerControlEntry(ETextureIndex t { } +/** + * Class to prevent hack in LLButton's constructor and use paddings declared in xml. + */ +class LLLabledBackButton : public LLButton +{ +public: + struct Params : public LLInitParam::Block<Params, LLButton::Params> + { + Params() {} + }; +protected: + friend class LLUICtrlFactory; + LLLabledBackButton(const Params&); +}; + +static LLDefaultChildRegistry::Register<LLLabledBackButton> labeled_back_btn("labeled_back_button"); + +LLLabledBackButton::LLLabledBackButton(const Params& params) +: LLButton(params) +{ + // override hack in LLButton's constructor to use paddings have been set in xml + setLeftHPad(params.pad_left); + setRightHPad(params.pad_right); +} + // Helper functions. static const texture_vec_t null_texture_vec; @@ -608,6 +632,65 @@ LLPanelEditWearable::~LLPanelEditWearable() } +bool LLPanelEditWearable::changeHeightUnits(const LLSD& new_value) +{ + updateMetricLayout( new_value.asBoolean() ); + updateTypeSpecificControls(LLWearableType::WT_SHAPE); + return true; +} + +void LLPanelEditWearable::updateMetricLayout(BOOL new_value) +{ + LLUIString current_metric, replacment_metric; + current_metric = new_value ? mMeters : mFeet; + replacment_metric = new_value ? mFeet : mMeters; + mHeigthValue.setArg( "[METRIC1]", current_metric.getString() ); + mReplacementMetricUrl.setArg( "[URL_METRIC2]", std::string("[secondlife:///app/metricsystem ") + replacment_metric.getString() + std::string("]")); +} + +void LLPanelEditWearable::updateAvatarHeightLabel() +{ + mTxtAvatarHeight->setText(LLStringUtil::null); + LLStyle::Params param; + param.color = mAvatarHeigthLabelColor; + mTxtAvatarHeight->appendText(mHeigth, false, param); + param.color = mAvatarHeigthValueLabelColor; + mTxtAvatarHeight->appendText(mHeigthValue, false, param); + param.color = mAvatarHeigthLabelColor; // using mAvatarHeigthLabelColor for '/' separator + mTxtAvatarHeight->appendText(" / ", false, param); + mTxtAvatarHeight->appendText(this->mReplacementMetricUrl, false, param); +} + +void LLPanelEditWearable::onWearablePanelVisibilityChange(const LLSD &in_visible_chain, LLAccordionCtrl* accordion_ctrl) +{ + if (in_visible_chain.asBoolean() && accordion_ctrl != NULL) + { + accordion_ctrl->expandDefaultTab(); + } +} + +void LLPanelEditWearable::setWearablePanelVisibilityChangeCallback(LLPanel* bodypart_panel) +{ + if (bodypart_panel != NULL) + { + LLAccordionCtrl* accordion_ctrl = bodypart_panel->getChild<LLAccordionCtrl>("wearable_accordion"); + + if (accordion_ctrl != NULL) + { + bodypart_panel->setVisibleCallback( + boost::bind(&LLPanelEditWearable::onWearablePanelVisibilityChange, this, _2, accordion_ctrl)); + } + else + { + llwarns << "accordion_ctrl is NULL" << llendl; + } + } + else + { + llwarns << "bodypart_panel is NULL" << llendl; + } +} + // virtual BOOL LLPanelEditWearable::postBuild() { @@ -616,10 +699,12 @@ BOOL LLPanelEditWearable::postBuild() mBtnRevert->setClickedCallback(boost::bind(&LLPanelEditWearable::onRevertButtonClicked, this)); mBtnBack = getChild<LLButton>("back_btn"); + mBackBtnLabel = mBtnBack->getLabelUnselected(); + mBtnBack->setLabel(LLStringUtil::null); // handled at appearance panel level? //mBtnBack->setClickedCallback(boost::bind(&LLPanelEditWearable::onBackButtonClicked, this)); - mTextEditor = getChild<LLTextEditor>("description"); + mNameEditor = getChild<LLLineEditor>("description"); mPanelTitle = getChild<LLTextBox>("edit_wearable_title"); mDescTitle = getChild<LLTextBox>("description_text"); @@ -634,6 +719,14 @@ BOOL LLPanelEditWearable::postBuild() mPanelEyes = getChild<LLPanel>("edit_eyes_panel"); mPanelHair = getChild<LLPanel>("edit_hair_panel"); + // Setting the visibility callback is applied only to the bodyparts panel + // because currently they are the only ones whose 'wearable_accordion' has + // multiple accordion tabs (see EXT-8164 for details). + setWearablePanelVisibilityChangeCallback(mPanelShape); + setWearablePanelVisibilityChangeCallback(mPanelSkin); + setWearablePanelVisibilityChangeCallback(mPanelEyes); + setWearablePanelVisibilityChangeCallback(mPanelHair); + //clothes mPanelShirt = getChild<LLPanel>("edit_shirt_panel"); mPanelPants = getChild<LLPanel>("edit_pants_panel"); @@ -700,6 +793,20 @@ BOOL LLPanelEditWearable::postBuild() for_each_picker_ctrl_entry <LLTextureCtrl> (getPanel(type), type, boost::bind(init_texture_ctrl, this, _1, _2)); } + // init all strings + mMeters = mPanelShape->getString("meters"); + mFeet = mPanelShape->getString("feet"); + mHeigth = mPanelShape->getString("height") + " "; + mHeigthValue = "[HEIGHT] [METRIC1]"; + mReplacementMetricUrl = "[URL_METRIC2]"; + + std::string color = mPanelShape->getString("heigth_label_color"); + mAvatarHeigthLabelColor = LLUIColorTable::instance().getColor(color, LLColor4::green); + color = mPanelShape->getString("heigth_value_label_color"); + mAvatarHeigthValueLabelColor = LLUIColorTable::instance().getColor(color, LLColor4::green); + gSavedSettings.getControl("HeightUnits")->getSignal()->connect(boost::bind(&LLPanelEditWearable::changeHeightUnits, this, _2)); + updateMetricLayout(gSavedSettings.getBOOL("HeightUnits")); + return TRUE; } @@ -711,7 +818,7 @@ BOOL LLPanelEditWearable::isDirty() const if (mWearablePtr) { if (mWearablePtr->isDirty() || - mWearablePtr->getName().compare(mTextEditor->getText()) != 0) + mWearableItem->getName().compare(mNameEditor->getText()) != 0) { isDirty = TRUE; } @@ -749,7 +856,7 @@ void LLPanelEditWearable::onRevertButtonClicked(void* userdata) void LLPanelEditWearable::onSaveAsButtonClicked() { LLSD args; - args["DESC"] = mTextEditor->getText(); + args["DESC"] = mNameEditor->getText(); LLNotificationsUtil::add("SaveWearableAs", args, LLSD(), boost::bind(&LLPanelEditWearable::saveAsCallback, this, _1, _2)); } @@ -763,8 +870,8 @@ void LLPanelEditWearable::saveAsCallback(const LLSD& notification, const LLSD& r LLStringUtil::trim(wearable_name); if( !wearable_name.empty() ) { - mTextEditor->setText(wearable_name); - saveChanges(); + mNameEditor->setText(wearable_name); + saveChanges(true); } } } @@ -821,7 +928,7 @@ void LLPanelEditWearable::onTexturePickerCommit(const LLUICtrl* ctrl) { // Set the new version LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(texture_ctrl->getImageAssetID()); - if( image->getID().isNull() ) + if( image->getID() == IMG_DEFAULT ) { image = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR); } @@ -873,7 +980,6 @@ void LLPanelEditWearable::updatePanelPickerControls(LLWearableType::EType type) return; bool is_modifiable = false; - bool is_complete = false; bool is_copyable = false; if(mWearableItem) @@ -881,17 +987,15 @@ void LLPanelEditWearable::updatePanelPickerControls(LLWearableType::EType type) const LLPermissions& perm = mWearableItem->getPermissions(); is_modifiable = perm.allowModifyBy(gAgent.getID(), gAgent.getGroupID()); is_copyable = perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID()); - is_complete = mWearableItem->isFinished(); } - if (is_modifiable && is_complete) + if (is_modifiable) { // Update picker controls for_each_picker_ctrl_entry <LLColorSwatchCtrl> (panel, type, boost::bind(update_color_swatch_ctrl, this, _1, _2)); for_each_picker_ctrl_entry <LLTextureCtrl> (panel, type, boost::bind(update_texture_ctrl, this, _1, _2)); } - - if (!is_modifiable || !is_complete || !is_copyable) + else { // Disable controls for_each_picker_ctrl_entry <LLColorSwatchCtrl> (panel, type, boost::bind(set_enabled_color_swatch_ctrl, false, _1, _2)); @@ -899,7 +1003,7 @@ void LLPanelEditWearable::updatePanelPickerControls(LLWearableType::EType type) } } -void LLPanelEditWearable::saveChanges() +void LLPanelEditWearable::saveChanges(bool force_save_as) { if (!mWearablePtr || !isDirty()) { @@ -908,15 +1012,18 @@ void LLPanelEditWearable::saveChanges() } U32 index = gAgentWearables.getWearableIndex(mWearablePtr); - - if (mWearablePtr->getName().compare(mTextEditor->getText()) != 0) + + std::string new_name = mNameEditor->getText(); + if (force_save_as) { // the name of the wearable has changed, re-save wearable with new name - gAgentWearables.saveWearableAs(mWearablePtr->getType(), index, mTextEditor->getText(), FALSE); + LLAppearanceMgr::instance().removeCOFItemLinks(mWearablePtr->getItemID(),false); + gAgentWearables.saveWearableAs(mWearablePtr->getType(), index, new_name, FALSE); + mNameEditor->setText(mWearableItem->getName()); } else { - gAgentWearables.saveWearable(mWearablePtr->getType(), index); + gAgentWearables.saveWearable(mWearablePtr->getType(), index, TRUE, new_name); } } @@ -929,7 +1036,10 @@ void LLPanelEditWearable::revertChanges() } mWearablePtr->revertValues(); - mTextEditor->setText(mWearablePtr->getName()); + mNameEditor->setText(mWearableItem->getName()); + updatePanelPickerControls(mWearablePtr->getType()); + updateTypeSpecificControls(mWearablePtr->getType()); + gAgentAvatarp->wearableUpdated(mWearablePtr->getType(), FALSE); } void LLPanelEditWearable::showWearable(LLWearable* wearable, BOOL show) @@ -968,10 +1078,11 @@ void LLPanelEditWearable::showWearable(LLWearable* wearable, BOOL show) if (show) { mPanelTitle->setText(title); + mPanelTitle->setToolTip(title); mDescTitle->setText(description_title); // set name - mTextEditor->setText(wearable->getName()); + mNameEditor->setText(mWearableItem->getName()); updatePanelPickerControls(type); updateTypeSpecificControls(type); @@ -1079,7 +1190,6 @@ void LLPanelEditWearable::changeCamera(U8 subpart) } // Update the camera - gMorphView->setCameraDistToDefault(); gMorphView->setCameraTargetJoint( gAgentAvatarp->getJoint( subpart_entry->mTargetJoint ) ); gMorphView->setCameraTargetOffset( subpart_entry->mTargetOffset ); gMorphView->setCameraOffset( subpart_entry->mCameraOffset ); @@ -1107,12 +1217,22 @@ void LLPanelEditWearable::toggleTypeSpecificControls(LLWearableType::EType type) void LLPanelEditWearable::updateTypeSpecificControls(LLWearableType::EType type) { + const F32 ONE_METER = 1.0; + const F32 ONE_FOOT = 0.3048 * ONE_METER; // in meters // Update controls specific to shape editing panel. if (type == LLWearableType::WT_SHAPE) { // Update avatar height - std::string avatar_height_str = llformat("%.2f", gAgentAvatarp->mBodySize.mV[VZ]); - mTxtAvatarHeight->setTextArg("[HEIGHT]", avatar_height_str); + F32 new_size = gAgentAvatarp->mBodySize.mV[VZ]; + if (gSavedSettings.getBOOL("HeightUnits") == FALSE) + { + // convert meters to feet + new_size = new_size / ONE_FOOT; + } + + std::string avatar_height_str = llformat("%.2f", new_size); + mHeigthValue.setArg("[HEIGHT]", avatar_height_str); + updateAvatarHeightLabel(); } if (LLWearableType::WT_ALPHA == type) @@ -1245,8 +1365,8 @@ void LLPanelEditWearable::getSortedParams(value_map_t &sorted_params, const std: { LLViewerVisualParam *param = (LLViewerVisualParam*) *iter; - if (param->getID() == -1 - || param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE + if (param->getID() == -1 + || !param->isTweakable() || param->getEditGroup() != edit_group || !(param->getSex() & avatar_sex)) { @@ -1300,6 +1420,28 @@ void LLPanelEditWearable::updateVerbs() gSavedSettings.setU32("AvatarSex", (gAgentAvatarp->getSex() == SEX_MALE) ); } + // update back button and title according to dirty state. + static BOOL was_dirty = FALSE; + if (was_dirty != is_dirty) // to avoid redundant changes because this method is called from draw + { + static S32 label_width = mBtnBack->getFont()->getWidth(mBackBtnLabel); + const std::string& label = is_dirty ? mBackBtnLabel : LLStringUtil::null; + const S32 delta_width = is_dirty ? label_width : -label_width; + + mBtnBack->setLabel(label); + + // update rect according to label width + LLRect rect = mBtnBack->getRect(); + rect.mRight += delta_width; + mBtnBack->setShape(rect); + + // update title rect according to back button width + rect = mPanelTitle->getRect(); + rect.mLeft += delta_width; + mPanelTitle->setShape(rect); + + was_dirty = is_dirty; + } } void LLPanelEditWearable::configureAlphaCheckbox(LLVOAvatarDefines::ETextureIndex te, const std::string& name) @@ -1381,4 +1523,21 @@ void LLPanelEditWearable::initPreviousAlphaTextureEntry(LLVOAvatarDefines::EText } } +// handle secondlife:///app/metricsystem +class LLMetricSystemHandler : public LLCommandHandler +{ +public: + LLMetricSystemHandler() : LLCommandHandler("metricsystem", UNTRUSTED_THROTTLE) { } + + bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) + { + // change height units TRUE for meters and FALSE for feet + BOOL new_value = (gSavedSettings.getBOOL("HeightUnits") == FALSE) ? TRUE : FALSE; + gSavedSettings.setBOOL("HeightUnits", new_value); + return true; + } +}; + +LLMetricSystemHandler gMetricSystemHandler; + // EOF |