major update

This was SVN commit r290.
This commit is contained in:
Gee 2004-05-29 04:06:50 +00:00
parent 1343010185
commit e326ebae46
31 changed files with 2891 additions and 901 deletions

View file

@ -6,59 +6,61 @@ gee@pyro.nu
//#include "stdafx."
#include "GUI.h"
#include "CButton.h"
// TODO Gee: font.h is temporary.
#include "res/font.h"
#include "res/res.h"
#include "ogl.h"
using namespace std;
// Offsets
DECLARE_SETTINGS_INFO(SButtonSettings)
//-------------------------------------------------------------------
// Constructor / Destructor
//-------------------------------------------------------------------
CButton::CButton()
{
// Settings defaults !
/* m_Settings.m_Disabled = false;
m_Settings.m_Font = "null";
m_Settings.m_Sprite = "null";
m_Settings.m_SpriteDisabled = "null";
m_Settings.m_SpriteOver = "null";
m_Settings.m_SpritePressed = "null";
m_Settings.m_TextAlign = EAlign_Center;
// m_Settings.m_TextColor = CColor();
// m_Settings.m_TextColorDisabled;
// m_Settings.m_TextColorOver;
// m_Settings.m_TextColorPressed;
m_Settings.m_TextValign = EValign_Center;
m_Settings.m_ToolTip = "null";
m_Settings.m_ToolTipStyle = "null";
*/
AddSetting(GUIST_CGUIString, "caption");
AddSetting(GUIST_CStr, "font");
AddSetting(GUIST_CStr, "sprite");
AddSetting(GUIST_CStr, "sprite-over");
AddSetting(GUIST_CStr, "sprite-pressed");
AddSetting(GUIST_CStr, "sprite-disabled");
AddSetting(GUIST_CColor, "textcolor");
AddSetting(GUIST_CColor, "textcolor-over");
AddSetting(GUIST_CColor, "textcolor-pressed");
AddSetting(GUIST_CColor, "textcolor-disabled");
// Static! Only done once
if (m_SettingsInfo.empty())
{
// Setup the base ones too
SetupBaseSettingsInfo(m_SettingsInfo);
GUI_ADD_OFFSET_EXT(SButtonSettings, m_Sprite, "string", "sprite")
GUI_ADD_OFFSET_EXT(SButtonSettings, m_SpriteOver, "string", "sprite-over")
GUI_ADD_OFFSET_EXT(SButtonSettings, m_SpritePressed, "string", "sprite-pressed")
GUI_ADD_OFFSET_EXT(SButtonSettings, m_SpriteDisabled, "string", "sprite-disabled")
}
// Add text
AddText(new SGUIText());
}
CButton::~CButton()
{
}
void CButton::SetupText()
{
if (!GetGUI())
return;
assert(m_GeneratedTexts.size()>=1);
CStr font;
CGUIString caption;
GUI<CGUIString>::GetSetting(this, "caption", caption);
*m_GeneratedTexts[0] = GetGUI()->GenerateText(caption, CStr("verdana12.fnt"), 0, 0);
// Set position of text
m_TextPos = m_CachedActualSize.CenterPoint() - m_GeneratedTexts[0]->m_Size/2;
}
void CButton::HandleMessage(const SGUIMessage &Message)
{
// Important
IGUIButtonBehavior::HandleMessage(Message);
IGUITextOwner::HandleMessage(Message);
switch (Message.type)
{
@ -98,31 +100,24 @@ void CButton::Draw()
glDisable(GL_TEXTURE_2D);
//////////
if (GetGUI())
{
bool useBase = false;
float bz = GetBufferedZ();
if (!GetBaseSettings().m_Enabled)
{
if (m_Settings.m_SpriteDisabled != CStr("null"))
GetGUI()->DrawSprite(m_Settings.m_SpriteDisabled, GetBufferedZ(), m_CachedActualSize);
else
useBase = true;
}
else
if (m_MouseHovering)
{
if (m_Pressed && m_Settings.m_SpritePressed != CStr("null"))
GetGUI()->DrawSprite(m_Settings.m_SpritePressed, GetBufferedZ(), m_CachedActualSize);
else
if (!m_Pressed && m_Settings.m_SpriteOver != CStr("null"))
GetGUI()->DrawSprite(m_Settings.m_SpriteOver, GetBufferedZ(), m_CachedActualSize);
else
useBase = true;
}
else useBase = true;
CStr sprite, sprite_over, sprite_pressed, sprite_disabled;
if (useBase)
GetGUI()->DrawSprite(m_Settings.m_Sprite, GetBufferedZ(), m_CachedActualSize);
}
GUI<CStr>::GetSetting(this, "sprite", sprite);
GUI<CStr>::GetSetting(this, "sprite-over", sprite_over);
GUI<CStr>::GetSetting(this, "sprite-pressed", sprite_pressed);
GUI<CStr>::GetSetting(this, "sprite-disabled", sprite_disabled);
DrawButton(m_CachedActualSize,
bz,
sprite,
sprite_over,
sprite_pressed,
sprite_disabled);
CColor color = ChooseColor();
IGUITextOwner::Draw(0, color, m_TextPos, bz+0.1f);
}

View file

@ -33,28 +33,6 @@ gee@pyro.nu
// Declarations
//--------------------------------------------------------
/**
* Button Settings
*/
struct SButtonSettings
{
CStr m_Font;
CStr m_Sprite;
CStr m_SpriteDisabled;
CStr m_SpriteOver;
CStr m_SpritePressed;
EAlign m_TextAlign;
CColor m_TextColor;
CColor m_TextColorDisabled;
CColor m_TextColorOver;
CColor m_TextColorPressed;
EValign m_TextValign;
CStr m_ToolTip;
CStr m_ToolTipStyle;
};
///////////////////////////////////////////////////////////////////////////////
/**
* @author Gustav Larsson
*
@ -63,9 +41,8 @@ struct SButtonSettings
* @see IGUIObject
* @see IGUISettingsObject
* @see IGUIButtonBehavior
* @see SButtonSettings
*/
class CButton : public IGUISettingsObject<SButtonSettings>, public IGUIButtonBehavior
class CButton : public IGUIButtonBehavior, public IGUITextOwner
{
GUI_OBJECT(CButton)
@ -73,13 +50,6 @@ public:
CButton();
virtual ~CButton();
/**
* Since we're doing multiple inheritance, this is to avoid error message
*
* @return Settings infos
*/
virtual map_Settings GetSettingsInfo() const { return IGUISettingsObject<SButtonSettings>::m_SettingsInfo; }
virtual void ResetStates() { IGUIButtonBehavior::ResetStates(); }
/**
@ -93,6 +63,18 @@ public:
* Draws the Button
*/
virtual void Draw();
protected:
/**
* Sets up text, should be called every time changes has been
* made that can change the visual.
*/
void SetupText();
/**
* Placement of text.
*/
CPos m_TextPos;
};
#endif

153
source/gui/CCheckBox.cpp Executable file
View file

@ -0,0 +1,153 @@
/*
CCheckBox
by Gustav Larsson
gee@pyro.nu
*/
//#include "stdafx."
#include "GUI.h"
#include "CCheckBox.h"
using namespace std;
//-------------------------------------------------------------------
// Constructor / Destructor
//-------------------------------------------------------------------
CCheckBox::CCheckBox()
{
/* bool m_Checked;
CStr m_Font;
CStr m_Sprite;
CStr m_SpriteDisabled;
CStr m_SpriteOver;
CStr m_SpritePressed;
CStr m_Sprite2;
CStr m_Sprite2Disabled;
CStr m_Sprite2Over;
CStr m_Sprite2Pressed;
int m_SquareSide;
EAlign m_TextAlign;
CColor m_TextColor;
CColor m_TextColorDisabled;
CColor m_TextColorOver;
CColor m_TextColorPressed;
EValign m_TextValign;
CStr m_ToolTip;
CStr m_ToolTipStyle;
*/
AddSetting(GUIST_CGUIString, "caption");
AddSetting(GUIST_bool, "checked");
AddSetting(GUIST_CStr, "sprite");
AddSetting(GUIST_CStr, "sprite-over");
AddSetting(GUIST_CStr, "sprite-pressed");
AddSetting(GUIST_CStr, "sprite-disabled");
AddSetting(GUIST_CStr, "sprite2");
AddSetting(GUIST_CStr, "sprite2-over");
AddSetting(GUIST_CStr, "sprite2-pressed");
AddSetting(GUIST_CStr, "sprite2-disabled");
AddSetting(GUIST_int, "square-side");
// Add text
AddText(new SGUIText());
}
CCheckBox::~CCheckBox()
{
}
void CCheckBox::SetupText()
{
if (!GetGUI())
return;
assert(m_GeneratedTexts.size()>=1);
CStr font;
CGUIString caption;
//int square_side;
GUI<CGUIString>::GetSetting(this, "caption", caption);
//GUI<CGUIString>::GetSetting(this, "square-side", square_side);
// TODO Gee: Establish buffer zones
*m_GeneratedTexts[0] = GetGUI()->GenerateText(caption, CStr("verdana12.fnt"), m_CachedActualSize.GetWidth()-20, 0);
// Set position of text
// TODO Gee: Big TODO
// m_TextPos.x = m_CachedActualSize.left + 20;
// m_TextPos.y = m_CachedActualSize.top;
}
void CCheckBox::HandleMessage(const SGUIMessage &Message)
{
// Important
IGUIButtonBehavior::HandleMessage(Message);
switch (Message.type)
{
case GUIM_PRESSED:
{
bool checked;
GUI<bool>::GetSetting(this, "checked", checked);
checked = !checked;
GUI<bool>::SetSetting(this, "checked", checked);
//GetGUI()->TEMPmessage = "Check box " + string((const TCHAR*)m_Name) + " was " + (m_Settings.m_Checked?"checked":"unchecked");
} break;
default:
break;
}
}
void CCheckBox::Draw()
{
////////// Gee: janwas, this is just temp to see it
glDisable(GL_TEXTURE_2D);
//////////
int square_side;
GUI<int>::GetSetting(this, "square-side", square_side);
float bz = GetBufferedZ();
// Get square
// TODO Gee: edit below when CRect has got "height()"
int middle = (m_CachedActualSize.bottom - m_CachedActualSize.top)/2;
CRect rect;
rect.left = m_CachedActualSize.left + middle - square_side/2;
rect.right = rect.left + square_side;
rect.top = m_CachedActualSize.top + middle - square_side/2;
rect.bottom = rect.top + square_side;
bool checked;
GUI<bool>::GetSetting(this, "checked", checked);
CStr sprite, sprite_over, sprite_pressed, sprite_disabled;
if (checked)
{
GUI<CStr>::GetSetting(this, "sprite2", sprite);
GUI<CStr>::GetSetting(this, "sprite2-over", sprite_over);
GUI<CStr>::GetSetting(this, "sprite2-pressed", sprite_pressed);
GUI<CStr>::GetSetting(this, "sprite2-disabled", sprite_disabled);
}
else
{
GUI<CStr>::GetSetting(this, "sprite", sprite);
GUI<CStr>::GetSetting(this, "sprite-over", sprite_over);
GUI<CStr>::GetSetting(this, "sprite-pressed", sprite_pressed);
GUI<CStr>::GetSetting(this, "sprite-disabled", sprite_disabled);
}
DrawButton( rect,
bz,
sprite,
sprite_over,
sprite_pressed,
sprite_disabled);
CColor color = ChooseColor();
// IGUITextOwner::Draw(0, color, m_TextPos, bz+0.1f);
}

75
source/gui/CCheckBox.h Executable file
View file

@ -0,0 +1,75 @@
/*
GUI Object - Check box
by Gustav Larsson
gee@pyro.nu
--Overview--
GUI Object representing a check box
--More info--
Check GUI.h
*/
#ifndef CCheckBox_H
#define CCheckBox_H
//--------------------------------------------------------
// Includes / Compiler directives
//--------------------------------------------------------
#include "GUI.h"
//--------------------------------------------------------
// Macros
//--------------------------------------------------------
//--------------------------------------------------------
// Types
//--------------------------------------------------------
//--------------------------------------------------------
// Declarations
//--------------------------------------------------------
/**
* @author Gustav Larsson
*
* CheckBox
*
* @see IGUIObject
* @see IGUISettingsObject
* @see IGUIButtonBehavior
*/
class CCheckBox : public IGUIButtonBehavior, public IGUITextOwner
{
GUI_OBJECT(CCheckBox)
public:
CCheckBox();
virtual ~CCheckBox();
virtual void ResetStates() { IGUIButtonBehavior::ResetStates(); }
/**
* Handle Messages
*
* @param Message GUI Message
*/
virtual void HandleMessage(const SGUIMessage &Message);
/**
* Draws the control
*/
virtual void Draw();
protected:
/**
* Sets up text, should be called every time changes has been
* made that can change the visual.
*/
void SetupText();
};
#endif

View file

@ -6,6 +6,13 @@ gee@pyro.nu
//#include "stdafx."
#include "GUI.h"
// Types - when including them into the engine.
#include "CButton.h"
#include "CText.h"
#include "CCheckBox.h"
#include "CRadioButton.h"
#include <xercesc/dom/DOM.hpp>
#include <xercesc/parsers/XercesDOMParser.hpp>
#include <xercesc/framework/LocalFileInputSource.hpp>
@ -15,6 +22,9 @@ gee@pyro.nu
#include "XercesErrorHandler.h"
#include "Prometheus.h"
#include "input.h"
#include "OverlayText.h"
// TODO Gee: Whatever include CRect/CPos/CSize
#include "Overlay.h"
#include <string>
#include <assert.h>
@ -28,6 +38,12 @@ using namespace std;
#pragma comment(lib, "xerces-c_2.lib")
#endif
// TODO Gee: how to draw overlays?
void render(COverlayText* overlaytext)
{
}
//-------------------------------------------------------------------
// called from main loop when (input) events are received.
@ -43,7 +59,7 @@ bool CGUI::HandleEvent(const SDL_Event& ev)
{
if(ev.type == SDL_MOUSEMOTION)
{
m_MouseX = ev.motion.x, m_MouseY = ev.motion.y;
m_MousePos = CPos(ev.motion.x, ev.motion.y);
// pNearest will after this point at the hovered object, possibly NULL
GUI<SGUIMessage>::RecurseObject(GUIRR_HIDDEN | GUIRR_GHOST, m_BaseObject,
@ -51,14 +67,15 @@ bool CGUI::HandleEvent(const SDL_Event& ev)
SGUIMessage(GUIM_MOUSE_MOTION));
}
char buf[30];
sprintf(buf, "type = %d", ev.type);
TEMPmessage = buf;
// TODO Gee: temp-stuff
// char buf[30];
// sprintf(buf, "type = %d", ev.type);
//TEMPmessage = buf;
if (ev.type == SDL_MOUSEBUTTONDOWN)
{
sprintf(buf, "button = %d", ev.button.button);
TEMPmessage = buf;
// sprintf(buf, "button = %d", ev.button.button);
//TEMPmessage = buf;
}
// JW: (pre|post)process omitted; what're they for? why would we need any special button_released handling?
@ -68,6 +85,9 @@ bool CGUI::HandleEvent(const SDL_Event& ev)
try
{
// TODO Gee: Optimizations needed!
// these two recursive function are quite overhead heavy.
// pNearest will after this point at the hovered object, possibly NULL
GUI<IGUIObject*>::RecurseObject(GUIRR_HIDDEN | GUIRR_GHOST, m_BaseObject,
&IGUIObject::ChooseMouseOverAndClosest,
@ -80,70 +100,79 @@ bool CGUI::HandleEvent(const SDL_Event& ev)
&IGUIObject::UpdateMouseOver,
pNearest);
//if (ev.type == SDL_MOUSEBUTTONDOWN)
if (ev.type == SDL_MOUSEBUTTONDOWN)
{
if (ev.type == SDL_MOUSEBUTTONDOWN)
switch (ev.button.button)
{
switch (ev.button.button)
{
case SDL_BUTTON_LEFT:
if (pNearest)
{
pNearest->HandleMessage(SGUIMessage(GUIM_MOUSE_PRESS_LEFT));
// some temp
CClientArea ca;
bool hidden;
/*GUI<CClientArea>::GetSetting(*this, CStr("backdrop"), CStr("size"), ca);
GUI<bool>::GetSetting(*this, CStr("backdrop"), CStr("hidden"), hidden);
//hidden = !hidden;
ca.pixel.right += 3;
ca.pixel.bottom += 3;
GUI<CClientArea>::SetSetting(*this, CStr("backdrop"), CStr("size"), ca);
GUI<bool>::SetSetting(*this, CStr("backdrop"), CStr("hidden"), hidden);
*/ }
break;
case 3: // wheel down
if (pNearest)
{
pNearest->HandleMessage(SGUIMessage(GUIM_MOUSE_WHEEL_DOWN));
}
break;
case 4: // wheel up
if (pNearest)
{
pNearest->HandleMessage(SGUIMessage(GUIM_MOUSE_WHEEL_UP));
}
break;
default:
break;
}
}
else
if (ev.type == SDL_MOUSEBUTTONUP)
{
if (ev.button.button == SDL_BUTTON_LEFT)
{
if (pNearest)
pNearest->HandleMessage(SGUIMessage(GUIM_MOUSE_RELEASE_LEFT));
}
// Reset all states on all visible objects
GUI<>::RecurseObject(GUIRR_HIDDEN, m_BaseObject,
&IGUIObject::ResetStates);
// It will have reset the mouse over of the current hovered, so we'll
// have to restore that
case SDL_BUTTON_LEFT:
if (pNearest)
pNearest->m_MouseHovering = true;
{
pNearest->HandleMessage(SGUIMessage(GUIM_MOUSE_PRESS_LEFT));
}
{
// some temp
/* CClientArea ca;
bool hidden;
GUI<CClientArea>::GetSetting(*this, CStr("backdrop43"), CStr("size"), ca);
//hidden = !hidden;
ca.pixel.right -= 3;
GUI<CClientArea>::SetSetting(*this, CStr("backdrop43"), CStr("size"), ca);
*/ }
break;
case 3: // wheel down
if (pNearest)
{
pNearest->HandleMessage(SGUIMessage(GUIM_MOUSE_WHEEL_DOWN));
}
break;
case 4: // wheel up
if (pNearest)
{
pNearest->HandleMessage(SGUIMessage(GUIM_MOUSE_WHEEL_UP));
}
break;
// TODO Gee: Just temp
case SDL_BUTTON_RIGHT:
{
CClientArea ca;
GUI<CClientArea>::GetSetting(*this, CStr("backdrop43"), CStr("size"), ca);
//hidden = !hidden;
ca.pixel.right -= 3;
GUI<CClientArea>::SetSetting(*this, CStr("backdrop43"), CStr("size"), ca);
}
break;
default:
break;
}
}
else
if (ev.type == SDL_MOUSEBUTTONUP)
{
if (ev.button.button == SDL_BUTTON_LEFT)
{
if (pNearest)
pNearest->HandleMessage(SGUIMessage(GUIM_MOUSE_RELEASE_LEFT));
}
// Reset all states on all visible objects
GUI<>::RecurseObject(GUIRR_HIDDEN, m_BaseObject,
&IGUIObject::ResetStates);
// It will have reset the mouse over of the current hovered, so we'll
// have to restore that
if (pNearest)
pNearest->m_MouseHovering = true;
}
}
catch (PS_RESULT e)
@ -164,7 +193,7 @@ bool CGUI::HandleEvent(const SDL_Event& ev)
//-------------------------------------------------------------------
// Constructor / Destructor
//-------------------------------------------------------------------
CGUI::CGUI()
CGUI::CGUI() : m_InternalNameNumber(0)
{
m_BaseObject = new CGUIDummyObject;
m_BaseObject->SetGUI(this);
@ -198,8 +227,11 @@ void CGUI::Initialize()
// Add base types!
// You can also add types outside the GUI to extend the flexibility of the GUI.
// Prometheus though will have all the object types inserted from here.
AddObjectType("button", &CButton::ConstructObject);
AddObjectType("text", &CText::ConstructObject);
AddObjectType("empty", &CGUIDummyObject::ConstructObject);
AddObjectType("button", &CButton::ConstructObject);
AddObjectType("text", &CText::ConstructObject);
AddObjectType("checkbox", &CCheckBox::ConstructObject);
AddObjectType("radiobutton", &CRadioButton::ConstructObject);
}
void CGUI::Process()
@ -301,10 +333,12 @@ void CGUI::DrawSprite(const CStr &SpriteName,
const CRect &Clipping)
{
// This is not an error, it's just a choice not to draw any sprite.
if (SpriteName == CStr("null") || SpriteName == CStr())
if (SpriteName == CStr())
return;
bool DoClipping = (Clipping != CRect(0,0,0,0));
const char * buf = SpriteName;
bool DoClipping = (Clipping != CRect());
CGUISprite Sprite;
// Fetch real sprite from name
@ -325,6 +359,9 @@ void CGUI::DrawSprite(const CStr &SpriteName,
{
CRect real = cit->m_Size.GetClientArea(Rect);
glPushMatrix();
glTranslatef(0.f, 0.f, cit->m_DeltaZ);
glColor3f(cit->m_BackColor.r , cit->m_BackColor.g, cit->m_BackColor.b);
//glColor3f((float)real.right/1000.f, 0.5f, 0.5f);
@ -335,6 +372,8 @@ void CGUI::DrawSprite(const CStr &SpriteName,
glVertex2i(real.left, real.top);
glVertex2i(real.right, real.top);
glEnd();
glPopMatrix();
}
glPopMatrix();
}
@ -356,7 +395,6 @@ void CGUI::Destroy()
}
delete it->second;
it->second = NULL;
}
// Clear all
@ -383,6 +421,8 @@ void CGUI::AddObject(IGUIObject* pObject)
// Cache tree
GUI<>::RecurseObject(0, pObject, &IGUIObject::UpdateCachedSize);
// Loaded
GUI<SGUIMessage>::RecurseObject(0, pObject, &IGUIObject::HandleMessage, SGUIMessage(GUIM_LOAD));
}
catch (PS_RESULT e)
{
@ -413,10 +453,316 @@ void CGUI::UpdateObjects()
bool CGUI::ObjectExists(const CStr &Name) const
{
if (m_pAllObjects.count(Name))
return true;
else
return false;
return m_pAllObjects.count(Name);
}
// private struct used only in GenerateText(...)
static struct SGenerateTextImage
{
int m_YFrom, // The images starting location in Y
m_YTo, // The images end location in Y
m_Indentation; // The image width in other words
// Some help functions
// TODO Gee: CRect => CPoint ?
void SetupSpriteCall(const bool &Left, SGUIText::SSpriteCall &SpriteCall,
const int &width, const int &y,
const CSize &Size, const CStr &TextureName,
const int &BufferZone)
{
// TODO Gee: Temp hardcoded values
SpriteCall.m_Area.top = y+BufferZone;
SpriteCall.m_Area.bottom = y+BufferZone + Size.cy;
if (Left)
{
SpriteCall.m_Area.left = BufferZone;
SpriteCall.m_Area.right = Size.cx+BufferZone;
}
else
{
SpriteCall.m_Area.left = width-BufferZone - Size.cx;
SpriteCall.m_Area.right = width-BufferZone;
}
SpriteCall.m_TextureName = TextureName;
m_YFrom = SpriteCall.m_Area.top-BufferZone;
m_YTo = SpriteCall.m_Area.bottom+BufferZone;
m_Indentation = Size.cx+BufferZone*2;
}
};
SGUIText CGUI::GenerateText(const CGUIString &string, /*const CColor &Color, */
const CStr &Font, const int &Width, const int &BufferZone)
{
SGUIText Text; // object we're generating
if (string.m_Words.size() == 0)
return Text;
int x=BufferZone, y=BufferZone; // drawing pointer
int from=0;
bool done=false;
// Images on the left or the right side.
vector<SGenerateTextImage> Images[2];
int pos_last_img=-1; // Position in the string where last img (either left or right) were encountered.
// in order to avoid duplicate processing.
// Easier to read.
bool WordWrapping = (Width != 0);
// Go through string word by word
for (int i=0; i<string.m_Words.size()-1 && !done; ++i)
{
// Pre-process each line one time, so we know which floating images
// will be added for that line.
// Generated stuff is stored in Feedback.
CGUIString::SFeedback Feedback;
// Preliminary line_height, used for word-wrapping with floating images.
int prelim_line_height=0;
// Width and height of all text calls generated.
string.GenerateTextCall(Feedback, Font, /*CColor(),*/
string.m_Words[i], string.m_Words[i+1]);
// Loop through our images queues, to see if images has been added.
// Check if this has already been processed.
// Also, floating images are only applicable if Word-Wrapping is on
if (WordWrapping && i > pos_last_img)
{
// Loop left/right
for (int j=0; j<2; ++j)
{
for (vector<CStr>::const_iterator it = Feedback.m_Images[j].begin();
it != Feedback.m_Images[j].end();
++it)
{
SGUIText::SSpriteCall SpriteCall;
SGenerateTextImage Image;
// Y is if no other floating images is above, y. Else it is placed
// after the last image, like a stack downwards.
int _y;
if (Images[j].size() > 0)
_y = max(y, Images[j].back().m_YTo);
else
_y = y;
// TODO Gee: CSize temp
CSize size; size.cx = 100; size.cy = 100;
Image.SetupSpriteCall((j==CGUIString::SFeedback::Left), SpriteCall, Width, _y, size, CStr("white-border"), BufferZone);
// Check if image is the lowest thing.
Text.m_Size.cy = max(Text.m_Size.cy, Image.m_YTo);
Images[j].push_back(Image);
Text.m_SpriteCalls.push_back(SpriteCall);
}
}
}
pos_last_img = max(pos_last_img, i);
x += Feedback.m_Size.cx;
prelim_line_height = max(prelim_line_height, Feedback.m_Size.cy);
// If Width is 0, then there's no word-wrapping, disable NewLine.
if ((WordWrapping && (x > Width-BufferZone || Feedback.m_NewLine)) || i == string.m_Words.size()-2)
{
// Change from to i, but first keep a copy of its value.
int temp_from = from;
from = i;
static const int From=0, To=1;
//int width_from=0, width_to=width;
int width_range[2];
width_range[From] = BufferZone;
width_range[To] = Width - BufferZone;
// Floating images are only appicable if word-wrapping is enabled.
if (WordWrapping)
{
// Decide width of the line. We need to iterate our floating images.
// this won't be exact because we're assuming the line_height
// will be as our preliminary calculation said. But that may change,
// although we'd have to add a couple of more loops to try straightening
// this problem out, and it is very unlikely to happen noticably if one
// stuctures his text in a stylistically pure fashion. Even if not, it
// is still quite unlikely it will happen.
// Loop through left and right side, from and to.
for (int j=0; j<2; ++j)
{
for (vector<SGenerateTextImage>::const_iterator it = Images[j].begin();
it != Images[j].end();
++it)
{
// We're working with two intervals here, the image's and the line height's.
// let's find the union of these two.
int union_from, union_to;
union_from = max(y, it->m_YFrom);
union_to = min(y+prelim_line_height, it->m_YTo);
// The union is not ø
if (union_to > union_from)
{
if (j == From)
width_range[From] = max(width_range[From], it->m_Indentation);
else
width_range[To] = min(width_range[To], Width - it->m_Indentation);
}
}
}
}
// Reset X for the next loop
x = width_range[From];
// Now we'll do another loop to figure out the height of
// the line (the height of the largest character). This
// couldn't be determined in the first loop (main loop)
// because it didn't regard images, so we don't know
// if all characters processed, will actually be involved
// in that line.
int line_height=0;
for (int j=temp_from; j<=i; ++j)
{
// We don't want to use Feedback now, so we'll have to use
// another.
CGUIString::SFeedback Feedback2;
string.GenerateTextCall(Feedback2, Font, /*CColor(),*/
string.m_Words[j], string.m_Words[j+1]);
// Append X value.
x += Feedback2.m_Size.cx;
if (WordWrapping && x > width_range[To] && j!=temp_from && !Feedback2.m_NewLine)
break;
// Let line_height be the maximum m_Height we encounter.
line_height = max(line_height, Feedback2.m_Size.cy);
if (WordWrapping && Feedback2.m_NewLine)
break;
}
// Reset x once more
x = width_range[From];
// Do the real processing now
for (int j=temp_from; j<=i; ++j)
{
// We don't want to use Feedback now, so we'll have to use
// another.
CGUIString::SFeedback Feedback2;
// Defaults
string.GenerateTextCall(Feedback2, Font, /*Color, */
string.m_Words[j], string.m_Words[j+1]);
// Iterate all and set X/Y values
// Since X values are not set, we need to make an internal
// iteration with an increment that will append the internal
// x, that is what x_pointer is for.
int x_pointer=0;
vector<SGUIText::STextCall>::iterator it;
for (it = Feedback2.m_TextCalls.begin(); it != Feedback2.m_TextCalls.end(); ++it)
{
it->m_Pos = CPos(x + x_pointer, y + line_height - it->m_Size.cy);
x_pointer += it->m_Size.cx;
if (it->m_pSpriteCall)
{
it->m_pSpriteCall->m_Area =
it->m_pSpriteCall->m_Area + it->m_Pos;
}
}
// Append X value.
x += Feedback2.m_Size.cx;
Text.m_Size.cx = max(Text.m_Size.cx, x+BufferZone);
// The first word overrides the width limit, that we
// do in those cases, are just draw that word even
// though it'll extend the object.
if (WordWrapping) // only if word-wrapping is applicable
{
if (Feedback2.m_NewLine)
{
from = j+1;
break;
}
else
if (x > width_range[To] && j==temp_from)
{
from = j+1;
// do not break, since we want it to be added to m_TextCalls
}
else
if (x > width_range[To])
{
from = j;
break;
}
}
// Add the whole Feedback2.m_TextCalls to our m_TextCalls.
Text.m_TextCalls.insert(Text.m_TextCalls.end(), Feedback2.m_TextCalls.begin(), Feedback2.m_TextCalls.end());
Text.m_SpriteCalls.insert(Text.m_SpriteCalls.end(), Feedback2.m_SpriteCalls.begin(), Feedback2.m_SpriteCalls.end());
if (j == string.m_Words.size()-2)
done = true;
}
// Reset X, and append Y.
x = 0;
y += line_height;
// Update height of all
Text.m_Size.cy = max(Text.m_Size.cy, y+BufferZone);
// Now if we entered as from = i, then we want
// i being one minus that, so that it will become
// the same i in the next loop. The difference is that
// we're on a new line now.
i = from-1;
}
}
return Text;
}
void CGUI::DrawText(const SGUIText &Text, const CColor &DefaultColor,
const CPos &pos, const float &z)
{
for (vector<SGUIText::STextCall>::const_iterator it=Text.m_TextCalls.begin();
it!=Text.m_TextCalls.end();
++it)
{
if (it->m_pSpriteCall)
continue;
COverlayText txt(pos.x+it->m_Pos.x, pos.y+it->m_Pos.y,
z, it->m_Font, it->m_String,
(it->m_UseCustomColor?it->m_Color:DefaultColor));
render(&txt);
}
for (vector<SGUIText::SSpriteCall>::const_iterator it=Text.m_SpriteCalls.begin();
it!=Text.m_SpriteCalls.end();
++it)
{
DrawSprite(it->m_TextureName, z, it->m_Area + pos);
}
}
void CGUI::ReportParseError(const CStr &str, ...)
@ -427,6 +773,8 @@ void CGUI::ReportParseError(const CStr &str, ...)
/// g_nemLog("*** GUI Tree Creation Errors");
}
// Important, set ParseError to true
++m_Errors;
/* TODO Gee: (MEGA)
@ -540,7 +888,7 @@ void CGUI::LoadXMLFile(const string &Filename)
// XML Reading Xerces Specific Sub-Routines
//===================================================================
void CGUI::Xerces_ReadRootObjects(XERCES_CPP_NAMESPACE::DOMElement *pElement)
void CGUI::Xerces_ReadRootObjects(DOMElement *pElement)
{
// Iterate main children
// they should all be <object> elements
@ -558,7 +906,7 @@ void CGUI::Xerces_ReadRootObjects(XERCES_CPP_NAMESPACE::DOMElement *pElement)
}
}
void CGUI::Xerces_ReadRootSprites(XERCES_CPP_NAMESPACE::DOMElement *pElement)
void CGUI::Xerces_ReadRootSprites(DOMElement *pElement)
{
// Iterate main children
// they should all be <sprite> elements
@ -576,7 +924,7 @@ void CGUI::Xerces_ReadRootSprites(XERCES_CPP_NAMESPACE::DOMElement *pElement)
}
}
void CGUI::Xerces_ReadRootStyles(XERCES_CPP_NAMESPACE::DOMElement *pElement)
void CGUI::Xerces_ReadRootStyles(DOMElement *pElement)
{
// Iterate main children
// they should all be <styles> elements
@ -594,7 +942,7 @@ void CGUI::Xerces_ReadRootStyles(XERCES_CPP_NAMESPACE::DOMElement *pElement)
}
}
void CGUI::Xerces_ReadRootSetup(XERCES_CPP_NAMESPACE::DOMElement *pElement)
void CGUI::Xerces_ReadRootSetup(DOMElement *pElement)
{
// Iterate main children
// they should all be <icon>, <scrollbar> or <tooltip>.
@ -665,7 +1013,6 @@ void CGUI::Xerces_ReadObject(DOMElement *pElement, IGUIObject *pParent)
}
else object->LoadStyle(*this, argStyle);
}
//
@ -683,6 +1030,10 @@ void CGUI::Xerces_ReadObject(DOMElement *pElement, IGUIObject *pParent)
CStr attr_name = XMLString::transcode( attr->getName() );
CStr attr_value = XMLString::transcode( attr->getValue() );
// If value is "null", then it is equivalent as never being entered
if (attr_value == CStr("null"))
continue;
// Ignore "type" and "style", we've already checked it
if (attr_name == CStr("type") || attr_name == CStr("style") )
continue;
@ -711,10 +1062,11 @@ void CGUI::Xerces_ReadObject(DOMElement *pElement, IGUIObject *pParent)
}
}
// Check if name isn't set, report error in that case
// Check if name isn't set, generate an internal name in that case.
if (!NameSet)
{
// TODO Gee: Generate internal name!
object->SetName(CStr("__internal(") + CStr(m_InternalNameNumber) + CStr(")"));
++m_InternalNameNumber;
}
//
@ -759,8 +1111,15 @@ void CGUI::Xerces_ReadObject(DOMElement *pElement, IGUIObject *pParent)
// Thank you CStr =)
caption.Trim(PS_TRIM_BOTH);
// Set the setting caption to this
GUI<CStr>::SetSetting(object, "caption", caption);
try
{
// Set the setting caption to this
object->SetSetting("caption", caption);
}
catch (...)
{
// There is no harm if the object didn't have a "caption"
}
}
// else
// TODO Gee: give warning
@ -779,9 +1138,12 @@ void CGUI::Xerces_ReadObject(DOMElement *pElement, IGUIObject *pParent)
}
else
{
bool absolute;
GUI<bool>::GetSetting(object, "absolute", absolute);
// If the object is absolute, we'll have to get the parent's Z buffered,
// and add to that!
if (object->GetBaseSettings().m_Absolute)
if (absolute)
{
GUI<float>::SetSetting(object, "z", pParent->GetBufferedZ() + 10.f);
}
@ -811,7 +1173,7 @@ void CGUI::Xerces_ReadObject(DOMElement *pElement, IGUIObject *pParent)
}
}
void CGUI::Xerces_ReadSprite(XERCES_CPP_NAMESPACE::DOMElement *pElement)
void CGUI::Xerces_ReadSprite(DOMElement *pElement)
{
assert(pElement);
@ -862,7 +1224,7 @@ void CGUI::Xerces_ReadSprite(XERCES_CPP_NAMESPACE::DOMElement *pElement)
m_Sprites[name] = sprite;
}
void CGUI::Xerces_ReadImage(XERCES_CPP_NAMESPACE::DOMElement *pElement, CGUISprite &parent)
void CGUI::Xerces_ReadImage(DOMElement *pElement, CGUISprite &parent)
{
assert(pElement);
@ -899,6 +1261,16 @@ void CGUI::Xerces_ReadImage(XERCES_CPP_NAMESPACE::DOMElement *pElement, CGUISpri
else image.m_Size = ca;
}
else
if (attr_name == CStr("z-level"))
{
int z_level;
if (!GUI<int>::ParseString(attr_value, z_level))
{
// TODO Gee: Error
}
else image.m_DeltaZ = (float)z_level/100.f;
}
else
if (attr_name == CStr("backcolor"))
{
CColor color;
@ -923,7 +1295,7 @@ void CGUI::Xerces_ReadImage(XERCES_CPP_NAMESPACE::DOMElement *pElement, CGUISpri
parent.AddImage(image);
}
void CGUI::Xerces_ReadStyle(XERCES_CPP_NAMESPACE::DOMElement *pElement)
void CGUI::Xerces_ReadStyle(DOMElement *pElement)
{
assert(pElement);
@ -958,7 +1330,7 @@ void CGUI::Xerces_ReadStyle(XERCES_CPP_NAMESPACE::DOMElement *pElement)
m_Styles[name] = style;
}
void CGUI::Xerces_ReadScrollBarStyle(XERCES_CPP_NAMESPACE::DOMElement *pElement)
void CGUI::Xerces_ReadScrollBarStyle(DOMElement *pElement)
{
assert(pElement);
@ -978,6 +1350,9 @@ void CGUI::Xerces_ReadScrollBarStyle(XERCES_CPP_NAMESPACE::DOMElement *pElement)
CStr attr_name = XMLString::transcode( attr->getName() );
CStr attr_value = XMLString::transcode( attr->getValue() );
if (attr_value == CStr("null"))
continue;
if (attr_name == CStr("name"))
name = attr_value;
else
@ -990,6 +1365,79 @@ void CGUI::Xerces_ReadScrollBarStyle(XERCES_CPP_NAMESPACE::DOMElement *pElement)
}
scrollbar.m_Width = i;
}
else
if (attr_name == CStr("minimum-bar-size"))
{
int i;
if (!GUI<int>::ParseString(attr_value, i))
{
// TODO Gee: Report in log file
}
scrollbar.m_MinimumBarSize = i;
}
else
if (attr_name == CStr("sprite-button-top"))
scrollbar.m_SpriteButtonTop = attr_value;
else
if (attr_name == CStr("sprite-button-top-pressed"))
scrollbar.m_SpriteButtonTopPressed = attr_value;
else
if (attr_name == CStr("sprite-button-top-disabled"))
scrollbar.m_SpriteButtonTopDisabled = attr_value;
else
if (attr_name == CStr("sprite-button-top-over"))
scrollbar.m_SpriteButtonTopOver = attr_value;
else
if (attr_name == CStr("sprite-button-bottom"))
scrollbar.m_SpriteButtonBottom = attr_value;
else
if (attr_name == CStr("sprite-button-bottom-pressed"))
scrollbar.m_SpriteButtonBottomPressed = attr_value;
else
if (attr_name == CStr("sprite-button-bottom-disabled"))
scrollbar.m_SpriteButtonBottomDisabled = attr_value;
else
if (attr_name == CStr("sprite-button-bottom-over"))
scrollbar.m_SpriteButtonBottomOver = attr_value;
else
if (attr_name == CStr("sprite-back-vertical"))
scrollbar.m_SpriteBackVertical = attr_value;
else
if (attr_name == CStr("sprite-bar-vertical"))
scrollbar.m_SpriteBarVertical = attr_value;
else
if (attr_name == CStr("sprite-bar-vertical-over"))
scrollbar.m_SpriteBarVerticalOver = attr_value;
else
if (attr_name == CStr("sprite-bar-vertical-pressed"))
scrollbar.m_SpriteBarVerticalPressed = attr_value;
/*
CStr m_SpriteButtonTop;
CStr m_SpriteButtonTopPressed;
CStr m_SpriteButtonTopDisabled;
CStr m_SpriteButtonBottom;
CStr m_SpriteButtonBottomPressed;
CStr m_SpriteButtonBottomDisabled;
CStr m_SpriteScrollBackHorizontal;
CStr m_SpriteScrollBarHorizontal;
CStr m_SpriteButtonLeft;
CStr m_SpriteButtonLeftPressed;
CStr m_SpriteButtonLeftDisabled;
CStr m_SpriteButtonRight;
CStr m_SpriteButtonRightPressed;
CStr m_SpriteButtonRightDisabled;
CStr m_SpriteScrollBackVertical;
CStr m_SpriteScrollBarVertical;
*/
}
//

