diff options
Diffstat (limited to 'indra/llui/lltoolbar.cpp')
-rw-r--r-- | indra/llui/lltoolbar.cpp | 232 |
1 files changed, 207 insertions, 25 deletions
diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp index efa077ffa1..1f5fa5f361 100644 --- a/indra/llui/lltoolbar.cpp +++ b/indra/llui/lltoolbar.cpp @@ -103,11 +103,14 @@ LLToolBar::LLToolBar(const LLToolBar::Params& p) mPadTop(p.pad_top), mPadBottom(p.pad_bottom), mPadBetween(p.pad_between), - mPopupMenuHandle() + mPopupMenuHandle(), + mStartDragItemCallback(NULL), + mHandleDragItemCallback(NULL), + mHandleDropCallback(NULL), + mDragAndDropTarget(false) { mButtonParams[LLToolBarEnums::BTNTYPE_ICONS_WITH_TEXT] = p.button_icon_and_text; mButtonParams[LLToolBarEnums::BTNTYPE_ICONS_ONLY] = p.button_icon; - mUUID = LLUUID::generateNewID(p.name); } LLToolBar::~LLToolBar() @@ -174,6 +177,7 @@ void LLToolBar::initFromParams(const LLToolBar::Params& p) center_panel_p.rect = getLocalRect(); center_panel_p.auto_resize = false; center_panel_p.user_resize = false; + center_panel_p.mouse_opaque = false; LLLayoutPanel* center_panel = LLUICtrlFactory::create<LLLayoutPanel>(center_panel_p); mCenteringStack->addChild(center_panel); @@ -193,21 +197,71 @@ void LLToolBar::initFromParams(const LLToolBar::Params& p) mNeedsLayout = true; } -bool LLToolBar::addCommand(const LLCommandId& commandId) +bool LLToolBar::addCommand(const LLCommandId& commandId, int rank) { LLCommand * command = LLCommandManager::instance().getCommand(commandId); if (!command) return false; - mButtonCommands.push_back(commandId); + // Create the button and do the things that don't need ordering LLToolBarButton* button = createButton(commandId); - mButtons.push_back(button); mButtonPanel->addChild(button); mButtonMap.insert(std::make_pair(commandId, button)); + + // Insert the command and button in the right place in their respective lists + if ((rank >= mButtonCommands.size()) || (rank < 0)) + { + // In that case, back load + mButtonCommands.push_back(commandId); + mButtons.push_back(button); + } + else + { + // Insert in place: iterate to the right spot... + std::list<LLToolBarButton*>::iterator it_button = mButtons.begin(); + command_id_list_t::iterator it_command = mButtonCommands.begin(); + while (rank > 0) + { + ++it_button; + ++it_command; + rank--; + } + // ...then insert + mButtonCommands.insert(it_command,commandId); + mButtons.insert(it_button,button); + } + mNeedsLayout = true; return true; } +bool LLToolBar::removeCommand(const LLCommandId& commandId) +{ + if (!hasCommand(commandId)) return false; + + // First erase the map record + command_id_map::iterator it = mButtonMap.find(commandId); + mButtonMap.erase(it); + + // Now iterate on the commands and buttons to identify the relevant records + std::list<LLToolBarButton*>::iterator it_button = mButtons.begin(); + command_id_list_t::iterator it_command = mButtonCommands.begin(); + while (*it_command != commandId) + { + ++it_button; + ++it_command; + } + + // Delete the button and erase the command and button records + delete (*it_button); + mButtonCommands.erase(it_command); + mButtons.erase(it_button); + + mNeedsLayout = true; + + return true; +} + void LLToolBar::clearCommandsList() { // Clears the commands list @@ -328,6 +382,37 @@ void LLToolBar::resizeButtonsInRow(std::vector<LLToolBarButton*>& buttons_in_row } } +int LLToolBar::getRankFromPosition(S32 x, S32 y) +{ + int rank = 0; + + LLLayoutStack::ELayoutOrientation orientation = getOrientation(mSideType); + S32 button_panel_x = 0; + S32 button_panel_y = 0; + localPointToOtherView(x, y, &button_panel_x, &button_panel_y, mButtonPanel); + + //llinfos << "Merov debug : rank compute: orientation = " << orientation << ", x = " << button_panel_x << ", y = " << button_panel_y << llendl; + + // Simply compare the passed coord with the buttons outbound box + std::list<LLToolBarButton*>::iterator it_button = mButtons.begin(); + std::list<LLToolBarButton*>::iterator end_button = mButtons.end(); + while (it_button != end_button) + { + LLRect button_rect = (*it_button)->getRect(); + //llinfos << "Merov debug : rank compute: rect = " << button_rect.mLeft << ", " << button_rect.mTop << ", " << button_rect.mRight << ", " << button_rect.mBottom << llendl; + if (((orientation == LLLayoutStack::HORIZONTAL) && (button_rect.mRight > button_panel_x)) || + ((orientation == LLLayoutStack::VERTICAL) && (button_rect.mBottom < button_panel_y)) ) + { + break; + } + rank++; + ++it_button; + } + //llinfos << "Merov debug : rank = " << rank << llendl; + + return rank; +} + void LLToolBar::updateLayoutAsNeeded() { if (!mNeedsLayout) return; @@ -471,7 +556,39 @@ void LLToolBar::updateLayoutAsNeeded() void LLToolBar::draw() { - if (mButtons.empty()) return; + if (mButtons.empty()) + { + mButtonPanel->setVisible(FALSE); + mButtonPanel->setMouseOpaque(FALSE); + } + else + { + mButtonPanel->setVisible(TRUE); + mButtonPanel->setMouseOpaque(TRUE); + } + + // Update enable/disable state and highlight state for editable toolbars + if (!mReadOnly) + { + for (toolbar_button_list::iterator btn_it = mButtons.begin(); btn_it != mButtons.end(); ++btn_it) + { + LLToolBarButton* btn = *btn_it; + LLCommand* command = LLCommandManager::instance().getCommand(btn->mId); + + if (command && btn->mIsEnabledSignal) + { + const bool button_command_enabled = (*btn->mIsEnabledSignal)(btn, command->isEnabledParameters()); + btn->setEnabled(button_command_enabled); + } + + if (command && btn->mIsRunningSignal) + { + const bool button_command_running = (*btn->mIsRunningSignal)(btn, command->isRunningParameters()); + btn->setToggleState(button_command_running); + } + } + } + updateLayoutAsNeeded(); // rect may have shifted during layout LLUI::popMatrix(); @@ -494,6 +611,7 @@ void LLToolBar::createButtons() delete button; } mButtons.clear(); + mButtonMap.clear(); BOOST_FOREACH(LLCommandId& command_id, mButtonCommands) { @@ -503,7 +621,6 @@ void LLToolBar::createButtons() mButtonMap.insert(std::make_pair(command_id, button)); } mNeedsLayout = true; - } LLToolBarButton* LLToolBar::createButton(const LLCommandId& id) @@ -525,16 +642,51 @@ LLToolBarButton* LLToolBar::createButton(const LLCommandId& id) if (!mReadOnly) { LLUICtrl::CommitCallbackParam cbParam; - cbParam.function_name = commandp->functionName(); - cbParam.parameter = commandp->parameter(); + cbParam.function_name = commandp->executeFunctionName(); + cbParam.parameter = commandp->executeParameters(); + button->setCommitCallback(cbParam); - button->setStartDragCallback(mStartDragItemCallback); - button->setHandleDragCallback(mHandleDragItemCallback); + + const std::string& isEnabledFunction = commandp->isEnabledFunctionName(); + if (isEnabledFunction.length() > 0) + { + LLUICtrl::EnableCallbackParam isEnabledParam; + isEnabledParam.function_name = isEnabledFunction; + isEnabledParam.parameter = commandp->isEnabledParameters(); + enable_signal_t::slot_type isEnabledCB = initEnableCallback(isEnabledParam); + + if (NULL == button->mIsEnabledSignal) + { + button->mIsEnabledSignal = new enable_signal_t(); + } + + button->mIsEnabledSignal->connect(isEnabledCB); + } + + const std::string& isRunningFunction = commandp->isRunningFunctionName(); + if (isRunningFunction.length() > 0) + { + LLUICtrl::EnableCallbackParam isRunningParam; + isRunningParam.function_name = isRunningFunction; + isRunningParam.parameter = commandp->isRunningParameters(); + enable_signal_t::slot_type isRunningCB = initEnableCallback(isRunningParam); + + if (NULL == button->mIsRunningSignal) + { + button->mIsRunningSignal = new enable_signal_t(); + } + + button->mIsRunningSignal->connect(isRunningCB); + } } + // Drag and drop behavior must work also if provided in the Toybox and, potentially, any read-only toolbar + button->setStartDragCallback(mStartDragItemCallback); + button->setHandleDragCallback(mHandleDragItemCallback); + button->setCommandId(id); - return button; + return button; } BOOL LLToolBar::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, @@ -543,20 +695,20 @@ BOOL LLToolBar::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EAcceptance* accept, std::string& tooltip_msg) { - llinfos << "Merov debug : handleDragAndDrop. drop = " << drop << ", tooltip = " << tooltip_msg << llendl; + //llinfos << "Merov debug : handleDragAndDrop. drop = " << drop << ", x = " << x << ", y = " << y << llendl; // If we have a drop callback, that means that we can handle the drop BOOL handled = (mHandleDropCallback ? TRUE : FALSE); - // if drop, time to call the drop callback to get the operation done + // if drop is set, it's time to call the callback to get the operation done if (handled && drop) { - handled = mHandleDropCallback(cargo_type,cargo_data,mUUID); + handled = mHandleDropCallback(cargo_data, x, y ,this); } - // We accept multi drop by default - *accept = (handled ? ACCEPT_YES_MULTI : ACCEPT_NO); + // We accept only single tool drop on toolbars + *accept = (handled ? ACCEPT_YES_SINGLE : ACCEPT_NO); - // We'll use that flag to change the visual aspect of the target on draw() + // We'll use that flag to change the visual aspect of the toolbar target on draw() mDragAndDropTarget = handled; return handled; @@ -568,9 +720,23 @@ LLToolBarButton::LLToolBarButton(const Params& p) mMouseDownY(0), mWidthRange(p.button_width), mDesiredHeight(p.desired_height), - mId("") + mId(""), + mIsEnabledSignal(NULL), + mIsRunningSignal(NULL), + mIsStartingSignal(NULL), + mIsDragged(false), + mStartDragItemCallback(NULL), + mHandleDragItemCallback(NULL) +{ + mButtonFlashRate = 0.0; + mButtonFlashCount = 0; +} + +LLToolBarButton::~LLToolBarButton() { - mUUID = LLUUID::generateNewID(p.name); + delete mIsEnabledSignal; + delete mIsRunningSignal; + delete mIsStartingSignal; } BOOL LLToolBarButton::handleMouseDown(S32 x, S32 y, MASK mask) @@ -585,19 +751,23 @@ BOOL LLToolBarButton::handleHover(S32 x, S32 y, MASK mask) // llinfos << "Merov debug: handleHover, x = " << x << ", y = " << y << ", mouse = " << hasMouseCapture() << llendl; BOOL handled = FALSE; - if (hasMouseCapture() && mStartDragItemCallback && mHandleDragItemCallback) + S32 mouse_distance_squared = (x - mMouseDownX) * (x - mMouseDownX) + (y - mMouseDownY) * (y - mMouseDownY); + S32 drag_threshold = LLUI::sSettingGroups["config"]->getS32("DragAndDropDistanceThreshold"); + if (mouse_distance_squared > drag_threshold * drag_threshold + && hasMouseCapture() && + mStartDragItemCallback && mHandleDragItemCallback) { if (!mIsDragged) { - mStartDragItemCallback(x,y,mUUID); + mStartDragItemCallback(x,y,mId.uuid()); mIsDragged = true; handled = TRUE; } else - { - handled = mHandleDragItemCallback(x,y,mUUID,LLAssetType::AT_WIDGET); - } + { + handled = mHandleDragItemCallback(x,y,mId.uuid(),LLAssetType::AT_WIDGET); } + } else { handled = LLButton::handleHover(x, y, mask); @@ -605,3 +775,15 @@ BOOL LLToolBarButton::handleHover(S32 x, S32 y, MASK mask) return handled; } +void LLToolBarButton::onMouseEnter(S32 x, S32 y, MASK mask) +{ + LLUICtrl::onMouseEnter(x, y, mask); + + // Always highlight toolbar buttons, even if they are disabled + mNeedsHighlight = TRUE; +} + +void LLToolBarButton::onMouseCaptureLost() +{ + mIsDragged = false; +} |