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.cpp717
1 files changed, 502 insertions, 215 deletions
diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp
index 93b708f299..41f5fe64a1 100644
--- a/indra/newview/llbottomtray.cpp
+++ b/indra/newview/llbottomtray.cpp
@@ -35,20 +35,32 @@
#define LLBOTTOMTRAY_CPP
#include "llbottomtray.h"
-#include "llagent.h"
-#include "llchiclet.h"
+// library includes
#include "llfloaterreg.h"
#include "llflyoutbutton.h"
-#include "llimfloater.h" // for LLIMFloater
#include "lllayoutstack.h"
-#include "llnearbychatbar.h"
+#include "llnotifications.h"
#include "llnotificationsutil.h"
+#include "lltexteditor.h"
+
+// newview includes
+#include "llagentcamera.h"
+#include "llchiclet.h"
+#include "llfloatercamera.h"
+#include "llimfloater.h" // for LLIMFloater
+#include "llnearbychatbar.h"
#include "llspeakbutton.h"
#include "llsplitbutton.h"
#include "llsyswellwindow.h"
-#include "llfloatercamera.h"
-#include "lltexteditor.h"
-#include "llnotifications.h"
+#include "lltoolmgr.h"
+#include "llviewerparcelmgr.h"
+
+static void update_build_button_enable_state()
+{
+ bool can_edit = LLToolMgr::getInstance()->canEdit();
+
+ LLBottomTray::getInstance()->childSetEnabled("build_btn", can_edit);
+}
// Build time optimization, generate extern template once in .cpp file
template class LLBottomTray* LLSingleton<class LLBottomTray>::getInstance();
@@ -60,6 +72,38 @@ 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, LLView* 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
@@ -93,7 +137,7 @@ public:
void onFocusLost()
{
- if (gAgent.cameraMouselook())
+ if (gAgentCamera.cameraMouselook())
{
LLBottomTray::getInstance()->setVisible(FALSE);
}
@@ -112,10 +156,6 @@ LLBottomTray::LLBottomTray(const LLSD&)
, mMovementButton(NULL)
, mResizeState(RS_NORESIZE)
, mBottomTrayContextMenu(NULL)
-, mMovementPanel(NULL)
-, mCamPanel(NULL)
-, mSnapshotPanel(NULL)
-, mGesturePanel(NULL)
, mCamButton(NULL)
, mBottomTrayLite(NULL)
, mIsInLiteMode(false)
@@ -128,19 +168,13 @@ LLBottomTray::LLBottomTray(const LLSD&)
LLUICtrlFactory::getInstance()->buildPanel(this,"panel_bottomtray.xml");
- mChicletPanel = getChild<LLChicletPanel>("chiclet_list");
-
- mChicletPanel->setChicletClickedCallback(boost::bind(&LLBottomTray::onChicletClick,this,_1));
-
- LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("CameraPresets.ChangeView", boost::bind(&LLFloaterCamera::onClickCameraPresets, _2));
+ LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("CameraPresets.ChangeView", boost::bind(&LLFloaterCamera::onClickCameraItem, _2));
//this is to fix a crash that occurs because LLBottomTray is a singleton
//and thus is deleted at the end of the viewers lifetime, but to be cleanly
//destroyed LLBottomTray requires some subsystems that are long gone
//LLUI::getRootView()->addChild(this);
- initStateProcessedObjectMap();
-
// Necessary for focus movement among child controls
setFocusRoot(TRUE);
@@ -157,24 +191,21 @@ LLBottomTray::~LLBottomTray()
{
LLIMMgr::getInstance()->removeSessionObserver(this);
}
-}
-void LLBottomTray::onChicletClick(LLUICtrl* ctrl)
-{
- LLIMChiclet* chiclet = dynamic_cast<LLIMChiclet*>(ctrl);
- if (chiclet)
+ if (mNearbyChatBar)
{
- // Until you can type into an IM Window and have a conversation,
- // still show the old communicate window
- //LLFloaterReg::showInstance("communicate", chiclet->getSessionId());
-
- // Show after comm window so it is frontmost (and hence will not
- // auto-hide)
-
-// this logic has been moved to LLIMChiclet::handleMouseDown
-// LLIMFloater::show(chiclet->getSessionId());
-// chiclet->setCounter(0);
+ // store custom width of chatbar panel.
+ S32 custom_width = mNearbyChatBar->getRect().getWidth();
+ gSavedSettings.setS32("ChatBarCustomWidth", custom_width);
}
+
+ // emulate previous floater behavior to be hidden on startup.
+ // override effect of save_visibility=true.
+ // this attribute is necessary to button.initial_callback=Button.SetFloaterToggle works properly:
+ // i.g when floater changes its visibility - button changes its toggle state.
+ getChild<LLUICtrl>("build_btn")->setControlValue(false);
+ getChild<LLUICtrl>("search_btn")->setControlValue(false);
+ getChild<LLUICtrl>("world_map_btn")->setControlValue(false);
}
// *TODO Vadim: why void* ?
@@ -293,7 +324,7 @@ void LLBottomTray::onChange(EStatusType status, const std::string &channelURI, b
// skipped to avoid button blinking
if (status != STATUS_JOINING && status!= STATUS_LEFT_CHANNEL)
{
- mSpeakBtn->setFlyoutBtnEnabled(LLVoiceClient::voiceEnabled() && gVoiceClient->voiceWorking());
+ mSpeakBtn->setFlyoutBtnEnabled(LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking());
}
}
@@ -329,7 +360,7 @@ void LLBottomTray::setVisible(BOOL visible)
{
mBottomTrayLite->setVisible(visible);
}
- else
+ else
{
LLPanel::setVisible(visible);
}
@@ -339,6 +370,37 @@ void LLBottomTray::setVisible(BOOL visible)
gFloaterView->setSnapOffsetBottom(0);
}
+S32 LLBottomTray::notifyParent(const LLSD& info)
+{
+ if(info.has("well_empty")) // implementation of EXT-3397
+ {
+ const std::string chiclet_name = info["well_name"];
+
+ // only "im_well" or "notification_well" names are expected.
+ // They are set in panel_bottomtray.xml in <chiclet_im_well> & <chiclet_notification>
+ llassert("im_well" == chiclet_name || "notification_well" == chiclet_name);
+
+ BOOL should_be_visible = !info["well_empty"];
+ showWellButton("im_well" == chiclet_name ? RS_IM_WELL : RS_NOTIFICATION_WELL, should_be_visible);
+ return 1;
+ }
+
+ if (info.has("action") && info["action"] == "resize")
+ {
+ const std::string& name = info["view_name"];
+
+ // expected only resize of nearby chatbar
+ if (mNearbyChatBar->getName() != name) return LLPanel::notifyParent(info);
+
+ const S32 new_width = info["new_width"];
+
+ processChatbarCustomization(new_width);
+
+ return 2;
+ }
+ return LLPanel::notifyParent(info);
+}
+
void LLBottomTray::showBottomTrayContextMenu(S32 x, S32 y, MASK mask)
{
// We should show BottomTrayContextMenu in last turn
@@ -363,22 +425,12 @@ void LLBottomTray::updateContextMenu(S32 x, S32 y, MASK mask)
bool in_edit_box = edit_box->pointInView(local_x, local_y);
- LLMenuItemGL* menu_item;
- menu_item = mBottomTrayContextMenu->findChild<LLMenuItemGL>("NearbyChatBar_Cut");
- if(menu_item)
- menu_item->setVisible(in_edit_box);
- menu_item = mBottomTrayContextMenu->findChild<LLMenuItemGL>("NearbyChatBar_Copy");
- if(menu_item)
- menu_item->setVisible(in_edit_box);
- menu_item = mBottomTrayContextMenu->findChild<LLMenuItemGL>("NearbyChatBar_Paste");
- if(menu_item)
- menu_item->setVisible(in_edit_box);
- menu_item = mBottomTrayContextMenu->findChild<LLMenuItemGL>("NearbyChatBar_Delete");
- if(menu_item)
- menu_item->setVisible(in_edit_box);
- menu_item = mBottomTrayContextMenu->findChild<LLMenuItemGL>("NearbyChatBar_Select_All");
- if(menu_item)
- menu_item->setVisible(in_edit_box);
+ mBottomTrayContextMenu->setItemVisible("Separator", in_edit_box);
+ mBottomTrayContextMenu->setItemVisible("NearbyChatBar_Cut", in_edit_box);
+ mBottomTrayContextMenu->setItemVisible("NearbyChatBar_Copy", in_edit_box);
+ mBottomTrayContextMenu->setItemVisible("NearbyChatBar_Paste", in_edit_box);
+ mBottomTrayContextMenu->setItemVisible("NearbyChatBar_Delete", in_edit_box);
+ mBottomTrayContextMenu->setItemVisible("NearbyChatBar_Select_All", in_edit_box);
}
void LLBottomTray::showGestureButton(BOOL visible)
@@ -401,6 +453,18 @@ void LLBottomTray::showSnapshotButton(BOOL visible)
setTrayButtonVisibleIfPossible(RS_BUTTON_SNAPSHOT, visible);
}
+void LLBottomTray::toggleMovementControls()
+{
+ if (mMovementButton)
+ mMovementButton->onCommit();
+}
+
+void LLBottomTray::toggleCameraControls()
+{
+ if (mCamButton)
+ mCamButton->onCommit();
+}
+
BOOL LLBottomTray::postBuild()
{
@@ -413,12 +477,8 @@ BOOL LLBottomTray::postBuild()
mNearbyChatBar = getChild<LLNearbyChatBar>("chat_bar");
mToolbarStack = getChild<LLLayoutStack>("toolbar_stack");
- mMovementPanel = getChild<LLPanel>("movement_panel");
- mMovementButton = mMovementPanel->getChild<LLButton>("movement_btn");
- mGesturePanel = getChild<LLPanel>("gesture_panel");
- mCamPanel = getChild<LLPanel>("cam_panel");
- mCamButton = mCamPanel->getChild<LLButton>("camera_btn");
- mSnapshotPanel = getChild<LLPanel>("snapshot_panel");
+ mMovementButton = getChild<LLButton>("movement_btn");
+ mCamButton = getChild<LLButton>("camera_btn");
setRightMouseDownCallback(boost::bind(&LLBottomTray::showBottomTrayContextMenu,this, _2, _3,_4));
mSpeakPanel = getChild<LLPanel>("speak_panel");
@@ -434,15 +494,24 @@ BOOL LLBottomTray::postBuild()
mSpeakBtn->setShowToolTip( getString("VoiceControlBtnToolTip") );
// Registering Chat Bar to receive Voice client status change notifications.
- gVoiceClient->addObserver(this);
-
- mObjectDefaultWidthMap[RS_BUTTON_GESTURES] = mGesturePanel->getRect().getWidth();
- mObjectDefaultWidthMap[RS_BUTTON_MOVEMENT] = mMovementPanel->getRect().getWidth();
- mObjectDefaultWidthMap[RS_BUTTON_CAMERA] = mCamPanel->getRect().getWidth();
- mObjectDefaultWidthMap[RS_BUTTON_SPEAK] = mSpeakPanel->getRect().getWidth();
+ LLVoiceClient::getInstance()->addObserver(this);
mNearbyChatBar->getChatBox()->setContextMenu(NULL);
+ mChicletPanel = getChild<LLChicletPanel>("chiclet_list");
+
+ initResizeStateContainers();
+
+ setButtonsControlsAndListeners();
+
+ initButtonsVisibility();
+
+ // update wells visibility:
+ showWellButton(RS_IM_WELL, !LLIMWellWindow::getInstance()->isWindowEmpty());
+ showWellButton(RS_NOTIFICATION_WELL, !LLNotificationWellWindow::getInstance()->isWindowEmpty());
+
+ LLViewerParcelMgr::getInstance()->addAgentParcelChangedCallback(boost::bind(&update_build_button_enable_state));
+
return TRUE;
}
@@ -604,6 +673,24 @@ void LLBottomTray::reshape(S32 width, S32 height, BOOL called_from_parent)
if (mNearbyChatBar) log(mNearbyChatBar, "after");
if (mChicletPanel) log(mChicletPanel, "after");
+
+
+ // Restore width of the chatbar on first reshape.
+ // we can not to do this from postBuild because reshape is called from parent view on startup
+ // creation after it and reset width according to resize logic.
+ static bool needs_restore_custom_state = true;
+ if (mNearbyChatBar && needs_restore_custom_state)
+ {
+ // restore custom width of chatbar panel.
+ S32 new_width = gSavedSettings.getS32("ChatBarCustomWidth");
+ if (new_width > 0)
+ {
+ processChatbarCustomization(new_width);
+ mNearbyChatBar->reshape(new_width, mNearbyChatBar->getRect().getHeight());
+ }
+ needs_restore_custom_state = false;
+ }
+
}
S32 LLBottomTray::processWidthDecreased(S32 delta_width)
@@ -639,7 +726,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
@@ -666,27 +753,9 @@ S32 LLBottomTray::processWidthDecreased(S32 delta_width)
S32 buttons_freed_width = 0;
if (still_should_be_processed)
{
- processShrinkButtons(&delta_width, &buttons_freed_width);
+ processShrinkButtons(delta_width, buttons_freed_width);
- if (delta_width < 0)
- {
- processHideButton(RS_BUTTON_SNAPSHOT, &delta_width, &buttons_freed_width);
- }
-
- if (delta_width < 0)
- {
- processHideButton(RS_BUTTON_CAMERA, &delta_width, &buttons_freed_width);
- }
-
- 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);
- }
+ processHideButtons(delta_width, buttons_freed_width);
if (delta_width < 0)
{
@@ -712,11 +781,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;
@@ -731,27 +800,10 @@ void LLBottomTray::processWidthIncreased(S32 delta_width)
<< llendl;
S32 available_width = total_available_width;
- if (available_width > 0)
- {
- processShowButton(RS_BUTTON_GESTURES, &available_width);
- }
- if (available_width > 0)
- {
- processShowButton(RS_BUTTON_MOVEMENT, &available_width);
- }
-
- if (available_width > 0)
- {
- processShowButton(RS_BUTTON_CAMERA, &available_width);
- }
-
- if (available_width > 0)
- {
- processShowButton(RS_BUTTON_SNAPSHOT, &available_width);
- }
+ processShowButtons(available_width);
- processExtendButtons(&available_width);
+ processExtendButtons(available_width);
// if we have to show/extend some buttons but resized delta width is not enough...
S32 processed_width = total_available_width - available_width;
@@ -808,9 +860,26 @@ void LLBottomTray::processWidthIncreased(S32 delta_width)
}
}
-bool LLBottomTray::processShowButton(EResizeState shown_object_type, S32* available_width)
+void LLBottomTray::processShowButtons(S32& available_width)
+{
+ // process buttons from left to right
+ resize_state_vec_t::const_iterator it = mButtonsProcessOrder.begin();
+ const resize_state_vec_t::const_iterator it_end = mButtonsProcessOrder.end();
+
+ for (; it != it_end; ++it)
+ {
+ // is there available space?
+ if (available_width <= 0) break;
+
+ // try to show next button
+ processShowButton(*it, available_width);
+ }
+}
+
+bool LLBottomTray::processShowButton(EResizeState shown_object_type, S32& available_width)
{
lldebugs << "Trying to show object type: " << shown_object_type << llendl;
+ llassert(mStateProcessedObjectMap[shown_object_type] != NULL);
LLPanel* panel = mStateProcessedObjectMap[shown_object_type];
if (NULL == panel)
@@ -823,15 +892,15 @@ bool LLBottomTray::processShowButton(EResizeState shown_object_type, S32* availa
{
//validate if we have enough room to show this button
const S32 required_width = panel->getRect().getWidth();
- can_be_shown = *available_width >= required_width;
+ can_be_shown = available_width >= required_width;
if (can_be_shown)
{
- *available_width -= required_width;
+ available_width -= required_width;
setTrayButtonVisible(shown_object_type, true);
lldebugs << "processed object type: " << shown_object_type
- << ", rest available width: " << *available_width
+ << ", rest available width: " << available_width
<< llendl;
mResizeState &= ~shown_object_type;
}
@@ -839,9 +908,26 @@ bool LLBottomTray::processShowButton(EResizeState shown_object_type, S32* availa
return can_be_shown;
}
-void LLBottomTray::processHideButton(EResizeState processed_object_type, S32* required_width, S32* buttons_freed_width)
+void LLBottomTray::processHideButtons(S32& required_width, S32& buttons_freed_width)
+{
+ // process buttons from right to left
+ resize_state_vec_t::const_reverse_iterator it = mButtonsProcessOrder.rbegin();
+ const resize_state_vec_t::const_reverse_iterator it_end = mButtonsProcessOrder.rend();
+
+ for (; it != it_end; ++it)
+ {
+ // is it still necessary to hide a button?
+ if (required_width >= 0) break;
+
+ // try to hide next button
+ processHideButton(*it, required_width, buttons_freed_width);
+ }
+}
+
+void LLBottomTray::processHideButton(EResizeState processed_object_type, S32& required_width, S32& buttons_freed_width)
{
lldebugs << "Trying to hide object type: " << processed_object_type << llendl;
+ llassert(mStateProcessedObjectMap[processed_object_type] != NULL);
LLPanel* panel = mStateProcessedObjectMap[processed_object_type];
if (NULL == panel)
@@ -852,11 +938,11 @@ void LLBottomTray::processHideButton(EResizeState processed_object_type, S32* re
if (panel->getVisible())
{
- *required_width += panel->getRect().getWidth();
+ required_width += panel->getRect().getWidth();
- if (*required_width > 0)
+ if (required_width > 0)
{
- *buttons_freed_width += *required_width;
+ buttons_freed_width += required_width;
}
setTrayButtonVisible(processed_object_type, false);
@@ -864,24 +950,29 @@ void LLBottomTray::processHideButton(EResizeState processed_object_type, S32* re
mResizeState |= processed_object_type;
lldebugs << "processing object type: " << processed_object_type
- << ", buttons_freed_width: " << *buttons_freed_width
+ << ", buttons_freed_width: " << buttons_freed_width
<< llendl;
}
}
-void LLBottomTray::processShrinkButtons(S32* required_width, S32* buttons_freed_width)
+void LLBottomTray::processShrinkButtons(S32& required_width, S32& buttons_freed_width)
{
- processShrinkButton(RS_BUTTON_CAMERA, required_width);
+ // process buttons from right to left
+ resize_state_vec_t::const_reverse_iterator it = mButtonsProcessOrder.rbegin();
+ const resize_state_vec_t::const_reverse_iterator it_end = mButtonsProcessOrder.rend();
- if (*required_width < 0)
- {
- processShrinkButton(RS_BUTTON_MOVEMENT, required_width);
- }
- if (*required_width < 0)
+ // iterate through buttons in the mButtonsProcessOrder first
+ for (; it != it_end; ++it)
{
- processShrinkButton(RS_BUTTON_GESTURES, required_width);
+ // is it still necessary to hide a button?
+ if (required_width >= 0) break;
+
+ // try to shrink next button
+ processShrinkButton(*it, required_width);
}
- if (*required_width < 0)
+
+ // then shrink Speak button
+ if (required_width < 0)
{
S32 panel_min_width = 0;
@@ -893,33 +984,33 @@ 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;
+ required_width += possible_shrink_width;
- if (*required_width > 0)
+ if (required_width > 0)
{
- *buttons_freed_width += *required_width;
+ buttons_freed_width += required_width;
}
- lldebugs << "Shrunk panel: " << panel_name
+ lldebugs << "Shrunk Speak button panel: " << panel_name
<< ", shrunk width: " << possible_shrink_width
- << ", rest width to process: " << *required_width
+ << ", rest width to process: " << required_width
<< llendl;
}
}
}
}
-void LLBottomTray::processShrinkButton(EResizeState processed_object_type, S32* required_width)
+void LLBottomTray::processShrinkButton(EResizeState processed_object_type, S32& required_width)
{
+ llassert(mStateProcessedObjectMap[processed_object_type] != NULL);
LLPanel* panel = mStateProcessedObjectMap[processed_object_type];
if (NULL == panel)
{
@@ -945,64 +1036,70 @@ void LLBottomTray::processShrinkButton(EResizeState processed_object_type, S32*
// let calculate real width to shrink
// 1. apply all possible width
- *required_width += possible_shrink_width;
+ required_width += possible_shrink_width;
// 2. it it is too much...
- if (*required_width > 0)
+ if (required_width > 0)
{
// reduce applied shrunk width to the excessive value.
- possible_shrink_width -= *required_width;
- *required_width = 0;
+ possible_shrink_width -= required_width;
+ required_width = 0;
}
panel->reshape(panel_width - possible_shrink_width, panel->getRect().getHeight());
lldebugs << "Shrunk panel: " << panel_name
<< ", shrunk width: " << possible_shrink_width
- << ", rest width to process: " << *required_width
+ << ", rest width to process: " << required_width
<< llendl;
}
}
}
-void LLBottomTray::processExtendButtons(S32* available_width)
+void LLBottomTray::processExtendButtons(S32& available_width)
{
- // do not allow extending any buttons if we have some buttons hidden
+ // do not allow extending any buttons if we have some buttons hidden via resize
if (mResizeState & RS_BUTTONS_CAN_BE_HIDDEN) return;
- processExtendButton(RS_BUTTON_GESTURES, available_width);
+ // process buttons from left to right
+ resize_state_vec_t::const_iterator it = mButtonsProcessOrder.begin();
+ const resize_state_vec_t::const_iterator it_end = mButtonsProcessOrder.end();
- if (*available_width > 0)
+ // iterate through buttons in the mButtonsProcessOrder first
+ for (; it != it_end; ++it)
{
- processExtendButton(RS_BUTTON_CAMERA, available_width);
- }
- if (*available_width > 0)
- {
- processExtendButton(RS_BUTTON_MOVEMENT, available_width);
+ // is there available space?
+ if (available_width <= 0) break;
+
+ // try to extend next button
+ processExtendButton(*it, available_width);
}
- if (*available_width > 0)
+
+ // then try to extend Speak button
+ 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());
log(mSpeakBtn, "speak button is extended");
- *available_width -= possible_extend_width;
+ available_width -= possible_extend_width;
- lldebugs << "Extending panel: " << mSpeakPanel->getName()
+ lldebugs << "Extending Speak button panel: " << mSpeakPanel->getName()
<< ", extended width: " << possible_extend_width
- << ", rest width to process: " << *available_width
+ << ", rest width to process: " << available_width
<< llendl;
}
}
}
-void LLBottomTray::processExtendButton(EResizeState processed_object_type, S32* available_width)
+void LLBottomTray::processExtendButton(EResizeState processed_object_type, S32& available_width)
{
+ llassert(mStateProcessedObjectMap[processed_object_type] != NULL);
LLPanel* panel = mStateProcessedObjectMap[processed_object_type];
if (NULL == panel)
{
@@ -1021,68 +1118,142 @@ void LLBottomTray::processExtendButton(EResizeState processed_object_type, S32*
// let calculate real width to extend
// 1. apply all possible width
- *available_width -= possible_extend_width;
+ available_width -= possible_extend_width;
// 2. it it is too much...
- if (*available_width < 0)
+ if (available_width < 0)
{
// reduce applied extended width to the excessive value.
- possible_extend_width += *available_width;
- *available_width = 0;
+ possible_extend_width += available_width;
+ available_width = 0;
}
panel->reshape(panel_width + possible_extend_width, panel->getRect().getHeight());
lldebugs << "Extending panel: " << panel->getName()
<< ", extended width: " << possible_extend_width
- << ", rest width to process: " << *available_width
+ << ", rest width to process: " << available_width
<< llendl;
}
}
bool LLBottomTray::canButtonBeShown(EResizeState processed_object_type) const
{
+ // 0. Check if passed button was previously hidden on resize
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;
+ // Yes, it was. Lets now check that all buttons before it (that can be hidden on resize)
+ // are already shown
+
+ // process buttons in direct order (from left to right)
+ resize_state_vec_t::const_iterator it = mButtonsProcessOrder.begin();
+ const resize_state_vec_t::const_iterator it_end = mButtonsProcessOrder.end();
- switch(processed_object_type)
+ // 1. Find and accumulate all buttons types before one passed into the method.
+ MASK buttons_before_mask = RS_NORESIZE;
+ for (; it != it_end; ++it)
{
- 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;
+ const EResizeState button_type = *it;
+ if (button_type == processed_object_type) break;
+
+ buttons_before_mask |= button_type;
}
+
+ // 2. Check if some previous buttons are still hidden on resize
+ can_be_shown = !(buttons_before_mask & mResizeState);
}
return can_be_shown;
}
-void LLBottomTray::initStateProcessedObjectMap()
+void LLBottomTray::initResizeStateContainers()
+{
+ // init map with objects should be processed for each type
+ mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_GESTURES, getChild<LLPanel>("gesture_panel")));
+ mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_MOVEMENT, getChild<LLPanel>("movement_panel")));
+ mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_CAMERA, getChild<LLPanel>("cam_panel")));
+ mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_SNAPSHOT, getChild<LLPanel>("snapshot_panel")));
+ mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_BUILD, getChild<LLPanel>("build_btn_panel")));
+ mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_SEARCH, getChild<LLPanel>("search_btn_panel")));
+ mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_WORLD_MAP, getChild<LLPanel>("world_map_btn_panel")));
+ mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_MINI_MAP, getChild<LLPanel>("mini_map_btn_panel")));
+
+ // init an order of processed buttons
+ mButtonsProcessOrder.push_back(RS_BUTTON_GESTURES);
+ mButtonsProcessOrder.push_back(RS_BUTTON_MOVEMENT);
+ mButtonsProcessOrder.push_back(RS_BUTTON_CAMERA);
+ mButtonsProcessOrder.push_back(RS_BUTTON_SNAPSHOT);
+ mButtonsProcessOrder.push_back(RS_BUTTON_BUILD);
+ mButtonsProcessOrder.push_back(RS_BUTTON_SEARCH);
+ mButtonsProcessOrder.push_back(RS_BUTTON_WORLD_MAP);
+ mButtonsProcessOrder.push_back(RS_BUTTON_MINI_MAP);
+
+ // init default widths
+
+ // process buttons that can be hidden on resize...
+ resize_state_vec_t::const_iterator it = mButtonsProcessOrder.begin();
+ const resize_state_vec_t::const_iterator it_end = mButtonsProcessOrder.end();
+
+ for (; it != it_end; ++it)
+ {
+ const EResizeState button_type = *it;
+ // is there an appropriate object?
+ llassert(mStateProcessedObjectMap.count(button_type) > 0);
+ if (0 == mStateProcessedObjectMap.count(button_type)) continue;
+
+ // set default width for it.
+ mObjectDefaultWidthMap[button_type] = mStateProcessedObjectMap[button_type]->getRect().getWidth();
+ }
+
+ // ... and add Speak button because it also can be shrunk.
+ mObjectDefaultWidthMap[RS_BUTTON_SPEAK] = mSpeakPanel->getRect().getWidth();
+
+}
+
+// this method must be called before restoring of the chat entry field on startup
+// because it resets chatbar's width according to resize logic.
+void LLBottomTray::initButtonsVisibility()
+{
+ setVisibleAndFitWidths(RS_BUTTON_GESTURES, gSavedSettings.getBOOL("ShowGestureButton"));
+ setVisibleAndFitWidths(RS_BUTTON_MOVEMENT, gSavedSettings.getBOOL("ShowMoveButton"));
+ setVisibleAndFitWidths(RS_BUTTON_CAMERA, gSavedSettings.getBOOL("ShowCameraButton"));
+ setVisibleAndFitWidths(RS_BUTTON_SNAPSHOT, gSavedSettings.getBOOL("ShowSnapshotButton"));
+ setVisibleAndFitWidths(RS_BUTTON_BUILD, gSavedSettings.getBOOL("ShowBuildButton"));
+ setVisibleAndFitWidths(RS_BUTTON_SEARCH, gSavedSettings.getBOOL("ShowSearchButton"));
+ setVisibleAndFitWidths(RS_BUTTON_WORLD_MAP, gSavedSettings.getBOOL("ShowWorldMapButton"));
+ setVisibleAndFitWidths(RS_BUTTON_MINI_MAP, gSavedSettings.getBOOL("ShowMiniMapButton"));
+}
+
+void LLBottomTray::setButtonsControlsAndListeners()
{
- 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));
-
- 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")));
+ gSavedSettings.getControl("ShowGestureButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_GESTURES, _2));
+ gSavedSettings.getControl("ShowMoveButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_MOVEMENT, _2));
+ gSavedSettings.getControl("ShowCameraButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_CAMERA, _2));
+ gSavedSettings.getControl("ShowSnapshotButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_SNAPSHOT, _2));
+ gSavedSettings.getControl("ShowBuildButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_BUILD, _2));
+ gSavedSettings.getControl("ShowSearchButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_SEARCH, _2));
+ gSavedSettings.getControl("ShowWorldMapButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_WORLD_MAP, _2));
+ gSavedSettings.getControl("ShowMiniMapButton")->getSignal()->connect(boost::bind(&LLBottomTray::toggleShowButton, RS_BUTTON_MINI_MAP, _2));
+
+
+ LLButton* build_btn = getChild<LLButton>("build_btn");
+ // set control name for Build button. It is not enough to link it with Button.SetFloaterToggle in xml
+ std::string vis_control_name = LLFloaterReg::declareVisibilityControl("build");
+ // Set the button control value (toggle state) to the floater visibility control (Sets the value as well)
+ build_btn->setControlVariable(LLUI::sSettingGroups["floater"]->getControl(vis_control_name));
+}
+
+bool LLBottomTray::toggleShowButton(LLBottomTray::EResizeState button_type, const LLSD& new_visibility)
+{
+ if (LLBottomTray::instanceExists())
+ {
+ LLBottomTray::getInstance()->setTrayButtonVisibleIfPossible(button_type, new_visibility.asBoolean());
+ }
+ return true;
}
void LLBottomTray::setTrayButtonVisible(EResizeState shown_object_type, bool visible)
{
+ llassert(mStateProcessedObjectMap[shown_object_type] != NULL);
LLPanel* panel = mStateProcessedObjectMap[shown_object_type];
if (NULL == panel)
{
@@ -1091,60 +1262,176 @@ void LLBottomTray::setTrayButtonVisible(EResizeState shown_object_type, bool vis
}
panel->setVisible(visible);
+}
- if (mDummiesMap.count(shown_object_type))
+void LLBottomTray::setTrayButtonVisibleIfPossible(EResizeState shown_object_type, bool visible, bool raise_notification)
+{
+ if (!setVisibleAndFitWidths(shown_object_type, visible) && visible && raise_notification)
{
- mDummiesMap[shown_object_type]->setVisible(visible);
+ LLNotificationsUtil::add("BottomTrayButtonCanNotBeShown",
+ LLSD(),
+ LLSD(),
+ LLNotificationFunctorRegistry::instance().DONOTHING);
}
}
-void LLBottomTray::setTrayButtonVisibleIfPossible(EResizeState shown_object_type, bool visible, bool raise_notification)
+bool LLBottomTray::setVisibleAndFitWidths(EResizeState object_type, bool visible)
{
- bool can_be_set = true;
+ LLPanel* cur_panel = mStateProcessedObjectMap[object_type];
+ if (NULL == cur_panel)
+ {
+ lldebugs << "There is no object to process for state: " << object_type << llendl;
+ return false;
+ }
+
+ bool is_set = true;
if (visible)
{
- LLPanel* panel = mStateProcessedObjectMap[shown_object_type];
- if (NULL == panel)
+ // Assume that only chiclet panel can be auto-resized
+ const S32 available_width =
+ mChicletPanel->getParent()->getRect().getWidth() - mChicletPanel->getMinWidth();
+
+ 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)
{
- lldebugs << "There is no object to process for state: " << shown_object_type << llendl;
- return;
+ 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 dummy_width = mDummiesMap.count(shown_object_type) ? mDummiesMap[shown_object_type]->getRect().getWidth() : 0;
+ S32 sum_of_min_widths = get_panel_min_width(mToolbarStack, mSpeakPanel);
+ S32 sum_of_curr_widths = get_curr_width(mSpeakPanel);
- const S32 chatbar_panel_width = mNearbyChatBar->getRect().getWidth();
- const S32 chatbar_panel_min_width = mNearbyChatBar->getMinWidth();
+ resize_state_vec_t::const_iterator it = mButtonsProcessOrder.begin();
+ const resize_state_vec_t::const_iterator it_end = mButtonsProcessOrder.end();
- const S32 chiclet_panel_width = mChicletPanel->getParent()->getRect().getWidth();
- const S32 chiclet_panel_min_width = mChicletPanel->getMinWidth();
+ for (; it != it_end; ++it)
+ {
+ LLPanel * cur_panel = mStateProcessedObjectMap[*it];
+ sum_of_min_widths += get_panel_min_width(mToolbarStack, cur_panel);
+ sum_of_curr_widths += get_curr_width(cur_panel);
+ }
- const S32 available_width = (chatbar_panel_width - chatbar_panel_min_width)
- + (chiclet_panel_width - chiclet_panel_min_width);
+ const S32 possible_shrunk_width =
+ chatbar_shrunk_width + (sum_of_curr_widths - sum_of_min_widths);
- const S32 required_width = panel->getRect().getWidth() + dummy_width;
- can_be_set = available_width >= required_width;
- }
+ // Minimal width of current panel
+ S32 minimal_width = 0;
+ mToolbarStack->getPanelMinSize(cur_panel->getName(), &minimal_width, NULL);
- if (can_be_set)
+ 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;
+ }
+ }
+
+ if (result_width != current_width)
+ {
+ cur_panel->reshape(result_width, cur_panel->getRect().getHeight());
+ current_width = result_width;
+ }
+
+ is_set = processShowButton(object_type, current_width);
+
+ // Shrink buttons if needed
+ if (is_set && decrease_width)
+ {
+ processWidthDecreased( -result_width);
+ }
+ }
+ else
{
- setTrayButtonVisible(shown_object_type, visible);
+ const S32 delta_width = get_curr_width(cur_panel);
+
+ setTrayButtonVisible(object_type, false);
- // if we hide the button mark it NOT to show while future bottom tray extending
- if (!visible)
+ // Mark button NOT to show while future bottom tray extending
+ mResizeState &= ~object_type;
+
+ // Extend other buttons if need
+ if (delta_width)
{
- mResizeState &= ~shown_object_type;
+ processWidthIncreased(delta_width);
}
}
+ return is_set;
+}
+
+void LLBottomTray::showWellButton(EResizeState object_type, bool visible)
+{
+ llassert( ((RS_NOTIFICATION_WELL | RS_IM_WELL) & object_type) == object_type );
+
+ const std::string panel_name = RS_IM_WELL == object_type ? "im_well_panel" : "notification_well_panel";
+
+ LLView * panel = getChild<LLView>(panel_name);
+
+ // if necessary visibility is set nothing to do here
+ if (panel->getVisible() == (BOOL)visible) return;
+
+ S32 panel_width = panel->getRect().getWidth();
+ panel->setVisible(visible);
+
+ if (visible)
+ {
+ // method assumes that input param is a negative value
+ processWidthDecreased(-panel_width);
+ }
else
{
- // mark this button to show it while future bottom tray extending
- mResizeState |= shown_object_type;
- if ( raise_notification )
- LLNotificationsUtil::add("BottomTrayButtonCanNotBeShown",
- LLSD(),
- LLSD(),
- LLNotificationFunctorRegistry::instance().DONOTHING);
+ processWidthIncreased(panel_width);
+ }
+}
+
+void LLBottomTray::processChatbarCustomization(S32 new_width)
+{
+ if (NULL == mNearbyChatBar) return;
+
+ const S32 delta_width = mNearbyChatBar->getRect().getWidth() - new_width;
+
+ if (delta_width == 0) return;
+
+ LLView * chiclet_layout_panel = mChicletPanel->getParent();
+ const S32 chiclet_min_width = get_panel_min_width(mToolbarStack, chiclet_layout_panel);
+ const S32 chiclet_panel_width = chiclet_layout_panel->getRect().getWidth();
+ const S32 available_chiclet_shrink_width = chiclet_panel_width - chiclet_min_width;
+ llassert(available_chiclet_shrink_width >= 0);
+
+ if (delta_width > 0) // panel gets narrowly
+ {
+ S32 total_possible_width = delta_width + available_chiclet_shrink_width;
+ processShowButtons(total_possible_width);
+ processExtendButtons(total_possible_width);
+ }
+ // here (delta_width < 0) // panel gets wider
+ else //if (-delta_width > available_chiclet_shrink_width)
+ {
+ S32 required_width = delta_width + available_chiclet_shrink_width;
+ S32 buttons_freed_width = 0;
+ processShrinkButtons(required_width, buttons_freed_width);
+ processHideButtons(required_width, buttons_freed_width);
}
}