View file

@ -108,7 +108,18 @@ public:
* @param Clipping The sprite shouldn't be drawn outside this rectangle
*/
void DrawSprite(const CStr &SpriteName, const float &Z,
const CRect &Rect, const CRect &Clipping=CRect(0,0,0,0));
const CRect &Rect, const CRect &Clipping=CRect());
/**
* Draw a SGUIText object
*
* @param Text Text object.
* @param DefaultColor Color used if no tag applied.
* @param pos position
* @param z z value.
*/
void DrawText(const SGUIText &Text, const CColor &DefaultColor,
const CPos &pos, const float &z);
/**
* Clean up, call this to clean up all memory allocated
@ -169,6 +180,24 @@ public:
*/
void UpdateResolution();
/**
* Generate a SGUIText object from the inputted string.
* The function will break down the string and its
* tags to calculate exactly which rendering queries
* will be sent to the Renderer.
*
* Done through the CGUI since it can communicate with
*
* @param Text Text to generate SGUIText object from
* @param Color Default color
* @param Font Default font, notice both Default color and defult font
* can be changed by tags.
* @param Width Width, 0 if no word-wrapping.
* @param BufferZone space between text and edge, and space between text and images.
*/
SGUIText GenerateText(const CGUIString &Text, /*const CColor &Color, */
const CStr &Font, const int &Width, const int &BufferZone);
private:
/**
* Updates the object pointers, needs to be called each
@ -385,9 +414,10 @@ private:
* ChooseMouseOverAndClosest broadcast -
* we'd need to pack this and pNearest in a struct
*/
u16 m_MouseX, m_MouseY;
CPos m_MousePos;
/// Used when reading in XML files
// TODO Gee: Used?
int16 m_Errors;
//@}
@ -411,6 +441,14 @@ private:
*/
map_pObjects m_pAllObjects;
/**
* Number of object that has been given name automatically.
* the name given will be '__internal(#)', the number (#)
* being this variable. When an object's name has been set
* as followed, the value will increment.
*/
int m_InternalNameNumber;
/**
* Function pointers to functions that constructs
* IGUIObjects by name... For instance m_ObjectTypes["button"]

View file

@ -9,81 +9,182 @@ gee@pyro.nu
using namespace std;
void CGUIScrollBarVertical::SetPosFromMousePos(int _x, int _y)
CGUIScrollBarVertical::CGUIScrollBarVertical()
{
m_Pos = m_PosWhenPressed + ((float)_y-m_BarPressedAtY)/(m_Length-GetStyle().m_Width*2)*2.f;
}
CGUIScrollBarVertical::~CGUIScrollBarVertical()
{
}
void CGUIScrollBarVertical::SetPosFromMousePos(const CPos &mouse)
{
if (!GetStyle())
return;
m_Pos = (m_PosWhenPressed + (float)m_ScrollRange*((float)mouse.y-m_BarPressedAtPos.y)/(m_Length-GetStyle()->m_Width*2));
}
void CGUIScrollBarVertical::Draw()
{
int StartX = (m_RightAligned)?(m_X-GetStyle().m_Width):(m_X);
if (!GetStyle())
{
// TODO Gee: Report in error log
return;
}
// Draw background
g_GUI.DrawSprite(GetStyle().m_SpriteScrollBackVertical, m_Z+0.1f,
CRect( StartX,
m_Y+GetStyle().m_Width,
StartX+GetStyle().m_Width,
m_Y+m_Length-GetStyle().m_Width)
);
if (GetGUI())
{
CRect outline = GetOuterRect();
// Draw top button
g_GUI.DrawSprite(GetStyle().m_SpriteButtonTop, m_Z+0.2f, CRect(StartX, m_Y, StartX+GetStyle().m_Width, m_Y+GetStyle().m_Width));
// Draw bottom button
g_GUI.DrawSprite(GetStyle().m_SpriteButtonBottom, m_Z+0.2f, CRect(StartX, m_Y+m_Length-GetStyle().m_Width, StartX+GetStyle().m_Width, m_Y+m_Length));
// Draw background
GetGUI()->DrawSprite(GetStyle()->m_SpriteBackVertical, m_Z+0.1f,
CRect( outline.left,
outline.top+(m_UseEdgeButtons?GetStyle()->m_Width:0),
outline.right,
outline.bottom-(m_UseEdgeButtons?GetStyle()->m_Width:0))
);
// Draw bar
if (m_BarPressed)
g_GUI.DrawSprite(GetStyle().m_SpriteScrollBarVertical, m_Z+0.2f, GetBarRect());
else
g_GUI.DrawSprite(GetStyle().m_SpriteScrollBarVertical, m_Z+0.2f, GetBarRect());
}
if (m_UseEdgeButtons)
{
// Get Appropriate sprites
CStr button_top, button_bottom;
bool CGUIScrollBarVertical::HandleMessage(const SGUIMessage &Message)
// figure out what sprite to use for top button
if (m_ButtonMinusHovered)
{
if (m_ButtonMinusPressed)
button_top = GUI<>::FallBackSprite(GetStyle()->m_SpriteButtonTopPressed, GetStyle()->m_SpriteButtonTop);
else
button_top = GUI<>::FallBackSprite(GetStyle()->m_SpriteButtonTopOver, GetStyle()->m_SpriteButtonTop);
}
else button_top = GetStyle()->m_SpriteButtonTop;
// figure out what sprite to use for top button
if (m_ButtonPlusHovered)
{
if (m_ButtonPlusPressed)
button_bottom = GUI<>::FallBackSprite(GetStyle()->m_SpriteButtonBottomPressed, GetStyle()->m_SpriteButtonBottom);
else
button_bottom = GUI<>::FallBackSprite(GetStyle()->m_SpriteButtonBottomOver, GetStyle()->m_SpriteButtonBottom);
}
else button_bottom = GetStyle()->m_SpriteButtonBottom;
// Draw top button
GetGUI()->DrawSprite(button_top,
m_Z+0.2f,
CRect(outline.left,
outline.top,
outline.right,
outline.top+GetStyle()->m_Width)
);
// Draw bottom button
GetGUI()->DrawSprite(button_bottom,
m_Z+0.2f,
CRect(outline.left,
outline.bottom-GetStyle()->m_Width,
outline.right,
outline.bottom)
);
}
// Draw bar
if (m_BarPressed)
GetGUI()->DrawSprite(GUI<>::FallBackSprite(GetStyle()->m_SpriteBarVerticalPressed, GetStyle()->m_SpriteBarVertical),
m_Z+0.2f,
GetBarRect());
else
if (m_BarHovered)
GetGUI()->DrawSprite(GUI<>::FallBackSprite(GetStyle()->m_SpriteBarVerticalOver, GetStyle()->m_SpriteBarVertical),
m_Z+0.2f,
GetBarRect());
else
GetGUI()->DrawSprite(GetStyle()->m_SpriteBarVertical,
m_Z+0.2f,
GetBarRect());
}
}
void CGUIScrollBarVertical::HandleMessage(const SGUIMessage &Message)
{
IGUIScrollBar::HandleMessage(Message);
/* switch (Message.type)
{
*/ return true;
}
CRect CGUIScrollBarVertical::GetBarRect() const
{
CRect ret;
if (!GetStyle())
return ret;
int size;
float from, to;
size = (int)((m_Length-GetStyle().m_Width*2)*m_BarSize);
from = (float)(m_Y+GetStyle().m_Width);
to = (float)(m_Y+m_Length-GetStyle().m_Width-size);
// is edge buttons used?
if (m_UseEdgeButtons)
{
size = (int)((m_Length-GetStyle()->m_Width*2)*m_BarSize);
if (size < GetStyle()->m_MinimumBarSize)
size = GetStyle()->m_MinimumBarSize;
from = (float)(m_Y+GetStyle()->m_Width);
to = (float)(m_Y+m_Length-GetStyle()->m_Width-size);
}
else
{
size = (int)(m_Length*m_BarSize);
if (size < GetStyle()->m_MinimumBarSize)
size = GetStyle()->m_MinimumBarSize;
from = (float)(m_Y);
to = (float)(m_Y+m_Length-size);
}
// Setup rectangle
CRect ret;
ret.top = (int)(from + (to-from)*m_Pos);
ret.top = (int)(from + (to-from)*((float)m_Pos/(float)(max(1,m_ScrollRange - m_ScrollSpace))));
ret.bottom = ret.top+size;
ret.right = m_X + ((m_RightAligned)?(0):(GetStyle().m_Width));
ret.left = ret.right - GetStyle().m_Width;
ret.right = m_X + ((m_RightAligned)?(0):(GetStyle()->m_Width));
ret.left = ret.right - GetStyle()->m_Width;
return ret;
}
bool CGUIScrollBarVertical::HoveringButtonMinus(int mouse_x, int mouse_y)
CRect CGUIScrollBarVertical::GetOuterRect() const
{
int StartX = (m_RightAligned)?(m_X-GetStyle().m_Width):(m_X);
CRect ret;
if (!GetStyle())
return ret;
return (mouse_x > StartX &&
mouse_x < StartX + GetStyle().m_Width &&
mouse_y > m_Y &&
mouse_y < m_Y + GetStyle().m_Width);
ret.top = m_Y;
ret.bottom = m_Y+m_Length;
ret.right = m_X + ((m_RightAligned)?(0):(GetStyle()->m_Width));
ret.left = ret.right - GetStyle()->m_Width;
return ret;
}
bool CGUIScrollBarVertical::HoveringButtonPlus(int mouse_x, int mouse_y)
bool CGUIScrollBarVertical::HoveringButtonMinus(const CPos &mouse)
{
int StartX = (m_RightAligned)?(m_X-GetStyle().m_Width):(m_X);
if (!GetStyle())
return false;
return (mouse_x > StartX &&
mouse_x < StartX + GetStyle().m_Width &&
mouse_y > m_Y + m_Length - GetStyle().m_Width &&
mouse_y < m_Y + m_Length);
int StartX = (m_RightAligned)?(m_X-GetStyle()->m_Width):(m_X);
return (mouse.x >= StartX &&
mouse.x <= StartX + GetStyle()->m_Width &&
mouse.y >= m_Y &&
mouse.y <= m_Y + GetStyle()->m_Width);
}
bool CGUIScrollBarVertical::HoveringButtonPlus(const CPos &mouse)
{
if (!GetStyle())
return false;
int StartX = (m_RightAligned)?(m_X-GetStyle()->m_Width):(m_X);
return (mouse.x > StartX &&
mouse.x < StartX + GetStyle()->m_Width &&
mouse.y > m_Y + m_Length - GetStyle()->m_Width &&
mouse.y < m_Y + m_Length);
}

