summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThorbjørn Lindeijer <bjorn@lindeijer.nl>2024-03-11 21:10:53 +0100
committerThorbjørn Lindeijer <bjorn@lindeijer.nl>2024-03-11 21:10:53 +0100
commit66599a9896e0cf69b58c0a73152aba4750d87af2 (patch)
tree034b6b4a05ea1b4fc87887f48734f630e757e6f7
parent0694d89c4147882561ff44c6d0d80e7414dcb24a (diff)
downloadMana-66599a9896e0cf69b58c0a73152aba4750d87af2.tar.gz
Mana-66599a9896e0cf69b58c0a73152aba4750d87af2.tar.bz2
Mana-66599a9896e0cf69b58c0a73152aba4750d87af2.tar.xz
Mana-66599a9896e0cf69b58c0a73152aba4750d87af2.zip
Implemented ability to open external links in news and chat
* Use ConfirmDialog to confirm the opening of the external link. * ConfirmDialog now centers on its parent window when provided. * Reset hovered link when mouse exits the BrowserBox.
-rw-r--r--src/gui/chatwindow.cpp2
-rw-r--r--src/gui/updaterwindow.cpp5
-rw-r--r--src/gui/updaterwindow.h5
-rw-r--r--src/gui/widgets/browserbox.cpp11
-rw-r--r--src/gui/widgets/browserbox.h1
-rw-r--r--src/gui/widgets/itemlinkhandler.cpp34
-rw-r--r--src/gui/widgets/itemlinkhandler.h20
-rw-r--r--src/gui/widgets/window.cpp5
-rw-r--r--src/utils/stringutils.h8
9 files changed, 73 insertions, 18 deletions
diff --git a/src/gui/chatwindow.cpp b/src/gui/chatwindow.cpp
index d51c3a25..041e08e9 100644
--- a/src/gui/chatwindow.cpp
+++ b/src/gui/chatwindow.cpp
@@ -106,7 +106,7 @@ ChatWindow::ChatWindow():
setMinWidth(150);
setMinHeight(90);
- mItemLinkHandler = new ItemLinkHandler;
+ mItemLinkHandler = new ItemLinkHandler(this);
mChatInput = new ChatInput;
mChatInput->setActionEventId("chatinput");
diff --git a/src/gui/updaterwindow.cpp b/src/gui/updaterwindow.cpp
index 8c63ef6a..c8ed66e1 100644
--- a/src/gui/updaterwindow.cpp
+++ b/src/gui/updaterwindow.cpp
@@ -33,6 +33,7 @@
#include "gui/widgets/layout.h"
#include "gui/widgets/progressbar.h"
#include "gui/widgets/scrollarea.h"
+#include "gui/widgets/itemlinkhandler.h"
#include "net/download.h"
@@ -123,7 +124,8 @@ UpdaterWindow::UpdaterWindow(const std::string &updateHost,
mUpdateHost(updateHost),
mUpdatesDir(updatesDir),
mCurrentFile("news.txt"),
- mLoadUpdates(applyUpdates)
+ mLoadUpdates(applyUpdates),
+ mLinkHandler(std::make_unique<ItemLinkHandler>(this))
{
setWindowName("UpdaterWindow");
setResizable(true);
@@ -138,6 +140,7 @@ UpdaterWindow::UpdaterWindow(const std::string &updateHost,
mCancelButton = new Button(_("Cancel"), "cancel", this);
mPlayButton = new Button(_("Play"), "play", this);
+ mBrowserBox->setLinkHandler(mLinkHandler.get());
mProgressBar->setSmoothProgress(false);
mScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
mPlayButton->setEnabled(false);
diff --git a/src/gui/updaterwindow.h b/src/gui/updaterwindow.h
index 2d1b059b..6ea1d754 100644
--- a/src/gui/updaterwindow.h
+++ b/src/gui/updaterwindow.h
@@ -31,9 +31,11 @@
#include <guichan/actionlistener.hpp>
#include <guichan/keylistener.hpp>
+#include <memory>
#include <string>
#include <vector>
+class LinkHandler;
class BrowserBox;
class Button;
class ProgressBar;
@@ -99,8 +101,6 @@ class UpdaterWindow : public Window, public gcn::ActionListener,
void logic() override;
- int updateState;
-
private:
void download();
@@ -189,6 +189,7 @@ private:
ProgressBar *mProgressBar; /**< Update progress bar. */
BrowserBox *mBrowserBox; /**< Box to display news. */
ScrollArea *mScrollArea; /**< Used to scroll news box. */
+ std::unique_ptr<LinkHandler> mLinkHandler;
};
#endif
diff --git a/src/gui/widgets/browserbox.cpp b/src/gui/widgets/browserbox.cpp
index d12562f1..8814a995 100644
--- a/src/gui/widgets/browserbox.cpp
+++ b/src/gui/widgets/browserbox.cpp
@@ -70,9 +70,7 @@ BrowserBox::BrowserBox(unsigned int mode):
addMouseListener(this);
}
-BrowserBox::~BrowserBox()
-{
-}
+BrowserBox::~BrowserBox() = default;
void BrowserBox::addRow(const std::string &row)
{
@@ -177,6 +175,11 @@ void BrowserBox::mouseMoved(gcn::MouseEvent &event)
updateHoveredLink(event.getX(), event.getY());
}
+void BrowserBox::mouseExited(gcn::MouseEvent &event)
+{
+ mHoveredLink.reset();
+}
+
void BrowserBox::draw(gcn::Graphics *graphics)
{
const gcn::ClipRectangle &cr = graphics->getCurrentClipArea();
@@ -285,7 +288,7 @@ void BrowserBox::layoutTextRow(TextRow &row, LayoutContext &context)
int x = 0;
// Check for separator lines
- if (row.text.find("---", 0) == 0)
+ if (startsWith(row.text, "---"))
{
for (x = 0; x < getWidth(); x += context.minusWidth - 1)
{
diff --git a/src/gui/widgets/browserbox.h b/src/gui/widgets/browserbox.h
index 11b391e0..a87634fd 100644
--- a/src/gui/widgets/browserbox.h
+++ b/src/gui/widgets/browserbox.h
@@ -118,6 +118,7 @@ class BrowserBox : public gcn::Widget,
*/
void mousePressed(gcn::MouseEvent &event) override;
void mouseMoved(gcn::MouseEvent &event) override;
+ void mouseExited(gcn::MouseEvent &event) override;
/**
* Draws the browser box.
diff --git a/src/gui/widgets/itemlinkhandler.cpp b/src/gui/widgets/itemlinkhandler.cpp
index 81fa2ba7..e15aa6d0 100644
--- a/src/gui/widgets/itemlinkhandler.cpp
+++ b/src/gui/widgets/itemlinkhandler.cpp
@@ -22,6 +22,7 @@
#include <sstream>
#include <string>
+#include "gui/confirmdialog.h"
#include "gui/itempopup.h"
#include "gui/viewport.h"
@@ -29,22 +30,37 @@
#include "resources/iteminfo.h"
#include "resources/itemdb.h"
+#include "utils/gettext.h"
+#include "utils/stringutils.h"
-ItemLinkHandler::ItemLinkHandler()
+ItemLinkHandler::ItemLinkHandler(Window *parent)
+ : mParent(parent)
{
- mItemPopup = new ItemPopup;
+ mItemPopup = std::make_unique<ItemPopup>();
}
-ItemLinkHandler::~ItemLinkHandler()
+ItemLinkHandler::~ItemLinkHandler() = default;
+
+static bool isUrl(const std::string &link)
{
- delete mItemPopup;
+ return startsWith(link, "https://") ||
+ startsWith(link, "http://") ||
+ startsWith(link, "ftp://");
}
void ItemLinkHandler::handleLink(const std::string &link)
{
+ if (isUrl(link))
+ {
+ mLink = link;
+
+ mConfirmDialog = new ConfirmDialog(_("Open URL?"), link, mParent);
+ mConfirmDialog->addActionListener(this);
+ return;
+ }
+
int id = 0;
- std::stringstream stream;
- stream << link;
+ std::istringstream stream(link);
stream >> id;
if (id > 0)
@@ -58,3 +74,9 @@ void ItemLinkHandler::handleLink(const std::string &link)
mItemPopup->position(viewport->getMouseX(), viewport->getMouseY());
}
}
+
+void ItemLinkHandler::action(const gcn::ActionEvent &actionEvent)
+{
+ if (actionEvent.getId() == "yes")
+ SDL_OpenURL(mLink.c_str());
+}
diff --git a/src/gui/widgets/itemlinkhandler.h b/src/gui/widgets/itemlinkhandler.h
index d0f00b25..3bb0b557 100644
--- a/src/gui/widgets/itemlinkhandler.h
+++ b/src/gui/widgets/itemlinkhandler.h
@@ -24,18 +24,32 @@
#include "gui/widgets/linkhandler.h"
+#include <guichan/actionlistener.hpp>
+
+#include <memory>
+
+class ConfirmDialog;
class ItemPopup;
+class Window;
-class ItemLinkHandler : public LinkHandler
+class ItemLinkHandler : public LinkHandler, gcn::ActionListener
{
public:
- ItemLinkHandler();
+ ItemLinkHandler(Window *parent = nullptr);
~ItemLinkHandler() override;
+ // LinkHandler interface
void handleLink(const std::string &link) override;
+ // ActionListener interface
+ void action(const gcn::ActionEvent &actionEvent) override;
+
private:
- ItemPopup *mItemPopup;
+ std::unique_ptr<ItemPopup> mItemPopup;
+ ConfirmDialog *mConfirmDialog = nullptr;
+
+ Window *mParent = nullptr;
+ std::string mLink;
};
#endif
diff --git a/src/gui/widgets/window.cpp b/src/gui/widgets/window.cpp
index 6290ef62..e09986d2 100644
--- a/src/gui/widgets/window.cpp
+++ b/src/gui/widgets/window.cpp
@@ -765,7 +765,10 @@ void Window::redraw()
void Window::center()
{
- setLocationRelativeTo(getParent());
+ if (auto window = getParentWindow())
+ setLocationRelativeTo(window);
+ else
+ setLocationRelativeTo(getParent());
}
void Window::ensureOnScreen()
diff --git a/src/utils/stringutils.h b/src/utils/stringutils.h
index cd80b60f..8e5f1102 100644
--- a/src/utils/stringutils.h
+++ b/src/utils/stringutils.h
@@ -121,6 +121,14 @@ std::string removeColors(std::string msg);
int compareStrI(const std::string &a, const std::string &b);
/**
+ * Returns whether a string starts with a given prefix.
+ */
+inline bool startsWith(const std::string &str, const char *prefix)
+{
+ return str.rfind(prefix, 0) == 0;
+}
+
+/**
* Tells wether the character is a word separator.
*/
bool isWordSeparator(char chr);