diff options
Diffstat (limited to 'indra/newview/llnavigationbar.cpp')
-rw-r--r-- | indra/newview/llnavigationbar.cpp | 434 |
1 files changed, 222 insertions, 212 deletions
diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp index 4a9dadfc7a..cf1d9a5d86 100644 --- a/indra/newview/llnavigationbar.cpp +++ b/indra/newview/llnavigationbar.cpp @@ -34,31 +34,127 @@ #include "llnavigationbar.h" -#include "llfocusmgr.h" -#include "llmenugl.h" -#include "llparcel.h" -#include "llregistry.h" -#include "llwindow.h" +#include <llfloaterreg.h> +#include <llfocusmgr.h> +#include <lliconctrl.h> +#include <llmenugl.h> +#include <llwindow.h> #include "llagent.h" #include "llfloaterhtmlhelp.h" -#include "llfloaterreg.h" #include "lllocationhistory.h" #include "lllocationinputctrl.h" #include "llteleporthistory.h" #include "llslurl.h" #include "llurlsimstring.h" +#include "llviewerinventory.h" +#include "llviewermenu.h" #include "llviewerparcelmgr.h" -#include "llviewerregion.h" #include "llworldmap.h" +//-- LLTeleportHistoryMenuItem ----------------------------------------------- + +/** + * Item look varies depending on the type (backward/current/forward). + */ +class LLTeleportHistoryMenuItem : public LLMenuItemCallGL +{ +public: + typedef enum e_item_type + { + TYPE_BACKWARD, + TYPE_CURRENT, + TYPE_FORWARD, + } EType; + + struct Params : public LLInitParam::Block<Params, LLMenuItemCallGL::Params> + { + Mandatory<EType> item_type; + + Params() {} + Params(EType type, std::string title); + }; + + /*virtual*/ void draw(); + /*virtual*/ void onMouseEnter(S32 x, S32 y, MASK mask); + /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask); + +private: + LLTeleportHistoryMenuItem(const Params&); + friend class LLUICtrlFactory; + + static const S32 ICON_WIDTH = 16; + static const S32 ICON_HEIGHT = 16; + static const std::string ICON_IMG_BACKWARD; + static const std::string ICON_IMG_FORWARD; + + LLIconCtrl* mArrowIcon; +}; + +const std::string LLTeleportHistoryMenuItem::ICON_IMG_BACKWARD("teleport_history_backward.tga"); +const std::string LLTeleportHistoryMenuItem::ICON_IMG_FORWARD("teleport_history_forward.tga"); + +LLTeleportHistoryMenuItem::Params::Params(EType type, std::string title) +{ + item_type(type); + font.name("SansSerif"); + + if (type == TYPE_CURRENT) + font.style("BOLD"); + else + title = " " + title; + + name(title); + label(title); +} + +LLTeleportHistoryMenuItem::LLTeleportHistoryMenuItem(const Params& p) +: LLMenuItemCallGL(p), + mArrowIcon(NULL) +{ + LLIconCtrl::Params icon_params; + icon_params.name("icon"); + icon_params.rect(LLRect(0, ICON_HEIGHT, ICON_WIDTH, 0)); + icon_params.mouse_opaque(false); + icon_params.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP); + icon_params.tab_stop(false); + icon_params.visible(false); + + mArrowIcon = LLUICtrlFactory::create<LLIconCtrl> (icon_params); + + // no image for the current item + if (p.item_type == TYPE_BACKWARD) + mArrowIcon->setValue(ICON_IMG_BACKWARD); + else if (p.item_type == TYPE_FORWARD) + mArrowIcon->setValue(ICON_IMG_FORWARD); + + addChild(mArrowIcon); +} + +void LLTeleportHistoryMenuItem::draw() +{ + // Draw menu item itself. + LLMenuItemCallGL::draw(); + + // Draw children if any. *TODO: move this to LLMenuItemGL? + LLUICtrl::draw(); +} + +void LLTeleportHistoryMenuItem::onMouseEnter(S32 x, S32 y, MASK mask) +{ + mArrowIcon->setVisible(TRUE); +} + +void LLTeleportHistoryMenuItem::onMouseLeave(S32 x, S32 y, MASK mask) +{ + mArrowIcon->setVisible(FALSE); +} + +//-- LNavigationBar ---------------------------------------------------------- /* TODO: - Load navbar height from saved settings (as it's done for status bar) or think of a better way. -- Share location info formatting code with LLStatusBar. -- Fix notifications appearing below navbar. -- Navbar should not be visible in mouselook mode. */ S32 NAVIGATION_BAR_HEIGHT = 60; // *HACK @@ -78,18 +174,20 @@ LLNavigationBar::LLNavigationBar() mBtnBack(NULL), mBtnForward(NULL), mBtnHome(NULL), - mBtnInfo(NULL), mBtnHelp(NULL), mCmbLocation(NULL), mLeSearch(NULL) { setIsChrome(TRUE); - + + // Register callbacks and load the location field context menu (NB: the order matters). + mCommitCallbackRegistrar.add("Navbar.Action", boost::bind(&LLNavigationBar::onLocationContextMenuItemClicked, this, _2)); + mEnableCallbackRegistrar.add("Navbar.EnableMenuItem", boost::bind(&LLNavigationBar::onLocationContextMenuItemEnabled, this, _2)); + LLUICtrlFactory::getInstance()->buildPanel(this, "panel_navigation_bar.xml"); // navigation bar can never get a tab setFocusRoot(FALSE); - } LLNavigationBar::~LLNavigationBar() @@ -102,14 +200,15 @@ BOOL LLNavigationBar::postBuild() mBtnBack = getChild<LLButton>("back_btn"); mBtnForward = getChild<LLButton>("forward_btn"); mBtnHome = getChild<LLButton>("home_btn"); - mBtnInfo = getChild<LLButton>("info_btn"); mBtnHelp = getChild<LLButton>("help_btn"); mCmbLocation= getChild<LLLocationInputCtrl>("location_combo"); mLeSearch = getChild<LLLineEditor>("search_input"); - if (!mBtnBack || !mBtnForward || !mBtnHome || !mBtnInfo || !mBtnHelp || - !mCmbLocation || !mLeSearch) + LLButton* search_btn = getChild<LLButton>("search_btn"); + + if (!mBtnBack || !mBtnForward || !mBtnHome || !mBtnHelp || + !mCmbLocation || !mLeSearch || !search_btn) { llwarns << "Malformed navigation bar" << llendl; return FALSE; @@ -124,23 +223,15 @@ BOOL LLNavigationBar::postBuild() mBtnForward->setHeldDownCallback(boost::bind(&LLNavigationBar::onBackOrForwardButtonHeldDown, this, _2)); mBtnHome->setClickedCallback(boost::bind(&LLNavigationBar::onHomeButtonClicked, this)); - mBtnInfo->setClickedCallback(boost::bind(&LLNavigationBar::onInfoButtonClicked, this)); mBtnHelp->setClickedCallback(boost::bind(&LLNavigationBar::onHelpButtonClicked, this)); - mCmbLocation->setFocusReceivedCallback(boost::bind(&LLNavigationBar::onLocationFocusReceived, this)); - mCmbLocation->setFocusLostCallback(boost::bind(&LLNavigationBar::onLocationFocusLost, this)); - mCmbLocation->setTextEntryCallback(boost::bind(&LLNavigationBar::onLocationTextEntry, this, _1)); - mCmbLocation->setPrearrangeCallback(boost::bind(&LLNavigationBar::onLocationPrearrange, this, _2)); mCmbLocation->setSelectionCallback(boost::bind(&LLNavigationBar::onLocationSelection, this)); mLeSearch->setCommitCallback(boost::bind(&LLNavigationBar::onSearchCommit, this)); + search_btn->setClickedCallback(boost::bind(&LLNavigationBar::onSearchCommit, this)); - // Register callbacks and load the location field context menu (NB: the order matters). - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar commit_registrar; - LLMenuItemGL::EnableCallbackRegistry::ScopedRegistrar enable_registrar; - commit_registrar.add("Navbar.Action", boost::bind(&LLNavigationBar::onLocationContextMenuItemClicked, this, _2)); - enable_registrar.add("Navbar.EnableMenuItem", boost::bind(&LLNavigationBar::onLocationContextMenuItemEnabled, this, _2)); - mLocationContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_navbar.xml", this); + // Load the location field context menu + mLocationContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_navbar.xml", gMenuHolder); if (!mLocationContextMenu) { llwarns << "Error loading navigation bar context menu" << llendl; @@ -150,49 +241,34 @@ BOOL LLNavigationBar::postBuild() // we'll be notified on teleport history changes LLTeleportHistory::getInstance()->setHistoryChangedCallback( boost::bind(&LLNavigationBar::onTeleportHistoryChanged, this)); - - LLLocationHistory::getInstance()->setLoadedCallback( - boost::bind(&LLNavigationBar::onLocationHistoryLoaded, this)); - - LLLocationHistory::getInstance()->load(); // *TODO: temporary, remove this after debugging - LLTeleportHistory::getInstance()->load(); // *TODO: temporary, remove this after debugging - + return TRUE; } void LLNavigationBar::draw() { - // *TODO: It doesn't look very optimal to refresh location every frame. - refreshLocation(); LLPanel::draw(); } BOOL LLNavigationBar::handleRightMouseDown(S32 x, S32 y, MASK mask) { + // *HACK. We should use mCmbLocation's right click callback instead. + // If the location field is clicked then show its context menu. if (mCmbLocation->getRect().pointInRect(x, y)) { - - // Pass the focus to the line editor when it is righ-clicked + // Pass the focus to the line editor when it is right-clicked mCmbLocation->setFocus(TRUE); - // IAN BUG why do the individual items need to be enabled individually here? - // where are they disabled? - if (mLocationContextMenu) { - mLocationContextMenu->setItemEnabled("Cut", mCmbLocation->canCut()); - mLocationContextMenu->setItemEnabled("Copy", mCmbLocation->canCopy()); - mLocationContextMenu->setItemEnabled("Paste", mCmbLocation->canPaste()); - mLocationContextMenu->setItemEnabled("Delete", mCmbLocation->canDeselect()); - mLocationContextMenu->setItemEnabled("Select All", mCmbLocation->canSelectAll()); - mLocationContextMenu->buildDrawLabels(); mLocationContextMenu->updateParent(LLMenuGL::sMenuContainer); LLMenuGL::showPopup(this, mLocationContextMenu, x, y); } + return TRUE; } - return TRUE; + return LLPanel:: handleRightMouseDown(x, y, mask); } void LLNavigationBar::onBackButtonClicked() @@ -216,13 +292,6 @@ void LLNavigationBar::onHomeButtonClicked() gAgent.teleportHome(); } -void LLNavigationBar::onInfoButtonClicked() -{ - // XXX temporary - LLTeleportHistory::getInstance()->dump(); - LLLocationHistory::getInstance()->dump(); -} - void LLNavigationBar::onHelpButtonClicked() { gViewerHtmlHelp.show(); @@ -230,17 +299,7 @@ void LLNavigationBar::onHelpButtonClicked() void LLNavigationBar::onSearchCommit() { - std::string search_text = mLeSearch->getText(); - LLFloaterReg::showInstance("search", LLSD().insert("panel", "all").insert("id", LLSD(search_text))); -} - -void LLNavigationBar::onLocationFocusReceived() -{ - mCmbLocation->setTextEntry(gAgent.getSLURL()); -} - -void LLNavigationBar::onLocationFocusLost() -{ + invokeSearch(mLeSearch->getText()); } void LLNavigationBar::onTeleportHistoryMenuItemClicked(const LLSD& userdata) @@ -253,51 +312,37 @@ void LLNavigationBar::onTeleportHistoryMenuItemClicked(const LLSD& userdata) // or selects a location from the typed locations dropdown. void LLNavigationBar::onLocationSelection() { - std::string loc_str = mCmbLocation->getSimple(); + std::string typed_location = mCmbLocation->getSimple(); // Will not teleport to empty location. - if (loc_str.empty()) + if (typed_location.empty()) return; - - // *TODO: validate location before adding it to the history. - S32 selected_item = mCmbLocation->getCurrentIndex(); - if (selected_item == -1) // user has typed text + + std::string region_name; + LLVector3 local_coords(128, 128, 0); + + // Is the typed location a SLURL? + if (LLSLURL::isSLURL(typed_location)) { - LLLocationHistory* lh = LLLocationHistory::getInstance(); - mCmbLocation->add(loc_str); - lh->addItem(loc_str); - lh->save(); + // Yes. Extract region name and local coordinates from it. + S32 x = 0, y = 0, z = 0; + if (LLURLSimString::parse(LLSLURL::stripProtocol(typed_location), ®ion_name, &x, &y, &z)) + local_coords.set(x, y, z); + else + return; } - - // If the input is not a SLURL treat it as a region name. - if (!LLSLURL::isSLURL(loc_str)) + else { - loc_str = LLSLURL::buildSLURL(loc_str, 128, 128, 0); + // Treat it as region name. + region_name = typed_location; } - - teleport(loc_str); -} -void LLNavigationBar::onLocationTextEntry(LLUICtrl* ctrl) -{ - LLLineEditor* editor = dynamic_cast<LLLineEditor*>(ctrl); - if (!editor) - return; - - // *TODO: decide whether to populate the list here on in LLLocationInputCtrl. - std::string text = editor->getText(); - //rebuildLocationHistory(text); -} - -void LLNavigationBar::onLocationPrearrange(const LLSD& data) -{ - std::string filter = data.asString(); - rebuildLocationHistory(filter); -} - -void LLNavigationBar::onLocationHistoryLoaded() -{ - rebuildLocationHistory(); + // Resolve the region name to its global coordinates. + // If resolution succeeds we'll teleport. + LLWorldMap::url_callback_t cb = boost::bind( + &LLNavigationBar::onRegionNameResponse, this, + typed_location, region_name, local_coords, _1, _2, _3, _4); + LLWorldMap::getInstance()->sendNamedRegionRequest(region_name, cb, std::string("unused"), false); } void LLNavigationBar::onTeleportHistoryChanged() @@ -309,57 +354,13 @@ void LLNavigationBar::onTeleportHistoryChanged() mBtnForward->setEnabled(cur_item < ((int)h->getItems().size() - 1)); } -void LLNavigationBar::refreshLocation() -{ - // Update location field. - if (mCmbLocation && !mCmbLocation->childHasFocus()) - { - std::string location_name; - - if (!gAgent.buildLocationString(location_name, LLAgent::LOCATION_FORMAT_FULL)) - location_name = "Unknown"; - - mCmbLocation->setText(location_name); - } -} - -void LLNavigationBar::rebuildLocationHistory(std::string filter) -{ - if (!mCmbLocation) - { - llwarns << "Cannot find location history control" << llendl; - return; - } - - LLLocationHistory::location_list_t filtered_items; - const LLLocationHistory::location_list_t* itemsp = NULL; - LLLocationHistory* lh = LLLocationHistory::getInstance(); - - if (filter.empty()) - itemsp = &lh->getItems(); - else - { - lh->getMatchingItems(filter, filtered_items); - itemsp = &filtered_items; - } - - mCmbLocation->removeall(); - for (LLLocationHistory::location_list_t::const_reverse_iterator it = itemsp->rbegin(); it != itemsp->rend(); it++) - mCmbLocation->add(*it); -} - void LLNavigationBar::rebuildTeleportHistoryMenu() { // Has the pop-up menu been built? if (mTeleportHistoryMenu) { // Clear it. - // *TODO: LLMenuGL should have a method for removing all items. - while (mTeleportHistoryMenu->getItemCount()) - { - LLMenuItemGL* itemp = mTeleportHistoryMenu->getItem(0); - mTeleportHistoryMenu->removeChild(itemp); - } + mTeleportHistoryMenu->empty(); } else { @@ -369,6 +370,7 @@ void LLNavigationBar::rebuildTeleportHistoryMenu() menu_p.can_tear_off(false); menu_p.visible(false); menu_p.bg_visible(true); + menu_p.scrollable(true); mTeleportHistoryMenu = LLUICtrlFactory::create<LLMenuGL>(menu_p); addChild(mTeleportHistoryMenu); @@ -382,26 +384,44 @@ void LLNavigationBar::rebuildTeleportHistoryMenu() // Items will be shown in the reverse order, just like in Firefox. for (int i = (int)hist_items.size()-1; i >= 0; i--) { - LLMenuItemCallGL::Params item_params; - std::string title = hist_items[i].mTitle; - - if (i == cur_item) - item_params.font.style("BOLD"); + LLTeleportHistoryMenuItem::EType type; + if (i < cur_item) + type = LLTeleportHistoryMenuItem::TYPE_BACKWARD; + else if (i > cur_item) + type = LLTeleportHistoryMenuItem::TYPE_FORWARD; else - title = " " + title; + type = LLTeleportHistoryMenuItem::TYPE_CURRENT; - item_params.name(title); - item_params.label(title); + LLTeleportHistoryMenuItem::Params item_params(type, hist_items[i].mTitle); item_params.on_click.function(boost::bind(&LLNavigationBar::onTeleportHistoryMenuItemClicked, this, i)); - mTeleportHistoryMenu->addChild(LLUICtrlFactory::create<LLMenuItemCallGL>(item_params)); + mTeleportHistoryMenu->addChild(LLUICtrlFactory::create<LLTeleportHistoryMenuItem>(item_params)); } } -// static void LLNavigationBar::onRegionNameResponse( + std::string typed_location, + std::string region_name, LLVector3 local_coords, U64 region_handle, const std::string& url, const LLUUID& snapshot_id, bool teleport) { + // Invalid location? + if (!region_handle) + { + invokeSearch(typed_location); + return; + } + + // Location is valid. Add it to the typed locations history. + S32 selected_item = mCmbLocation->getCurrentIndex(); + if (selected_item == -1) // user has typed text + { + LLLocationHistory* lh = LLLocationHistory::getInstance(); + mCmbLocation->add(typed_location); + lh->addItem(typed_location); + lh->save(); + } + + // Teleport to the location. LLVector3d region_pos = from_region_handle(region_handle); LLVector3d global_pos = region_pos + (LLVector3d) local_coords; @@ -409,25 +429,6 @@ void LLNavigationBar::onRegionNameResponse( gAgent.teleportViaLocation(global_pos); } -// static -void LLNavigationBar::teleport(std::string slurl) -{ - std::string sim_string = LLSLURL::stripProtocol(slurl); - std::string region_name; - S32 x = 128; - S32 y = 128; - S32 z = 0; - - LLURLSimString::parse(sim_string, ®ion_name, &x, &y, &z); - - // Resolve region name to global coords. - LLVector3 local_coords(x, y, z); - LLWorldMap::getInstance()->sendNamedRegionRequest(region_name, - boost::bind(&LLNavigationBar::onRegionNameResponse, local_coords, _1, _2, _3, _4), - slurl, - false); // don't teleport -} - void LLNavigationBar::showTeleportHistoryMenu() { // Don't show the popup if teleport history is empty. @@ -449,75 +450,84 @@ void LLNavigationBar::showTeleportHistoryMenu() LLMenuGL::showPopup(this, mTeleportHistoryMenu, btnBackRect.mLeft, btnBackRect.mBottom); // *HACK pass the mouse capturing to the drop-down menu - gFocusMgr.setMouseCapture( mTeleportHistoryMenu ); + gFocusMgr.setMouseCapture( NULL ); } void LLNavigationBar::onLocationContextMenuItemClicked(const LLSD& userdata) { - std::string level = userdata.asString(); + std::string item = userdata.asString(); + LLLineEditor* location_entry = mCmbLocation->getTextEntry(); - if (level == std::string("copy_url")) + if (item == std::string("copy_url")) { - LLUIString url(gAgent.getSLURL()); - LLView::getWindow()->copyTextToClipboard(url.getWString()); - lldebugs << "Copy SLURL" << llendl; + std::string sl_url = gAgent.getSLURL(); + LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(sl_url)); + + LLSD args; + args["SLURL"] = sl_url; + LLNotifications::instance().add("CopySLURL", args); } - else if (level == std::string("landmark")) + else if (item == std::string("landmark")) { - // *TODO To be implemented - lldebugs << "Add Landmark" << llendl; + LLFloaterReg::showInstance("add_landmark"); } - else if (level == std::string("cut")) + else if (item == std::string("cut")) { - mCmbLocation->cut(); - lldebugs << "Cut" << llendl; + location_entry->cut(); } - else if (level == std::string("copy")) + else if (item == std::string("copy")) { - mCmbLocation->copy(); - lldebugs << "Copy" << llendl; + location_entry->copy(); } - else if (level == std::string("paste")) + else if (item == std::string("paste")) { - mCmbLocation->paste(); - lldebugs << "Paste" << llendl; + location_entry->paste(); } - else if (level == std::string("delete")) + else if (item == std::string("delete")) { - mCmbLocation->deleteSelection(); - lldebugs << "Delete" << llendl; + location_entry->deleteSelection(); } - else if (level == std::string("select_all")) + else if (item == std::string("select_all")) { - mCmbLocation->selectAll(); - lldebugs << "Select All" << llendl; + location_entry->selectAll(); } } bool LLNavigationBar::onLocationContextMenuItemEnabled(const LLSD& userdata) { - std::string level = userdata.asString(); + std::string item = userdata.asString(); + const LLLineEditor* location_entry = mCmbLocation->getTextEntry(); - if (level == std::string("can_cut")) + if (item == std::string("can_cut")) { - return mCmbLocation->canCut(); + return location_entry->canCut(); } - else if (level == std::string("can_copy")) + else if (item == std::string("can_copy")) { - return mCmbLocation->canCopy(); + return location_entry->canCopy(); } - else if (level == std::string("can_paste")) + else if (item == std::string("can_paste")) { - return mCmbLocation->canPaste(); + return location_entry->canPaste(); } - else if (level == std::string("can_delete")) + else if (item == std::string("can_delete")) { - return mCmbLocation->canDeselect(); + return location_entry->canDeselect(); } - else if (level == std::string("can_select_all")) + else if (item == std::string("can_select_all")) { - return mCmbLocation->canSelectAll(); + return location_entry->canSelectAll(); } return false; } + +void LLNavigationBar::handleLoginComplete() +{ + mCmbLocation->handleLoginComplete(); +} + +void LLNavigationBar::invokeSearch(std::string search_text) +{ + LLFloaterReg::showInstance("search", LLSD().insert("panel", "all").insert("id", LLSD(search_text))); +} |