summaryrefslogtreecommitdiff
path: root/indra/newview/llbottomtray.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llbottomtray.cpp')
-rw-r--r--indra/newview/llbottomtray.cpp336
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, &current_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