diff options
Diffstat (limited to 'indra/newview/llnavigationbar.cpp')
-rw-r--r-- | indra/newview/llnavigationbar.cpp | 290 |
1 files changed, 205 insertions, 85 deletions
diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp index 71dc0f9011..18bba6e358 100644 --- a/indra/newview/llnavigationbar.cpp +++ b/indra/newview/llnavigationbar.cpp @@ -2,31 +2,25 @@ * @file llnavigationbar.cpp * @brief Navigation bar implementation * - * $LicenseInfo:firstyear=2009&license=viewergpl$ - * - * Copyright (c) 2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -34,6 +28,8 @@ #include "llnavigationbar.h" +#include "v2math.h" + #include "llregionhandle.h" #include "llfloaterreg.h" @@ -46,11 +42,11 @@ #include "lllandmarkactions.h" #include "lllocationhistory.h" #include "lllocationinputctrl.h" +#include "llpaneltopinfobar.h" #include "llteleporthistory.h" #include "llsearchcombobox.h" #include "llsidetray.h" #include "llslurl.h" -#include "llurlsimstring.h" #include "llurlregistry.h" #include "llurldispatcher.h" #include "llviewerinventory.h" @@ -181,6 +177,84 @@ void LLTeleportHistoryMenuItem::onMouseLeave(S32 x, S32 y, MASK mask) mArrowIcon->setVisible(FALSE); } +static LLDefaultChildRegistry::Register<LLPullButton> menu_button("pull_button"); + +LLPullButton::LLPullButton(const LLPullButton::Params& params) : + LLButton(params) +{ + setDirectionFromName(params.direction); +} +boost::signals2::connection LLPullButton::setClickDraggingCallback(const commit_signal_t::slot_type& cb) +{ + return mClickDraggingSignal.connect(cb); +} + +/*virtual*/ +void LLPullButton::onMouseLeave(S32 x, S32 y, MASK mask) +{ + LLButton::onMouseLeave(x, y, mask); + + if (mMouseDownTimer.getStarted()) //an user have done a mouse down, if the timer started. see LLButton::handleMouseDown for details + { + const LLVector2 cursor_direction = LLVector2(F32(x), F32(y)) - mLastMouseDown; + /* For now cursor_direction points to the direction of mouse movement + * Need to decide whether should we fire a signal. + * We fire if angle between mDraggingDirection and cursor_direction is less that 45 degree + * Note: + * 0.5 * F_PI_BY_TWO equals to PI/4 radian that equals to angle of 45 degrees + */ + if (angle_between(mDraggingDirection, cursor_direction) < 0.5 * F_PI_BY_TWO)//call if angle < pi/4 + { + mClickDraggingSignal(this, LLSD()); + } + } + +} + +/*virtual*/ +BOOL LLPullButton::handleMouseDown(S32 x, S32 y, MASK mask) +{ + BOOL handled = LLButton::handleMouseDown(x, y, mask); + if (handled) + { + //if mouse down was handled by button, + //capture mouse position to calculate the direction of mouse move after mouseLeave event + mLastMouseDown.set(F32(x), F32(y)); + } + return handled; +} + +/*virtual*/ +BOOL LLPullButton::handleMouseUp(S32 x, S32 y, MASK mask) +{ + // reset data to get ready for next circle + mLastMouseDown.clear(); + return LLButton::handleMouseUp(x, y, mask); +} +/** + * this function is setting up dragging direction vector. + * Last one is just unit vector. It points to direction of mouse drag that we need to handle + */ +void LLPullButton::setDirectionFromName(const std::string& name) +{ + if (name == "left") + { + mDraggingDirection.set(F32(-1), F32(0)); + } + else if (name == "right") + { + mDraggingDirection.set(F32(0), F32(1)); + } + else if (name == "down") + { + mDraggingDirection.set(F32(0), F32(-1)); + } + else if (name == "up") + { + mDraggingDirection.set(F32(0), F32(1)); + } +} + //-- LNavigationBar ---------------------------------------------------------- /* @@ -215,8 +289,8 @@ LLNavigationBar::~LLNavigationBar() BOOL LLNavigationBar::postBuild() { - mBtnBack = getChild<LLButton>("back_btn"); - mBtnForward = getChild<LLButton>("forward_btn"); + mBtnBack = getChild<LLPullButton>("back_btn"); + mBtnForward = getChild<LLPullButton>("forward_btn"); mBtnHome = getChild<LLButton>("home_btn"); mCmbLocation= getChild<LLLocationInputCtrl>("location_combo"); @@ -224,20 +298,15 @@ BOOL LLNavigationBar::postBuild() fillSearchComboBox(); - if (!mBtnBack || !mBtnForward || !mBtnHome || - !mCmbLocation || !mSearchComboBox) - { - llwarns << "Malformed navigation bar" << llendl; - return FALSE; - } - mBtnBack->setEnabled(FALSE); mBtnBack->setClickedCallback(boost::bind(&LLNavigationBar::onBackButtonClicked, this)); - mBtnBack->setHeldDownCallback(boost::bind(&LLNavigationBar::onBackOrForwardButtonHeldDown, this, _2)); - + mBtnBack->setHeldDownCallback(boost::bind(&LLNavigationBar::onBackOrForwardButtonHeldDown, this,_1, _2)); + mBtnBack->setClickDraggingCallback(boost::bind(&LLNavigationBar::showTeleportHistoryMenu, this,_1)); + mBtnForward->setEnabled(FALSE); mBtnForward->setClickedCallback(boost::bind(&LLNavigationBar::onForwardButtonClicked, this)); - mBtnForward->setHeldDownCallback(boost::bind(&LLNavigationBar::onBackOrForwardButtonHeldDown, this, _2)); + mBtnForward->setHeldDownCallback(boost::bind(&LLNavigationBar::onBackOrForwardButtonHeldDown, this, _1, _2)); + mBtnForward->setClickDraggingCallback(boost::bind(&LLNavigationBar::showTeleportHistoryMenu, this,_1)); mBtnHome->setClickedCallback(boost::bind(&LLNavigationBar::onHomeButtonClicked, this)); @@ -300,7 +369,6 @@ void LLNavigationBar::draw() if(mPurgeTPHistoryItems) { LLTeleportHistory::getInstance()->purgeItems(); - onTeleportHistoryChanged(); mPurgeTPHistoryItems = false; } @@ -332,10 +400,10 @@ void LLNavigationBar::onBackButtonClicked() LLTeleportHistory::getInstance()->goBack(); } -void LLNavigationBar::onBackOrForwardButtonHeldDown(const LLSD& param) +void LLNavigationBar::onBackOrForwardButtonHeldDown(LLUICtrl* ctrl, const LLSD& param) { if (param["count"].asInteger() == 0) - showTeleportHistoryMenu(); + showTeleportHistoryMenu(ctrl); } void LLNavigationBar::onForwardButtonClicked() @@ -374,8 +442,20 @@ void LLNavigationBar::onLocationSelection() // Will not teleport to empty location. if (typed_location.empty()) return; - + //get selected item from combobox item LLSD value = mCmbLocation->getSelectedValue(); + if(value.isUndefined() && !mCmbLocation->getTextEntry()->isDirty()) + { + // At this point we know that: there is no selected item in list and text field has NOT been changed + // So there is no sense to try to change the location + return; + } + /* since navbar list support autocompletion it contains several types of item: landmark, teleport hystory item, + * typed by user slurl or region name. Let's find out which type of item the user has selected + * to make decision about adding this location into typed history. see mSaveToLocationHistory + * Note: + * Only TYPED_REGION_SLURL item will be added into LLLocationHistory + */ if(value.has("item_type")) { @@ -405,7 +485,7 @@ void LLNavigationBar::onLocationSelection() case TELEPORT_HISTORY: //in case of teleport item was selected, teleport by position too. - case TYPED_REGION_SURL: + case TYPED_REGION_SLURL: if(value.has("global_pos")) { gAgent.teleportViaLocation(LLVector3d(value["global_pos"])); @@ -417,23 +497,38 @@ void LLNavigationBar::onLocationSelection() break; } } - //Let's parse surl or region name + //Let's parse slurl or region name std::string region_name; LLVector3 local_coords(128, 128, 0); - S32 x = 0, y = 0, z = 0; // Is the typed location a SLURL? - if (LLSLURL::isSLURL(typed_location)) + LLSLURL slurl = LLSLURL(typed_location); + if (slurl.getType() == LLSLURL::LOCATION) { - // Yes. Extract region name and local coordinates from it. - if (LLURLSimString::parse(LLSLURL::stripProtocol(typed_location), ®ion_name, &x, &y, &z)) - local_coords.set(x, y, z); - else - return; - }else + region_name = slurl.getRegion(); + local_coords = slurl.getPosition(); + } + else if(!slurl.isValid()) { - // assume that an user has typed the {region name} or possible {region_name, parcel} - region_name = typed_location.substr(0,typed_location.find(',')); + // we have to do this check after previous, because LLUrlRegistry contains handlers for slurl too + // but we need to know whether typed_location is a simple http url. + if (LLUrlRegistry::instance().isUrl(typed_location)) + { + // display http:// URLs in the media browser, or + // anything else is sent to the search floater + LLWeb::loadURL(typed_location); + return; + } + else + { + // assume that an user has typed the {region name} or possible {region_name, parcel} + region_name = typed_location.substr(0,typed_location.find(',')); + } + } + else + { + // was an app slurl, home, whatever. Bail + return; } // Resolve the region name to its global coordinates. @@ -456,7 +551,7 @@ void LLNavigationBar::onTeleportFinished(const LLVector3d& global_agent_pos) return; LLLocationHistory* lh = LLLocationHistory::getInstance(); - //TODO*: do we need convert surl into readable format? + //TODO*: do we need convert slurl into readable format? std::string location; /*NOTE: * We can't use gAgent.getPositionAgent() in case of local teleport to build location. @@ -465,10 +560,10 @@ void LLNavigationBar::onTeleportFinished(const LLVector3d& global_agent_pos) */ LLAgentUI::buildLocationString(location, LLAgentUI::LOCATION_FORMAT_NO_MATURITY, gAgent.getPosAgentFromGlobal(global_agent_pos)); - std::string tooltip (LLSLURL::buildSLURLfromPosGlobal(gAgent.getRegion()->getName(), global_agent_pos, false)); + std::string tooltip (LLSLURL(gAgent.getRegion()->getName(), global_agent_pos).getSLURLString()); LLLocationHistoryItem item (location, - global_agent_pos, tooltip,TYPED_REGION_SURL);// we can add into history only TYPED location + global_agent_pos, tooltip,TYPED_REGION_SLURL);// we can add into history only TYPED location //Touch it, if it is at list already, add new location otherwise if ( !lh->touchItem(item) ) { lh->addItem(item); @@ -546,20 +641,7 @@ void LLNavigationBar::onRegionNameResponse( // Invalid location? if (!region_handle) { - // handle any secondlife:// SLapps, or - // display http:// URLs in the media browser, or - // anything else is sent to the search floater - if (LLUrlRegistry::instance().isUrl(typed_location)) - { - if (! LLURLDispatcher::dispatchFromTextEditor(typed_location)) - { - LLWeb::loadURL(typed_location); - } - } - else - { - invokeSearch(typed_location); - } + invokeSearch(typed_location); return; } @@ -567,11 +649,11 @@ void LLNavigationBar::onRegionNameResponse( LLVector3d region_pos = from_region_handle(region_handle); LLVector3d global_pos = region_pos + (LLVector3d) local_coords; - llinfos << "Teleporting to: " << LLSLURL::buildSLURLfromPosGlobal(region_name, global_pos, false) << llendl; + llinfos << "Teleporting to: " << LLSLURL(region_name, global_pos).getSLURLString() << llendl; gAgent.teleportViaLocation(global_pos); } -void LLNavigationBar::showTeleportHistoryMenu() +void LLNavigationBar::showTeleportHistoryMenu(LLUICtrl* btn_ctrl) { // Don't show the popup if teleport history is empty. if (LLTeleportHistory::getInstance()->isEmpty()) @@ -585,18 +667,49 @@ void LLNavigationBar::showTeleportHistoryMenu() if (mTeleportHistoryMenu == NULL) return; - // *TODO: why to draw/update anything before showing the menu? - mTeleportHistoryMenu->buildDrawLabels(); mTeleportHistoryMenu->updateParent(LLMenuGL::sMenuContainer); const S32 MENU_SPAWN_PAD = -1; - LLMenuGL::showPopup(mBtnBack, mTeleportHistoryMenu, 0, MENU_SPAWN_PAD); - + LLMenuGL::showPopup(btn_ctrl, mTeleportHistoryMenu, 0, MENU_SPAWN_PAD); + LLButton* nav_button = dynamic_cast<LLButton*>(btn_ctrl); + if(nav_button) + { + if(mHistoryMenuConnection.connected()) + { + LL_WARNS("Navgationbar")<<"mHistoryMenuConnection should be disconnected at this moment."<<LL_ENDL; + mHistoryMenuConnection.disconnect(); + } + mHistoryMenuConnection = gMenuHolder->setMouseUpCallback(boost::bind(&LLNavigationBar::onNavigationButtonHeldUp, this, nav_button)); + // pressed state will be update after mouseUp in onBackOrForwardButtonHeldUp(); + nav_button->setForcePressedState(true); + } // *HACK pass the mouse capturing to the drop-down menu - gFocusMgr.setMouseCapture( NULL ); + // it need to let menu handle mouseup event + gFocusMgr.setMouseCapture(gMenuHolder); +} +/** + * Taking into account the HACK above, this callback-function is responsible for correct handling of mouseUp event in case of holding-down the navigation buttons.. + * We need to process this case separately to update a pressed state of navigation button. + */ +void LLNavigationBar::onNavigationButtonHeldUp(LLButton* nav_button) +{ + if(nav_button) + { + nav_button->setForcePressedState(false); + } + if(gFocusMgr.getMouseCapture() == gMenuHolder) + { + // we had passed mouseCapture in showTeleportHistoryMenu() + // now we MUST release mouseCapture to continue a proper mouseevent workflow. + gFocusMgr.setMouseCapture(NULL); + } + //gMenuHolder is using to display bunch of menus. Disconnect signal to avoid unnecessary calls. + mHistoryMenuConnection.disconnect(); } void LLNavigationBar::handleLoginComplete() { + LLTeleportHistory::getInstance()->handleLoginComplete(); + LLPanelTopInfoBar::instance().handleLoginComplete(); mCmbLocation->handleLoginComplete(); } @@ -657,7 +770,7 @@ void LLNavigationBar::showNavigationPanel(BOOL visible) { // Navigation Panel must be shown. Favorites Panel is hidden. - S32 height = mDefaultNbRect.getHeight() - mDefaultFpRect.getHeight(); + S32 height = mDefaultNbRect.getHeight() - mDefaultFpRect.getHeight() - FAVBAR_TOP_PADDING; nbRect.setLeftTopAndSize(nbRect.mLeft, nbRect.mTop, nbRect.getWidth(), height); reshape(nbRect.getWidth(), nbRect.getHeight()); @@ -671,8 +784,11 @@ void LLNavigationBar::showNavigationPanel(BOOL visible) { // Navigation Panel must be hidden. Favorites Panel is visible. - nbRect.setLeftTopAndSize(nbRect.mLeft, nbRect.mTop, nbRect.getWidth(), fbRect.getHeight()); - fbRect.setLeftTopAndSize(fbRect.mLeft, fbRect.getHeight(), fbRect.getWidth(), fbRect.getHeight()); + S32 fpHeight = mDefaultFpRect.getHeight() + FAVBAR_TOP_PADDING; + S32 fpTop = fpHeight - (mDefaultFpRect.getHeight() / 2) + 1; + + nbRect.setLeftTopAndSize(nbRect.mLeft, nbRect.mTop, nbRect.getWidth(), fpHeight); + fbRect.setLeftTopAndSize(fbRect.mLeft, fpTop, fbRect.getWidth(), mDefaultFpRect.getHeight()); // this is duplicated in 'else' section because it should be called BEFORE fb->reshape reshape(nbRect.getWidth(), nbRect.getHeight()); @@ -694,8 +810,9 @@ void LLNavigationBar::showNavigationPanel(BOOL visible) } } - childSetVisible("bg_icon", fpVisible); - childSetVisible("bg_icon_no_fav", !fpVisible); + getChildView("bg_icon")->setVisible( visible && fpVisible); + getChildView("bg_icon_no_fav_bevel")->setVisible( visible && !fpVisible); + getChildView("bg_icon_no_nav_bevel")->setVisible( !visible && fpVisible); } void LLNavigationBar::showFavoritesPanel(BOOL visible) @@ -714,7 +831,7 @@ void LLNavigationBar::showFavoritesPanel(BOOL visible) // Favorites Panel must be shown. Navigation Panel is visible. S32 fbHeight = fbRect.getHeight(); - S32 newHeight = nbRect.getHeight() + fbHeight; + S32 newHeight = nbRect.getHeight() + fbHeight + FAVBAR_TOP_PADDING; nbRect.setLeftTopAndSize(nbRect.mLeft, nbRect.mTop, nbRect.getWidth(), newHeight); fbRect.setLeftTopAndSize(mDefaultFpRect.mLeft, mDefaultFpRect.mTop, fbRect.getWidth(), fbRect.getHeight()); @@ -723,9 +840,11 @@ void LLNavigationBar::showFavoritesPanel(BOOL visible) { // Favorites Panel must be shown. Navigation Panel is hidden. - S32 fpHeight = mDefaultFpRect.getHeight(); + S32 fpHeight = mDefaultFpRect.getHeight() + FAVBAR_TOP_PADDING; + S32 fpTop = fpHeight - (mDefaultFpRect.getHeight() / 2) + 1; + nbRect.setLeftTopAndSize(nbRect.mLeft, nbRect.mTop, nbRect.getWidth(), fpHeight); - fbRect.setLeftTopAndSize(fbRect.mLeft, fpHeight, fbRect.getWidth(), fpHeight); + fbRect.setLeftTopAndSize(fbRect.mLeft, fpTop, fbRect.getWidth(), mDefaultFpRect.getHeight()); } reshape(nbRect.getWidth(), nbRect.getHeight()); @@ -742,7 +861,7 @@ void LLNavigationBar::showFavoritesPanel(BOOL visible) // Favorites Panel must be hidden. Navigation Panel is visible. S32 fbHeight = fbRect.getHeight(); - S32 newHeight = nbRect.getHeight() - fbHeight; + S32 newHeight = nbRect.getHeight() - fbHeight - FAVBAR_TOP_PADDING; nbRect.setLeftTopAndSize(nbRect.mLeft, nbRect.mTop, nbRect.getWidth(), newHeight); } @@ -758,8 +877,9 @@ void LLNavigationBar::showFavoritesPanel(BOOL visible) getParent()->reshape(nbRect.getWidth(), nbRect.getHeight()); } - childSetVisible("bg_icon", visible); - childSetVisible("bg_icon_no_fav", !visible); + getChildView("bg_icon")->setVisible( npVisible && visible); + getChildView("bg_icon_no_fav_bevel")->setVisible( npVisible && !visible); + getChildView("bg_icon_no_nav_bevel")->setVisible( !npVisible && visible); fb->setVisible(visible); } |