From eb800ade7eb27038823e12f667901ea32c14160d Mon Sep 17 00:00:00 2001 From: Andrew Dyukov Date: Thu, 14 Jan 2010 17:42:21 +0200 Subject: At last! Implemented normal task EXT-3477 (Change gesture list implementation). Created a new widget consisting of button and scrollist. List is added to NonSideTrayView to properly draw it without using topcontrol (because it caused problems). This commit also fixes following bugs: EXT-3301 (Opening Gestures on Bottom Tray Disables Move Button) EXT-3190 (No bottom tray's context menu appears if right mouse click was perform over enabled Gesture button) EXT-2610 ('Gesture' btn: floater opens on OnMouseDown) --HG-- branch : product-engine --- indra/newview/llfloatergesture.cpp | 2 +- indra/newview/llgesturemgr.cpp | 10 + indra/newview/llgesturemgr.h | 2 + indra/newview/llnearbychatbar.cpp | 253 +++++++++++++++------ indra/newview/llnearbychatbar.h | 47 ++-- .../skins/default/xui/en/panel_bottomtray.xml | 6 +- .../default/xui/en/widgets/gesture_combo_box.xml | 30 --- .../default/xui/en/widgets/gesture_combo_list.xml | 21 ++ 8 files changed, 259 insertions(+), 112 deletions(-) delete mode 100644 indra/newview/skins/default/xui/en/widgets/gesture_combo_box.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/gesture_combo_list.xml (limited to 'indra') diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp index 5072bc8c82..6a9c602db2 100644 --- a/indra/newview/llfloatergesture.cpp +++ b/indra/newview/llfloatergesture.cpp @@ -415,7 +415,7 @@ void LLFloaterGesture::onClickPlay() LL_DEBUGS("Gesture")<<" Trying to play gesture id: "<< item_id <mPlaying; } +BOOL LLGestureManager::isGesturePlaying(LLMultiGesture* gesture) +{ + if(!gesture) + { + return FALSE; + } + + return gesture->mPlaying; +} + void LLGestureManager::replaceGesture(const LLUUID& item_id, LLMultiGesture* new_gesture, const LLUUID& asset_id) { const LLUUID& base_item_id = get_linked_uuid(item_id); diff --git a/indra/newview/llgesturemgr.h b/indra/newview/llgesturemgr.h index e80eea9ae9..c562587c6f 100644 --- a/indra/newview/llgesturemgr.h +++ b/indra/newview/llgesturemgr.h @@ -103,6 +103,8 @@ public: BOOL isGesturePlaying(const LLUUID& item_id); + BOOL isGesturePlaying(LLMultiGesture* gesture); + const item_map_t& getActiveGestures() const { return mActive; } // Force a gesture to be played, for example, if it is being // previewed. diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp index 75c2fb07d1..6cf8bcb417 100644 --- a/indra/newview/llnearbychatbar.cpp +++ b/indra/newview/llnearbychatbar.cpp @@ -48,13 +48,16 @@ #include "llcommandhandler.h" #include "llviewercontrol.h" #include "llnavigationbar.h" +#include "llwindow.h" +#include "llviewerwindow.h" +#include "llrootview.h" S32 LLNearbyChatBar::sLastSpecialChatChannel = 0; // legacy callback glue void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel); -static LLDefaultChildRegistry::Register r("gesture_combo_box"); +static LLDefaultChildRegistry::Register r("gesture_combo_list"); struct LLChatTypeTrigger { std::string name; @@ -66,13 +69,42 @@ static LLChatTypeTrigger sChatTypeTriggers[] = { { "/shout" , CHAT_TYPE_SHOUT} }; -LLGestureComboBox::LLGestureComboBox(const LLGestureComboBox::Params& p) - : LLComboBox(p) - , mGestureLabelTimer() +LLGestureComboList::Params::Params() +: combo_button("combo_button"), + combo_list("combo_list") +{ +} + +LLGestureComboList::LLGestureComboList(const LLGestureComboList::Params& p) +: LLUICtrl(p) , mLabel(p.label) , mViewAllItemIndex(0) { - setCommitCallback(boost::bind(&LLGestureComboBox::onCommitGesture, this)); + LLButton::Params button_params = p.combo_button; + button_params.follows.flags(FOLLOWS_LEFT|FOLLOWS_BOTTOM|FOLLOWS_RIGHT); + + mButton = LLUICtrlFactory::create(button_params); + mButton->reshape(getRect().getWidth(),getRect().getHeight()); + mButton->setCommitCallback(boost::bind(&LLGestureComboList::onButtonCommit, this)); + + addChild(mButton); + + LLScrollListCtrl::Params params = p.combo_list; + params.name("GestureComboList"); + params.commit_callback.function(boost::bind(&LLGestureComboList::onItemSelected, this, _2)); + params.visible(false); + params.commit_on_keyboard_movement(false); + + mList = LLUICtrlFactory::create(params); + + // *HACK: adding list as a child to NonSideTrayView to make it fully visible without + // making it top control (because it would cause problems). + gViewerWindow->getNonSideTrayView()->addChild(mList); + mList->setVisible(FALSE); + + //****************************Gesture Part********************************/ + + setCommitCallback(boost::bind(&LLGestureComboList::onCommitGesture, this)); // now register us as observer since we have a place to put the results LLGestureManager::instance().addObserver(this); @@ -80,26 +112,139 @@ LLGestureComboBox::LLGestureComboBox(const LLGestureComboBox::Params& p) // refresh list from current active gestures refreshGestures(); - // This forces using of halign from xml, since LLComboBox - // sets it to LLFontGL::LEFT, if text entry is disabled - mButton->setHAlign(p.drop_down_button.font_halign); + setFocusLostCallback(boost::bind(&LLGestureComboList::hideList, this)); +} + +BOOL LLGestureComboList::handleKey(KEY key, MASK mask, BOOL called_from_parent) +{ + BOOL handled = FALSE; + + if (key == KEY_ESCAPE && mask == MASK_NONE ) + { + hideList(); + handled = TRUE; + } + else + { + handled = mList->handleKey(key, mask, called_from_parent); + } - // Pressing Gesture button by SPACE/ENTER key should open gestures list - mButton->setCommitCallback(boost::bind(&LLComboBox::onButtonMouseDown, this)); + return handled; } -LLGestureComboBox::~LLGestureComboBox() +void LLGestureComboList::showList() { - LLGestureManager::instance().removeObserver(this); + LLRect rect = mList->getRect(); + LLRect screen; + mButton->localRectToScreen(getRect(), &screen); + + // Calculating amount of space between the navigation bar and gestures combo + LLNavigationBar* nb = LLNavigationBar::getInstance(); + + S32 x, nb_bottom; + nb->localPointToScreen(0, 0, &x, &nb_bottom); + + S32 max_height = nb_bottom - screen.mTop; + mList->calcColumnWidths(); + rect.setOriginAndSize(screen.mLeft, screen.mTop, llmax(mList->getMaxContentWidth(),mButton->getRect().getWidth()), max_height); + + mList->setRect(rect); + mList->fitContents( llmax(mList->getMaxContentWidth(),mButton->getRect().getWidth()), max_height); + + gFocusMgr.setKeyboardFocus(this); + + // Show the list and push the button down + mButton->setToggleState(TRUE); + mList->setVisible(TRUE); +} + +void LLGestureComboList::onButtonCommit() +{ + if (!mList->getVisible()) + { + // highlight the last selected item from the original selection before potentially selecting a new item + // as visual cue to original value of combo box + LLScrollListItem* last_selected_item = mList->getLastSelectedItem(); + if (last_selected_item) + { + mList->mouseOverHighlightNthItem(mList->getItemIndex(last_selected_item)); + } + + if (mList->getItemCount() != 0) + { + showList(); + } + } + else + { + hideList(); + } +} + +void LLGestureComboList::hideList() +{ + if (mList->getVisible()) + { + mButton->setToggleState(FALSE); + mList->setVisible(FALSE); + mList->mouseOverHighlightNthItem(-1); + gFocusMgr.setKeyboardFocus(NULL); + } +} + +S32 LLGestureComboList::getCurrentIndex() const +{ + LLScrollListItem* item = mList->getFirstSelected(); + if( item ) + { + return mList->getItemIndex( item ); + } + return -1; } -void LLGestureComboBox::refreshGestures() +void LLGestureComboList::onItemSelected(const LLSD& data) +{ + const std::string name = mList->getSelectedItemLabel(); + + S32 cur_id = getCurrentIndex(); + mLastSelectedIndex = cur_id; + if (cur_id != mList->getItemCount()-1 && cur_id != -1) + { + mButton->setLabel(name); + } + + // hiding the list reasserts the old value stored in the text editor/dropdown button + hideList(); + + // commit does the reverse, asserting the value in the list + onCommit(); +} + +void LLGestureComboList::sortByName(bool ascending) +{ + mList->sortOnce(0, ascending); +} + +LLSD LLGestureComboList::getValue() const +{ + LLScrollListItem* item = mList->getFirstSelected(); + if( item ) + { + return item->getValue(); + } + else + { + return LLSD(); + } +} + +void LLGestureComboList::refreshGestures() { //store current selection so we can maintain it LLSD cur_gesture = getValue(); - selectFirstItem(); - // clear - clearRows(); + + mList->selectFirstItem(); + mList->clearRows(); mGestures.clear(); LLGestureManager::item_map_t::const_iterator it; @@ -110,7 +255,7 @@ void LLGestureComboBox::refreshGestures() LLMultiGesture* gesture = (*it).second; if (gesture) { - addSimpleElement(gesture->mName, ADD_BOTTOM, LLSD(idx)); + mList->addSimpleElement(gesture->mName, ADD_BOTTOM, LLSD(idx)); mGestures.push_back(gesture); idx++; } @@ -120,23 +265,42 @@ void LLGestureComboBox::refreshGestures() // store index followed by the last added Gesture and add View All item at bottom mViewAllItemIndex = idx; - addSimpleElement(LLTrans::getString("ViewAllGestures"), ADD_BOTTOM, LLSD(mViewAllItemIndex)); + + mList->addSimpleElement(LLTrans::getString("ViewAllGestures"), ADD_BOTTOM, LLSD(mViewAllItemIndex)); // Insert label after sorting, at top, with separator below it - addSeparator(ADD_TOP); - addSimpleElement(mLabel, ADD_TOP); + mList->addSeparator(ADD_TOP); + mList->addSimpleElement(mLabel, ADD_TOP); if (cur_gesture.isDefined()) { - selectByValue(cur_gesture); + mList->selectByValue(cur_gesture); + } else { - selectFirstItem(); + mList->selectFirstItem(); + } + + LLCtrlListInterface* gestures = getListInterface(); + LLMultiGesture* gesture = NULL; + + if (gestures) + { + S32 index = gestures->getSelectedValue().asInteger(); + if(index > 0) + gesture = mGestures.at(index); } + + if(gesture && LLGestureManager::instance().isGesturePlaying(gesture)) + { + return; + } + + mButton->setLabel(mLabel); } -void LLGestureComboBox::onCommitGesture() +void LLGestureComboList::onCommitGesture() { LLCtrlListInterface* gestures = getListInterface(); if (gestures) @@ -167,50 +331,11 @@ void LLGestureComboBox::onCommitGesture() } } } - - mGestureLabelTimer.start(); - // free focus back to chat bar - setFocus(FALSE); } -//virtual -void LLGestureComboBox::draw() +LLGestureComboList::~LLGestureComboList() { - // HACK: Leave the name of the gesture in place for a few seconds. - const F32 SHOW_GESTURE_NAME_TIME = 2.f; - if (mGestureLabelTimer.getStarted() && mGestureLabelTimer.getElapsedTimeF32() > SHOW_GESTURE_NAME_TIME) - { - LLCtrlListInterface* gestures = getListInterface(); - if (gestures) gestures->selectFirstItem(); - mGestureLabelTimer.stop(); - } - - LLComboBox::draw(); -} - -//virtual -void LLGestureComboBox::showList() -{ - LLComboBox::showList(); - - // Calculating amount of space between the navigation bar and gestures combo - LLNavigationBar* nb = LLNavigationBar::getInstance(); - S32 x, nb_bottom; - nb->localPointToScreen(0, 0, &x, &nb_bottom); - - S32 list_bottom; - mList->localPointToScreen(0, 0, &x, &list_bottom); - - S32 max_height = nb_bottom - list_bottom; - - LLRect rect = mList->getRect(); - // List overlapped navigation bar, downsize it - if (rect.getHeight() > max_height) - { - rect.setOriginAndSize(rect.mLeft, rect.mBottom, rect.getWidth(), max_height); - mList->setRect(rect); - mList->reshape(rect.getWidth(), rect.getHeight()); - } + LLGestureManager::instance().removeObserver(this); } LLNearbyChatBar::LLNearbyChatBar() diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h index 224118e088..d9a7403611 100644 --- a/indra/newview/llnearbychatbar.h +++ b/indra/newview/llnearbychatbar.h @@ -42,33 +42,52 @@ #include "llspeakers.h" -class LLGestureComboBox - : public LLComboBox - , public LLGestureManagerObserver +class LLGestureComboList + : public LLGestureManagerObserver + , public LLUICtrl { public: - struct Params : public LLInitParam::Block { }; + struct Params : public LLInitParam::Block + { + Optional combo_button; + Optional combo_list; + + Params(); + }; + protected: - LLGestureComboBox(const Params&); + friend class LLUICtrlFactory; + LLGestureComboList(const Params&); + std::vector mGestures; + std::string mLabel; + LLSD::Integer mViewAllItemIndex; + public: - ~LLGestureComboBox(); + ~LLGestureComboList(); + + LLCtrlListInterface* getListInterface() { return (LLCtrlListInterface*)mList; }; + virtual void showList(); + virtual void hideList(); + virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); + + S32 getCurrentIndex() const; + void onItemSelected(const LLSD& data); + void sortByName(bool ascending = true); void refreshGestures(); void onCommitGesture(); - virtual void draw(); + void onButtonCommit(); + virtual LLSD getValue() const; // LLGestureManagerObserver trigger virtual void changed() { refreshGestures(); } -protected: - - virtual void showList(); +private: - LLFrameTimer mGestureLabelTimer; - std::vector mGestures; - std::string mLabel; - LLSD::Integer mViewAllItemIndex; + LLButton* mButton; + LLScrollListCtrl* mList; + S32 mLastSelectedIndex; }; class LLNearbyChatBar diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml index ca547a79e2..4b39210f30 100644 --- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml +++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml @@ -103,7 +103,7 @@ min_width="52" name="gesture_panel" user_resize="false"> - - - + - - - - - - diff --git a/indra/newview/skins/default/xui/en/widgets/gesture_combo_list.xml b/indra/newview/skins/default/xui/en/widgets/gesture_combo_list.xml new file mode 100644 index 0000000000..808683864d --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/gesture_combo_list.xml @@ -0,0 +1,21 @@ + + + + + -- cgit v1.2.3