View file

@ -41,8 +41,8 @@ gee@pyro.nu
class CGUIScrollBarVertical : public IGUIScrollBar
{
public:
CGUIScrollBarVertical() {}
virtual ~CGUIScrollBarVertical() {}
CGUIScrollBarVertical();
virtual ~CGUIScrollBarVertical();
public:
/**
@ -59,22 +59,22 @@ public:
* @return true if messages handled the scroll-bar some. False if
* the message should be processed by the object.
*/
virtual bool HandleMessage(const SGUIMessage &Message);
virtual void HandleMessage(const SGUIMessage &Message);
/**
* Set m_Pos with mouse_x/y input, i.e. when draggin.
*/
virtual void SetPosFromMousePos(int _x, int _y);
virtual void SetPosFromMousePos(const CPos &mouse);
/**
* @see IGUIScrollBar#HoveringButtonMinus
*/
virtual bool HoveringButtonMinus(int m_x, int m_y);
virtual bool HoveringButtonMinus(const CPos &mouse);
/**
* @see IGUIScrollBar#HoveringButtonPlus
*/
virtual bool HoveringButtonPlus(int m_x, int m_y);
virtual bool HoveringButtonPlus(const CPos &mouse);
/**
* Set Right Aligned
@ -89,6 +89,13 @@ protected:
*/
virtual CRect GetBarRect() const;
/**
* Get the rectangle of the outline of the scrollbar, every component of the
* scroll-bar should be inside this area.
* @return Rectangle, CRect
*/
virtual CRect GetOuterRect() const;
/**
* Should the scroll bar proceed to the left or to the right of the m_X value.
* Notice, this has nothing to do with where the owner places it.

View file

@ -26,6 +26,7 @@ gee@pyro.nu
// Includes / Compiler directives
//--------------------------------------------------------
#include "GUI.h"
#include "Overlay.h"
//--------------------------------------------------------
// Macros
@ -51,6 +52,9 @@ gee@pyro.nu
*/
struct SGUIImage
{
SGUIImage() : m_Border(false), m_DeltaZ(0.f) {}
~SGUIImage() {}
CStr m_Texture;
// Image placement
@ -65,6 +69,13 @@ struct SGUIImage
// 0 or 1 pixel border is the only option
bool m_Border;
/**
* Z value modification of the image.
* Inputted in XML as x-level, although it just an easier and safer
* way of declaring delta-z.
*/
float m_DeltaZ;
};
/**
@ -87,16 +98,6 @@ public:
CGUISprite() {}
virtual ~CGUISprite() {}
/**
* Execute a drawing request for this sprite
*
* @param z Draw in what depth.
* @param rect Outer rectangle to draw the collage.
* @param clipping The clipping rectangle, things should only
* be drawn within these perimeters.
*/
//void Draw(const float &z, const CRect &rect, const CRect &clipping);
/**
* Adds an image to the sprite collage.
*

37
source/gui/CRadioButton.cpp Executable file
View file

@ -0,0 +1,37 @@
/*
CCheckBox
by Gustav Larsson
gee@pyro.nu
*/
//#include "stdafx."
#include "GUI.h"
#include "CRadioButton.h"
using namespace std;
void CRadioButton::HandleMessage(const SGUIMessage &Message)
{
// Important
IGUIButtonBehavior::HandleMessage(Message);
switch (Message.type)
{
case GUIM_PRESSED:
for (vector_pObjects::iterator it = GetParent()->ChildrenItBegin(); it != GetParent()->ChildrenItEnd(); ++it)
{
// Notice, if you use other objects within the parent object that has got
// this the "checked", it too will change. Hence NO OTHER OBJECTS THAN
// RADIO BUTTONS SHOULD BE WITHIN IT!
GUI<bool>::SetSetting((*it), "checked", false);
}
GUI<bool>::SetSetting(this, "checked", true);
//GetGUI()->TEMPmessage = "Check box " + string((const TCHAR*)m_Name) + " was " + (m_Settings.m_Checked?"checked":"unchecked");
break;
default:
break;
}
}

49
source/gui/CRadioButton.h Executable file
View file

@ -0,0 +1,49 @@
/*
GUI Object - Radio Button
by Gustav Larsson
gee@pyro.nu
--Overview--
GUI Object representing a radio button
--More info--
Check GUI.h
*/
#ifndef CRadioButton_H
#define CRadioButton_H
//--------------------------------------------------------
// Includes / Compiler directives
//--------------------------------------------------------
#include "GUI.h"
#include "CCheckBox.h"
/**
* @author Gustav Larsson
*
* Just like a check box, but it'll nullify its siblings (of the same kind),
* and it won't switch itself.
*
* @see CCheckBox
*/
class CRadioButton : public CCheckBox
{
GUI_OBJECT(CRadioButton)
// Let the class freely interact with its siblings
friend class CRadioButton;
public:
/**
* Handle Messages
*
* @param Message GUI Message
*/
virtual void HandleMessage(const SGUIMessage &Message);
};
#endif

View file

@ -6,71 +6,122 @@ gee@pyro.nu
//#include "stdafx."
#include "GUI.h"
#include "CText.h"
// TODO Gee: font.h is temporary.
#include "res/font.h"
#include "ogl.h"
using namespace std;
// TODO Gee: new
#include "OverlayText.h"
// Offsets
DECLARE_SETTINGS_INFO(STextSettings)
using namespace std;
//-------------------------------------------------------------------
// Constructor / Destructor
//-------------------------------------------------------------------
CText::CText()
{
// Static! Only done once
if (m_SettingsInfo.empty())
{
// Setup the base ones too
SetupBaseSettingsInfo(m_SettingsInfo);
AddSetting(GUIST_CGUIString, "caption");
AddSetting(GUIST_bool, "scrollbar");
AddSetting(GUIST_CStr, "scrollbar-style");
AddSetting(GUIST_CStr, "sprite");
AddSetting(GUIST_CColor, "textcolor");
GUI_ADD_OFFSET_EXT(STextSettings, m_Sprite, "string", "sprite")
GUI_ADD_OFFSET_EXT(STextSettings, m_ScrollBar, "bool", "scrollbar")
GUI_ADD_OFFSET_EXT(STextSettings, m_ScrollBarStyle, "string", "scrollbar-style")
}
//GUI<bool>::SetSetting(this, "ghost", true);
GUI<bool>::SetSetting(this, "scrollbar", false);
// Add scroll-bar
CGUIScrollBarVertical * bar = new CGUIScrollBarVertical();
bar->SetRightAligned(true);
bar->SetUseEdgeButtons(true);
AddScrollBar(bar);
// Add text
AddText(new SGUIText());
}
CText::~CText()
{
}
void CText::SetupText()
{
if (!GetGUI())
return;
assert(m_GeneratedTexts.size()>=1);
CColor color;
CStr font;
CGUIString caption;
bool scrollbar;
GUI<CColor>::GetSetting(this, "textcolor", color);
GUI<CGUIString>::GetSetting(this, "caption", caption);
GUI<bool>::GetSetting(this, "scrollbar", scrollbar);
int width = m_CachedActualSize.GetWidth();
// remove scrollbar if applicable
if (scrollbar && GetScrollBar(0).GetStyle())
width -= GetScrollBar(0).GetStyle()->m_Width;
*m_GeneratedTexts[0] = GetGUI()->GenerateText(caption, /*color,*/ CStr("verdana12.fnt"), width, 4);
// Setup scrollbar
if (scrollbar)
{
GetScrollBar(0).SetScrollRange( m_GeneratedTexts[0]->m_Size.cy );
GetScrollBar(0).SetScrollSpace( m_CachedActualSize.GetHeight() );
}
}
void CText::HandleMessage(const SGUIMessage &Message)
{
// TODO Gee:
IGUIScrollBarOwner::HandleMessage(Message);
IGUITextOwner::HandleMessage(Message);
switch (Message.type)
{
case GUIM_SETTINGS_UPDATED:
if (Message.value == CStr("size") || Message.value == CStr("z") ||
Message.value == CStr("absolute"))
bool scrollbar;
GUI<bool>::GetSetting(this, "scrollbar", scrollbar);
// Update scroll-bar
if (scrollbar &&
(Message.value == CStr("size") || Message.value == CStr("z") ||
Message.value == CStr("absolute")))
{
GetScrollBar(0).SetX( m_CachedActualSize.right );
GetScrollBar(0).SetY( m_CachedActualSize.top );
GetScrollBar(0).SetZ( GetBufferedZ() );
GetScrollBar(0).SetLength( m_CachedActualSize.bottom - m_CachedActualSize.top );
}
// Update scrollbar
if (Message.value == CStr("scrollbar-style"))
{
GetScrollBar(0).SetScrollBarStyle( GetSettings().m_ScrollBarStyle );
CStr scrollbar_style;
GUI<CStr>::GetSetting(this, Message.value, scrollbar_style);
GetScrollBar(0).SetScrollBarStyle( scrollbar_style );
}
break;
case GUIM_MOUSE_WHEEL_DOWN:
GetScrollBar(0).ScrollPlus();
// Since the scroll was changed, let's simulate a mouse movement
// to check if scrollbar now is hovered
HandleMessage(SGUIMessage(GUIM_MOUSE_MOTION));
break;
case GUIM_MOUSE_WHEEL_UP:
GetScrollBar(0).ScrollMinus();
// Since the scroll was changed, let's simulate a mouse movement
// to check if scrollbar now is hovered
HandleMessage(SGUIMessage(GUIM_MOUSE_MOTION));
break;
default:
@ -84,12 +135,35 @@ void CText::Draw()
glDisable(GL_TEXTURE_2D);
//////////
float bz = GetBufferedZ();
// First call draw on ScrollBarOwner
IGUIScrollBarOwner::Draw();
bool scrollbar;
GUI<bool>::GetSetting(this, "scrollbar", scrollbar);
if (scrollbar)
{
// Draw scrollbar
IGUIScrollBarOwner::Draw();
}
if (GetGUI())
{
GetGUI()->DrawSprite(m_Settings.m_Sprite, GetBufferedZ(), m_CachedActualSize);
}
CStr sprite;
GUI<CStr>::GetSetting(this, "sprite", sprite);
GetGUI()->DrawSprite(sprite, bz, m_CachedActualSize);
int scroll=0;
if (scrollbar)
{
scroll = GetScrollBar(0).GetPos();
}
CColor color;
GUI<CColor>::GetSetting(this, "textcolor", color);
// Draw text
IGUITextOwner::Draw(0, color, m_CachedActualSize.TopLeft() - CPos(0,scroll), bz+0.1f);
}
}

View file

@ -36,24 +36,6 @@ class IGUIScrollBar;
// Declarations
//--------------------------------------------------------
/**
* Text Settings
*/
struct STextSettings
{
CStr m_Font;
CStr m_Sprite;
EAlign m_TextAlign;
CColor m_TextColor;
EValign m_TextValign;
CStr m_ToolTip;
CStr m_ToolTipStyle;
bool m_ScrollBar;
CStr m_ScrollBarStyle;
};
///////////////////////////////////////////////////////////////////////////////
/**
* @author Gustav Larsson
*
@ -61,9 +43,8 @@ struct STextSettings
*
* @see IGUIObject
* @see IGUISettingsObject
* @see STextSettings
*/
class CText : public IGUISettingsObject<STextSettings>, public IGUIScrollBarOwner
class CText : public IGUIScrollBarOwner, public IGUITextOwner
{
GUI_OBJECT(CText)
@ -71,15 +52,15 @@ public:
CText();
virtual ~CText();
/**
* Since we're doing multiple inheritance, this is to avoid error message
*
* @return Settings infos
*/
virtual map_Settings GetSettingsInfo() const { return IGUISettingsObject<STextSettings>::m_SettingsInfo; }
virtual void ResetStates() { IGUIScrollBarOwner::ResetStates(); }
protected:
/**
* Sets up text, should be called every time changes has been
* made that can change the visual.
*/
void SetupText();
/**
* Handle Messages
*
@ -91,9 +72,6 @@ public:
* Draws the Text
*/
virtual void Draw();
// TODO Gee: Temp!
//CGUIScrollBar m_ScrollBar;
};
#endif

View file

@ -66,16 +66,14 @@ gee@pyro.nu
#include "GUIbase.h"
#include "GUIutil.h"
#include "GUItext.h"
#include "IGUIObject.h"
#include "IGUISettingsObject.h"
#include "IGUIButtonBehavior.h"
#include "IGUIScrollBarOwner.h"
#include "IGUITextOwner.h"
#include "IGUIScrollBar.h"
#include "CGUIScrollBarVertical.h"
#include "CButton.h"
#include "CText.h"
#include "CGUISprite.h"
#include "CGUI.h"
#endif

View file

@ -36,20 +36,6 @@ class IGUIObject;
#define g_GUI CGUI::GetSingleton()
// Object settings setups
#define GUI_ADD_OFFSET_GENERIC(si, guiss, _struct, var, type, str) \
si[CStr(str)].m_Offset = offsetof(_struct, var); \
si[CStr(str)].m_SettingsStruct = guiss; \
si[CStr(str)].m_Type = CStr(type);
#define GUI_ADD_OFFSET_BASE(_struct, var, type, str) \
GUI_ADD_OFFSET_GENERIC(m_SettingsInfo, GUISS_BASE, _struct, var, type, str)
#define GUI_ADD_OFFSET_EXT(_struct, var, type, str) \
GUI_ADD_OFFSET_GENERIC(m_SettingsInfo, GUISS_EXTENDED, _struct, var, type, str)
// Declares the static variable in IGUISettingsObject<>
#define DECLARE_SETTINGS_INFO(_struct) \
map_Settings IGUISettingsObject<_struct>::m_SettingsInfo;
// Setup an object's ConstructObject function
#define GUI_OBJECT(obj) \
@ -83,10 +69,13 @@ enum EGUIMessageType
GUIM_MOUSE_WHEEL_DOWN,
GUIM_SETTINGS_UPDATED, // SGUIMessage.m_Value = name of setting
GUIM_PRESSED,
GUIM_MOUSE_MOTION
GUIM_MOUSE_MOTION,
GUIM_LOAD // Called when an object is added to the GUI.
};
/**
* @author Gustav Larsson
*
* Message send to IGUIObject::HandleMessage() in order
* to give life to Objects manually with
* a derived HandleMessage().

481
source/gui/GUItext.cpp Executable file
View file

@ -0,0 +1,481 @@
/*
GUI text
by Gustav Larsson
gee@pyro.nu
*/
#include "GUI.h"
#include "Parser.h"
#include "OverlayText.h"
#include <algorithm>
// TODO Gee: Remove, just for temp-output
#include <fstream>
static const TCHAR TagStart = '[';
static const TCHAR TagEnd = ']';
void CGUIString::SFeedback::Reset()
{
m_Images[Left].clear();
m_Images[Right].clear();
m_TextCalls.clear();
m_SpriteCalls.clear();
m_Size = CSize();
m_NewLine=false;
}
void CGUIString::GenerateTextCall(SFeedback &Feedback,
const CStr &DefaultFont, /*const CColor &DefaultColor,*/
const int &from, const int &to) const
{
// Reset width and height, because they will be determined with incrementation
// or comparisons.
Feedback.Reset();
// Check out which text chunk this is within.
//bool match_found = false;
vector<TextChunk>::const_iterator itTextChunk;
for (itTextChunk=m_TextChunks.begin(); itTextChunk!=m_TextChunks.end(); ++itTextChunk)
{
// Get the area that is overlapped by both the TextChunk and
// by the from/to inputted.
int _from, _to;
_from = max(from, itTextChunk->m_From);
_to = min(to, itTextChunk->m_To);
// If from is larger than to, than they are not overlapping
if (_to == _from && itTextChunk->m_From == itTextChunk->m_To && _from > from)
{
// These should never be able to have more than one tag.
assert(itTextChunk->m_Tags.size()==1);
// Single tags
if (itTextChunk->m_Tags[0].m_TagType == CGUIString::TextChunk::Tag::TAG_IMGLEFT)
{
//if (_from > from)
Feedback.m_Images[SFeedback::Left].push_back(itTextChunk->m_Tags[0].m_TagValue);
}
else
if (itTextChunk->m_Tags[0].m_TagType == CGUIString::TextChunk::Tag::TAG_IMGRIGHT)
{
//if (_from > from)
Feedback.m_Images[SFeedback::Right].push_back(itTextChunk->m_Tags[0].m_TagValue);
}
else
if (itTextChunk->m_Tags[0].m_TagType == CGUIString::TextChunk::Tag::TAG_ICON)
{
//if (_from <= from)continue;;
// We'll need to setup a text-call that will point
// to the icon, this is to be able to iterate
// through the text-calls without having to
// complex the structure ultimately for nothing more.
SGUIText::STextCall TextCall;
// Also add it to the sprites being rendered.
SGUIText::SSpriteCall SpriteCall;
CSize size(20,20);
// Query size of icon
// TODO Gee: Temp
// append width, and make maximum height the height.
Feedback.m_Size.cx += size.cx;
Feedback.m_Size.cy = max(Feedback.m_Size.cy, size.cy);
// These are also needed later
TextCall.m_Size = size;
SpriteCall.m_Area = size;
SpriteCall.m_TextureName = CStr("scroll");
// Add sprite call
Feedback.m_SpriteCalls.push_back(SpriteCall);
// Finalize text call
TextCall.m_pSpriteCall = &Feedback.m_SpriteCalls.back();
// Add text call
Feedback.m_TextCalls.push_back(TextCall);
}
}
else
if (_to > _from && !Feedback.m_NewLine)
{
SGUIText::STextCall TextCall;
// Set defaults
TextCall.m_Font = DefaultFont;
TextCall.m_UseCustomColor = false;
// Extract substring from RawString.
TextCall.m_String = GetRawString().GetSubstring(_from, _to-_from);
// Go through tags and apply changes.
vector<CGUIString::TextChunk::Tag>::const_iterator it2;
for (it2 = itTextChunk->m_Tags.begin(); it2 != itTextChunk->m_Tags.end(); ++it2)
{
if (it2->m_TagType == CGUIString::TextChunk::Tag::TAG_COLOR)
{
// Set custom color
TextCall.m_UseCustomColor = true;
GUI<CColor>::ParseString(it2->m_TagValue, TextCall.m_Color);
}
else
if (it2->m_TagType == CGUIString::TextChunk::Tag::TAG_FONT)
{
TextCall.m_Font = it2->m_TagValue;
}
}
CSize size;
COverlayText txt(0, 0, 0, TextCall.m_Font, TextCall.m_String, TextCall.m_Color);
// TODO Gee: Ask Rich to change to (size);
txt.GetOutputStringSize((int&)size.cx, (int&)size.cy);
// append width, and make maximum height the height.
Feedback.m_Size.cx += size.cx;
Feedback.m_Size.cy = max(Feedback.m_Size.cy, size.cy);
// These are also needed later
TextCall.m_Size = size;
if (TextCall.m_String.Length() >= 1)
{
if (TextCall.m_String[0] == '\n')
{
Feedback.m_NewLine = true;
}
}
// Add text-chunk
Feedback.m_TextCalls.push_back(TextCall);
}
}
}
bool CGUIString::TextChunk::Tag::SetTagType(const CStr &tagtype)
{
CStr _tagtype = tagtype.UpperCase();
if (_tagtype == CStr("B"))
{
m_TagType = TAG_B;
return true;
}
else
if (_tagtype == CStr("I"))
{
m_TagType = TAG_I;
return true;
}
else
if (_tagtype == CStr("COLOR"))
{
m_TagType = TAG_COLOR;
return true;
}
else
if (_tagtype == CStr("FONT"))
{
m_TagType = TAG_FONT;
return true;
}
else
if (_tagtype == CStr("ICON"))
{
m_TagType = TAG_ICON;
return true;
}
else
if (_tagtype == CStr("IMGLEFT"))
{
m_TagType = TAG_IMGLEFT;
return true;
}
else
if (_tagtype == CStr("IMGRIGHT"))
{
m_TagType = TAG_IMGRIGHT;
return true;
}
return false;
}
void CGUIString::SetValue(const CStr &str)
{
// clear
m_TextChunks.clear();
m_Words.clear();
m_RawString = CStr();
// Setup parser
CParser Parser;
Parser.InputTaskType("start", "$ident[_=_$value]");
Parser.InputTaskType("end", "/$ident");
_long position = 0;
_long from=0; // the position in the raw string where the last tag ended
_long from_nonraw=0; // like from only in position of the REAL string, with tags.
_long curpos = 0;
// Current Text Chunk
CGUIString::TextChunk CurrentTextChunk;
for (;;position = curpos+1)
{
// Find next TagStart character
curpos = str.Find(position, TagStart);
if (curpos == -1)
{
m_RawString += str.GetSubstring(position, str.Length()-position);
if (from != m_RawString.Length())
{
CurrentTextChunk.m_From = from;
CurrentTextChunk.m_To = m_RawString.Length();
m_TextChunks.push_back(CurrentTextChunk);
}
break;
}
else
{
// First check if there is another TagStart before a TagEnd,
// in that case it's just a regular TagStart and we can continue.
_long pos_left = str.Find(curpos+1, TagStart);
_long pos_right = str.Find(curpos+1, TagEnd);
if (pos_right == -1)
{
m_RawString += str.GetSubstring(position, curpos-position+1);
continue;
}
else
if (pos_left != -1 && pos_left < pos_right)
{
m_RawString += str.GetSubstring(position, pos_left-position);
continue;
}
else
{
m_RawString += str.GetSubstring(position, curpos-position);
// Okay we've found a TagStart and TagEnd, positioned
// at pos and pos_right. Now let's extract the
// interior and try parsing.
CStr tagstr = str.GetSubstring(curpos+1, pos_right-curpos-1);
CParserLine Line;
Line.ParseString(Parser, (const char*)tagstr);
// Set to true if the tag is just text.
bool justtext = false;
if (Line.m_ParseOK)
{
if (Line.m_TaskTypeName == "start")
{
// The tag
TextChunk::Tag tag;
CStr Str_TagType;
Line.GetArgString(0, (std::string &)Str_TagType);
if (!tag.SetTagType(Str_TagType))
{
justtext = true;
}
else
{
// Check for possible value-strings
if (Line.GetArgCount() == 2)
Line.GetArgString(1, (std::string &)tag.m_TagValue);
// Finalize last
if (curpos != from_nonraw)
{
CurrentTextChunk.m_From = from;
CurrentTextChunk.m_To = from + curpos - from_nonraw;
m_TextChunks.push_back(CurrentTextChunk);
from = CurrentTextChunk.m_To;
}
from_nonraw = pos_right+1;
// Some tags does not have a closure, and should be
// stored without text. Like a <tag /> in XML.
if (tag.m_TagType == TextChunk::Tag::TAG_IMGLEFT ||
tag.m_TagType == TextChunk::Tag::TAG_IMGRIGHT ||
tag.m_TagType == TextChunk::Tag::TAG_ICON)
{
// We need to use a fresh text chunk
// because 'tag' should be the *only* tag.
TextChunk FreshTextChunk;
// They does not work with the text system.
FreshTextChunk.m_From = from + pos_right+1 - from_nonraw;
FreshTextChunk.m_To = from + pos_right+1 - from_nonraw;
FreshTextChunk.m_Tags.push_back(tag);
m_TextChunks.push_back(FreshTextChunk);
}
else
{
// Add that tag, but first, erase previous occurences of the
// same tag.
vector<TextChunk::Tag>::iterator it;
for (it = CurrentTextChunk.m_Tags.begin(); it != CurrentTextChunk.m_Tags.end(); ++it)
{
if (it->m_TagType == tag.m_TagType)
{
CurrentTextChunk.m_Tags.erase(it);
break;
}
}
// Add!
CurrentTextChunk.m_Tags.push_back(tag);
}
}
}
else
if (Line.m_TaskTypeName == "end")
{
// The tag
TextChunk::Tag tag;
CStr Str_TagType;
Line.GetArgString(0, (std::string &)Str_TagType);
if (!tag.SetTagType(Str_TagType))
{
justtext = true;
}
else
{
// Finalize the previous chunk
if (curpos != from_nonraw)
{
CurrentTextChunk.m_From = from;
CurrentTextChunk.m_To = from + curpos - from_nonraw;
m_TextChunks.push_back(CurrentTextChunk);
from = CurrentTextChunk.m_To;
}
from_nonraw = pos_right+1;
// Search for the tag, if it's not added, then
// pass it as plain text.
vector<TextChunk::Tag>::iterator it;
for (it = CurrentTextChunk.m_Tags.begin(); it != CurrentTextChunk.m_Tags.end(); ++it)
{
if (it->m_TagType == tag.m_TagType)
{
CurrentTextChunk.m_Tags.erase(it);
break;
}
}
}
}
}
else justtext = true;
if (justtext)
{
// What was within the tags could not be interpreted
// so we'll assume it's just text.
m_RawString += str.GetSubstring(curpos, pos_right-curpos+1);
}
curpos = pos_right;
continue;
}
}
}
#if 1
ofstream fout("output1.txt");
for (int i=0; i<m_TextChunks.size(); ++i)
{
fout << "{\"";
fout << m_TextChunks[i].m_From << " " << m_TextChunks[i].m_To << "\",";
for (int j=0; j<m_TextChunks[i].m_Tags.size(); ++j)
{
fout << "(" << m_TextChunks[i].m_Tags[j].m_TagType << " " << m_TextChunks[i].m_Tags[j].m_TagValue << ")";
}
fout << "}\n";
}
fout.close();
#endif
// Add a delimiter at start and at end, it helps when
// processing later, because we don't have make exceptions for
// those cases.
// We'll sort later.
m_Words.push_back(0);
m_Words.push_back(m_RawString.Length());
// Space: ' '
for (position=0, curpos=0;;position = curpos+1)
{
// Find the next word-delimiter.
_long dl = m_RawString.Find(position, ' ');
if (dl == -1)
break;
curpos = dl;
m_Words.push_back((int)dl+1);
}
// Dash: '-'
for (position=0, curpos=0;;position = curpos+1)
{
// Find the next word-delimiter.
_long dl = m_RawString.Find(position, '-');
if (dl == -1)
break;
curpos = dl;
m_Words.push_back((int)dl+1);
}
// New Line: '\n'
for (position=0, curpos=0;;position = curpos+1)
{
// Find the next word-delimiter.
_long dl = m_RawString.Find(position, '\n');
if (dl == -1)
break;
curpos = dl;
// Add before and
m_Words.push_back((int)dl);
m_Words.push_back((int)dl+1);
}
sort(m_Words.begin(), m_Words.end());
// Remove duplicates
vector<int>::iterator it;
int last_word = -1;
for (it = m_Words.begin(); it != m_Words.end(); ++it)
{
if (last_word == *it)
m_Words.erase(it);
last_word = *it;
}
}

