lltoastnotifypanel.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:12k
源码类别:
游戏引擎
开发平台:
C++ Builder
- /**
- * @file lltoastnotifypanel.cpp
- * @brief Panel for notify toasts.
- *
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2010, Linden Research, Inc.
- *
- * 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.
- * $/LicenseInfo$
- */
- #include "llviewerprecompiledheaders.h"
- #include "lltoastnotifypanel.h"
- // project includes
- #include "llviewercontrol.h"
- // library includes
- #include "lldbstrings.h"
- #include "llnotifications.h"
- #include "lluiconstants.h"
- #include "llrect.h"
- #include "lltrans.h"
- #include "llnotificationsutil.h"
- const S32 BOTTOM_PAD = VPAD * 3;
- const S32 IGNORE_BTN_TOP_DELTA = 3*VPAD;//additional ignore_btn padding
- S32 BUTTON_WIDTH = 90;
- //static
- const LLFontGL* LLToastNotifyPanel::sFont = NULL;
- const LLFontGL* LLToastNotifyPanel::sFontSmall = NULL;
- LLToastNotifyPanel::LLToastNotifyPanel(LLNotificationPtr& notification) :
- LLToastPanel(notification),
- mTextBox(NULL),
- mInfoPanel(NULL),
- mControlPanel(NULL),
- mNumOptions(0),
- mNumButtons(0),
- mAddedDefaultBtn(false)
- {
- LLUICtrlFactory::getInstance()->buildPanel(this, "panel_notification.xml");
- 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 = 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
- //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");
- }
- // *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->setMaxTextLength(MAX_LENGTH);
- mTextBox->setVisible(TRUE);
- mTextBox->setValue(notification->getMessage());
- // 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")
- {
- 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
- */
- 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);
- }
- }
- // adjust panel's height to the text size
- mInfoPanel->setFollowsAll();
- snapToMessageHeight(mTextBox, MAX_LENGTH);
- }
- 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 is_ignore_btn = form_element["index"].asInteger() == -1;
- const LLFontGL* font = is_ignore_btn ? sFontSmall: sFont; // for ignore button 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_RIGHT | FOLLOWS_LEFT | FOLLOWS_BOTTOM);
- if (mIsCaution)
- {
- p.image_color(LLUIColorTable::instance().getColor("ButtonCautionImageColor"));
- p.image_color_disabled(LLUIColorTable::instance().getColor("ButtonCautionImageColor"));
- }
- // for the scriptdialog buttons we use fixed button size. This is a limit!
- if (!mIsScriptDialog && font->getWidth(form_element["text"].asString()) > BUTTON_WIDTH)
- {
- p.rect.width = 1;
- p.auto_resize = true;
- }
- else if (mIsScriptDialog && is_ignore_btn)
- {
- // this is ignore button,make it smaller
- p.rect.height = BTN_HEIGHT_SMALL;
- p.rect.width = 1;
- p.auto_resize = true;
- }
- LLButton* btn = LLUICtrlFactory::create<LLButton>(p);
- mNumButtons++;
- btn->autoResize();
- if (form_element["default"].asBoolean())
- {
- setDefaultBtn(btn);
- }
- return btn;
- }
- LLToastNotifyPanel::~LLToastNotifyPanel()
- {
- std::for_each(mBtnCallbackData.begin(), mBtnCallbackData.end(), DeletePointer());
- if (LLNotificationsUtil::find(mNotification->getID()) != NULL)
- {
- LLNotifications::getInstance()->cancel(mNotification);
- }
- }
- void LLToastNotifyPanel::updateButtonsLayout(const std::vector<index_button_pair_t>& buttons, S32 h_pad)
- {
- 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;
- for (std::vector<index_button_pair_t>::const_iterator it = buttons.begin(); it != buttons.end(); it++)
- {
- if (it->first == -1)
- {
- 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);
- }
- if (mIsScriptDialog && ignore_btn != NULL)
- {
- LLRect ignore_btn_rect(ignore_btn->getRect());
- S32 buttons_per_row = max_width / BUTTON_WIDTH; //assume that h_pad far less than BUTTON_WIDTH
- S32 ignore_btn_left = buttons_per_row * BUTTON_WIDTH + (buttons_per_row - 1) * h_pad - ignore_btn_rect.getWidth();
- if (ignore_btn_left + ignore_btn_rect.getWidth() > max_width)// make sure that the ignore button is in panel
- {
- ignore_btn_left = max_width - ignore_btn_rect.getWidth() - 2 * HPAD;
- }
- 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);
- mControlPanel->addChild(ignore_btn, -1);
- }
- }
- void LLToastNotifyPanel::adjustPanelForScriptNotice(S32 button_panel_width, S32 button_panel_height)
- {
- //adjust layout
- // 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);
- }
- 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
- void LLToastNotifyPanel::onClickButton(void* data)
- {
- InstanceAndS32* self_and_button = (InstanceAndS32*)data;
- LLToastNotifyPanel* self = self_and_button->mSelf;
- std::string button_name = self_and_button->mButtonName;
- LLSD response = self->mNotification->getResponseTemplate();
- if (!self->mAddedDefaultBtn && !button_name.empty())
- {
- response[button_name] = true;
- }
- self->mNotification->respond(response);
- // disable all buttons
- self->mControlPanel->setEnabled(FALSE);
- }