summaryrefslogtreecommitdiff
path: root/src/gui/widgets/window.cpp
diff options
context:
space:
mode:
authorAndrei Karas <akaras@inbox.ru>2011-01-02 01:48:38 +0200
committerAndrei Karas <akaras@inbox.ru>2011-01-02 02:41:24 +0200
commit3eeae12c498d1a4dbe969462d2ba841f77ee3ccb (patch)
treeff8eab35e732bc0749fc11677c8873a7b3a58704 /src/gui/widgets/window.cpp
downloadmv-3eeae12c498d1a4dbe969462d2ba841f77ee3ccb.tar.gz
mv-3eeae12c498d1a4dbe969462d2ba841f77ee3ccb.tar.bz2
mv-3eeae12c498d1a4dbe969462d2ba841f77ee3ccb.tar.xz
mv-3eeae12c498d1a4dbe969462d2ba841f77ee3ccb.zip
Initial commit.
This code based on mana client http://www.gitorious.org/mana/mana and my private repository.
Diffstat (limited to 'src/gui/widgets/window.cpp')
-rw-r--r--src/gui/widgets/window.cpp924
1 files changed, 924 insertions, 0 deletions
diff --git a/src/gui/widgets/window.cpp b/src/gui/widgets/window.cpp
new file mode 100644
index 000000000..6564a8d3f
--- /dev/null
+++ b/src/gui/widgets/window.cpp
@@ -0,0 +1,924 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2004-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/widgets/window.h"
+
+#include "client.h"
+#include "configuration.h"
+#include "log.h"
+
+#include "gui/gui.h"
+#include "gui/palette.h"
+#include "gui/theme.h"
+#include "gui/viewport.h"
+
+#include "gui/widgets/layout.h"
+#include "gui/widgets/resizegrip.h"
+#include "gui/widgets/windowcontainer.h"
+
+#include "resources/image.h"
+
+#include <guichan/exception.hpp>
+#include <guichan/focushandler.hpp>
+
+int Window::instances = 0;
+int Window::mouseResize = 0;
+
+Window::Window(const std::string &caption, bool modal, Window *parent,
+ const std::string &skin):
+ gcn::Window(caption),
+ mGrip(0),
+ mParent(parent),
+ mLayout(NULL),
+ mWindowName("window"),
+ mShowTitle(true),
+ mModal(modal),
+ mCloseButton(false),
+ mDefaultVisible(false),
+ mSaveVisible(false),
+ mStickyButton(false),
+ mSticky(false),
+ mMinWinWidth(100),
+ mMinWinHeight(40),
+ mMaxWinWidth(graphics->getWidth()),
+ mMaxWinHeight(graphics->getHeight())
+{
+ logger->log("Window::Window(\"%s\")", caption.c_str());
+
+ if (!windowContainer)
+ throw GCN_EXCEPTION("Window::Window(): no windowContainer set");
+
+ instances++;
+
+ setFrameSize(0);
+ setPadding(3);
+ setTitleBarHeight(20);
+
+ // Loads the skin
+ mSkin = Theme::instance()->load(skin);
+
+ // Add this window to the window container
+ windowContainer->add(this);
+
+ if (mModal)
+ {
+ gui->setCursorType(Gui::CURSOR_POINTER);
+ requestModalFocus();
+ }
+
+ // Windows are invisible by default
+ setVisible(false);
+
+ addWidgetListener(this);
+}
+
+Window::~Window()
+{
+ logger->log("Window::~Window(\"%s\")", getCaption().c_str());
+
+ saveWindowState();
+
+ delete mLayout;
+ mLayout = 0;
+
+ while (!mWidgets.empty())
+ delete mWidgets.front();
+
+// need mWidgets.clean ?
+
+ removeWidgetListener(this);
+
+ instances--;
+
+ if (mSkin)
+ mSkin->instances--;
+}
+
+void Window::setWindowContainer(WindowContainer *wc)
+{
+ windowContainer = wc;
+}
+
+void Window::draw(gcn::Graphics *graphics)
+{
+ if (!mSkin)
+ return;
+
+ Graphics *g = static_cast<Graphics*>(graphics);
+
+ g->drawImageRect(0, 0, getWidth(), getHeight(), mSkin->getBorder());
+
+ // Draw title
+ if (mShowTitle)
+ {
+ g->setColor(Theme::getThemeColor(Theme::TEXT));
+ g->setFont(getFont());
+ g->drawText(getCaption(), 7, 5, gcn::Graphics::LEFT);
+ }
+
+ // Draw Close Button
+ if (mCloseButton && mSkin->getCloseImage())
+ {
+ g->drawImage(mSkin->getCloseImage(),
+ getWidth() - mSkin->getCloseImage()->getWidth() - getPadding(),
+ getPadding());
+ }
+
+ // Draw Sticky Button
+ if (mStickyButton)
+ {
+ Image *button = mSkin->getStickyImage(mSticky);
+ if (button)
+ {
+ int x = getWidth() - button->getWidth() - getPadding();
+ if (mCloseButton && mSkin->getCloseImage())
+ x -= mSkin->getCloseImage()->getWidth();
+
+ g->drawImage(button, x, getPadding());
+ }
+ }
+
+ drawChildren(graphics);
+}
+
+void Window::setContentSize(int width, int height)
+{
+ width = width + 2 * getPadding();
+ height = height + getPadding() + getTitleBarHeight();
+
+ if (getMinWidth() > width)
+ width = getMinWidth();
+ else if (getMaxWidth() < width)
+ width = getMaxWidth();
+ if (getMinHeight() > height)
+ height = getMinHeight();
+ else if (getMaxHeight() < height)
+ height = getMaxHeight();
+
+ setSize(width, height);
+}
+
+void Window::setLocationRelativeTo(gcn::Widget *widget)
+{
+ if (!widget)
+ return;
+
+ int wx, wy;
+ int x, y;
+
+ widget->getAbsolutePosition(wx, wy);
+ getAbsolutePosition(x, y);
+
+ setPosition(getX() + (wx + (widget->getWidth() - getWidth()) / 2 - x),
+ getY() + (wy + (widget->getHeight() - getHeight()) / 2 - y));
+}
+
+void Window::setLocationHorisontallyRelativeTo(gcn::Widget *widget)
+{
+ if (!widget)
+ return;
+
+ int wx, wy;
+ int x, y;
+
+ widget->getAbsolutePosition(wx, wy);
+ getAbsolutePosition(x, y);
+
+ setPosition(getX() + (wx + (widget->getWidth() - getWidth()) / 2 - x), 0);
+}
+
+void Window::setLocationRelativeTo(ImageRect::ImagePosition position,
+ int offsetX, int offsetY)
+{
+ if (position == ImageRect::UPPER_LEFT)
+ {
+ }
+ else if (position == ImageRect::UPPER_CENTER)
+ {
+ offsetX += (graphics->getWidth() - getWidth()) / 2;
+ }
+ else if (position == ImageRect::UPPER_RIGHT)
+ {
+ offsetX += graphics->getWidth() - getWidth();
+ }
+ else if (position == ImageRect::LEFT)
+ {
+ offsetY += (graphics->getHeight() - getHeight()) / 2;
+ }
+ else if (position == ImageRect::CENTER)
+ {
+ offsetX += (graphics->getWidth() - getWidth()) / 2;
+ offsetY += (graphics->getHeight() - getHeight()) / 2;
+ }
+ else if (position == ImageRect::RIGHT)
+ {
+ offsetX += graphics->getWidth() - getWidth();
+ offsetY += (graphics->getHeight() - getHeight()) / 2;
+ }
+ else if (position == ImageRect::LOWER_LEFT)
+ {
+ offsetY += graphics->getHeight() - getHeight();
+ }
+ else if (position == ImageRect::LOWER_CENTER)
+ {
+ offsetX += (graphics->getWidth() - getWidth()) / 2;
+ offsetY += graphics->getHeight() - getHeight();
+ }
+ else if (position == ImageRect::LOWER_RIGHT)
+ {
+ offsetX += graphics->getWidth() - getWidth();
+ offsetY += graphics->getHeight() - getHeight();
+ }
+
+ setPosition(offsetX, offsetY);
+}
+
+void Window::setMinWidth(int width)
+{
+ mMinWinWidth = width > mSkin->getMinWidth() ? width : mSkin->getMinWidth();
+}
+
+void Window::setMinHeight(int height)
+{
+ mMinWinHeight = height > mSkin->getMinHeight() ?
+ height : mSkin->getMinHeight();
+}
+
+void Window::setMaxWidth(int width)
+{
+ mMaxWinWidth = width;
+}
+
+void Window::setMaxHeight(int height)
+{
+ mMaxWinHeight = height;
+}
+
+void Window::setResizable(bool r)
+{
+ if (static_cast<bool>(mGrip) == r)
+ return;
+
+ if (r)
+ {
+ mGrip = new ResizeGrip;
+ mGrip->setX(getWidth() - mGrip->getWidth() - getChildrenArea().x);
+ mGrip->setY(getHeight() - mGrip->getHeight() - getChildrenArea().y);
+ add(mGrip);
+ }
+ else
+ {
+ remove(mGrip);
+ delete mGrip;
+ mGrip = 0;
+ }
+}
+
+void Window::widgetResized(const gcn::Event &event _UNUSED_)
+{
+ const gcn::Rectangle area = getChildrenArea();
+
+ if (mGrip)
+ {
+ mGrip->setPosition(getWidth() - mGrip->getWidth() - area.x,
+ getHeight() - mGrip->getHeight() - area.y);
+ }
+
+ if (mLayout)
+ {
+ int w = area.width;
+ int h = area.height;
+ mLayout->reflow(w, h);
+ }
+}
+
+void Window::widgetHidden(const gcn::Event &event _UNUSED_)
+{
+ if (gui)
+ gui->setCursorType(Gui::CURSOR_POINTER);
+
+ WidgetListIterator it;
+
+ if (!mFocusHandler)
+ return;
+
+ for (it = mWidgets.begin(); it != mWidgets.end(); it++)
+ {
+ if (mFocusHandler->isFocused(*it))
+ mFocusHandler->focusNone();
+ }
+}
+
+void Window::setCloseButton(bool flag)
+{
+ mCloseButton = flag;
+}
+
+bool Window::isResizable() const
+{
+ return mGrip;
+}
+
+void Window::setStickyButton(bool flag)
+{
+ mStickyButton = flag;
+}
+
+void Window::setSticky(bool sticky)
+{
+ mSticky = sticky;
+}
+
+void Window::setVisible(bool visible)
+{
+ setVisible(visible, false);
+}
+
+void Window::setVisible(bool visible, bool forceSticky)
+{
+ if (visible == isVisible())
+ return; // Nothing to do
+
+ // Check if the window is off screen...
+ if (visible)
+ checkIfIsOffScreen();
+
+ gcn::Window::setVisible((!forceSticky && isSticky()) || visible);
+}
+
+void Window::scheduleDelete()
+{
+ windowContainer->scheduleDelete(this);
+}
+
+void Window::mousePressed(gcn::MouseEvent &event)
+{
+ // Let Guichan move window to top and figure out title bar drag
+ gcn::Window::mousePressed(event);
+
+ if (event.getButton() == gcn::MouseEvent::LEFT)
+ {
+ const int x = event.getX();
+ const int y = event.getY();
+
+ // Handle close button
+ if (mCloseButton)
+ {
+ Image *img = mSkin->getCloseImage();
+ if (img)
+ {
+ gcn::Rectangle closeButtonRect(
+ getWidth() - img->getWidth()
+ - getPadding(), getPadding(),
+ img->getWidth(), img->getHeight());
+
+ if (closeButtonRect.isPointInRect(x, y))
+ {
+ mouseResize = 0;
+ mMoved = 0;
+ close();
+ return;
+ }
+ }
+ }
+
+ // Handle sticky button
+ if (mStickyButton)
+ {
+ Image *button = mSkin->getStickyImage(mSticky);
+ if (button)
+ {
+ int rx = getWidth() - button->getWidth() - getPadding();
+ if (mCloseButton)
+ {
+ Image *img = mSkin->getCloseImage();
+ if (img)
+ rx -= img->getWidth();
+ }
+ gcn::Rectangle stickyButtonRect(rx, getPadding(),
+ button->getWidth(), button->getHeight());
+ if (stickyButtonRect.isPointInRect(x, y))
+ {
+ setSticky(!isSticky());
+ mouseResize = 0;
+ mMoved = 0;
+ return;
+ }
+ }
+ }
+
+ // Handle window resizing
+ mouseResize = getResizeHandles(event);
+ mMoved = !mouseResize;
+ }
+}
+
+void Window::close()
+{
+ setVisible(false);
+}
+
+void Window::mouseReleased(gcn::MouseEvent &event _UNUSED_)
+{
+ if (mGrip && mouseResize)
+ {
+ mouseResize = 0;
+ if (gui)
+ gui->setCursorType(Gui::CURSOR_POINTER);
+ }
+
+ // This should be the responsibility of Guichan (and is from 0.8.0 on)
+ mMoved = false;
+}
+
+void Window::mouseExited(gcn::MouseEvent &event _UNUSED_)
+{
+ if (mGrip && !mouseResize && gui)
+ gui->setCursorType(Gui::CURSOR_POINTER);
+}
+
+void Window::mouseMoved(gcn::MouseEvent &event)
+{
+ if (!gui)
+ return;
+
+ int resizeHandles = getResizeHandles(event);
+
+ // Changes the custom mouse cursor based on it's current position.
+ switch (resizeHandles)
+ {
+ case BOTTOM | RIGHT:
+ case TOP | LEFT:
+ gui->setCursorType(Gui::CURSOR_RESIZE_DOWN_RIGHT);
+ break;
+ case TOP | RIGHT:
+ case BOTTOM | LEFT:
+ gui->setCursorType(Gui::CURSOR_RESIZE_DOWN_LEFT);
+ break;
+ case BOTTOM:
+ case TOP:
+ gui->setCursorType(Gui::CURSOR_RESIZE_DOWN);
+ break;
+ case RIGHT:
+ case LEFT:
+ gui->setCursorType(Gui::CURSOR_RESIZE_ACROSS);
+ break;
+ default:
+ gui->setCursorType(Gui::CURSOR_POINTER);
+ }
+
+ if (viewport)
+ viewport->hideBeingPopup();
+}
+
+void Window::mouseDragged(gcn::MouseEvent &event)
+{
+ // Let Guichan handle title bar drag
+ gcn::Window::mouseDragged(event);
+
+ // Keep guichan window inside screen when it may be moved
+ if (isMovable() && mMoved)
+ {
+ int newX = std::max(0, getX());
+ int newY = std::max(0, getY());
+ newX = std::min(graphics->getWidth() - getWidth(), newX);
+ newY = std::min(graphics->getHeight() - getHeight(), newY);
+ setPosition(newX, newY);
+ }
+
+ if (mouseResize && !mMoved)
+ {
+ const int dx = event.getX() - mDragOffsetX;
+ const int dy = event.getY() - mDragOffsetY;
+ gcn::Rectangle newDim = getDimension();
+
+ if (mouseResize & (TOP | BOTTOM))
+ {
+ int newHeight = newDim.height + ((mouseResize & TOP) ? -dy : dy);
+ newDim.height = std::min(mMaxWinHeight,
+ std::max(mMinWinHeight, newHeight));
+
+ if (mouseResize & TOP)
+ newDim.y -= newDim.height - getHeight();
+ }
+
+ if (mouseResize & (LEFT | RIGHT))
+ {
+ int newWidth = newDim.width + ((mouseResize & LEFT) ? -dx : dx);
+ newDim.width = std::min(mMaxWinWidth,
+ std::max(mMinWinWidth, newWidth));
+
+ if (mouseResize & LEFT)
+ newDim.x -= newDim.width - getWidth();
+ }
+
+ // Keep guichan window inside screen (supports resizing any side)
+ if (newDim.x < 0)
+ {
+ newDim.width += newDim.x;
+ newDim.x = 0;
+ }
+ if (newDim.y < 0)
+ {
+ newDim.height += newDim.y;
+ newDim.y = 0;
+ }
+ if (newDim.x + newDim.width > graphics->getWidth())
+ {
+ newDim.width = graphics->getWidth() - newDim.x;
+ }
+ if (newDim.y + newDim.height > graphics->getHeight())
+ {
+ newDim.height = graphics->getHeight() - newDim.y;
+ }
+
+ // Update mouse offset when dragging bottom or right border
+ if (mouseResize & BOTTOM)
+ mDragOffsetY += newDim.height - getHeight();
+
+ if (mouseResize & RIGHT)
+ mDragOffsetX += newDim.width - getWidth();
+
+ // Set the new window and content dimensions
+ setDimension(newDim);
+ }
+}
+
+void Window::setModal(bool modal)
+{
+ if (mModal != modal)
+ {
+ mModal = modal;
+ if (mModal)
+ {
+ if (gui)
+ gui->setCursorType(Gui::CURSOR_POINTER);
+ requestModalFocus();
+ }
+ else
+ {
+ releaseModalFocus();
+ }
+ }
+}
+
+void Window::loadWindowState()
+{
+ const std::string &name = mWindowName;
+ assert(!name.empty());
+
+ setPosition(config.getValueInt(name + "WinX", mDefaultX),
+ config.getValueInt(name + "WinY", mDefaultY));
+
+ if (mSaveVisible)
+ {
+ setVisible(config.getValueBool(name
+ + "Visible", mDefaultVisible));
+ }
+
+ if (mStickyButton)
+ {
+ setSticky(config.getValueBool(name
+ + "Sticky", isSticky()));
+ }
+
+ if (mGrip)
+ {
+ int width = config.getValueInt(name + "WinWidth", mDefaultWidth);
+ int height = config.getValueInt(name + "WinHeight", mDefaultHeight);
+
+ if (getMinWidth() > width)
+ width = getMinWidth();
+ else if (getMaxWidth() < width)
+ width = getMaxWidth();
+ if (getMinHeight() > height)
+ height = getMinHeight();
+ else if (getMaxHeight() < height)
+ height = getMaxHeight();
+
+ setSize(width, height);
+ }
+ else
+ {
+ setSize(mDefaultWidth, mDefaultHeight);
+ }
+
+ // Check if the window is off screen...
+ checkIfIsOffScreen();
+}
+
+void Window::saveWindowState()
+{
+ // Saving X, Y and Width and Height for resizables in the config
+ if (!mWindowName.empty() && mWindowName != "window")
+ {
+ config.setValue(mWindowName + "WinX", getX());
+ config.setValue(mWindowName + "WinY", getY());
+
+ if (mSaveVisible)
+ config.setValue(mWindowName + "Visible", isVisible());
+
+ if (mStickyButton)
+ config.setValue(mWindowName + "Sticky", isSticky());
+
+ if (mGrip)
+ {
+ if (getMinWidth() > getWidth())
+ setWidth(getMinWidth());
+ else if (getMaxWidth() < getWidth())
+ setWidth(getMaxWidth());
+ if (getMinHeight() > getHeight())
+ setHeight(getMinHeight());
+ else if (getMaxHeight() < getHeight())
+ setHeight(getMaxHeight());
+
+ config.setValue(mWindowName + "WinWidth", getWidth());
+ config.setValue(mWindowName + "WinHeight", getHeight());
+ }
+ }
+}
+
+void Window::setDefaultSize(int defaultX, int defaultY,
+ int defaultWidth, int defaultHeight)
+{
+ if (getMinWidth() > defaultWidth)
+ defaultWidth = getMinWidth();
+ else if (getMaxWidth() < defaultWidth)
+ defaultWidth = getMaxWidth();
+ if (getMinHeight() > defaultHeight)
+ defaultHeight = getMinHeight();
+ else if (getMaxHeight() < defaultHeight)
+ defaultHeight = getMaxHeight();
+
+ mDefaultX = defaultX;
+ mDefaultY = defaultY;
+ mDefaultWidth = defaultWidth;
+ mDefaultHeight = defaultHeight;
+}
+
+void Window::setDefaultSize()
+{
+ mDefaultX = getX();
+ mDefaultY = getY();
+ mDefaultWidth = getWidth();
+ mDefaultHeight = getHeight();
+}
+
+void Window::setDefaultSize(int defaultWidth, int defaultHeight,
+ ImageRect::ImagePosition position,
+ int offsetX, int offsetY)
+{
+ int x = 0, y = 0;
+
+ if (position == ImageRect::UPPER_LEFT)
+ {
+ }
+ else if (position == ImageRect::UPPER_CENTER)
+ {
+ x = (graphics->getWidth() - defaultWidth) / 2;
+ }
+ else if (position == ImageRect::UPPER_RIGHT)
+ {
+ x = graphics->getWidth() - defaultWidth;
+ }
+ else if (position == ImageRect::LEFT)
+ {
+ y = (graphics->getHeight() - defaultHeight) / 2;
+ }
+ else if (position == ImageRect::CENTER)
+ {
+ x = (graphics->getWidth() - defaultWidth) / 2;
+ y = (graphics->getHeight() - defaultHeight) / 2;
+ }
+ else if (position == ImageRect::RIGHT)
+ {
+ x = graphics->getWidth() - defaultWidth;
+ y = (graphics->getHeight() - defaultHeight) / 2;
+ }
+ else if (position == ImageRect::LOWER_LEFT)
+ {
+ y = graphics->getHeight() - defaultHeight;
+ }
+ else if (position == ImageRect::LOWER_CENTER)
+ {
+ x = (graphics->getWidth() - defaultWidth) / 2;
+ y = graphics->getHeight() - defaultHeight;
+ }
+ else if (position == ImageRect::LOWER_RIGHT)
+ {
+ x = graphics->getWidth() - defaultWidth;
+ y = graphics->getHeight() - defaultHeight;
+ }
+
+ mDefaultX = x - offsetX;
+ mDefaultY = y - offsetY;
+ mDefaultWidth = defaultWidth;
+ mDefaultHeight = defaultHeight;
+}
+
+void Window::resetToDefaultSize()
+{
+ setPosition(mDefaultX, mDefaultY);
+ setSize(mDefaultWidth, mDefaultHeight);
+ saveWindowState();
+}
+
+int Window::getResizeHandles(gcn::MouseEvent &event)
+{
+ int resizeHandles = 0;
+ const int y = event.getY();
+
+ if (mGrip && (y > static_cast<int>(mTitleBarHeight)
+ || (y < (int)getPadding() && mTitleBarHeight > getPadding())))
+ {
+ const int x = event.getX();
+
+ if (!getWindowArea().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;
+}
+
+bool Window::isResizeAllowed(gcn::MouseEvent &event)
+{
+ const int y = event.getY();
+
+ if (mGrip && (y > static_cast<int>(mTitleBarHeight)
+ || y < (int)getPadding()))
+ {
+ const int x = event.getX();
+
+ if (!getWindowArea().isPointInRect(x, y) && event.getSource() == this)
+ return true;
+
+ if (event.getSource() == mGrip)
+ return true;
+ }
+
+ return false;
+}
+
+int Window::getGuiAlpha()
+{
+ float alpha = std::max(Client::getGuiAlpha(),
+ Theme::instance()->getMinimumOpacity());
+ return static_cast<int>(alpha * 255.0f);
+}
+
+Layout &Window::getLayout()
+{
+ if (!mLayout)
+ mLayout = new Layout;
+ return *mLayout;
+}
+
+void Window::clearLayout()
+{
+ clear();
+
+ // Restore the resize grip
+ if (mGrip)
+ add(mGrip);
+
+ // Recreate layout instance when one is present
+ if (mLayout)
+ {
+ delete mLayout;
+ mLayout = new Layout;
+ }
+}
+
+LayoutCell &Window::place(int x, int y, gcn::Widget *wg, int w, int h)
+{
+ add(wg);
+ return getLayout().place(wg, x, y, w, h);
+}
+
+ContainerPlacer Window::getPlacer(int x, int y)
+{
+ return ContainerPlacer(this, &getLayout().at(x, y));
+}
+
+void Window::reflowLayout(int w, int h)
+{
+ if (!mLayout)
+ return;
+
+ mLayout->reflow(w, h);
+ delete mLayout;
+ mLayout = 0;
+ setContentSize(w, h);
+}
+
+void Window::redraw()
+{
+ if (mLayout)
+ {
+ const gcn::Rectangle area = getChildrenArea();
+ int w = area.width;
+ int h = area.height;
+ mLayout->reflow(w, h);
+ }
+}
+
+void Window::center()
+{
+ setLocationRelativeTo(getParent());
+}
+
+void Window::centerHorisontally()
+{
+ setLocationHorisontallyRelativeTo(getParent());
+}
+
+void Window::checkIfIsOffScreen(bool partially, bool entirely)
+{
+ // Move the window onto screen if it has become off screen
+ // For instance, because of resolution change...
+
+ // First of all, don't deal when a window hasn't got
+ // any size initialized yet...
+ if (getWidth() == 0 && getHeight() == 0)
+ return;
+
+ // Made partially the default behaviour
+ if (!partially && !entirely)
+ partially = true;
+
+ // Keep guichan window inside screen (supports resizing any side)
+
+ gcn::Rectangle winDimension = getDimension();
+
+ if (winDimension.x < 0)
+ {
+ winDimension.width += winDimension.x;
+ winDimension.x = 0;
+ }
+ if (winDimension.y < 0)
+ {
+ winDimension.height += winDimension.y;
+ winDimension.y = 0;
+ }
+
+ // Look if the window is partially off-screen limits...
+ if (partially)
+ {
+ if (winDimension.x + winDimension.width > graphics->getWidth())
+ winDimension.x = graphics->getWidth() - winDimension.width;
+
+ if (winDimension.y + winDimension.height > graphics->getHeight())
+ winDimension.y = graphics->getHeight() - winDimension.height;
+
+ setDimension(winDimension);
+ return;
+ }
+
+ if (entirely)
+ {
+ if (winDimension.x > graphics->getWidth())
+ winDimension.x = graphics->getWidth() - winDimension.width;
+
+ if (winDimension.y > graphics->getHeight())
+ winDimension.y = graphics->getHeight() - winDimension.height;
+ }
+ setDimension(winDimension);
+}
+
+gcn::Rectangle Window::getWindowArea()
+{
+ return gcn::Rectangle(getPadding(),
+ getPadding(),
+ getWidth() - getPadding() * 2,
+ getHeight() - getPadding() * 2);
+} \ No newline at end of file