summaryrefslogtreecommitdiff
path: root/src/gui/emotepopup.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/emotepopup.cpp')
-rw-r--r--src/gui/emotepopup.cpp214
1 files changed, 214 insertions, 0 deletions
diff --git a/src/gui/emotepopup.cpp b/src/gui/emotepopup.cpp
new file mode 100644
index 000000000..2a0d94aca
--- /dev/null
+++ b/src/gui/emotepopup.cpp
@@ -0,0 +1,214 @@
+/*
+ * Extended support for activating emotes
+ * Copyright (C) 2009 Aethyra Development Team
+ * Copyright (C) 2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gui/emotepopup.h"
+
+#include "animatedsprite.h"
+#include "configuration.h"
+#include "emoteshortcut.h"
+#include "graphics.h"
+#include "localplayer.h"
+#include "log.h"
+
+#include "gui/theme.h"
+
+#include "resources/emotedb.h"
+#include "resources/image.h"
+#include "resources/iteminfo.h"
+
+#include "utils/dtor.h"
+
+#include <guichan/mouseinput.hpp>
+#include <guichan/selectionlistener.hpp>
+
+const int EmotePopup::gridWidth = 34; // emote icon width + 4
+const int EmotePopup::gridHeight = 36; // emote icon height + 4
+
+static const int MAX_COLUMNS = 6;
+
+EmotePopup::EmotePopup():
+ mSelectedEmoteIndex(-1),
+ mHoveredEmoteIndex(-1),
+ mRowCount(1),
+ mColumnCount(1)
+{
+ // Setup emote sprites
+ for (int i = 0; i <= EmoteDB::getLast(); ++i)
+ {
+ const AnimatedSprite *sprite = EmoteDB::getAnimation(i, true);
+ if (sprite)
+ mEmotes.push_back(sprite);
+ }
+
+ mSelectionImage = Theme::getImageFromTheme("selection.png");
+ if (!mSelectionImage)
+ logger->log1("Error: Unable to load selection.png");
+
+ if (mSelectionImage)
+ mSelectionImage->setAlpha(Client::getGuiAlpha());
+
+ addMouseListener(this);
+ recalculateSize();
+ setVisible(true);
+}
+
+EmotePopup::~EmotePopup()
+{
+ if (mSelectionImage)
+ mSelectionImage->decRef();
+}
+
+void EmotePopup::draw(gcn::Graphics *graphics)
+{
+ Popup::draw(graphics);
+
+ if (!mColumnCount)
+ return;
+
+ const unsigned int emoteCount = static_cast<unsigned>(mEmotes.size());
+ const unsigned int emotesLeft
+ = static_cast<unsigned>(mEmotes.size() % mColumnCount);
+
+ for (unsigned int i = 0; i < emoteCount ; i++)
+ {
+ int row = i / mColumnCount;
+ int column = i % mColumnCount;
+
+ unsigned int emoteX = 4 + column * gridWidth;
+ unsigned int emoteY = 4 + row * gridHeight;
+
+ // Center the last row when there are less emotes than columns
+ if (emotesLeft > 0 && row == mRowCount - 1)
+ emoteX += (mColumnCount - emotesLeft) * gridWidth / 2;
+
+ // Draw selection image below hovered item
+ if (mSelectionImage && static_cast<int>(i) == mHoveredEmoteIndex)
+ {
+ static_cast<Graphics*>(graphics)->drawImage(
+ mSelectionImage, emoteX, emoteY + 4);
+ }
+
+ // Draw emote icon
+ if (mEmotes[i])
+ mEmotes[i]->draw(static_cast<Graphics*>(graphics), emoteX, emoteY);
+ }
+}
+
+void EmotePopup::mousePressed(gcn::MouseEvent &event)
+{
+ if (event.getButton() != gcn::MouseEvent::LEFT)
+ return;
+
+ const int index = getIndexAt(event.getX(), event.getY());
+ if (index != -1)
+ {
+ setSelectedEmoteIndex(index);
+ if (emoteShortcut)
+ {
+ emoteShortcut->setEmoteSelected(
+ static_cast<unsigned char>(index + 1));
+ }
+ }
+}
+
+void EmotePopup::mouseMoved(gcn::MouseEvent &event)
+{
+ Popup::mouseMoved(event);
+
+ mHoveredEmoteIndex = getIndexAt(event.getX(), event.getY());
+}
+
+int EmotePopup::getSelectedEmote() const
+{
+ return 1 + mSelectedEmoteIndex;
+}
+
+void EmotePopup::setSelectedEmoteIndex(int index)
+{
+ if (index == mSelectedEmoteIndex)
+ return;
+
+ mSelectedEmoteIndex = index;
+ distributeValueChangedEvent();
+}
+
+int EmotePopup::getIndexAt(int x, int y) const
+{
+ if (!gridWidth || !gridHeight)
+ return -1;
+
+ const unsigned int emotesLeft
+ = static_cast<unsigned>(mEmotes.size() % mColumnCount);
+ const unsigned int row = y / gridHeight;
+ unsigned int column;
+
+ // Take into account that the last row is centered
+ if (emotesLeft > 0 && static_cast<signed>(row) == mRowCount - 1)
+ {
+ int unsigned emotesMissing = mColumnCount - emotesLeft;
+ column = std::min((x - emotesMissing * gridWidth / 2) / gridWidth,
+ emotesLeft - 1);
+ }
+ else
+ {
+ column = std::min(x / gridWidth, mColumnCount - 1);
+ }
+
+ int unsigned index = column + (row * mColumnCount);
+
+ if (index < mEmotes.size())
+ return index;
+
+ return -1;
+}
+
+void EmotePopup::recalculateSize()
+{
+ const unsigned emoteCount = static_cast<unsigned>(mEmotes.size());
+
+ mRowCount = emoteCount / MAX_COLUMNS;
+ if (emoteCount % MAX_COLUMNS > 0)
+ ++mRowCount;
+
+ if (mRowCount)
+ mColumnCount = emoteCount / mRowCount;
+ else
+ mColumnCount = 1;
+
+ if (emoteCount % mRowCount > 0)
+ ++mColumnCount;
+
+ setContentSize(mColumnCount * gridWidth, mRowCount * gridHeight);
+}
+
+void EmotePopup::distributeValueChangedEvent()
+{
+ gcn::SelectionEvent event(this);
+ Listeners::const_iterator i_end = mListeners.end();
+ Listeners::const_iterator i;
+
+ for (i = mListeners.begin(); i != i_end; ++i)
+ {
+ if (*i)
+ (*i)->valueChanged(event);
+ }
+}