300
source/gui/GUItext.h Executable file
View file

@ -0,0 +1,300 @@
/*
GUI text, handles text stuff
by Gustav Larsson
gee@pyro.nu
--Overview--
Mainly contains struct SGUIText and friends.
Actual text processing is made in CGUI::GenerateText()
--More info--
Check GUI.h
*/
#ifndef GUItext_H
#define GUItext_H
//--------------------------------------------------------
// Includes / Compiler directives
//--------------------------------------------------------
//--------------------------------------------------------
// Declarations
//--------------------------------------------------------
/**
* @author Gustav Larsson
*
* An SGUIText object is a parsed string, divided into
* text-rendering components. Each component, being a
* call to the Renderer. For instance, if you by tags
* change the color, then the GUI will have to make
* individual calls saying it want that color on the
* text.
*
* For instance (this is not the syntax):
* "Hello [b]there[/b] bunny!"
*
* That without word-wrapping would mean 3 components.
* i.e. 3 calls to CRenderer. One drawing "Hello",
* one drawing "there" in bold, and one drawing "bunny!".
*/
struct SGUIText
{
/**
* @author Gustav Larsson
*
* A sprite call to the CRenderer
*/
struct SSpriteCall
{
/**
* Size and position of sprite
*/
CRect m_Area;
/**
* Texture name from texture database.
*/
CStr m_TextureName;
};
/**
* @author Gustav Larsson
*
* A text call to the CRenderer
*/
struct STextCall
{
STextCall() :
m_Bold(false), m_Italic(false), m_Underlined(false),
m_UseCustomColor(false), m_pSpriteCall(NULL) {}
/**
* Position
*/
CPos m_Pos;
/**
* Size
*/
CSize m_Size;
/**
* The string that is suppose to be rendered.
*/
CStr m_String;
/**
* Use custom color? If true then m_Color is used,
* else the color inputted will be used.
*/
bool m_UseCustomColor;
/**
* Color setup
*/
CColor m_Color;
/**
* Font name
*/
CStr m_Font;
/**
* Settings
*/
bool m_Bold, m_Italic, m_Underlined;
/**
* *IF* an icon, than this is not NULL.
*/
SSpriteCall *m_pSpriteCall;
};
/**
* List of TextCalls, for instance "Hello", "there!"
*/
std::vector<STextCall> m_TextCalls;
/**
* List of sprites, or "icons" that should be rendered
* along with the text.
*/
std::vector<SSpriteCall> m_SpriteCalls;
/**
* Width and height of the whole output, used when setting up
* scrollbars and such.
*/
CSize m_Size;
};
/**
* @author Gustav Larsson
*
* String class, substitue for CStr, but that parses
* the tags and builds up a list of all text that will
* be different when outputted.
*
* The difference between CGUIString and SGUIText is that
* CGUIString is a string-class that parses the tags
* when the value is set. The SGUIText is just a container
* which stores the positions and settings of all text-calls
* that will have to be made to the Renderer.
*/
class CGUIString
{
public:
/**
* @author Gustav Larsson
*
* A chunk of text that represents one call to the renderer.
* In other words, all text in one chunk, will be drawn
* exactly with the same settings.
*/
struct TextChunk
{
/**
* @author Gustav Larsson
*
* A tag looks like this "Hello [B]there[/B] little"
*/
struct Tag
{
/**
* Tag Type
*/
enum TagType
{
TAG_B,
TAG_I,
TAG_FONT,
TAG_SIZE,
TAG_COLOR,
TAG_IMGLEFT,
TAG_IMGRIGHT,
TAG_ICON
};
/**
* Set tag from string
*
* @param tagtype TagType by string, like 'IMG' for [IMG]
* @return True if m_TagType was set.
*/
bool SetTagType(const CStr &tagtype);
/**
* In [B=Hello][/B]
* m_TagType is TAG_B
*/
TagType m_TagType;
/**
* In [B=Hello][/B]
* m_TagValue is 'Hello'
*/
CStr m_TagValue;
};
/**
* m_From and m_To is the range of the string
*/
int m_From, m_To;
/**
* Tags that are present. [A][B]
*/
std::vector<Tag> m_Tags;
};
/**
* @author Gustav Larsson
*
* All data generated in GenerateTextCall()
*/
struct SFeedback
{
// Constants
const static int Left=0;
const static int Right=1;
/**
* Reset all member data.
*/
void Reset();
/**
* Image stacks, for left and right floating images.
*/
std::vector<CStr> m_Images[2]; // left and right
/**
* Text and Sprite Calls.
*/
std::vector<SGUIText::STextCall> m_TextCalls;
std::vector<SGUIText::SSpriteCall> m_SpriteCalls;
/**
* Width and Height *feedback*
*/
CSize m_Size;
/**
* If the word inputted was a new line.
*/
bool m_NewLine;
};
/**
* Set the value, the string will automatically
* be parsed when set.
*/
void SetValue(const CStr &str);
/**
* Get String, without tags
*/
CStr GetRawString() const { return m_RawString; }
/**
* Generate Text Call from specified range. The range
* must span only within ONE TextChunk though. Otherwise
* it can't be fit into a single Text Call
*
* Notice it won't make it complete, you will have to add
* X/Y values and such.
*
* @param Feedback contains all info that is generated.
* @param DefaultFont Default Font
* @param DefaultColor Default Color
* @param from From character n,
* @param to to chacter n.
*/
void GenerateTextCall(SFeedback &Feedback,
const CStr &DefaultFont, /*const CColor &DefaultColor,*/
const int &from, const int &to) const;
/**
* Words
*/
std::vector<int> m_Words;
/**
* TextChunks
*/
std::vector<TextChunk> m_TextChunks;
private:
/**
* The full raw string. Stripped of tags.
*/
CStr m_RawString;
};
#endif

