Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
232 KB
Referenced Files
None
Subscribers
None
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 &copy){
+ 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 &copy){
+ 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*)&currentTime);
+
+ currentTime *= 1000000;
+ currentTime /= freq;
+
+ return currentTime - startTime * 1000;
+#else
+ gettimeofday(&currentTime, 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(&currentTime, 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(&currentTime, 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 &copy){
+ 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

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)

Event Timeline