diff options
Diffstat (limited to 'indra/newview/llfloaterimsessiontab.cpp')
-rw-r--r-- | indra/newview/llfloaterimsessiontab.cpp | 220 |
1 files changed, 176 insertions, 44 deletions
diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index dc64d09f9f..0855a628fb 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -39,6 +39,7 @@ #include "llchicletbar.h" #include "lldraghandle.h" #include "llemojidictionary.h" +#include "llemojihelper.h" #include "llfloaterreg.h" #include "llfloateremojipicker.h" #include "llfloaterimsession.h" @@ -78,11 +79,11 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) mInputPanels(NULL), mChatLayoutPanelHeight(0) { - setAutoFocus(FALSE); + setAutoFocus(false); mSession = LLIMModel::getInstance()->findIMSession(mSessionID); mCommitCallbackRegistrar.add("IMSession.Menu.Action", - boost::bind(&LLFloaterIMSessionTab::onIMSessionMenuItemClicked, this, _2)); + { boost::bind(&LLFloaterIMSessionTab::onIMSessionMenuItemClicked, this, _2) }); mEnableCallbackRegistrar.add("IMSession.Menu.CompactExpandedModes.CheckItem", boost::bind(&LLFloaterIMSessionTab::onIMCompactExpandedMenuItemCheck, this, _2)); mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.CheckItem", @@ -93,8 +94,8 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) // Right click menu handling mEnableCallbackRegistrar.add("Avatar.CheckItem", boost::bind(&LLFloaterIMSessionTab::checkContextMenuItem, this, _2)); mEnableCallbackRegistrar.add("Avatar.EnableItem", boost::bind(&LLFloaterIMSessionTab::enableContextMenuItem, this, _2)); - mCommitCallbackRegistrar.add("Avatar.DoToSelected", boost::bind(&LLFloaterIMSessionTab::doToSelected, this, _2)); - mCommitCallbackRegistrar.add("Group.DoToSelected", boost::bind(&cb_group_do_nothing)); + mCommitCallbackRegistrar.add("Avatar.DoToSelected", { boost::bind(&LLFloaterIMSessionTab::doToSelected, this, _2) }); + mCommitCallbackRegistrar.add("Group.DoToSelected", { boost::bind(&cb_group_do_nothing) }); mMinFloaterHeight = getMinHeight(); } @@ -102,6 +103,26 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) LLFloaterIMSessionTab::~LLFloaterIMSessionTab() { delete mRefreshTimer; + + LLFloaterIMContainer* im_container = LLFloaterIMContainer::findInstance(); + if (im_container) + { + LLParticipantList* session = dynamic_cast<LLParticipantList*>(im_container->getSessionModel(mSessionID)); + if (session) + { + for (const conversations_widgets_map::value_type& widget_pair : mConversationsWidgets) + { + LLFolderViewItem* widget = widget_pair.second; + LLFolderViewModelItem* item_vmi = widget->getViewModelItem(); + if (item_vmi && item_vmi->getNumRefs() == 1) + { + // This is the last pointer, remove participant from session + // before participant gets deleted on destroyView. + session->removeChild(item_vmi); + } + } + } + } } // static @@ -141,7 +162,7 @@ LLFloaterIMSessionTab* LLFloaterIMSessionTab::getConversation(const LLUUID& uuid }; // virtual -void LLFloaterIMSessionTab::setVisible(BOOL visible) +void LLFloaterIMSessionTab::setVisible(bool visible) { if (visible && !mHasVisibleBeenInitialized) { @@ -164,7 +185,7 @@ void LLFloaterIMSessionTab::setVisible(BOOL visible) } // virtual -void LLFloaterIMSessionTab::setFocus(BOOL focus) +void LLFloaterIMSessionTab::setFocus(bool focus) { super::setFocus(focus); @@ -175,7 +196,7 @@ void LLFloaterIMSessionTab::setFocus(BOOL focus) if (mInputEditor) { - mInputEditor->setFocus(TRUE); + mInputEditor->setFocus(true); } } } @@ -238,10 +259,11 @@ void LLFloaterIMSessionTab::assignResizeLimits() } // virtual -BOOL LLFloaterIMSessionTab::postBuild() +bool LLFloaterIMSessionTab::postBuild() { - BOOL result; + bool result; + mContentsView = getChild<LLView>("contents_view"); mBodyStack = getChild<LLLayoutStack>("main_stack"); mParticipantListAndHistoryStack = getChild<LLLayoutStack>("im_panels"); @@ -277,10 +299,13 @@ BOOL LLFloaterIMSessionTab::postBuild() mEmojiPickerShowBtn = getChild<LLButton>("emoji_picker_show_btn"); mEmojiPickerShowBtn->setClickedCallback([this](LLUICtrl*, const LLSD&) { onEmojiPickerShowBtnClicked(); }); + mEmojiPickerShowBtn->setMouseDownCallback([this](LLUICtrl*, const LLSD&) { onEmojiPickerShowBtnDown(); }); + mEmojiCloseConn = LLEmojiHelper::instance().setCloseCallback([this](LLUICtrl*, const LLSD&) { onEmojiPickerClosed(); }); mGearBtn = getChild<LLButton>("gear_btn"); mAddBtn = getChild<LLButton>("add_btn"); mVoiceButton = getChild<LLButton>("voice_call_btn"); + mVoiceButton->setClickedCallback([this](LLUICtrl*, const LLSD&) { onCallButtonClicked(); }); mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel"); mRightPartPanel = getChild<LLLayoutPanel>("right_part_holder"); @@ -309,8 +334,8 @@ BOOL LLFloaterIMSessionTab::postBuild() mInputEditor->setTextExpandedCallback(boost::bind(&LLFloaterIMSessionTab::reshapeChatLayoutPanel, this)); mInputEditor->setMouseUpCallback(boost::bind(&LLFloaterIMSessionTab::onInputEditorClicked, this)); - mInputEditor->setCommitOnFocusLost( FALSE ); - mInputEditor->setPassDelete(TRUE); + mInputEditor->setCommitOnFocusLost( false ); + mInputEditor->setPassDelete(true); mInputEditor->setFont(LLViewerChat::getChatFont()); mChatLayoutPanelHeight = mChatLayoutPanel->getRect().getHeight(); @@ -413,16 +438,35 @@ void LLFloaterIMSessionTab::draw() void LLFloaterIMSessionTab::enableDisableCallBtn() { - if (LLVoiceClient::instanceExists() && mVoiceButton) + if (!mVoiceButton) + return; + + bool enable = false; + + if (mSessionID.notNull() && mSession && mSession->mSessionInitialized && mSession->mCallBackEnabled) { - mVoiceButton->setEnabled( - mSessionID.notNull() - && mSession - && mSession->mSessionInitialized - && LLVoiceClient::getInstance()->voiceEnabled() - && LLVoiceClient::getInstance()->isVoiceWorking() - && mSession->mCallBackEnabled); + if (mVoiceButtonHangUpMode) + { + // We allow to hang up from any state + enable = true; + } + else + { + // We allow to start call from this state only + if (mSession->mVoiceChannel && + !mSession->mVoiceChannel->callStarted() && + LLVoiceClient::instanceExists()) + { + LLVoiceClient* client = LLVoiceClient::getInstance(); + if (client->voiceEnabled() && client->isVoiceWorking()) + { + enable = true; + } + } + } } + + mVoiceButton->setEnabled(enable); } // virtual @@ -445,6 +489,22 @@ void LLFloaterIMSessionTab::onFocusLost() super::onFocusLost(); } +void LLFloaterIMSessionTab::onCallButtonClicked() +{ + if (mVoiceButtonHangUpMode) + { + // We allow to hang up from any state + gIMMgr->endCall(mSessionID); + } + else + { + if (mSession->mVoiceChannel && !mSession->mVoiceChannel->callStarted()) + { + gIMMgr->startCall(mSessionID); + } + } +} + void LLFloaterIMSessionTab::onInputEditorClicked() { LLFloaterIMContainer* im_box = LLFloaterIMContainer::findInstance(); @@ -457,20 +517,55 @@ void LLFloaterIMSessionTab::onInputEditorClicked() void LLFloaterIMSessionTab::onEmojiRecentPanelToggleBtnClicked() { - BOOL show = mEmojiRecentPanel->getVisible() ? FALSE : TRUE; + bool show = !mEmojiRecentPanel->getVisible(); if (show) { initEmojiRecentPanel(); } mEmojiRecentPanel->setVisible(show); - mInputEditor->setFocus(TRUE); + mInputEditor->setFocus(true); } void LLFloaterIMSessionTab::onEmojiPickerShowBtnClicked() { - mInputEditor->setFocus(TRUE); - mInputEditor->showEmojiHelper(); + if (!mEmojiPickerShowBtn->getToggleState()) + { + mInputEditor->hideEmojiHelper(); + mInputEditor->setFocus(true); + mInputEditor->showEmojiHelper(); + mEmojiPickerShowBtn->setToggleState(true); // in case hideEmojiHelper closed a visible instance + } + else + { + mInputEditor->hideEmojiHelper(); + mEmojiPickerShowBtn->setToggleState(false); + } +} + +void LLFloaterIMSessionTab::onEmojiPickerShowBtnDown() +{ + if (mEmojiHelperLastCallbackFrame == LLFrameTimer::getFrameCount()) + { + // Helper gets closed by focus lost event on Down before before onEmojiPickerShowBtnDown + // triggers. + // If this condition is true, user pressed button and it was 'toggled' during press, + // restore 'toggled' state so that button will not reopen helper. + mEmojiPickerShowBtn->setToggleState(true); + } +} + +void LLFloaterIMSessionTab::onEmojiPickerClosed() +{ + if (mEmojiPickerShowBtn->getToggleState()) + { + mEmojiPickerShowBtn->setToggleState(false); + // Helper gets closed by focus lost event on Down before onEmojiPickerShowBtnDown + // triggers. If mEmojiHelperLastCallbackFrame is set and matches Down, means close + // was triggered by user's press. + // A bit hacky, but I can't think of a better way to handle this without rewriting helper. + mEmojiHelperLastCallbackFrame = LLFrameTimer::getFrameCount(); + } } void LLFloaterIMSessionTab::initEmojiRecentPanel() @@ -478,8 +573,8 @@ void LLFloaterIMSessionTab::initEmojiRecentPanel() std::list<llwchar>& recentlyUsed = LLFloaterEmojiPicker::getRecentlyUsed(); if (recentlyUsed.empty()) { - mEmojiRecentEmptyText->setVisible(TRUE); - mEmojiRecentContainer->setVisible(FALSE); + mEmojiRecentEmptyText->setVisible(true); + mEmojiRecentContainer->setVisible(false); } else { @@ -489,8 +584,8 @@ void LLFloaterIMSessionTab::initEmojiRecentPanel() emojis += emoji; } mEmojiRecentIconsCtrl->setEmojis(emojis); - mEmojiRecentEmptyText->setVisible(FALSE); - mEmojiRecentContainer->setVisible(TRUE); + mEmojiRecentEmptyText->setVisible(false); + mEmojiRecentContainer->setVisible(true); } } @@ -526,10 +621,27 @@ void LLFloaterIMSessionTab::closeFloater(bool app_quitting) super::closeFloater(app_quitting); } +void LLFloaterIMSessionTab::deleteAllChildren() +{ + super::deleteAllChildren(); + mVoiceButton = NULL; +} + std::string LLFloaterIMSessionTab::appendTime() { - std::string timeStr = "[" + LLTrans::getString("TimeHour") + "]:" - "[" + LLTrans::getString("TimeMin") + "]"; + std::string timeStr; + static bool use_24h = gSavedSettings.getBOOL("Use24HourClock"); + if (use_24h) + { + timeStr = "[" + LLTrans::getString("TimeHour") + "]:" + "[" + LLTrans::getString("TimeMin") + "]"; + } + else + { + timeStr = "[" + LLTrans::getString("TimeHour12") + "]:" + "[" + LLTrans::getString("TimeMin") + "] [" + + LLTrans::getString("TimeAMPM") + "]"; + } LLSD substitution; substitution["datetime"] = (S32)time_corrected(); @@ -567,13 +679,13 @@ void LLFloaterIMSessionTab::appendMessage(const LLChat& chat, const LLSD& args) mChatHistory->appendMessage(chat, chat_args); } -void LLFloaterIMSessionTab::updateUsedEmojis(LLWString text) +void LLFloaterIMSessionTab::updateUsedEmojis(LLWStringView text) { LLEmojiDictionary* dictionary = LLEmojiDictionary::getInstance(); llassert_always(dictionary); bool emojiSent = false; - for (llwchar& c : text) + for (const llwchar& c : text) { if (dictionary->isEmoji(c)) { @@ -654,7 +766,7 @@ void LLFloaterIMSessionTab::addConversationViewParticipant(LLConversationItem* p mConversationsWidgets[uuid] = participant_view; participant_view->addToFolder(mConversationsRoot); participant_view->addToSession(mSessionID); - participant_view->setVisible(TRUE); + participant_view->setVisible(true); } } @@ -663,6 +775,27 @@ void LLFloaterIMSessionTab::removeConversationViewParticipant(const LLUUID& part LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,participant_id); if (widget) { + LLFolderViewModelItem* item_vmi = widget->getViewModelItem(); + if (item_vmi && item_vmi->getNumRefs() == 1) + { + // This is the last pointer, remove participant from session + // before participant gets deleted on destroyView. + // + // Floater (widget) and participant's view can simultaneously + // co-own the model, in which case view is responsible for + // the deletion and floater is free to clear and recreate + // the list, yet there are cases where only widget owns + // the pointer so it should do the cleanup. + // See "add_participant". + // + // Todo: If it keeps causing issues turn participants + // into LLPointers in the session + LLParticipantList* session = getParticipantList(); + if (session) + { + session->removeChild(item_vmi); + } + } widget->destroyView(); } mConversationsWidgets.erase(participant_id); @@ -699,7 +832,7 @@ void LLFloaterIMSessionTab::refreshConversation() if (widget_it->second->getViewModelItem()) { widget_it->second->refresh(); - widget_it->second->setVisible(TRUE); + widget_it->second->setVisible(true); } ++widget_it; } @@ -820,7 +953,6 @@ void LLFloaterIMSessionTab::hideOrShowTitle() { const LLFloater::Params& default_params = LLFloater::getDefaultParams(); S32 floater_header_size = default_params.header_height; - LLView* floater_contents = getChild<LLView>("contents_view"); LLRect floater_rect = getLocalRect(); S32 top_border_of_contents = floater_rect.mTop - (isTornOff()? floater_header_size : 0); @@ -828,7 +960,7 @@ void LLFloaterIMSessionTab::hideOrShowTitle() LLRect contents_rect (0, top_border_of_contents, floater_rect.mRight, floater_rect.mBottom); mDragHandle->setShape(handle_rect); mDragHandle->setVisible(isTornOff()); - floater_contents->setShape(contents_rect); + mContentsView->setShape(contents_rect); } void LLFloaterIMSessionTab::updateSessionName(const std::string& name) @@ -944,7 +1076,7 @@ void LLFloaterIMSessionTab::forceReshape() void LLFloaterIMSessionTab::reshapeChatLayoutPanel() { - mChatLayoutPanel->reshape(mChatLayoutPanel->getRect().getWidth(), mInputEditor->getRect().getHeight() + mInputEditorPad, FALSE); + mChatLayoutPanel->reshape(mChatLayoutPanel->getRect().getWidth(), mInputEditor->getRect().getHeight() + mInputEditorPad, false); } // static @@ -993,6 +1125,7 @@ void LLFloaterIMSessionTab::updateCallBtnState(bool callIsActive) { mVoiceButton->setImageOverlay(callIsActive? getString("call_btn_stop") : getString("call_btn_start")); mVoiceButton->setToolTip(callIsActive? getString("end_call_button_tooltip") : getString("start_call_button_tooltip")); + mVoiceButtonHangUpMode = callIsActive; enableDisableCallBtn(); } @@ -1105,7 +1238,7 @@ void LLFloaterIMSessionTab::onOpen(const LLSD& key) mInputButtonPanel->setVisible(isTornOff()); - setFocus(TRUE); + setFocus(true); } @@ -1137,8 +1270,7 @@ void LLFloaterIMSessionTab::onTearOffClicked() void LLFloaterIMSessionTab::updateGearBtn() { - - BOOL prevVisibility = mGearBtn->getVisible(); + bool prevVisibility = mGearBtn->getVisible(); mGearBtn->setVisible(checkIfTornOff() && mIsP2PChat); @@ -1283,9 +1415,9 @@ LLView* LLFloaterIMSessionTab::getChatHistory() return mChatHistory; } -BOOL LLFloaterIMSessionTab::handleKeyHere(KEY key, MASK mask ) +bool LLFloaterIMSessionTab::handleKeyHere(KEY key, MASK mask ) { - BOOL handled = FALSE; + bool handled = false; if(mask == MASK_ALT) { @@ -1293,17 +1425,17 @@ BOOL LLFloaterIMSessionTab::handleKeyHere(KEY key, MASK mask ) if (KEY_RETURN == key && !isTornOff()) { floater_container->expandConversation(); - handled = TRUE; + handled = true; } if ((KEY_UP == key) || (KEY_LEFT == key)) { floater_container->selectNextorPreviousConversation(false); - handled = TRUE; + handled = true; } if ((KEY_DOWN == key ) || (KEY_RIGHT == key)) { floater_container->selectNextorPreviousConversation(true); - handled = TRUE; + handled = true; } } return handled; |