View file

@ -10,6 +10,122 @@ gee@pyro.nu
using namespace std;
template <typename T>
bool __ParseString(const CStr &Value, T &tOutput)
{
// TODO Gee: Unsupported, report error/warning
return false;
}
template <>
bool __ParseString<bool>(const CStr &Value, bool &Output)
{
if (Value == CStr(_T("true")))
Output = true;
else
if (Value == CStr(_T("false")))
Output = false;
else
return false;
return true;
}
template <>
bool __ParseString<int>(const CStr &Value, int &Output)
{
Output = Value.ToInt();
return true;
}
template <>
bool __ParseString<float>(const CStr &Value, float &Output)
{
Output = Value.ToFloat();
return true;
}
template <>
bool __ParseString<CRect>(const CStr &Value, CRect &Output)
{
// Use the parser to parse the values
CParser parser;
parser.InputTaskType("", "_$value_$value_$value_$value_");
string str = (const TCHAR*)Value;
CParserLine line;
line.ParseString(parser, str);
if (!line.m_ParseOK)
{
// Parsing failed
return false;
}
int values[4];
for (int i=0; i<4; ++i)
{
if (!line.GetArgInt(i, values[i]))
{
// Parsing failed
return false;
}
}
// Finally the rectangle values
Output = CRect(values[0], values[1], values[2], values[3]);
return true;
}
template <>
bool __ParseString<CClientArea>(const CStr &Value, CClientArea &Output)
{
return Output.SetClientArea(Value);
}
template <>
bool __ParseString<CColor>(const CStr &Value, CColor &Output)
{
// Use the parser to parse the values
CParser parser;
parser.InputTaskType("", "_$value_$value_$value_[$value_]");
string str = (const TCHAR*)Value;
CParserLine line;
line.ParseString(parser, str);
if (!line.m_ParseOK)
{
// TODO Gee: Parsing failed
return false;
}
float values[4];
values[3] = 255.f; // default
for (int i=0; i<line.GetArgCount(); ++i)
{
if (!line.GetArgFloat(i, values[i]))
{
// TODO Gee: Parsing failed
return false;
}
}
Output.r = values[0]/255.f;
Output.g = values[1]/255.f;
Output.b = values[2]/255.f;
Output.a = values[3]/255.f;
return true;
}
template <>
bool __ParseString<CGUIString>(const CStr &Value, CGUIString &Output)
{
const char * buf = Value;
Output.SetValue(Value);
return true;
}
//--------------------------------------------------------
// Help Classes/Structs for the GUI implementation
//--------------------------------------------------------
@ -177,11 +293,6 @@ void CInternalCGUIAccessorBase::QueryResetting(IGUIObject *pObject)
GUI<>::RecurseObject(0, pObject, &IGUIObject::ResetStates);
}
void * CInternalCGUIAccessorBase::GetStructPointer(IGUIObject *pObject, const EGUISettingsStruct &SettingsStruct)
{
return pObject->GetStructPointer(SettingsStruct);
}
void CInternalCGUIAccessorBase::HandleMessage(IGUIObject *pObject, const SGUIMessage &message)
{
pObject->HandleMessage(message);

View file

@ -23,40 +23,39 @@ gee@pyro.nu
//--------------------------------------------------------
#include "GUI.h"
#include "Parser.h"
// TODO Gee: New
#include "Overlay.h"
//--------------------------------------------------------
// Help Classes/Structs for the GUI
//--------------------------------------------------------
// TEMP
struct CRect
{
CRect() {}
CRect(int _l, int _t, int _r, int _b) :
left(_l),
top(_t),
right(_r),
bottom(_b) {}
int bottom, top, left, right;
bool operator ==(const CRect &rect) const
{
return (bottom==rect.bottom) &&
(top==rect.top) &&
(left==rect.left) &&
(right==rect.right);
}
class CClientArea;
class CGUIString;
bool operator !=(const CRect &rect) const
{
return !(*this==rect);
}
};
template <typename T>
bool __ParseString(const CStr &Value, T &tOutput);
// TEMP
struct CColor
{
float r, g, b, a;
};
template <>
bool __ParseString<bool>(const CStr &Value, bool &Output);
template <>
bool __ParseString<int>(const CStr &Value, int &Output);
template <>
bool __ParseString<float>(const CStr &Value, float &Output);
template <>
bool __ParseString<CRect>(const CStr &Value, CRect &Output);
template <>
bool __ParseString<CClientArea>(const CStr &Value, CClientArea &Output);
template <>
bool __ParseString<CColor>(const CStr &Value, CColor &Output);
template <>
bool __ParseString<CGUIString>(const CStr &Value, CGUIString &Output);
/**
* @author Gustav Larsson
@ -66,7 +65,7 @@ struct CColor
* You can input the whole value of the Client Area by
* string. Like used in the GUI.
*/
struct CClientArea
class CClientArea
{
public:
CClientArea();
@ -128,8 +127,6 @@ protected:
/// Wrapper for ResetStates
static void QueryResetting(IGUIObject *pObject);
static void * GetStructPointer(IGUIObject *pObject, const EGUISettingsStruct &SettingsStruct);
static void HandleMessage(IGUIObject *pObject, const SGUIMessage &message);
};
@ -167,13 +164,12 @@ public:
if (!pObject->SettingExists(Setting))
return PS_SETTING_FAIL;
// Set value
Value =
// *(T*)((size_t)pObject->GetStructPointer(pObject->GetSettingsInfo()[Setting].m_SettingsStruct) +
// pObject->GetSettingsInfo()[Setting].m_Offset);
*(T*)((size_t)GetStructPointer(pObject, pObject->GetSettingsInfo()[Setting].m_SettingsStruct) +
pObject->GetSettingsInfo()[Setting].m_Offset);
if (!pObject->m_Settings.find(Setting)->second.m_pSetting)
return PS_FAIL;
// Set value
Value = *(T*)pObject->m_Settings.find(Setting)->second.m_pSetting;
return PS_OK;
}
@ -196,11 +192,7 @@ public:
return PS_SETTING_FAIL;
// Set value
//*(T*)((size_t)pObject->GetStructPointer(pObject->GetSettingsInfo()[Setting].m_SettingsStruct) +
// pObject->GetSettingsInfo()[Setting].m_Offset) = Value;
*(T*)((size_t)GetStructPointer(pObject, pObject->GetSettingsInfo()[Setting].m_SettingsStruct) +
pObject->GetSettingsInfo()[Setting].m_Offset) = Value;
*(T*)pObject->m_Settings[Setting].m_pSetting = Value;
//
// Some settings needs special attention at change
@ -219,12 +211,24 @@ public:
//RecurseObject(0, pObject, IGUIObject::ResetStates);
}
//pObject->HandleMessage(SGUIMessage(GUIM_SETTINGS_UPDATED, Setting));
HandleMessage(pObject, SGUIMessage(GUIM_SETTINGS_UPDATED, Setting));
return PS_OK;
}
#ifdef g_GUI
/**
* Adapter that uses the singleton g_GUI
* Can safely be removed.
*/
static PS_RESULT GetSetting(
const CStr &Object,
const CStr &Setting, T &Value)
{
return GetSetting(g_GUI, Object, Setting, Value);
}
#endif // g_GUI
/**
* Retrieves a setting by settings name and object name
*
@ -246,6 +250,18 @@ public:
return GetSetting(pObject, Setting, Value);
}
#ifdef g_GUI
/**
* Adapter that uses the singleton g_GUI
* Can safely be removed.
*/
static PS_RESULT SetSetting(
const CStr &Object, const CStr &Setting, const T &Value)
{
return SetSetting(g_GUI, Object, Setting, Value);
}
#endif // g_GUI
/**
* Sets a value by setting and object name using a real
* datatype as input
@ -274,8 +290,36 @@ public:
return SetSetting(pObject, Setting, Value);
}
/**
* This will return the value of the first sprite if it's not null,
* if it is null, it will return the value of the second sprite, if
* that one is null, then null it is.
*
* @param prim Primary sprite that should be used
* @param sec Secondary sprite if Primary should fail
* @return Resulting string
*/
static CStr FallBackSprite(const CStr &prim, const CStr &sec)
{
// CStr() == empty string, null
return ((prim!=CStr())?(prim):(sec));
}
/**
* Same principle as FallBackSprite
*
* @param prim Primary color that should be used
* @param sec Secondary color if Primary should fail
* @return Resulting color
* @see FallBackSprite
*/
static CColor FallBackColor(const CColor &prim, const CColor &sec)
{
// CColor() == null.
return ((prim!=CColor())?(prim):(sec));
}
/**
* Sets a value by setting and object name using a real
* datatype as input.
@ -283,7 +327,6 @@ public:
* This is just a wrapper for _mem_ParseString() which really
* works the magic.
*
* @param Type type in string, like "float" or "client area"
* @param Value The value in string form, like "0 0 100% 100%"
* @param tOutput Parsed value of type T
* @return True at success.
@ -292,164 +335,10 @@ public:
*/
static bool ParseString(const CStr &Value, T &tOutput)
{
void *mem = NULL;
if (!_mem_ParseString(Value, mem))
return false;
// Copy from memory
tOutput = *(T*)mem;
free(mem);
// TODO Gee: Undefined type - maybe report in log
return true;
return __ParseString<T>(Value, tOutput);
}
private:
/**
* Input a value in string form, and it will output the result in
* Memory with type T.
*
* @param Type type in string, like "float" or "client area"
* @param Value The value in string form, like "0 0 100% 100%"
* @param Memory Should be NULL, will be constructed within the function.
* @return True at success.
*/
static bool _mem_ParseString(const CStr &Value, void *&Memory)
{
/* if (typeid(T) == typeid(CStr))
{
tOutput = Value;
return true;
}
else
*/ if (typeid(T) == typeid(bool))
{
bool _Value;
if (Value == CStr(_T("true")))
_Value = true;
else
if (Value == CStr(_T("false")))
_Value = false;
else
return false;
Memory = malloc(sizeof(bool));
memcpy(Memory, (const void*)&_Value, sizeof(bool));
return true;
}
else
if (typeid(T) == typeid(float))
{
float _Value = Value.ToFloat();
// TODO Gee: Okay float value!?
Memory = malloc(sizeof(float));
memcpy(Memory, (const void*)&_Value, sizeof(float));
return true;
}
else
if (typeid(T) == typeid(int))
{
int _Value = Value.ToInt();
// TODO Gee: Okay float value!?
Memory = malloc(sizeof(int));
memcpy(Memory, (const void*)&_Value, sizeof(int));
return true;
}
else
if (typeid(T) == typeid(CRect))
{
// Use the parser to parse the values
CParser parser;
parser.InputTaskType("", "_$value_$value_$value_$value_");
string str = (const TCHAR*)Value;
CParserLine line;
line.ParseString(parser, str);
if (!line.m_ParseOK)
{
// Parsing failed
return false;
}
int values[4];
for (int i=0; i<4; ++i)
{
if (!line.GetArgInt(i, values[i]))
{
// Parsing failed
return false;
}
}
// Finally the rectangle values
CRect _Value(values[0], values[1], values[2], values[3]);
Memory = malloc(sizeof(CRect));
memcpy(Memory, (const void*)&_Value, sizeof(CRect));
return true;
}
else
if (typeid(T) == typeid(CClientArea))
{
// Get Client Area
CClientArea _Value;
// Check if valid!
if (!_Value.SetClientArea(Value))
{
return false;
}
Memory = malloc(sizeof(CClientArea));
memcpy(Memory, (const void*)&_Value, sizeof(CClientArea));
return true;
}
else
if (typeid(T) == typeid(CColor))
{
// Use the parser to parse the values
CParser parser;
parser.InputTaskType("", "_$value_$value_$value_[$value_]");
string str = (const TCHAR*)Value;
CParserLine line;
line.ParseString(parser, str);
if (!line.m_ParseOK)
{
// TODO Gee: Parsing failed
return false;
}
float values[4];
values[3] = 255.f; // default
for (int i=0; i<line.GetArgCount(); ++i)
{
if (!line.GetArgFloat(i, values[i]))
{
// TODO Gee: Parsing failed
return false;
}
}
// Finally the rectangle values
CColor _Value;
// TODO Gee: Done better when CColor is sweeter
_Value.r = values[0]/255.f;
_Value.g = values[1]/255.f;
_Value.b = values[2]/255.f;
_Value.a = values[3]/255.f;
Memory = malloc(sizeof(CColor));
memcpy(Memory, (const void*)&_Value, sizeof(CColor));
return true;
}
// TODO Gee: Undefined type - maybe report in log
return false;
}
// templated typedef of function pointer
typedef void (IGUIObject::*void_Object_pFunction_argT)(const T &arg);
@ -553,17 +442,26 @@ private:
{
if (RR & GUIRR_HIDDEN)
{
if (pObject->GetBaseSettings().m_Hidden)
bool hidden;
GUI<bool>::GetSetting(pObject, "hidden", hidden);
if (hidden)
return true;
}
if (RR & GUIRR_DISABLED)
{
if (pObject->GetBaseSettings().m_Enabled)
bool enabled;
GUI<bool>::GetSetting(pObject, "enabled", enabled);
if (!enabled)
return true;
}
if (RR & GUIRR_GHOST)
{
if (pObject->GetBaseSettings().m_Ghost)
bool ghost;
GUI<bool>::GetSetting(pObject, "ghost", ghost);
if (ghost)
return true;
}

View file

@ -22,38 +22,26 @@ IGUIButtonBehavior::~IGUIButtonBehavior()
void IGUIButtonBehavior::HandleMessage(const SGUIMessage &Message)
{
// TODO Gee: easier access functions
switch (Message.type)
{
case GUIM_PREPROCESS:
m_Pressed = false;
break;
/* case GUIM_POSTPROCESS:
// Check if button has been pressed
if (m_Pressed)
{
// Now check if mouse is released, that means
// it's released outside, since GUIM_MOUSE_RELEASE_LEFT
// would've handled m_Pressed and reset it already
// Get input structure
/// if (GetGUI()->GetInput()->mRelease(NEMM_BUTTON1))
{
// Reset
m_Pressed = false;
}
}
break;
*/
case GUIM_MOUSE_PRESS_LEFT:
if (!GetBaseSettings().m_Enabled)
{
bool enabled;
GUI<bool>::GetSetting(this, "enabled", enabled);
if (!enabled)
break;
m_Pressed = true;
break;
} break;
case GUIM_MOUSE_RELEASE_LEFT:
if (!GetBaseSettings().m_Enabled)
{
bool enabled;
GUI<bool>::GetSetting(this, "enabled", enabled);
if (!enabled)
break;
if (m_Pressed)
@ -62,7 +50,7 @@ void IGUIButtonBehavior::HandleMessage(const SGUIMessage &Message)
// BUTTON WAS CLICKED
HandleMessage(GUIM_PRESSED);
}
break;
} break;
case GUIM_SETTINGS_UPDATED:
// If it's hidden, then it can't be pressed
@ -74,3 +62,59 @@ void IGUIButtonBehavior::HandleMessage(const SGUIMessage &Message)
break;
}
}
CColor IGUIButtonBehavior::ChooseColor()
{
CColor color, color_over, color_pressed, color_disabled;
// Yes, the object must possess these settings. They are standard
GUI<CColor>::GetSetting(this, "textcolor", color);
GUI<CColor>::GetSetting(this, "textcolor-over", color_over);
GUI<CColor>::GetSetting(this, "textcolor-pressed", color_pressed);
GUI<CColor>::GetSetting(this, "textcolor-disabled", color_disabled);
bool enabled;
GUI<bool>::GetSetting(this, "enabled", enabled);
if (!enabled)
{
return GUI<>::FallBackColor(color_disabled, color);
}
else
if (m_MouseHovering)
{
if (m_Pressed)
return GUI<>::FallBackColor(color_pressed, color);
else
return GUI<>::FallBackColor(color_over, color);
}
else return color;
}
void IGUIButtonBehavior::DrawButton(const CRect &rect,
const float &z,
const CStr &sprite,
const CStr &sprite_over,
const CStr &sprite_pressed,
const CStr &sprite_disabled)
{
if (GetGUI())
{
bool enabled;
GUI<bool>::GetSetting(this, "enabled", enabled);
if (!enabled)
{
GetGUI()->DrawSprite(GUI<>::FallBackSprite(sprite_disabled, sprite), z, rect);
}
else
if (m_MouseHovering)
{
if (m_Pressed)
GetGUI()->DrawSprite(GUI<>::FallBackSprite(sprite_pressed, sprite), z, rect);
else
GetGUI()->DrawSprite(GUI<>::FallBackSprite(sprite_over, sprite), z, rect);
}
else GetGUI()->DrawSprite(sprite, z, rect);
}
}

