Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F126488
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
232 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/util/gui/al_keyinput.cpp b/util/gui/al_keyinput.cpp
new file mode 100644
index 00000000..a28266a7
--- /dev/null
+++ b/util/gui/al_keyinput.cpp
@@ -0,0 +1,311 @@
+/*
+SAGGUI (Simplified All Gaming Graphical User Interface)
+Copyright (c) 2005-2007, Miguel A. Gavidia
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+ * Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the following
+ disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+ * Neither the name of the "SAGGUI" nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef USE_ALLEGRO
+
+#include <allegro.h>
+#include "al_keyinput.h"
+
+// constructor
+ allegroKeyInput::allegroKeyInput()
+ {
+ // Nothing
+ }
+
+ // destructor
+ allegroKeyInput::~allegroKeyInput()
+ {
+ // Nothing
+ }
+
+ keys allegroKeyInput::convertKey(int unicode, int scancode)
+ {
+ int value;
+
+ switch(scancode)
+ {
+ case KEY_ESC:
+ value = keys::ESC;
+ break;
+
+ case KEY_ALT:
+ value = keys::ALT;
+ break;
+
+ case KEY_ALTGR:
+ value = keys::ALTGR;
+ break;
+
+ case KEY_LSHIFT:
+ value = keys::LSHIFT;
+ break;
+
+ case KEY_RSHIFT:
+ value = keys::RSHIFT;
+ break;
+
+ case KEY_LCONTROL:
+ value = keys::LCONTROL;
+ break;
+
+ case KEY_RCONTROL:
+ value = keys::RCONTROL;
+ break;
+
+ case KEY_LWIN:
+ value = keys::LWIN;
+ break;
+
+ case KEY_RWIN:
+ value = keys::RWIN;
+ break;
+
+ case KEY_INSERT:
+ value = keys::INSERT;
+ break;
+
+ case KEY_HOME:
+ value = keys::HOME;
+ break;
+
+ case KEY_PGUP:
+ value = keys::PGUP;
+ break;
+
+ case KEY_PGDN:
+ value = keys::PGDN;
+ break;
+
+ case KEY_DEL:
+ value = keys::DEL;
+ break;
+
+ case KEY_DEL_PAD:
+ value = keys::PAD_DEL;
+ break;
+
+ case KEY_END:
+ value = keys::END;
+ break;
+
+ case KEY_CAPSLOCK:
+ value = keys::CAPSLOCK;
+ break;
+
+ case KEY_BACKSPACE:
+ value = keys::BACKSPACE;
+ break;
+
+ case KEY_F1:
+ value = keys::F1;
+ break;
+
+ case KEY_F2:
+ value = keys::F2;
+ break;
+
+ case KEY_F3:
+ value = keys::F3;
+ break;
+
+ case KEY_F4:
+ value = keys::F4;
+ break;
+
+ case KEY_F5:
+ value = keys::F5;
+ break;
+
+ case KEY_F6:
+ value = keys::F6;
+ break;
+
+ case KEY_F7:
+ value = keys::F7;
+ break;
+
+ case KEY_F8:
+ value = keys::F8;
+ break;
+
+ case KEY_F9:
+ value = keys::F9;
+ break;
+
+ case KEY_F10:
+ value = keys::F10;
+ break;
+
+ case KEY_F11:
+ value = keys::F11;
+ break;
+
+ case KEY_F12:
+ value = keys::F12;
+ break;
+
+ case KEY_PRTSCR:
+ value = keys::PRTSCR;
+ break;
+
+ case KEY_PAUSE:
+ value = keys::PAUSE;
+ break;
+
+ case KEY_SCRLOCK:
+ value = keys::SCRLOCK;
+ break;
+
+ case KEY_NUMLOCK:
+ value = keys::NUMLOCK;
+ break;
+
+ case KEY_LEFT:
+ value = keys::LEFT;
+ break;
+
+ case KEY_RIGHT:
+ value = keys::RIGHT;
+ break;
+
+ case KEY_UP:
+ value = keys::UP;
+ break;
+
+ case KEY_DOWN:
+ value = keys::DOWN;
+ break;
+
+ case KEY_ENTER_PAD:
+ value = keys::PAD_ENTER;
+ break;
+ case KEY_ENTER:
+ value = keys::ENTER;
+ break;
+
+ case KEY_0_PAD:
+ value = keys::PAD_0;
+ break;
+ case KEY_1_PAD:
+ value = keys::PAD_1;
+ break;
+ case KEY_2_PAD:
+ value = keys::PAD_2;
+ break;
+ case KEY_3_PAD:
+ value = keys::PAD_3;
+ break;
+ case KEY_4_PAD:
+ value = keys::PAD_4;
+ break;
+ case KEY_5_PAD:
+ value = keys::PAD_5;
+ break;
+ case KEY_6_PAD:
+ value = keys::PAD_6;
+ break;
+ case KEY_7_PAD:
+ value = keys::PAD_7;
+ break;
+ case KEY_8_PAD:
+ value = keys::PAD_8;
+ break;
+ case KEY_9_PAD:
+ value = keys::PAD_9;
+ break;
+ case KEY_SLASH_PAD:
+ value = keys::PAD_SLASH;
+ break;
+ case KEY_MINUS_PAD:
+ value = keys::PAD_MINUS;
+ break;
+ case KEY_PLUS_PAD:
+ value = keys::PAD_PLUS;
+ break;
+
+ default:
+ value = unicode;
+ }
+
+ keys newkey(value, scancode);
+
+ return newkey;
+
+ }
+
+ //init
+ void allegroKeyInput::update()
+ {
+ // Poll allegros keyboard and set the keys
+ while(keypressed())
+ {
+ int unicode, scancode;
+ unicode = ureadkey(&scancode);
+ keys pressed = convertKey(unicode,scancode);
+ queuePressed(pressed);
+ }
+
+ // Check these other keys since allegro doesn't do it just right :|
+ if(key[KEY_LSHIFT])queuePressed(keys(keys::LSHIFT,KEY_LSHIFT));
+ if(key[KEY_RSHIFT])queuePressed(keys(keys::RSHIFT,KEY_RSHIFT));
+ if(key[KEY_LCONTROL])queuePressed(keys(keys::LCONTROL,KEY_LCONTROL));
+ if(key[KEY_RCONTROL])queuePressed(keys(keys::RCONTROL,KEY_RCONTROL));
+ if(key[KEY_ALT])queuePressed(keys(keys::ALT,KEY_ALT));
+ if(key[KEY_ALTGR])queuePressed(keys(keys::ALTGR,KEY_ALTGR));
+ if(key[KEY_LWIN])queuePressed(keys(keys::LWIN,KEY_LWIN));
+ if(key[KEY_RWIN])queuePressed(keys(keys::RWIN,KEY_RWIN));
+ if(key[KEY_MENU])queuePressed(keys(keys::MENU,KEY_MENU));
+ if(key[KEY_SCRLOCK])queuePressed(keys(keys::SCRLOCK,KEY_SCRLOCK));
+ if(key[KEY_NUMLOCK])queuePressed(keys(keys::NUMLOCK,KEY_NUMLOCK));
+ if(key[KEY_CAPSLOCK])queuePressed(keys(keys::CAPSLOCK,KEY_CAPSLOCK));
+
+ for(std::map<int, keys>::iterator i = pressedKeys.begin();i!=pressedKeys.end();++i)
+ {
+ if(!key[(i->second).getScancodeValue()])
+ {
+ queueReleased(i->second);
+ }
+ }
+ for(std::list< std::map<int, keys>::iterator >::iterator i = deleteList.begin();i!=deleteList.end();++i)
+ {
+ pressedKeys.erase((*i));
+ }
+ deleteList.clear();
+ }
+
+#endif
diff --git a/util/gui/al_keyinput.h b/util/gui/al_keyinput.h
new file mode 100644
index 00000000..363a224a
--- /dev/null
+++ b/util/gui/al_keyinput.h
@@ -0,0 +1,63 @@
+/*
+SAGGUI (Simplified All Gaming Graphical User Interface)
+Copyright (c) 2005-2007, Miguel A. Gavidia
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+ * Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the following
+ disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+ * Neither the name of the "SAGGUI" nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef AL_KEYINPUT_H
+#define AL_KEYINPUT_H
+
+/*
+#include <allegro.h>
+#ifdef ALLEGRO_WINDOWS
+#include <winalleg.h>
+#endif
+*/
+
+#include "keyinput.h"
+
+class allegroKeyInput : public keyInput
+{
+ private:
+ // Convert key
+ keys convertKey(int unicode, int scancode);
+ public:
+ allegroKeyInput();
+ ~allegroKeyInput();
+ //! Poll keyboard input
+ void update();
+};
+
+#endif
diff --git a/util/gui/animation.cpp b/util/gui/animation.cpp
new file mode 100644
index 00000000..190f1035
--- /dev/null
+++ b/util/gui/animation.cpp
@@ -0,0 +1,385 @@
+#include "animation.h"
+
+#include <vector>
+#include <math.h>
+#include <sstream>
+#include "util/token.h"
+#include "util/bitmap.h"
+#include "globals.h"
+#include "../debug.h"
+#include "../funcs.h"
+#include "../file-system.h"
+
+using namespace std;
+using namespace Gui;
+
+// Temporary solution
+static void renderSprite(const Bitmap & bmp, const int x, const int y, const int alpha, const bool hflip, const bool vflip, const Bitmap & work){
+ if (alpha != 255){
+ Bitmap::transBlender( 0, 0, 0, alpha );
+ if (hflip && !vflip){
+ bmp.drawTransHFlip(x,y, work);
+ } else if (!hflip && vflip){
+ bmp.drawTransVFlip(x,y, work);
+ } else if (hflip && vflip){
+ bmp.drawTransHVFlip(x,y, work);
+ } else if (!hflip && !vflip){
+ bmp.drawTrans(x,y, work);
+ }
+ } else {
+ if (hflip && !vflip){
+ bmp.drawHFlip(x,y, work);
+ } else if (!hflip && vflip){
+ bmp.drawVFlip(x,y, work);
+ } else if (hflip && vflip){
+ bmp.drawHVFlip(x,y, work);
+ } else if (!hflip && !vflip){
+ bmp.draw(x,y, work);
+ }
+ }
+}
+
+Frame::Frame(const Token *the_token, imageMap &images) throw (LoadException):
+bmp(0),
+time(0),
+horizontalFlip(false),
+verticalFlip(false),
+alpha(255){
+ if ( *the_token != "frame" ){
+ throw LoadException(__FILE__, __LINE__, "Not an frame");
+ }
+ const Token & tok = *the_token;
+ /* The usual setup of an animation frame is
+ // use image -1 to not draw anything, it can be used to get a blinking effect
+ (frame (image NUM) (alpha NUM) (offset x y) (hflip 0|1) (vflip 0|1) (time NUM))
+ */
+ TokenView view = tok.view();
+ while (view.hasMore()){
+ try{
+ const Token * token;
+ view >> token;
+ if (*token == "image"){
+ // get the number
+ int num;
+ token->view() >> num;
+ // now assign the bitmap
+ bmp = images[num];
+ } else if (*token == "alpha"){
+ // get alpha
+ token->view() >> alpha;
+ } else if (*token == "offset"){
+ // Get the offset location it defaults to 0,0
+ double x=0, y=0;
+ try {
+ token->view() >> x >> y;
+ } catch (const TokenException & ex){
+ }
+ offset.set(x,y);
+ } else if (*token == "hflip"){
+ // horizontal flip
+ token->view() >> horizontalFlip;
+ } else if (*token == "vflip"){
+ // horizontal flip
+ token->view() >> verticalFlip;
+ } else if (*token == "time"){
+ // time to display
+ token->view() >> time;
+ } else {
+ Global::debug( 3 ) << "Unhandled menu attribute: "<<endl;
+ if (Global::getDebug() >= 3){
+ token->print(" ");
+ }
+ }
+ } catch ( const TokenException & ex ) {
+ throw LoadException(__FILE__, __LINE__, ex, "Menu animation parse error");
+ } catch ( const LoadException & ex ) {
+ throw ex;
+ }
+ }
+}
+
+Frame::Frame(Bitmap * bmp):
+bmp(bmp),
+time(0),
+horizontalFlip(false),
+verticalFlip(false),
+alpha(255){
+}
+
+Frame::~Frame(){
+}
+
+void Frame::act(double xvel, double yvel){
+ scrollOffset.moveBy(xvel,yvel);
+ if (scrollOffset.getDistanceFromCenterX() >=bmp->getWidth()){
+ scrollOffset.setX(0);
+ } else if (scrollOffset.getDistanceFromCenterX() <= -(bmp->getWidth())){
+ scrollOffset.setX(0);
+ }
+ if (scrollOffset.getDistanceFromCenterY() >=bmp->getHeight()){
+ scrollOffset.setY(0);
+ } else if (scrollOffset.getDistanceFromCenterY() <= -(bmp->getHeight())){
+ scrollOffset.setY(0);
+ }
+}
+
+static bool closeFloat(double a, double b){
+ const double epsilon = 0.001;
+ return fabs(a-b) < epsilon;
+}
+
+void Frame::draw(const int xaxis, const int yaxis, const Bitmap & work){
+ if (!bmp){
+ return;
+ }
+
+ if (!closeFloat(scrollOffset.getDistanceFromCenterX(), 0) || !closeFloat(scrollOffset.getDistanceFromCenterY(), 0)){
+
+ // Lets do some scrolling
+ Bitmap temp = Bitmap::temporaryBitmap(bmp->getWidth(), bmp->getHeight());
+ //AnimationPoint loc;
+ AbsolutePoint loc;
+ if (scrollOffset.getRelativeX() < 0){
+ loc.setX(scrollOffset.getDistanceFromCenterX() + bmp->getWidth());
+ } else if (scrollOffset.getRelativeX() > 0){
+ loc.setX(scrollOffset.getDistanceFromCenterX() - bmp->getWidth());
+ }
+ if (scrollOffset.getRelativeY() < 0){
+ loc.setY(scrollOffset.getDistanceFromCenterY() + bmp->getHeight());
+ } else if (scrollOffset.getRelativeY() > 0){
+ loc.setY(scrollOffset.getDistanceFromCenterY() - bmp->getHeight());
+ }
+ bmp->Blit((int) scrollOffset.getDistanceFromCenterX(), (int) scrollOffset.getDistanceFromCenterY(), temp);
+ bmp->Blit((int) scrollOffset.getDistanceFromCenterX(), (int) loc.getY(), temp);
+ bmp->Blit((int) loc.getX(), (int) scrollOffset.getDistanceFromCenterY(), temp);
+ bmp->Blit((int) loc.getX(), (int) loc.getY(), temp);
+
+ renderSprite(temp, (int)(xaxis+offset.getDistanceFromCenterX()), (int)(yaxis+offset.getDistanceFromCenterY()), alpha, horizontalFlip, verticalFlip, work);
+
+ } else {
+ renderSprite(*bmp, (int)(xaxis+offset.getDistanceFromCenterX()), (int)(yaxis+offset.getDistanceFromCenterY()), alpha, horizontalFlip, verticalFlip, work);
+ }
+}
+
+Animation::Animation(const Token *the_token) throw (LoadException):
+id(0),
+depth(BackgroundBottom),
+ticks(0),
+currentFrame(0),
+loop(0),
+allowReset(true){
+ images[-1] = 0;
+ std::string basedir = "";
+ if ( *the_token != "anim" ){
+ throw LoadException(__FILE__, __LINE__, "Not an animation");
+ }
+ /* The usual setup of an animation is
+ The images must be listed prior to listing any frames, basedir can be used to set the directory where the images are located
+ loop will begin at the subsequent frame listed after loop
+ axis is the location in which the drawing must be placed
+ location *old* - used to render in background or foreground (0 == background [default]| 1 == foreground)
+ depth - used to render in background or foreground space (depth background bottom|middle|top) | (depth foreground bottom|midle|top)
+ reset - used to allow resetting of animation (0 == no | 1 == yes [default])
+ velocity - used to get a wrapping scroll effect while animating
+ window - area in which the item will be contained
+ (anim (id NUM)
+ (location NUM)
+ (depth background|foreground NUM)
+ (basedir LOCATION)
+ (image NUM FILE)
+ (velocity x y)
+ (axis x y)
+ (frame "Read comments above in constructor")
+ (loop)
+ (reset NUM)
+ (window x1 y1 x2 y2))
+ */
+ const Token & tok = *the_token;
+ TokenView view = tok.view();
+ while (view.hasMore()){
+ try{
+ const Token * token;
+ view >> token;
+ if (*token == "id"){
+ // get the id
+ token->view() >> id;
+ } else if (*token == "location"){
+ // translate location to depth
+ int location = 0;
+ token->view() >> location;
+ if (location == 0){
+ depth = BackgroundBottom;
+ } else if (location == 1){
+ depth = ForegroundBottom;
+ }
+ } else if (*token == "depth"){
+ // get the depth
+ std::string name, level;
+ token->view() >> name >> level;
+ if (name == "background"){
+ if (level == "bottom"){
+ depth = BackgroundBottom;
+ } else if (level == "middle"){
+ depth = BackgroundMiddle;
+ } else if (level == "top"){
+ depth = BackgroundTop;
+ }
+ } else if (name == "foreground"){
+ if (level == "bottom"){
+ depth = ForegroundBottom;
+ } else if (level == "middle"){
+ depth = ForegroundMiddle;
+ } else if (level == "top"){
+ depth = ForegroundTop;
+ }
+ }
+ } else if (*token == "basedir"){
+ // set the base directory for loading images
+ token->view() >> basedir;
+ } else if (*token == "image"){
+ // add bitmaps by number to the map
+ int number;
+ std::string temp;
+ token->view() >> number >> temp;
+ Bitmap *bmp = new Bitmap(Filesystem::find(Filesystem::RelativePath(basedir + temp)).path());
+ if (bmp->getError()){
+ delete bmp;
+ } else {
+ images[number] = bmp;
+ }
+ } else if (*token == "axis"){
+ // Get the axis location it defaults to 0,0
+ double x=0, y=0;
+ try {
+ token->view() >> x >> y;
+ } catch (const TokenException & ex){
+ }
+ axis.set(x,y);
+ } else if (*token == "window"){
+ // Windowed area where to clip if necessary otherwise it defaults to max
+ double x1=0,x2=0, y1=0,y2=0;
+ try {
+ token->view() >> x1 >> y1 >> x2 >> y2;
+ } catch (const TokenException & ex){
+ }
+ window.set(x1,y1,x2,y2);
+ } else if (*token == "velocity"){
+ // This allows the animation to get a wrapping scroll action going on
+ double x=0, y=0;
+ try {
+ token->view() >> x >> y;
+ } catch (const TokenException & ex){
+ }
+ velocity.set(x,y);
+ } else if (*token == "frame"){
+ // new frame
+ Frame *frame = new Frame(token, images);
+ frames.push_back(frame);
+ } else if (*token == "loop"){
+ // start loop here
+ int l;
+ token->view() >> l;
+ if (l >= frames.size()){
+ ostringstream out;
+ out << "Loop location is larger than the number of frames. Loop: " << loop << " Frames: " << frames.size();
+ throw LoadException(__FILE__, __LINE__, out.str());
+ }
+ loop = l;
+ } else if (*token == "reset"){
+ // Allow reset of animation
+ token->view() >> allowReset;
+ } else {
+ Global::debug( 3 ) << "Unhandled menu attribute: "<<endl;
+ if (Global::getDebug() >= 3){
+ token->print(" ");
+ }
+ }
+ } catch ( const TokenException & ex ) {
+ throw LoadException(__FILE__, __LINE__, ex, "Menu animation parse error");
+ } catch ( const LoadException & ex ) {
+ throw ex;
+ }
+ }
+}
+
+Animation::Animation(const std::string & background) throw (LoadException):
+id(0),
+depth(BackgroundBottom),
+ticks(0),
+currentFrame(0),
+loop(0),
+allowReset(true){
+ // add bitmap
+ Bitmap *bmp = new Bitmap(Filesystem::find(Filesystem::RelativePath(background)).path());
+ if (bmp->getError()){
+ delete bmp;
+ throw LoadException(__FILE__,__LINE__, "Problem loading file: " + background);
+ } else {
+ images[0] = bmp;
+ }
+ Frame *frame = new Frame(bmp);
+ frames.push_back(frame);
+}
+
+Animation::Animation(Bitmap * image):
+id(0),
+depth(BackgroundBottom),
+ticks(0),
+currentFrame(0),
+loop(0),
+allowReset(true){
+ images[0] = image;
+ Frame *frame = new Frame(image);
+ frames.push_back(frame);
+}
+
+Animation::~Animation(){
+ for (std::vector<Frame *>::iterator i = frames.begin(); i != frames.end(); ++i){
+ if (*i){
+ delete *i;
+ }
+ }
+
+ for (imageMap::iterator i = images.begin(); i != images.end(); ++i){
+ if (i->second){
+ delete i->second;
+ }
+ }
+}
+void Animation::act(){
+ // Used for scrolling
+ for (std::vector<Frame *>::iterator i = frames.begin(); i != frames.end(); ++i){
+ (*i)->act(velocity.getRelativeX(), velocity.getRelativeY());
+ }
+ if( frames[currentFrame]->time != -1 ){
+ ticks++;
+ if(ticks >= frames[currentFrame]->time){
+ ticks = 0;
+ forwardFrame();
+ }
+ }
+}
+void Animation::draw(const Bitmap & work){
+ /* should use sub-bitmaps here */
+ // Set clip from the axis default is 0,0,bitmap width, bitmap height
+ work.setClipRect(-(window.getPosition().getDistanceFromCenterX()),-(window.getPosition().getDistanceFromCenterY()),work.getWidth() - window.getPosition2().getDistanceFromCenterX(),work.getHeight() - window.getPosition2().getDistanceFromCenterY());
+ frames[currentFrame]->draw(axis.getDistanceFromCenterX(), axis.getDistanceFromCenterY(),work);
+ work.setClipRect(0,0,work.getWidth(),work.getHeight());
+}
+
+void Animation::forwardFrame(){
+ if (currentFrame < frames.size() -1){
+ currentFrame++;
+ } else {
+ currentFrame = loop;
+ }
+}
+void Animation::backFrame(){
+ if (currentFrame > loop){
+ currentFrame--;
+ } else {
+ currentFrame = frames.size() - 1;
+ }
+}
+
+
diff --git a/util/gui/animation.h b/util/gui/animation.h
new file mode 100644
index 00000000..e682f28f
--- /dev/null
+++ b/util/gui/animation.h
@@ -0,0 +1,76 @@
+#ifndef _paintown_gui_animation_h
+#define _paintown_gui_animation_h
+
+#include <vector>
+#include <map>
+
+#include "../load_exception.h"
+#include "coordinate.h"
+
+class Token;
+class Bitmap;
+
+namespace Gui{
+
+// To hold images by number easier to access and reuse
+typedef std::map< int, Bitmap *> imageMap;
+
+class Frame{
+public:
+ Frame(const Token *token, imageMap &images) throw (LoadException);
+ Frame(Bitmap *);
+ virtual ~Frame();
+ virtual void act(double xvel, double yvel);
+ virtual void draw(int xaxis, int yaxis, const Bitmap &);
+ Bitmap *bmp;
+ RelativePoint offset;
+ RelativePoint scrollOffset;
+ int time;
+ bool horizontalFlip;
+ bool verticalFlip;
+ int alpha;
+};
+
+class Animation{
+public:
+ Animation(const Token *token) throw (LoadException);
+ /*! Load only a single bitmap (for bacwards compatibility of backgrounds in menu) */
+ Animation(const std::string &) throw (LoadException);
+ /* use an existing bitmap */
+ Animation(Bitmap * image);
+ virtual ~Animation();
+ // Logic
+ virtual void act();
+ virtual void draw(const Bitmap &);
+ virtual void forwardFrame();
+ virtual void backFrame();
+
+ inline void reset(){ if (allowReset){ currentFrame = 0; } }
+ inline int getID() const { return id; }
+
+ enum Depth {
+ BackgroundBottom,
+ BackgroundMiddle,
+ BackgroundTop,
+ ForegroundBottom,
+ ForegroundMiddle,
+ ForegroundTop,
+ };
+ inline const Depth & getDepth() const { return this->depth; }
+
+private:
+ int id;
+ Depth depth;
+ int ticks;
+ unsigned int currentFrame;
+ unsigned int loop;
+ bool allowReset;
+ RelativePoint axis;
+ // This allows the frames to scroll in place
+ RelativePoint velocity;
+ Coordinate window;
+ std::vector<Frame *> frames;
+ imageMap images;
+};
+}
+#endif
diff --git a/util/gui/box.cpp b/util/gui/box.cpp
new file mode 100644
index 00000000..d8e18361
--- /dev/null
+++ b/util/gui/box.cpp
@@ -0,0 +1,72 @@
+#include "util/bitmap.h"
+#include "box.h"
+
+#include "menu/menu.h"
+
+#include "util/font.h"
+
+using namespace Gui;
+
+Box::Box(){
+ // Nothing yet
+}
+
+Box::Box( const Box & b ){
+ this->location = b.location;
+ this->workArea = b.workArea;
+}
+
+Box::~Box(){
+ // Nothing yet
+}
+
+Box &Box::operator=( const Box ©){
+ location = copy.location;
+ workArea = copy.workArea;
+
+ return *this;
+}
+
+// Logic
+void Box::act(const Font & font){
+ // Nothing yet
+}
+
+// Render
+void Box::render(const Bitmap & work){
+ checkWorkArea();
+ // Check if we are using a rounded box
+ if (location.getRadius() > 0){
+ roundRectFill(*workArea, (int)location.getRadius(), 0, 0, location.getWidth()-1, location.getHeight()-1, colors.body);
+ roundRect(*workArea, (int)location.getRadius(), 0, 0, location.getWidth()-1, location.getHeight()-1, colors.border);
+ } else {
+ workArea->rectangleFill(0, 0, location.getWidth()-1, location.getHeight()-1, colors.body );
+ workArea->rectangle(0, 0, location.getWidth()-1, location.getHeight()-1, colors.border );
+ }
+ Bitmap::transBlender( 0, 0, 0, colors.bodyAlpha );
+ // workArea->drawingMode( Bitmap::MODE_TRANS );
+ workArea->drawTrans(location.getX(), location.getY(), work);
+ // work.drawingMode( Bitmap::MODE_SOLID );
+}
+
+void Box::messageDialog(int centerWidth, int centerHeight, const std::string & message, int radius){
+ /* FIXME Get rid of this */
+ #if 0
+ const Font &vFont = Font::getFont(OldMenu::Menu::getFont(),OldMenu::Menu::getFontWidth(),OldMenu::Menu::getFontHeight());
+ const int width = vFont.textLength(message.c_str()) + 10;
+ const int height = vFont.getHeight() + 10;
+ const int x = (centerWidth/2) - (width/2);
+ const int y = (centerHeight/2) - (height/2);
+ Box dialog;
+ dialog.location.setDimensions(width, height);
+ dialog.location.setRadius(radius);
+ dialog.colors.body = Bitmap::makeColor(0,0,0);
+ dialog.colors.bodyAlpha = 200;
+ dialog.colors.border = Bitmap::makeColor(255,255,255);
+ dialog.colors.borderAlpha = 255;
+ Bitmap temp = Bitmap::temporaryBitmap(width,height);
+ dialog.render(temp);
+ vFont.printf( 5, 5, Bitmap::makeColor(255,255,255), temp, message, -1);
+ temp.BlitToScreen(x,y);
+ #endif
+}
diff --git a/util/gui/box.h b/util/gui/box.h
new file mode 100644
index 00000000..1d104073
--- /dev/null
+++ b/util/gui/box.h
@@ -0,0 +1,34 @@
+#ifndef _paintown_gui_box_h
+#define _paintown_gui_box_h
+
+#include <string>
+
+#include "widget.h"
+
+namespace Gui{
+
+class Box : public Widget {
+public:
+ Box();
+ Box( const Box & b );
+ virtual ~Box();
+
+ // copy
+ Box &operator=( const Box &);
+
+ // Logic
+ virtual void act(const Font &);
+
+ // Render
+ using Widget::render;
+ virtual void render(const Bitmap &);
+
+ // Do a message Dialog centered with respect to the given width/height
+ static void messageDialog(int width, int height, const std::string & message, int radius = 0);
+
+protected:
+};
+
+}
+
+#endif
diff --git a/util/gui/container.cpp b/util/gui/container.cpp
new file mode 100644
index 00000000..8a289120
--- /dev/null
+++ b/util/gui/container.cpp
@@ -0,0 +1,50 @@
+#include "container.h"
+
+#include "../bitmap.h"
+#include "widget.h"
+
+using namespace Gui;
+
+Container::Container()
+{
+ // Nothing yet
+}
+
+Container::~Container()
+{
+ // Nothing yet
+}
+
+// Add widget
+void Container::add(Widget *widget)
+{
+ widgets.push_back(widget);
+}
+
+// Remove widget
+void Container::remove(Widget *widget)
+{
+ widgets.remove(widget);
+}
+
+// Logic
+void Container::act(const Font & font){
+ std::list<Widget *>::iterator i = widgets.begin(), end = widgets.end();
+ while(i!=end){
+ (*i)->act(font);
+ i++;
+ }
+}
+
+// Render
+void Container::render(const Bitmap & work)
+{
+ work.setClipRect(position.x,position.y,position.getX2(),position.getY2());
+ std::list<Widget *>::iterator i = widgets.begin(), end = widgets.end();
+ while(i!=end)
+ {
+ (*i)->render(work);
+ i++;
+ }
+ work.setClipRect(0,0,work.getWidth(),work.getHeight());
+}
diff --git a/util/gui/container.h b/util/gui/container.h
new file mode 100644
index 00000000..8cd09234
--- /dev/null
+++ b/util/gui/container.h
@@ -0,0 +1,40 @@
+#ifndef _paintown_gui_container_h
+#define _paintown_gui_container_h
+
+#include <list>
+#include "rectarea.h"
+
+class Bitmap;
+class Font;
+
+namespace Gui{
+
+class Widget;
+
+class Container{
+public:
+ Container();
+ virtual ~Container();
+
+ // position info
+ RectArea position;
+
+ // Logic
+ void act(const Font & font);
+
+ // Render
+ void render(const Bitmap &);
+
+ // Add widget
+ void add(Widget *widget);
+
+ // Remove widget
+ void remove(Widget *widget);
+
+private:
+ std::list<Widget *>widgets;
+};
+
+}
+
+#endif
diff --git a/util/gui/context-box.cpp b/util/gui/context-box.cpp
new file mode 100644
index 00000000..12c47a8b
--- /dev/null
+++ b/util/gui/context-box.cpp
@@ -0,0 +1,332 @@
+#include "util/bitmap.h"
+#include "util/trans-bitmap.h"
+
+#include "context-box.h"
+#include "util/font.h"
+
+static const double FONT_SPACER = 1.3;
+static const int GradientMax = 50;
+
+static int selectedGradientStart(){
+ static int color = Bitmap::makeColor(19, 167, 168);
+ return color;
+}
+
+static int selectedGradientEnd(){
+ static int color = Bitmap::makeColor(27, 237, 239);
+ return color;
+}
+
+using namespace std;
+using namespace Gui;
+
+ContextItem::ContextItem(){
+}
+ContextItem::~ContextItem(){
+}
+bool ContextItem::isAdjustable(){
+ return false;
+}
+int ContextItem::getLeftColor(){
+ return 0;
+}
+int ContextItem::getRightColor(){
+ return 0;
+}
+
+ContextBox::ContextBox():
+current(0),
+fadeState(NotActive),
+/*
+fontWidth(0),
+fontHeight(0),
+*/
+fadeSpeed(12),
+fadeAlpha(0),
+cursorCenter(0),
+cursorLocation(0),
+scrollWait(4),
+selectedGradient(GradientMax, selectedGradientStart(), selectedGradientEnd()),
+useGradient(true),
+renderOnlyText(false){
+}
+ContextBox::ContextBox( const ContextBox & copy ):
+current(0),
+fadeState(NotActive),
+selectedGradient(GradientMax, selectedGradientStart(), selectedGradientEnd()),
+renderOnlyText(false){
+ this->context = copy.context;
+ /*
+ this->font = copy.font;
+ this->fontWidth = copy.fontWidth;
+ this->fontHeight = copy.fontHeight;
+ */
+ this->fadeSpeed = copy.fadeSpeed;
+ this->fadeAlpha = copy.fadeAlpha;
+ this->cursorCenter = copy.cursorCenter;
+ this->cursorLocation = copy.cursorLocation;
+ this->scrollWait = copy.scrollWait;
+ this->useGradient = copy.useGradient;
+ this->renderOnlyText = copy.renderOnlyText;
+}
+ContextBox::~ContextBox(){
+}
+ContextBox & ContextBox::operator=( const ContextBox & copy){
+ this->current = 0;
+ this->fadeState = NotActive;
+ this->context = copy.context;
+ /*
+ this->font = copy.font;
+ this->fontWidth = copy.fontWidth;
+ this->fontHeight = copy.fontHeight;
+ */
+ this->fadeSpeed = copy.fadeSpeed;
+ this->fadeAlpha = copy.fadeAlpha;
+ this->cursorCenter = copy.cursorCenter;
+ this->cursorLocation = copy.cursorLocation;
+ this->scrollWait = copy.scrollWait;
+ this->useGradient = copy.useGradient;
+ this->renderOnlyText = copy.renderOnlyText;
+ return *this;
+}
+
+void ContextBox::act(const Font & font){
+ // update board
+ board.act(font);
+
+ // Calculate text info
+ calculateText(font);
+
+ // do fade
+ doFade();
+
+ // Update gradient
+ selectedGradient.update();
+}
+
+void ContextBox::render(const Bitmap & work){
+}
+
+void ContextBox::render(const Bitmap & work, const Font & font){
+
+ if (!renderOnlyText){
+ board.render(work);
+ }
+ drawText(work, font);
+}
+
+bool ContextBox::next(const Font & font){
+ if (fadeState == FadeOut){
+ return false;
+ }
+
+ /*
+ const Font & vFont = Font::getFont(font, fontWidth, fontHeight);
+ */
+ cursorLocation += (int)(font.getHeight()/FONT_SPACER);
+
+ if (current < context.size()-1){
+ current++;
+ } else {
+ current = 0;
+ }
+ return true;
+}
+
+bool ContextBox::previous(const Font & font){
+ if (fadeState == FadeOut){
+ return false;
+ }
+
+ /*
+ const Font & vFont = Font::getFont(font, fontWidth, fontHeight);
+ */
+ cursorLocation -= (int)(font.getHeight()/FONT_SPACER);
+
+ if (current > 0){
+ current--;
+ } else {
+ current = context.size()-1;
+ }
+ return true;
+}
+
+void ContextBox::adjustLeft(){
+}
+
+void ContextBox::adjustRight(){
+}
+
+void ContextBox::open(){
+ // Set the fade stuff
+ fadeState = FadeIn;
+ //board.position = position;
+ board.location = location;
+ board.colors = colors;
+ board.open();
+ fadeAlpha = 0;
+ cursorLocation = 0;
+}
+
+void ContextBox::close(){
+ fadeState = FadeOut;
+ board.close();
+ fadeAlpha = 255;
+ cursorLocation = 480;
+}
+
+
+void ContextBox::doFade(){
+ switch ( fadeState ){
+ case FadeIn: {
+ if (fadeAlpha < 255){
+ fadeAlpha += (fadeSpeed+2);
+ }
+
+ if (fadeAlpha >= 255){
+ fadeAlpha = 255;
+ if (board.isActive()){
+ fadeState = Active;
+ }
+ }
+ break;
+ }
+ case FadeOut: {
+ if (fadeAlpha > 0){
+ fadeAlpha -= (fadeSpeed+2);
+ }
+
+ if (fadeAlpha <= 0){
+ fadeAlpha = 0;
+ if (!board.isActive()){
+ fadeState = NotActive;
+ }
+ }
+ break;
+ }
+ case Active:
+ case NotActive:
+ default:
+ break;
+ }
+}
+
+void ContextBox::calculateText(const Font & vFont){
+ if (context.empty()){
+ return;
+ }
+
+ // const Font & vFont = Font::getFont(font, fontWidth, fontHeight);
+
+ cursorCenter = (location.getY() + (int)location.getHeight()/2) - vFont.getHeight()/2;//(position.y + (int)position.height/2) - vFont.getHeight()/2;
+
+ if (cursorLocation == cursorCenter){
+ scrollWait = 4;
+ } else {
+ if (scrollWait <= 0){
+ cursorLocation = (cursorLocation + cursorCenter)/2;
+ scrollWait = 4;
+ } else {
+ scrollWait--;
+ }
+ }
+}
+
+void ContextBox::drawText(const Bitmap & bmp, const Font & vFont){
+ if (context.empty()){
+ return;
+ }
+ // const Font & vFont = Font::getFont(font, fontWidth, fontHeight);
+ const int x1 = board.getArea().getX()+(int)(board.getArea().getRadius()/2);
+ const int y1 = board.getArea().getY()+2;//(board.getArea().radius/2);
+ const int x2 = board.getArea().getX2()-(int)(board.getArea().getRadius()/2);
+ const int y2 = board.getArea().getY2()-2;//(board.getArea().radius/2);
+
+ bmp.setClipRect(x1, y1, x2, y2);
+ int locationY = cursorLocation;
+ int currentOption = current;
+ int count = 0;
+ while (locationY < location.getX2() + vFont.getHeight()){
+ const int startx = (location.getWidth()/2)-(vFont.textLength(context[currentOption]->getName().c_str())/2);
+ if (count == 0){
+ Bitmap::transBlender(0, 0, 0, fadeAlpha);
+ TranslucentBitmap translucent(bmp);
+ // Bitmap::drawingMode( Bitmap::MODE_TRANS );
+ const int color = useGradient ? selectedGradient.current() : selectedGradientStart();
+ vFont.printf(location.getX() + startx, locationY, color, translucent, context[currentOption]->getName(), 0 );
+ if (context[currentOption]->isAdjustable()){
+ const int triangleSize = 14;
+ int cx = (location.getX() + startx) - 15;
+ int cy = (int)(locationY + (vFont.getHeight()/FONT_SPACER) / 2 + 2);
+
+ /*
+ int cx1 = cx + triangleSize / 2;
+ int cy1 = cy - triangleSize / 2;
+ int cx2 = cx - triangleSize;
+ int cy2 = cy;
+ int cx3 = cx + triangleSize / 2;
+ int cy3 = cy + triangleSize / 2;
+ */
+
+ /* do the triangles need to be translucent? */
+ // translucent.triangle(cx1, cy1, cx2, cy2, cx3, cy3, context[currentOption]->getLeftColor());
+ translucent.equilateralTriangle(cx, cy, 180, triangleSize, context[currentOption]->getLeftColor());
+
+ cx = (location.getX()+startx + vFont.textLength(context[currentOption]->getName().c_str()))+15;
+ translucent.equilateralTriangle(cx, cy, 0, triangleSize, context[currentOption]->getLeftColor());
+ // translucent.triangle( cx - triangleSize / 2, cy - triangleSize / 2, cx + triangleSize, cy, cx - triangleSize / 2, cy + triangleSize / 2, context[currentOption]->getRightColor() );
+ }
+ // Bitmap::drawingMode(Bitmap::MODE_SOLID);
+ } else {
+ int textAlpha = fadeAlpha - (count * 35);
+ if (textAlpha < 0){
+ textAlpha = 0;
+ }
+ Bitmap::transBlender(0, 0, 0, textAlpha);
+ // Bitmap::drawingMode( Bitmap::MODE_TRANS );
+ const int color = Bitmap::makeColor(255,255,255);
+ vFont.printf(location.getX() + startx, locationY, color, bmp.translucent(), context[currentOption]->getName(), 0 );
+ // Bitmap::drawingMode( Bitmap::MODE_SOLID );
+ }
+ if (context.size() == 1){
+ bmp.setClipRect(0, 0, bmp.getWidth(), bmp.getHeight());
+ return;
+ }
+ currentOption++;
+ if (currentOption == (int)context.size()){
+ currentOption = 0;
+ }
+ locationY += (int)(vFont.getHeight()/FONT_SPACER);
+ count++;
+ /*if (context.size() < 2 && count == 2){
+ break;
+ }*/
+ }
+ locationY = cursorLocation - (int)(vFont.getHeight()/FONT_SPACER);
+ currentOption = current;
+ currentOption--;
+ count = 0;
+ while (locationY > location.getX() - vFont.getHeight()){
+ if (currentOption < 0){
+ currentOption = context.size()-1;
+ }
+ const int startx = (location.getWidth()/2)-(vFont.textLength(context[currentOption]->getName().c_str())/2);
+ int textAlpha = fadeAlpha - (count * 35);
+ if (textAlpha < 0){
+ textAlpha = 0;
+ }
+ Bitmap::transBlender(0, 0, 0, textAlpha);
+ // Bitmap::drawingMode( Bitmap::MODE_TRANS );
+ const int color = Bitmap::makeColor(255,255,255);
+ vFont.printf(location.getX() + startx, locationY, color, bmp.translucent(), context[currentOption]->getName(), 0 );
+ // Bitmap::drawingMode( Bitmap::MODE_SOLID );
+ currentOption--;
+ locationY -= (int)(vFont.getHeight()/FONT_SPACER);
+ count++;
+ /*if (context.size() < 2 && count == 1){
+ break;
+ }*/
+ }
+ bmp.setClipRect(0, 0, bmp.getWidth(), bmp.getHeight());
+}
+
diff --git a/util/gui/context-box.h b/util/gui/context-box.h
new file mode 100644
index 00000000..53f4dc1a
--- /dev/null
+++ b/util/gui/context-box.h
@@ -0,0 +1,151 @@
+#ifndef _paintown_gui_context_box_h
+#define _paintown_gui_context_box_h
+
+#include <string>
+#include <vector>
+
+#include "widget.h"
+#include "popup-box.h"
+
+#include "../gradient.h"
+#include "../file-system.h"
+
+namespace Gui{
+
+class ContextItem{
+ public:
+ ContextItem();
+ virtual ~ContextItem();
+
+ virtual const std::string getName() = 0;
+ virtual bool isAdjustable();
+ virtual int getLeftColor();
+ virtual int getRightColor();
+};
+
+class ContextBox : public Widget {
+ public:
+ ContextBox();
+ ContextBox(const ContextBox &);
+ virtual ~ContextBox();
+
+ //! copy
+ ContextBox &operator=(const ContextBox &);
+ //! Logic
+ virtual void act(const Font &);
+ //! Render
+ using Widget::render;
+ virtual void render(const Bitmap &);
+ virtual void render(const Bitmap &, const Font & font);
+ //! Next
+ virtual bool next(const Font &);
+ //! Previous
+ virtual bool previous(const Font &);
+ //! Adjust left
+ virtual void adjustLeft();
+ //! Adjust right
+ virtual void adjustRight();
+ //! open context box
+ virtual void open();
+ //! Close context box
+ virtual void close();
+ //! Set context list
+ virtual inline void setList(const std::vector<ContextItem *> & list){
+ this->context = list;
+ this->current = 0;
+ }
+ //! Set current font
+ /*
+ virtual inline void setFont(const Filesystem::RelativePath & font, int width, int height){
+ this->font = font;
+ this->fontWidth = width;
+ this->fontHeight = height;
+ }
+ */
+ //! Get current index
+ virtual inline unsigned int getCurrentIndex(){
+ return this->current;
+ }
+ //! Is active?
+ virtual inline bool isActive(){
+ return (this->fadeState != NotActive);
+ }
+ //!set fadespeed
+ virtual inline void setFadeSpeed(int speed){
+ this->fadeSpeed = speed;
+ this->board.setFadeSpeed(speed);
+ }
+ //!set fade alpha
+ virtual inline void setFadeAlpha(int alpha){
+ this->fadeAlpha = alpha;
+ }
+
+ //! use gradient?
+ virtual inline void setUseGradient(bool useGradient){
+ this->useGradient = useGradient;
+ }
+
+ //! Set to use only text on background
+ virtual inline void setRenderOnlyText(bool render){
+ this->renderOnlyText = render;
+ }
+
+ private:
+
+ void doFade();
+
+ void calculateText(const Font & font);
+
+ void drawText(const Bitmap &, const Font & font);
+
+ enum FadeState{
+ NotActive,
+ FadeIn,
+ Active,
+ FadeOut,
+ };
+ //! Current index
+ unsigned int current;
+
+ //! Current fade state
+ FadeState fadeState;
+
+ //! Context list
+ std::vector<ContextItem *> context;
+
+ //! Current font
+ /*
+ Filesystem::RelativePath font;
+ int fontWidth;
+ int fontHeight;
+ */
+
+ //! Fade speed
+ int fadeSpeed;
+
+ //! Fade Aplha
+ int fadeAlpha;
+
+ //! Board
+ PopupBox board;
+
+ //! The centered position
+ int cursorCenter;
+ //! Current y coordinate to render text from
+ int cursorLocation;
+ //! scroll wait
+ int scrollWait;
+
+ //! Gradient for selected cursor
+ Effects::Gradient selectedGradient;
+
+ //! Use gradient
+ bool useGradient;
+
+ //! Render Text only
+ bool renderOnlyText;
+};
+
+}
+
+#endif
diff --git a/util/gui/coordinate.cpp b/util/gui/coordinate.cpp
new file mode 100644
index 00000000..3c73afee
--- /dev/null
+++ b/util/gui/coordinate.cpp
@@ -0,0 +1,475 @@
+#include "util/bitmap.h"
+#include "coordinate.h"
+#include "globals.h"
+#include "util/load_exception.h"
+#include <sstream>
+
+using namespace Gui;
+
+namespace Gui{
+namespace Space{
+
+Point::Point(double x, double y, const Space & space):
+x(x),
+y(y),
+space(space){
+}
+
+Point::Point(const Point & point, const Space & space):
+space(space){
+ x = space.getLocalX(point.physicalX());
+ y = space.getLocalY(point.physicalY());
+}
+
+Point::Point(const Point & point):
+x(point.x),
+y(point.y),
+space(point.space){
+}
+
+Point & Point::operator=(const Point & point){
+ if (!sameSpace(point)){
+ /* FIXME: throw an error */
+ }
+
+ this->x = point.x;
+ this->y = point.y;
+ return *this;
+}
+
+Point & Point::operator+=(const Point & point){
+ *this = *this + point;
+ return *this;
+}
+
+Point Point::operator+(const Point & point){
+ if (sameSpace(point)){
+ x += point.x;
+ y += point.y;
+ return *this;
+ } else {
+ return *this + Point(point, space);
+ }
+}
+
+bool Point::sameSpace(const Point & point){
+ return space == point.space;
+}
+
+int Point::physicalX() const {
+ return (x * space.sizeX() / 2) + space.centerX();
+}
+
+int Point::physicalY() const {
+ return (y * space.sizeY() / 2) + space.centerY();
+}
+
+Space::Space(double minX, double minY, double maxX, double maxY):
+minX(minX),
+minY(minY),
+maxX(maxX),
+maxY(maxY){
+}
+
+bool Space::operator==(const Space & space) const {
+ if (this == &space){
+ return true;
+ }
+
+ return minX == space.minX &&
+ minY == space.minY &&
+ maxX == space.maxX &&
+ maxY == space.maxY;
+}
+
+Point Space::fromPhysical(int x, int y){
+ return Point(getLocalX(x), getLocalY(y), *this);
+}
+
+double Space::sizeX() const {
+ return maxX - minX;
+}
+
+double Space::sizeY() const {
+ return maxY - minY;
+}
+
+double Space::centerX() const {
+ return (maxX - minX) / 2;
+}
+
+double Space::centerY() const {
+ return (maxY - minY) / 2;
+}
+
+double Space::getLocalX(int physicalX) const {
+ return (physicalX - centerX()) / sizeX();
+}
+
+double Space::getLocalY(int physicalY) const {
+ return (physicalY - centerY()) / sizeY();
+}
+
+}
+}
+
+static int relativeToAbsolute(double x, int center){
+ return (int)(center + (center * x));
+}
+
+static int amountFromCenterX(int x){
+ return x - (640 / 2);
+}
+
+static int amountFromCenterY(int y){
+ return y - (480 / 2);
+}
+
+/* scale an absolute distance to a relative distance
+ * distance / absolute = X / relative
+ * absolute space = 0 to 640
+ * relative space = -1 to 1
+ * X = distance * relative / absolute
+ */
+static double scaleAbsoluteToRelativeDistanceX(int distance){
+ return distance * (1.0 - (-1.0)) / (640.0 - 0);
+}
+
+static double scaleAbsoluteToRelativeDistanceY(int distance){
+ return distance * (1.0 - (-1.0)) / (480.0 - 0);
+}
+
+/* convert a point in absolute space to relative space */
+static double absoluteToRelative(int x, int center){
+ return (double)(x-center)/center;
+}
+
+static double relativeToAbsoluteX(double x){
+ // return relativeToAbsolute(x, Global::getScreenWidth() / 2);
+ return relativeToAbsolute(x, 640 / 2);
+}
+
+static double relativeToAbsoluteY(double y){
+ // return relativeToAbsolute(y, Global::getScreenHeight() / 2);
+ return relativeToAbsolute(y, 480 / 2);
+}
+
+static double absoluteToRelativeX(int x){
+ return absoluteToRelative(x, 640/2);
+}
+
+static double absoluteToRelativeY(int y){
+ return absoluteToRelative(y, 480/2);
+}
+
+AbsolutePoint::AbsolutePoint():
+x(0),
+y(0){
+}
+AbsolutePoint::AbsolutePoint(int x, int y):
+x(x),
+y(y){
+}
+AbsolutePoint::AbsolutePoint(const AbsolutePoint & copy):
+x(copy.x),
+y(copy.y){
+}
+AbsolutePoint::~AbsolutePoint(){
+}
+
+const AbsolutePoint & AbsolutePoint::operator=(const AbsolutePoint & copy){
+ this->x = copy.x;
+ this->y = copy.y;
+ return *this;
+}
+
+int AbsolutePoint::getX() const {
+ return x;
+}
+
+int AbsolutePoint::getY() const {
+ return y;
+}
+
+RelativePoint::RelativePoint():
+x(0),
+y(0){
+}
+
+RelativePoint::RelativePoint(double x, double y):
+x(x),
+y(y){
+}
+
+RelativePoint::RelativePoint(const RelativePoint & copy):
+x(copy.x),
+y(copy.y){
+}
+
+RelativePoint::RelativePoint(const AbsolutePoint & point):
+x(absoluteToRelativeX(point.getX())),
+y(absoluteToRelativeY(point.getY())){
+}
+
+RelativePoint::~RelativePoint(){
+}
+
+const RelativePoint & RelativePoint::operator=(const RelativePoint & copy){
+ this->x = copy.x;
+ this->y = copy.y;
+ return *this;
+}
+const RelativePoint & RelativePoint::operator=(const AbsolutePoint & point){
+ this->x = absoluteToRelativeX(point.getX());
+ this->y = absoluteToRelativeY(point.getY());
+ return *this;
+}
+bool RelativePoint::operator==(const RelativePoint & point){
+ return (this->x == point.x && this->y == point.y);
+}
+bool RelativePoint::operator!=(const RelativePoint & point){
+ return !(*this == point);
+}
+
+int RelativePoint::getX() const{
+ return relativeToAbsoluteX(x);
+}
+
+int RelativePoint::getY() const{
+ return relativeToAbsoluteY(y);
+}
+
+int RelativePoint::getDistanceFromCenterX(){
+ return amountFromCenterX(getX());
+}
+
+int RelativePoint::getDistanceFromCenterY(){
+ return amountFromCenterY(getY());
+}
+
+void RelativePoint::moveX(double percent){
+ x += percent;
+}
+
+void RelativePoint::moveY(double percent){
+ y += percent;
+}
+
+void RelativePoint::moveBy(double x, double y){
+ moveX(x);
+ moveY(y);
+}
+
+AbsolutePoint RelativePoint::getAbsolute(){
+ return AbsolutePoint(relativeToAbsoluteX(x), relativeToAbsoluteY(y));
+}
+
+double RelativePoint::getRelativeX() const{
+ return x;
+}
+
+double RelativePoint::getRelativeY() const{
+ return y;
+}
+
+Coordinate::Coordinate():
+z(0),
+radius(0){
+}
+
+Coordinate::Coordinate(AbsolutePoint & position, AbsolutePoint & position2):
+position(position),
+position2(position2),
+z(0),
+radius(0){
+}
+
+Coordinate::Coordinate(const RelativePoint & position, const RelativePoint & position2):
+position(position),
+position2(position2),
+z(0),
+radius(0){
+}
+
+Coordinate::Coordinate(const Coordinate & copy):
+position(copy.position),
+position2(copy.position2),
+z(copy.z),
+radius(copy.radius){
+}
+
+Coordinate::~Coordinate(){
+}
+
+const Coordinate & Coordinate::operator=(const Coordinate & copy){
+ this->position = copy.position;
+ this->position2 = copy.position2;
+ this->z = copy.z;
+ this->radius = copy.radius;
+
+ return *this;
+}
+
+int Coordinate::getX() const{
+ return position.getX();
+}
+int Coordinate::getY() const{
+ return position.getY();
+}
+
+int Coordinate::getWidth() const {
+ return position2.getX() - position.getX();
+}
+
+int Coordinate::getHeight() const {
+ return position2.getY() - position.getY();
+}
+
+int Coordinate::getX2() const{
+ return position2.getX();
+}
+int Coordinate::getY2() const{
+ return position2.getY();
+}
+
+void Coordinate::growHorizontal(double by){
+ position.moveX(-(by));
+ position2.moveX(by);
+}
+
+void Coordinate::growHorizontalAbsolute(int distance){
+ growHorizontal(scaleAbsoluteToRelativeDistanceX(distance));
+}
+
+void Coordinate::growVerticalAbsolute(int distance){
+ growVertical(scaleAbsoluteToRelativeDistanceY(distance));
+}
+
+void Coordinate::growVertical(double by){
+ position.moveY(-(by));
+ position2.moveY(by);
+}
+
+void Coordinate::growTo(const Coordinate & coord, double percent){
+ if (position.getRelativeX() > coord.position.getRelativeX()){
+ position.moveX(-(percent));
+ if (position.getRelativeX() < coord.position.getRelativeX()){
+ position.setX(coord.position.getRelativeX());
+ }
+ } else if (position.getRelativeX() < coord.position.getRelativeX()){
+ position.moveX(percent);
+ if (position.getRelativeX() > coord.position.getRelativeX()){
+ position.setX(coord.position.getRelativeX());
+ }
+ }
+ if (position.getRelativeY() > coord.position.getRelativeY()){
+ position.moveY(-(percent));
+ if (position.getRelativeY() < coord.position.getRelativeY()){
+ position.setY(coord.position.getRelativeY());
+ }
+ } else if (position.getRelativeY() < coord.position.getRelativeY()){
+ position.moveY(percent);
+ if (position.getRelativeY() > coord.position.getRelativeY()){
+ position.setY(coord.position.getRelativeY());
+ }
+ }
+ if (position2.getRelativeX() > coord.position2.getRelativeX()){
+ position2.moveX(-(percent));
+ if (position2.getRelativeX() < coord.position2.getRelativeX()){
+ position2.setX(coord.position2.getRelativeX());
+ }
+ } else if (position2.getRelativeX() < coord.position2.getRelativeX()){
+ position2.moveX(percent);
+ if (position2.getRelativeX() > coord.position2.getRelativeX()){
+ position2.setX(coord.position2.getRelativeX());
+ }
+ }
+ if (position2.getRelativeY() > coord.position2.getRelativeY()){
+ position2.moveY(-(percent));
+ if (position2.getRelativeY() < coord.position2.getRelativeY()){
+ position2.setY(coord.position2.getRelativeY());
+ }
+ } else if (position2.getRelativeY() < coord.position2.getRelativeY()){
+ position2.moveY(percent);
+ if (position2.getRelativeY() > coord.position2.getRelativeY()){
+ position2.setY(coord.position2.getRelativeY());
+ }
+ }
+}
+
+void Coordinate::center(const Coordinate & coord){
+ const double centerx = (coord.getRelativeX1() + coord.getRelativeX2())/2;
+ const double centery = (coord.getRelativeY1() + coord.getRelativeY2())/2;
+
+ set(centerx, centery, centerx, centery);
+}
+
+void Coordinate::moveBy(double x, double y){
+ position.moveBy(x, y);
+ position2.moveBy(x, y);
+}
+
+bool Coordinate::operator==( const Coordinate & coord){
+ return ( (position == coord.position) &&
+ (position2 == coord.position2));
+}
+
+bool Coordinate::operator!=( const Coordinate & coord){
+ return ( !(position == coord.position) ||
+ !(position2 == coord.position2));
+}
+
+bool Coordinate::operator==( const Bitmap & bmp){
+ return ( (getWidth() == bmp.getWidth()) &&
+ (getHeight() == bmp.getHeight()));
+}
+
+bool Coordinate::operator!=( const Bitmap & bmp){
+ return !(*this == bmp);
+}
+
+void Coordinate::setPosition(const RelativePoint & point){
+ position = point;
+}
+
+void Coordinate::setPosition(const AbsolutePoint & point){
+ position = RelativePoint(point);
+}
+
+void Coordinate::setPosition2(const RelativePoint & point){
+ position2 = point;
+}
+
+void Coordinate::setPosition2(const AbsolutePoint & point){
+ position2 = RelativePoint(point);
+}
+
+void Coordinate::moveTo(const AbsolutePoint & where){
+ double dx = position2.getRelativeX() - position.getRelativeX();
+ double dy = position2.getRelativeY() - position.getRelativeY();
+ setPosition(where);
+
+ /* sort of ugly, use operator+ for RelativePosition */
+ setPosition2(RelativePoint(position.getRelativeX() + dx, position.getRelativeY() + dy));
+}
+
+void Coordinate::checkDimensions(){
+ if (getWidth() < 0 || getHeight() < 0){
+ std::ostringstream out;
+ out << "Cannot have a negative coordinate dimension " << getWidth() << ", " << getHeight();
+ throw LoadException(__FILE__, __LINE__, out.str());
+ }
+}
+
+void Coordinate::setDimensions(int width, int height){
+ position2 = RelativePoint(AbsolutePoint(getX() + width, getY() + height));
+}
+
+void Coordinate::setCenterPosition(const RelativePoint & center){
+ int width = getWidth();
+ int height = getHeight();
+ this->position = center;
+ this->position2 = center;
+ growHorizontalAbsolute(width / 2.0);
+ growVerticalAbsolute(height / 2.0);
+}
diff --git a/util/gui/coordinate.h b/util/gui/coordinate.h
new file mode 100644
index 00000000..0fbb1f1b
--- /dev/null
+++ b/util/gui/coordinate.h
@@ -0,0 +1,231 @@
+#ifndef _paintown_gui_coordinate_h
+#define _paintown_gui_coordinate_h
+
+class Bitmap;
+
+namespace Gui {
+
+namespace Space{
+
+class Space;
+/* a 2-d point */
+class Point{
+public:
+ Point(double x, double y, const Space & space);
+ Point(const Point & point, const Space & space);
+ Point(const Point & point);
+
+ Point operator+(const Point &);
+ Point & operator+=(const Point &);
+ Point & operator=(const Point &);
+
+ /* convert to physical space */
+ int physicalX() const;
+ int physicalY() const;
+
+ double x;
+ double y;
+ const Space & space;
+private:
+ /* true if points use the same space system */
+ bool sameSpace(const Point & point);
+};
+
+/* mapping from coordinate space to physical space */
+class Space{
+public:
+ Space(double minX, double minY, double maxX, double maxY);
+ Point fromPhysical(int x, int y);
+
+ bool operator==(const Space & space) const;
+
+ double sizeX() const;
+ double sizeY() const;
+ double centerX() const;
+ double centerY() const;
+ double getLocalX(int physicalX) const;
+ double getLocalY(int physicalY) const;
+private:
+ double minX, minY, maxX, maxY;
+};
+
+}
+
+/* Coordinate system for handling scalable graphics */
+
+class AbsolutePoint {
+ public:
+ AbsolutePoint();
+ explicit AbsolutePoint(int x, int y);
+ AbsolutePoint(const AbsolutePoint &);
+ virtual ~AbsolutePoint();
+
+ const AbsolutePoint & operator=(const AbsolutePoint &);
+ virtual inline void setX(int x){
+ this->x = x;
+ }
+ virtual int getX() const;
+ virtual inline void setY(int y){
+ this->y = y;
+ }
+ virtual int getY() const;
+ private:
+ int x;
+ int y;
+};
+
+class RelativePoint {
+ public:
+ RelativePoint();
+ explicit RelativePoint(double x, double y);
+ RelativePoint(const RelativePoint &);
+ RelativePoint(const AbsolutePoint &);
+ virtual ~RelativePoint();
+
+ const RelativePoint & operator=(const RelativePoint &);
+ const RelativePoint & operator=(const AbsolutePoint &);
+ bool operator==(const RelativePoint &);
+ bool operator!=(const RelativePoint &);
+ virtual inline void setX(double x){
+ this->x = x;
+ }
+ virtual int getX() const;
+ virtual inline void setY(double y){
+ this->y = y;
+ }
+ virtual int getY() const;
+ virtual inline void set(double x, double y){
+ this->x = x;
+ this->y = y;
+ }
+ virtual int getDistanceFromCenterX();
+ virtual int getDistanceFromCenterY();
+ virtual void moveX(double percent);
+ virtual void moveY(double percent);
+ virtual void moveBy(double x, double y);
+ virtual AbsolutePoint getAbsolute();
+ virtual double getRelativeX() const;
+ virtual double getRelativeY() const;
+ private:
+ double x;
+ double y;
+};
+
+class Coordinate {
+ public:
+ Coordinate();
+ Coordinate(AbsolutePoint &, AbsolutePoint &);
+ Coordinate(const RelativePoint &, const RelativePoint &);
+ Coordinate(const Coordinate &);
+ virtual ~Coordinate();
+
+ const Coordinate & operator=(const Coordinate &);
+
+ virtual inline void setZ(double z){
+ this->z = z;
+ }
+ virtual inline double getZ() const{
+ return this->z;
+ }
+ virtual inline void setRadius(double radius){
+ this->radius = radius;
+ }
+ virtual inline double getRadius() const{
+ return this->radius;
+ }
+
+ virtual int getX() const;
+ virtual int getY() const;
+ virtual int getWidth() const;
+ virtual int getHeight() const;
+ virtual int getX2() const;
+ virtual int getY2() const;
+ /* give a relative quantity */
+ virtual void growHorizontal(double by);
+ /* give an absolute quantity */
+ virtual void growHorizontalAbsolute(int by);
+ /* give a relative quantity */
+ virtual void growVertical(double by);
+ /* give an absolute quantity */
+ virtual void growVerticalAbsolute(int by);
+
+ virtual void growTo(const Coordinate &, double percent = 0.005);
+ virtual void center(const Coordinate &);
+ virtual void moveBy(double x, double y);
+ virtual inline double getRelativeX1() const{
+ return this->position.getRelativeX();
+ }
+ virtual inline double getRelativeX2() const{
+ return this->position2.getRelativeX();
+ }
+ virtual inline double getRelativeY1() const{
+ return this->position.getRelativeY();
+ }
+ virtual inline double getRelativeY2() const{
+ return this->position2.getRelativeY();
+ }
+
+ virtual inline void set(double x1, double y1, double x2, double y2){
+ this->position.setX(x1);
+ this->position.setY(y1);
+ this->position2.setX(x2);
+ this->position2.setY(y2);
+ }
+
+ virtual inline void setX1(double x){
+ this->position.setX(x);
+ }
+ virtual inline void setX2(double x){
+ this->position2.setX(x);
+ }
+ virtual inline void setY1(double y){
+ this->position.setY(y);
+ }
+ virtual inline void setY2(double y){
+ this->position2.setY(y);
+ }
+
+ bool operator==( const Coordinate &);
+ bool operator!=( const Coordinate &);
+ bool operator==( const Bitmap &);
+ bool operator!=( const Bitmap &);
+
+ /* moves the positions so that `center' is in the middle but the
+ * width/height is maintained
+ */
+ virtual void setCenterPosition(const RelativePoint & center);
+
+ virtual void setPosition(const RelativePoint &);
+ virtual void setPosition(const AbsolutePoint &);
+ virtual void setPosition2(const RelativePoint &);
+ virtual void setPosition2(const AbsolutePoint &);
+
+ virtual void moveTo(const AbsolutePoint &);
+
+ virtual void setDimensions(int width, int height);
+
+ virtual inline RelativePoint & getPosition(){
+ return this->position;
+ }
+
+ virtual inline RelativePoint & getPosition2(){
+ return this->position2;
+ }
+
+ virtual inline bool empty(){
+ return (getWidth() == 0 && getHeight() == 0);
+ }
+
+ private:
+ void checkDimensions();
+
+ RelativePoint position;
+ RelativePoint position2;
+ double z;
+ double radius;
+};
+
+}
+
+
+#endif
diff --git a/util/gui/fadetool.cpp b/util/gui/fadetool.cpp
new file mode 100644
index 00000000..d960e861
--- /dev/null
+++ b/util/gui/fadetool.cpp
@@ -0,0 +1,152 @@
+#include "fadetool.h"
+#include "../bitmap.h"
+#include "../trans-bitmap.h"
+#include "../token.h"
+#include "../load_exception.h"
+
+using namespace Gui;
+
+FadeTool::FadeTool():
+currentState(FadeIn),
+lastState(FadeIn),
+fadeTime(0),
+fadeInTime(0),
+fadeOutTime(0),
+fadeInColor(Bitmap::makeColor(0,0,0)),
+fadeOutColor(Bitmap::makeColor(0,0,0)){
+}
+
+FadeTool::~FadeTool(){
+}
+
+void FadeTool::parseDefaults(const Token * token){
+ if ( *token != "fade" ){
+ throw LoadException(__FILE__, __LINE__, "Not a fader");
+ }
+ /*!
+ * (fade
+ (in (color 0 0 0) (time 0) )
+ (out (color 0 0 0) (time 0) ))
+ */
+ const Token & ourToken = *token;
+ TokenView view = ourToken.view();
+ /* FIXME: this code looks like its expecting a structure like
+ * (in (color ...) (out ...))
+ * But its not parsing that way, rewrite it
+ */
+ while (view.hasMore()){
+ try{
+ const Token * tok;
+ view >> tok;
+ if (*tok == "in"){
+ TokenView inView = tok->view();
+ /* FIXME: this loop is pretty wierd, shouldn't the if's be on the outside? */
+ while (inView.hasMore()){
+ if (*tok == "color"){
+ int r=0,g=0,b=0;
+ try {
+ inView >> r >> g >> b;
+ } catch (const TokenException & ex){
+ }
+ setFadeInColor(Bitmap::makeColor(r,b,g));
+ } else if (*tok == "time"){
+ int time=0;
+ try {
+ inView >> time;
+ } catch (const TokenException & ex){
+ }
+ setFadeInTime(time);
+ }
+ }
+ } else if (*tok == "out"){
+ /*
+ Token & out = *tok;
+ while (out.hasTokens()){
+ if (out == "color"){
+ int r=0,g=0,b=0;
+ try {
+ out >> r >> g >> b;
+ } catch (const TokenException & ex){
+ }
+ setFadeOutColor(Bitmap::makeColor(r,b,g));
+ } else if (out == "time"){
+ int time=0;
+ try {
+ out >> time;
+ } catch (const TokenException & ex){
+ }
+ setFadeOutTime(time);
+ }
+ }
+ */
+ }
+ } catch ( const TokenException & ex ) {
+ throw LoadException(__FILE__, __LINE__, ex, "Fade tool parse error");
+ } catch ( const LoadException & ex ) {
+ throw ex;
+ }
+ }
+}
+
+
+void FadeTool::setState( const State & f){
+ lastState = currentState;
+ currentState = f;
+
+ switch (currentState){
+ case FadeIn:
+ fadeTime = 255;
+ break;
+ case FadeOut:
+ fadeTime = 0;
+ break;
+ case NoFade:
+ case EndFade:
+ default:
+ fadeTime = 0;
+ break;
+ }
+}
+
+void FadeTool::act(){
+ switch (currentState){
+ case FadeIn:
+ fadeTime-=(255/(fadeInTime <= 0 ? 1 : fadeInTime));
+ if (fadeTime<=0){
+ setState(NoFade);
+ }
+ break;
+ case FadeOut:
+ fadeTime+=(255/(fadeOutTime <= 0 ? 1 : fadeOutTime));
+ if (fadeTime>=255){
+ setState(EndFade);
+ }
+ break;
+ case NoFade:
+ case EndFade:
+ default:
+ break;
+ }
+}
+
+void FadeTool::draw(const Bitmap &bmp){
+ switch (currentState){
+ case FadeIn:
+ // Bitmap::drawingMode(Bitmap::MODE_TRANS);
+ Bitmap::transBlender(0,0,0,fadeTime);
+ bmp.translucent().rectangleFill(0, 0, bmp.getWidth(),bmp.getHeight(),fadeInColor);
+ // Bitmap::drawingMode(Bitmap::MODE_SOLID);
+ break;
+ case FadeOut:
+ // Bitmap::drawingMode(Bitmap::MODE_TRANS);
+ Bitmap::transBlender(0,0,0,fadeTime);
+ bmp.translucent().rectangleFill(0, 0, bmp.getWidth(),bmp.getHeight(),fadeOutColor);
+ // Bitmap::drawingMode(Bitmap::MODE_SOLID);
+ break;
+ case NoFade:
+ case EndFade:
+ default:
+ break;
+ }
+}
+
diff --git a/util/gui/fadetool.h b/util/gui/fadetool.h
new file mode 100644
index 00000000..b6b1ea0d
--- /dev/null
+++ b/util/gui/fadetool.h
@@ -0,0 +1,76 @@
+#ifndef gui_fadetool_h
+#define gui_fadetool_h
+
+/*! FADE UTILITY */
+
+class Bitmap;
+class Token;
+
+namespace Gui{
+
+class FadeTool{
+public:
+ FadeTool();
+ virtual ~FadeTool();
+
+ enum State{
+ FadeIn,
+ FadeOut,
+ NoFade,
+ EndFade,
+ };
+
+ //! Read info from Token
+ void parseDefaults(const Token *);
+
+ // Fade state
+ void setState(const State &);
+
+ // update
+ void act();
+
+ // Fade to whatever state it is at
+ virtual void draw(const Bitmap &);
+
+ inline const State & getState() const {
+ return currentState;
+ }
+ inline void setFadeInTime(const int time){
+ fadeInTime = time;
+ }
+ inline void setFadeOutTime(const int time){
+ fadeOutTime = time;
+ }
+ inline int getFadeInTime() const {
+ return fadeInTime;
+ }
+ inline int getFadeOutTime() const {
+ return fadeOutTime;
+ }
+ inline void setFadeInColor( int c ){
+ fadeInColor = c;
+ }
+ inline int getFadeInColor() const {
+ return fadeInColor;
+ }
+ inline void setFadeOutColor( int c ){
+ fadeInColor = c;
+ }
+ inline int getFadeOutColor() const {
+ return fadeInColor;
+ }
+private:
+
+ State currentState;
+ State lastState;
+ int fadeTime;
+ int fadeInTime;
+ int fadeOutTime;
+ int fadeInColor;
+ int fadeOutColor;
+
+};
+
+}
+
+#endif
diff --git a/util/gui/keyinput.cpp b/util/gui/keyinput.cpp
new file mode 100644
index 00000000..f3b5a3bc
--- /dev/null
+++ b/util/gui/keyinput.cpp
@@ -0,0 +1,124 @@
+/*
+SAGGUI (Simplified All Gaming Graphical User Interface)
+Copyright (c) 2005-2007, Miguel A. Gavidia
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+ * Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the following
+ disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+ * Neither the name of the "SAGGUI" nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OFkeyinput.cpp
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "keyinput.h"
+#include <iostream>
+#include "globals.h"
+
+/*
+static std::ostream & debug( int level ){
+ Global::debug( level ) << "[key input] ";
+ return Global::debug( level );
+}
+*/
+
+ // Constructor
+ keyInput::keyInput()
+ {
+ //Nothing to do
+ }
+ // Destructor
+ keyInput::~keyInput()
+ {
+ // Nothing to do
+ }
+ // Is queue empty
+ bool keyInput::pressedEmpty()
+ {
+ return pressedQueue.empty();
+ }
+ bool keyInput::releasedEmpty()
+ {
+ return releasedQueue.empty();
+ }
+ // Get the next key on the stack
+ keys keyInput::dequeuePressed()
+ {
+ keys k = pressedQueue.front();
+ pressedQueue.pop();
+ return k;
+ }
+ keys keyInput::dequeueReleased()
+ {
+ keys k = releasedQueue.front();
+ releasedQueue.pop();
+ return k;
+ }
+
+ // Check key without popping
+ keys keyInput::checkNextPressed()
+ {
+ return pressedQueue.front();
+ }
+
+ // Check key without popping
+ keys keyInput::checkNextReleased()
+ {
+ return releasedQueue.front();
+ }
+
+ // Push a key
+ void keyInput::queuePressed(keys k){
+ pressedQueue.push(k);
+ std::map<int, keys>::iterator p;
+ p = pressedKeys.find(k.getValue());
+ if(p == pressedKeys.end())pressedKeys.insert(std::make_pair(k.getValue(),k));
+
+ }
+
+ void keyInput::clear(){
+ int pressedElements = pressedQueue.size();
+ for ( int i = 0; i < pressedElements; i++ ){
+ pressedQueue.pop();
+ }
+ int releasedElements = releasedQueue.size();
+ for ( int i = 0; i < releasedElements; i++ ){
+ releasedQueue.pop();
+ }
+ pressedKeys.clear();
+ }
+
+ // Push a key
+ void keyInput::queueReleased(keys k)
+ {
+ releasedQueue.push(k);
+ std::map<int, keys>::iterator p;
+ p = pressedKeys.find(k.getValue());
+
+ if(p != pressedKeys.end())deleteList.push_back(p);
+ }
diff --git a/util/gui/keyinput.h b/util/gui/keyinput.h
new file mode 100644
index 00000000..37c9f7ed
--- /dev/null
+++ b/util/gui/keyinput.h
@@ -0,0 +1,101 @@
+/*
+SAGGUI (Simplified All Gaming Graphical User Interface)
+Copyright (c) 2005-2007, Miguel A. Gavidia
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+ * Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the following
+ disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+ * Neither the name of the "SAGGUI" nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef KEYINPUT_H
+#define KEYINPUT_H
+
+#include "keys.h"
+#include <queue>
+#include <map>
+#include <utility>
+#include <list>
+
+class keyInput
+{
+ protected:
+ //! Pressed button queue
+ std::queue<keys>pressedQueue;
+
+ //! Released button queue
+ std::queue<keys>releasedQueue;
+
+ //! Map of pressed keys
+ std::map<int,keys>pressedKeys;
+
+ //! Temporary deletion queue
+ std::list< std::map<int, keys>::iterator >deleteList;
+
+ public:
+ //! Constructor
+ keyInput();
+
+ //! Destructor
+ virtual ~keyInput();
+
+ //! Is pressed queue empty
+ bool pressedEmpty();
+
+ //! Is the pressed queue empty?
+ bool releasedEmpty();
+
+ /* clear all buffers */
+ void clear();
+
+ //! Get next pressed key
+ keys dequeuePressed();
+
+ //! Get next released key
+ keys dequeueReleased();
+
+ //! Check key without popping
+ keys checkNextPressed();
+
+ //! Check key without popping
+ keys checkNextReleased();
+
+ //! Insert pressed key
+ void queuePressed(keys k);
+
+ //! Insert released key
+ void queueReleased(keys k);
+
+ //! Poll keyboard input
+ virtual void update()=0;
+};
+
+#endif
diff --git a/util/gui/keyinput_manager.cpp b/util/gui/keyinput_manager.cpp
new file mode 100644
index 00000000..fa246741
--- /dev/null
+++ b/util/gui/keyinput_manager.cpp
@@ -0,0 +1,149 @@
+/*
+SAGGUI (Simplified All Gaming Graphical User Interface)
+Copyright (c) 2005-2007, Miguel A. Gavidia
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+ * Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the following
+ disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+ * Neither the name of the "SAGGUI" nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "al_keyinput.h"
+#include "keyinput_manager.h"
+#include <iostream>
+#include "globals.h"
+#include "util/debug.h"
+
+static std::ostream & debug( int level ){
+ Global::debug( level ) << "[key input manager] ";
+ return Global::debug( level );
+}
+
+#ifdef USE_ALLEGRO
+allegroKeyInput keyInputManager::input;
+#endif
+
+guiTimer keyInputManager::dTimer[keys::MAX];
+unsigned int keyInputManager::delay[keys::MAX];
+bool keyInputManager::keyHolder[keys::MAX];
+bool keyInputManager::keyBlocker[keys::MAX];
+sigslot::signal1<const keys &> keyInputManager::pressed;
+sigslot::signal1<const keys &> keyInputManager::released;
+
+// Mouse Manager Constructor
+keyInputManager::keyInputManager(){
+ //dTimer.reset();
+ //delay = 0;
+ keyHolder[keys::SPACE]=false;
+ keyHolder[keys::TAB]=false;
+ keyHolder[keys::ENTER]=false;
+ keyBlocker[keys::SPACE]=false;
+ keyBlocker[keys::TAB]=false;
+ keyBlocker[keys::ENTER]=false;
+ for(int i=0;i<keys::MAX;++i)
+ {
+ dTimer[i].reset();
+ delay[i]=0;
+ keyHolder[i]=false;
+ keyBlocker[i]=false;
+ }
+}
+
+// Mouse Manager Destructor
+keyInputManager::~keyInputManager(){
+ // nothing
+}
+
+void keyInputManager::clear(){
+#ifdef USE_ALLEGRO
+ input.clear();
+#endif
+}
+
+// Check mouse for changes and fire events
+void keyInputManager::update(){
+ //if(delay<=dTimer.msecs())dTimer.reset();
+
+#ifdef USE_ALLEGRO
+ // update the keyboard
+ input.update();
+ //if(dTimer.msecs()<=delay)
+ //{
+ // Do pressed queue
+ while(!input.pressedEmpty()){
+ keys k = input.checkNextPressed();
+ if(delay[k.getValue()]<=dTimer[k.getValue()].msecs())dTimer[k.getValue()].reset();
+ if(dTimer[k.getValue()].msecs()<=delay[k.getValue()])
+ {
+ input.dequeuePressed();
+ keyHolder[k.getValue()] = true;
+ debug( 5 ) << "Pressed key " << k.getValue() << std::endl;
+ pressed.emit(k);
+ }
+ }
+
+ // Do released queue
+ while(!input.releasedEmpty())
+ {
+ keys k = input.dequeueReleased();
+ keyHolder[k.getValue()] = false;
+ released.emit(k);
+ }
+ //}
+#endif
+}
+
+// Key state
+bool keyInputManager::keyState(int unicode, bool blocking){
+ //if(unicode>255 || unicode<0)return false;
+
+ if(blocking)
+ {
+
+ if(keyHolder[unicode] && !(keyBlocker[unicode]))
+ {
+ keyBlocker[unicode]=true;
+ return true;
+ }
+ else if(!keyHolder[unicode] && keyBlocker[unicode])
+ {
+ keyBlocker[unicode]=false;
+ return false;
+ }
+ return false;
+ }
+ return keyHolder[unicode];
+}
+
+//! Set delay in milleseconds (doesn't effect the keyStates)
+void keyInputManager::setDelay(unsigned int msecs, const keys::keyTypes key){
+ delay[key] = msecs;
+}
diff --git a/util/gui/keyinput_manager.h b/util/gui/keyinput_manager.h
new file mode 100644
index 00000000..20ae390a
--- /dev/null
+++ b/util/gui/keyinput_manager.h
@@ -0,0 +1,90 @@
+/*
+SAGGUI (Simplified All Gaming Graphical User Interface)
+Copyright (c) 2005-2007, Miguel A. Gavidia
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+ * Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the following
+ disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+ * Neither the name of the "SAGGUI" nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef KEYINPUT_MANAGER_H
+#define KEYINPUT_MANAGER_H
+
+#include "keys.h"
+//#include "keyinput.h"
+#include "sigslot.h"
+#include "timer.h"
+
+class allegroKeyInput;
+
+class keyInputManager
+{
+ public:
+ //! Evaluate keyboard and fire events
+ static void update();
+
+ static void clear();
+
+ //! Key state (pass true to enable blocking checking)
+ static bool keyState(int unicode, bool blocking=false);
+
+ //! Set delay in milleseconds (doesn't effect the keyStates)
+ static void setDelay(unsigned int msecs, const keys::keyTypes);
+
+ //! \name Signals
+ static sigslot::signal1<const keys &> pressed;
+ static sigslot::signal1<const keys &> released;
+
+ private:
+ //! Constructor
+ keyInputManager();
+
+ //! Destructor
+ ~keyInputManager();
+
+ //! input pointer
+ static allegroKeyInput input;
+
+ //! Timer for delay
+ static guiTimer dTimer[keys::MAX];
+
+ //! Delay
+ static unsigned int delay[keys::MAX];
+
+ //! Key states
+ static bool keyHolder[keys::MAX];
+
+ //! Blocker state
+ static bool keyBlocker[keys::MAX];
+};
+
+#endif /* KEYINPUT_MANAGER_H */
diff --git a/util/gui/keys.cpp b/util/gui/keys.cpp
new file mode 100644
index 00000000..f9a9927b
--- /dev/null
+++ b/util/gui/keys.cpp
@@ -0,0 +1,98 @@
+/*
+SAGGUI (Simplified All Gaming Graphical User Interface)
+Copyright (c) 2005-2007, Miguel A. Gavidia
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+ * Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the following
+ disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+ * Neither the name of the "SAGGUI" nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "keys.h"
+
+ // Constructor
+ keys::keys()
+ {
+ value = 0;
+ scancode = 0;
+ }
+ keys::keys(int v)
+ {
+ value = v;
+ }
+ keys::keys(int v, int s)
+ {
+ value = v;
+ scancode = s;
+ }
+
+ // Destructor
+ keys::~keys()
+ {
+ // Nothing to do
+ }
+ // Is the value a character
+ bool keys::isCharacter() const
+ {
+ return (getValue() >= 32 && getValue() <= 126);
+ }
+ // Is the value a number
+ bool keys::isNumber() const
+ {
+ return (getValue() >= 48 && getValue() <= 57);
+ }
+ // Is the value a letter
+ bool keys::isLetter() const
+ {
+ return (getValue() >= 65 && getValue() <= 90) || (getValue() >= 97 && getValue() <= 122);
+ }
+ // Get the Raw Value
+ int keys::getValue() const
+ {
+ return value;
+ }
+
+ // Get scancode Value
+ int keys::getScancodeValue() const
+ {
+ return scancode;
+ }
+
+ // Set the value
+ void keys::setValue(int v)
+ {
+ value = v;
+ }
+
+ void keys::setScancodeValue(int s)
+ {
+ scancode = s;
+ }
diff --git a/util/gui/keys.h b/util/gui/keys.h
new file mode 100644
index 00000000..fe0a6d48
--- /dev/null
+++ b/util/gui/keys.h
@@ -0,0 +1,191 @@
+/*
+SAGGUI (Simplified All Gaming Graphical User Interface)
+Copyright (c) 2005-2007, Miguel A. Gavidia
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+ * Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the following
+ disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+ * Neither the name of the "SAGGUI" nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef KEYS_H
+#define KEYS_H
+
+
+class keys
+{
+ protected:
+ int value;
+
+ int scancode;
+
+ public:
+
+ //! Constructor
+ keys();
+
+ //! Constructor setting it to the given value
+ keys(int v, int s);
+
+ keys(int v);
+
+ //! Destructor
+ ~keys();
+
+ //! Is the value a character
+ bool isCharacter() const;
+
+ //! Is the value a number
+ bool isNumber() const;
+
+ //! Is the value a letter
+ bool isLetter() const;
+
+ //! Get the Raw Value
+ int getValue() const;
+
+ //! Get scancode Value
+ int getScancodeValue() const;
+
+ //! Set the unicode value
+ void setValue(int v);
+
+ //! Set scancode value
+ void setScancodeValue(int s);
+
+ //! Enumerator of lookup chart for common keys
+ enum keyTypes
+ {
+ SPACE = ' ',
+ TAB = '\t',
+ ENTER = '\n',
+ NUM_0 = '0',
+ NUM_1 = '1',
+ NUM_2 = '2',
+ NUM_3 = '3',
+ NUM_4 = '4',
+ NUM_5 = '5',
+ NUM_6 = '6',
+ NUM_7 = '7',
+ NUM_8 = '8',
+ NUM_9 = '9',
+ PAD_0 = 1000,
+ PAD_1,
+ PAD_2,
+ PAD_3,
+ PAD_4,
+ PAD_5,
+ PAD_6,
+ PAD_7,
+ PAD_8,
+ PAD_9,
+ F1,
+ F2,
+ F3,
+ F4,
+ F5,
+ F6,
+ F7,
+ F8,
+ F9,
+ F10,
+ F11,
+ F12,
+ ESC,
+ TILDE,
+ MINUS,
+ EQUALS,
+ BACKSPACE,
+ OPENBRACE,
+ CLOSEBRACE,
+ COLON,
+ QUOTE,
+ BACKSLASH,
+ BACKSLASH2,
+ COMMA,
+ STOP,
+ SLASH,
+ INSERT,
+ DEL,
+ HOME,
+ END,
+ PGUP,
+ PGDN,
+ LEFT,
+ RIGHT,
+ UP,
+ DOWN,
+ PAD_SLASH,
+ ASTERISK,
+ PAD_MINUS,
+ PAD_PLUS,
+ PAD_DEL,
+ PAD_ENTER,
+ PRTSCR,
+ PAUSE,
+ ABNT_C1,
+ YEN,
+ KANA,
+ CONVERT,
+ NOCONVERT,
+ AT,
+ CIRCUMFLEX,
+ COLON2,
+ KANJI,
+ PAD_EQUALS, /* MacOS X */
+ BACKQUOTE, /* MacOS X */
+ SEMICOLON, /* MacOS X */
+ COMMAND, /* MacOS X */
+ UNKNOWN1,
+ UNKNOWN2,
+ UNKNOWN3,
+ UNKNOWN4,
+ UNKNOWN5,
+ UNKNOWN6,
+ UNKNOWN7,
+ UNKNOWN8,
+ LSHIFT,
+ RSHIFT,
+ LCONTROL,
+ RCONTROL,
+ ALT,
+ ALTGR,
+ LWIN,
+ RWIN,
+ MENU,
+ SCRLOCK,
+ NUMLOCK,
+ CAPSLOCK,
+ MAX = 1200
+ };
+};
+
+#endif
diff --git a/util/gui/lineedit.cpp b/util/gui/lineedit.cpp
new file mode 100644
index 00000000..0f9981b9
--- /dev/null
+++ b/util/gui/lineedit.cpp
@@ -0,0 +1,359 @@
+#include "util/bitmap.h"
+#include "util/font.h"
+#include "lineedit.h"
+#include "keys.h"
+#include "globals.h"
+#include "util/debug.h"
+#include <iostream>
+
+using namespace Gui;
+
+static std::ostream & debug( int level ){
+ Global::debug(level) << "[line edit] ";
+ return Global::debug(level);
+}
+
+LineEdit::LineEdit() :
+currentSetFont(0),
+hAlignment(T_Middle),
+hAlignMod(T_Middle),
+vAlignment(T_Middle),
+inputTypeValue(inputGeneral),
+changed_(0),
+autoResizable(0),
+textX(0),
+textY(0),
+cursorX(0),
+cursorY(0),
+cursorIndex(0),
+textColor(0),
+textSizeH(0),
+limit(0),
+blinkRate(500),
+blink(false),
+focused(false),
+changeCounter(0){
+ cursorTime.reset();
+}
+
+LineEdit::~LineEdit()
+{
+}
+
+void LineEdit::hookKey(int key, void (*callback)(void *), void * arg){
+ input.addBlockingHandle(key, callback, arg);
+}
+
+bool LineEdit::didChanged(unsigned long long & counter){
+ bool did = counter < changeCounter;
+ counter = changeCounter;
+ return did;
+}
+
+// If the font size changes
+void LineEdit::fontChange(){
+ changed();
+}
+
+// Update
+void LineEdit::act(const Font & font){
+ if (cursorTime.msecs() >= blinkRate){
+ cursorTime.reset();
+ blink = !blink;
+ changed();
+ }
+ /*
+ if ((blinkRate * 2) <= cursorTime.msecs()){
+ cursorTime.reset();
+ changed();
+ }
+ */
+
+ if (input.doInput()){
+ changed();
+ cursorIndex = input.getText().size();
+ }
+
+ if (changed_){
+ textSizeH = currentSetFont->getHeight();
+ if (autoResizable) {
+ location.setDimensions(textSizeH+2, currentSetFont->textLength(input.getText().c_str()) + 4);
+ } else {
+ if (hAlignMod==T_Left){
+ if (currentSetFont->textLength(input.getText().c_str())>location.getWidth()){
+ hAlignment = T_Right;
+ } else {
+ hAlignment = T_Left;
+ }
+ }
+ }
+
+ switch (hAlignment) {
+ case T_Left:
+ textX = 2;
+ cursorX = textX + currentSetFont->textLength(input.getText().substr(0,cursorIndex).c_str()) + 1;
+ break;
+ case T_Middle:
+ textX = (location.getWidth()/2) - (currentSetFont->textLength(input.getText().c_str())/2);
+ cursorX = (textX) + currentSetFont->textLength(input.getText().substr(0,cursorIndex).c_str()) + 1;
+ break;
+ case T_Right:
+ textX = location.getWidth() - currentSetFont->textLength(input.getText().c_str());//(position.width - 1)-2;
+ cursorX = location.getWidth() - currentSetFont->textLength(input.getText().substr(0, input.getText().length()-cursorIndex).c_str());
+ break;
+ case T_Bottom:
+ case T_Top:
+ break;
+ }
+
+ switch (vAlignment) {
+ case T_Top:
+ textY = 1;
+ cursorY = 1;
+ break;
+ case T_Middle:
+ textY = cursorY = (location.getHeight() - textSizeH-(5))/2;
+ break;
+ case T_Bottom:
+ textY = (location.getHeight() - 1) - textSizeH - 1;
+ cursorY = textY - textSizeH;
+ break;
+ case T_Right:
+ case T_Left:
+ break;
+ }
+
+ //textY++;
+ //textX++;
+ stable();
+ }
+}
+
+// Draw
+void LineEdit::render(const Bitmap & work){
+
+ checkWorkArea();
+ // Check if we are using a rounded box
+ if (location.getRadius()>0) {
+ Bitmap::transBlender( 0, 0, 0, colors.bodyAlpha );
+ roundRectFill( *workArea, (int)location.getRadius(), 0, 0, location.getWidth()-1, location.getHeight()-1, colors.body );
+ workArea->drawTrans(location.getX(),location.getY(),work);
+
+ workArea->fill(Bitmap::makeColor(255,0,255));
+
+ Bitmap::transBlender( 0, 0, 0, colors.borderAlpha );
+ roundRect( *workArea, (int)location.getRadius(), 0, 0, location.getWidth()-1, location.getHeight()-1, colors.border );
+ workArea->drawTrans(location.getX(),location.getY(),work);
+ } else {
+ Bitmap::transBlender( 0, 0, 0, colors.bodyAlpha );
+ workArea->rectangleFill( 0, 0, location.getWidth()-1, location.getHeight()-1, colors.body );
+ workArea->drawTrans(location.getX(),location.getY(),work);
+
+ workArea->fill(Bitmap::makeColor(255,0,255));
+
+ Bitmap::transBlender( 0, 0, 0, colors.borderAlpha );
+ workArea->rectangle( 0, 0, location.getWidth()-1, location.getHeight()-1, colors.border );
+ workArea->drawTrans(location.getX(),location.getY(),work);
+ }
+
+ work.drawingMode( Bitmap::MODE_SOLID );
+
+ workArea->fill(Bitmap::makeColor(255,0,255));
+
+ if (currentSetFont){
+ currentSetFont->printf(textX,textY,textColor,*workArea, input.getText(), 0);
+ }
+
+ if (focused){
+ /*
+ if (cursorTime.msecs() <= blinkRate){
+ workArea->line(cursorX,cursorY,cursorX,cursorY+textSizeH-5,textColor);
+ }
+ */
+ if (blink){
+ workArea->line(cursorX,cursorY,cursorX,cursorY+textSizeH-5,textColor);
+ }
+ }
+
+ workArea->draw(location.getX(), location.getY(), work);
+}
+
+#if 0
+// Keypresses
+sigslot::slot LineEdit::keyPress(const keys &k)
+{
+ debug( 5 ) << "Received key press " << k.getValue() << std::endl;
+ if(focused)
+ {
+ if(k.isCharacter())
+ {
+ char keyValue = k.getValue();
+ bool addValue = false;
+
+ switch(inputTypeValue){
+ case inputNumerical:
+ if ( k.isNumber() ) addValue = !addValue;
+ break;
+ case inputNoCaps:
+ keyValue = tolower(keyValue);
+ addValue = !addValue;
+ break;
+ case inputAllCaps:
+ keyValue = toupper(keyValue);
+ addValue = !addValue;
+ break;
+ case inputGeneral:
+ default:
+ addValue = !addValue;
+ break;
+ }
+ if(addValue){
+ if(limit!=0)
+ {
+ if(currentSetText.length()<limit)
+ {
+ //currentSetText += k.getValue();
+ currentSetText.insert(cursorIndex, std::string(1,keyValue));
+ ++cursorIndex;
+ changed();
+ }
+ }
+ else
+ {
+ //currentSetText += k.getValue();
+ currentSetText.insert(cursorIndex, std::string(1,keyValue));
+ ++cursorIndex;
+ changed();
+ }
+ }
+ }
+ else
+ {
+ switch(k.getValue())
+ {
+ case keys::DEL:
+ if(cursorIndex<currentSetText.length())
+ {
+ currentSetText.erase(cursorIndex,1);
+ }
+ break;
+ case keys::BACKSPACE:
+ if(cursorIndex>0)
+ {
+ currentSetText.erase(cursorIndex - 1, 1);
+ --cursorIndex;
+ }
+ break;
+ case keys::RIGHT:
+ if(cursorIndex<currentSetText.length())++cursorIndex;
+ break;
+ case keys::LEFT:
+ if(cursorIndex>0)--cursorIndex;
+ break;
+ case keys::INSERT:
+ break;
+ }
+ changed();
+ }
+ }
+}
+#endif
+
+// Set text
+void LineEdit::setText(const std::string & text){
+ input.setText(text);
+ if (limit!=0) {
+ if (input.getText().length() > limit) {
+ while (input.getText().length() > limit){
+ // currentSetText.erase(currentSetText.begin()+currentSetText.length()-1);
+ }
+ }
+ }
+ cursorIndex = input.getText().length();
+ changed();
+}
+
+
+//! Get text
+const std::string LineEdit::getText(){
+ return input.getText();
+}
+
+//! Clear text
+void LineEdit::clearText(){
+ input.clearInput();
+ cursorIndex=0;
+ changed();
+}
+
+//! Set text limit
+void LineEdit::setLimit(unsigned int l){
+ limit = l;
+ if (limit!=0){
+ if (input.getText().length()>limit){
+ while (input.getText().length()>limit){
+ // currentSetText.erase(currentSetText.begin()+currentSetText.length()-1);
+ }
+ }
+ }
+ cursorIndex = input.getText().length();
+ changed();
+}
+
+// Set Horizontal Alignment
+void LineEdit::setHorizontalAlign(const textAlign & a){
+ hAlignment = hAlignMod = a;
+ changed();
+}
+
+// Set Vertical Alignment
+void LineEdit::setVerticalAlign(const textAlign & a){
+ vAlignment = a;
+ changed();
+}
+
+//! Set the type of input default general
+void LineEdit::setInputType(const inputType i){
+ inputTypeValue = i;
+}
+
+// Set textColor
+void LineEdit::setTextColor(const int color){
+ textColor = color;
+}
+
+//! Set textColor
+void LineEdit::setCursorColor(const int color){
+ textColor = color;
+}
+
+// Set font
+void LineEdit::setFont(const Font *f){
+ currentSetFont = f;
+ if (currentSetFont) changed();
+}
+
+// Set autoResizeable
+void LineEdit::setAutoResize(bool r){
+ autoResizable = r;
+}
+
+// Set the cursor blink rate in miliseconds (default 500)
+void LineEdit::setCursorBlinkRate(unsigned int msecs){
+ blinkRate = msecs;
+}
+
+//! set Focus
+void LineEdit::setFocused(bool focus){
+ focused = focus;
+ if (focus){
+ input.enable();
+ } else {
+ input.disable();
+ }
+}
+
+//! check Focus
+bool LineEdit::isFocused(){
+ return focused;
+}
diff --git a/util/gui/lineedit.h b/util/gui/lineedit.h
new file mode 100644
index 00000000..e00f5957
--- /dev/null
+++ b/util/gui/lineedit.h
@@ -0,0 +1,178 @@
+#ifndef paintown_gui_lineedit_h
+#define paintown_gui_lineedit_h
+
+#include <iostream>
+#include <vector>
+
+#include "widget.h"
+#include "timer.h"
+#include "sigslot.h"
+#include "util/input/text-input.h"
+
+class Font;
+
+class keys;
+
+namespace Gui{
+
+class LineEdit: public Widget, public sigslot::has_slots<> {
+public:
+ //! enumerator housing alignment positions
+ enum textAlign {
+ T_Left = 0,
+ T_Middle,
+ T_Right,
+ T_Top,
+ T_Bottom
+ };
+
+ //! enumerator housing alignment positions
+ enum inputType {
+ inputGeneral = 0,
+ inputAllCaps,
+ inputNoCaps,
+ inputNumerical
+ };
+
+ //! Constructor
+ LineEdit();
+
+ //! Destructor
+ virtual ~LineEdit();
+
+ //! Set text
+ void setText(const std::string & text);
+
+ //! Get text
+ const std::string getText();
+
+ //! Clear text
+ void clearText();
+
+ //! Set text limit (default 0, no limit)
+ void setLimit(unsigned int l);
+
+ void hookKey(int key, void (*callback)(void *), void * arg);
+
+ //! Set Horizontal Alignment
+ void setHorizontalAlign(const textAlign & a);
+
+ //! Set Vertical Alignment
+ void setVerticalAlign(const textAlign & a);
+
+ //! Set the type of input default general
+ void setInputType(const inputType i = inputGeneral);
+
+ //! Set textColor
+ void setTextColor(const int color);
+
+ //! Set textColor
+ void setCursorColor(const int color);
+
+ //! Set font
+ void setFont(const Font *f);
+
+ //! Set autoResizeable
+ void setAutoResize(bool r);
+
+ //! Set the cursor blink rate in miliseconds (default 500)
+ void setCursorBlinkRate(unsigned int msecs);
+
+ //! Update
+ void act(const Font &);
+
+ //! Draw
+ using Widget::render;
+ void render(const Bitmap &);
+
+ //! set Focus
+ void setFocused(bool focus);
+
+ //! check Focus
+ bool isFocused();
+
+ //! Keypresses
+ // sigslot::slot keyPress(const keys &k);
+
+ bool didChanged( unsigned long long & counter );
+
+protected:
+ //! Current font the label is currently using (uses systemFont by default)
+ const Font *currentSetFont;
+
+ //! Current set text
+ // std::string currentSetText;
+
+ //! Horizontal Alignment (RIGHT, MIDDLE, LEFT)
+ textAlign hAlignment;
+
+ //! Additional checker for Horizontal alignment for easy adjustment
+ textAlign hAlignMod;
+
+ //! Vertical Alignment (TOP, MIDDLE, BOTTOM)
+ textAlign vAlignment;
+
+ //! Input type
+ inputType inputTypeValue;
+
+ //! Has changed?
+ bool changed_;
+
+ //! Auto resize
+ bool autoResizable;
+
+ //! Text horizontal position
+ int textX;
+
+ //! Text vertical position
+ int textY;
+
+ //! Cursor horizontal position
+ int cursorX;
+
+ //! Cursor vertical position
+ int cursorY;
+
+ //! Cursor index relative to the string
+ unsigned int cursorIndex;
+
+ //! Text color
+ int textColor;
+
+ //! Text size Height check in case it changes
+ int textSizeH;
+
+ //! Text limit
+ unsigned int limit;
+
+ //! Cursor timer
+ guiTimer cursorTime;
+
+ //! Cursor blink rate
+ unsigned int blinkRate;
+ bool blink;
+
+ //! Focused?
+ bool focused;
+
+ TextInput input;
+
+ // keeps track of changes
+ unsigned long long changeCounter;
+
+ //! If the font size changes
+ void fontChange();
+
+ inline void changed(){
+ changed_ = true;
+ changeCounter += 1;
+ }
+
+ inline void stable(){
+ changed_ = false;
+ }
+};
+
+}
+
+#endif
diff --git a/util/gui/popup-box.cpp b/util/gui/popup-box.cpp
new file mode 100644
index 00000000..1537219d
--- /dev/null
+++ b/util/gui/popup-box.cpp
@@ -0,0 +1,98 @@
+#include "util/bitmap.h"
+#include "popup-box.h"
+
+using namespace std;
+using namespace Gui;
+
+PopupBox::PopupBox():
+fadeState(Closed),
+fadeSpeed(12){
+}
+
+PopupBox::PopupBox( const PopupBox & copy ):
+fadeState(Closed){
+ this->fadeSpeed = copy.fadeSpeed;
+}
+
+PopupBox::~PopupBox(){
+}
+
+PopupBox & PopupBox::operator=( const PopupBox & copy){
+ this->fadeState = Closed;
+ this->fadeSpeed = copy.fadeSpeed;
+ return *this;
+}
+
+void PopupBox::act(const Font & font){
+ // do fade
+ doFade();
+}
+
+void PopupBox::render(const Bitmap & work){
+ board.render(work);
+}
+
+void PopupBox::open(){
+ // Set the fade stuff
+ fadeState = FadeIn;
+ board.location = location;
+ board.colors = colors;
+ board.location.center(location);
+ board.colors.borderAlpha = board.colors.bodyAlpha = 0;
+}
+
+void PopupBox::close(){
+ fadeState = FadeOut;
+}
+
+void PopupBox::doFade(){
+ switch (fadeState){
+ case FadeIn: {
+ board.location.growTo(location, 0.0025 * fadeSpeed);
+ if (board.colors.borderAlpha < colors.borderAlpha){
+ board.colors.borderAlpha += (int)(fadeSpeed/2);
+ if (board.colors.borderAlpha >= colors.borderAlpha){
+ board.colors.borderAlpha = colors.borderAlpha;
+ }
+ }
+ if (board.colors.bodyAlpha < colors.bodyAlpha){
+ board.colors.bodyAlpha += (int)(fadeSpeed/2);
+ if (board.colors.bodyAlpha >= colors.bodyAlpha){
+ board.colors.bodyAlpha = colors.bodyAlpha;
+ }
+ }
+
+ if (board.location == location && board.colors.bodyAlpha == colors.bodyAlpha && board.colors.borderAlpha == colors.borderAlpha){
+ fadeState = Open;
+ }
+
+ break;
+ }
+ case FadeOut: {
+ Coordinate coord;
+ coord.center(location);
+ board.location.growTo(coord, 0.0025 * fadeSpeed);
+
+ if (board.colors.borderAlpha > 0){
+ board.colors.borderAlpha -= (int)(fadeSpeed/2);
+ if (board.colors.borderAlpha <= 0){
+ board.colors.borderAlpha = 0;
+ }
+ }
+ if (board.colors.bodyAlpha > 0){
+ board.colors.bodyAlpha -= (int)(fadeSpeed/2);
+ if (board.colors.bodyAlpha <= 0){
+ board.colors.bodyAlpha = 0;
+ }
+ }
+ if (board.location.empty() && board.colors.borderAlpha == 0 && board.colors.bodyAlpha == 0){
+ fadeState = Closed;
+ }
+ break;
+ }
+ case Open:
+ case Closed:
+ default:
+ break;
+ }
+}
diff --git a/util/gui/popup-box.h b/util/gui/popup-box.h
new file mode 100644
index 00000000..ea0d0a85
--- /dev/null
+++ b/util/gui/popup-box.h
@@ -0,0 +1,65 @@
+#ifndef _paintown_gui_popup_box_h
+#define _paintown_gui_popup_box_h
+
+#include <string>
+#include <vector>
+
+#include "widget.h"
+#include "box.h"
+
+#include "../gradient.h"
+
+namespace Gui{
+
+class PopupBox : public Widget {
+ public:
+ PopupBox();
+ PopupBox(const PopupBox &);
+ virtual ~PopupBox();
+
+ //! copy
+ PopupBox &operator=(const PopupBox &);
+ //! Logic
+ virtual void act(const Font &);
+ //! Render
+ using Widget::render;
+ virtual void render(const Bitmap &);
+ //! Open box
+ virtual void open();
+ //! Close box
+ virtual void close();
+ //! Is active?
+ virtual inline bool isActive(){
+ return (this->fadeState != Closed);
+ }
+ //!set fadespeed
+ virtual inline void setFadeSpeed(int speed){
+ this->fadeSpeed = speed;
+ }
+ //! Get current box coordinates
+ virtual inline const Coordinate & getArea(){
+ return this->board.location;
+ }
+ private:
+
+ void doFade();
+
+ enum FadeState{
+ Closed,
+ FadeIn,
+ Open,
+ FadeOut,
+ };
+ //! Current fade state
+ FadeState fadeState;
+
+ //! Fade speed
+ int fadeSpeed;
+
+ //! Board
+ Box board;
+};
+
+}
+
+#endif
diff --git a/util/gui/rectarea.cpp b/util/gui/rectarea.cpp
new file mode 100644
index 00000000..78f05e2c
--- /dev/null
+++ b/util/gui/rectarea.cpp
@@ -0,0 +1,51 @@
+#include "../bitmap.h"
+#include "rectarea.h"
+
+using namespace Gui;
+
+RectArea::RectArea():
+x(0),
+y(0),
+width(0),
+height(0),
+radius(0){
+}
+
+RectArea::RectArea(int x, int y, int w, int h):
+x(x),
+y(y),
+width(w),
+height(h),
+radius(0){
+}
+
+bool RectArea::empty(){
+ // return (x==0 && y==0 && width==0 && height==0);
+ return width == 0 && height == 0;
+}
+
+bool RectArea::operator==( const RectArea &rect){
+ return ( (x == rect.x) &&
+ (y == rect.y) &&
+ (width == rect.width) &&
+ (height == rect.height));
+}
+
+bool RectArea::operator!=( const RectArea &rect){
+ return ( (x != rect.x) ||
+ (y != rect.y) ||
+ (width != rect.width) ||
+ (height != rect.height));
+}
+
+bool RectArea::operator==( const Bitmap &bmp){
+ return ( (width == bmp.getWidth()) &&
+ (height == bmp.getHeight()));
+}
+
+bool RectArea::operator!=( const Bitmap &bmp){
+ return ( (width != bmp.getWidth()) ||
+ (height != bmp.getHeight()));
+}
+
+
diff --git a/util/gui/rectarea.h b/util/gui/rectarea.h
new file mode 100644
index 00000000..398db4df
--- /dev/null
+++ b/util/gui/rectarea.h
@@ -0,0 +1,29 @@
+#ifndef _paintown_gui_rectarea_h
+#define _paintown_gui_rectarea_h
+
+class Bitmap;
+
+namespace Gui{
+
+struct RectArea{
+ RectArea();
+ RectArea(int x, int y, int w, int h);
+ inline int getX1() const { return x; }
+ inline int getY1() const { return y; }
+ inline int getX2() const { return x + width; }
+ inline int getY2() const { return y + height; }
+ bool operator==( const RectArea &);
+ bool operator!=( const RectArea &);
+ bool operator==( const Bitmap &);
+ bool operator!=( const Bitmap &);
+ bool empty();
+ int x;
+ int y;
+ int width;
+ int height;
+ int radius;
+};
+
+}
+
+#endif
diff --git a/util/gui/sigslot.h b/util/gui/sigslot.h
new file mode 100644
index 00000000..c88c1392
--- /dev/null
+++ b/util/gui/sigslot.h
@@ -0,0 +1,3391 @@
+/*
+SAGGUI (Simplified All Gaming Graphical User Interface)
+Copyright (c) 2007 Miguel A. Gavidia
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+ * Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the following
+ disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+ * Neither the name of the "SAGGUI" nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+// sigslot.h: Signal/Slot classes
+//
+// Written by Sarah Thompson (sarah@telergy.com) 2002.
+//
+// License: Public domain. You are free to use this code however you like, with the proviso that
+// the author takes on no responsibility or liability for any use.
+//
+// QUICK DOCUMENTATION
+//
+// (see also the full documentation at http://sigslot.sourceforge.net/)
+//
+// #define switches
+// SIGSLOT_PURE_ISO - Define this to force ISO C++ compliance. This also disables
+// all of the thread safety support on platforms where it is
+// available.
+//
+// SIGSLOT_USE_POSIX_THREADS - Force use of Posix threads when using a C++ compiler other than
+// gcc on a platform that supports Posix threads. (When using gcc,
+// this is the default - use SIGSLOT_PURE_ISO to disable this if
+// necessary)
+//
+// SIGSLOT_DEFAULT_MT_POLICY - Where thread support is enabled, this defaults to multi_threaded_global.
+// Otherwise, the default is single_threaded. #define this yourself to
+// override the default. In pure ISO mode, anything other than
+// single_threaded will cause a compiler error.
+//
+// PLATFORM NOTES
+//
+// Win32 - On Win32, the WIN32 symbol must be #defined. Most mainstream
+// compilers do this by default, but you may need to define it
+// yourself if your build environment is less standard. This causes
+// the Win32 thread support to be compiled in and used automatically.
+//
+// Unix/Linux/BSD, etc. - If you're using gcc, it is assumed that you have Posix threads
+// available, so they are used automatically. You can override this
+// (as under Windows) with the SIGSLOT_PURE_ISO switch. If you're using
+// something other than gcc but still want to use Posix threads, you
+// need to #define SIGSLOT_USE_POSIX_THREADS.
+//
+// ISO C++ - If none of the supported platforms are detected, or if
+// SIGSLOT_PURE_ISO is defined, all multithreading support is turned off,
+// along with any code that might cause a pure ISO C++ environment to
+// complain. Before you ask, gcc -ansi -pedantic won't compile this
+// library, but gcc -ansi is fine. Pedantic mode seems to throw a lot of
+// errors that aren't really there. If you feel like investigating this,
+// please contact the author.
+//
+//
+// THREADING MODES
+//
+// single_threaded - Your program is assumed to be single threaded from the point of view
+// of signal/slot usage (i.e. all objects using signals and slots are
+// created and destroyed from a single thread). Behaviour if objects are
+// destroyed concurrently is undefined (i.e. you'll get the occasional
+// segmentation fault/memory exception).
+//
+// multi_threaded_global - Your program is assumed to be multi threaded. Objects using signals and
+// slots can be safely created and destroyed from any thread, even when
+// connections exist. In multi_threaded_global mode, this is achieved by a
+// single global mutex (actually a critical section on Windows because they
+// are faster). This option uses less OS resources, but results in more
+// opportunities for contention, possibly resulting in more context switches
+// than are strictly necessary.
+//
+// multi_threaded_local - Behaviour in this mode is essentially the same as multi_threaded_global,
+// except that each signal, and each object that inherits has_slots, all
+// have their own mutex/critical section. In practice, this means that
+// mutex collisions (and hence context switches) only happen if they are
+// absolutely essential. However, on some platforms, creating a lot of
+// mutexes can slow down the whole OS, so use this option with care.
+//
+// USING THE LIBRARY
+//
+// See the full documentation at http://sigslot.sourceforge.net/
+//
+//
+
+// Modified by juvinious adding in chaining support 01/01/2007
+// Modded to add in specific slot disconnections 01/24/2007
+// Added in stuff to be inclusive to saggui, else check out the comments below on line 148
+
+#ifndef paintown_SIGSLOT_H__
+#define paintown_SIGSLOT_H__
+
+#include <set>
+#include <list>
+#include <algorithm>
+
+#define SIGSLOT_PURE_ISO 1
+
+#if defined(SIGSLOT_PURE_ISO) || (!defined(WIN32) && !defined(__GNUG__) && !defined(SIGSLOT_USE_POSIX_THREADS))
+# define _SIGSLOT_SINGLE_THREADED
+#elif defined(WIN32)
+# define _SIGSLOT_HAS_WIN32_THREADS
+# include <windows.h>
+#elif defined(__GNUG__) || defined(SIGSLOT_USE_POSIX_THREADS)
+# define _SIGSLOT_HAS_POSIX_THREADS
+# include <pthread.h>
+#else
+# define _SIGSLOT_SINGLE_THREADED
+#endif
+
+#ifndef SIGSLOT_DEFAULT_MT_POLICY
+# ifdef _SIGSLOT_SINGLE_THREADED
+# define SIGSLOT_DEFAULT_MT_POLICY single_threaded
+# else
+# define SIGSLOT_DEFAULT_MT_POLICY multi_threaded_local
+# endif
+#endif
+
+#include <iostream>
+
+/* If you plan on using this outside of saggui, comment the include then uncomment the definition */
+//#include "dllspec.h"
+#define SAGGUI_EXPORT
+
+/* This can be safely ignored if you are using this outside saggui as it puts the sigslot back into its own namespace */
+#ifdef SAGGUI_EXT_EXPORT
+namespace saggui {
+#else
+namespace sigslot {
+#endif
+ class SAGGUI_EXPORT single_threaded
+ {
+ public:
+ single_threaded()
+ {
+ ;
+ }
+
+ virtual ~single_threaded()
+ {
+ ;
+ }
+
+ virtual void lock()
+ {
+ ;
+ }
+
+ virtual void unlock()
+ {
+ ;
+ }
+ };
+
+#ifdef _SIGSLOT_HAS_WIN32_THREADS
+ // The multi threading policies only get compiled in if they are enabled.
+ class SAGGUI_EXPORT multi_threaded_global
+ {
+ public:
+ multi_threaded_global()
+ {
+ static bool isinitialised = false;
+
+ if(!isinitialised)
+ {
+ InitializeCriticalSection(get_critsec());
+ isinitialised = true;
+ }
+ }
+
+ multi_threaded_global(const multi_threaded_global&)
+ {
+ ;
+ }
+
+ virtual ~multi_threaded_global()
+ {
+ ;
+ }
+
+ virtual void lock()
+ {
+ EnterCriticalSection(get_critsec());
+ }
+
+ virtual void unlock()
+ {
+ LeaveCriticalSection(get_critsec());
+ }
+
+ private:
+ CRITICAL_SECTION* get_critsec()
+ {
+ static CRITICAL_SECTION g_critsec;
+ return &g_critsec;
+ }
+ };
+
+ class SAGGUI_EXPORT multi_threaded_local
+ {
+ public:
+ multi_threaded_local()
+ {
+ InitializeCriticalSection(&m_critsec);
+ }
+
+ multi_threaded_local(const multi_threaded_local&)
+ {
+ InitializeCriticalSection(&m_critsec);
+ }
+
+ virtual ~multi_threaded_local()
+ {
+ DeleteCriticalSection(&m_critsec);
+ }
+
+ virtual void lock()
+ {
+ EnterCriticalSection(&m_critsec);
+ }
+
+ virtual void unlock()
+ {
+ LeaveCriticalSection(&m_critsec);
+ }
+
+ private:
+ CRITICAL_SECTION m_critsec;
+ };
+#endif // _SIGSLOT_HAS_WIN32_THREADS
+
+#ifdef _SIGSLOT_HAS_POSIX_THREADS
+ // The multi threading policies only get compiled in if they are enabled.
+ class SAGGUI_EXPORT multi_threaded_global
+ {
+ public:
+ multi_threaded_global()
+ {
+ pthread_mutex_init(get_mutex(), NULL);
+ }
+
+ multi_threaded_global(const multi_threaded_global&)
+ {
+ ;
+ }
+
+ virtual ~multi_threaded_global()
+ {
+ ;
+ }
+
+ virtual void lock()
+ {
+ pthread_mutex_lock(get_mutex());
+ }
+
+ virtual void unlock()
+ {
+ pthread_mutex_unlock(get_mutex());
+ }
+
+ private:
+ pthread_mutex_t* get_mutex()
+ {
+ static pthread_mutex_t g_mutex;
+ return &g_mutex;
+ }
+ };
+
+ class SAGGUI_EXPORT multi_threaded_local
+ {
+ public:
+ multi_threaded_local()
+ {
+ pthread_mutex_init(&m_mutex, NULL);
+ }
+
+ multi_threaded_local(const multi_threaded_local&)
+ {
+ pthread_mutex_init(&m_mutex, NULL);
+ }
+
+ virtual ~multi_threaded_local()
+ {
+ pthread_mutex_destroy(&m_mutex);
+ }
+
+ virtual void lock()
+ {
+ pthread_mutex_lock(&m_mutex);
+ }
+
+ virtual void unlock()
+ {
+ pthread_mutex_unlock(&m_mutex);
+ }
+
+ private:
+ pthread_mutex_t m_mutex;
+ };
+#endif // _SIGSLOT_HAS_POSIX_THREADS
+
+ template<class mt_policy>
+ class SAGGUI_EXPORT lock_block
+ {
+ public:
+ mt_policy *m_mutex;
+
+ lock_block(mt_policy *mtx)
+ : m_mutex(mtx)
+ {
+ m_mutex->lock();
+ }
+
+ ~lock_block()
+ {
+ m_mutex->unlock();
+ }
+ };
+
+ template<class mt_policy>
+ class SAGGUI_EXPORT has_slots;
+
+ template<class mt_policy>
+ class SAGGUI_EXPORT _connection_base0
+ {
+ public:
+ virtual ~_connection_base0() { ; }
+ virtual has_slots<mt_policy>* getdest() const = 0;
+ virtual void emit() = 0;
+ virtual _connection_base0* clone() = 0;
+ virtual _connection_base0* duplicate(has_slots<mt_policy>* pnewdest) = 0;
+ };
+
+ template<class arg1_type, class mt_policy>
+ class SAGGUI_EXPORT _connection_base1
+ {
+ public:
+ virtual ~_connection_base1() { ; }
+ virtual has_slots<mt_policy>* getdest() const = 0;
+ virtual void emit(arg1_type) = 0;
+ virtual _connection_base1<arg1_type, mt_policy>* clone() = 0;
+ virtual _connection_base1<arg1_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;
+ };
+
+ template<class arg1_type, class arg2_type, class mt_policy>
+ class SAGGUI_EXPORT _connection_base2
+ {
+ public:
+ virtual ~_connection_base2() { ; }
+ virtual has_slots<mt_policy>* getdest() const = 0;
+ virtual void emit(arg1_type, arg2_type) = 0;
+ virtual _connection_base2<arg1_type, arg2_type, mt_policy>* clone() = 0;
+ virtual _connection_base2<arg1_type, arg2_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;
+ };
+
+ template<class arg1_type, class arg2_type, class arg3_type, class mt_policy>
+ class SAGGUI_EXPORT _connection_base3
+ {
+ public:
+ virtual ~_connection_base3() { ; }
+ virtual has_slots<mt_policy>* getdest() const = 0;
+ virtual void emit(arg1_type, arg2_type, arg3_type) = 0;
+ virtual _connection_base3<arg1_type, arg2_type, arg3_type, mt_policy>* clone() = 0;
+ virtual _connection_base3<arg1_type, arg2_type, arg3_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;
+ };
+
+ template<class arg1_type, class arg2_type, class arg3_type, class arg4_type, class mt_policy>
+ class SAGGUI_EXPORT _connection_base4
+ {
+ public:
+ virtual ~_connection_base4() { ; }
+ virtual has_slots<mt_policy>* getdest() const = 0;
+ virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type) = 0;
+ virtual _connection_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>* clone() = 0;
+ virtual _connection_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;
+ };
+
+ template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
+ class arg5_type, class mt_policy>
+ class SAGGUI_EXPORT _connection_base5
+ {
+ public:
+ virtual ~_connection_base5() { ; }
+ virtual has_slots<mt_policy>* getdest() const = 0;
+ virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type) = 0;
+ virtual _connection_base5<arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, mt_policy>* clone() = 0;
+ virtual _connection_base5<arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;
+ };
+
+ template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
+ class arg5_type, class arg6_type, class mt_policy>
+ class SAGGUI_EXPORT _connection_base6
+ {
+ public:
+ virtual ~_connection_base6() { ; }
+ virtual has_slots<mt_policy>* getdest() const = 0;
+ virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type,
+ arg6_type) = 0;
+ virtual _connection_base6<arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, arg6_type, mt_policy>* clone() = 0;
+ virtual _connection_base6<arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, arg6_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;
+ };
+
+ template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
+ class arg5_type, class arg6_type, class arg7_type, class mt_policy>
+ class SAGGUI_EXPORT _connection_base7
+ {
+ public:
+ virtual ~_connection_base7() { ; }
+ virtual has_slots<mt_policy>* getdest() const = 0;
+ virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type,
+ arg6_type, arg7_type) = 0;
+ virtual _connection_base7<arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, arg6_type, arg7_type, mt_policy>* clone() = 0;
+ virtual _connection_base7<arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, arg6_type, arg7_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;
+ };
+
+ template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
+ class arg5_type, class arg6_type, class arg7_type, class arg8_type, class mt_policy>
+ class SAGGUI_EXPORT _connection_base8
+ {
+ public:
+ virtual ~_connection_base8() { ; }
+ virtual has_slots<mt_policy>* getdest() const = 0;
+ virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type,
+ arg6_type, arg7_type, arg8_type) = 0;
+ virtual _connection_base8<arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>* clone() = 0;
+ virtual _connection_base8<arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest) = 0;
+ };
+
+ template<class mt_policy>
+ class SAGGUI_EXPORT _signal_base : public mt_policy
+ {
+ public:
+ virtual void slot_disconnect(has_slots<mt_policy>* pslot) = 0;
+ virtual void slot_duplicate(const has_slots<mt_policy>* poldslot, has_slots<mt_policy>* pnewslot) = 0;
+ };
+
+ template<class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
+ class SAGGUI_EXPORT has_slots : public mt_policy
+ {
+ private:
+ typedef typename std::set<_signal_base<mt_policy> *> sender_set;
+ typedef typename sender_set::const_iterator const_iterator;
+
+ public:
+ has_slots()
+ {
+ ;
+ }
+
+ has_slots(const has_slots& hs)
+ : mt_policy(hs)
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator it = hs.m_senders.begin();
+ const_iterator itEnd = hs.m_senders.end();
+
+ while(it != itEnd)
+ {
+ (*it)->slot_duplicate(&hs, this);
+ m_senders.insert(*it);
+ ++it;
+ }
+ }
+
+ void signal_connect(_signal_base<mt_policy>* sender)
+ {
+ lock_block<mt_policy> lock(this);
+ m_senders.insert(sender);
+ }
+
+ void signal_disconnect(_signal_base<mt_policy>* sender)
+ {
+ lock_block<mt_policy> lock(this);
+ m_senders.erase(sender);
+ }
+
+ virtual ~has_slots()
+ {
+ disconnect_all();
+ }
+
+ void disconnect_all()
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator it = m_senders.begin();
+ const_iterator itEnd = m_senders.end();
+
+ while(it != itEnd)
+ {
+ (*it)->slot_disconnect(this);
+ ++it;
+ }
+
+ m_senders.erase(m_senders.begin(), m_senders.end());
+ }
+
+ private:
+ sender_set m_senders;
+ };
+
+ template<class mt_policy>
+ class SAGGUI_EXPORT _signal_base0 : public _signal_base<mt_policy>
+ {
+ public:
+ typedef typename std::list<_connection_base0<mt_policy> *> connections_list;
+ typedef typename connections_list::const_iterator const_iterator;
+ typedef typename connections_list::iterator iterator;
+
+ _signal_base0()
+ {
+ ;
+ }
+
+ _signal_base0(const _signal_base0& s)
+ : _signal_base<mt_policy>(s)
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator it = s.m_connected_slots.begin();
+ const_iterator itEnd = s.m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ (*it)->getdest()->signal_connect(this);
+ m_connected_slots.push_back((*it)->clone());
+
+ ++it;
+ }
+ }
+
+ ~_signal_base0()
+ {
+ disconnect_all();
+ }
+
+ void disconnect_all()
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator it = m_connected_slots.begin();
+ const_iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ (*it)->getdest()->signal_disconnect(this);
+ delete *it;
+
+ ++it;
+ }
+
+ m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
+ }
+
+ void disconnect(has_slots<mt_policy>* pclass)
+ {
+ lock_block<mt_policy> lock(this);
+ iterator it = m_connected_slots.begin();
+ iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ if((*it)->getdest() == pclass)
+ {
+ delete *it;
+ m_connected_slots.erase(it);
+ pclass->signal_disconnect(this);
+ return;
+ }
+
+ ++it;
+ }
+ }
+
+ void slot_disconnect(has_slots<mt_policy>* pslot)
+ {
+ lock_block<mt_policy> lock(this);
+ iterator it = m_connected_slots.begin();
+ iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ iterator itNext = it;
+ ++itNext;
+
+ if((*it)->getdest() == pslot)
+ {
+ delete *it;
+ m_connected_slots.erase(it);
+ // delete *it;
+ }
+
+ it = itNext;
+ }
+ }
+
+ void slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)
+ {
+ lock_block<mt_policy> lock(this);
+ iterator it = m_connected_slots.begin();
+ iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ if((*it)->getdest() == oldtarget)
+ {
+ m_connected_slots.push_back((*it)->duplicate(newtarget));
+ }
+
+ ++it;
+ }
+ }
+
+ protected:
+ connections_list m_connected_slots;
+ };
+
+ template<class arg1_type, class mt_policy>
+ class SAGGUI_EXPORT _signal_base1 : public _signal_base<mt_policy>
+ {
+ public:
+ typedef typename std::list<_connection_base1<arg1_type, mt_policy> *> connections_list;
+ typedef typename connections_list::const_iterator const_iterator;
+ typedef typename connections_list::iterator iterator;
+
+ _signal_base1()
+ {
+ ;
+ }
+
+ _signal_base1(const _signal_base1<arg1_type, mt_policy>& s)
+ : _signal_base<mt_policy>(s)
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator it = s.m_connected_slots.begin();
+ const_iterator itEnd = s.m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ (*it)->getdest()->signal_connect(this);
+ m_connected_slots.push_back((*it)->clone());
+
+ ++it;
+ }
+ }
+
+ void slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)
+ {
+ lock_block<mt_policy> lock(this);
+ iterator it = m_connected_slots.begin();
+ iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ if((*it)->getdest() == oldtarget)
+ {
+ m_connected_slots.push_back((*it)->duplicate(newtarget));
+ }
+
+ ++it;
+ }
+ }
+
+ ~_signal_base1()
+ {
+ disconnect_all();
+ }
+
+ void disconnect_all()
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator it = m_connected_slots.begin();
+ const_iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ (*it)->getdest()->signal_disconnect(this);
+ delete *it;
+
+ ++it;
+ }
+
+ m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
+ }
+
+ void disconnect(has_slots<mt_policy>* pclass)
+ {
+ lock_block<mt_policy> lock(this);
+ iterator it = m_connected_slots.begin();
+ iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ if((*it)->getdest() == pclass)
+ {
+ delete *it;
+ m_connected_slots.erase(it);
+ pclass->signal_disconnect(this);
+ return;
+ }
+
+ ++it;
+ }
+ }
+
+ void slot_disconnect(has_slots<mt_policy>* pslot)
+ {
+ lock_block<mt_policy> lock(this);
+ iterator it = m_connected_slots.begin();
+ iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ iterator itNext = it;
+ ++itNext;
+
+ if((*it)->getdest() == pslot)
+ {
+ delete *it;
+ m_connected_slots.erase(it);
+ // delete *it;
+ }
+
+ it = itNext;
+ }
+ }
+
+
+ protected:
+ connections_list m_connected_slots;
+ };
+
+ template<class arg1_type, class arg2_type, class mt_policy>
+ class SAGGUI_EXPORT _signal_base2 : public _signal_base<mt_policy>
+ {
+ public:
+ typedef typename std::list<_connection_base2<arg1_type, arg2_type, mt_policy> *>
+ connections_list;
+ typedef typename connections_list::const_iterator const_iterator;
+ typedef typename connections_list::iterator iterator;
+
+ _signal_base2()
+ {
+ ;
+ }
+
+ _signal_base2(const _signal_base2<arg1_type, arg2_type, mt_policy>& s)
+ : _signal_base<mt_policy>(s)
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator it = s.m_connected_slots.begin();
+ const_iterator itEnd = s.m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ (*it)->getdest()->signal_connect(this);
+ m_connected_slots.push_back((*it)->clone());
+
+ ++it;
+ }
+ }
+
+ void slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)
+ {
+ lock_block<mt_policy> lock(this);
+ iterator it = m_connected_slots.begin();
+ iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ if((*it)->getdest() == oldtarget)
+ {
+ m_connected_slots.push_back((*it)->duplicate(newtarget));
+ }
+
+ ++it;
+ }
+ }
+
+ ~_signal_base2()
+ {
+ disconnect_all();
+ }
+
+ void disconnect_all()
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator it = m_connected_slots.begin();
+ const_iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ (*it)->getdest()->signal_disconnect(this);
+ delete *it;
+
+ ++it;
+ }
+
+ m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
+ }
+
+ void disconnect(has_slots<mt_policy>* pclass)
+ {
+ lock_block<mt_policy> lock(this);
+ iterator it = m_connected_slots.begin();
+ iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ if((*it)->getdest() == pclass)
+ {
+ delete *it;
+ m_connected_slots.erase(it);
+ pclass->signal_disconnect(this);
+ return;
+ }
+
+ ++it;
+ }
+ }
+
+ void slot_disconnect(has_slots<mt_policy>* pslot)
+ {
+ lock_block<mt_policy> lock(this);
+ iterator it = m_connected_slots.begin();
+ iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ iterator itNext = it;
+ ++itNext;
+
+ if((*it)->getdest() == pslot)
+ {
+ delete *it;
+ m_connected_slots.erase(it);
+ // delete *it;
+ }
+
+ it = itNext;
+ }
+ }
+
+ protected:
+ connections_list m_connected_slots;
+ };
+
+ template<class arg1_type, class arg2_type, class arg3_type, class mt_policy>
+ class SAGGUI_EXPORT _signal_base3 : public _signal_base<mt_policy>
+ {
+ public:
+ typedef std::list<_connection_base3<arg1_type, arg2_type, arg3_type, mt_policy> *>
+ connections_list;
+
+ typedef typename connections_list::const_iterator const_iterator;
+ typedef typename connections_list::iterator iterator;
+ _signal_base3()
+ {
+ ;
+ }
+
+ _signal_base3(const _signal_base3<arg1_type, arg2_type, arg3_type, mt_policy>& s)
+ : _signal_base<mt_policy>(s)
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator it = s.m_connected_slots.begin();
+ const_iterator itEnd = s.m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ (*it)->getdest()->signal_connect(this);
+ m_connected_slots.push_back((*it)->clone());
+
+ ++it;
+ }
+ }
+
+ void slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)
+ {
+ lock_block<mt_policy> lock(this);
+ iterator it = m_connected_slots.begin();
+ iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ if((*it)->getdest() == oldtarget)
+ {
+ m_connected_slots.push_back((*it)->duplicate(newtarget));
+ }
+
+ ++it;
+ }
+ }
+
+ ~_signal_base3()
+ {
+ disconnect_all();
+ }
+
+ void disconnect_all()
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator it = m_connected_slots.begin();
+ const_iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ (*it)->getdest()->signal_disconnect(this);
+ delete *it;
+
+ ++it;
+ }
+
+ m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
+ }
+
+ void disconnect(has_slots<mt_policy>* pclass)
+ {
+ lock_block<mt_policy> lock(this);
+ iterator it = m_connected_slots.begin();
+ iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ if((*it)->getdest() == pclass)
+ {
+ delete *it;
+ m_connected_slots.erase(it);
+ pclass->signal_disconnect(this);
+ return;
+ }
+
+ ++it;
+ }
+ }
+
+ void slot_disconnect(has_slots<mt_policy>* pslot)
+ {
+ lock_block<mt_policy> lock(this);
+ iterator it = m_connected_slots.begin();
+ iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ iterator itNext = it;
+ ++itNext;
+
+ if((*it)->getdest() == pslot)
+ {
+ delete *it;
+ m_connected_slots.erase(it);
+ // delete *it;
+ }
+
+ it = itNext;
+ }
+ }
+
+ protected:
+ connections_list m_connected_slots;
+ };
+
+ template<class arg1_type, class arg2_type, class arg3_type, class arg4_type, class mt_policy>
+ class SAGGUI_EXPORT _signal_base4 : public _signal_base<mt_policy>
+ {
+ public:
+ typedef std::list<_connection_base4<arg1_type, arg2_type, arg3_type,
+ arg4_type, mt_policy> *> connections_list;
+ typedef typename connections_list::const_iterator const_iterator;
+ typedef typename connections_list::iterator iterator;
+
+ _signal_base4()
+ {
+ ;
+ }
+
+ _signal_base4(const _signal_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>& s)
+ : _signal_base<mt_policy>(s)
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator it = s.m_connected_slots.begin();
+ const_iterator itEnd = s.m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ (*it)->getdest()->signal_connect(this);
+ m_connected_slots.push_back((*it)->clone());
+
+ ++it;
+ }
+ }
+
+ void slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)
+ {
+ lock_block<mt_policy> lock(this);
+ iterator it = m_connected_slots.begin();
+ iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ if((*it)->getdest() == oldtarget)
+ {
+ m_connected_slots.push_back((*it)->duplicate(newtarget));
+ }
+
+ ++it;
+ }
+ }
+
+ ~_signal_base4()
+ {
+ disconnect_all();
+ }
+
+ void disconnect_all()
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator it = m_connected_slots.begin();
+ const_iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ (*it)->getdest()->signal_disconnect(this);
+ delete *it;
+
+ ++it;
+ }
+
+ m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
+ }
+
+ void disconnect(has_slots<mt_policy>* pclass)
+ {
+ lock_block<mt_policy> lock(this);
+ iterator it = m_connected_slots.begin();
+ iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ if((*it)->getdest() == pclass)
+ {
+ delete *it;
+ this->m_connected_slots.erase(it);
+ pclass->signal_disconnect(this);
+ return;
+ }
+
+ ++it;
+ }
+ }
+
+ void slot_disconnect(has_slots<mt_policy>* pslot)
+ {
+ lock_block<mt_policy> lock(this);
+ iterator it = m_connected_slots.begin();
+ iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ iterator itNext = it;
+ ++itNext;
+
+ if((*it)->getdest() == pslot)
+ {
+ delete *it;
+ m_connected_slots.erase(it);
+ // delete *it;
+ }
+
+ it = itNext;
+ }
+ }
+
+ protected:
+ connections_list m_connected_slots;
+ };
+
+ template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
+ class arg5_type, class mt_policy>
+ class SAGGUI_EXPORT _signal_base5 : public _signal_base<mt_policy>
+ {
+ public:
+ typedef std::list<_connection_base5<arg1_type, arg2_type, arg3_type,
+ arg4_type, arg5_type, mt_policy> *> connections_list;
+ typedef typename connections_list::const_iterator const_iterator;
+ typedef typename connections_list::iterator iterator;
+
+ _signal_base5()
+ {
+ ;
+ }
+
+ _signal_base5(const _signal_base5<arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, mt_policy>& s)
+ : _signal_base<mt_policy>(s)
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator it = s.m_connected_slots.begin();
+ const_iterator itEnd = s.m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ (*it)->getdest()->signal_connect(this);
+ m_connected_slots.push_back((*it)->clone());
+
+ ++it;
+ }
+ }
+
+ void slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)
+ {
+ lock_block<mt_policy> lock(this);
+ iterator it = m_connected_slots.begin();
+ iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ if((*it)->getdest() == oldtarget)
+ {
+ m_connected_slots.push_back((*it)->duplicate(newtarget));
+ }
+
+ ++it;
+ }
+ }
+
+ ~_signal_base5()
+ {
+ disconnect_all();
+ }
+
+ void disconnect_all()
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator it = m_connected_slots.begin();
+ const_iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ (*it)->getdest()->signal_disconnect(this);
+ delete *it;
+
+ ++it;
+ }
+
+ m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
+ }
+
+ void disconnect(has_slots<mt_policy>* pclass)
+ {
+ lock_block<mt_policy> lock(this);
+ iterator it = m_connected_slots.begin();
+ iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ if((*it)->getdest() == pclass)
+ {
+ delete *it;
+ m_connected_slots.erase(it);
+ pclass->signal_disconnect(this);
+ return;
+ }
+
+ ++it;
+ }
+ }
+
+ void slot_disconnect(has_slots<mt_policy>* pslot)
+ {
+ lock_block<mt_policy> lock(this);
+ iterator it = m_connected_slots.begin();
+ iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ iterator itNext = it;
+ ++itNext;
+
+ if((*it)->getdest() == pslot)
+ {
+ delete *it;
+ m_connected_slots.erase(it);
+ // delete *it;
+ }
+
+ it = itNext;
+ }
+ }
+
+ protected:
+ connections_list m_connected_slots;
+ };
+
+ template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
+ class arg5_type, class arg6_type, class mt_policy>
+ class SAGGUI_EXPORT _signal_base6 : public _signal_base<mt_policy>
+ {
+ public:
+ typedef std::list<_connection_base6<arg1_type, arg2_type, arg3_type,
+ arg4_type, arg5_type, arg6_type, mt_policy> *> connections_list;
+ typedef typename connections_list::const_iterator const_iterator;
+ typedef typename connections_list::iterator iterator;
+
+ _signal_base6()
+ {
+ ;
+ }
+
+ _signal_base6(const _signal_base6<arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, arg6_type, mt_policy>& s)
+ : _signal_base<mt_policy>(s)
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator it = s.m_connected_slots.begin();
+ const_iterator itEnd = s.m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ (*it)->getdest()->signal_connect(this);
+ m_connected_slots.push_back((*it)->clone());
+
+ ++it;
+ }
+ }
+
+ void slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)
+ {
+ lock_block<mt_policy> lock(this);
+ iterator it = m_connected_slots.begin();
+ iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ if((*it)->getdest() == oldtarget)
+ {
+ m_connected_slots.push_back((*it)->duplicate(newtarget));
+ }
+
+ ++it;
+ }
+ }
+
+ ~_signal_base6()
+ {
+ disconnect_all();
+ }
+
+ void disconnect_all()
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator it = m_connected_slots.begin();
+ const_iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ (*it)->getdest()->signal_disconnect(this);
+ delete *it;
+
+ ++it;
+ }
+
+ m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
+ }
+
+ void disconnect(has_slots<mt_policy>* pclass)
+ {
+ lock_block<mt_policy> lock(this);
+ iterator it = m_connected_slots.begin();
+ iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ if((*it)->getdest() == pclass)
+ {
+ delete *it;
+ m_connected_slots.erase(it);
+ pclass->signal_disconnect(this);
+ return;
+ }
+
+ ++it;
+ }
+ }
+
+ void slot_disconnect(has_slots<mt_policy>* pslot)
+ {
+ lock_block<mt_policy> lock(this);
+ iterator it = m_connected_slots.begin();
+ iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ iterator itNext = it;
+ ++itNext;
+
+ if((*it)->getdest() == pslot)
+ {
+ delete *it;
+ m_connected_slots.erase(it);
+ // delete *it;
+ }
+
+ it = itNext;
+ }
+ }
+
+ protected:
+ connections_list m_connected_slots;
+ };
+
+ template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
+ class arg5_type, class arg6_type, class arg7_type, class mt_policy>
+ class SAGGUI_EXPORT _signal_base7 : public _signal_base<mt_policy>
+ {
+ public:
+ typedef std::list<_connection_base7<arg1_type, arg2_type, arg3_type,
+ arg4_type, arg5_type, arg6_type, arg7_type, mt_policy> *> connections_list;
+ typedef typename connections_list::const_iterator const_iterator;
+ typedef typename connections_list::iterator iterator;
+
+ _signal_base7()
+ {
+ ;
+ }
+
+ _signal_base7(const _signal_base7<arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, arg6_type, arg7_type, mt_policy>& s)
+ : _signal_base<mt_policy>(s)
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator it = s.m_connected_slots.begin();
+ const_iterator itEnd = s.m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ (*it)->getdest()->signal_connect(this);
+ m_connected_slots.push_back((*it)->clone());
+
+ ++it;
+ }
+ }
+
+ void slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)
+ {
+ lock_block<mt_policy> lock(this);
+ iterator it = m_connected_slots.begin();
+ iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ if((*it)->getdest() == oldtarget)
+ {
+ m_connected_slots.push_back((*it)->duplicate(newtarget));
+ }
+
+ ++it;
+ }
+ }
+
+ ~_signal_base7()
+ {
+ disconnect_all();
+ }
+
+ void disconnect_all()
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator it = m_connected_slots.begin();
+ const_iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ (*it)->getdest()->signal_disconnect(this);
+ delete *it;
+
+ ++it;
+ }
+
+ m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
+ }
+
+ void disconnect(has_slots<mt_policy>* pclass)
+ {
+ lock_block<mt_policy> lock(this);
+ iterator it = m_connected_slots.begin();
+ iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ if((*it)->getdest() == pclass)
+ {
+ delete *it;
+ m_connected_slots.erase(it);
+ pclass->signal_disconnect(this);
+ return;
+ }
+
+ ++it;
+ }
+ }
+
+ void slot_disconnect(has_slots<mt_policy>* pslot)
+ {
+ lock_block<mt_policy> lock(this);
+ iterator it = m_connected_slots.begin();
+ iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ iterator itNext = it;
+ ++itNext;
+
+ if((*it)->getdest() == pslot)
+ {
+ delete *it;
+ m_connected_slots.erase(it);
+ // delete *it;
+ }
+
+ it = itNext;
+ }
+ }
+
+ protected:
+ connections_list m_connected_slots;
+ };
+
+ template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
+ class arg5_type, class arg6_type, class arg7_type, class arg8_type, class mt_policy>
+ class SAGGUI_EXPORT _signal_base8 : public _signal_base<mt_policy>
+ {
+ public:
+ typedef std::list<_connection_base8<arg1_type, arg2_type, arg3_type,
+ arg4_type, arg5_type, arg6_type, arg7_type, arg8_type, mt_policy> *>
+ connections_list;
+ typedef typename connections_list::const_iterator const_iterator;
+ typedef typename connections_list::iterator iterator;
+
+ _signal_base8()
+ {
+ ;
+ }
+
+ _signal_base8(const _signal_base8<arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>& s)
+ : _signal_base<mt_policy>(s)
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator it = s.m_connected_slots.begin();
+ const_iterator itEnd = s.m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ (*it)->getdest()->signal_connect(this);
+ m_connected_slots.push_back((*it)->clone());
+
+ ++it;
+ }
+ }
+
+ void slot_duplicate(const has_slots<mt_policy>* oldtarget, has_slots<mt_policy>* newtarget)
+ {
+ lock_block<mt_policy> lock(this);
+ iterator it = m_connected_slots.begin();
+ iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ if((*it)->getdest() == oldtarget)
+ {
+ m_connected_slots.push_back((*it)->duplicate(newtarget));
+ }
+
+ ++it;
+ }
+ }
+
+ ~_signal_base8()
+ {
+ disconnect_all();
+ }
+
+ void disconnect_all()
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator it = m_connected_slots.begin();
+ const_iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ (*it)->getdest()->signal_disconnect(this);
+ delete *it;
+
+ ++it;
+ }
+
+ m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end());
+ }
+
+ void disconnect(has_slots<mt_policy>* pclass)
+ {
+ lock_block<mt_policy> lock(this);
+ iterator it = m_connected_slots.begin();
+ iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ if((*it)->getdest() == pclass)
+ {
+ delete *it;
+ m_connected_slots.erase(it);
+ pclass->signal_disconnect(this);
+ return;
+ }
+
+ ++it;
+ }
+ }
+
+ void slot_disconnect(has_slots<mt_policy>* pslot)
+ {
+ lock_block<mt_policy> lock(this);
+ iterator it = m_connected_slots.begin();
+ iterator itEnd = m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ iterator itNext = it;
+ ++itNext;
+
+ if((*it)->getdest() == pslot)
+ {
+ delete *it;
+ m_connected_slots.erase(it);
+ // delete *it;
+ }
+
+ it = itNext;
+ }
+ }
+
+ protected:
+ connections_list m_connected_slots;
+ };
+
+ typedef void slot;
+
+ template<class dest_type, class mt_policy>
+ class SAGGUI_EXPORT _connection0 : public _connection_base0<mt_policy>
+ {
+ public:
+ _connection0()
+ {
+ this->pobject = NULL;
+ this->pmemfun = NULL;
+ }
+
+ _connection0(dest_type* pobject, slot (dest_type::*pmemfun)())
+ {
+ m_pobject = pobject;
+ m_pmemfun = pmemfun;
+ }
+
+ virtual ~_connection0()
+ {
+ ;
+ }
+
+ virtual _connection_base0<mt_policy>* clone()
+ {
+ return new _connection0<dest_type, mt_policy>(*this);
+ }
+
+ virtual _connection_base0<mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)
+ {
+ return new _connection0<dest_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);
+ }
+
+ virtual void emit()
+ {
+ (m_pobject->*m_pmemfun)();
+ }
+
+ virtual has_slots<mt_policy>* getdest() const
+ {
+ return m_pobject;
+ }
+
+ //private:
+ dest_type* m_pobject;
+ void (dest_type::* m_pmemfun)();
+ };
+
+ template<class dest_type, class arg1_type, class mt_policy>
+ class SAGGUI_EXPORT _connection1 : public _connection_base1<arg1_type, mt_policy>
+ {
+ public:
+ _connection1()
+ {
+ this->pobject = NULL;
+ this->pmemfun = NULL;
+ }
+
+ _connection1(dest_type* pobject, slot (dest_type::*pmemfun)(arg1_type))
+ {
+ m_pobject = pobject;
+ m_pmemfun = pmemfun;
+ }
+
+ virtual ~_connection1()
+ {
+ ;
+ }
+
+ virtual _connection_base1<arg1_type, mt_policy>* clone()
+ {
+ return new _connection1<dest_type, arg1_type, mt_policy>(*this);
+ }
+
+ virtual _connection_base1<arg1_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)
+ {
+ return new _connection1<dest_type, arg1_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);
+ }
+
+ virtual void emit(arg1_type a1)
+ {
+ (m_pobject->*m_pmemfun)(a1);
+ }
+
+ virtual has_slots<mt_policy>* getdest() const
+ {
+ return m_pobject;
+ }
+
+ //private:
+ dest_type* m_pobject;
+ void (dest_type::* m_pmemfun)(arg1_type);
+ };
+
+ template<class dest_type, class arg1_type, class arg2_type, class mt_policy>
+ class SAGGUI_EXPORT _connection2 : public _connection_base2<arg1_type, arg2_type, mt_policy>
+ {
+ public:
+ _connection2()
+ {
+ this->pobject = NULL;
+ this->pmemfun = NULL;
+ }
+
+ _connection2(dest_type* pobject, slot (dest_type::*pmemfun)(arg1_type,
+ arg2_type))
+ {
+ m_pobject = pobject;
+ m_pmemfun = pmemfun;
+ }
+
+ virtual ~_connection2()
+ {
+ ;
+ }
+
+
+ virtual _connection_base2<arg1_type, arg2_type, mt_policy>* clone()
+ {
+ return new _connection2<dest_type, arg1_type, arg2_type, mt_policy>(*this);
+ }
+
+ virtual _connection_base2<arg1_type, arg2_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)
+ {
+ return new _connection2<dest_type, arg1_type, arg2_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);
+ }
+
+ virtual void emit(arg1_type a1, arg2_type a2)
+ {
+ (m_pobject->*m_pmemfun)(a1, a2);
+ }
+
+ virtual has_slots<mt_policy>* getdest() const
+ {
+ return m_pobject;
+ }
+
+ //private:
+ dest_type* m_pobject;
+ void (dest_type::* m_pmemfun)(arg1_type, arg2_type);
+ };
+
+ template<class dest_type, class arg1_type, class arg2_type, class arg3_type, class mt_policy>
+ class SAGGUI_EXPORT _connection3 : public _connection_base3<arg1_type, arg2_type, arg3_type, mt_policy>
+ {
+ public:
+ _connection3()
+ {
+ this->pobject = NULL;
+ this->pmemfun = NULL;
+ }
+
+ _connection3(dest_type* pobject, slot (dest_type::*pmemfun)(arg1_type,
+ arg2_type, arg3_type))
+ {
+ m_pobject = pobject;
+ m_pmemfun = pmemfun;
+ }
+
+ virtual ~_connection3()
+ {
+ ;
+ }
+
+
+ virtual _connection_base3<arg1_type, arg2_type, arg3_type, mt_policy>* clone()
+ {
+ return new _connection3<dest_type, arg1_type, arg2_type, arg3_type, mt_policy>(*this);
+ }
+
+ virtual _connection_base3<arg1_type, arg2_type, arg3_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)
+ {
+ return new _connection3<dest_type, arg1_type, arg2_type, arg3_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);
+ }
+
+ virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3)
+ {
+ (m_pobject->*m_pmemfun)(a1, a2, a3);
+ }
+
+ virtual has_slots<mt_policy>* getdest() const
+ {
+ return m_pobject;
+ }
+
+ //private:
+ dest_type* m_pobject;
+ void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type);
+ };
+
+ template<class dest_type, class arg1_type, class arg2_type, class arg3_type,
+ class arg4_type, class mt_policy>
+ class SAGGUI_EXPORT _connection4 : public _connection_base4<arg1_type, arg2_type,
+ arg3_type, arg4_type, mt_policy>
+ {
+ public:
+ _connection4()
+ {
+ this->pobject = NULL;
+ this->pmemfun = NULL;
+ }
+
+ _connection4(dest_type* pobject, slot (dest_type::*pmemfun)(arg1_type,
+ arg2_type, arg3_type, arg4_type))
+ {
+ m_pobject = pobject;
+ m_pmemfun = pmemfun;
+ }
+
+ virtual ~_connection4()
+ {
+ ;
+ }
+
+ virtual _connection_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>* clone()
+ {
+ return new _connection4<dest_type, arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>(*this);
+ }
+
+ virtual _connection_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)
+ {
+ return new _connection4<dest_type, arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);
+ }
+
+ virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3,
+ arg4_type a4)
+ {
+ (m_pobject->*m_pmemfun)(a1, a2, a3, a4);
+ }
+
+ virtual has_slots<mt_policy>* getdest() const
+ {
+ return m_pobject;
+ }
+
+ //private:
+ dest_type* m_pobject;
+ void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type,
+ arg4_type);
+ };
+
+ template<class dest_type, class arg1_type, class arg2_type, class arg3_type,
+ class arg4_type, class arg5_type, class mt_policy>
+ class SAGGUI_EXPORT _connection5 : public _connection_base5<arg1_type, arg2_type,
+ arg3_type, arg4_type, arg5_type, mt_policy>
+ {
+ public:
+ _connection5()
+ {
+ this->pobject = NULL;
+ this->pmemfun = NULL;
+ }
+
+ _connection5(dest_type* pobject, slot (dest_type::*pmemfun)(arg1_type,
+ arg2_type, arg3_type, arg4_type, arg5_type))
+ {
+ m_pobject = pobject;
+ m_pmemfun = pmemfun;
+ }
+
+ virtual ~_connection5()
+ {
+ ;
+ }
+
+ virtual _connection_base5<arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, mt_policy>* clone()
+ {
+ return new _connection5<dest_type, arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, mt_policy>(*this);
+ }
+
+ virtual _connection_base5<arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)
+ {
+ return new _connection5<dest_type, arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);
+ }
+
+ virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
+ arg5_type a5)
+ {
+ (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5);
+ }
+
+ virtual has_slots<mt_policy>* getdest() const
+ {
+ return m_pobject;
+ }
+
+ //private:
+ dest_type* m_pobject;
+ void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type);
+ };
+
+ template<class dest_type, class arg1_type, class arg2_type, class arg3_type,
+ class arg4_type, class arg5_type, class arg6_type, class mt_policy>
+ class SAGGUI_EXPORT _connection6 : public _connection_base6<arg1_type, arg2_type,
+ arg3_type, arg4_type, arg5_type, arg6_type, mt_policy>
+ {
+ public:
+ _connection6()
+ {
+ this->pobject = NULL;
+ this->pmemfun = NULL;
+ }
+
+ _connection6(dest_type* pobject, slot (dest_type::*pmemfun)(arg1_type,
+ arg2_type, arg3_type, arg4_type, arg5_type, arg6_type))
+ {
+ m_pobject = pobject;
+ m_pmemfun = pmemfun;
+ }
+
+ virtual ~_connection6()
+ {
+ ;
+ }
+
+ virtual _connection_base6<arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, arg6_type, mt_policy>* clone()
+ {
+ return new _connection6<dest_type, arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, arg6_type, mt_policy>(*this);
+ }
+
+ virtual _connection_base6<arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, arg6_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)
+ {
+ return new _connection6<dest_type, arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, arg6_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);
+ }
+
+ virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
+ arg5_type a5, arg6_type a6)
+ {
+ (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6);
+ }
+
+ virtual has_slots<mt_policy>* getdest() const
+ {
+ return m_pobject;
+ }
+
+ //private:
+ dest_type* m_pobject;
+ void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, arg6_type);
+ };
+
+ template<class dest_type, class arg1_type, class arg2_type, class arg3_type,
+ class arg4_type, class arg5_type, class arg6_type, class arg7_type, class mt_policy>
+ class SAGGUI_EXPORT _connection7 : public _connection_base7<arg1_type, arg2_type,
+ arg3_type, arg4_type, arg5_type, arg6_type, arg7_type, mt_policy>
+ {
+ public:
+ _connection7()
+ {
+ this->pobject = NULL;
+ this->pmemfun = NULL;
+ }
+
+ _connection7(dest_type* pobject, slot (dest_type::*pmemfun)(arg1_type,
+ arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, arg7_type))
+ {
+ m_pobject = pobject;
+ m_pmemfun = pmemfun;
+ }
+
+ virtual ~_connection7()
+ {
+ ;
+ }
+
+ virtual _connection_base7<arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, arg6_type, arg7_type, mt_policy>* clone()
+ {
+ return new _connection7<dest_type, arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, arg6_type, arg7_type, mt_policy>(*this);
+ }
+
+ virtual _connection_base7<arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, arg6_type, arg7_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)
+ {
+ return new _connection7<dest_type, arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, arg6_type, arg7_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);
+ }
+
+ virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
+ arg5_type a5, arg6_type a6, arg7_type a7)
+ {
+ (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6, a7);
+ }
+
+ virtual has_slots<mt_policy>* getdest() const
+ {
+ return m_pobject;
+ }
+
+ //private:
+ dest_type* m_pobject;
+ void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, arg6_type, arg7_type);
+ };
+
+ template<class dest_type, class arg1_type, class arg2_type, class arg3_type,
+ class arg4_type, class arg5_type, class arg6_type, class arg7_type,
+ class arg8_type, class mt_policy>
+ class SAGGUI_EXPORT _connection8 : public _connection_base8<arg1_type, arg2_type,
+ arg3_type, arg4_type, arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>
+ {
+ public:
+ _connection8()
+ {
+ this->pobject = NULL;
+ this->pmemfun = NULL;
+ }
+
+ _connection8(dest_type* pobject, slot (dest_type::*pmemfun)(arg1_type,
+ arg2_type, arg3_type, arg4_type, arg5_type, arg6_type,
+ arg7_type, arg8_type))
+ {
+ m_pobject = pobject;
+ m_pmemfun = pmemfun;
+ }
+
+ virtual ~_connection8()
+ {
+ ;
+ }
+
+ virtual _connection_base8<arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>* clone()
+ {
+ return new _connection8<dest_type, arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>(*this);
+ }
+
+ virtual _connection_base8<arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>* duplicate(has_slots<mt_policy>* pnewdest)
+ {
+ return new _connection8<dest_type, arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);
+ }
+
+ virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
+ arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8)
+ {
+ (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6, a7, a8);
+ }
+
+ virtual has_slots<mt_policy>* getdest() const
+ {
+ return m_pobject;
+ }
+
+ //private:
+ dest_type* m_pobject;
+ void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, arg6_type, arg7_type, arg8_type);
+ };
+
+ template<class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
+ class SAGGUI_EXPORT has_signals
+ {
+ public:
+ has_signals()
+ {
+ ;
+ }
+
+ virtual ~has_signals()
+ {
+ ;
+ remove_connections();
+ }
+
+ void bind_signal(has_signals<mt_policy>* chainsig)
+ {
+ this->bound_signals.push_back(chainsig);
+ }
+
+ void connect_signal(has_signals<mt_policy>* chainsig)
+ {
+ if(chainsig == this)return;
+ sig_iterator it = connected_signals.begin();
+ sig_iterator itEnd = connected_signals.end();
+ sig_iterator itFind;
+
+ if((itFind = std::find(it, itEnd, chainsig)) == itEnd)
+ {
+ this->connected_signals.push_back(chainsig);
+ chainsig->bind_signal(this);
+ }
+ }
+
+ void disconnect_connected(has_signals<mt_policy>* chainsig)
+ {
+ sig_iterator it = connected_signals.begin();
+ sig_iterator itEnd = connected_signals.end();
+ sig_iterator itFind;
+
+ if((itFind = std::find(it, itEnd, chainsig)) != itEnd)
+ {
+ if((*itFind))
+ {
+ (*itFind)->bound_signals.remove(this);
+ }
+ connected_signals.erase(itFind);
+ }
+ }
+
+ void disconnect_bound(has_signals<mt_policy>* chainsig)
+ {
+ sig_iterator it = bound_signals.begin();
+ sig_iterator itEnd = bound_signals.end();
+ sig_iterator itFind;
+
+ if((itFind = std::find(it, itEnd, chainsig)) != itEnd)
+ {
+ if((*itFind))
+ {
+ (*itFind)->connected_signals.remove(this);
+ }
+ bound_signals.erase(itFind);
+ }
+ }
+
+ void remove_connections()
+ {
+ if(!connected_signals.empty())
+ {
+ sig_iterator it = connected_signals.begin();
+ sig_iterator itEnd = connected_signals.end();
+ while(it != itEnd)
+ {
+ if((*it))(*it)->bound_signals.remove(this);
+ ++it;
+ }
+ connected_signals.resize(0);
+ }
+
+ if(!bound_signals.empty())
+ {
+ sig_iterator it = bound_signals.begin();
+ sig_iterator itEnd = bound_signals.end();
+ while(it != itEnd)
+ {
+ if((*it))(*it)->connected_signals.remove(this);
+ ++it;
+ }
+ bound_signals.resize(0);
+ }
+ }
+
+ protected:
+ std::list<has_signals<mt_policy>*> connected_signals;
+ std::list<has_signals<mt_policy>*> bound_signals;
+ typedef typename std::list<has_signals<mt_policy>*>::iterator sig_iterator;
+ };
+
+ template<class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
+ class SAGGUI_EXPORT signal0 : public _signal_base0<mt_policy>, public has_signals<mt_policy>
+ {
+ public:
+ typedef typename _signal_base0<mt_policy>::connections_list::iterator iterator;
+ typedef typename _signal_base0<mt_policy>::connections_list::const_iterator const_iterator;
+ typedef typename std::list<has_signals<mt_policy>*>::iterator sig_iterator;
+ signal0()
+ {
+ ;
+ }
+
+ signal0(const signal0<mt_policy>& s)
+ : _signal_base0<mt_policy>(s)
+ {
+ ;
+ }
+
+ virtual ~signal0()
+ {
+ ;
+ }
+
+ template<class desttype>
+ void connect(desttype* pclass, void (desttype::*pmemfun)())
+ {
+ lock_block<mt_policy> lock(this);
+ _connection0<desttype, mt_policy>* conn =
+ new _connection0<desttype, mt_policy>(pclass, pmemfun);
+ this->m_connected_slots.push_back(conn);
+ pclass->signal_connect(this);
+ }
+
+ template<class desttype>
+ void disconnect_slot(desttype* pclass, void (desttype::*pmemfun)())
+ {
+ lock_block<mt_policy> lock(this);
+ iterator itNext, it = this->m_connected_slots.begin();
+ iterator itEnd = this->m_connected_slots.end();
+
+
+ while(it != itEnd)
+ {
+ itNext = it;
+ ++itNext;
+ _connection0<desttype, mt_policy>* temp = dynamic_cast<_connection0<desttype, mt_policy> *>((*it));
+ if(temp->m_pobject == pclass && temp->m_pmemfun == pmemfun)
+ {
+ delete (*it);
+ this->m_connected_slots.erase(it);
+ pclass->signal_disconnect(this);
+ break;
+ }
+
+ it = itNext;
+ }
+ }
+
+ void connect(signal0<mt_policy>* chainsig)
+ {
+ lock_block<mt_policy> lock(this);
+ this->connect_signal(chainsig);
+ }
+
+ void disconnect_signal(signal0<mt_policy>* chainsig)
+ {
+ lock_block<mt_policy> lock(this);
+ this->disconnect_connected(chainsig);
+ }
+
+ void emit()
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator itNext, it = this->m_connected_slots.begin();
+ const_iterator itEnd = this->m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ itNext = it;
+ ++itNext;
+
+ (*it)->emit();
+
+ it = itNext;
+ }
+
+ sig_iterator siNext, si = this->connected_signals.begin();
+ sig_iterator siEnd = this->connected_signals.end();
+
+ while(si != siEnd)
+ {
+ siNext = si;
+ ++siNext;
+
+ static_cast<signal0<mt_policy>*>(*si)->emit();
+
+ si = siNext;
+ }
+ }
+
+ void operator()()
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator itNext, it = this->m_connected_slots.begin();
+ const_iterator itEnd = this->m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ itNext = it;
+ ++itNext;
+
+ (*it)->emit();
+
+ it = itNext;
+ }
+
+ sig_iterator siNext, si = this->connected_signals.begin();
+ sig_iterator siEnd = this->connected_signals.end();
+
+ while(si != siEnd)
+ {
+ siNext = si;
+ ++siNext;
+
+ static_cast<signal0<mt_policy>*>(*si)->emit();
+
+ si = siNext;
+ }
+ }
+ };
+
+ template<class arg1_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
+ class SAGGUI_EXPORT signal1 : public _signal_base1<arg1_type, mt_policy>, public has_signals<mt_policy>
+ {
+ public:
+ typedef typename std::list<has_signals<mt_policy>*>::iterator sig_iterator;
+ typedef typename _signal_base1<arg1_type, mt_policy>::connections_list::iterator iterator;
+ typedef typename _signal_base1<arg1_type, mt_policy>::connections_list::const_iterator const_iterator;
+ signal1()
+ {
+ ;
+ }
+
+ signal1(const signal1<arg1_type, mt_policy>& s)
+ : _signal_base1<arg1_type, mt_policy>(s)
+ {
+ ;
+ }
+
+ virtual ~signal1()
+ {
+ ;
+ }
+
+ template<class desttype>
+ void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type))
+ {
+ lock_block<mt_policy> lock(this);
+ _connection1<desttype, arg1_type, mt_policy>* conn =
+ new _connection1<desttype, arg1_type, mt_policy>(pclass, pmemfun);
+ this->m_connected_slots.push_back(conn);
+ pclass->signal_connect(this);
+ }
+
+ template<class desttype>
+ void disconnect_slot(desttype* pclass, void (desttype::*pmemfun)(arg1_type))
+ {
+ lock_block<mt_policy> lock(this);
+ iterator itNext, it = this->m_connected_slots.begin();
+ iterator itEnd = this->m_connected_slots.end();
+
+
+ while(it != itEnd)
+ {
+ itNext = it;
+ ++itNext;
+ _connection1<desttype, arg1_type, mt_policy>* temp = dynamic_cast<_connection1<desttype, arg1_type, mt_policy> *>((*it));
+ if(temp->m_pobject == pclass && temp->m_pmemfun == pmemfun)
+ {
+ delete (*it);
+ this->m_connected_slots.erase(it);
+ pclass->signal_disconnect(this);
+ break;
+ }
+
+ it = itNext;
+ }
+ }
+
+ void bind_signal(signal1<arg1_type, mt_policy>* chainsig)
+ {
+ lock_block<mt_policy> lock(this);
+ this->bound_signals.push_back(chainsig);
+ }
+
+ void connect(signal1<arg1_type, mt_policy>* chainsig)
+ {
+ lock_block<mt_policy> lock(this);
+ this->connect_signal(chainsig);
+ }
+
+ void disconnect_signal(signal1<arg1_type, mt_policy>* chainsig)
+ {
+ lock_block<mt_policy> lock(this);
+ this->disconnect_connected(chainsig);
+ }
+
+ void emit(arg1_type a1)
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator itNext, it = this->m_connected_slots.begin();
+ const_iterator itEnd = this->m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ itNext = it;
+ ++itNext;
+
+ (*it)->emit(a1);
+
+ it = itNext;
+ }
+
+ sig_iterator siNext, si = this->connected_signals.begin();
+ sig_iterator siEnd = this->connected_signals.end();
+
+ while(si != siEnd)
+ {
+ siNext = si;
+ ++siNext;
+
+ static_cast<signal1<arg1_type, mt_policy>*>(*si)->emit(a1);
+
+ si = siNext;
+ }
+ }
+
+ void operator()(arg1_type a1)
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator itNext, it = this->m_connected_slots.begin();
+ const_iterator itEnd = this->m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ itNext = it;
+ ++itNext;
+
+ (*it)->emit(a1);
+
+ it = itNext;
+ }
+
+ sig_iterator siNext, si = this->connected_signals.begin();
+ sig_iterator siEnd = this->connected_signals.end();
+
+ while(si != siEnd)
+ {
+ siNext = si;
+ ++siNext;
+
+ static_cast<signal1<arg1_type, mt_policy>*>(*si)->emit(a1);
+
+ si = siNext;
+ }
+ }
+ };
+
+ template<class arg1_type, typename arg2_type, typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
+ class SAGGUI_EXPORT signal2 : public _signal_base2<arg1_type, arg2_type, mt_policy>, public has_signals<mt_policy>
+ {
+ public:
+ typedef typename std::list<has_signals<mt_policy>*>::iterator sig_iterator;
+ typedef typename _signal_base2<arg1_type, arg2_type, mt_policy>::connections_list::const_iterator const_iterator;
+ typedef typename _signal_base2<arg1_type, arg2_type, mt_policy>::connections_list::iterator iterator;
+ signal2()
+ {
+ ;
+ }
+
+ signal2(const signal2<arg1_type, arg2_type, mt_policy>& s)
+ : _signal_base2<arg1_type, arg2_type, mt_policy>(s)
+ {
+ ;
+ }
+
+ virtual ~signal2()
+ {
+ ;
+ }
+
+ template<class desttype>
+ void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,
+ arg2_type))
+ {
+ lock_block<mt_policy> lock(this);
+ _connection2<desttype, arg1_type, arg2_type, mt_policy>* conn = new
+ _connection2<desttype, arg1_type, arg2_type, mt_policy>(pclass, pmemfun);
+ this->m_connected_slots.push_back(conn);
+ pclass->signal_connect(this);
+ }
+
+ template<class desttype>
+ void disconnect_slot(desttype* pclass, void (desttype::*pmemfun)(arg1_type,
+ arg2_type))
+ {
+ lock_block<mt_policy> lock(this);
+ iterator itNext, it = this->m_connected_slots.begin();
+ iterator itEnd = this->m_connected_slots.end();
+
+
+ while(it != itEnd)
+ {
+ itNext = it;
+ ++itNext;
+ _connection2<desttype, arg1_type, arg2_type, mt_policy>* temp = dynamic_cast<_connection2<desttype, arg1_type, arg2_type, mt_policy> *>((*it));
+ if(temp->m_pobject == pclass && temp->m_pmemfun == pmemfun)
+ {
+ delete (*it);
+ this->m_connected_slots.erase(it);
+ pclass->signal_disconnect(this);
+ break;
+ }
+
+ it = itNext;
+ }
+ }
+
+ void connect(signal2<arg1_type, arg2_type, mt_policy>* chainsig)
+ {
+ lock_block<mt_policy> lock(this);
+ this->connect_signal(chainsig);
+ }
+
+ void disconnect_signal(signal2<arg1_type, arg2_type, mt_policy>* chainsig)
+ {
+ lock_block<mt_policy> lock(this);
+ this->disconnect_connected(chainsig);
+ }
+
+ void emit(arg1_type a1, arg2_type a2)
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator itNext, it = this->m_connected_slots.begin();
+ const_iterator itEnd = this->m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ itNext = it;
+ ++itNext;
+
+ (*it)->emit(a1, a2);
+
+ it = itNext;
+ }
+
+ sig_iterator siNext, si = this->connected_signals.begin();
+ sig_iterator siEnd = this->connected_signals.end();
+
+ while(si != siEnd)
+ {
+ siNext = si;
+ ++siNext;
+
+ static_cast<signal2<arg1_type, arg2_type, mt_policy>*>(*si)->emit(a1,a2);
+
+ si = siNext;
+ }
+ }
+
+ void operator()(arg1_type a1, arg2_type a2)
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator itNext, it = this->m_connected_slots.begin();
+ const_iterator itEnd = this->m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ itNext = it;
+ ++itNext;
+
+ (*it)->emit(a1, a2);
+
+ it = itNext;
+ }
+
+ sig_iterator siNext, si = this->connected_signals.begin();
+ sig_iterator siEnd = this->connected_signals.end();
+
+ while(si != siEnd)
+ {
+ siNext = si;
+ ++siNext;
+
+ static_cast<signal2<arg1_type, arg2_type, mt_policy>*>(*si)->emit(a1,a2);
+
+ si = siNext;
+ }
+ }
+ };
+
+ template<class arg1_type, typename arg2_type, typename arg3_type, typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
+ class SAGGUI_EXPORT signal3 : public _signal_base3<arg1_type, arg2_type, arg3_type, mt_policy>, public has_signals<mt_policy>
+ {
+ public:
+ typedef typename std::list<has_signals<mt_policy>*>::iterator sig_iterator;
+ typedef typename _signal_base3<arg1_type, arg2_type, arg3_type, mt_policy>::connections_list::const_iterator const_iterator;
+ typedef typename _signal_base3<arg1_type, arg2_type, arg3_type, mt_policy>::connections_list::iterator iterator;
+ signal3()
+ {
+ ;
+ }
+
+ signal3(const signal3<arg1_type, arg2_type, arg3_type, mt_policy>& s)
+ : _signal_base3<arg1_type, arg2_type, arg3_type, mt_policy>(s)
+ {
+ ;
+ }
+
+ virtual ~signal3()
+ {
+ ;
+ }
+
+ template<class desttype>
+ void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,
+ arg2_type, arg3_type))
+ {
+ lock_block<mt_policy> lock(this);
+ _connection3<desttype, arg1_type, arg2_type, arg3_type, mt_policy>* conn =
+ new _connection3<desttype, arg1_type, arg2_type, arg3_type, mt_policy>(pclass,
+ pmemfun);
+ this->m_connected_slots.push_back(conn);
+ pclass->signal_connect(this);
+ }
+
+ template<class desttype>
+ void disconnect_slot(desttype* pclass, void (desttype::*pmemfun)(arg1_type,
+ arg2_type, arg3_type))
+ {
+ lock_block<mt_policy> lock(this);
+ iterator itNext, it = this->m_connected_slots.begin();
+ iterator itEnd = this->m_connected_slots.end();
+
+
+ while(it != itEnd)
+ {
+ itNext = it;
+ ++itNext;
+ _connection3<desttype, arg1_type, arg2_type, arg3_type, mt_policy>* temp = dynamic_cast<_connection3<desttype, arg1_type, arg2_type, arg3_type, mt_policy> *>((*it));
+ if(temp->m_pobject == pclass && temp->m_pmemfun == pmemfun)
+ {
+ delete (*it);
+ this->m_connected_slots.erase(it);
+ pclass->signal_disconnect(this);
+ break;
+ }
+
+ it = itNext;
+ }
+ }
+
+ void connect(signal3<arg1_type, arg2_type, arg3_type, mt_policy>* chainsig)
+ {
+ lock_block<mt_policy> lock(this);
+ this->connect_signal(chainsig);
+ }
+
+ void disconnect_signal(signal3<arg1_type, arg2_type, arg3_type, mt_policy>* chainsig)
+ {
+ lock_block<mt_policy> lock(this);
+ this->disconnect_connected(chainsig);
+ }
+
+ void emit(arg1_type a1, arg2_type a2, arg3_type a3)
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator itNext, it = this->m_connected_slots.begin();
+ const_iterator itEnd = this->m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ itNext = it;
+ ++itNext;
+
+ (*it)->emit(a1, a2, a3);
+
+ it = itNext;
+ }
+
+ sig_iterator siNext, si = this->connected_signals.begin();
+ sig_iterator siEnd = this->connected_signals.end();
+
+ while(si != siEnd)
+ {
+ siNext = si;
+ ++siNext;
+
+ static_cast<signal3<arg1_type, arg2_type, arg3_type, mt_policy>*>(*si)->emit(a1,a2,a3);
+
+ si = siNext;
+ }
+ }
+
+ void operator()(arg1_type a1, arg2_type a2, arg3_type a3)
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator itNext, it = this->m_connected_slots.begin();
+ const_iterator itEnd = this->m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ itNext = it;
+ ++itNext;
+
+ (*it)->emit(a1, a2, a3);
+
+ it = itNext;
+ }
+
+ sig_iterator siNext, si = this->connected_signals.begin();
+ sig_iterator siEnd = this->connected_signals.end();
+
+ while(si != siEnd)
+ {
+ siNext = si;
+ ++siNext;
+
+ static_cast<signal3<arg1_type, arg2_type, arg3_type, mt_policy>*>(*si)->emit(a1,a2,a3);
+
+ si = siNext;
+ }
+ }
+ };
+
+ template<class arg1_type, class arg2_type, class arg3_type, class arg4_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
+ class SAGGUI_EXPORT signal4 : public _signal_base4<arg1_type, arg2_type, arg3_type,
+ arg4_type, mt_policy>, public has_signals<mt_policy>
+ {
+ public:
+ typedef typename std::list<has_signals<mt_policy>*>::iterator sig_iterator;
+ typedef typename _signal_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>::connections_list::const_iterator const_iterator;
+ typedef typename _signal_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>::connections_list::iterator iterator;
+ signal4()
+ {
+ ;
+ }
+
+ signal4(const signal4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>& s)
+ : _signal_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>(s)
+ {
+ ;
+ }
+
+ virtual ~signal4()
+ {
+ ;
+ }
+
+ template<class desttype>
+ void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,
+ arg2_type, arg3_type, arg4_type))
+ {
+ lock_block<mt_policy> lock(this);
+ _connection4<desttype, arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>*
+ conn = new _connection4<desttype, arg1_type, arg2_type, arg3_type,
+ arg4_type, mt_policy>(pclass, pmemfun);
+ this->m_connected_slots.push_back(conn);
+ pclass->signal_connect(this);
+ }
+
+ template<class desttype>
+ void disconnect_slot(desttype* pclass, void (desttype::*pmemfun)(arg1_type,
+ arg2_type, arg3_type, arg4_type))
+ {
+ lock_block<mt_policy> lock(this);
+ iterator itNext, it = this->m_connected_slots.begin();
+ iterator itEnd = this->m_connected_slots.end();
+
+
+ while(it != itEnd)
+ {
+ itNext = it;
+ ++itNext;
+ _connection4<desttype, arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>* temp = dynamic_cast<_connection4<desttype, arg1_type, arg2_type, arg3_type, arg4_type, mt_policy> *>((*it));
+ if(temp->m_pobject == pclass && temp->m_pmemfun == pmemfun)
+ {
+ delete (*it);
+ this->m_connected_slots.erase(it);
+ pclass->signal_disconnect(this);
+ break;
+ }
+
+ it = itNext;
+ }
+ }
+
+ void connect(signal4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>* chainsig)
+ {
+ lock_block<mt_policy> lock(this);
+ this->connect_signal(chainsig);
+ }
+
+ void disconnect_signal(signal4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>* chainsig)
+ {
+ lock_block<mt_policy> lock(this);
+ this->disconnect_connected(chainsig);
+ }
+
+ void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4)
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator itNext, it = this->m_connected_slots.begin();
+ const_iterator itEnd = this->m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ itNext = it;
+ ++itNext;
+
+ (*it)->emit(a1, a2, a3, a4);
+
+ it = itNext;
+ }
+
+ sig_iterator siNext, si = this->connected_signals.begin();
+ sig_iterator siEnd = this->connected_signals.end();
+
+ while(si != siEnd)
+ {
+ siNext = si;
+ ++siNext;
+
+ static_cast<signal4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>*>(*si)->emit(a1,a2,a3,a4);
+
+ si = siNext;
+ }
+ }
+
+ void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4)
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator itNext, it = this->m_connected_slots.begin();
+ const_iterator itEnd = this->m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ itNext = it;
+ ++itNext;
+
+ (*it)->emit(a1, a2, a3, a4);
+
+ it = itNext;
+ }
+
+ sig_iterator siNext, si = this->connected_signals.begin();
+ sig_iterator siEnd = this->connected_signals.end();
+
+ while(si != siEnd)
+ {
+ siNext = si;
+ ++siNext;
+
+ static_cast<signal4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>*>(*si)->emit(a1,a2,a3,a4);
+
+ si = siNext;
+ }
+ }
+ };
+
+ template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
+ class arg5_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
+ class SAGGUI_EXPORT signal5 : public _signal_base5<arg1_type, arg2_type, arg3_type,
+ arg4_type, arg5_type, mt_policy>, public has_signals<mt_policy>
+ {
+ public:
+ typedef typename std::list<has_signals<mt_policy>*>::iterator sig_iterator;
+ typedef typename _signal_base5<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, mt_policy>::connections_list::const_iterator const_iterator;
+ typedef typename _signal_base5<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, mt_policy>::connections_list::iterator iterator;
+ signal5()
+ {
+ ;
+ }
+
+ signal5(const signal5<arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, mt_policy>& s)
+ : _signal_base5<arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, mt_policy>(s)
+ {
+ ;
+ }
+
+ virtual ~signal5()
+ {
+ ;
+ }
+
+ template<class desttype>
+ void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,
+ arg2_type, arg3_type, arg4_type, arg5_type))
+ {
+ lock_block<mt_policy> lock(this);
+ _connection5<desttype, arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, mt_policy>* conn = new _connection5<desttype, arg1_type, arg2_type,
+ arg3_type, arg4_type, arg5_type, mt_policy>(pclass, pmemfun);
+ this->m_connected_slots.push_back(conn);
+ pclass->signal_connect(this);
+ }
+
+ template<class desttype>
+ void disconnect_slot(desttype* pclass, void (desttype::*pmemfun)(arg1_type,
+ arg2_type, arg3_type, arg4_type, arg5_type))
+ {
+ lock_block<mt_policy> lock(this);
+ iterator itNext, it = this->m_connected_slots.begin();
+ iterator itEnd = this->m_connected_slots.end();
+
+
+ while(it != itEnd)
+ {
+ itNext = it;
+ ++itNext;
+ _connection5<desttype, arg1_type, arg2_type, arg3_type, arg4_type, arg5_type,mt_policy>* temp = dynamic_cast<_connection5<desttype, arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, mt_policy> *>((*it));
+ if(temp->m_pobject == pclass && temp->m_pmemfun == pmemfun)
+ {
+ delete (*it);
+ this->m_connected_slots.erase(it);
+ pclass->signal_disconnect(this);
+ break;
+ }
+
+ it = itNext;
+ }
+ }
+
+ void connect(signal5<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, mt_policy>* chainsig)
+ {
+ lock_block<mt_policy> lock(this);
+ this->connect_signal(chainsig);
+ }
+
+ void disconnect_signal(signal5<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, mt_policy>* chainsig)
+ {
+ lock_block<mt_policy> lock(this);
+ this->disconnect_connected(chainsig);
+ }
+
+ void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
+ arg5_type a5)
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator itNext, it = this->m_connected_slots.begin();
+ const_iterator itEnd = this->m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ itNext = it;
+ ++itNext;
+
+ (*it)->emit(a1, a2, a3, a4, a5);
+
+ it = itNext;
+ }
+
+ sig_iterator siNext, si = this->connected_signals.begin();
+ sig_iterator siEnd = this->connected_signals.end();
+
+ while(si != siEnd)
+ {
+ siNext = si;
+ ++siNext;
+
+ static_cast<signal5<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, mt_policy>*>(*si)->emit(a1,a2,a3,a4,a5);
+
+ si = siNext;
+ }
+ }
+
+ void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
+ arg5_type a5)
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator itNext, it = this->m_connected_slots.begin();
+ const_iterator itEnd = this->m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ itNext = it;
+ ++itNext;
+
+ (*it)->emit(a1, a2, a3, a4, a5);
+
+ it = itNext;
+ }
+
+ sig_iterator siNext, si = this->connected_signals.begin();
+ sig_iterator siEnd = this->connected_signals.end();
+
+ while(si != siEnd)
+ {
+ siNext = si;
+ ++siNext;
+
+ static_cast<signal5<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, mt_policy>*>(*si)->emit(a1,a2,a3,a4,a5);
+
+ si = siNext;
+ }
+ }
+ };
+
+
+ template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
+ class arg5_type, class arg6_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
+ class SAGGUI_EXPORT signal6 : public _signal_base6<arg1_type, arg2_type, arg3_type,
+ arg4_type, arg5_type, arg6_type, mt_policy>, public has_signals<mt_policy>
+ {
+ public:
+ typedef typename std::list<has_signals<mt_policy>*>::iterator sig_iterator;
+ typedef typename _signal_base6<arg1_type, arg2_type, arg3_type,
+ arg4_type, arg5_type, arg6_type, mt_policy>::connections_list::const_iterator const_iterator;
+ typedef typename _signal_base6<arg1_type, arg2_type, arg3_type,
+ arg4_type, arg5_type, arg6_type, mt_policy>::connections_list::iterator iterator;
+ signal6()
+ {
+ ;
+ }
+
+ signal6(const signal6<arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, arg6_type, mt_policy>& s)
+ : _signal_base6<arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, arg6_type, mt_policy>(s)
+ {
+ ;
+ }
+
+ virtual ~signal6()
+ {
+ ;
+ }
+
+ template<class desttype>
+ void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,
+ arg2_type, arg3_type, arg4_type, arg5_type, arg6_type))
+ {
+ lock_block<mt_policy> lock(this);
+ _connection6<desttype, arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, arg6_type, mt_policy>* conn =
+ new _connection6<desttype, arg1_type, arg2_type, arg3_type,
+ arg4_type, arg5_type, arg6_type, mt_policy>(pclass, pmemfun);
+ this->m_connected_slots.push_back(conn);
+ pclass->signal_connect(this);
+ }
+
+ template<class desttype>
+ void disconnect_slot(desttype* pclass, void (desttype::*pmemfun)(arg1_type,
+ arg2_type, arg3_type, arg4_type, arg5_type, arg6_type))
+ {
+ lock_block<mt_policy> lock(this);
+ iterator itNext, it = this->m_connected_slots.begin();
+ iterator itEnd = this->m_connected_slots.end();
+
+
+ while(it != itEnd)
+ {
+ itNext = it;
+ ++itNext;
+ _connection6<desttype, arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, mt_policy>* temp = dynamic_cast<_connection6<desttype, arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, mt_policy> *>((*it));
+ if(temp->m_pobject == pclass && temp->m_pmemfun == pmemfun)
+ {
+ delete (*it);
+ this->m_connected_slots.erase(it);
+ pclass->signal_disconnect(this);
+ break;
+ }
+
+ it = itNext;
+ }
+ }
+
+ void connect(signal6<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, mt_policy>* chainsig)
+ {
+ lock_block<mt_policy> lock(this);
+ this->connect_signal(chainsig);
+ }
+
+ void disconnect_signal(signal6<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, mt_policy>* chainsig)
+ {
+ lock_block<mt_policy> lock(this);
+ this->disconnect_connected(chainsig);
+ }
+
+ void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
+ arg5_type a5, arg6_type a6)
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator itNext, it = this->m_connected_slots.begin();
+ const_iterator itEnd = this->m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ itNext = it;
+ ++itNext;
+
+ (*it)->emit(a1, a2, a3, a4, a5, a6);
+
+ it = itNext;
+ }
+
+ sig_iterator siNext, si = this->connected_signals.begin();
+ sig_iterator siEnd = this->connected_signals.end();
+
+ while(si != siEnd)
+ {
+ siNext = si;
+ ++siNext;
+
+ static_cast<signal6<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, mt_policy>*>(*si)->emit(a1,a2,a3,a4,a5,a6);
+
+ si = siNext;
+ }
+ }
+
+ void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
+ arg5_type a5, arg6_type a6)
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator itNext, it = this->m_connected_slots.begin();
+ const_iterator itEnd = this->m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ itNext = it;
+ ++itNext;
+
+ (*it)->emit(a1, a2, a3, a4, a5, a6);
+
+ it = itNext;
+ }
+
+ sig_iterator siNext, si = this->connected_signals.begin();
+ sig_iterator siEnd = this->connected_signals.end();
+
+ while(si != siEnd)
+ {
+ siNext = si;
+ ++siNext;
+
+ static_cast<signal6<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, mt_policy>*>(*si)->emit(a1,a2,a3,a4,a5,a6);
+
+ si = siNext;
+ }
+ }
+ };
+
+ template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
+ class arg5_type, class arg6_type, class arg7_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
+ class SAGGUI_EXPORT signal7 : public _signal_base7<arg1_type, arg2_type, arg3_type,
+ arg4_type, arg5_type, arg6_type, arg7_type, mt_policy>, public has_signals<mt_policy>
+ {
+ public:
+ typedef typename std::list<has_signals<mt_policy>*>::iterator sig_iterator;
+ typedef typename _signal_base7<arg1_type, arg2_type, arg3_type,
+ arg4_type, arg5_type, arg6_type, arg7_type, mt_policy>::connections_list::const_iterator const_iterator;
+ typedef typename _signal_base7<arg1_type, arg2_type, arg3_type,
+ arg4_type, arg5_type, arg6_type, arg7_type, mt_policy>::connections_list::iterator iterator;
+ signal7()
+ {
+ ;
+ }
+
+ signal7(const signal7<arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, arg6_type, arg7_type, mt_policy>& s)
+ : _signal_base7<arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, arg6_type, arg7_type, mt_policy>(s)
+ {
+ ;
+ }
+
+ virtual ~signal7()
+ {
+ ;
+ }
+
+ template<class desttype>
+ void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,
+ arg2_type, arg3_type, arg4_type, arg5_type, arg6_type,
+ arg7_type))
+ {
+ lock_block<mt_policy> lock(this);
+ _connection7<desttype, arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, arg6_type, arg7_type, mt_policy>* conn =
+ new _connection7<desttype, arg1_type, arg2_type, arg3_type,
+ arg4_type, arg5_type, arg6_type, arg7_type, mt_policy>(pclass, pmemfun);
+ this->m_connected_slots.push_back(conn);
+ pclass->signal_connect(this);
+ }
+
+ template<class desttype>
+ void disconnect_slot(desttype* pclass, void (desttype::*pmemfun)(arg1_type,
+ arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, arg7_type))
+ {
+ lock_block<mt_policy> lock(this);
+ iterator itNext, it = this->m_connected_slots.begin();
+ iterator itEnd = this->m_connected_slots.end();
+
+
+ while(it != itEnd)
+ {
+ itNext = it;
+ ++itNext;
+ _connection7<desttype, arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, arg7_type, mt_policy>* temp = dynamic_cast<_connection7<desttype, arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, arg7_type, mt_policy> *>((*it));
+ if(temp->m_pobject == pclass && temp->m_pmemfun == pmemfun)
+ {
+ delete (*it);
+ this->m_connected_slots.erase(it);
+ pclass->signal_disconnect(this);
+ break;
+ }
+
+ it = itNext;
+ }
+ }
+
+ void connect(signal7<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, arg7_type, mt_policy>* chainsig)
+ {
+ lock_block<mt_policy> lock(this);
+ this->connect_signal(chainsig);
+ }
+
+ void disconnect_signal(signal7<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, arg7_type, mt_policy>* chainsig)
+ {
+ lock_block<mt_policy> lock(this);
+ this->disconnect_connected(chainsig);
+ }
+
+ void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
+ arg5_type a5, arg6_type a6, arg7_type a7)
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator itNext, it = this->m_connected_slots.begin();
+ const_iterator itEnd = this->m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ itNext = it;
+ ++itNext;
+
+ (*it)->emit(a1, a2, a3, a4, a5, a6, a7);
+
+ it = itNext;
+ }
+
+ sig_iterator siNext, si = this->connected_signals.begin();
+ sig_iterator siEnd = this->connected_signals.end();
+
+ while(si != siEnd)
+ {
+ siNext = si;
+ ++siNext;
+
+ static_cast<signal7<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, arg7_type, mt_policy>*>(*si)->emit(a1,a2,a3,a4,a5,a6,a7);
+
+ si = siNext;
+ }
+ }
+
+ void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
+ arg5_type a5, arg6_type a6, arg7_type a7)
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator itNext, it = this->m_connected_slots.begin();
+ const_iterator itEnd = this->m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ itNext = it;
+ ++itNext;
+
+ (*it)->emit(a1, a2, a3, a4, a5, a6, a7);
+
+ it = itNext;
+ }
+
+ sig_iterator siNext, si = this->connected_signals.begin();
+ sig_iterator siEnd = this->connected_signals.end();
+
+ while(si != siEnd)
+ {
+ siNext = si;
+ ++siNext;
+
+ static_cast<signal7<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, arg7_type, mt_policy>*>(*si)->emit(a1,a2,a3,a4,a5,a6,a7);
+
+ si = siNext;
+ }
+ }
+ };
+
+ template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
+ class arg5_type, class arg6_type, class arg7_type, class arg8_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
+ class SAGGUI_EXPORT signal8 : public _signal_base8<arg1_type, arg2_type, arg3_type,
+ arg4_type, arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>, public has_signals<mt_policy>
+ {
+ public:
+ typedef typename std::list<has_signals<mt_policy>*>::iterator sig_iterator;
+ typedef typename _signal_base8<arg1_type, arg2_type, arg3_type,
+ arg4_type, arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>::connections_list::const_iterator const_iterator;
+ typedef typename _signal_base8<arg1_type, arg2_type, arg3_type,
+ arg4_type, arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>::connections_list::iterator iterator;
+ signal8()
+ {
+ ;
+ }
+
+ signal8(const signal8<arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>& s)
+ : _signal_base8<arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>(s)
+ {
+ ;
+ }
+
+ virtual ~signal8()
+ {
+ ;
+ }
+
+ template<class desttype>
+ void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,
+ arg2_type, arg3_type, arg4_type, arg5_type, arg6_type,
+ arg7_type, arg8_type))
+ {
+ lock_block<mt_policy> lock(this);
+ _connection8<desttype, arg1_type, arg2_type, arg3_type, arg4_type,
+ arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>* conn =
+ new _connection8<desttype, arg1_type, arg2_type, arg3_type,
+ arg4_type, arg5_type, arg6_type, arg7_type,
+ arg8_type, mt_policy>(pclass, pmemfun);
+ this->m_connected_slots.push_back(conn);
+ pclass->signal_connect(this);
+ }
+
+ template<class desttype>
+ void disconnect_slot(desttype* pclass, void (desttype::*pmemfun)(arg1_type,
+ arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, arg7_type, arg8_type))
+ {
+ lock_block<mt_policy> lock(this);
+ iterator itNext, it = this->m_connected_slots.begin();
+ iterator itEnd = this->m_connected_slots.end();
+
+
+ while(it != itEnd)
+ {
+ itNext = it;
+ ++itNext;
+ _connection8<desttype, arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>* temp = dynamic_cast<_connection8<desttype, arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, arg7_type, arg8_type, mt_policy> *>((*it));
+ if(temp->m_pobject == pclass && temp->m_pmemfun == pmemfun)
+ {
+ delete (*it);
+ this->m_connected_slots.erase(it);
+ pclass->signal_disconnect(this);
+ break;
+ }
+
+ it = itNext;
+ }
+ }
+
+ void connect(signal8<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>* chainsig)
+ {
+ lock_block<mt_policy> lock(this);
+ this->connect_signal(chainsig);
+ }
+
+ void disconnect_signal(signal8<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>* chainsig)
+ {
+ lock_block<mt_policy> lock(this);
+ this->disconnect_connected(chainsig);
+ }
+
+ void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
+ arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8)
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator itNext, it = this->m_connected_slots.begin();
+ const_iterator itEnd = this->m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ itNext = it;
+ ++itNext;
+
+ (*it)->emit(a1, a2, a3, a4, a5, a6, a7, a8);
+
+ it = itNext;
+ }
+
+ sig_iterator siNext, si = this->connected_signals.begin();
+ sig_iterator siEnd = this->connected_signals.end();
+
+ while(si != siEnd)
+ {
+ siNext = si;
+ ++siNext;
+
+ static_cast<signal8<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>*>(*si)->emit(a1,a2,a3,a4,a5,a6,a7,a8);
+
+ si = siNext;
+ }
+ }
+
+ void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4,
+ arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8)
+ {
+ lock_block<mt_policy> lock(this);
+ const_iterator itNext, it = this->m_connected_slots.begin();
+ const_iterator itEnd = this->m_connected_slots.end();
+
+ while(it != itEnd)
+ {
+ itNext = it;
+ ++itNext;
+
+ (*it)->emit(a1, a2, a3, a4, a5, a6, a7, a8);
+
+ it = itNext;
+ }
+
+ sig_iterator siNext, si = this->connected_signals.begin();
+ sig_iterator siEnd = this->connected_signals.end();
+
+ while(si != siEnd)
+ {
+ siNext = si;
+ ++siNext;
+
+ static_cast<signal8<arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, arg7_type, arg8_type, mt_policy>*>(*si)->emit(a1,a2,a3,a4,a5,a6,a7,a8);
+
+ si = siNext;
+ }
+ }
+ };
+
+} // namespace sigslot
+
+#endif // SIGSLOT_H__
diff --git a/util/gui/tabbed-box.cpp b/util/gui/tabbed-box.cpp
new file mode 100644
index 00000000..810b76ec
--- /dev/null
+++ b/util/gui/tabbed-box.cpp
@@ -0,0 +1,301 @@
+#include "../bitmap.h"
+#include "../trans-bitmap.h"
+#include "tabbed-box.h"
+
+#include "menu/menu.h"
+
+#include "util/font.h"
+
+#include "context-box.h"
+
+using namespace Gui;
+
+#if 0
+/* FIXME add rounded tabs */
+static void roundTab( const Bitmap & work, int radius, int x1, int y1, int x2, int y2, int color, bool bottom = true ){
+ const int width = x2 - x1;
+ const int height = y2 - y1;
+ radius = Mid(0, radius, Min((x1+width - x1)/2, (y1+height - y1)/2));
+
+ work.circleFill(x1+radius, y1+radius, radius, color);
+ work.circleFill((x1+width)-radius, y1+radius, radius, color);
+ work.circleFill(x1+radius, (y1+height)-radius, radius, color);
+ work.circleFill((x1+width)-radius, (y1+height)-radius, radius, color);
+ work.rectangleFill( x1+radius, y1, x2-radius, y1+radius, color);
+ work.rectangleFill( x1, y1+radius, x2, y2-radius, color);
+ work.rectangleFill( x1+radius, y2-radius, x2-radius, y2, color);
+
+ work.line(x1+radius, y1, x1+width-radius, y1, color);
+ work.line(x1+radius, y1+height, x1+width-radius,y1+height, color);
+ work.line(x1, y1+radius,x1, y1+height-radius, color);
+ work.line(x1+width, y1+radius,x1+width, y1+height-radius, color);
+
+ arc(work, x1+radius, y1+radius, S_PI-1.115, radius, color);
+ arc(work, x1+radius + (width - radius *2), y1+radius, -S_PI/2 +0.116, radius, color);
+ arc(work, x1+width-radius, y1+height-radius, -0.110, radius ,color);
+ arc(work, x1+radius, y1+height-radius, S_PI/2-0.119, radius, color);
+}
+#endif
+
+Tab::Tab():
+context(new ContextBox()),
+active(false){
+ // Set alpha to 0 as we are not interested in the box
+ context->setRenderOnlyText(true);
+}
+
+Tab::~Tab(){
+ delete context;
+}
+
+TabbedBox::TabbedBox():
+current(0),
+fontWidth(24),
+fontHeight(24),
+inTab(false),
+tabWidthMax(0),
+tabFontColor(Bitmap::makeColor(255,255,255)),
+currentTabFontColor(Bitmap::makeColor(0,0,255)){
+ activeTabFontColor = new Effects::Gradient(50, tabFontColor, currentTabFontColor);
+}
+
+TabbedBox::TabbedBox(const TabbedBox & b):
+activeTabFontColor(NULL){
+ this->location = b.location;
+ this->workArea = b.workArea;
+}
+
+TabbedBox::~TabbedBox(){
+ for (std::vector<Gui::Tab *>::iterator i = tabs.begin(); i != tabs.end(); ++i){
+ Gui::Tab * tab = *i;
+ if (tab){
+ delete tab;
+ }
+ }
+
+ if (activeTabFontColor){
+ delete activeTabFontColor;
+ }
+}
+
+TabbedBox &TabbedBox::operator=( const TabbedBox ©){
+ location = copy.location;
+ workArea = copy.workArea;
+
+ return *this;
+}
+
+// Logic
+void TabbedBox::act(const Font & font){
+ if (!tabs.empty()){
+ // const Font & vFont = Font::getFont(font, fontWidth, fontHeight);
+ //tabWidthMax = location.getWidth()/tabs.size();
+ const int width = font.textLength(tabs[current]->name.c_str()) + 5;
+ tabWidthMax = (location.getWidth() - width) / (tabs.size() - 1);
+ } else {
+ return;
+ }
+ if (!tabs[current]->active){
+ tabs[current]->active = true;
+ }
+ tabs[current]->context->act(font);
+ if (inTab){
+ if (activeTabFontColor){
+ activeTabFontColor->update();
+ }
+ }
+}
+
+void TabbedBox::render(const Bitmap & work){
+ /* nothing */
+}
+
+// Render
+void TabbedBox::render(const Bitmap & work, const Font & font){
+ const int tabHeight = fontHeight + 5;
+ // checkWorkArea();
+ Bitmap area(work, location.getX(), location.getY(), location.getWidth(), location.getHeight());
+ // Check if we are using a rounded box
+ if (location.getRadius() > 0){
+ //roundRectFill( *workArea, (int)location.getRadius(), 0, 0, location.getWidth()-1, location.getHeight()-1, colors.body );
+ //roundRect( *workArea, (int)location.getRadius(), 0, 0, location.getWidth()-1, location.getHeight()-1, colors.border );
+ } else {
+ area.translucent().rectangleFill(0, tabHeight+1, location.getWidth()-1, location.getHeight()-1, colors.body );
+ //area.translucent().rectangle(0, tabHeight, location.getWidth()-1, location.getHeight()-1, colors.border );
+ area.translucent().vLine(tabHeight,0,location.getHeight()-1,colors.border);
+ area.translucent().hLine(0,location.getHeight()-1,location.getWidth()-1,colors.border);
+ area.translucent().vLine(tabHeight,location.getWidth()-1,location.getHeight()-1,colors.border);
+ }
+
+ tabs[current]->context->render(area, font);
+
+ renderTabs(area, font);
+
+ /* FIXME: only render the background in translucent mode, the text should
+ * not be translucent
+ */
+ // workArea->draw(location.getX(), location.getY(), work);
+}
+
+// Add tab
+void TabbedBox::addTab(const std::string & name, const std::vector<ContextItem *> & list){
+ for (std::vector<Tab *>::iterator i = tabs.begin(); i != tabs.end(); ++i){
+ Tab * tab = *i;
+ if (tab->name == name){
+ return;
+ }
+ }
+ Tab * tab = new Tab();
+ tab->name = name;
+ tab->context->setList(list);
+ // tab->context->setFont(font, fontWidth, fontHeight);
+ const int modifier = fontHeight * .35;
+ tab->context->location.setPosition(Gui::AbsolutePoint(0, fontHeight + modifier));
+ tab->context->location.setPosition2(Gui::AbsolutePoint(location.getWidth(), location.getHeight()- modifier));
+ tab->context->open();
+ tabs.push_back(tab);
+}
+
+void TabbedBox::moveTab(int direction){
+ tabs[current]->context->close();
+ tabs[current]->active = false;
+ current = (unsigned int) ((int)current + direction + (int) tabs.size()) % tabs.size();
+ /*
+ if (current == 0){
+ current = tabs.size()-1;
+ } else {
+ current--;
+ }
+ */
+ tabs[current]->context->open();
+ tabs[current]->active = true;
+}
+
+void TabbedBox::up(const Font & font){
+ if (tabs.size() == 0){
+ return;
+ }
+ if (!inTab){
+ moveTab(-1);
+ } else {
+ tabs[current]->context->previous(font);
+ }
+}
+
+void TabbedBox::down(const Font & font){
+ if (tabs.size() == 0){
+ return;
+ }
+ if (!inTab){
+ moveTab(1);
+ } else {
+ tabs[current]->context->next(font);
+ }
+}
+
+void TabbedBox::left(const Font & font){
+ if (tabs.size() == 0){
+ return;
+ }
+ if (!inTab){
+ moveTab(-1);
+ } else {
+ tabs[current]->context->adjustLeft();
+ }
+}
+
+void TabbedBox::right(const Font & font){
+ if (tabs.size() == 0){
+ return;
+ }
+ if (!inTab){
+ moveTab(1);
+ } else {
+ tabs[current]->context->adjustRight();
+ }
+}
+
+void TabbedBox::toggleTabSelect(){
+ inTab = !inTab;
+}
+
+unsigned int TabbedBox::getCurrentIndex() const {
+ if (tabs.size() == 0){
+ return 0;
+ }
+ return this->tabs[current]->context->getCurrentIndex();
+}
+
+void TabbedBox::setTabFontColor(int color){
+ tabFontColor = color;
+ if (activeTabFontColor){
+ delete activeTabFontColor;
+ }
+ activeTabFontColor = new Effects::Gradient(50, tabFontColor, currentTabFontColor);
+}
+
+void TabbedBox::setSelectedTabFontColor(int color){
+ currentTabFontColor = color;
+ if (activeTabFontColor){
+ delete activeTabFontColor;
+ }
+ activeTabFontColor = new Effects::Gradient(50, tabFontColor, currentTabFontColor);
+}
+
+void TabbedBox::renderTabs(const Bitmap & bmp, const Font & vFont){
+ const int tabHeight = fontHeight + 5;
+ // const Font & vFont = Font::getFont(font, fontWidth, fontHeight);
+
+ int x = 0;
+ Bitmap::transBlender(0, 0, 0, colors.bodyAlpha);
+
+ for (std::vector<Gui::Tab *>::iterator i = tabs.begin(); i != tabs.end(); ++i){
+ Gui::Tab * tab = *i;
+ const int textWidth = vFont.textLength(tab->name.c_str()) + 5;
+ // for last tab
+ int modifier = 0;
+ // Check last tab so we can ensure proper sizing
+ if ( i == (tabs.begin() + tabs.size() -1)){
+ if ( ( (tabWidthMax * (tabs.size() - 1) ) + textWidth ) != (unsigned int)location.getWidth() ){
+ modifier = location.getWidth() - x - (tab->active ? textWidth : tabWidthMax);
+ }
+ }
+
+ if (tab->context->location.getRadius() > 0){
+ } else {
+ if (tab->active){
+ if (!inTab){
+ //bmp.translucent().rectangle(x, 0, x+textWidth + modifier - 1, tabHeight, colors.border);
+ bmp.translucent().vLine(0,x,tabHeight,colors.border);
+ bmp.translucent().hLine(x,0,x+textWidth+modifier-1,colors.border);
+ bmp.translucent().vLine(0,x+textWidth+modifier-1,tabHeight,colors.border);
+ bmp.translucent().rectangleFill( x+1, 1, x+textWidth + modifier - 2, tabHeight, colors.body);
+
+ bmp.setClipRect(x, 0, x+textWidth + modifier, tabHeight-1);
+ vFont.printf(x + (((textWidth + modifier)/2)-(((textWidth + modifier) - 5)/2)), 0, currentTabFontColor, bmp, tab->name, 0 );
+ } else {
+ //bmp.translucent().rectangle(x, 0, x+textWidth + modifier -1, tabHeight, colors.border);
+ bmp.translucent().vLine(0,x,tabHeight,colors.border);
+ bmp.translucent().hLine(x,0,x+textWidth+modifier-1,colors.border);
+ bmp.translucent().vLine(0,x+textWidth+modifier-1,tabHeight,colors.border);
+ bmp.translucent().rectangleFill( x+1, 1, x+textWidth-2 + modifier, tabHeight, colors.body );
+
+ bmp.setClipRect(x, 0, x+textWidth + modifier, tabHeight-1);
+ vFont.printf(x + (((textWidth + modifier)/2)-(((textWidth + modifier) - 5)/2)), 0, activeTabFontColor->current(), bmp, tab->name, 0 );
+ }
+
+ x+=textWidth + modifier;
+ } else {
+ const int heightMod = tabHeight * .15;
+ bmp.translucent().rectangle(x, 1 + heightMod, x+tabWidthMax + modifier -1, tabHeight, tabColors.border);
+ bmp.translucent().hLine(x,tabHeight,x+tabWidthMax+modifier-1,colors.border);
+ bmp.translucent().rectangleFill( x+1, 2 + heightMod, x+tabWidthMax + modifier -2, tabHeight-2, tabColors.body);
+
+ bmp.setClipRect(x+2, 6 + heightMod, x+tabWidthMax + modifier -3, tabHeight-1);
+ vFont.printf(x + (((tabWidthMax + modifier)/2)-((textWidth + modifier)/2)), 0, tabFontColor, bmp, tab->name, 0 );
+ x += tabWidthMax + modifier;
+ }
+ bmp.setClipRect(0, 0, bmp.getWidth(), bmp.getHeight());
+ }
+ }
+}
diff --git a/util/gui/tabbed-box.h b/util/gui/tabbed-box.h
new file mode 100644
index 00000000..cb7ab213
--- /dev/null
+++ b/util/gui/tabbed-box.h
@@ -0,0 +1,134 @@
+#ifndef _paintown_gui_tabbed_box_h
+#define _paintown_gui_tabbed_box_h
+
+#include <string>
+#include <vector>
+
+#include "widget.h"
+#include "../file-system.h"
+
+#include "../gradient.h"
+
+class Token;
+
+namespace Gui{
+
+class ContextBox;
+class ContextItem;
+
+class Tab{
+ public:
+ Tab();
+ ~Tab();
+ std::string name;
+ Gui::ContextBox * context;
+ bool active;
+};
+
+class TabbedBox : public Widget{
+ public:
+ TabbedBox();
+ TabbedBox( const TabbedBox & );
+ virtual ~TabbedBox();
+
+ //! copy
+ TabbedBox &operator=( const TabbedBox &);
+
+ //! Logic
+ virtual void act(const Font &);
+
+ //! Render
+ using Widget::render;
+ virtual void render(const Bitmap &);
+ virtual void render(const Bitmap &, const Font &);
+
+ //! Add tab
+ virtual void addTab(const std::string &, const std::vector<ContextItem *> & list);
+
+ //! Up
+ virtual void up(const Font &);
+
+ //! Down
+ virtual void down(const Font &);
+
+ //! Left
+ virtual void left(const Font &);
+
+ //! Right
+ virtual void right(const Font &);
+
+ //! Virtual
+ virtual void toggleTabSelect();
+
+ //! Set current font
+ virtual inline void setFont(const Filesystem::RelativePath & font, int width, int height){
+ this->font = font;
+ this->fontWidth = width;
+ this->fontHeight = height;
+ }
+
+ //! Get current tab
+ virtual inline unsigned int getCurrentTab() const {
+ return this->current;
+ }
+
+ //! Get current index on selected tab
+ virtual unsigned int getCurrentIndex() const;
+
+ //! Set tab font colors
+ virtual void setTabFontColor(int color);
+
+ //! Set selected tab font color
+ virtual void setSelectedTabFontColor(int color);
+
+ //! Empty
+ virtual inline bool empty() const {
+ return this->tabs.empty();
+ }
+
+ virtual inline bool isInTab() const {
+ return this->inTab;
+ }
+
+ /*! Tab Colors */
+ ColorInfo tabColors;
+
+ /*! Selected Tab Colors */
+ ColorInfo selectedTabColors;
+
+ /*! Selected Tab Colors */
+ ColorInfo runningTabColors;
+
+ protected:
+ void moveTab(int direction);
+
+ std::vector<Gui::Tab *> tabs;
+
+ unsigned int current;
+
+ Filesystem::RelativePath font;
+ int fontWidth;
+ int fontHeight;
+
+ /*! Is in tab */
+ bool inTab;
+
+ /*! Max Width of tabs */
+ int tabWidthMax;
+
+ /*! Render tab */
+ void renderTabs(const Bitmap &, const Font &);
+
+ /*! Font Color */
+ int tabFontColor;
+
+ /*! Current Tab Font Color */
+ int currentTabFontColor;
+
+ /*! Gradient for selected Font */
+ Effects::Gradient * activeTabFontColor;
+};
+
+}
+
+#endif
diff --git a/util/gui/timer.cpp b/util/gui/timer.cpp
new file mode 100644
index 00000000..b11aae85
--- /dev/null
+++ b/util/gui/timer.cpp
@@ -0,0 +1,131 @@
+/*
+SAGGUI (Simplified All Gaming Graphical User Interface)
+Copyright (c) 2005-2007, Miguel A. Gavidia
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+ * Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the following
+ disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+ * Neither the name of the "SAGGUI" nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "timer.h"
+#include "util/funcs.h"
+
+ guiTimer::guiTimer()
+ {
+ // Setup initial
+ reset();
+ }
+
+ guiTimer::~guiTimer()
+ {
+ // nothing to be done
+ }
+
+ unsigned int guiTimer::usecs()
+ {
+#if defined (_WIN32)
+ static bool onetime = 0;
+ static unsigned long long freq = 0;
+
+ if(!onetime) {
+ onetime = true;
+ QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
+ }
+
+ QueryPerformanceCounter((LARGE_INTEGER*)¤tTime);
+
+ currentTime *= 1000000;
+ currentTime /= freq;
+
+ return currentTime - startTime * 1000;
+#else
+ gettimeofday(¤tTime, 0);
+
+ return (unsigned long)((currentTime.tv_sec - startTime.tv_sec) / 1000)
+ + (unsigned long)((currentTime.tv_usec - startTime.tv_usec));
+#endif
+ }
+
+ unsigned int guiTimer::msecs()
+ {
+#if defined (_WIN32)
+ currentTime = GetTickCount();
+
+ return currentTime - startTime;
+#else
+ gettimeofday(¤tTime, 0);
+
+ return (unsigned long)((currentTime.tv_sec - startTime.tv_sec) * 1000)
+ + (unsigned long)((currentTime.tv_usec - startTime.tv_usec) / 1000);
+#endif
+ }
+
+ unsigned int guiTimer::secs()
+ {
+#if defined (_WIN32)
+ currentTime = GetTickCount();
+
+ return (currentTime - startTime) / 1000;
+#else
+ gettimeofday(¤tTime, 0);
+
+ return (unsigned long)(currentTime.tv_sec - startTime.tv_sec);
+#endif
+ }
+
+ // Reset timer
+ void guiTimer::reset()
+ {
+#if defined (_WIN32)
+ startTime = GetTickCount();
+#else
+ gettimeofday(&startTime, 0);
+#endif
+ }
+
+ // Provides a method to sleep
+ void guiTimer::sleep(int msecs)
+ {
+ Util::rest(msecs);
+ /*
+#if defined (_WIN32)
+ Sleep(msecs);
+#else
+ struct timespec timeOut;
+ timeOut.tv_sec = 0;
+ timeOut.tv_nsec = (msecs * 1000000);
+ nanosleep(&timeOut, NULL);
+#endif
+*/
+
+ }
+
diff --git a/util/gui/timer.h b/util/gui/timer.h
new file mode 100644
index 00000000..692e3949
--- /dev/null
+++ b/util/gui/timer.h
@@ -0,0 +1,90 @@
+/*
+SAGGUI (Simplified All Gaming Graphical User Interface)
+Copyright (c) 2005-2007, Miguel A. Gavidia
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+ * Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the following
+ disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+ * Neither the name of the "SAGGUI" nor the names of its
+ contributors may be used to endorse or promote products
+ derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef TIMER_H
+#define TIMER_H
+
+#if defined (_WIN32)
+#include <windows.h>
+#else
+#include <time.h>
+#include <sys/time.h>
+#endif
+
+class guiTimer
+{
+ private:
+#if defined (_WIN32)
+ //! Start time for timer
+ unsigned long long startTime;
+
+ //! Current time for comparison against startTime
+ unsigned long long currentTime;
+#else
+
+ //! Start time for timer
+ timeval startTime;
+
+ //! Current time for comparison against startTime
+ timeval currentTime;
+#endif
+ public:
+ //! Constructor
+ guiTimer();
+
+ //! Destructor
+ ~guiTimer();
+
+ //! Provides the currentTime in microseconds
+ unsigned int usecs();
+
+ //! Provides the currentTime in milliseconds
+ unsigned int msecs();
+
+ //! Provides the currentTime in seconds
+ unsigned int secs();
+
+ //! Reset timer
+ void reset();
+
+ //! Provides a method to sleep in milliseconds
+ static void sleep(int msecs);
+};
+
+
+#endif
diff --git a/util/gui/widget.cpp b/util/gui/widget.cpp
new file mode 100644
index 00000000..2d90853b
--- /dev/null
+++ b/util/gui/widget.cpp
@@ -0,0 +1,249 @@
+#include "util/bitmap.h"
+#include "widget.h"
+#include <math.h>
+#include "globals.h"
+#include "util/token.h"
+#include "coordinate.h"
+#include "util/load_exception.h"
+#include <sstream>
+
+using namespace Gui;
+
+static const double S_PI = 3.14159265358979323846;
+static const double DEG_TO_RAD = 180.0/S_PI;
+static const double RAD_TO_DEG = S_PI/180.0;
+
+static void round_double (double dbl_to_round , int &rounded_num) {
+ rounded_num = static_cast<int>(dbl_to_round);
+ if ((dbl_to_round - static_cast<double>(rounded_num)) >= 0.5) {rounded_num++;}
+}
+
+//! min (borrowed from allegro)
+static inline int Min(int x, int y){ return (((x) < (y)) ? (x) : (y)); }
+
+//! max (borrowed from allegro)
+static inline int Max(int x, int y){ return (((x) > (y)) ? (x) : (y)); }
+
+//! mid (borrowed from allegro)
+static inline int Mid(int x,int y,int z){ return (Max((x), Min((y), (z)))); }
+
+Widget::Widget() : workArea(0)
+{
+ // Nothing yet
+}
+
+Widget::Widget( const Widget & w ){
+ this->location = w.location;
+ this->workArea = w.workArea;
+}
+
+Widget::~Widget(){
+ if ( workArea ){
+ delete workArea;
+ }
+}
+
+// copy
+Widget &Widget::operator=( const Widget ©){
+ location = copy.location;
+ workArea = copy.workArea;
+
+ return *this;
+}
+
+void Widget::setCoordinates(const Token * token){
+ if ( *token == "position" ){
+ int x, y, width, height;
+ token->view() >> x >> y >> width >> height;
+ AbsolutePoint pos(x, y);
+ AbsolutePoint dimensions(x + width, y + height);
+ location.setPosition(pos);
+ location.setPosition2(dimensions);
+ } else if ( *token == "relative-position" ){
+ double x1, y1, x2, y2;
+ token->view() >> x1 >> y1 >> x2 >> y2;
+ RelativePoint pos(x1,y1);
+ RelativePoint dimensions(x2,y2);
+ location = Coordinate(pos, dimensions);
+ } else if ( *token == "coordinate" ){
+ TokenView view = token->view();
+ while (view.hasMore()){
+ const Token * coordToken;
+ view >> coordToken;
+ if (*coordToken == "absolute"){
+ int x, y, width, height;
+ coordToken->view() >> x >> y >> width >> height;
+ AbsolutePoint pos(x, y);
+ AbsolutePoint dimensions(x + width, y + height);
+ location = Coordinate(pos, dimensions);
+ } else if (*coordToken == "relative"){
+ double x1, y1, x2, y2;
+ coordToken->view() >> x1 >> y1 >> x2 >> y2;
+ RelativePoint pos(x1,y1);
+ RelativePoint dimensions(x2,y2);
+ location = Coordinate(pos, dimensions);
+ } else if (*coordToken == "radius"){
+ double radius;
+ coordToken->view() >> radius;
+ location.setRadius(radius);
+ } else if (*coordToken == "z"){
+ double z;
+ coordToken->view() >> z;
+ location.setZ(z);
+ }
+ }
+ }
+
+ if (location.getWidth() < 0 || location.getHeight() < 0){
+ std::ostringstream out;
+ out << "Invalid location dimension (cannot have a negative size). Width " << location.getWidth() << " Height " << location.getHeight() << ". From token: ";
+ token->toString(out, "");
+ throw LoadException(__FILE__, __LINE__, out.str());
+ }
+}
+
+void Widget::setColors(const Token * token){
+ if ( *token == "position-body" ) {
+ // This handles the body color of the widget
+ int r,g,b;
+ token->view() >> r >> g >> b >> colors.bodyAlpha;
+ colors.body = Bitmap::makeColor(r,g,b);
+ } else if ( *token == "position-border" ) {
+ // This handles the border color of the widget
+ int r,g,b;
+ token->view() >> r >> g >> b >> colors.borderAlpha;
+ colors.border = Bitmap::makeColor(r,g,b);
+ }
+}
+
+void Widget::render(const Bitmap & bitmap, const Font & font){
+ render(bitmap);
+}
+
+void Widget::arc( const Bitmap & work, int x, int y, double startAngle, int radius, int color ){
+ int q = 0;// for counters
+ double d_q = 0.0;// for percentage of loop completed
+ double d_q_plus_one = 0.0;
+
+ const double d_angular_length_deg = 0.030;
+ const double d_start_angle_rad = startAngle*DEG_TO_RAD;
+ const double d_angular_length_rad = d_angular_length_deg*DEG_TO_RAD;
+ const double d_arc_distance_between_points = 0.25*pow(2.0 , static_cast<double>(10) / 10.0);
+ double d_angular_length_rad_per_segment = 0.0;
+
+ double arc_length = radius*d_angular_length_rad;
+ if (arc_length < 0.0) {arc_length *= -1.0;}
+ const double d_num_segments = arc_length / d_arc_distance_between_points;
+
+ int num_segments = 0;
+ round_double(d_num_segments , num_segments);
+
+ if (num_segments == 0) {num_segments += 1;} // need at least one segment (two points)
+ const int num_points = num_segments + 1;
+ const double d_num_points_minus_one = static_cast<double>(num_points - 1);
+
+ int arc_point_x;//[num_points];
+ int arc_point_y;//[num_points];
+ int arc_point2_x;//[num_points];
+ int arc_point2_y;//[num_points];
+ double d_arc_point_x = 0.0;
+ double d_arc_point_y = 0.0;
+ double d_arc_point2_x = 0.0;
+ double d_arc_point2_y = 0.0;
+
+ double current_angle_rad = 0.0;
+ double current_angle2_rad = 0.0;
+
+ if (d_arc_distance_between_points <= 1.0) {
+ for (q = 0 ; q < num_points ; q++) {
+ d_q = static_cast<double>(q);
+ current_angle_rad = d_start_angle_rad + (d_q / d_num_points_minus_one)*d_angular_length_rad;
+ d_arc_point_x = x + radius*cos(current_angle_rad);
+ d_arc_point_y = y + radius*sin(current_angle_rad);
+
+ round_double(d_arc_point_x , arc_point_x);
+ round_double(d_arc_point_y , arc_point_y);
+
+ work.putPixel(arc_point_x,arc_point_y,color);
+ }
+ }
+ if (d_arc_distance_between_points > 1.0) {
+
+ d_angular_length_rad_per_segment = d_angular_length_rad / d_num_points_minus_one;
+ for (q = 0 ; q < num_segments ; q++) {
+ d_q = static_cast<double>(q);
+ d_q_plus_one = static_cast<double>(q + 1);
+
+ current_angle_rad = d_start_angle_rad + d_q*d_angular_length_rad_per_segment;
+ current_angle2_rad = d_start_angle_rad + d_q_plus_one*d_angular_length_rad_per_segment;
+
+ d_arc_point_x = x + radius*cos(current_angle_rad);
+ d_arc_point_y = y + radius*sin(current_angle_rad);
+
+ round_double(d_arc_point_x , arc_point_x);
+ round_double(d_arc_point_y , arc_point_y);
+
+ d_arc_point2_x = x + radius*cos(current_angle2_rad);
+ d_arc_point2_y = y + radius*sin(current_angle2_rad);
+
+ round_double(d_arc_point2_x , arc_point2_x);
+ round_double(d_arc_point2_y , arc_point2_y);
+
+ work.line(arc_point_x,arc_point_y, arc_point2_x, arc_point2_y,color);
+ }
+ }
+}
+
+void Widget::roundRect( const Bitmap & work, int radius, int x1, int y1, int x2, int y2, int color ){
+ const int width = x2 - x1;
+ const int height = y2 - y1;
+ radius = Mid(0, radius, Min((x1+width - x1)/2, (y1+height - y1)/2));
+ work.line(x1+radius, y1, x1+width-radius, y1, color);
+ work.line(x1+radius, y1+height, x1+width-radius,y1+height, color);
+ work.line(x1, y1+radius,x1, y1+height-radius, color);
+ work.line(x1+width, y1+radius,x1+width, y1+height-radius, color);
+
+ arc(work, x1+radius, y1+radius, S_PI-1.115, radius, color);
+ arc(work, x1+radius + (width - radius *2), y1+radius, -S_PI/2 +0.116, radius, color);
+ arc(work, x1+width-radius, y1+height-radius, -0.110, radius ,color);
+ arc(work, x1+radius, y1+height-radius, S_PI/2-0.119, radius, color);
+}
+
+void Widget::roundRectFill( const Bitmap & work, int radius, int x1, int y1, int x2, int y2, int color ){
+ const int width = x2 - x1;
+ const int height = y2 - y1;
+ radius = Mid(0, radius, Min((x1+width - x1)/2, (y1+height - y1)/2));
+ work.circleFill(x1+radius, y1+radius, radius, color);
+ work.circleFill((x1+width)-radius, y1+radius, radius, color);
+ work.circleFill(x1+radius, (y1+height)-radius, radius, color);
+ work.circleFill((x1+width)-radius, (y1+height)-radius, radius, color);
+ work.rectangleFill( x1+radius, y1, x2-radius, y1+radius, color);
+ work.rectangleFill( x1, y1+radius, x2, y2-radius, color);
+ work.rectangleFill( x1+radius, y2-radius, x2-radius, y2, color);
+}
+
+static void foobar(int a, int b){
+ a = a + b;
+}
+
+void Widget::checkWorkArea(){
+ /*
+ if (location.getWidth() < 0 || location.getHeight() < 0){
+ foobar(location.getWidth(), location.getHeight());
+ }
+ */
+
+ if ( ! workArea ){
+ workArea = new Bitmap(location.getWidth(), location.getHeight());
+ } else if (location.getWidth() < workArea->getWidth() || location.getHeight() < workArea->getHeight()){
+ delete workArea;
+ workArea = new Bitmap(location.getWidth(), location.getHeight());
+ } else if (location.getWidth() > workArea->getWidth() || location.getHeight() > workArea->getHeight()){
+ delete workArea;
+ workArea = new Bitmap(location.getWidth(), location.getHeight());
+ }
+
+ if (workArea){
+ workArea->fill(Bitmap::makeColor(255,0,255));
+ }
+}
diff --git a/util/gui/widget.h b/util/gui/widget.h
new file mode 100644
index 00000000..102ecfcf
--- /dev/null
+++ b/util/gui/widget.h
@@ -0,0 +1,65 @@
+#ifndef _paintown_gui_widget_h
+#define _paintown_gui_widget_h
+
+#include "rectarea.h"
+#include "coordinate.h"
+
+class Bitmap;
+class Token;
+class Font;
+
+namespace Gui{
+
+struct ColorInfo{
+ ColorInfo():
+ body(0),
+ bodyAlpha(0),
+ border(0),
+ borderAlpha(0){
+ }
+
+ int body;
+ int bodyAlpha;
+ int border;
+ int borderAlpha;
+};
+
+class Widget{
+ public:
+ Widget();
+ Widget( const Widget & w );
+ virtual ~Widget();
+
+ // copy
+ Widget &operator=( const Widget &);
+
+ void setCoordinates(const Token * token);
+ void setColors(const Token * token);
+
+ //! New position data
+ Coordinate location;
+
+ //! Colors
+ ColorInfo colors;
+
+ // Logic
+ virtual void act(const Font &)=0;
+
+ // Render
+ virtual void render(const Bitmap &) = 0;
+ /* default behavior is just to call render() */
+ virtual void render(const Bitmap &, const Font &);
+
+ protected:
+ void arc( const Bitmap &, int x, int y, double startAngle, int radius, int color );
+ void roundRect( const Bitmap &, int radius, int x1, int y1, int x2, int y2, int color );
+ void roundRectFill( const Bitmap &, int radius, int x1, int y1, int x2, int y2, int color );
+
+ void checkWorkArea();
+
+ Bitmap *workArea;
+};
+
+}
+
+#endif
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Jun 11, 11:45 AM (3 w, 4 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
68856
Default Alt Text
(232 KB)
Attached To
Mode
R75 R-Tech1
Attached
Detach File
Event Timeline