diff options
Diffstat (limited to 'indra/newview/llbottomtray.cpp')
-rw-r--r-- | indra/newview/llbottomtray.cpp | 336 |
1 files changed, 236 insertions, 100 deletions
diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index 8a7ed23b59..463add9f4b 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -48,6 +48,7 @@ #include "llsyswellwindow.h" #include "llfloatercamera.h" #include "lltexteditor.h" +#include "llnotifications.h" // Build time optimization, generate extern template once in .cpp file template class LLBottomTray* LLSingleton<class LLBottomTray>::getInstance(); @@ -59,8 +60,70 @@ namespace const std::string& PANEL_MOVEMENT_NAME = "movement_panel"; const std::string& PANEL_CAMERA_NAME = "cam_panel"; const std::string& PANEL_GESTURE_NAME = "gesture_panel"; + + S32 get_panel_min_width(LLLayoutStack* stack, LLPanel* panel) + { + S32 minimal_width = 0; + llassert(stack); + if ( stack && panel && panel->getVisible() ) + { + stack->getPanelMinSize(panel->getName(), &minimal_width, NULL); + } + return minimal_width; + } + + S32 get_curr_width(LLUICtrl* ctrl) + { + S32 cur_width = 0; + if ( ctrl && ctrl->getVisible() ) + { + cur_width = ctrl->getRect().getWidth(); + } + return cur_width; + } } +class LLBottomTrayLite + : public LLPanel +{ +public: + LLBottomTrayLite() + : mNearbyChatBar(NULL), + mGesturePanel(NULL) + { + mFactoryMap["chat_bar"] = LLCallbackMap(LLBottomTray::createNearbyChatBar, NULL); + LLUICtrlFactory::getInstance()->buildPanel(this, "panel_bottomtray_lite.xml"); + // Necessary for focus movement among child controls + setFocusRoot(TRUE); + } + + BOOL postBuild() + { + mNearbyChatBar = getChild<LLNearbyChatBar>("chat_bar"); + mGesturePanel = getChild<LLPanel>("gesture_panel"); + + // Hide "show_nearby_chat" button + LLLineEditor* chat_box = mNearbyChatBar->getChatBox(); + LLUICtrl* show_btn = mNearbyChatBar->getChild<LLUICtrl>("show_nearby_chat"); + S32 delta_width = show_btn->getRect().getWidth(); + show_btn->setVisible(FALSE); + chat_box->reshape(chat_box->getRect().getWidth() + delta_width, chat_box->getRect().getHeight()); + + return TRUE; + } + + void onFocusLost() + { + if (gAgent.cameraMouselook()) + { + LLBottomTray::getInstance()->setVisible(FALSE); +} + } + + LLNearbyChatBar* mNearbyChatBar; + LLPanel* mGesturePanel; +}; + LLBottomTray::LLBottomTray(const LLSD&) : mChicletPanel(NULL), mSpeakPanel(NULL), @@ -75,6 +138,8 @@ LLBottomTray::LLBottomTray(const LLSD&) , mSnapshotPanel(NULL) , mGesturePanel(NULL) , mCamButton(NULL) +, mBottomTrayLite(NULL) +, mIsInLiteMode(false) { // Firstly add ourself to IMSession observers, so we catch session events // before chiclets do that. @@ -99,6 +164,12 @@ LLBottomTray::LLBottomTray(const LLSD&) // Necessary for focus movement among child controls setFocusRoot(TRUE); + + { + mBottomTrayLite = new LLBottomTrayLite(); + mBottomTrayLite->setFollowsAll(); + mBottomTrayLite->setVisible(FALSE); + } } LLBottomTray::~LLBottomTray() @@ -133,6 +204,11 @@ void* LLBottomTray::createNearbyChatBar(void* userdata) return new LLNearbyChatBar(); } +LLNearbyChatBar* LLBottomTray::getNearbyChatBar() +{ + return mIsInLiteMode ? mBottomTrayLite->mNearbyChatBar : mNearbyChatBar; +} + LLIMChiclet* LLBottomTray::createIMChiclet(const LLUUID& session_id) { LLIMChiclet::EType im_chiclet_type = LLIMChiclet::getIMSessionType(session_id); @@ -233,67 +309,36 @@ void LLBottomTray::onChange(EStatusType status, const std::string &channelURI, b break; } - mSpeakBtn->setEnabled(enable); -} - -//virtual -void LLBottomTray::onFocusLost() -{ - if (gAgent.cameraMouselook()) - { - setVisible(FALSE); - } -} - -void LLBottomTray::savePanelsShape() -{ - mSavedShapeList.clear(); - for (child_list_const_iter_t - child_it = mToolbarStack->beginChild(), - child_it_end = mToolbarStack->endChild(); - child_it != child_it_end; ++child_it) - { - mSavedShapeList.push_back( (*child_it)->getRect() ); - } -} - -void LLBottomTray::restorePanelsShape() -{ - if (mSavedShapeList.size() != mToolbarStack->getChildCount()) - return; - int i = 0; - for (child_list_const_iter_t - child_it = mToolbarStack->beginChild(), - child_it_end = mToolbarStack->endChild(); - child_it != child_it_end; ++child_it) + // We have to enable/disable right and left parts of speak button separately (EXT-4648) + mSpeakBtn->setSpeakBtnEnabled(enable); + // skipped to avoid button blinking + if (status != STATUS_JOINING && status!= STATUS_LEFT_CHANNEL) { - (*child_it)->setShape(mSavedShapeList[i++]); + mSpeakBtn->setFlyoutBtnEnabled(LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking()); } } void LLBottomTray::onMouselookModeOut() -{ - // Apply the saved settings when we are not in mouselook mode, see EXT-3988. { - setTrayButtonVisibleIfPossible (RS_BUTTON_GESTURES, gSavedSettings.getBOOL("ShowGestureButton"), false); - setTrayButtonVisibleIfPossible (RS_BUTTON_MOVEMENT, gSavedSettings.getBOOL("ShowMoveButton"), false); - setTrayButtonVisibleIfPossible (RS_BUTTON_CAMERA, gSavedSettings.getBOOL("ShowCameraButton"), false); - setTrayButtonVisibleIfPossible (RS_BUTTON_SNAPSHOT, gSavedSettings.getBOOL("ShowSnapshotButton"),false); - } - // HACK: To avoid usage the LLLayoutStack logic of resizing, we force the updateLayout - // and then restore children saved shapes. See EXT-4309. - BOOL saved_anim = mToolbarStack->getAnimate(); - mToolbarStack->updatePanelAutoResize(PANEL_CHATBAR_NAME, FALSE); - mToolbarStack->setAnimate(FALSE); - mToolbarStack->updateLayout(); - mToolbarStack->setAnimate(saved_anim); - restorePanelsShape(); + mIsInLiteMode = false; + mBottomTrayLite->setVisible(FALSE); + mNearbyChatBar->getChatBox()->setText(mBottomTrayLite->mNearbyChatBar->getChatBox()->getText()); + setVisible(TRUE); } void LLBottomTray::onMouselookModeIn() { - savePanelsShape(); - mToolbarStack->updatePanelAutoResize(PANEL_CHATBAR_NAME, TRUE); + setVisible(FALSE); + + // Attach the lite bottom tray + if (getParent() && mBottomTrayLite->getParent() != getParent()) + getParent()->addChild(mBottomTrayLite); + + mBottomTrayLite->setShape(getLocalRect()); + mBottomTrayLite->mNearbyChatBar->getChatBox()->setText(mNearbyChatBar->getChatBox()->getText()); + mBottomTrayLite->mGesturePanel->setVisible(gSavedSettings.getBOOL("ShowGestureButton")); + + mIsInLiteMode = true; } //virtual @@ -301,30 +346,18 @@ void LLBottomTray::onMouselookModeIn() // If bottom tray is already visible in mouselook mode, then onVisibilityChange will not be called from setVisible(true), void LLBottomTray::setVisible(BOOL visible) { - LLPanel::setVisible(visible); - - // *NOTE: we must check mToolbarStack against NULL because setVisible is called from the - // LLPanel::initFromParams BEFORE postBuild is called and child controls are not exist yet - if (NULL != mToolbarStack) + if (mIsInLiteMode) { - BOOL visibility = gAgent.cameraMouselook() ? false : true; - - for ( child_list_const_iter_t child_it = mToolbarStack->getChildList()->begin(); - child_it != mToolbarStack->getChildList()->end(); child_it++) - { - LLView* viewp = *child_it; - std::string name = viewp->getName(); - - // Chat bar and gesture button are shown even in mouselook mode. - // But the move, camera and snapshot buttons shouldn't be displayed. See EXT-3988. - if ("chat_bar" == name || "gesture_panel" == name) - continue; + mBottomTrayLite->setVisible(visible); + } else { - viewp->setVisible(visibility); + LLPanel::setVisible(visible); } - } - } + if(visible) + gFloaterView->setSnapOffsetBottom(getRect().getHeight()); + else + gFloaterView->setSnapOffsetBottom(0); } void LLBottomTray::showBottomTrayContextMenu(S32 x, S32 y, MASK mask) @@ -412,9 +445,10 @@ BOOL LLBottomTray::postBuild() mSpeakPanel = getChild<LLPanel>("speak_panel"); mSpeakBtn = getChild<LLSpeakButton>("talk"); - // Speak button should be initially disabled because + // Both parts of speak button should be initially disabled because // it takes some time between logging in to world and connecting to voice channel. - mSpeakBtn->setEnabled(FALSE); + mSpeakBtn->setSpeakBtnEnabled(false); + mSpeakBtn->setFlyoutBtnEnabled(false); // Localization tool doesn't understand custom buttons like <talk_button> mSpeakBtn->setSpeakToolTip( getString("SpeakBtnToolTip") ); @@ -428,6 +462,8 @@ BOOL LLBottomTray::postBuild() mObjectDefaultWidthMap[RS_BUTTON_CAMERA] = mCamPanel->getRect().getWidth(); mObjectDefaultWidthMap[RS_BUTTON_SPEAK] = mSpeakPanel->getRect().getWidth(); + mNearbyChatBar->getChatBox()->setContextMenu(NULL); + return TRUE; } @@ -476,6 +512,7 @@ void LLBottomTray::onContextMenuItemClicked(const LLSD& userdata) else if (item == "paste") { edit_box->paste(); + edit_box->setFocus(TRUE); } else if (item == "delete") { @@ -525,7 +562,18 @@ void LLBottomTray::reshape(S32 width, S32 height, BOOL called_from_parent) if (mChicletPanel && mToolbarStack && mNearbyChatBar) { + // Firstly, update layout stack to ensure we deal with correct panel sizes. + { + BOOL saved_anim = mToolbarStack->getAnimate(); + // Set chiclet panel to be autoresized by default. mToolbarStack->updatePanelAutoResize(PANEL_CHICLET_NAME, TRUE); + // Disable animation to prevent layout updating in several frames. + mToolbarStack->setAnimate(FALSE); + // Force the updating of layout to reset panels collapse factor. + mToolbarStack->updateLayout(); + // Restore animate state. + mToolbarStack->setAnimate(saved_anim); + } // bottom tray is narrowed if (delta_width < 0) @@ -627,7 +675,7 @@ S32 LLBottomTray::processWidthDecreased(S32 delta_width) mNearbyChatBar->reshape(mNearbyChatBar->getRect().getWidth() - delta_panel, mNearbyChatBar->getRect().getHeight()); - log(mChicletPanel, "after processing panel decreasing via nearby chatbar panel"); + log(mNearbyChatBar, "after processing panel decreasing via nearby chatbar panel"); lldebugs << "RS_CHATBAR_INPUT" << ", delta_panel: " << delta_panel @@ -1047,6 +1095,11 @@ void LLBottomTray::initStateProcessedObjectMap() mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_MOVEMENT, mMovementPanel)); mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_CAMERA, mCamPanel)); mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_SNAPSHOT, mSnapshotPanel)); + + mDummiesMap.insert(std::make_pair(RS_BUTTON_GESTURES, getChild<LLUICtrl>("after_gesture_panel"))); + mDummiesMap.insert(std::make_pair(RS_BUTTON_MOVEMENT, getChild<LLUICtrl>("after_movement_panel"))); + mDummiesMap.insert(std::make_pair(RS_BUTTON_CAMERA, getChild<LLUICtrl>("after_cam_panel"))); + mDummiesMap.insert(std::make_pair(RS_BUTTON_SPEAK, getChild<LLUICtrl>("after_speak_panel"))); } void LLBottomTray::setTrayButtonVisible(EResizeState shown_object_type, bool visible) @@ -1059,51 +1112,134 @@ void LLBottomTray::setTrayButtonVisible(EResizeState shown_object_type, bool vis } panel->setVisible(visible); + + if (mDummiesMap.count(shown_object_type)) + { + // Hide/show layout panel for dummy icon. + mDummiesMap[shown_object_type]->getParent()->setVisible(visible); + } } void LLBottomTray::setTrayButtonVisibleIfPossible(EResizeState shown_object_type, bool visible, bool raise_notification) { - bool can_be_set = true; - - if (visible) + if (!setVisibleAndFitWidths(shown_object_type, visible) && visible && raise_notification) { - LLPanel* panel = mStateProcessedObjectMap[shown_object_type]; - if (NULL == panel) - { - lldebugs << "There is no object to process for state: " << shown_object_type << llendl; - return; - } + LLNotificationsUtil::add("BottomTrayButtonCanNotBeShown", + LLSD(), + LLSD(), + LLNotificationFunctorRegistry::instance().DONOTHING); + } +} - const S32 chatbar_panel_width = mNearbyChatBar->getRect().getWidth(); - const S32 chatbar_panel_min_width = mNearbyChatBar->getMinWidth(); +bool LLBottomTray::setVisibleAndFitWidths(EResizeState object_type, bool visible) +{ + LLPanel* cur_panel = mStateProcessedObjectMap[object_type]; + if (NULL == cur_panel) + { + lldebugs << "There is no object to process for state: " << object_type << llendl; + return false; + } - const S32 chiclet_panel_width = mChicletPanel->getParent()->getRect().getWidth(); - const S32 chiclet_panel_min_width = mChicletPanel->getMinWidth(); + const S32 dummy_width = mDummiesMap.count(object_type) + ? mDummiesMap[object_type]->getParent()->getRect().getWidth() + : 0; - const S32 available_width = (chatbar_panel_width - chatbar_panel_min_width) - + (chiclet_panel_width - chiclet_panel_min_width); + bool is_set = true; - const S32 required_width = panel->getRect().getWidth(); - can_be_set = available_width >= required_width; + if (visible) + { + // Assume that only chiclet panel can be auto-resized and + // don't take into account width of dummy widgets + const S32 available_width = + mChicletPanel->getParent()->getRect().getWidth() - + mChicletPanel->getMinWidth() - + dummy_width; + + S32 preferred_width = mObjectDefaultWidthMap[object_type]; + S32 current_width = cur_panel->getRect().getWidth(); + S32 result_width = 0; + bool decrease_width = false; + + // Mark this button to be shown + mResizeState |= object_type; + + if (preferred_width > 0 && available_width >= preferred_width) + { + result_width = preferred_width; + } + else if (available_width >= current_width) + { + result_width = current_width; + } + else + { + // Calculate the possible shrunk width as difference between current and minimal widths + const S32 chatbar_shrunk_width = + mNearbyChatBar->getRect().getWidth() - mNearbyChatBar->getMinWidth(); + + const S32 sum_of_min_widths = + get_panel_min_width(mToolbarStack, mStateProcessedObjectMap[RS_BUTTON_CAMERA]) + + get_panel_min_width(mToolbarStack, mStateProcessedObjectMap[RS_BUTTON_MOVEMENT]) + + get_panel_min_width(mToolbarStack, mStateProcessedObjectMap[RS_BUTTON_GESTURES]) + + get_panel_min_width(mToolbarStack, mSpeakPanel); + + const S32 sum_of_curr_widths = + get_curr_width(mStateProcessedObjectMap[RS_BUTTON_CAMERA]) + + get_curr_width(mStateProcessedObjectMap[RS_BUTTON_MOVEMENT]) + + get_curr_width(mStateProcessedObjectMap[RS_BUTTON_GESTURES]) + + get_curr_width(mSpeakPanel); + + const S32 possible_shrunk_width = + chatbar_shrunk_width + (sum_of_curr_widths - sum_of_min_widths); + + // Minimal width of current panel + S32 minimal_width = 0; + mToolbarStack->getPanelMinSize(cur_panel->getName(), &minimal_width, NULL); + + if ( (available_width + possible_shrunk_width) >= minimal_width) + { + // There is enough space for minimal width, but set the result_width + // to current_width so buttons widths decreasing will be done in predefined order + result_width = current_width; + decrease_width = true; + } + else + { + // Nothing can be done, give up... + return false; + } } - if (can_be_set) + if (result_width != current_width) { - setTrayButtonVisible(shown_object_type, visible); + cur_panel->reshape(result_width, cur_panel->getRect().getHeight()); + current_width = result_width; + } + + is_set = processShowButton(object_type, ¤t_width); - // if we hide the button mark it NOT to show while future bottom tray extending - if (!visible) + // Shrink buttons if needed + if (is_set && decrease_width) { - mResizeState &= ~shown_object_type; + processWidthDecreased( -result_width - dummy_width ); } } else { - // mark this button to show it while future bottom tray extending - mResizeState |= shown_object_type; - if ( raise_notification ) - LLNotificationsUtil::add("BottomTrayButtonCanNotBeShown"); + const S32 delta_width = get_curr_width(cur_panel); + + setTrayButtonVisible(object_type, false); + + // Mark button NOT to show while future bottom tray extending + mResizeState &= ~object_type; + + // Extend other buttons if need + if (delta_width) + { + processWidthIncreased(delta_width + dummy_width); + } } + return is_set; } //EOF |