View file

@ -57,6 +57,34 @@ public:
*/
virtual void HandleMessage(const SGUIMessage &Message);
/**
* This is a function that lets a button being drawn,
* it regards if it's over, disabled, pressed and such.
* You input sprite names and area and it'll output
* it accordingly.
*
* This class is meant to be used manually in Draw()
*
* @param rect Rectangle in which the sprite should be drawn
* @param z Z-value
* @param sprite Sprite drawn when not pressed, hovered or disabled
* @param sprite_over Sprite drawn when m_MouseHovering is true
* @param sprite_pressed Sprite drawn when m_Pressed is true
* @param sprite_disabled Sprite drawn when "enabled" is false
*/
void DrawButton(const CRect &rect,
const float &z,
const CStr &sprite,
const CStr &sprite_over,
const CStr &sprite_pressed,
const CStr &sprite_disabled);
/**
* Choosing which color of the following according to
*/
CColor IGUIButtonBehavior::ChooseColor();
protected:
virtual void ResetStates()
{

View file

@ -14,16 +14,10 @@ gee@pyro.nu
using namespace std;
// Offsets
map_Settings IGUIObject::m_SettingsInfo;
//-------------------------------------------------------------------
// Implementation Macros
//-------------------------------------------------------------------
/*#define _GUI_ADD_OFFSET(type, str, var) \
SettingsInfo[str].m_Offset = offsetof(IGUIObject, m_BaseSettings) + offsetof(SGUIBaseSettings,var); \
SettingsInfo[str].m_Type = type;
*/
//-------------------------------------------------------------------
// Constructor / Destructor
//-------------------------------------------------------------------
@ -32,21 +26,38 @@ IGUIObject::IGUIObject() :
m_pParent(NULL),
m_MouseHovering(false)
{
// TODO Gee: Remove this when base object is excluded from the recursion routines.
m_BaseSettings.m_Hidden = false;
m_BaseSettings.m_Ghost = false;
m_BaseSettings.m_Enabled = true;
m_BaseSettings.m_Absolute = true;
AddSetting(GUIST_bool, "enabled");
AddSetting(GUIST_bool, "hidden");
AddSetting(GUIST_CClientArea, "size");
AddSetting(GUIST_CStr, "style");
AddSetting(GUIST_float, "z");
// AddSetting(GUIST_CGUIString, "caption");
AddSetting(GUIST_bool, "absolute");
AddSetting(GUIST_bool, "ghost");
// Static! Only done once
if (m_SettingsInfo.empty())
{
SetupBaseSettingsInfo(m_SettingsInfo);
}
// Setup important defaults
GUI<bool>::SetSetting(this, "hidden", false);
GUI<bool>::SetSetting(this, "ghost", false);
GUI<bool>::SetSetting(this, "enabled", true);
GUI<bool>::SetSetting(this, "absolute", true);
bool hidden=true;
GUI<bool>::GetSetting(this, "hidden", hidden);
int hej=23;
}
IGUIObject::~IGUIObject()
{
map<CStr, SGUISetting>::iterator it;
for (it = m_Settings.begin(); it != m_Settings.end(); ++it)
{
if (!it->second.m_pSetting)
delete it->second.m_pSetting;
}
}
//-------------------------------------------------------------------
@ -116,24 +127,36 @@ void IGUIObject::Destroy()
// Is there anything besides the children to destroy?
}
void IGUIObject::SetupBaseSettingsInfo(map_Settings &SettingsInfo)
// Notice if using this, the naming convention of GUIST_ should be strict.
#define CASE_TYPE(type) \
case GUIST_##type: \
m_Settings[Name].m_pSetting = new type(); \
break;
void IGUIObject::AddSetting(const EGUISettingType &Type, const CStr &Name)
{
/* _GUI_ADD_OFFSET("bool", "enabled", m_Enabled)
_GUI_ADD_OFFSET("bool", "hidden", m_Hidden)
_GUI_ADD_OFFSET("client area", "size", m_Size)
_GUI_ADD_OFFSET("string", "style", m_Style)
_GUI_ADD_OFFSET("float", "z", m_Z)
_GUI_ADD_OFFSET("string", "caption", m_Caption)
_GUI_ADD_OFFSET("bool", "absolute", m_Absolute)
*/
GUI_ADD_OFFSET_GENERIC(SettingsInfo, GUISS_BASE, SGUIBaseSettings, m_Enabled, "bool", "enabled")
GUI_ADD_OFFSET_GENERIC(SettingsInfo, GUISS_BASE, SGUIBaseSettings, m_Hidden, "bool", "hidden")
GUI_ADD_OFFSET_GENERIC(SettingsInfo, GUISS_BASE, SGUIBaseSettings, m_Size, "client area", "size")
GUI_ADD_OFFSET_GENERIC(SettingsInfo, GUISS_BASE, SGUIBaseSettings, m_Style, "string", "style")
GUI_ADD_OFFSET_GENERIC(SettingsInfo, GUISS_BASE, SGUIBaseSettings, m_Z, "float", "z")
GUI_ADD_OFFSET_GENERIC(SettingsInfo, GUISS_BASE, SGUIBaseSettings, m_Caption, "string", "caption")
GUI_ADD_OFFSET_GENERIC(SettingsInfo, GUISS_BASE, SGUIBaseSettings, m_Absolute, "bool", "absolute")
GUI_ADD_OFFSET_GENERIC(SettingsInfo, GUISS_BASE, SGUIBaseSettings, m_Ghost, "bool", "ghost")
// Is name already taken?
if (m_Settings.count(Name) >= 1)
return;
// Construct, and set type
m_Settings[Name].m_Type = Type;
switch (Type)
{
// Construct the setting.
CASE_TYPE(bool)
CASE_TYPE(int)
CASE_TYPE(float)
CASE_TYPE(CClientArea)
CASE_TYPE(CStr)
CASE_TYPE(CColor)
CASE_TYPE(CGUIString)
default:
// TODO Gee: Report in log, type is not recognized.
break;
}
}
bool IGUIObject::MouseOver()
@ -141,23 +164,12 @@ bool IGUIObject::MouseOver()
if(!GetGUI())
throw PS_NEEDS_PGUI;
u16 mouse_x = GetMouseX(),
mouse_y = GetMouseY();
return (mouse_x >= m_CachedActualSize.left &&
mouse_x <= m_CachedActualSize.right &&
mouse_y >= m_CachedActualSize.top &&
mouse_y <= m_CachedActualSize.bottom);
return m_CachedActualSize.PointInside(GetMousePos());
}
u16 IGUIObject::GetMouseX() const
CPos IGUIObject::GetMousePos() const
{
return ((GetGUI())?(GetGUI()->m_MouseX):0);
}
u16 IGUIObject::GetMouseY() const
{
return ((GetGUI())?(GetGUI()->m_MouseY):0);
return ((GetGUI())?(GetGUI()->m_MousePos):CPos());
}
void IGUIObject::UpdateMouseOver(IGUIObject * const &pMouseOver)
@ -190,12 +202,24 @@ void IGUIObject::UpdateMouseOver(IGUIObject * const &pMouseOver)
bool IGUIObject::SettingExists(const CStr &Setting) const
{
// Because GetOffsets will direct dynamically defined
// classes with polymorifsm to respective m_SettingsInfo
// classes with polymorifsm to respective ms_SettingsInfo
// we need to make no further updates on this function
// in derived classes.
return (GetSettingsInfo().count(Setting) == 1)?true:false;
//return (GetSettingsInfo().count(Setting) >= 1);
return (m_Settings.count(Setting) >= 1);
}
#define ADD_TYPE(type) \
else \
if (set.m_Type == GUIST_##type) \
{ \
type _Value; \
if (!GUI<type>::ParseString(Value, _Value)) \
throw PS_FAIL; \
\
GUI<type>::SetSetting(this, Setting, _Value); \
}
void IGUIObject::SetSetting(const CStr &Setting, const CStr &Value)
{
if (!SettingExists(Setting))
@ -204,48 +228,18 @@ void IGUIObject::SetSetting(const CStr &Setting, const CStr &Value)
}
// Get setting
SGUISetting set = GetSettingsInfo()[Setting];
SGUISetting set = m_Settings[Setting];
if (set.m_Type == CStr(_T("string")))
if (set.m_Type == GUIST_CStr)
{
GUI<CStr>::SetSetting(this, Setting, Value);
}
else
if (set.m_Type == CStr(_T("bool")))
{
bool _Value;
if (!GUI<bool>::ParseString(Value, _Value))
throw PS_FAIL;
GUI<bool>::SetSetting(this, Setting, _Value);
}
else
if (set.m_Type == CStr(_T("float")))
{
float _Value;
if (!GUI<float>::ParseString(Value, _Value))
throw PS_FAIL;
GUI<float>::SetSetting(this, Setting, _Value);
}
else
if (set.m_Type == CStr(_T("rect")))
{
CRect _Value;
if (!GUI<CRect>::ParseString(Value, _Value))
throw PS_FAIL;
GUI<CRect>::SetSetting(this, Setting, _Value);
}
else
if (set.m_Type == CStr(_T("client area")))
{
CClientArea _Value;
if (!GUI<CClientArea>::ParseString(Value, _Value))
throw PS_FAIL;
GUI<CClientArea>::SetSetting(this, Setting, _Value);
}
ADD_TYPE(bool, "bool")
ADD_TYPE(float, "float")
ADD_TYPE(int, "int")
ADD_TYPE(CColor, "color")
ADD_TYPE(CClientArea, "client area")
ADD_TYPE(CGUIString, "text")
else
{
throw PS_FAIL;
@ -285,28 +279,22 @@ IGUIObject *IGUIObject::GetParent() const
return m_pParent;
}
void * IGUIObject::GetStructPointer(const EGUISettingsStruct &SettingsStruct) const
{
switch (SettingsStruct)
{
case GUISS_BASE:
return (void*)&m_BaseSettings;
default:
// TODO Gee: report error
return NULL;
}
}
void IGUIObject::UpdateCachedSize()
{
bool absolute;
GUI<bool>::GetSetting(this, "absolute", absolute);
CClientArea ca;
GUI<CClientArea>::GetSetting(this, "size", ca);
// If absolute="false" and the object has got a parent,
// use its cached size instead of the screen. Notice
// it must have just been cached for it to work.
if (m_BaseSettings.m_Absolute == false && m_pParent)
m_CachedActualSize = m_BaseSettings.m_Size.GetClientArea( m_pParent->m_CachedActualSize );
if (absolute == false && m_pParent)
m_CachedActualSize = ca.GetClientArea(m_pParent->m_CachedActualSize);
else
m_CachedActualSize = m_BaseSettings.m_Size.GetClientArea( CRect(0, 0, g_xres, g_yres) );
m_CachedActualSize = ca.GetClientArea(CRect(0, 0, g_xres, g_yres));
}
void IGUIObject::LoadStyle(CGUI &GUIinstance, const CStr &StyleName)
@ -335,31 +323,39 @@ void IGUIObject::LoadStyle(const SGUIStyle &Style)
// since it's generic.
catch (PS_RESULT e)
{
// was ist das?
e;
// TODO Gee: was ist das?
}
}
}
float IGUIObject::GetBufferedZ() const
{
if (GetBaseSettings().m_Absolute)
return GetBaseSettings().m_Z;
bool absolute;
GUI<bool>::GetSetting(this, "absolute", absolute);
float Z;
GUI<float>::GetSetting(this, "z", Z);
if (absolute)
return Z;
else
{
if (GetParent())
return GetParent()->GetBufferedZ() + GetBaseSettings().m_Z;
return GetParent()->GetBufferedZ() + Z;
else
// TODO Gee: Error, no object should be relative with a parent!
return GetBaseSettings().m_Z;
// TODO Gee: Error, no object should be relative without a parent!
return Z;
}
}
// TODO Gee: keep this function and all???
void IGUIObject::CheckSettingsValidity()
{
bool hidden;
GUI<bool>::GetSetting(this, "hidden", hidden);
// If we hide an object, reset many of its parts
if (GetBaseSettings().m_Hidden)
if (hidden)
{
// Simulate that no object is hovered for this object and all its children
// why? because it's

View file

@ -63,17 +63,39 @@ typedef std::map<CStr, SGUISetting> map_Settings;
enum EAlign { EAlign_Left, EAlign_Right, EAlign_Center };
enum EValign { EValign_Top, EValign_Bottom, EValign_Center };
/**
* Setting Type
* @see SGUISetting
*
* For use of later macros, all names should be GUIST_ followed
* by the code name (case sensitive!).
*/
enum EGUISettingType
{
GUIST_bool,
GUIST_int,
GUIST_float,
GUIST_CColor,
GUIST_CClientArea,
GUIST_CGUIString,
GUIST_CStr
};
/**
* @author Gustav Larsson
*
* Stores the information where to find a variable
* in a GUI-Object object, also what type it is.
* A GUI Setting is anything that can be inputted from XML as
* <object>-attributes (with exceptions). For instance:
* <object style="null">
*
* "style" will be a SGUISetting.
*/
struct SGUISetting
{
size_t m_Offset; // The offset from IGUIObject to the variable (not from SGUIBaseSettings or similar)
EGUISettingsStruct m_SettingsStruct;
CStr m_Type; // "string" or maybe "int"
SGUISetting() : m_pSetting(NULL) {}
void *m_pSetting;
EGUISettingType m_Type;
};
/**
@ -83,8 +105,9 @@ struct SGUISetting
* in their m_BaseSettings
* Instructions can be found in the documentations.
*/
struct SGUIBaseSettings
/*struct SGUIBaseSettings
{
//int banan;
bool m_Absolute;
CStr m_Caption; // Is usually set within an XML element and not in the attributes
bool m_Enabled;
@ -93,7 +116,7 @@ struct SGUIBaseSettings
CClientArea m_Size;
CStr m_Style;
float m_Z;
};
};*/
//////////////////////////////////////////////////////////
@ -108,22 +131,11 @@ class IGUIObject
friend class CGUI;
friend class CInternalCGUIAccessorBase;
friend class IGUIScrollBar;
#ifndef _MSC_VER
template <class T>
#endif
friend class GUI;
public:
IGUIObject();
virtual ~IGUIObject();
/**
* Get offsets
*
* @return Retrieves settings info
*/
virtual map_Settings GetSettingsInfo() const { return m_SettingsInfo; }
/**
* Checks if mouse is hovering this object.
* The mouse position is cached in CGUI.
@ -193,8 +205,6 @@ public:
//--------------------------------------------------------
//@{
SGUIBaseSettings GetBaseSettings() const { return m_BaseSettings; }
/**
* Checks if settings exists, only available for derived
* classes that has this set up, that's why the base
@ -231,7 +241,7 @@ public:
*
* @param SettingsInfo Pointers that should be filled with base variables
*/
void SetupBaseSettingsInfo(map_Settings &SettingsInfo);
//void SetupBaseSettingsInfo(map_Settings &SettingsInfo);
/**
* Set a setting by string, regardless of what type it is.
@ -259,6 +269,14 @@ protected:
//--------------------------------------------------------
//@{
/**
* Add a setting to m_Settings
*
* @param Type Setting type
* @param Name Setting reference name
*/
void AddSetting(const EGUISettingType &Type, const CStr &Name);
/**
* Calls Destroy on all children, and deallocates all memory.
* MEGA TODO Should it destroy it's children?
@ -271,7 +289,7 @@ protected:
*
* @param Message GUI Message
*/
virtual void HandleMessage(const SGUIMessage &Message)=0;
virtual void HandleMessage(const SGUIMessage &Message) {};
/**
* Draws the object.
@ -305,7 +323,7 @@ protected:
*
* @return Actual Z value on the screen.
*/
float GetBufferedZ() const;
virtual float GetBufferedZ() const;
// This is done internally
CGUI *GetGUI() { return m_pGUI; }
@ -342,11 +360,12 @@ protected:
*
* @param SettingsStruct tells us which pointer ot return
*/
virtual void *GetStructPointer(const EGUISettingsStruct &SettingsStruct) const;
//virtual void *GetStructPointer(const EGUISettingsStruct &SettingsStruct) const;
// Get cached mouse x/y from CGUI
u16 GetMouseX() const;
u16 GetMouseY() const;
/**
* Get Mouse from CGUI.
*/
CPos GetMousePos() const;
/**
* Cached size, real size m_Size is actually dependent on resolution
@ -402,7 +421,7 @@ protected:
IGUIObject *m_pParent;
/// Base settings
SGUIBaseSettings m_BaseSettings;
//SGUIBaseSettings m_BaseSettings;
/**
* This is an array of true or false, each element is associated with
@ -429,7 +448,18 @@ protected:
* <b>note!</b> @uNOT from SGUIBaseSettings to
* m_Frozen!
*/
static map_Settings m_SettingsInfo;
//static map_Settings ms_SettingsInfo;
/**
* Settings pool, all an object's settings are located here
* If a derived object has got more settings that the base
* settings, it's becasue they have a new version of the
* function SetupSettings().
*
* @see SetupSettings()
*/
public:
std::map<CStr, SGUISetting> m_Settings;
private:
/// An object can't function stand alone
@ -441,10 +471,13 @@ private:
* @author Gustav Larsson
*
* Dummy object used primarily for the root object
* which isn't a *real* object in the GUI.
* or objects of type 'empty'
*/
class CGUIDummyObject : public IGUIObject
{
GUI_OBJECT(CGUIDummyObject)
public:
virtual void HandleMessage(const SGUIMessage &Message) {}
virtual void Draw() {}
};

View file

@ -12,7 +12,18 @@ using namespace std;
//-------------------------------------------------------------------
// IGUIScrollBar
//-------------------------------------------------------------------
IGUIScrollBar::IGUIScrollBar() : m_pStyle(NULL), m_X(300), m_Y(300), m_Length(200), m_Width(20), m_BarSize(0.5), m_Pos(0.5)
IGUIScrollBar::IGUIScrollBar() : m_pStyle(NULL), m_pGUI(NULL),
m_X(300), m_Y(300),
m_ScrollRange(1), m_ScrollSpace(0), // MaxPos: not 0, due to division.
m_Length(200), m_Width(20),
m_BarSize(0.5), m_Pos(0),
m_UseEdgeButtons(true),
m_ButtonPlusPressed(false),
m_ButtonMinusPressed(false),
m_ButtonPlusHovered(false),
m_ButtonMinusHovered(false),
m_BarHovered(false),
m_BarPressed(false)
{
}
@ -20,72 +31,122 @@ IGUIScrollBar::~IGUIScrollBar()
{
}
const SGUIScrollBarStyle & IGUIScrollBar::GetStyle() const
void IGUIScrollBar::SetupBarSize()
{
m_BarSize = min((float)m_ScrollSpace/(float)m_ScrollRange, 1.f);
}
const SGUIScrollBarStyle *IGUIScrollBar::GetStyle() const
{
if (!m_pHostObject)
return SGUIScrollBarStyle();
return NULL;
return m_pHostObject->GetScrollBarStyle(m_ScrollBarStyle);
}
void IGUIScrollBar::UpdatePosBoundaries()
{
if (m_Pos > 1.f)
m_Pos = 1.f;
else
if (m_Pos < 0.f)
m_Pos = 0.f;
CGUI *IGUIScrollBar::GetGUI() const
{
if (!m_pHostObject)
return NULL;
return m_pHostObject->GetGUI();
}
bool IGUIScrollBar::HandleMessage(const SGUIMessage &Message)
void IGUIScrollBar::UpdatePosBoundaries()
{
if (m_Pos < 0 ||
m_ScrollRange < m_ScrollSpace) // <= scrolling not applicable
m_Pos = 0;
else
if (m_Pos > m_ScrollRange - m_ScrollSpace)
m_Pos = m_ScrollRange - m_ScrollSpace;
}
void IGUIScrollBar::HandleMessage(const SGUIMessage &Message)
{
switch (Message.type)
{
case GUIM_MOUSE_MOTION:
if (m_BarPressed)
{
SetPosFromMousePos(m_pHostObject->GetMouseX(), m_pHostObject->GetMouseY());
UpdatePosBoundaries();
}
break;
// TODO Gee: Optimizations needed!
CPos mouse = m_pHostObject->GetMousePos();
// If bar is being dragged
if (m_BarPressed)
{
SetPosFromMousePos(mouse);
UpdatePosBoundaries();
}
CRect bar_rect = GetBarRect();
// check if components are being hovered
m_BarHovered = bar_rect.PointInside(mouse);
m_ButtonMinusHovered = HoveringButtonMinus(m_pHostObject->GetMousePos());
m_ButtonPlusHovered = HoveringButtonPlus(m_pHostObject->GetMousePos());
if (!m_ButtonMinusHovered)
m_ButtonMinusPressed = false;
if (!m_ButtonPlusHovered)
m_ButtonPlusPressed = false;
} break;
case GUIM_MOUSE_PRESS_LEFT:
{
if (!m_pHostObject)
break;
int mouse_x = m_pHostObject->GetMouseX(),
mouse_y = m_pHostObject->GetMouseY();
CPos mouse = m_pHostObject->GetMousePos();
// if bar is pressed
if (mouse_x >= GetBarRect().left &&
mouse_x <= GetBarRect().right &&
mouse_y >= GetBarRect().top &&
mouse_y <= GetBarRect().bottom)
if (GetBarRect().PointInside(mouse))
{
m_BarPressed = true;
m_BarPressedAtX = mouse_x;
m_BarPressedAtY = mouse_y;
m_BarPressedAtPos = mouse;
m_PosWhenPressed = m_Pos;
}
else
// if button-minus is pressed
if (HoveringButtonMinus(mouse_x, mouse_y))
if (m_ButtonMinusHovered)
{
m_ButtonMinusPressed = true;
ScrollMinus();
}
else
// if button-plus is pressed
if (HoveringButtonPlus(mouse_x, mouse_y))
if (m_ButtonPlusHovered)
{
m_ButtonPlusPressed = true;
ScrollPlus();
}
}
else
// Pressing the background of the bar, to scroll
// notice the if-sentence alone does not admit that,
// it must be after the above if/elses
{
if (GetOuterRect().PointInside(mouse))
{
// Scroll plus or minus a lot, this might change, it doesn't
// have to be fancy though.
if (mouse.y < GetBarRect().top)
ScrollMinusPlenty();
else
ScrollPlusPlenty();
// Simulate mouse movement to see if bar now is hovered
HandleMessage(SGUIMessage(GUIM_MOUSE_MOTION));
}
}
} break;
case GUIM_MOUSE_RELEASE_LEFT:
m_ButtonMinusPressed = false;
m_ButtonPlusPressed = false;
break;
default:
return false;
break;
}
return true;
}

View file

@ -86,13 +86,18 @@ struct SGUIScrollBarStyle
CStr m_SpriteButtonTop;
CStr m_SpriteButtonTopPressed;
CStr m_SpriteButtonTopDisabled;
CStr m_SpriteButtonTopOver;
CStr m_SpriteButtonBottom;
CStr m_SpriteButtonBottomPressed;
CStr m_SpriteButtonBottomDisabled;
CStr m_SpriteButtonBottomOver;
CStr m_SpriteScrollBackHorizontal;
CStr m_SpriteScrollBarHorizontal;
CStr m_SpriteBarVertical;
CStr m_SpriteBarVerticalOver;
CStr m_SpriteBarVerticalPressed;
CStr m_SpriteBackVertical;
//@}
//--------------------------------------------------------
@ -108,8 +113,8 @@ struct SGUIScrollBarStyle
CStr m_SpriteButtonRightPressed;
CStr m_SpriteButtonRightDisabled;
CStr m_SpriteScrollBackVertical;
CStr m_SpriteScrollBarVertical;
CStr m_SpriteBackHorizontal;
CStr m_SpriteBarHorizontal;
//@}
};
@ -151,12 +156,12 @@ public:
* @return true if messages handled the scroll-bar some. False if
* the message should be processed by the object.
*/
virtual bool HandleMessage(const SGUIMessage &Message)=0;
virtual void HandleMessage(const SGUIMessage &Message)=0;
/**
* Set m_Pos with mouse_x/y input, i.e. when draggin.
*/
virtual void SetPosFromMousePos(int _x, int _y)=0;
virtual void SetPosFromMousePos(const CPos &mouse)=0;
/**
* Hovering the scroll minus button
@ -165,7 +170,7 @@ public:
* @param m_y mouse y
* @return True if mouse positions are hovering the button
*/
virtual bool HoveringButtonMinus(int m_x, int m_y) { return false; }
virtual bool HoveringButtonMinus(const CPos &mouse) { return false; }
/**
* Hovering the scroll plus button
@ -174,17 +179,32 @@ public:
* @param m_y mouse y
* @return True if mouse positions are hovering the button
*/
virtual bool HoveringButtonPlus(int m_x, int m_y) { return false; }
virtual bool HoveringButtonPlus(const CPos &mouse) { return false; }
/**
* Get scroll-position
*/
int GetPos() const { return m_Pos; }
/**
* Scroll towards 1.0 one step
*/
virtual void ScrollPlus() { m_Pos += 0.1f; UpdatePosBoundaries(); }
virtual void ScrollPlus() { m_Pos += 30; UpdatePosBoundaries(); }
/**
* Scroll towards 0.0 one step
*/
virtual void ScrollMinus() { m_Pos -= 0.1f; UpdatePosBoundaries(); }
virtual void ScrollMinus() { m_Pos -= 30; UpdatePosBoundaries(); }
/**
* Scroll towards 1.0 one step
*/
virtual void ScrollPlusPlenty() { m_Pos += 90; UpdatePosBoundaries(); }
/**
* Scroll towards 0.0 one step
*/
virtual void ScrollMinusPlenty() { m_Pos -= 90; UpdatePosBoundaries(); }
/**
* Set host object, must be done almost at creation of scroll bar.
@ -192,6 +212,18 @@ public:
*/
void SetHostObject(IGUIScrollBarOwner * pOwner) { m_pHostObject = pOwner; }
/**
* Get GUI pointer
* @return CGUI pointer
*/
CGUI *GetGUI() const;
/**
* Set GUI pointer
* @param pGUI pointer to CGUI object.
*/
void SetGUI(CGUI *pGUI) { m_pGUI = pGUI; }
/**
* Set Width
* @param width Width
@ -202,25 +234,37 @@ public:
* Set X Position
* @param x Position in this axis
*/
void SetX(const int &x) {m_X = x; }
void SetX(const int &x) { m_X = x; }
/**
* Set Y Position
* @param y Position in this axis
*/
void SetY(const int &y) {m_Y = y; }
void SetY(const int &y) { m_Y = y; }
/**
* Set Z Position
* @param z Position in this axis
*/
void SetZ(const float &z) {m_Z = z; }
void SetZ(const float &z) { m_Z = z; }
/**
* Set Length of scroll bar
* @param length Length
*/
void SetLength(const float &length) {m_Length = length; }
void SetLength(const int &length) { m_Length = length; }
/**
* Set content length
* @param range Maximum scrollable range
*/
void SetScrollRange(const int &range) { m_ScrollRange = max(range,1); SetupBarSize(); }
/**
* Set space that is visible in the scrollable control.
* @param space Visible area in the scrollable control.
*/
void SetScrollSpace(const int &space) { m_ScrollSpace = space; SetupBarSize(); }
/**
* Set bar pressed
@ -228,23 +272,42 @@ public:
*/
void SetBarPressed(const bool &b) { m_BarPressed = b; }
/**
* Set use edge buttons
* @param b True if edge buttons should be used
*/
void SetUseEdgeButtons(const bool &b) { m_UseEdgeButtons = b; }
/**
* Set Scroll bar style string
* @param style String with scroll bar style reference name
*/
void SetScrollBarStyle(const CStr &style) { m_ScrollBarStyle = style; }
protected:
/**
* Get the rectangle of the actual BAR. not the whole scroll-bar.
*/
virtual CRect GetBarRect() const = 0;
/**
* Get style used by the scrollbar
* @return Scroll bar style struct.
*/
const SGUIScrollBarStyle & GetStyle() const;
const SGUIScrollBarStyle * GetStyle() const;
protected:
/**
* Sets up bar size
*/
void SetupBarSize();
/**
* Get the rectangle of the actual BAR. not the whole scroll-bar.
* @return Rectangle, CRect
*/
virtual CRect GetBarRect() const = 0;
/**
* Get the rectangle of the outline of the scrollbar, every component of the
* scroll-bar should be inside this area.
* @return Rectangle, CRect
*/
virtual CRect GetOuterRect() const = 0;
/**
* Call every time m_Pos has been updated.
@ -258,10 +321,16 @@ protected:
//--------------------------------------------------------
//@{
/**
* True if you want edge buttons, i.e. buttons that can be pressed in order
* to scroll.
*/
bool m_UseEdgeButtons;
/**
* Width of the scroll bar
*/
int16 m_Width;
int m_Width;
/**
* Absolute X Position
@ -283,6 +352,16 @@ protected:
*/
int m_Length;
/**
* Content that can be scrolled, in pixels
*/
int m_ScrollRange;
/**
* Content that can be viewed at a time, in pixels
*/
int m_ScrollSpace;
/**
* Use input from the scroll-wheel? True or false.
*/
@ -303,10 +382,15 @@ protected:
*/
IGUIScrollBarOwner *m_pHostObject;
/**
* Reference to CGUI object, these cannot work stand-alone
*/
CGUI *m_pGUI;
/**
* Mouse position when bar was pressed
*/
int m_BarPressedAtX, m_BarPressedAtY;
CPos m_BarPressedAtPos;
//@}
//--------------------------------------------------------
@ -320,10 +404,26 @@ protected:
bool m_BarPressed;
/**
* Position of scroll bar, 0 means scrolled all the way to one side... 1 means
* scrolled all the way to the other side.
* Bar being hovered or not
*/
float m_Pos;
bool m_BarHovered;
/**
* Scroll buttons hovered
*/
bool m_ButtonMinusHovered, m_ButtonPlusHovered;
/**
* Scroll buttons pressed
*/
bool m_ButtonMinusPressed, m_ButtonPlusPressed;
/**
* Position of scroll bar, 0 means scrolled all the way to one side.
* It is meassured in pixels, it is up to the host to make it actually
* apply in pixels.
*/
int m_Pos;
/**
* Position from 0.f to 1.f it had when the bar was pressed.

View file

@ -40,24 +40,31 @@ void IGUIScrollBarOwner::ResetStates()
void IGUIScrollBarOwner::AddScrollBar(IGUIScrollBar * scrollbar)
{
scrollbar->SetHostObject(this);
scrollbar->SetGUI(GetGUI());
m_ScrollBars.push_back(scrollbar);
}
const SGUIScrollBarStyle & IGUIScrollBarOwner::GetScrollBarStyle(const CStr &style) const
/*
void SetGUI(CGUI * const &pGUI)
{
m_pGUI = pGUI;
scrollbar->SetGUI(m_pGUI);
}
*/
const SGUIScrollBarStyle * IGUIScrollBarOwner::GetScrollBarStyle(const CStr &style) const
{
if (!GetGUI())
{
// TODO Gee: Output in log
return SGUIScrollBarStyle();
return NULL;
}
if (GetGUI()->m_ScrollBarStyles.count(style) == 0)
{
// TODO Gee: Output in log
return SGUIScrollBarStyle();
return NULL;
}
return GetGUI()->m_ScrollBarStyles.find(style)->second;
return &GetGUI()->m_ScrollBarStyles.find(style)->second;
}
void IGUIScrollBarOwner::HandleMessage(const SGUIMessage &Message)

