summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/Makefile.am4
-rw-r--r--src/gui/inventorywindow.cpp7
-rw-r--r--src/gui/widgets/resizegrip.cpp65
-rw-r--r--src/gui/widgets/resizegrip.h61
-rw-r--r--src/gui/window.cpp191
-rw-r--r--src/gui/window.h66
8 files changed, 312 insertions, 91 deletions
diff --git a/ChangeLog b/ChangeLog
index 20cfc79c..348e90fd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,13 @@
2007-04-15 Bjørn Lindeijer <bjorn@lindeijer.nl>
* src/openglgraphics.cpp: Rely on default 0 value for z axis.
+ * src/CMakeLists.txt, src/gui/window.cpp, src/gui/widgets,
+ src/gui/widgets/resizegrip.cpp, src/gui/widgets/resizegrip.h,
+ src/gui/inventorywindow.cpp, src/gui/window.h, src/Makefile.am:
+ Reimplemented window resizing. It is now once again possible to resize
+ windows using their borders (except for the top one, since that's the
+ title bar for Guichan) and the resize grip in the bottom right is much
+ easier to grab.
2007-04-05 Eugenio Favalli <elvenprogrammer@gmail.com>
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 2dd84177..ed5623fc 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -50,6 +50,8 @@ MARK_AS_ADVANCED(SDL_INCLUDE_DIR)
MARK_AS_ADVANCED(SDL_LIBRARY)
SET(SRCS
+ gui/widgets/resizegrip.cpp
+ gui/widgets/resizegrip.h
gui/browserbox.cpp
gui/browserbox.h
gui/buddywindow.cpp
diff --git a/src/Makefile.am b/src/Makefile.am
index a71414ed..d491ca4b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,5 +1,7 @@
bin_PROGRAMS = tmw
-tmw_SOURCES = gui/browserbox.cpp \
+tmw_SOURCES = gui/widgets/resizegrip.cpp \
+ gui/widgets/resizegrip.h \
+ gui/browserbox.cpp \
gui/browserbox.h \
gui/buddywindow.cpp \
gui/buddywindow.h \
diff --git a/src/gui/inventorywindow.cpp b/src/gui/inventorywindow.cpp
index e533c16c..982aaaf3 100644
--- a/src/gui/inventorywindow.cpp
+++ b/src/gui/inventorywindow.cpp
@@ -165,8 +165,8 @@ void InventoryWindow::mouseClicked(gcn::MouseEvent &event)
if (!item) return;
- /* Convert relative to the window coordinates to
- * absolute screen coordinates.
+ /* Convert relative to the window coordinates to absolute screen
+ * coordinates.
*/
int mx = event.getX() + getX();
int my = event.getY() + getY();
@@ -178,7 +178,8 @@ void InventoryWindow::mouseDragged(gcn::MouseEvent &event)
{
int tmpWidth = getWidth(), tmpHeight = getHeight();
Window::mouseDragged(event);
- if (getWidth() != tmpWidth || getHeight() != tmpHeight) {
+ if (getWidth() != tmpWidth || getHeight() != tmpHeight)
+ {
updateWidgets();
}
}
diff --git a/src/gui/widgets/resizegrip.cpp b/src/gui/widgets/resizegrip.cpp
new file mode 100644
index 00000000..50a6fce4
--- /dev/null
+++ b/src/gui/widgets/resizegrip.cpp
@@ -0,0 +1,65 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World 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.
+ *
+ * The Mana World 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 The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#include "resizegrip.h"
+
+#include <guichan/graphics.hpp>
+
+#include "../../graphics.h"
+
+#include "../../resources/image.h"
+#include "../../resources/resourcemanager.h"
+
+Image *ResizeGrip::gripImage = 0;
+int ResizeGrip::mInstances = 0;
+
+ResizeGrip::ResizeGrip()
+{
+ if (mInstances == 0)
+ {
+ // Load the grip image
+ ResourceManager *resman = ResourceManager::getInstance();
+ gripImage = resman->getImage("graphics/gui/resize.png");
+ }
+
+ mInstances++;
+
+ setWidth(gripImage->getWidth() + 2);
+ setHeight(gripImage->getHeight() + 2);
+}
+
+ResizeGrip::~ResizeGrip()
+{
+ mInstances--;
+
+ if (mInstances == 0)
+ {
+ gripImage->decRef();
+ }
+}
+
+void
+ResizeGrip::draw(gcn::Graphics *graphics)
+{
+ dynamic_cast<Graphics*>(graphics)->drawImage(gripImage, 0, 0);
+}
diff --git a/src/gui/widgets/resizegrip.h b/src/gui/widgets/resizegrip.h
new file mode 100644
index 00000000..04be3db3
--- /dev/null
+++ b/src/gui/widgets/resizegrip.h
@@ -0,0 +1,61 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World 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.
+ *
+ * The Mana World 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 The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#ifndef _TMW_RESIZEGRIP_H
+#define _TMW_RESIZEGRIP_H
+
+#include <guichan/widget.hpp>
+
+class Image;
+
+/**
+ * Resize grip. The resize grip is part of a resizable Window. It relies on the
+ * fact that uncaught mouse events are automatically routed to the parent
+ * window.
+ *
+ * \ingroup GUI
+ */
+class ResizeGrip : public gcn::Widget
+{
+ public:
+ /**
+ * Constructor.
+ */
+ ResizeGrip();
+
+ /**
+ * Destructor.
+ */
+ ~ResizeGrip();
+
+ /**
+ * Draws the resize grip.
+ */
+ void draw(gcn::Graphics *graphics);
+
+ private:
+ static Image *gripImage; /**< Resize grip image */
+ static int mInstances; /**< Number of resize grip instances */
+};
+
+#endif
diff --git a/src/gui/window.cpp b/src/gui/window.cpp
index 4f26af79..bd3e7eb5 100644
--- a/src/gui/window.cpp
+++ b/src/gui/window.cpp
@@ -24,10 +24,13 @@
#include "window.h"
#include <guichan/exception.hpp>
+#include <guichan/widgets/icon.hpp>
#include "gccontainer.h"
#include "windowcontainer.h"
+#include "widgets/resizegrip.h"
+
#include "../configlistener.h"
#include "../configuration.h"
#include "../graphics.h"
@@ -36,11 +39,10 @@
#include "../resources/image.h"
#include "../resources/resourcemanager.h"
-ConfigListener *Window::windowConfigListener = NULL;
-WindowContainer *Window::windowContainer = NULL;
+ConfigListener *Window::windowConfigListener = 0;
+WindowContainer *Window::windowContainer = 0;
int Window::instances = 0;
ImageRect Window::border;
-Image *Window::resizeGrip;
class WindowConfigListener : public ConfigListener
{
@@ -54,13 +56,13 @@ class WindowConfigListener : public ConfigListener
Window::Window(const std::string& caption, bool modal, Window *parent):
gcn::Window(caption),
+ mGrip(0),
mParent(parent),
mWindowName("window"),
- mSnapSize(8),
mShowTitle(true),
mModal(modal),
mResizable(false),
- mMouseResize(false),
+ mMouseResize(0),
mSticky(false),
mMinWinWidth(100),
mMinWinHeight(28),
@@ -87,7 +89,6 @@ Window::Window(const std::string& caption, bool modal, Window *parent):
border.grid[6] = dBorders->getSubImage(0, 15, 4, 4);
border.grid[7] = dBorders->getSubImage(4, 15, 3, 4);
border.grid[8] = dBorders->getSubImage(7, 15, 4, 4);
- resizeGrip = resman->getImage("graphics/gui/resize.png");
dBorders->decRef();
windowConfigListener = new WindowConfigListener();
// Send GUI alpha changed for initialization
@@ -151,10 +152,10 @@ Window::~Window()
delete border.grid[6];
delete border.grid[7];
delete border.grid[8];
- resizeGrip->decRef();
}
delete mChrome;
+ delete mGrip;
}
void Window::setWindowContainer(WindowContainer *wc)
@@ -162,22 +163,15 @@ void Window::setWindowContainer(WindowContainer *wc)
windowContainer = wc;
}
-void Window::draw(gcn::Graphics* graphics)
+void Window::draw(gcn::Graphics *graphics)
{
- Graphics *g = (Graphics*)graphics;
+ Graphics *g = static_cast<Graphics*>(graphics);
g->drawImageRect(0, 0, getWidth(), getHeight(), border);
- // Draw grip
- if (mResizable)
- {
- g->drawImage(Window::resizeGrip,
- getWidth() - resizeGrip->getWidth(),
- getHeight() - resizeGrip->getHeight());
- }
-
// Draw title
- if (mShowTitle) {
+ if (mShowTitle)
+ {
graphics->setFont(getFont());
graphics->drawText(getCaption(), 7, 5, gcn::Graphics::LEFT);
}
@@ -203,6 +197,37 @@ void Window::setContentSize(int width, int height)
setContentHeight(height);
}
+void Window::setWidth(int width)
+{
+ gcn::Window::setWidth(width);
+
+ if (mGrip)
+ {
+ mGrip->setX(getWidth() - mGrip->getWidth() - getChildrenArea().x);
+ }
+}
+
+void Window::setHeight(int height)
+{
+ gcn::Window::setHeight(height);
+
+ if (mGrip)
+ {
+ mGrip->setY(getHeight() - mGrip->getHeight() - getChildrenArea().y);
+ }
+}
+
+void Window::setDimension(const gcn::Rectangle &dimension)
+{
+ gcn::Window::setDimension(dimension);
+
+ if (mGrip)
+ {
+ mGrip->setX(getWidth() - mGrip->getWidth() - getChildrenArea().x);
+ mGrip->setY(getHeight() - mGrip->getHeight() - getChildrenArea().y);
+ }
+}
+
void Window::setLocationRelativeTo(gcn::Widget* widget)
{
int wx, wy;
@@ -238,6 +263,19 @@ void Window::setMaxHeight(unsigned int height)
void Window::setResizable(bool r)
{
mResizable = r;
+
+ if (mResizable)
+ {
+ mGrip = new ResizeGrip();
+ mGrip->setX(getWidth() - mGrip->getWidth() - getChildrenArea().x);
+ mGrip->setY(getHeight() - mGrip->getHeight() - getChildrenArea().y);
+ gcn::Window::add(mGrip);
+ }
+ else
+ {
+ delete mGrip;
+ mGrip = 0;
+ }
}
bool Window::isResizable()
@@ -250,16 +288,18 @@ void Window::setSticky(bool sticky)
mSticky = sticky;
}
-bool Window::isSticky() {
+bool Window::isSticky()
+{
return mSticky;
}
-void Window::setVisible(bool visible) {
- if(isSticky())
+void Window::setVisible(bool visible)
+{
+ if (isSticky())
{
gcn::Window::setVisible(true);
- }
- else
+ }
+ else
{
gcn::Window::setVisible(visible);
}
@@ -285,15 +325,27 @@ void Window::mousePressed(gcn::MouseEvent &event)
// Let Guichan move window to top and figure out title bar drag
gcn::Window::mousePressed(event);
- int x = event.getX();
- int y = event.getY();
+ const int x = event.getX();
+ const int y = event.getY();
+ mMouseResize = 0;
- // Activate resizing if the left mouse button was pressed on the grip
- mMouseResize =
- isResizable() &&
- event.getButton() == gcn::MouseEvent::LEFT &&
- getGripDimension().isPointInRect(x, y) &&
- !getChildrenArea().isPointInRect(x, y);
+ // Activate resizing handles as appropriate
+ if (event.getSource() == this && isResizable() &&
+ event.getButton() == gcn::MouseEvent::LEFT &&
+ !getChildrenArea().isPointInRect(x, y))
+ {
+ mMouseResize |= (x > getWidth() - resizeBorderWidth) ? RIGHT :
+ (x < resizeBorderWidth) ? LEFT : 0;
+ mMouseResize |= (y > getHeight() - resizeBorderWidth) ? BOTTOM :
+ (y < resizeBorderWidth) ? TOP : 0;
+ }
+ else if (event.getSource() == mGrip)
+ {
+ mDragOffsetX = x + mGrip->getX();
+ mDragOffsetY = y + mGrip->getY();
+ mMouseResize |= BOTTOM | RIGHT;
+ mIsMoving = false;
+ }
}
void Window::mouseDragged(gcn::MouseEvent &event)
@@ -301,20 +353,47 @@ void Window::mouseDragged(gcn::MouseEvent &event)
// Let Guichan handle title bar drag
gcn::Window::mouseDragged(event);
- // Keep guichan window inside screen
- int newX = std::max(0, getX());
- int newY = std::max(0, getY());
- newX = std::min(windowContainer->getWidth() - getWidth(), newX);
- newY = std::min(windowContainer->getHeight() - getHeight(), newY);
- setPosition(newX, newY);
+ // Keep guichan window inside screen when it may be moved
+ if (isMovable() && mIsMoving)
+ {
+ int newX = std::max(0, getX());
+ int newY = std::max(0, getY());
+ newX = std::min(windowContainer->getWidth() - getWidth(), newX);
+ newY = std::min(windowContainer->getHeight() - getHeight(), newY);
+ setPosition(newX, newY);
+ }
if (mMouseResize && !mIsMoving)
{
+ const int dx = event.getX() - mDragOffsetX +
+ ((event.getSource() == mGrip) ? mGrip->getX() : 0);
+ const int dy = event.getY() - mDragOffsetY +
+ ((event.getSource() == mGrip) ? mGrip->getY() : 0);
gcn::Rectangle newDim = getDimension();
- // We're dragging bottom right
- newDim.width += event.getX() - mDragOffsetX;
- newDim.height += event.getY() - mDragOffsetY;
+ if (mMouseResize & (TOP | BOTTOM))
+ {
+ int newHeight = newDim.height + ((mMouseResize & TOP) ? -dy : dy);
+ newDim.height = std::min(mMaxWinHeight,
+ std::max(mMinWinHeight, newHeight));
+
+ if (mMouseResize & TOP)
+ {
+ newDim.y -= newDim.height - getHeight();
+ }
+ }
+
+ if (mMouseResize & (LEFT | RIGHT))
+ {
+ int newWidth = newDim.width + ((mMouseResize & LEFT) ? -dx : dx);
+ newDim.width = std::min(mMaxWinWidth,
+ std::max(mMinWinWidth, newWidth));
+
+ if (mMouseResize & LEFT)
+ {
+ newDim.x -= newDim.width - getWidth();
+ }
+ }
// Keep guichan window inside screen (supports resizing any side)
if (newDim.x < 0)
@@ -336,29 +415,16 @@ void Window::mouseDragged(gcn::MouseEvent &event)
newDim.height = windowContainer->getHeight() - newDim.y;
}
- // Keep the window at least its minimum size
- if (newDim.width < mMinWinWidth)
- {
- newDim.width = mMinWinWidth;
- }
- else if (newDim.width > mMaxWinWidth)
- {
- newDim.width = mMaxWinWidth;
- }
-
- if (newDim.height < mMinWinHeight)
+ // Update mouse offset when dragging bottom or right border
+ if (mMouseResize & BOTTOM)
{
- newDim.height = mMinWinHeight;
+ mDragOffsetY += newDim.height - getHeight();
}
- else if (newDim.height > mMaxWinHeight)
+ if (mMouseResize & RIGHT)
{
- newDim.height = mMaxWinHeight;
+ mDragOffsetX += newDim.width - getWidth();
}
- // Update mouse offset when dragging bottom or right border
- mDragOffsetX += newDim.width - getWidth();
- mDragOffsetY += newDim.height - getHeight();
-
// Set the new window and content dimensions
setDimension(newDim);
const gcn::Rectangle area = getChildrenArea();
@@ -366,15 +432,6 @@ void Window::mouseDragged(gcn::MouseEvent &event)
}
}
-gcn::Rectangle
-Window::getGripDimension()
-{
- return gcn::Rectangle(getWidth() - resizeGrip->getWidth(),
- getHeight() - resizeGrip->getHeight(),
- getWidth(),
- getHeight());
-}
-
void
Window::loadWindowState()
{
diff --git a/src/gui/window.h b/src/gui/window.h
index 9ac02287..1180d91c 100644
--- a/src/gui/window.h
+++ b/src/gui/window.h
@@ -30,11 +30,10 @@
class ConfigListener;
class GCContainer;
-class Image;
class ImageRect;
+class ResizeGrip;
class WindowContainer;
-
/**
* A window. This window can be dragged around and has a title bar. Windows are
* invisible by default.
@@ -100,6 +99,21 @@ class Window : public gcn::Window
void setContentSize(int width, int height);
/**
+ * Sets the width of this window.
+ */
+ void setWidth(int width);
+
+ /**
+ * Sets the height of this window.
+ */
+ void setHeight(int height);
+
+ /**
+ * Sets the position and size of this window.
+ */
+ void setDimension(const gcn::Rectangle &dimension);
+
+ /**
* Sets the location relative to the given widget.
*/
void setLocationRelativeTo(gcn::Widget *widget);
@@ -168,16 +182,15 @@ class Window : public gcn::Window
void scheduleDelete();
/**
- * Window dragging and resizing mouse related. These methods also makes
- * sure the window is not dragged/resized outside of the screen.
+ * Starts window resizing when appropriate.
*/
void mousePressed(gcn::MouseEvent &event);
- void mouseDragged(gcn::MouseEvent &event);
/**
- * Gets the position of the resize grip.
+ * Implements window resizing and makes sure the window is not
+ * dragged/resized outside of the screen.
*/
- gcn::Rectangle getGripDimension();
+ void mouseDragged(gcn::MouseEvent &event);
/**
* Sets the name of the window. This is not the window title.
@@ -214,37 +227,50 @@ class Window : public gcn::Window
*/
virtual void resetToDefaultSize();
+ enum ResizeHandles
+ {
+ TOP = 0x01,
+ RIGHT = 0x02,
+ BOTTOM = 0x04,
+ LEFT = 0x08
+ };
+
protected:
- GCContainer *mChrome; /**< Contained container */
+ GCContainer *mChrome; /**< Contained container */
+ ResizeGrip *mGrip; /**< Resize grip */
Window *mParent; /**< The parent window */
std::string mWindowName; /**< Name of the window */
- int mSnapSize; /**< Snap distance to window edge */
bool mShowTitle; /**< Window has a title bar */
bool mModal; /**< Window is modal */
- bool mResizable; /**< Window can be resized */
- bool mMouseResize; /**< Window is being resized */
- bool mSticky; /**< Window resists minimzation */
- int mMinWinWidth; /**< Minimum window width */
- int mMinWinHeight; /**< Minimum window height */
- int mMaxWinWidth; /**< Maximum window width */
- int mMaxWinHeight; /**< Maximum window height */
+ bool mResizable; /**< Window can be resized */
+ int mMouseResize; /**< Window is being resized */
+ bool mSticky; /**< Window resists minimization */
+ int mMinWinWidth; /**< Minimum window width */
+ int mMinWinHeight; /**< Minimum window height */
+ int mMaxWinWidth; /**< Maximum window width */
+ int mMaxWinHeight; /**< Maximum window height */
int mDefaultX; /**< Default window X position */
int mDefaultY; /**< Default window Y position */
int mDefaultWidth; /**< Default window width */
int mDefaultHeight; /**< Default window height */
/** The window container windows add themselves to. */
- static WindowContainer* windowContainer;
+ static WindowContainer *windowContainer;
/**
- * The config listener that listens to changes relevant to all
- * windows
+ * The config listener that listens to changes relevant to all windows.
*/
static ConfigListener *windowConfigListener;
static int instances; /**< Number of Window instances */
static ImageRect border; /**< The window border and background */
- static Image *resizeGrip; /**< The grip to resize window */
+
+ /**
+ * The width of the resize border. Is independent of the actual window
+ * border width, and determines mostly the size of the corner area
+ * where two borders are moved at the same time.
+ */
+ static const int resizeBorderWidth = 10;
};
#endif