From c322e6eac2373358c04e7bd70c8e0fc1bcfb37db Mon Sep 17 00:00:00 2001 From: Joshua Langley Date: Mon, 20 Aug 2007 05:29:12 +0000 Subject: Added close button functionality, resize cursor cues. --- ChangeLog | 10 ++- data/graphics/gui/close_button.png | Bin 0 -> 650 bytes data/graphics/gui/mouse.png | Bin 1134 -> 4508 bytes src/gui/equipmentwindow.cpp | 1 + src/gui/gui.cpp | 21 +++-- src/gui/gui.h | 35 +++++++- src/gui/inventorywindow.cpp | 1 + src/gui/setup.cpp | 3 +- src/gui/skill.cpp | 6 +- src/gui/skill.h | 1 - src/gui/status.cpp | 1 + src/gui/window.cpp | 164 +++++++++++++++++++++++++++++++------ src/gui/window.h | 31 ++++++- 13 files changed, 228 insertions(+), 46 deletions(-) create mode 100644 data/graphics/gui/close_button.png diff --git a/ChangeLog b/ChangeLog index edec977c..a04f6f77 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,12 @@ -2007-08-19 Bjørn Lindeijer +2007-08-20 Joshua Langley + + * data/graphics/gui/mouse.png, src/gui/equipmentwindow.cpp, src/gui/gui.cpp, + src/gui/gui.h, src/gui/inventorywindow.cpp, src/gui/setup.cpp, + src/gui/skill.cpp, src/gui/skill.h, src/gui/status.cpp, src/gui/window.cpp, + src/gui/window.h, data/graphics/gui/close_button.png: Added close button + functionality, resize cursor cues. + +2007-08-19 Bjørn Lindeijer * data/equipment.xml: Fixed typo in female light plate mail. * NEWS: Updated with changes since 0.0.23. diff --git a/data/graphics/gui/close_button.png b/data/graphics/gui/close_button.png new file mode 100644 index 00000000..f87cc2a9 Binary files /dev/null and b/data/graphics/gui/close_button.png differ diff --git a/data/graphics/gui/mouse.png b/data/graphics/gui/mouse.png index 2eeb0e51..84dc2ad1 100644 Binary files a/data/graphics/gui/mouse.png and b/data/graphics/gui/mouse.png differ diff --git a/src/gui/equipmentwindow.cpp b/src/gui/equipmentwindow.cpp index ec84491e..78727ff8 100644 --- a/src/gui/equipmentwindow.cpp +++ b/src/gui/equipmentwindow.cpp @@ -37,6 +37,7 @@ EquipmentWindow::EquipmentWindow(Equipment *equipment): Window("Equipment"), mEquipment(equipment) { setWindowName("Equipment"); + setCloseButton(true); setDefaultSize(5, 230, 200, 120); loadWindowState(); } diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 60d5ae8a..ba9aa930 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -44,7 +44,7 @@ #include "../graphics.h" #include "../log.h" -#include "../resources/image.h" +#include "../resources/imageset.h" #include "../resources/resourcemanager.h" #include "../resources/sdlimageloader.h" @@ -59,6 +59,7 @@ gcn::Font *hitBlueFont; gcn::Font *hitYellowFont; // Font used to display speech and player names gcn::Font *speechFont; +ImageSet *Gui::mMouseCursor = NULL; class GuiConfigListener : public ConfigListener { @@ -80,7 +81,6 @@ class GuiConfigListener : public ConfigListener Gui::Gui(Graphics *graphics): mHostImageLoader(NULL), - mMouseCursor(NULL), mCustomCursor(false) { logger->log("Initializing GUI..."); @@ -180,8 +180,8 @@ Gui::~Gui() if (mMouseCursor) { mMouseCursor->decRef(); + mMouseCursor = NULL; } - delete mGuiFont; delete speechFont; delete viewport; @@ -210,9 +210,11 @@ Gui::draw() if ((SDL_GetAppState() & SDL_APPMOUSEFOCUS || button & SDL_BUTTON(1)) && mCustomCursor) { - dynamic_cast(mGraphics)->drawImage(mMouseCursor, - mouseX - 5, - mouseY - 2); + + static_cast(mGraphics)->drawImage( + mMouseCursor->get(mCursorType), + mouseX - 15, + mouseY - 17); } mGraphics->popClipArea(); @@ -232,10 +234,13 @@ Gui::setUseCustomCursor(bool customCursor) // Load the mouse cursor ResourceManager *resman = ResourceManager::getInstance(); - mMouseCursor = resman->getImage("graphics/gui/mouse.png"); + mMouseCursor = + resman->getImageSet("graphics/gui/mouse.png", 40, 40); + if (!mMouseCursor) { - logger->error("Unable to load mouse cursor."); + logger->error("Unable to load mouse cursors."); } + mCursorType = CURSOR_POINTER; } else { diff --git a/src/gui/gui.h b/src/gui/gui.h index caf27744..21b10454 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -30,7 +30,7 @@ class GuiConfigListener; class Graphics; -class Image; +class ImageSet; class Viewport; /** @@ -84,13 +84,44 @@ class Gui : public gcn::Gui void setUseCustomCursor(bool customCursor); + /** + * Sets which cursor should be used. + */ + void setCursorType(int index) + { + mCursorType = index; + } + + /** + * Gets the custom cursor flag. + */ + bool isCustomCursor() + { + return mCustomCursor; + } + + /** + * Cursors are in graphic order from left to right. + * CURSOR_POINTER should be left untouched. + * CURSOR_TOTAL should always be last. + */ + enum{ + CURSOR_POINTER = 0, + CURSOR_RESIZE_ACROSS, + CURSOR_RESIZE_DOWN, + CURSOR_RESIZE_DOWN_LEFT, + CURSOR_RESIZE_DOWN_RIGHT, + CURSOR_TOTAL + }; private: GuiConfigListener *mConfigListener; gcn::ImageLoader *mHostImageLoader; /**< For loading images in GL */ gcn::ImageLoader *mImageLoader; /**< For loading images */ gcn::Font *mGuiFont; /**< The global GUI font */ - Image *mMouseCursor; /**< Mouse cursor image */ bool mCustomCursor; /**< Show custom cursor */ + int mCursorType; + + static ImageSet *mMouseCursor; /**< Mouse cursor images */ }; extern Gui *gui; /**< The GUI system */ diff --git a/src/gui/inventorywindow.cpp b/src/gui/inventorywindow.cpp index 982aaaf3..da391a7b 100644 --- a/src/gui/inventorywindow.cpp +++ b/src/gui/inventorywindow.cpp @@ -48,6 +48,7 @@ InventoryWindow::InventoryWindow(): { setWindowName("Inventory"); setResizable(true); + setCloseButton(true); setMinWidth(240); setMinHeight(172); // If you adjust these defaults, don't forget to adjust the trade window's. diff --git a/src/gui/setup.cpp b/src/gui/setup.cpp index 1c17c50e..7142c76b 100644 --- a/src/gui/setup.cpp +++ b/src/gui/setup.cpp @@ -43,7 +43,8 @@ extern Window *skillDialog; Setup::Setup(): Window("Setup") { - int width = 260; + setCloseButton(true); + int width = 250; int height = 245; setContentSize(width, height); diff --git a/src/gui/skill.cpp b/src/gui/skill.cpp index 1b00a732..6406dd2a 100644 --- a/src/gui/skill.cpp +++ b/src/gui/skill.cpp @@ -64,6 +64,7 @@ SkillDialog::SkillDialog(): Window("Skills") { setWindowName("Skills"); + setCloseButton(true); setDefaultSize(windowContainer->getWidth() - 255, 25, 240, 240); mSkillListBox = new ListBox(this); @@ -72,7 +73,6 @@ SkillDialog::SkillDialog(): mIncButton = new Button("Up", "inc", this); mUseButton = new Button("Use", "use", this); mUseButton->setEnabled(false); - mCloseButton = new Button("Close", "close", this); mSkillListBox->setActionEventId("skill"); @@ -82,15 +82,11 @@ SkillDialog::SkillDialog(): mIncButton->setPosition(skillScrollArea->getX(), 210); mUseButton->setPosition(mIncButton->getX() + mIncButton->getWidth() + 5, 210); - mCloseButton->setPosition( - skillScrollArea->getX() + skillScrollArea->getWidth() - mCloseButton->getWidth(), - 210); add(skillScrollArea); add(mPointsLabel); add(mIncButton); add(mUseButton); - add(mCloseButton); mSkillListBox->addActionListener(this); diff --git a/src/gui/skill.h b/src/gui/skill.h index ed1257b0..6879640c 100644 --- a/src/gui/skill.h +++ b/src/gui/skill.h @@ -74,7 +74,6 @@ class SkillDialog : public Window, public gcn::ActionListener, gcn::Label *mPointsLabel; gcn::Button *mIncButton; gcn::Button *mUseButton; - gcn::Button *mCloseButton; std::vector mSkillList; }; diff --git a/src/gui/status.cpp b/src/gui/status.cpp index 6bd696ec..117e90de 100644 --- a/src/gui/status.cpp +++ b/src/gui/status.cpp @@ -39,6 +39,7 @@ StatusWindow::StatusWindow(LocalPlayer *player): { setWindowName("Status"); setResizable(true); + setCloseButton(true); setDefaultSize((windowContainer->getWidth() - 365) / 2, (windowContainer->getHeight() - 255) / 2, 365, 255); loadWindowState(); diff --git a/src/gui/window.cpp b/src/gui/window.cpp index 9f9ce9fc..a4c81bc7 100644 --- a/src/gui/window.cpp +++ b/src/gui/window.cpp @@ -26,6 +26,7 @@ #include #include +#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 { @@ -62,7 +65,7 @@ Window::Window(const std::string& caption, bool modal, Window *parent): mShowTitle(true), mModal(modal), mResizable(false), - mMouseResize(0), + mCloseButton(false), mSticky(false), mMinWinWidth(100), mMinWinHeight(40), @@ -90,6 +93,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"); @@ -112,6 +117,10 @@ Window::Window(const std::string& caption, bool modal, Window *parent): if (mModal) { + if (gui->isCustomCursor()) + { + gui->setCursorType(Gui::CURSOR_POINTER); + } requestModalFocus(); } @@ -152,6 +161,9 @@ Window::~Window() delete border.grid[6]; delete border.grid[7]; delete border.grid[8]; + + closeImage->decRef(); + closeImage = NULL; } delete mChrome; @@ -172,10 +184,18 @@ void Window::draw(gcn::Graphics *graphics) // Draw title if (mShowTitle) { - graphics->setFont(getFont()); - graphics->drawText(getCaption(), 7, 5, gcn::Graphics::LEFT); + 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); } @@ -278,6 +298,11 @@ void Window::setResizable(bool r) } } +void Window::setCloseButton(bool flag) +{ + mCloseButton = flag; +} + bool Window::isResizable() { return mResizable; @@ -327,25 +352,112 @@ void Window::mousePressed(gcn::MouseEvent &event) const int x = event.getX(); const int y = event.getY(); - mMouseResize = 0; + mouseResize = 0; - // Activate resizing handles as appropriate - if (event.getSource() == this && isResizable() && - event.getButton() == gcn::MouseEvent::LEFT && + if (event.getButton() == gcn::MouseEvent::LEFT) + { + // Close Button Handler + if (mCloseButton) + { + gcn::Rectangle tCloseButtonRect( + getWidth() - closeImage->getWidth() - getPadding(), + getPadding(), + closeImage->getWidth(), + closeImage->getHeight() + ); + if (tCloseButtonRect.isPointInRect(x, y)) + { + setVisible(false); + return; + } + } + // Resize Window Handler + if (mResizable && + event.getSource() == this && !getChildrenArea().isPointInRect(x, y)) + { + mouseResize |= (x > getWidth() - resizeBorderWidth) ? RIGHT : + (x < resizeBorderWidth) ? LEFT : 0; + mouseResize |= (y > getHeight() - resizeBorderWidth) ? BOTTOM : + (y < resizeBorderWidth) ? TOP : 0; + return; + } + if (event.getSource() == mGrip && + event.getButton() == gcn::MouseEvent::LEFT) + { + mDragOffsetX = x; + mDragOffsetY = y; + mouseResize |= BOTTOM | RIGHT; + mIsMoving = false; + } + } +} + +void Window::mouseReleased(gcn::MouseEvent &event) +{ + if (mResizable && + mouseResize && + gui->isCustomCursor()) { - mMouseResize |= (x > getWidth() - resizeBorderWidth) ? RIGHT : - (x < resizeBorderWidth) ? LEFT : 0; - mMouseResize |= (y > getHeight() - resizeBorderWidth) ? BOTTOM : - (y < resizeBorderWidth) ? TOP : 0; + mouseResize = 0; + gui->setCursorType(Gui::CURSOR_POINTER); } - else if (event.getSource() == mGrip && - event.getButton() == gcn::MouseEvent::LEFT) +} + +void Window::mouseExited(gcn::MouseEvent &event) +{ + if (mResizable && + !mouseResize && + gui->isCustomCursor()) { - mDragOffsetX = x; - mDragOffsetY = y; - mMouseResize |= BOTTOM | RIGHT; - mIsMoving = false; + gui->setCursorType(Gui::CURSOR_POINTER); + } +} + +void Window::mouseMoved(gcn::MouseEvent &event) +{ + const int x = event.getX(); + const int y = event.getY(); + + // changes the custom mouse cursor based on it's current position. + if (mResizable && + !mouseResize && + gui->isCustomCursor()) + { + gcn::Rectangle tContainerRect( + getPadding(), + getPadding(), + getWidth()-(getPadding() * 2), + getHeight()-(getPadding() * 2) + ); + if (!tContainerRect.isPointInRect(x, y)) + { + int tMouseResize = 0; + tMouseResize |= (x > getWidth() - resizeBorderWidth) ? RIGHT : + (x < resizeBorderWidth) ? LEFT : 0; + tMouseResize |= (y > getHeight() - resizeBorderWidth) ? BOTTOM : + (y < resizeBorderWidth) ? TOP : 0; + switch (tMouseResize) + { + 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; + } + } + else + { + gui->setCursorType(Gui::CURSOR_POINTER); + } } } @@ -364,31 +476,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(); } @@ -415,11 +527,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(); } diff --git a/src/gui/window.h b/src/gui/window.h index 1180d91c..a44a56d8 100644 --- a/src/gui/window.h +++ b/src/gui/window.h @@ -33,6 +33,7 @@ class GCContainer; class ImageRect; class ResizeGrip; class WindowContainer; +class Image; /** * A window. This window can be dragged around and has a title bar. Windows are @@ -119,10 +120,15 @@ class Window : public gcn::Window void setLocationRelativeTo(gcn::Widget *widget); /** - * Sets whether of not the window can be resized. + * Sets whether or not the window can be resized. */ void setResizable(bool resize); + /** + * Sets whether or not the window has a close button. + */ + void setCloseButton(bool flag); + /** * Returns whether the window can be resized. */ @@ -192,6 +198,24 @@ class Window : public gcn::Window */ void mouseDragged(gcn::MouseEvent &event); + /** + * Implements custom cursor image changing context, + * based on mouse relative position. + */ + void mouseMoved(gcn::MouseEvent &event); + + /** + * When the mouse button has been let go, this ensures that the mouse + * custom cursor is restored back to it's standard image. + */ + void mouseReleased(gcn::MouseEvent &event); + + /** + * When the mouse leaves the window this ensures that the custom cursor + * is restored back to it's standard image. + */ + void mouseExited(gcn::MouseEvent &event); + /** * Sets the name of the window. This is not the window title. */ @@ -243,7 +267,7 @@ class Window : public gcn::Window bool mShowTitle; /**< Window has a title bar */ bool mModal; /**< Window is modal */ bool mResizable; /**< Window can be resized */ - int mMouseResize; /**< Window is being resized */ + bool mCloseButton; /**< Window has a close button */ bool mSticky; /**< Window resists minimization */ int mMinWinWidth; /**< Minimum window width */ int mMinWinHeight; /**< Minimum window height */ @@ -263,6 +287,7 @@ class Window : public gcn::Window static ConfigListener *windowConfigListener; static int instances; /**< Number of Window instances */ + static int mouseResize; /**< Window is being resized */ static ImageRect border; /**< The window border and background */ /** @@ -271,6 +296,8 @@ class Window : public gcn::Window * where two borders are moved at the same time. */ static const int resizeBorderWidth = 10; + static Image *closeImage; /**< Close Button Image */ + }; #endif -- cgit v1.2.3-60-g2f50