summaryrefslogtreecommitdiff
path: root/src/gui/window.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/window.cpp')
-rw-r--r--src/gui/window.cpp198
1 files changed, 168 insertions, 30 deletions
diff --git a/src/gui/window.cpp b/src/gui/window.cpp
index 84f4466c..17447009 100644
--- a/src/gui/window.cpp
+++ b/src/gui/window.cpp
@@ -26,6 +26,7 @@
#include <guichan/exception.hpp>
#include <guichan/widgets/icon.hpp>
+#include "gui.h"
#include "gccontainer.h"
#include "windowcontainer.h"
@@ -42,7 +43,9 @@
ConfigListener *Window::windowConfigListener = 0;
WindowContainer *Window::windowContainer = 0;
int Window::instances = 0;
+int Window::mouseResize = 0;
ImageRect Window::border;
+Image *Window::closeImage = NULL;
class WindowConfigListener : public ConfigListener
{
@@ -60,7 +63,7 @@ Window::Window(const std::string& caption, bool modal, Window *parent):
mParent(parent),
mModal(modal),
mResizable(false),
- mMouseResize(0),
+ mCloseButton(false),
mSticky(false),
mMinWinWidth(100),
mMinWinHeight(40),
@@ -88,6 +91,8 @@ Window::Window(const std::string& caption, bool modal, Window *parent):
border.grid[7] = dBorders->getSubImage(4, 15, 3, 4);
border.grid[8] = dBorders->getSubImage(7, 15, 4, 4);
dBorders->decRef();
+ closeImage = resman->getImage("graphics/gui/close_button.png");
+
windowConfigListener = new WindowConfigListener();
// Send GUI alpha changed for initialization
windowConfigListener->optionChanged("guialpha");
@@ -110,6 +115,7 @@ Window::Window(const std::string& caption, bool modal, Window *parent):
if (mModal)
{
+ gui->setCursorType(Gui::CURSOR_POINTER);
requestModalFocus();
}
@@ -153,6 +159,7 @@ Window::~Window()
delete border.grid[6];
delete border.grid[7];
delete border.grid[8];
+ closeImage->decRef();
}
delete mChrome;
@@ -173,11 +180,19 @@ void Window::draw(gcn::Graphics *graphics)
// Draw title
if (getTitleBarHeight())
{
- graphics->setColor(gcn::Color(0, 0, 0));
- graphics->setFont(getFont());
- graphics->drawText(getCaption(), 7, 5, gcn::Graphics::LEFT);
+ g->setColor(gcn::Color(0, 0, 0));
+ g->setFont(getFont());
+ g->drawText(getCaption(), 7, 5, gcn::Graphics::LEFT);
}
+ // Draw Close Button
+ if (mCloseButton)
+ {
+ g->drawImage(closeImage,
+ getWidth() - closeImage->getWidth() - getPadding(),
+ getPadding()
+ );
+ }
drawChildren(graphics);
}
@@ -207,6 +222,8 @@ void Window::setWidth(int width)
{
mGrip->setX(getWidth() - mGrip->getWidth() - getChildrenArea().x);
}
+
+ fireWindowEvent(WindowEvent(this, WindowEvent::WINDOW_RESIZED));
}
void Window::setHeight(int height)
@@ -217,6 +234,8 @@ void Window::setHeight(int height)
{
mGrip->setY(getHeight() - mGrip->getHeight() - getChildrenArea().y);
}
+
+ fireWindowEvent(WindowEvent(this, WindowEvent::WINDOW_RESIZED));
}
void Window::setDimension(const gcn::Rectangle &dimension)
@@ -228,6 +247,27 @@ void Window::setDimension(const gcn::Rectangle &dimension)
mGrip->setX(getWidth() - mGrip->getWidth() - getChildrenArea().x);
mGrip->setY(getHeight() - mGrip->getHeight() - getChildrenArea().y);
}
+
+ fireWindowEvent(WindowEvent(this, WindowEvent::WINDOW_RESIZED));
+ fireWindowEvent(WindowEvent(this, WindowEvent::WINDOW_MOVED));
+}
+
+void Window::setPosition(int x, int y)
+{
+ gcn::Window::setPosition(x, y);
+ fireWindowEvent(WindowEvent(this, WindowEvent::WINDOW_MOVED));
+}
+
+void Window::setX(int x)
+{
+ gcn::Window::setX(x);
+ fireWindowEvent(WindowEvent(this, WindowEvent::WINDOW_MOVED));
+}
+
+void Window::setY(int y)
+{
+ gcn::Window::setY(y);
+ fireWindowEvent(WindowEvent(this, WindowEvent::WINDOW_MOVED));
}
void Window::setLocationRelativeTo(gcn::Widget *widget)
@@ -280,6 +320,11 @@ void Window::setResizable(bool r)
}
}
+void Window::setCloseButton(bool flag)
+{
+ mCloseButton = flag;
+}
+
bool Window::isResizable()
{
return mResizable;
@@ -327,27 +372,73 @@ void Window::mousePressed(gcn::MouseEvent &event)
// Let Guichan move window to top and figure out title bar drag
gcn::Window::mousePressed(event);
- const int x = event.getX();
- const int y = event.getY();
- mMouseResize = 0;
+ if (event.getButton() == gcn::MouseEvent::LEFT)
+ {
+ const int x = event.getX();
+ const int y = event.getY();
+
+ // Handle close button
+ if (mCloseButton)
+ {
+ gcn::Rectangle closeButtonRect(
+ getWidth() - closeImage->getWidth() - getPadding(),
+ getPadding(),
+ closeImage->getWidth(),
+ closeImage->getHeight());
+
+ if (closeButtonRect.isPointInRect(x, y))
+ {
+ setVisible(false);
+ }
+ }
+
+ // Handle window resizing
+ mouseResize = getResizeHandles(event);
+ }
+}
+
+void Window::mouseReleased(gcn::MouseEvent &event)
+{
+ if (mResizable && mouseResize)
+ {
+ mouseResize = 0;
+ gui->setCursorType(Gui::CURSOR_POINTER);
+ }
+
+ // This should be the responsibility of Guichan (and is from 0.8.0 on)
+ mIsMoving = false;
+}
- // Activate resizing handles as appropriate
- if (event.getSource() == this && isResizable() &&
- event.getButton() == gcn::MouseEvent::LEFT &&
- !getChildrenArea().isPointInRect(x, y))
+void Window::mouseExited(gcn::MouseEvent &event)
+{
+ if (mResizable && !mouseResize)
{
- mMouseResize |= (x > getWidth() - resizeBorderWidth) ? RIGHT :
- (x < resizeBorderWidth) ? LEFT : 0;
- mMouseResize |= (y > getHeight() - resizeBorderWidth) ? BOTTOM :
- (y < resizeBorderWidth) ? TOP : 0;
+ gui->setCursorType(Gui::CURSOR_POINTER);
}
- else if (event.getSource() == mGrip &&
- event.getButton() == gcn::MouseEvent::LEFT)
+}
+
+void Window::mouseMoved(gcn::MouseEvent &event)
+{
+ int resizeHandles = getResizeHandles(event);
+
+ // Changes the custom mouse cursor based on it's current position.
+ switch (resizeHandles)
{
- mDragOffsetX = x;
- mDragOffsetY = y;
- mMouseResize |= BOTTOM | RIGHT;
- mIsMoving = false;
+ case BOTTOM | RIGHT:
+ gui->setCursorType(Gui::CURSOR_RESIZE_DOWN_RIGHT);
+ break;
+ case BOTTOM | LEFT:
+ gui->setCursorType(Gui::CURSOR_RESIZE_DOWN_LEFT);
+ break;
+ case BOTTOM:
+ gui->setCursorType(Gui::CURSOR_RESIZE_DOWN);
+ break;
+ case RIGHT:
+ case LEFT:
+ gui->setCursorType(Gui::CURSOR_RESIZE_ACROSS);
+ break;
+ default:
+ gui->setCursorType(Gui::CURSOR_POINTER);
}
}
@@ -366,31 +457,31 @@ void Window::mouseDragged(gcn::MouseEvent &event)
setPosition(newX, newY);
}
- if (mMouseResize && !mIsMoving)
+ if (mouseResize && !mIsMoving)
{
const int dx = event.getX() - mDragOffsetX;
const int dy = event.getY() - mDragOffsetY;
gcn::Rectangle newDim = getDimension();
- if (mMouseResize & (TOP | BOTTOM))
+ if (mouseResize & (TOP | BOTTOM))
{
- int newHeight = newDim.height + ((mMouseResize & TOP) ? -dy : dy);
+ int newHeight = newDim.height + ((mouseResize & TOP) ? -dy : dy);
newDim.height = std::min(mMaxWinHeight,
std::max(mMinWinHeight, newHeight));
- if (mMouseResize & TOP)
+ if (mouseResize & TOP)
{
newDim.y -= newDim.height - getHeight();
}
}
- if (mMouseResize & (LEFT | RIGHT))
+ if (mouseResize & (LEFT | RIGHT))
{
- int newWidth = newDim.width + ((mMouseResize & LEFT) ? -dx : dx);
+ int newWidth = newDim.width + ((mouseResize & LEFT) ? -dx : dx);
newDim.width = std::min(mMaxWinWidth,
std::max(mMinWinWidth, newWidth));
- if (mMouseResize & LEFT)
+ if (mouseResize & LEFT)
{
newDim.x -= newDim.width - getWidth();
}
@@ -417,11 +508,11 @@ void Window::mouseDragged(gcn::MouseEvent &event)
}
// Update mouse offset when dragging bottom or right border
- if (mMouseResize & BOTTOM)
+ if (mouseResize & BOTTOM)
{
mDragOffsetY += newDim.height - getHeight();
}
- if (mMouseResize & RIGHT)
+ if (mouseResize & RIGHT)
{
mDragOffsetX += newDim.width - getWidth();
}
@@ -469,3 +560,50 @@ void Window::resetToDefaultSize()
setContentSize(mDefaultWidth, mDefaultHeight);
updateContentSize();
}
+
+int Window::getResizeHandles(gcn::MouseEvent &event)
+{
+ int resizeHandles = 0;
+ const int y = event.getY();
+
+ if (mResizable && y > (int) mTitleBarHeight)
+ {
+ const int x = event.getX();
+
+ if (!getChildrenArea().isPointInRect(x, y) &&
+ event.getSource() == this)
+ {
+ resizeHandles |= (x > getWidth() - resizeBorderWidth) ? RIGHT :
+ (x < resizeBorderWidth) ? LEFT : 0;
+ resizeHandles |= (y > getHeight() - resizeBorderWidth) ? BOTTOM :
+ (y < resizeBorderWidth) ? TOP : 0;
+ }
+
+ if (event.getSource() == mGrip)
+ {
+ mDragOffsetX = x;
+ mDragOffsetY = y;
+ resizeHandles |= BOTTOM | RIGHT;
+ }
+ }
+
+ return resizeHandles;
+}
+
+void Window::fireWindowEvent(const WindowEvent &event)
+{
+ WindowListeners::iterator i_end = mListeners.end();
+ WindowListeners::iterator i = mListeners.begin();
+
+ switch (event.getType())
+ {
+ case WindowEvent::WINDOW_MOVED:
+ for (; i != i_end; ++i)
+ { (*i)->windowMoved(event); }
+ break;
+ case WindowEvent::WINDOW_RESIZED:
+ for (; i != i_end; ++i)
+ { (*i)->windowResized(event); }
+ break;
+ }
+}