diff options
Diffstat (limited to 'indra/newview/lltoastnotifypanel.cpp')
-rwxr-xr-x[-rw-r--r--] | indra/newview/lltoastnotifypanel.cpp | 630 |
1 files changed, 437 insertions, 193 deletions
diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index 0c23947a8c..602c701a33 100644..100755 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -2,209 +2,225 @@ * @file lltoastnotifypanel.cpp * @brief Panel for notify toasts. * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2001&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 - * - * 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 - * - * 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. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * 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 "lltoastnotifypanel.h" + +// project includes #include "llviewercontrol.h" + +// library includes +#include "lldbstrings.h" +#include "lllslconstants.h" +#include "llnotifications.h" #include "lluiconstants.h" #include "llrect.h" #include "lltrans.h" +#include "llnotificationsutil.h" +#include "llviewermessage.h" +#include "llfloaterimsession.h" +#include "llavataractions.h" const S32 BOTTOM_PAD = VPAD * 3; -const S32 BUTTON_WIDTH = 90; +const S32 IGNORE_BTN_TOP_DELTA = 3*VPAD;//additional ignore_btn padding +S32 BUTTON_WIDTH = 90; +// *TODO: magic numbers(?) - copied from llnotify.cpp(250) +const S32 MAX_LENGTH = 512 + 20 + DB_FIRST_NAME_BUF_SIZE + DB_LAST_NAME_BUF_SIZE + DB_INV_ITEM_NAME_BUF_SIZE; + //static const LLFontGL* LLToastNotifyPanel::sFont = NULL; const LLFontGL* LLToastNotifyPanel::sFontSmall = NULL; -LLToastNotifyPanel::LLToastNotifyPanel(LLNotificationPtr& notification) : -LLToastPanel(notification), -mTextBox(NULL), -mIcon(NULL), -mInfoPanel(NULL), -mControlPanel(NULL), -mNumOptions(0), -mNumButtons(0), -mAddedDefaultBtn(false) +LLToastNotifyPanel::button_click_signal_t LLToastNotifyPanel::sButtonClickSignal; + +LLToastNotifyPanel::LLToastNotifyPanel(const LLNotificationPtr& notification, const LLRect& rect, bool show_images) +: LLToastPanel(notification), + LLInstanceTracker<LLToastNotifyPanel, LLUUID, LLInstanceTrackerReplaceOnCollision>(notification->getID()) { - LLUICtrlFactory::getInstance()->buildPanel(this, "panel_notification.xml"); - mInfoPanel = getChild<LLPanel>("info_panel"); - mControlPanel = getChild<LLPanel>("control_panel"); - mIcon = getChild<LLIconCtrl>("info_icon"); - - // customize panel's attributes - // is it intended for displaying a tip - mIsTip = notification->getType() == "notifytip"; - // is it a script dialog - mIsScriptDialog = (notification->getName() == "ScriptDialog" || notification->getName() == "ScriptDialogGroup"); - // is it a caution - // - // caution flag can be set explicitly by specifying it in the notification payload, or it can be set implicitly if the - // notify xml template specifies that it is a caution - // tip-style notification handle 'caution' differently -they display the tip in a different color - mIsCaution = notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH; - - // setup parameters - // get a notification message - mMessage = notification->getMessage(); - // init font variables - if (!sFont) - { - sFont = LLFontGL::getFontSansSerif(); - sFontSmall = LLFontGL::getFontSansSerifSmall(); - } - // clicking on a button does not steal current focus - setIsChrome(TRUE); - // initialize - setFocusRoot(!mIsTip); - // get a form for the notification - LLNotificationFormPtr form(notification->getForm()); - // get number of elements - mNumOptions = form->getNumElements(); - - // customize panel's outfit - // preliminary adjust panel's layout - mIsTip ? adjustPanelForTipNotice() : adjustPanelForScriptNotice(form); - - // choose a right icon - if (mIsTip) - { - // use the tip notification icon - mIcon->setValue("notify_tip_icon.tga"); - LLRect icon_rect = mIcon->getRect(); - icon_rect.setLeftTopAndSize(icon_rect.mLeft, getRect().getHeight() - VPAD, icon_rect.getWidth(), icon_rect.getHeight()); - mIcon->setRect(icon_rect); - } - else if (mIsCaution) + init(rect, show_images); +} +void LLToastNotifyPanel::addDefaultButton() +{ + LLSD form_element; + form_element.with("name", "OK").with("text", LLTrans::getString("ok")).with("default", true); + LLButton* ok_btn = createButton(form_element, FALSE); + LLRect new_btn_rect(ok_btn->getRect()); + + new_btn_rect.setOriginAndSize(llabs(getRect().getWidth() - BUTTON_WIDTH)/ 2, BOTTOM_PAD, + //auto_size for ok button makes it very small, so let's make it wider + BUTTON_WIDTH, new_btn_rect.getHeight()); + ok_btn->setRect(new_btn_rect); + addChild(ok_btn, -1); + mNumButtons = 1; + mAddedDefaultBtn = true; +} +LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, BOOL is_option) +{ + InstanceAndS32* userdata = new InstanceAndS32; + userdata->mSelf = this; + userdata->mButtonName = is_option ? form_element["name"].asString() : ""; + + mBtnCallbackData.push_back(userdata); + + LLButton::Params p; + bool make_small_btn = form_element["index"].asInteger() == -1 || form_element["index"].asInteger() == -2; + const LLFontGL* font = make_small_btn ? sFontSmall: sFont; // for block and ignore buttons in script dialog + p.name = form_element["name"].asString(); + p.label = form_element["text"].asString(); + p.font = font; + p.rect.height = BTN_HEIGHT; + p.click_callback.function(boost::bind(&LLToastNotifyPanel::onClickButton, userdata)); + p.rect.width = BUTTON_WIDTH; + p.auto_resize = false; + p.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM); + p.enabled = !form_element.has("enabled") || form_element["enabled"].asBoolean(); + if (mIsCaution) { - // use the caution notification icon - mIcon->setValue("notify_caution_icon.tga"); + p.image_color(LLUIColorTable::instance().getColor("ButtonCautionImageColor")); + p.image_color_disabled(LLUIColorTable::instance().getColor("ButtonCautionImageColor")); } - else + // for the scriptdialog buttons we use fixed button size. This is a limit! + if (!mIsScriptDialog && font->getWidth(form_element["text"].asString()) > BUTTON_WIDTH) { - // use the default notification icon - mIcon->setValue("notify_box_icon.tga"); + p.rect.width = 1; + p.auto_resize = true; } - - // adjust text options according to the notification type - // add a caution textbox at the top of a caution notification - if (mIsCaution && !mIsTip) + else if (mIsScriptDialog && make_small_btn) { - mTextBox = getChild<LLTextBox>("caution_text_box"); + // this is ignore button, make it smaller + p.rect.height = BTN_HEIGHT_SMALL; + p.rect.width = 1; + p.auto_resize = true; } - else - { - mTextBox = getChild<LLTextEditor>("text_editor_box"); - } - - // *TODO: magic numbers(???) - copied from llnotify.cpp(250) - const S32 MAX_LENGTH = 512 + 20 + DB_FIRST_NAME_BUF_SIZE + DB_LAST_NAME_BUF_SIZE + DB_INV_ITEM_NAME_BUF_SIZE; - - mTextBox->setVisible(TRUE); - mTextBox->setValue(notification->getMessage()); - - // add buttons for a script notification - if (!mIsTip) + LLButton* btn = LLUICtrlFactory::create<LLButton>(p); + mNumButtons++; + btn->autoResize(); + if (form_element["default"].asBoolean()) { - for (S32 i = 0; i < mNumOptions; i++) - { - LLSD form_element = form->getElement(i); - if (form_element["type"].asString() != "button") - { - continue; - } - - addButton(form_element["name"].asString(), form_element["text"].asString(), TRUE, form_element["default"].asBoolean()); - } - - if (mNumButtons == 0) - { - addButton("OK", LLTrans::getString("ok"), FALSE, TRUE); - mAddedDefaultBtn = true; - } + setDefaultBtn(btn); } - // adjust panel's height to the text size - mInfoPanel->setFollowsAll(); - snapToMessageHeight(mTextBox, MAX_LENGTH); + return btn; } LLToastNotifyPanel::~LLToastNotifyPanel() { - std::for_each(mBtnCallbackData.begin(), mBtnCallbackData.end(), DeletePointer()); -} + mButtonClickConnection.disconnect(); + std::for_each(mBtnCallbackData.begin(), mBtnCallbackData.end(), DeletePointer()); + mBtnCallbackData.clear(); + if (mIsTip) + { + LLNotifications::getInstance()->cancel(mNotification); + } + } -void LLToastNotifyPanel::adjustPanelForScriptNotice(const LLNotificationFormPtr form) +void LLToastNotifyPanel::updateButtonsLayout(const std::vector<index_button_pair_t>& buttons, S32 h_pad) { - F32 buttons_num = 0; - S32 button_rows = 0; - - // calculate number of buttons - for (S32 i = 0; i < mNumOptions; i++) + S32 left = 0; + //reserve place for ignore button + S32 bottom_offset = mIsScriptDialog ? (BTN_HEIGHT + IGNORE_BTN_TOP_DELTA + BOTTOM_PAD) : BOTTOM_PAD; + S32 max_width = mControlPanel->getRect().getWidth(); + LLButton* ignore_btn = NULL; + LLButton* mute_btn = NULL; + for (std::vector<index_button_pair_t>::const_iterator it = buttons.begin(); it != buttons.end(); it++) { - if (form->getElement(i)["type"].asString() == "button") + if (-2 == it->first) + { + mute_btn = it->second; + continue; + } + if (it->first == -1) { - buttons_num++; + ignore_btn = it->second; + continue; } + LLButton* btn = it->second; + LLRect btn_rect(btn->getRect()); + if (left + btn_rect.getWidth() > max_width)// whether there is still some place for button+h_pad in the mControlPanel + { + // looks like we need to add button to the next row + left = 0; + bottom_offset += (BTN_HEIGHT + VPAD); + } + //we arrange buttons from bottom to top for backward support of old script + btn_rect.setOriginAndSize(left, bottom_offset, btn_rect.getWidth(), btn_rect.getHeight()); + btn->setRect(btn_rect); + left = btn_rect.mLeft + btn_rect.getWidth() + h_pad; + mControlPanel->addChild(btn, -1); } - // calculate necessary height for the button panel - // if notification form contains no buttons - reserve a place for OK button - // script notifications have extra line for an IGNORE button - if(mIsScriptDialog) + U32 ignore_btn_width = 0; + U32 mute_btn_pad = 0; + if (mIsScriptDialog && ignore_btn != NULL) { - button_rows = llceil((buttons_num - 1) / 3.0f) + 1; + LLRect ignore_btn_rect(ignore_btn->getRect()); + S32 ignore_btn_left = max_width - ignore_btn_rect.getWidth(); + ignore_btn_rect.setOriginAndSize(ignore_btn_left, BOTTOM_PAD,// always move ignore button at the bottom + ignore_btn_rect.getWidth(), ignore_btn_rect.getHeight()); + ignore_btn->setRect(ignore_btn_rect); + ignore_btn_width = ignore_btn_rect.getWidth(); + mControlPanel->addChild(ignore_btn, -1); + mute_btn_pad = 4 * HPAD; //only use a 4 * HPAD padding if an ignore button exists } - else + + if (mIsScriptDialog && mute_btn != NULL) { - button_rows = llmax( 1, llceil(buttons_num / 3.0f)); + LLRect mute_btn_rect(mute_btn->getRect()); + // Place mute (Block) button to the left of the ignore button. + S32 mute_btn_left = max_width - mute_btn_rect.getWidth() - ignore_btn_width - mute_btn_pad; + mute_btn_rect.setOriginAndSize(mute_btn_left, BOTTOM_PAD,// always move mute button at the bottom + mute_btn_rect.getWidth(), mute_btn_rect.getHeight()); + mute_btn->setRect(mute_btn_rect); + mControlPanel->addChild(mute_btn); } +} - S32 button_panel_height = button_rows * BTN_HEIGHT + (button_rows + 1) * VPAD + BOTTOM_PAD; - +void LLToastNotifyPanel::adjustPanelForScriptNotice(S32 button_panel_width, S32 button_panel_height) +{ //adjust layout - LLRect button_rect = mControlPanel->getRect(); - reshape(getRect().getWidth(), mInfoPanel->getRect().getHeight() + button_panel_height); - mControlPanel->reshape(button_rect.getWidth(), button_panel_height); + // we need to keep min width and max height to make visible all buttons, because width of the toast can not be changed + reshape(getRect().getWidth(), mInfoPanel->getRect().getHeight() + button_panel_height + VPAD); + mControlPanel->reshape( button_panel_width, button_panel_height); } -// static void LLToastNotifyPanel::adjustPanelForTipNotice() { - LLRect info_rect = mInfoPanel->getRect(); - LLRect this_rect = getRect(); - + //we don't need display ControlPanel for tips because they doesn't contain any buttons. mControlPanel->setVisible(FALSE); reshape(getRect().getWidth(), mInfoPanel->getRect().getHeight()); + + if (mNotification->getPayload().has("respond_on_mousedown") + && mNotification->getPayload()["respond_on_mousedown"] ) + { + mInfoPanel->setMouseDownCallback( + boost::bind(&LLNotification::respond, + mNotification, + mNotification->getResponseTemplate())); + } } // static @@ -219,66 +235,294 @@ void LLToastNotifyPanel::onClickButton(void* data) { response[button_name] = true; } + + // disable all buttons + self->mControlPanel->setEnabled(FALSE); + + // this might repost notification with new form data/enabled buttons self->mNotification->respond(response); } -// virtual -LLButton* LLToastNotifyPanel::addButton(const std::string& name, const std::string& label, BOOL is_option, BOOL is_default) +void LLToastNotifyPanel::init( LLRect rect, bool show_images ) +{ + deleteAllChildren(); + + mTextBox = NULL; + mInfoPanel = NULL; + mControlPanel = NULL; + mNumOptions = 0; + mNumButtons = 0; + mAddedDefaultBtn = false; + + LLRect current_rect = getRect(); + + setXMLFilename(""); + buildFromFile("panel_notification.xml"); + + if(rect != LLRect::null) + { + this->setShape(rect); + } + mInfoPanel = getChild<LLPanel>("info_panel"); + + mControlPanel = getChild<LLPanel>("control_panel"); + BUTTON_WIDTH = gSavedSettings.getS32("ToastButtonWidth"); + // customize panel's attributes + // is it intended for displaying a tip? + mIsTip = mNotification->getType() == "notifytip"; + + std::string notif_name = mNotification->getName(); + // is it a script dialog? + mIsScriptDialog = (notif_name == "ScriptDialog" || notif_name == "ScriptDialogGroup"); + + bool is_content_trusted = (notif_name != "LoadWebPage"); + // is it a caution? + // + // caution flag can be set explicitly by specifying it in the notification payload, or it can be set implicitly if the + // notify xml template specifies that it is a caution + // tip-style notification handle 'caution' differently -they display the tip in a different color + mIsCaution = mNotification->getPriority() >= NOTIFICATION_PRIORITY_HIGH; + + // setup parameters + // get a notification message + mMessage = mNotification->getMessage(); + // init font variables + if (!sFont) + { + sFont = LLFontGL::getFontSansSerif(); + sFontSmall = LLFontGL::getFontSansSerifSmall(); + } + // initialize + setFocusRoot(!mIsTip); + // get a form for the notification + LLNotificationFormPtr form(mNotification->getForm()); + // get number of elements + mNumOptions = form->getNumElements(); + + // customize panel's outfit + // preliminary adjust panel's layout + //move to the end + //mIsTip ? adjustPanelForTipNotice() : adjustPanelForScriptNotice(form); + + // adjust text options according to the notification type + // add a caution textbox at the top of a caution notification + if (mIsCaution && !mIsTip) + { + mTextBox = getChild<LLTextBox>("caution_text_box"); + } + else + { + mTextBox = getChild<LLTextEditor>("text_editor_box"); + } + + mTextBox->setMaxTextLength(MAX_LENGTH); + mTextBox->setVisible(TRUE); + mTextBox->setPlainText(!show_images); + mTextBox->setContentTrusted(is_content_trusted); + mTextBox->setValue(mNotification->getMessage()); + mTextBox->setIsFriendCallback(LLAvatarActions::isFriend); + + // add buttons for a script notification + if (mIsTip) + { + adjustPanelForTipNotice(); + } + else + { + std::vector<index_button_pair_t> buttons; + buttons.reserve(mNumOptions); + S32 buttons_width = 0; + // create all buttons and accumulate they total width to reshape mControlPanel + for (S32 i = 0; i < mNumOptions; i++) + { + LLSD form_element = form->getElement(i); + if (form_element["type"].asString() != "button") + { + // not a button. + continue; + } + if (form_element["name"].asString() == TEXTBOX_MAGIC_TOKEN) + { + // a textbox pretending to be a button. + continue; + } + LLButton* new_button = createButton(form_element, TRUE); + buttons_width += new_button->getRect().getWidth(); + S32 index = form_element["index"].asInteger(); + buttons.push_back(index_button_pair_t(index,new_button)); + } + if (buttons.empty()) + { + addDefaultButton(); + } + else + { + const S32 button_panel_width = mControlPanel->getRect().getWidth();// do not change width of the panel + S32 button_panel_height = mControlPanel->getRect().getHeight(); + //try get an average h_pad to spread out buttons + S32 h_pad = (button_panel_width - buttons_width) / (S32(buttons.size())); + if(h_pad < 2*HPAD) + { + /* + * Probably it is a scriptdialog toast + * for a scriptdialog toast h_pad can be < 2*HPAD if we have a lot of buttons. + * In last case set default h_pad to avoid heaping of buttons + */ + S32 button_per_row = button_panel_width / BUTTON_WIDTH; + h_pad = (button_panel_width % BUTTON_WIDTH) / (button_per_row - 1);// -1 because we do not need space after last button in a row + if(h_pad < 2*HPAD) // still not enough space between buttons ? + { + h_pad = 2*HPAD; + } + } + if (mIsScriptDialog) + { + // we are using default width for script buttons so we can determinate button_rows + //to get a number of rows we divide the required width of the buttons to button_panel_width + S32 button_rows = llceil(F32(buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width); + //S32 button_rows = (buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width; + //reserve one row for the ignore_btn + button_rows++; + //calculate required panel height for scripdialog notification. + button_panel_height = button_rows * (BTN_HEIGHT + VPAD) + IGNORE_BTN_TOP_DELTA + BOTTOM_PAD; + } + else + { + // in common case buttons can have different widths so we need to calculate button_rows according to buttons_width + //S32 button_rows = llceil(F32(buttons.size()) * (buttons_width + h_pad) / button_panel_width); + S32 button_rows = llceil(F32((buttons.size() - 1) * h_pad + buttons_width) / button_panel_width); + //calculate required panel height + button_panel_height = button_rows * (BTN_HEIGHT + VPAD) + BOTTOM_PAD; + } + + // we need to keep min width and max height to make visible all buttons, because width of the toast can not be changed + adjustPanelForScriptNotice(button_panel_width, button_panel_height); + updateButtonsLayout(buttons, h_pad); + // save buttons for later use in disableButtons() + //mButtons.assign(buttons.begin(), buttons.end()); + } + } + + //.xml file intially makes info panel only follow left/right/top. This is so that when control buttons are added the info panel + //can shift upward making room for the buttons inside mControlPanel. After the buttons are added, the info panel can then be set to follow 'all'. + mInfoPanel->setFollowsAll(); + snapToMessageHeight(mTextBox, MAX_LENGTH); + + // reshape the panel to its previous size + if (current_rect.notEmpty()) + { + reshape(current_rect.getWidth(), current_rect.getHeight()); + } +} + +bool LLToastNotifyPanel::isControlPanelEnabled() const { - LLRect btn_rect; - LLButton* btn; - S32 btn_height= BTN_HEIGHT; - const LLFontGL* font = sFont; - S32 ignore_pad = 0; - S32 button_index = mNumButtons; - S32 index = button_index; - S32 x = (HPAD * 4) + 32; - - if (mIsScriptDialog) + bool cp_enabled = mControlPanel->getEnabled(); + bool some_buttons_enabled = false; + if (cp_enabled) { - // Add two "blank" option spaces, before the "Ignore" button - index = button_index + 2; - if (button_index == 0) + LLView::child_list_const_iter_t child_it = mControlPanel->beginChild(); + LLView::child_list_const_iter_t child_it_end = mControlPanel->endChild(); + for(; child_it != child_it_end; ++child_it) { - // Ignore button is smaller, less wide - btn_height = BTN_HEIGHT_SMALL; - font = sFontSmall; - ignore_pad = 10; + LLButton * buttonp = dynamic_cast<LLButton *>(*child_it); + if (buttonp && buttonp->getEnabled()) + { + some_buttons_enabled = true; + break; + } } } - btn_rect.setOriginAndSize(x + (index % 3) * (BUTTON_WIDTH+HPAD+HPAD) + ignore_pad, - BOTTOM_PAD + (index / 3) * (BTN_HEIGHT+VPAD), - BUTTON_WIDTH - 2*ignore_pad, - btn_height); + return cp_enabled && some_buttons_enabled; +} - InstanceAndS32* userdata = new InstanceAndS32; - userdata->mSelf = this; - userdata->mButtonName = is_option ? name : ""; +////////////////////////////////////////////////////////////////////////// - mBtnCallbackData.push_back(userdata); +LLIMToastNotifyPanel::LLIMToastNotifyPanel(LLNotificationPtr& pNotification, const LLUUID& session_id, const LLRect& rect /* = LLRect::null */, + bool show_images /* = true */, LLTextBase* parent_text) +: mSessionID(session_id), LLToastNotifyPanel(pNotification, rect, show_images), + mParentText(parent_text) +{ + compactButtons(); +} - LLButton::Params p; - p.name(name); - p.label(label); - p.rect(btn_rect); - p.click_callback.function(boost::bind(&LLToastNotifyPanel::onClickButton, userdata)); - p.font(font); - if (mIsCaution) +LLIMToastNotifyPanel::~LLIMToastNotifyPanel() +{ +} + +void LLIMToastNotifyPanel::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */) +{ + LLToastPanel::reshape(width, height, called_from_parent); + snapToMessageHeight(); +} + +void LLIMToastNotifyPanel::snapToMessageHeight() +{ + if(!mTextBox) { - p.image_color(LLUIColorTable::instance().getColor("ButtonCautionImageColor")); - p.image_color_disabled(LLUIColorTable::instance().getColor("ButtonCautionImageColor")); + return; } - btn = LLUICtrlFactory::create<LLButton>(p); + //Add message height if it is visible + if (mTextBox->getVisible()) + { + S32 new_panel_height = computeSnappedToMessageHeight(mTextBox, MAX_LENGTH); - mControlPanel->addChild(btn, -1); + //reshape the panel with new height + if (new_panel_height != getRect().getHeight()) + { + LLToastNotifyPanel::reshape( getRect().getWidth(), new_panel_height); + } + } +} - if (is_default) +void LLIMToastNotifyPanel::compactButtons() +{ + //we can't set follows in xml since it broke toasts behavior + setFollows(FOLLOWS_LEFT|FOLLOWS_RIGHT|FOLLOWS_TOP); + + const child_list_t* children = getControlPanel()->getChildList(); + S32 offset = 0; + // Children were added by addChild() which uses push_front to insert them into list, + // so to get buttons in correct order reverse iterator is used (EXT-5906) + for (child_list_t::const_reverse_iterator it = children->rbegin(); it != children->rend(); it++) { - setDefaultBtn(btn); + LLButton * button = dynamic_cast<LLButton*> (*it); + if (button != NULL) + { + button->setOrigin( offset,button->getRect().mBottom); + button->setLeftHPad(2 * HPAD); + button->setRightHPad(2 * HPAD); + // set zero width before perform autoResize() + button->setRect(LLRect(button->getRect().mLeft, + button->getRect().mTop, + button->getRect().mLeft, + button->getRect().mBottom)); + button->setAutoResize(true); + button->autoResize(); + offset += HPAD + button->getRect().getWidth(); + button->setFollowsNone(); + } } - mNumButtons++; - return btn; + if (mParentText) + { + mParentText->needsReflow(); + } +} + +void LLIMToastNotifyPanel::updateNotification() + { + init(LLRect(), true); + } + +void LLIMToastNotifyPanel::init( LLRect rect, bool show_images ) +{ + LLToastNotifyPanel::init(LLRect(), show_images); + + compactButtons(); } + +// EOF + |