diff options
Diffstat (limited to 'indra/newview/llbottomtray.cpp')
-rw-r--r-- | indra/newview/llbottomtray.cpp | 361 |
1 files changed, 288 insertions, 73 deletions
diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index 976b312509..b88be53d79 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -48,10 +48,93 @@ #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(); +namespace +{ + const std::string& PANEL_CHICLET_NAME = "chiclet_list_panel"; + const std::string& PANEL_CHATBAR_NAME = "chat_bar"; + 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_panel_max_width(LLLayoutStack* stack, LLPanel* panel) + { + S32 max_width = 0; + llassert(stack); + if ( stack && panel && panel->getVisible() ) + { + stack->getPanelMaxSize(panel->getName(), &max_width, NULL); + } + return max_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), @@ -66,6 +149,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. @@ -90,6 +175,12 @@ LLBottomTray::LLBottomTray(const LLSD&) // Necessary for focus movement among child controls setFocusRoot(TRUE); + + { + mBottomTrayLite = new LLBottomTrayLite(); + mBottomTrayLite->setFollowsAll(); + mBottomTrayLite->setVisible(FALSE); + } } LLBottomTray::~LLBottomTray() @@ -124,6 +215,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); @@ -161,6 +257,9 @@ void LLBottomTray::sessionAdded(const LLUUID& session_id, const std::string& nam { chiclet->setIMSessionName(name); chiclet->setOtherParticipantId(other_participant_id); + + LLIMFloater::onIMChicletCreated(session_id); + } else { @@ -221,16 +320,36 @@ void LLBottomTray::onChange(EStatusType status, const std::string &channelURI, b break; } - mSpeakBtn->setEnabled(enable); + // 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) + { + mSpeakBtn->setFlyoutBtnEnabled(LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking()); + } } -//virtual -void LLBottomTray::onFocusLost() +void LLBottomTray::onMouselookModeOut() { - if (gAgent.cameraMouselook()) - { - setVisible(FALSE); - } + mIsInLiteMode = false; + mBottomTrayLite->setVisible(FALSE); + mNearbyChatBar->getChatBox()->setText(mBottomTrayLite->mNearbyChatBar->getChatBox()->getText()); + setVisible(TRUE); +} + +void LLBottomTray::onMouselookModeIn() +{ + 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 @@ -238,28 +357,18 @@ void LLBottomTray::onFocusLost() // 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(); - - if ("chat_bar" == name || "movement_panel" == name || "cam_panel" == name || "snapshot_panel" == name || "gesture_panel" == name) - continue; - else - { - viewp->setVisible(visibility); - } - } + mBottomTrayLite->setVisible(visible); + } + else + { + LLPanel::setVisible(visible); } + if(visible) + gFloaterView->setSnapOffsetBottom(getRect().getHeight()); + else + gFloaterView->setSnapOffsetBottom(0); } void LLBottomTray::showBottomTrayContextMenu(S32 x, S32 y, MASK mask) @@ -324,13 +433,16 @@ void LLBottomTray::showSnapshotButton(BOOL visible) setTrayButtonVisibleIfPossible(RS_BUTTON_SNAPSHOT, visible); } -namespace +void LLBottomTray::toggleMovementControls() { - const std::string& PANEL_CHICLET_NAME = "chiclet_list_panel"; - const std::string& PANEL_CHATBAR_NAME = "chat_bar"; - const std::string& PANEL_MOVEMENT_NAME = "movement_panel"; - const std::string& PANEL_CAMERA_NAME = "cam_panel"; - const std::string& PANEL_GESTURE_NAME = "gesture_panel"; + if (mMovementButton) + mMovementButton->onCommit(); +} + +void LLBottomTray::toggleCameraControls() +{ + if (mCamButton) + mCamButton->onCommit(); } BOOL LLBottomTray::postBuild() @@ -356,9 +468,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") ); @@ -372,6 +485,8 @@ BOOL LLBottomTray::postBuild() mObjectDefaultWidthMap[RS_BUTTON_CAMERA] = mCamPanel->getRect().getWidth(); mObjectDefaultWidthMap[RS_BUTTON_SPEAK] = mSpeakPanel->getRect().getWidth(); + mNearbyChatBar->getChatBox()->setContextMenu(NULL); + return TRUE; } @@ -420,6 +535,7 @@ void LLBottomTray::onContextMenuItemClicked(const LLSD& userdata) else if (item == "paste") { edit_box->paste(); + edit_box->setFocus(TRUE); } else if (item == "delete") { @@ -469,7 +585,18 @@ void LLBottomTray::reshape(S32 width, S32 height, BOOL called_from_parent) if (mChicletPanel && mToolbarStack && mNearbyChatBar) { - mToolbarStack->updatePanelAutoResize(PANEL_CHICLET_NAME, TRUE); + // 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) @@ -556,7 +683,7 @@ S32 LLBottomTray::processWidthDecreased(S32 delta_width) } const S32 chatbar_panel_width = mNearbyChatBar->getRect().getWidth(); - const S32 chatbar_panel_min_width = mNearbyChatBar->getMinWidth(); + const S32 chatbar_panel_min_width = get_panel_min_width(mToolbarStack, mNearbyChatBar); if (still_should_be_processed && chatbar_panel_width > chatbar_panel_min_width) { // we have some space to decrease chatbar panel @@ -571,7 +698,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 @@ -629,11 +756,11 @@ void LLBottomTray::processWidthIncreased(S32 delta_width) if (delta_width <= 0) return; const S32 chiclet_panel_width = mChicletPanel->getParent()->getRect().getWidth(); - const S32 chiclet_panel_min_width = mChicletPanel->getMinWidth(); + static const S32 chiclet_panel_min_width = mChicletPanel->getMinWidth(); const S32 chatbar_panel_width = mNearbyChatBar->getRect().getWidth(); - const S32 chatbar_panel_min_width = mNearbyChatBar->getMinWidth(); - const S32 chatbar_panel_max_width = mNearbyChatBar->getMaxWidth(); + static const S32 chatbar_panel_min_width = get_panel_min_width(mToolbarStack, mNearbyChatBar); + static const S32 chatbar_panel_max_width = get_panel_max_width(mToolbarStack, mNearbyChatBar); const S32 chatbar_available_shrink_width = chatbar_panel_width - chatbar_panel_min_width; const S32 available_width_chiclet = chiclet_panel_width - chiclet_panel_min_width; @@ -810,13 +937,12 @@ void LLBottomTray::processShrinkButtons(S32* required_width, S32* buttons_freed_ } else { - // - mSpeakBtn->setLabelVisible(false); S32 panel_width = mSpeakPanel->getRect().getWidth(); S32 possible_shrink_width = panel_width - panel_min_width; if (possible_shrink_width > 0) { + mSpeakBtn->setLabelVisible(false); mSpeakPanel->reshape(panel_width - possible_shrink_width, mSpeakPanel->getRect().getHeight()); *required_width += possible_shrink_width; @@ -891,18 +1017,18 @@ void LLBottomTray::processExtendButtons(S32* available_width) if (*available_width > 0) { - processExtendButton(RS_BUTTON_CAMERA, available_width); + processExtendButton(RS_BUTTON_MOVEMENT, available_width); } if (*available_width > 0) { - processExtendButton(RS_BUTTON_MOVEMENT, available_width); + processExtendButton(RS_BUTTON_CAMERA, available_width); } if (*available_width > 0) { S32 panel_max_width = mObjectDefaultWidthMap[RS_BUTTON_SPEAK]; S32 panel_width = mSpeakPanel->getRect().getWidth(); S32 possible_extend_width = panel_max_width - panel_width; - if (possible_extend_width > 0 && possible_extend_width <= *available_width) + if (possible_extend_width >= 0 && possible_extend_width <= *available_width) // HACK: this button doesn't change size so possible_extend_width will be 0 { mSpeakBtn->setLabelVisible(true); mSpeakPanel->reshape(panel_max_width, mSpeakPanel->getRect().getHeight()); @@ -991,6 +1117,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) @@ -1003,50 +1134,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) +void LLBottomTray::setTrayButtonVisibleIfPossible(EResizeState shown_object_type, bool visible, bool raise_notification) { - bool can_be_set = true; + if (!setVisibleAndFitWidths(shown_object_type, visible) && visible && raise_notification) + { + LLNotificationsUtil::add("BottomTrayButtonCanNotBeShown", + LLSD(), + LLSD(), + LLNotificationFunctorRegistry::instance().DONOTHING); + } +} - if (visible) +bool LLBottomTray::setVisibleAndFitWidths(EResizeState object_type, bool visible) +{ + LLPanel* cur_panel = mStateProcessedObjectMap[object_type]; + if (NULL == cur_panel) { - LLPanel* panel = mStateProcessedObjectMap[shown_object_type]; - if (NULL == panel) - { - lldebugs << "There is no object to process for state: " << shown_object_type << llendl; - return; - } + lldebugs << "There is no object to process for state: " << object_type << llendl; + return false; + } - const S32 chatbar_panel_width = mNearbyChatBar->getRect().getWidth(); - const S32 chatbar_panel_min_width = mNearbyChatBar->getMinWidth(); + const S32 dummy_width = mDummiesMap.count(object_type) + ? mDummiesMap[object_type]->getParent()->getRect().getWidth() + : 0; - const S32 chiclet_panel_width = mChicletPanel->getParent()->getRect().getWidth(); - const S32 chiclet_panel_min_width = mChicletPanel->getMinWidth(); + bool is_set = true; - const S32 available_width = (chatbar_panel_width - chatbar_panel_min_width) - + (chiclet_panel_width - chiclet_panel_min_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() - get_panel_min_width(mToolbarStack, mNearbyChatBar); + + 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 preferred_width so buttons widths decreasing will be done in predefined order + result_width = (preferred_width > 0) ? preferred_width : current_width; + decrease_width = true; + } + else + { + // Nothing can be done, give up... + return false; + } + } - const S32 required_width = panel->getRect().getWidth(); - can_be_set = available_width >= required_width; - } + if (result_width != current_width) + { + cur_panel->reshape(result_width, cur_panel->getRect().getHeight()); + current_width = result_width; + } - if (can_be_set) - { - setTrayButtonVisible(shown_object_type, visible); + 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; - 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 |