diff -abBdpuNPr --exclude='*.svn' irrlicht-svn-ss/trunk/include/EWindowFlags.h Irrlicht_starsonata/include/EWindowFlags.h --- irrlicht-svn-ss/trunk/include/EWindowFlags.h 1970-01-01 01:00:00.000000000 +0100 +++ Irrlicht_starsonata/include/EWindowFlags.h 2008-05-31 04:15:24.000000000 +0200 @@ -0,0 +1,30 @@ +// Copyright (C) 2007 StarSonata + +#ifndef __E_WINDOW_FLAGS_H_INCLUDED__ +#define __E_WINDOW_FLAGS_H_INCLUDED__ + +namespace irr +{ +namespace gui +{ + + //! enumeration for windows layout flags + enum EWINDOW_FLAG + { + //! Flag for close button + EWF_CLOSE = 0x1, + + //! Flag for title bar of windows + EWF_TITLEBAR = 0x2, + + //! Flag for maximize button + EWF_MAXIMIZE = 0x4, + + //! Flag for minimize button + EWF_MINIMIZE = 0x8, + }; + +} // namespace gui +} // namespace irr + +#endif diff -abBdpuNPr --exclude='*.svn' irrlicht-svn-ss/trunk/include/IGUIWindow.h Irrlicht_starsonata/include/IGUIWindow.h --- irrlicht-svn-ss/trunk/include/IGUIWindow.h 2007-07-26 02:11:22.000000000 +0200 +++ Irrlicht_starsonata/include/IGUIWindow.h 2008-05-31 04:53:20.000000000 +0200 @@ -7,6 +7,7 @@ #include "IGUIElement.h" #include "EMessageBoxFlags.h" +#include "EWindowFlags.h" namespace irr { @@ -34,8 +35,36 @@ namespace gui //! Returns pointer to the maximize button virtual IGUIButton* getMaximizeButton() = 0; - }; + //! On EGET_WINDOW_SIZING events you can access and change the sizing rect + //! The rect is in relative posisitions + virtual core::rect * getSizingRect() = 0; + + // starsonata, micha + //! return if given flag is set + virtual bool hasFlag( EWINDOW_FLAG flag ) = 0; + + // starsonata, micha, bunch of flags which turned out to be useful + virtual void setTopResizable(bool resizable) = 0; + virtual bool isTopResizable() const = 0; + virtual void setRightResizable(bool resizable) = 0; + virtual bool isRightResizable() const = 0; + virtual void setBottomResizable(bool resizable) = 0; + virtual bool isBottomResizable() const = 0; + virtual void setLeftResizable(bool resizable) = 0; + virtual bool isLeftResizable() const = 0; + virtual void setMovable(bool movable) = 0; + virtual bool isMovable() const = 0; + virtual void setDrawBackground(bool draw) = 0; + virtual bool getDrawBackground() const = 0; + + // starsonata, micha + //! define the way the borders should look like + //! It's up to the skin to interpret the style + //! For example 0 = no border, 1 = normal border, 2 = soft border + virtual void setBorderStyle(u32 style=1) = 0; + virtual u32 getBorderStyle() const = 0; + }; } // end namespace gui } // end namespace irr diff -abBdpuNPr --exclude='*.svn' irrlicht-svn-ss/trunk/source/Irrlicht/CGUIWindow.cpp Irrlicht_starsonata/source/Irrlicht/CGUIWindow.cpp --- irrlicht-svn-ss/trunk/source/Irrlicht/CGUIWindow.cpp 2007-07-26 02:11:08.000000000 +0200 +++ Irrlicht_starsonata/source/Irrlicht/CGUIWindow.cpp 2008-06-07 11:17:58.000000000 +0200 @@ -16,8 +16,17 @@ namespace gui { //! constructor -CGUIWindow::CGUIWindow(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle) -: IGUIWindow(environment, parent, id, rectangle), Dragging(false) +CGUIWindow::CGUIWindow(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle, s32 flags) +: IGUIWindow(environment, parent, id, rectangle) +, Dragging(false) +, ResizingTop(false), ResizingRight(false), ResizingBottom(false), ResizingLeft(false) +, MouseOnTopBorder(false), MouseOnRightBorder(false), MouseOnBottomBorder(false), MouseOnLeftBorder(false) +, CloseButton(NULL), MinButton(NULL), RestoreButton(NULL) +, Flags(flags) +, ResizeBorderWidth(3) +, IsTopResizable(false), IsRightResizable(false), IsBottomResizable(false), IsLeftResizable(false) +, IsMovable(false), DrawBackground(true) +, BorderStyle(1) { #ifdef _DEBUG setDebugName("CGUIWindow"); @@ -54,7 +63,6 @@ CGUIWindow::CGUIWindow(IGUIEnvironment* RestoreButton = Environment->addButton(core::rect(posx, 3, posx + buttonw, 3 + buttonw), this, -1, L"", skin ? skin->getDefaultText(EGDT_WINDOW_RESTORE) : L"Restore" ); - RestoreButton->setVisible(false); RestoreButton->setSubElement(true); RestoreButton->setTabStop(false); RestoreButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); @@ -68,7 +76,6 @@ CGUIWindow::CGUIWindow(IGUIEnvironment* MinButton = Environment->addButton(core::rect(posx, 3, posx + buttonw, 3 + buttonw), this, -1, L"", skin ? skin->getDefaultText(EGDT_WINDOW_MINIMIZE) : L"Minimize" ); - MinButton->setVisible(false); MinButton->setSubElement(true); MinButton->setTabStop(false); MinButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); @@ -87,6 +94,8 @@ CGUIWindow::CGUIWindow(IGUIEnvironment* setTabGroup(true); setTabStop(true); setTabOrder(-1); + + refreshControls(); } @@ -104,7 +113,23 @@ CGUIWindow::~CGUIWindow() CloseButton->drop(); } +void CGUIWindow::refreshControls() +{ + if ( Flags & EWF_CLOSE ) + CloseButton->setVisible(true); + else + CloseButton->setVisible(false); + + if ( Flags & EWF_MAXIMIZE ) + RestoreButton->setVisible(true); + else + RestoreButton->setVisible(false); + if ( Flags & EWF_MINIMIZE ) + MinButton->setVisible(true); + else + MinButton->setVisible(false); +} //! called if an event happened. bool CGUIWindow::OnEvent(SEvent event) @@ -114,8 +139,11 @@ bool CGUIWindow::OnEvent(SEvent event) case EET_GUI_EVENT: if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST) { + if ( event.GUIEvent.Caller == this ) + { Dragging = false; } + } else if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUSED) { @@ -124,20 +152,68 @@ bool CGUIWindow::OnEvent(SEvent event) Parent->bringToFront(this); } } - else - if (event.GUIEvent.EventType == EGET_BUTTON_CLICKED) + else if ( event.GUIEvent.EventType == EGET_ELEMENT_LEFT) + { + MouseOnTopBorder = false; + MouseOnRightBorder = false; + MouseOnBottomBorder = false; + MouseOnLeftBorder = false; + } + else if (event.GUIEvent.EventType == EGET_BUTTON_CLICKED) { if (event.GUIEvent.Caller == CloseButton) { + if (Parent) + { + // send close event to parent + SEvent e; + e.EventType = EET_GUI_EVENT; + e.GUIEvent.Caller = this; + e.GUIEvent.Element = 0; + e.GUIEvent.EventType = EGET_ELEMENT_CLOSED; + + // if the event was not absorbed + if (!Parent->OnEvent(e)) + { + remove(); + } + return true; + } + else + { remove(); return true; } } + } break; case EET_MOUSE_INPUT_EVENT: switch(event.MouseInput.Event) { case EMIE_LMOUSE_PRESSED_DOWN: + + // check for resizing + if ( isTopResizable() ) + { + if ( event.MouseInput.Y < AbsoluteRect.UpperLeftCorner.Y+ResizeBorderWidth ) + ResizingTop = true; + } + if ( isRightResizable() ) + { + if ( event.MouseInput.X > AbsoluteRect.LowerRightCorner.X-ResizeBorderWidth ) + ResizingRight = true; + } + if ( isBottomResizable() ) + { + if ( event.MouseInput.Y > AbsoluteRect.LowerRightCorner.Y-ResizeBorderWidth ) + ResizingBottom = true; + } + if ( isLeftResizable() ) + { + if ( event.MouseInput.X < AbsoluteRect.UpperLeftCorner.X+ResizeBorderWidth ) + ResizingLeft = true; + } + DragStart.X = event.MouseInput.X; DragStart.Y = event.MouseInput.Y; Dragging = true; @@ -150,8 +226,38 @@ bool CGUIWindow::OnEvent(SEvent event) return true; case EMIE_LMOUSE_LEFT_UP: Dragging = false; + ResizingTop = false; + ResizingRight = false; + ResizingBottom = false; + ResizingLeft = false; return true; + + case EMIE_LMOUSE_DOUBLE_CLICK: + { + // check for click on resize area + if ( ( isTopResizable() && event.MouseInput.Y < AbsoluteRect.UpperLeftCorner.Y+ResizeBorderWidth) + || ( isRightResizable() && event.MouseInput.X > AbsoluteRect.LowerRightCorner.X-ResizeBorderWidth ) + || ( isBottomResizable() && event.MouseInput.Y > AbsoluteRect.LowerRightCorner.Y-ResizeBorderWidth ) + || ( isLeftResizable() && event.MouseInput.X < AbsoluteRect.UpperLeftCorner.X+ResizeBorderWidth ) ) + { + // send a sizing event to parent + SEvent eventDoubleClick; + eventDoubleClick.EventType = EET_GUI_EVENT; + eventDoubleClick.GUIEvent.Caller = this; + eventDoubleClick.GUIEvent.Element = 0; + eventDoubleClick.GUIEvent.EventType = EGET_ELEMENT_DOUBLE_CLICKED; + if ( Parent->OnEvent(eventDoubleClick) ) + return true; + } + + return false; + } + case EMIE_MOUSE_MOVED: + MouseOnTopBorder = false; + MouseOnRightBorder = false; + MouseOnBottomBorder = false; + MouseOnLeftBorder = false; if (Dragging) { // gui window should not be dragged outside its parent @@ -163,12 +269,77 @@ bool CGUIWindow::OnEvent(SEvent event) return true; - + if ( !ResizingTop && !ResizingRight && !ResizingBottom && !ResizingLeft ) + { + if ( isMovable() ) + { move(core::position2d(event.MouseInput.X - DragStart.X, event.MouseInput.Y - DragStart.Y)); + } + } + else + { + ResizingRect = getRelativePosition(); + if ( ResizingTop ) + { + ResizingRect.UpperLeftCorner.Y += event.MouseInput.Y - DragStart.Y; + } + if ( ResizingRight ) + { + ResizingRect.LowerRightCorner.X += event.MouseInput.X - DragStart.X; + } + if ( ResizingBottom ) + { + ResizingRect.LowerRightCorner.Y += event.MouseInput.Y - DragStart.Y; + } + if ( ResizingLeft ) + { + ResizingRect.UpperLeftCorner.X += event.MouseInput.X - DragStart.X; + } + // send a sizing event to parent + SEvent eventSizing; + eventSizing.EventType = EET_GUI_EVENT; + eventSizing.GUIEvent.Caller = this; + eventSizing.GUIEvent.Element = 0; + eventSizing.GUIEvent.EventType = EGET_WINDOW_SIZING; + // if the event was not absorbed + if (!Parent->OnEvent(eventSizing)) + { + setRelativePosition(ResizingRect); + } + } + DragStart.X = event.MouseInput.X; DragStart.Y = event.MouseInput.Y; return true; } + else + { + // check if we could resize + if ( isTopResizable() ) + { + if ( event.MouseInput.Y < AbsoluteRect.UpperLeftCorner.Y+ResizeBorderWidth + && event.MouseInput.Y >= AbsoluteRect.UpperLeftCorner.Y ) + MouseOnTopBorder = true; + } + if ( isRightResizable() ) + { + if ( event.MouseInput.X > AbsoluteRect.LowerRightCorner.X-ResizeBorderWidth + && event.MouseInput.X <= AbsoluteRect.LowerRightCorner.X ) + MouseOnRightBorder = true; + } + if ( isBottomResizable() ) + { + if ( event.MouseInput.Y > AbsoluteRect.LowerRightCorner.Y-ResizeBorderWidth + && event.MouseInput.Y <= AbsoluteRect.LowerRightCorner.Y ) + MouseOnBottomBorder = true; + } + if ( isLeftResizable() ) + { + if ( event.MouseInput.X < AbsoluteRect.UpperLeftCorner.X+ResizeBorderWidth + && event.MouseInput.X >= AbsoluteRect.UpperLeftCorner.X ) + MouseOnLeftBorder = true; + } + } break; } } @@ -182,7 +353,10 @@ void CGUIWindow::updateAbsolutePosition( IGUIElement::updateAbsolutePosition(); } - +bool CGUIWindow::hasFlag( EWINDOW_FLAG flag ) +{ + return (Flags & flag) ? true : false; +} //! draws the element and its children void CGUIWindow::draw() @@ -196,8 +370,10 @@ void CGUIWindow::draw() core::rect *cl = &AbsoluteClippingRect; // draw body fast + if ( Flags & EWF_TITLEBAR ) + { rect = skin->draw3DWindowBackground(this, true, skin->getColor(EGDC_ACTIVE_BORDER), - AbsoluteRect, &AbsoluteClippingRect); + rect, &AbsoluteClippingRect); if (Text.size()) { @@ -209,6 +385,40 @@ void CGUIWindow::draw() if (font) font->draw(Text.c_str(), rect, skin->getColor(EGDC_ACTIVE_CAPTION), false, true, cl); } + } + else + { + rect = skin->draw3DWindowBackground(this, false, skin->getColor(EGDC_ACTIVE_BORDER), + rect, &AbsoluteClippingRect); + } + + // TODO: Drawing resize-borders is just a placeholder for now. + // The typical solution would be to change the cursor, but Irrlicht does not yet support that. + // So for now draw some rectangles there. + if ( isTopResizable() && (ResizingTop || MouseOnTopBorder) ) + { + skin->draw2DRectangle(this, ResizingTop ? skin->getColor(EGDC_ACTIVE_BORDER) : skin->getColor(EGDC_INACTIVE_BORDER), + core::rect(AbsoluteRect.UpperLeftCorner.X, AbsoluteRect.UpperLeftCorner.Y, AbsoluteRect.LowerRightCorner.X, AbsoluteRect.UpperLeftCorner.Y+ResizeBorderWidth), + &AbsoluteClippingRect); + } + if ( isRightResizable() && (ResizingRight || MouseOnRightBorder) ) + { + skin->draw2DRectangle(this, ResizingRight ? skin->getColor(EGDC_ACTIVE_BORDER) : skin->getColor(EGDC_INACTIVE_BORDER), + core::rect(AbsoluteRect.LowerRightCorner.X - ResizeBorderWidth, AbsoluteRect.UpperLeftCorner.Y, AbsoluteRect.LowerRightCorner.X, AbsoluteRect.LowerRightCorner.Y), + &AbsoluteClippingRect); + } { + if ( isBottomResizable() && (ResizingBottom || MouseOnBottomBorder) ) + { + skin->draw2DRectangle(this, ResizingBottom ? skin->getColor(EGDC_ACTIVE_BORDER) : skin->getColor(EGDC_INACTIVE_BORDER), + core::rect(AbsoluteRect.UpperLeftCorner.X, AbsoluteRect.LowerRightCorner.Y - ResizeBorderWidth, AbsoluteRect.LowerRightCorner.X, AbsoluteRect.LowerRightCorner.Y), + &AbsoluteClippingRect); + } + if ( isLeftResizable() && (ResizingLeft || MouseOnLeftBorder) ) + { + skin->draw2DRectangle(this, ResizingLeft ? skin->getColor(EGDC_ACTIVE_BORDER) : skin->getColor(EGDC_INACTIVE_BORDER), + core::rect(AbsoluteRect.UpperLeftCorner.X, AbsoluteRect.UpperLeftCorner.Y, AbsoluteRect.UpperLeftCorner.X+ResizeBorderWidth, AbsoluteRect.LowerRightCorner.Y), + &AbsoluteClippingRect); + } IGUIElement::draw(); } @@ -237,6 +447,156 @@ IGUIButton* CGUIWindow::getMaximizeButto return RestoreButton; } +core::rect * CGUIWindow::getSizingRect() +{ + return &ResizingRect; +} + +void CGUIWindow::setTopResizable(bool resizable) +{ + IsTopResizable = resizable; + if ( !IsTopResizable ) + { + ResizingTop = false; + MouseOnTopBorder = false; + } +} + +bool CGUIWindow::isTopResizable() const +{ + return IsTopResizable; +} + +void CGUIWindow::setRightResizable(bool resizable) +{ + IsRightResizable = resizable; + if ( !IsRightResizable ) + { + ResizingRight = false; + MouseOnRightBorder = false; + } +} + +bool CGUIWindow::isRightResizable() const +{ + return IsRightResizable; +} + +void CGUIWindow::setBottomResizable(bool resizable) +{ + IsBottomResizable = resizable; + if ( !IsBottomResizable ) + { + ResizingBottom = false; + MouseOnBottomBorder = false; + } +} + +bool CGUIWindow::isBottomResizable() const +{ + return IsBottomResizable; +} + +void CGUIWindow::setLeftResizable(bool resizable) +{ + IsLeftResizable = resizable; + if ( !IsLeftResizable ) + { + ResizingLeft = false; + MouseOnLeftBorder = false; + } +} + +bool CGUIWindow::isLeftResizable() const +{ + return IsLeftResizable; +} + +void CGUIWindow::setMovable(bool movable) +{ + IsMovable = movable; + + if ( !IsMovable ) + Dragging = false; +} + +bool CGUIWindow::isMovable() const +{ + return IsMovable; +} + +void CGUIWindow::setDrawBackground(bool draw) +{ + DrawBackground = draw; +} + +bool CGUIWindow::getDrawBackground() const +{ + return DrawBackground; +} + +void CGUIWindow::setBorderStyle(u32 style) +{ + BorderStyle = style; +} + +u32 CGUIWindow::getBorderStyle() const +{ + return BorderStyle; +} + +//! Writes attributes of the element. +void CGUIWindow::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) +{ + IGUIWindow::serializeAttributes(out, options); + + //core::position2d DragStart; // runtime info - no need for serialization + //bool Dragging; // runtime info - no need for serialization + //bool ResizingTop; // runtime info - no need for serialization + //bool ResizingRight; // runtime info - no need for serialization + //bool ResizingBottom; // runtime info - no need for serialization + //bool ResizingLeft; // runtime info - no need for serialization + //bool MouseOnTopBorder; // runtime info - no need for serialization + //bool MouseOnRightBorder; // runtime info - no need for serialization + //bool MouseOnBottomBorder; // runtime info - no need for serialization + //bool MouseOnLeftBorder; // runtime info - no need for serialization + + //IGUIButton* CloseButton; // currently those are always at whole lifetime of the object + //IGUIButton* MinButton; // currently those are always at whole lifetime of the object + //IGUIButton* RestoreButton; // currently those are always at whole lifetime of the object + + out->addInt ("Flags", Flags ); + out->addInt ("ResizeBorderWidth", ResizeBorderWidth); + + out->addBool("TopResizable", IsTopResizable); + out->addBool("RightResizable", IsRightResizable); + out->addBool("BottomResizable", IsBottomResizable); + out->addBool("LeftResizable", IsLeftResizable); + out->addBool("Movable", IsMovable); + out->addBool("DrawBackground", DrawBackground); + out->addInt ("BorderStyle", BorderStyle ); +} + +//! Reads attributes of the element +void CGUIWindow::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) +{ + IGUIWindow::deserializeAttributes(in, options); + + Flags = in->getAttributeAsInt("Flags"); + ResizeBorderWidth = in->getAttributeAsInt("ResizeBorderWidth"); + + setTopResizable( in->getAttributeAsBool("TopResizable") ); + setRightResizable( in->getAttributeAsBool("RightResizable") ); + setBottomResizable( in->getAttributeAsBool("BottomResizable") ); + setLeftResizable( in->getAttributeAsBool("LeftResizable") ); + setMovable( in->getAttributeAsBool("Movable") ); + setDrawBackground( in->getAttributeAsBool("DrawBackground") ); + setBorderStyle( in->getAttributeAsInt("BorderStyle") ); + + refreshControls(); +} + + } // end namespace gui } // end namespace irr diff -abBdpuNPr --exclude='*.svn' irrlicht-svn-ss/trunk/source/Irrlicht/CGUIWindow.h Irrlicht_starsonata/source/Irrlicht/CGUIWindow.h --- irrlicht-svn-ss/trunk/source/Irrlicht/CGUIWindow.h 2007-07-26 02:11:08.000000000 +0200 +++ Irrlicht_starsonata/source/Irrlicht/CGUIWindow.h 2008-05-31 04:53:10.000000000 +0200 @@ -18,7 +18,7 @@ namespace gui public: //! constructor - CGUIWindow(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle); + CGUIWindow(IGUIEnvironment* environment, IGUIElement* parent, s32 id, core::rect rectangle, s32 flags=EWF_CLOSE|EWF_TITLEBAR); //! destructor ~CGUIWindow(); @@ -41,14 +41,68 @@ namespace gui //! Returns pointer to the maximize button virtual IGUIButton* getMaximizeButton(); + //! On EGET_WINDOW_SIZING events you can access and change the sizing rect + virtual core::rect * getSizingRect(); + + //! Writes attributes of the element. + virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options); + + //! Reads attributes of the element + virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); + + // starsonata, micha + //! return if given flag is set + virtual bool hasFlag( EWINDOW_FLAG flag ); + + // starsonata, micha, bunch of flags which turned out to be useful + virtual void setTopResizable(bool resizable); + virtual bool isTopResizable() const; + virtual void setRightResizable(bool resizable); + virtual bool isRightResizable() const; + virtual void setBottomResizable(bool resizable); + virtual bool isBottomResizable() const; + virtual void setLeftResizable(bool resizable); + virtual bool isLeftResizable() const; + virtual void setMovable(bool movable); + virtual bool isMovable() const; + virtual void setDrawBackground(bool draw); + virtual bool getDrawBackground() const; + + // starsonata, micha + //! define the way the borders should look like + //! It's up to the skin to interpret the style + virtual void setBorderStyle(u32 style); + virtual u32 getBorderStyle() const; + protected: + void refreshControls(); + core::position2d DragStart; bool Dragging; + bool ResizingTop; + bool ResizingRight; + bool ResizingBottom; + bool ResizingLeft; + core::rect ResizingRect; + bool MouseOnTopBorder; + bool MouseOnRightBorder; + bool MouseOnBottomBorder; + bool MouseOnLeftBorder; IGUIButton* CloseButton; IGUIButton* MinButton; IGUIButton* RestoreButton; + + s32 Flags; + s32 ResizeBorderWidth; + bool IsTopResizable; + bool IsRightResizable; + bool IsBottomResizable; + bool IsLeftResizable; + bool IsMovable; + bool DrawBackground; + u32 BorderStyle; }; } // end namespace gui