diff options
Diffstat (limited to 'indra/newview/llbottomtray.cpp')
-rw-r--r-- | indra/newview/llbottomtray.cpp | 529 |
1 files changed, 420 insertions, 109 deletions
diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index 832694873f..958dbf226a 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -40,6 +40,7 @@ #include "llimfloater.h" // for LLIMFloater #include "lllayoutstack.h" #include "llnearbychatbar.h" +#include "llspeakbutton.h" #include "llsplitbutton.h" #include "llsyswellwindow.h" #include "llfloatercamera.h" @@ -50,6 +51,9 @@ LLBottomTray::LLBottomTray(const LLSD&) mSpeakBtn(NULL), mNearbyChatBar(NULL), mToolbarStack(NULL) +, mMovementButton(NULL) +, mResizeState(RS_NORESIZE) +// Add more members { mFactoryMap["chat_bar"] = LLCallbackMap(LLBottomTray::createNearbyChatBar, NULL); @@ -72,6 +76,8 @@ LLBottomTray::LLBottomTray(const LLSD&) //destroyed LLBottomTray requires some subsystems that are long gone //LLUI::getRootView()->addChild(this); + initStateProcessedObjectMap(); + // Necessary for focus movement among child controls setFocusRoot(TRUE); } @@ -181,6 +187,28 @@ void LLBottomTray::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& } } +// virtual +void LLBottomTray::onChange(EStatusType status, const std::string &channelURI, bool proximal) +{ + // Time it takes to connect to voice channel might be pretty long, + // so don't expect user login or STATUS_VOICE_ENABLED to be followed by STATUS_JOINED. + BOOL enable = FALSE; + + switch (status) + { + // Do not add STATUS_VOICE_ENABLED because voice chat is + // inactive until STATUS_JOINED + case STATUS_JOINED: + enable = TRUE; + break; + default: + enable = FALSE; + break; + } + + mSpeakBtn->setEnabled(enable); +} + //virtual void LLBottomTray::onFocusLost() { @@ -234,30 +262,31 @@ void LLBottomTray::showBottomTrayContextMenu(S32 x, S32 y, MASK mask) void LLBottomTray::showGestureButton(BOOL visible) { - mGesturePanel->setVisible(visible); + setTrayButtonVisibleIfPossible(RS_BUTTON_GESTURES, visible); } void LLBottomTray::showMoveButton(BOOL visible) { - mMovementPanel->setVisible(visible); + setTrayButtonVisibleIfPossible(RS_BUTTON_MOVEMENT, visible); } void LLBottomTray::showCameraButton(BOOL visible) { - mCamPanel->setVisible(visible); + setTrayButtonVisibleIfPossible(RS_BUTTON_CAMERA, visible); } void LLBottomTray::showSnapshotButton(BOOL visible) { - mSnapshotPanel->setVisible(visible); + setTrayButtonVisibleIfPossible(RS_BUTTON_SNAPSHOT, visible); } 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_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"; } BOOL LLBottomTray::postBuild() @@ -275,167 +304,449 @@ BOOL LLBottomTray::postBuild() mSnapshotPanel = getChild<LLPanel>("snapshot_panel"); setRightMouseDownCallback(boost::bind(&LLBottomTray::showBottomTrayContextMenu,this, _2, _3,_4)); - if (mChicletPanel && mToolbarStack && mNearbyChatBar) - { - verifyChildControlsSizes(); - } + mSpeakBtn = getChild<LLSpeakButton>("talk"); + + // Speak button should be initially disabled because + // it takes some time between logging in to world and connecting to voice channel. + mSpeakBtn->setEnabled(FALSE); + + // Localization tool doesn't understand custom buttons like <talk_button> + mSpeakBtn->setSpeakToolTip( getString("SpeakBtnToolTip") ); + mSpeakBtn->setShowToolTip( getString("VoiceControlBtnToolTip") ); + + // Registering Chat Bar to receive Voice client status change notifications. + gVoiceClient->addObserver(this); return TRUE; } -void LLBottomTray::verifyChildControlsSizes() +void LLBottomTray::log(LLView* panel, const std::string& descr) { - LLRect rect = mChicletPanel->getRect(); - if (rect.getWidth() < mChicletPanel->getMinWidth()) - { - mChicletPanel->reshape(mChicletPanel->getMinWidth(), rect.getHeight()); - } + if (NULL == panel) return; + LLView* layout = panel->getParent(); + lldebugs << descr << ": " + << "panel: " << panel->getName() + << ", rect: " << panel->getRect() + + + << "layout: " << layout->getName() + << ", rect: " << layout->getRect() + << llendl + ; +} + +void LLBottomTray::reshape(S32 width, S32 height, BOOL called_from_parent) +{ + static S32 debug_calling_number = 0; + lldebugs << "**************************************** " << ++debug_calling_number << llendl; - rect = mNearbyChatBar->getRect(); - if (rect.getWidth() < mNearbyChatBar->getMinWidth()) + S32 current_width = getRect().getWidth(); + S32 delta_width = width - current_width; + lldebugs << "Reshaping: " + << ", width: " << width + << ", cur width: " << current_width + << ", delta_width: " << delta_width + << ", called_from_parent: " << called_from_parent + << llendl; + + if (mNearbyChatBar) log(mNearbyChatBar, "before"); + if (mChicletPanel) log(mChicletPanel, "before"); + + // stores width size on which bottom tray is less than width required by its children. EXT-991 + static S32 extra_shrink_width = 0; + bool should_be_reshaped = true; + + if (mChicletPanel && mToolbarStack && mNearbyChatBar) { - mNearbyChatBar->reshape(mNearbyChatBar->getMinWidth(), rect.getHeight()); + mToolbarStack->updatePanelAutoResize(PANEL_CHICLET_NAME, TRUE); + + // bottom tray is narrowed + if (delta_width < 0) + { + if (extra_shrink_width > 0) + { + // is world rect was extra shrunk and decreasing again only update this value + // to delta_width negative + extra_shrink_width -= delta_width; // use "-=" because delta_width is negative + should_be_reshaped = false; + } + else + { + extra_shrink_width = processWidthDecreased(delta_width); + + // increase new width to extra_shrink_width value to not reshape less than bottom tray minimum + width += extra_shrink_width; + } + } + // bottom tray is widen + else + { + if (extra_shrink_width > delta_width) + { + // Less than minimum width is more than increasing (delta_width) + // only reduce it value and make no reshape + extra_shrink_width -= delta_width; + should_be_reshaped = false; + } + else + { + if (extra_shrink_width > 0) + { + // If we have some extra shrink width let's reduce delta_width & width + delta_width -= extra_shrink_width; + width -= extra_shrink_width; + extra_shrink_width = 0; + } + processWidthIncreased(delta_width); + } + } } - else if (rect.getWidth() > mNearbyChatBar->getMaxWidth()) + + lldebugs << "There is no enough width to reshape all children: " << extra_shrink_width << llendl; + if (should_be_reshaped) { - rect.setLeftTopAndSize(rect.mLeft, rect.mTop, mNearbyChatBar->getMaxWidth(), rect.getHeight()); - mNearbyChatBar->reshape(mNearbyChatBar->getMaxWidth(), rect.getHeight()); - mNearbyChatBar->setRect(rect); + lldebugs << "Reshape all children with width: " << width << llendl; + LLPanel::reshape(width, height, called_from_parent); } + + if (mNearbyChatBar) log(mNearbyChatBar, "after"); + if (mChicletPanel) log(mChicletPanel, "after"); } -void LLBottomTray::reshape(S32 width, S32 height, BOOL called_from_parent) +S32 LLBottomTray::processWidthDecreased(S32 delta_width) { + bool still_should_be_processed = true; - if (mChicletPanel && mToolbarStack && mNearbyChatBar) + const S32 chiclet_panel_width = mChicletPanel->getParent()->getRect().getWidth(); + const S32 chiclet_panel_min_width = mChicletPanel->getMinWidth(); + + if (chiclet_panel_width > chiclet_panel_min_width) { -#ifdef __FEATURE_EXT_991__ - BOOL shrink = width < getRect().getWidth(); - const S32 MIN_RENDERED_CHARS = 3; -#endif + // we have some space to decrease chiclet panel + S32 panel_delta_min = chiclet_panel_width - chiclet_panel_min_width; - verifyChildControlsSizes(); - updateResizeState(width, height); + S32 delta_panel = llmin(-delta_width, panel_delta_min); - switch (mResizeState) - { - case STATE_CHICLET_PANEL: - mToolbarStack->updatePanelAutoResize(PANEL_CHICLET_NAME, TRUE); + lldebugs << "delta_width: " << delta_width + << ", panel_delta_min: " << panel_delta_min + << ", delta_panel: " << delta_panel + << llendl; - mToolbarStack->updatePanelAutoResize(PANEL_CHATBAR_NAME, FALSE); - mToolbarStack->updatePanelAutoResize(PANEL_CAMERA_NAME, FALSE); - mToolbarStack->updatePanelAutoResize(PANEL_MOVEMENT_NAME, FALSE); + // is chiclet panel width enough to process resizing? + delta_width += panel_delta_min; - break; - case STATE_CHATBAR_INPUT: - mToolbarStack->updatePanelAutoResize(PANEL_CHATBAR_NAME, TRUE); + still_should_be_processed = delta_width < 0; - mToolbarStack->updatePanelAutoResize(PANEL_CHICLET_NAME, FALSE); - mToolbarStack->updatePanelAutoResize(PANEL_CAMERA_NAME, FALSE); - mToolbarStack->updatePanelAutoResize(PANEL_MOVEMENT_NAME, FALSE); + mChicletPanel->getParent()->reshape(mChicletPanel->getParent()->getRect().getWidth() - delta_panel, mChicletPanel->getParent()->getRect().getHeight()); + log(mChicletPanel, "after processing panel decreasing via chiclet panel"); - break; + lldebugs << "RS_CHICLET_PANEL" + << ", delta_width: " << delta_width + << llendl; + } -#ifdef __FEATURE_EXT_991__ + const S32 chatbar_panel_width = mNearbyChatBar->getRect().getWidth(); + const S32 chatbar_panel_min_width = mNearbyChatBar->getMinWidth(); + if (still_should_be_processed && chatbar_panel_width > chatbar_panel_min_width) + { + // we have some space to decrease chatbar panel + S32 panel_delta_min = chatbar_panel_width - chatbar_panel_min_width; - case STATE_BUTTONS: - mToolbarStack->updatePanelAutoResize(PANEL_CAMERA_NAME, TRUE); - mToolbarStack->updatePanelAutoResize(PANEL_MOVEMENT_NAME, TRUE); + S32 delta_panel = llmin(-delta_width, panel_delta_min); - mToolbarStack->updatePanelAutoResize(PANEL_CHICLET_NAME, FALSE); - mToolbarStack->updatePanelAutoResize(PANEL_CHATBAR_NAME, FALSE); + // whether chatbar panel width is enough to process resizing? + delta_width += panel_delta_min; - if (shrink) - { + still_should_be_processed = delta_width < 0; - if (mSnapshotPanel->getVisible()) - { - showSnapshotButton(FALSE); - } + mNearbyChatBar->reshape(mNearbyChatBar->getRect().getWidth() - delta_panel, mNearbyChatBar->getRect().getHeight()); - if (mCamPanel->getVisible() && mCamButton->getLastDrawCharsCount() < MIN_RENDERED_CHARS) - { - showCameraButton(FALSE); - } + log(mChicletPanel, "after processing panel decreasing via nearby chatbar panel"); - if (mMovementPanel->getVisible() && mMovementButton->getLastDrawCharsCount() < MIN_RENDERED_CHARS) - { - showMoveButton(FALSE); - } + lldebugs << "RS_CHATBAR_INPUT" + << ", delta_panel: " << delta_panel + << ", delta_width: " << delta_width + << llendl; + } - } - else - { - showMoveButton(TRUE); - mMovementPanel->draw(); + S32 extra_shrink_width = 0; + S32 buttons_freed_width = 0; + if (still_should_be_processed) + { + processHideButton(RS_BUTTON_SNAPSHOT, &delta_width, &buttons_freed_width); - if (mMovementButton->getLastDrawCharsCount() >= MIN_RENDERED_CHARS) - { - showMoveButton(TRUE); - } - else - { - showMoveButton(FALSE); - } - } - break; -#endif + if (delta_width < 0) + { + processHideButton(RS_BUTTON_CAMERA, &delta_width, &buttons_freed_width); + } - default: - break; + if (delta_width < 0) + { + processHideButton(RS_BUTTON_MOVEMENT, &delta_width, &buttons_freed_width); + } + + if (delta_width < 0) + { + processHideButton(RS_BUTTON_GESTURES, &delta_width, &buttons_freed_width); + } + + if (delta_width < 0) + { + extra_shrink_width = -delta_width; + lldebugs << "There is no enough room for bottom tray, resizing still should be processed: " + << extra_shrink_width << llendl; + } + + if (buttons_freed_width > 0) + { + log(mNearbyChatBar, "before applying compensative width"); + mNearbyChatBar->reshape(mNearbyChatBar->getRect().getWidth() + buttons_freed_width, mNearbyChatBar->getRect().getHeight() ); + log(mNearbyChatBar, "after applying compensative width"); + lldebugs << buttons_freed_width << llendl; } } - LLPanel::reshape(width, height, called_from_parent); + return extra_shrink_width; } -void LLBottomTray::updateResizeState(S32 width, S32 height) +void LLBottomTray::processWidthIncreased(S32 delta_width) { - mResizeState = STATE_BUTTONS; + if (delta_width <= 0) return; - const S32 chiclet_panel_width = mChicletPanel->getRect().getWidth(); + const S32 chiclet_panel_width = mChicletPanel->getParent()->getRect().getWidth(); 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(); - // bottom tray is narrowed - if (width < getRect().getWidth()) + 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; + + // how many room we have to show hidden buttons + S32 available_width = delta_width + chatbar_available_shrink_width + available_width_chiclet; + S32 buttons_required_width = 0; //How many room will take shown buttons + + if (available_width > 0) + { + lldebugs << "Trying to process: RS_BUTTON_GESTURES" << llendl; + processShowButton(RS_BUTTON_GESTURES, &available_width, &buttons_required_width); + } + + if (available_width > 0) + { + lldebugs << "Trying to process: RS_BUTTON_MOVEMENT" << llendl; + processShowButton(RS_BUTTON_MOVEMENT, &available_width, &buttons_required_width); + } + + if (available_width > 0) + { + lldebugs << "Trying to process: RS_BUTTON_CAMERA" << llendl; + processShowButton(RS_BUTTON_CAMERA, &available_width, &buttons_required_width); + } + + if (available_width > 0) + { + lldebugs << "Trying to process: RS_BUTTON_SNAPSHOT" << llendl; + processShowButton(RS_BUTTON_SNAPSHOT, &available_width, &buttons_required_width); + } + + // if we have to show some buttons but whidth increasing is not enough... + if (buttons_required_width > 0 && delta_width < buttons_required_width) { - if (chiclet_panel_width > chiclet_panel_min_width) + // ... let's shrink nearby chat & chiclet panels + S32 required_to_process_width = buttons_required_width; + + // 1. use delta width of resizing + required_to_process_width -= delta_width; + + // 2. use width available via decreasing of nearby chat panel + S32 chatbar_shrink_width = required_to_process_width; + if (chatbar_available_shrink_width < chatbar_shrink_width) { - mResizeState = STATE_CHICLET_PANEL; + chatbar_shrink_width = chatbar_available_shrink_width; } - else if (chatbar_panel_width > chatbar_panel_min_width) + + log(mNearbyChatBar, "increase width: before applying compensative width"); + mNearbyChatBar->reshape(mNearbyChatBar->getRect().getWidth() - chatbar_shrink_width, mNearbyChatBar->getRect().getHeight() ); + if (mNearbyChatBar) log(mNearbyChatBar, "after applying compensative width"); + lldebugs << chatbar_shrink_width << llendl; + + // 3. use width available via decreasing of chiclet panel + required_to_process_width -= chatbar_shrink_width; + + if (required_to_process_width > 0) { - mResizeState = STATE_CHATBAR_INPUT; + mChicletPanel->getParent()->reshape(mChicletPanel->getParent()->getRect().getWidth() - required_to_process_width, mChicletPanel->getParent()->getRect().getHeight()); + log(mChicletPanel, "after applying compensative width for chiclets: "); + lldebugs << required_to_process_width << llendl; } - else + + } + + // shown buttons take some space, rest should be processed by nearby chatbar & chiclet panels + delta_width -= buttons_required_width; + + // how many space can nearby chatbar take? + S32 chatbar_panel_width_ = mNearbyChatBar->getRect().getWidth(); + if (delta_width > 0 && chatbar_panel_width_ < chatbar_panel_max_width) + { + S32 delta_panel_max = chatbar_panel_max_width - chatbar_panel_width_; + S32 delta_panel = llmin(delta_width, delta_panel_max); + delta_width -= delta_panel_max; + mNearbyChatBar->reshape(chatbar_panel_width_ + delta_panel, mNearbyChatBar->getRect().getHeight()); + } +} + +bool LLBottomTray::processShowButton(EResizeState shown_object_type, S32* available_width, S32* buttons_required_width) +{ + LLPanel* panel = mStateProcessedObjectMap[shown_object_type]; + if (NULL == panel) + { + lldebugs << "There is no object to process for state: " << shown_object_type << llendl; + return false; + } + bool can_be_shown = canButtonBeShown(shown_object_type); + if (can_be_shown) + { + //validate if we have enough room to show this button + const S32 required_width = panel->getRect().getWidth(); + can_be_shown = *available_width >= required_width; + if (can_be_shown) { - mResizeState = STATE_BUTTONS; + *available_width -= required_width; + *buttons_required_width += required_width; + + setTrayButtonVisible(shown_object_type, true); + + lldebugs << "processing object type: " << shown_object_type + << ", buttons_required_width: " << *buttons_required_width + << llendl; + mResizeState &= ~shown_object_type; } } - // bottom tray is widen - else + return can_be_shown; +} + +void LLBottomTray::processHideButton(EResizeState processed_object_type, S32* required_width, S32* buttons_freed_width) +{ + LLPanel* panel = mStateProcessedObjectMap[processed_object_type]; + if (NULL == panel) { -#ifdef __FEATURE_EXT_991__ - if (!mMovementPanel->getVisible()) + lldebugs << "There is no object to process for state: " << processed_object_type << llendl; + return; + } + + if (panel->getVisible()) + { + *required_width += panel->getRect().getWidth(); + + if (*required_width > 0) { - mResizeState = STATE_BUTTONS; + *buttons_freed_width += *required_width; } - else -#endif - if (chatbar_panel_width < chatbar_panel_max_width) + + setTrayButtonVisible(processed_object_type, false); + + mResizeState |= processed_object_type; + + lldebugs << "processing object type: " << processed_object_type + << ", buttons_freed_width: " << *buttons_freed_width + << llendl; + } +} + +bool LLBottomTray::canButtonBeShown(EResizeState processed_object_type) const +{ + bool can_be_shown = mResizeState & processed_object_type; + if (can_be_shown) + { + static MASK MOVEMENT_PREVIOUS_BUTTONS_MASK = RS_BUTTON_GESTURES; + static MASK CAMERA_PREVIOUS_BUTTONS_MASK = RS_BUTTON_GESTURES | RS_BUTTON_MOVEMENT; + static MASK SNAPSHOT_PREVIOUS_BUTTONS_MASK = RS_BUTTON_GESTURES | RS_BUTTON_MOVEMENT | RS_BUTTON_CAMERA; + + switch(processed_object_type) { - mResizeState = STATE_CHATBAR_INPUT; + case RS_BUTTON_GESTURES: // Gestures should be shown first + break; + case RS_BUTTON_MOVEMENT: // Move only if gesture is shown + can_be_shown = !(MOVEMENT_PREVIOUS_BUTTONS_MASK & mResizeState); + break; + case RS_BUTTON_CAMERA: + can_be_shown = !(CAMERA_PREVIOUS_BUTTONS_MASK & mResizeState); + break; + case RS_BUTTON_SNAPSHOT: + can_be_shown = !(SNAPSHOT_PREVIOUS_BUTTONS_MASK & mResizeState); + break; + default: // nothing to do here + break; } - else + } + return can_be_shown; +} + +void LLBottomTray::initStateProcessedObjectMap() +{ + mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_GESTURES, mGesturePanel)); + 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)); +} + +void LLBottomTray::setTrayButtonVisible(EResizeState shown_object_type, bool visible) +{ + LLPanel* panel = mStateProcessedObjectMap[shown_object_type]; + if (NULL == panel) + { + lldebugs << "There is no object to show for state: " << shown_object_type << llendl; + return; + } + + panel->setVisible(visible); +} + +void LLBottomTray::setTrayButtonVisibleIfPossible(EResizeState shown_object_type, bool visible) +{ + bool can_be_set = true; + + if (visible) + { + LLPanel* panel = mStateProcessedObjectMap[shown_object_type]; + if (NULL == panel) { - mResizeState = STATE_CHICLET_PANEL; + lldebugs << "There is no object to process for state: " << shown_object_type << llendl; + return; } + + const S32 chatbar_panel_width = mNearbyChatBar->getRect().getWidth(); + const S32 chatbar_panel_min_width = mNearbyChatBar->getMinWidth(); + + const S32 chiclet_panel_width = mChicletPanel->getParent()->getRect().getWidth(); + const S32 chiclet_panel_min_width = mChicletPanel->getMinWidth(); + + const S32 available_width = (chatbar_panel_width - chatbar_panel_min_width) + + (chiclet_panel_width - chiclet_panel_min_width); + + const S32 required_width = panel->getRect().getWidth(); + can_be_set = available_width >= required_width; } + if (can_be_set) + { + setTrayButtonVisible(shown_object_type, visible); - // TODO: finish implementation + // if we hide the button mark it NOT to show while future bottom tray extending + if (!visible) + { + mResizeState &= ~shown_object_type; + } + } + else + { + // mark this button to show it while future bottom tray extending + mResizeState |= shown_object_type; + LLNotifications::instance().add("BottomTrayButtonCanNotBeShown"); + } } + +//EOF |