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.cpp361
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, &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;
- 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