View file

@ -46,6 +46,8 @@ struct SGUIScrollBarStyle;
*/
class IGUIScrollBarOwner : virtual public IGUIObject
{
friend class IGUIScrollBar;
public:
IGUIScrollBarOwner();
virtual ~IGUIScrollBarOwner();
@ -65,7 +67,7 @@ public:
/**
* Interface for the m_ScrollBar to use.
*/
virtual const SGUIScrollBarStyle & GetScrollBarStyle(const CStr &style) const;
virtual const SGUIScrollBarStyle *GetScrollBarStyle(const CStr &style) const;
/**
* Add a scroll-bar

View file

@ -1,11 +0,0 @@
/*
IGUISettingsObject
by Gustav Larsson
gee@pyro.nu
*/
//#include "stdafx.h"
#include "GUI.h"
using namespace std;

View file

@ -1,146 +0,0 @@
/*
GUI Object Base - Setting Extension
by Gustav Larsson
gee@pyro.nu
--Overview--
Generic object that stores a struct with settings
--Usage--
If an object wants settings with a standard,
it will use this as a middle step instead of being
directly derived from IGUIObject
--Examples--
instead of:
class CButton : public IGUIObject
you go:
class CButton : public IGUISettingsObject<SButtonSettings>
and SButtonSettings will be included as m_Settings with
all gets and sets set up
--More info--
Check GUI.h
*/
#ifndef IGUISettingsObject_H
#define IGUISettingsObject_H
//--------------------------------------------------------
// Includes / Compiler directives
//--------------------------------------------------------
#include "GUI.h"
//--------------------------------------------------------
// Macros
//--------------------------------------------------------
//--------------------------------------------------------
// Types
//--------------------------------------------------------
//--------------------------------------------------------
// Error declarations
//--------------------------------------------------------
//--------------------------------------------------------
// Declarations
//--------------------------------------------------------
/**
* @author Gustav Larsson
*
* Appends more settings to the IGUIObject.
* Can be used with multiple inheritance.
*
* @see IGUIObject
*/
template <typename SETTINGS>
class IGUISettingsObject : virtual public IGUIObject
{
public:
IGUISettingsObject() {}
virtual ~IGUISettingsObject() {}
/**
* Get Offsets, <b>important</b> to include so it returns this
* m_Offsets and not IGUIObject::m_SettingsInfo
*
* @return Settings infos
*/
virtual map_Settings GetSettingsInfo() const { return m_SettingsInfo; }
/**
* @return Returns a copy of m_Settings
*/
SETTINGS GetSettings() const { return m_Settings; }
/// Sets settings
void SetSettings(const SETTINGS &Set)
{
m_Settings = Set;
//CheckSettingsValidity();
// Since that function out-commented above really
// does just update the base settings, we'll call
// the message immediately instead
try
{
HandleMessage(GUIM_SETTINGS_UPDATED);
}
catch (...) { }
}
protected:
/**
* You input the setting struct you want, and it will return a pointer to
* the struct.
*
* @param SettingsStruct tells us which pointer to return
*/
virtual void *GetStructPointer(const EGUISettingsStruct &SettingsStruct) const
{
switch (SettingsStruct)
{
case GUISS_BASE:
return (void*)&m_BaseSettings;
case GUISS_EXTENDED:
return (void*)&m_Settings;
default:
// TODO Gee: Report error
return NULL;
}
}
/// Settings struct
SETTINGS m_Settings;
/**
* <b>Offset database</b>\n
* tells us where a variable by a string name is
* located hardcoded, in order to acquire a pointer
* for that variable... Say "frozen" gives
* the offset from IGUIObject to m_Frozen.
*
* <b>note!</b> _NOT_ from SGUIBaseSettings to m_Frozen!
*
* Note that it's imperative that this m_SettingsInfo includes
* all offsets of m_BaseSettings too, because when
* using this class, this m_SettingsInfo will be the only
* one used.
*/
static map_Settings m_SettingsInfo;
};
#endif

73
source/gui/IGUITextOwner.cpp Executable file
View file

@ -0,0 +1,73 @@
/*
IGUITextOwner
by Gustav Larsson
gee@pyro.nu
*/
//#include "stdafx.h"
#include "GUI.h"
using namespace std;
//-------------------------------------------------------------------
// Constructor / Destructor
//-------------------------------------------------------------------
IGUITextOwner::IGUITextOwner()
{
}
IGUITextOwner::~IGUITextOwner()
{
// Delete scroll-bars
vector<SGUIText*>::iterator it;
for (it=m_GeneratedTexts.begin(); it!=m_GeneratedTexts.end(); ++it)
{
delete *it;
}
}
void IGUITextOwner::AddText(SGUIText * text)
{
m_GeneratedTexts.push_back(text);
}
void IGUITextOwner::HandleMessage(const SGUIMessage &Message)
{
switch (Message.type)
{
case GUIM_SETTINGS_UPDATED:
// Everything that can change the visual appearance.
// it is assumed that the text of the object will be dependent on
// these. But that is not certain, but one will have to manually
// change it and disregard this function.
if (Message.value == CStr("size") || Message.value == CStr("z") ||
Message.value == CStr("absolute") || Message.value == CStr("caption") ||
Message.value == CStr("font") || Message.value == CStr("textcolor"))
{
SetupText();
}
break;
case GUIM_LOAD:
SetupText();
break;
default:
break;
}
}
void IGUITextOwner::Draw(const int &index, const CColor &color, const CPos &pos,
const float &z, const CRect &clipping)
{
if (index < 0 && index >= m_GeneratedTexts.size())
{
// TODO Gee: Warning
return;
}
if (GetGUI())
{
GetGUI()->DrawText(*m_GeneratedTexts[index], color, pos, z);
}
}

88
source/gui/IGUITextOwner.h Executable file
View file

@ -0,0 +1,88 @@
/*
GUI Object Base - Text Owner
by Gustav Larsson
gee@pyro.nu
--Overview--
Interface class that enhance the IGUIObject with
cached CGUIStrings. This class is not at all needed,
and many controls that will use CGUIStrings might
not use this, but does help for regular usage such
as a text-box, a button, a radio button etc.
--More info--
Check GUI.h
*/
#ifndef IGUITextOwner_H
#define IGUITextOwner_H
//--------------------------------------------------------
// Includes / Compiler directives
//--------------------------------------------------------
#include "GUI.h"
//--------------------------------------------------------
// Macros
//--------------------------------------------------------
//--------------------------------------------------------
// Types
//--------------------------------------------------------
//--------------------------------------------------------
// Declarations
//--------------------------------------------------------
/**
* @author Gustav Larsson
*
* Framework for handling Output text.
*
* @see IGUIObject
*/
class IGUITextOwner : virtual public IGUIObject
{
public:
IGUITextOwner();
virtual ~IGUITextOwner();
/**
* Adds a text object.
*/
void AddText(SGUIText * text);
/**
* @see IGUIObject#HandleMessage()
*/
virtual void HandleMessage(const SGUIMessage &Message);
/**
* Draws the Text.
*
* @param index Index value of text. Mostly this will be 0
* @param pos Position
* @param z Z value
* @param clipping Clipping rectangle, don't even add a paramter
* to get no clipping.
*/
virtual void Draw(const int &index, const CColor &color, const CPos &pos,
const float &z, const CRect &clipping = CRect());
protected:
/**
* Setup texts. Functions that sets up all texts when changes have been made.
*/
virtual void SetupText()=0;
/**
* Texts that are generated and ready to be rendred.
*/
std::vector<SGUIText*> m_GeneratedTexts;
};
#endif