1
0
forked from 0ad/0ad

Remove virtual inheritance from the codebase, refs 6b51d71c85, e21ebb37f5 e326ebae46.

Remove workaround in 3d07327837 / D2136, the pointer from IGUIObject to
IGUITextOwner that avoided the dynamic_cast.
Have the GUIObject implementing class take responsibility of calling the
virtual methods in the base classes.
Leaves the code in a clean state that can serve as an example for new
GUI object classes, such as D1346, refs #4683.

Differential Revision: https://code.wildfiregames.com/D2325
Comments By: Vladislav on IRC 2019-07-30, 2019-08-22, 2019-09-20-23
Tested on: clang 8.0.1, Jenkins

This was SVN commit r23020.
This commit is contained in:
elexis 2019-09-30 14:08:14 +00:00
parent 1679510bb8
commit 8190293f8b
31 changed files with 293 additions and 250 deletions

View File

@ -25,8 +25,8 @@
CButton::CButton(CGUI& pGUI) CButton::CButton(CGUI& pGUI)
: IGUIObject(pGUI), : IGUIObject(pGUI),
IGUIButtonBehavior(pGUI), IGUIButtonBehavior(*static_cast<IGUIObject*>(this)),
IGUITextOwner(pGUI), IGUITextOwner(*static_cast<IGUIObject*>(this)),
m_BufferZone(), m_BufferZone(),
m_CellID(), m_CellID(),
m_Caption(), m_Caption(),
@ -72,9 +72,21 @@ void CButton::SetupText()
CalculateTextPosition(m_CachedActualSize, m_TextPos, m_GeneratedTexts[0]); CalculateTextPosition(m_CachedActualSize, m_TextPos, m_GeneratedTexts[0]);
} }
void CButton::ResetStates()
{
IGUIObject::ResetStates();
IGUIButtonBehavior::ResetStates();
}
void CButton::UpdateCachedSize()
{
IGUIObject::UpdateCachedSize();
IGUITextOwner::UpdateCachedSize();
}
void CButton::HandleMessage(SGUIMessage& Message) void CButton::HandleMessage(SGUIMessage& Message)
{ {
// Important IGUIObject::HandleMessage(Message);
IGUIButtonBehavior::HandleMessage(Message); IGUIButtonBehavior::HandleMessage(Message);
IGUITextOwner::HandleMessage(Message); IGUITextOwner::HandleMessage(Message);
} }

View File

@ -24,7 +24,7 @@
#include "gui/CGUISprite.h" #include "gui/CGUISprite.h"
#include "gui/CGUIString.h" #include "gui/CGUIString.h"
class CButton : public IGUIButtonBehavior, public IGUITextOwner class CButton : public IGUIObject, public IGUITextOwner, public IGUIButtonBehavior
{ {
GUI_OBJECT(CButton) GUI_OBJECT(CButton)
@ -35,7 +35,12 @@ public:
/** /**
* @see IGUIObject#ResetStates() * @see IGUIObject#ResetStates()
*/ */
virtual void ResetStates() { IGUIButtonBehavior::ResetStates(); } virtual void ResetStates();
/**
* @see IGUIObject#UpdateCachedSize()
*/
virtual void UpdateCachedSize();
/** /**
* @see IGUIObject#HandleMessage() * @see IGUIObject#HandleMessage()

View File

@ -32,7 +32,7 @@
CChart::CChart(CGUI& pGUI) CChart::CChart(CGUI& pGUI)
: IGUIObject(pGUI), : IGUIObject(pGUI),
IGUITextOwner(pGUI), IGUITextOwner(*static_cast<IGUIObject*>(this)),
m_AxisColor(), m_AxisColor(),
m_AxisWidth(), m_AxisWidth(),
m_BufferZone(), m_BufferZone(),
@ -58,8 +58,17 @@ CChart::~CChart()
{ {
} }
void CChart::UpdateCachedSize()
{
IGUIObject::UpdateCachedSize();
IGUITextOwner::UpdateCachedSize();
}
void CChart::HandleMessage(SGUIMessage& Message) void CChart::HandleMessage(SGUIMessage& Message)
{ {
IGUIObject::HandleMessage(Message);
// IGUITextOwner::HandleMessage(Message); performed in UpdateSeries
// TODO: implement zoom // TODO: implement zoom
switch (Message.type) switch (Message.type)
{ {

View File

@ -41,7 +41,7 @@ struct CChartData
/** /**
* Chart for a data visualization as lines or points * Chart for a data visualization as lines or points
*/ */
class CChart : public IGUITextOwner class CChart : public IGUIObject, public IGUITextOwner
{ {
GUI_OBJECT(CChart) GUI_OBJECT(CChart)
@ -50,6 +50,11 @@ public:
virtual ~CChart(); virtual ~CChart();
protected: protected:
/**
* @see IGUIObject#UpdateCachedSize()
*/
void UpdateCachedSize();
/** /**
* @see IGUIObject#HandleMessage() * @see IGUIObject#HandleMessage()
*/ */

View File

@ -23,7 +23,7 @@
CCheckBox::CCheckBox(CGUI& pGUI) CCheckBox::CCheckBox(CGUI& pGUI)
: IGUIObject(pGUI), : IGUIObject(pGUI),
IGUIButtonBehavior(pGUI), IGUIButtonBehavior(*static_cast<IGUIObject*>(this)),
m_CellID(), m_CellID(),
m_Checked(), m_Checked(),
m_SpriteUnchecked(), m_SpriteUnchecked(),
@ -51,16 +51,21 @@ CCheckBox::~CCheckBox()
{ {
} }
void CCheckBox::ResetStates()
{
IGUIObject::ResetStates();
IGUIButtonBehavior::ResetStates();
}
void CCheckBox::HandleMessage(SGUIMessage& Message) void CCheckBox::HandleMessage(SGUIMessage& Message)
{ {
// Important IGUIObject::HandleMessage(Message);
IGUIButtonBehavior::HandleMessage(Message); IGUIButtonBehavior::HandleMessage(Message);
switch (Message.type) switch (Message.type)
{ {
case GUIM_PRESSED: case GUIM_PRESSED:
{ {
// Switch to opposite.
SetSetting<bool>("checked", !m_Checked, true); SetSetting<bool>("checked", !m_Checked, true);
break; break;
} }

View File

@ -21,7 +21,7 @@
#include "gui/CGUISprite.h" #include "gui/CGUISprite.h"
#include "gui/IGUIButtonBehavior.h" #include "gui/IGUIButtonBehavior.h"
class CCheckBox : public IGUIButtonBehavior class CCheckBox : public IGUIObject, public IGUIButtonBehavior
{ {
GUI_OBJECT(CCheckBox) GUI_OBJECT(CCheckBox)
@ -32,7 +32,7 @@ public:
/** /**
* @see IGUIObject#ResetStates() * @see IGUIObject#ResetStates()
*/ */
virtual void ResetStates() { IGUIButtonBehavior::ResetStates(); } virtual void ResetStates();
/** /**
* @see IGUIObject#HandleMessage() * @see IGUIObject#HandleMessage()

View File

@ -29,7 +29,6 @@
CDropDown::CDropDown(CGUI& pGUI) CDropDown::CDropDown(CGUI& pGUI)
: CList(pGUI), : CList(pGUI),
IGUIObject(pGUI),
m_Open(), m_Open(),
m_HideScrollBar(), m_HideScrollBar(),
m_ElementHighlight(-1), m_ElementHighlight(-1),
@ -93,7 +92,7 @@ void CDropDown::UpdateCachedSize()
void CDropDown::HandleMessage(SGUIMessage& Message) void CDropDown::HandleMessage(SGUIMessage& Message)
{ {
// Important // CList::HandleMessage(Message); placed after the switch!
switch (Message.type) switch (Message.type)
{ {

View File

@ -40,7 +40,7 @@ extern int g_yres;
CInput::CInput(CGUI& pGUI) CInput::CInput(CGUI& pGUI)
: :
IGUIObject(pGUI), IGUIObject(pGUI),
IGUIScrollBarOwner(pGUI), IGUIScrollBarOwner(*static_cast<IGUIObject*>(this)),
m_iBufferPos(-1), m_iBufferPos(-1),
m_iBufferPos_Tail(-1), m_iBufferPos_Tail(-1),
m_SelectingText(), m_SelectingText(),
@ -842,9 +842,15 @@ InReaction CInput::ManuallyHandleHotkeyEvent(const SDL_Event_* ev)
return IN_PASS; return IN_PASS;
} }
void CInput::ResetStates()
{
IGUIObject::ResetStates();
IGUIScrollBarOwner::ResetStates();
}
void CInput::HandleMessage(SGUIMessage& Message) void CInput::HandleMessage(SGUIMessage& Message)
{ {
IGUIObject::HandleMessage(Message);
IGUIScrollBarOwner::HandleMessage(Message); IGUIScrollBarOwner::HandleMessage(Message);
switch (Message.type) switch (Message.type)

View File

@ -31,7 +31,7 @@
* any other features than word-wrapping, and we need to be * any other features than word-wrapping, and we need to be
* able to rapidly change the string. * able to rapidly change the string.
*/ */
class CInput : public IGUIScrollBarOwner class CInput : public IGUIObject, public IGUIScrollBarOwner
{ {
GUI_OBJECT(CInput) GUI_OBJECT(CInput)
@ -45,7 +45,7 @@ public:
/** /**
* @see IGUIObject#ResetStates() * @see IGUIObject#ResetStates()
*/ */
virtual void ResetStates() { IGUIScrollBarOwner::ResetStates(); } virtual void ResetStates();
// Check where the mouse is hovering, and get the appropriate text position. // Check where the mouse is hovering, and get the appropriate text position.
// return is the text-position index. // return is the text-position index.

View File

@ -28,8 +28,8 @@
CList::CList(CGUI& pGUI) CList::CList(CGUI& pGUI)
: IGUIObject(pGUI), : IGUIObject(pGUI),
IGUITextOwner(pGUI), IGUITextOwner(*static_cast<IGUIObject*>(this)),
IGUIScrollBarOwner(pGUI), IGUIScrollBarOwner(*static_cast<IGUIObject*>(this)),
m_Modified(false), m_Modified(false),
m_PrevSelectedItem(-1), m_PrevSelectedItem(-1),
m_LastItemClickTime(0), m_LastItemClickTime(0),
@ -139,8 +139,21 @@ void CList::SetupText()
} }
} }
void CList::ResetStates()
{
IGUIObject::ResetStates();
IGUIScrollBarOwner::ResetStates();
}
void CList::UpdateCachedSize()
{
IGUIObject::UpdateCachedSize();
IGUITextOwner::UpdateCachedSize();
}
void CList::HandleMessage(SGUIMessage& Message) void CList::HandleMessage(SGUIMessage& Message)
{ {
IGUIObject::HandleMessage(Message);
IGUIScrollBarOwner::HandleMessage(Message); IGUIScrollBarOwner::HandleMessage(Message);
//IGUITextOwner::HandleMessage(Message); <== placed it after the switch instead! //IGUITextOwner::HandleMessage(Message); <== placed it after the switch instead!

View File

@ -34,7 +34,7 @@
* A scroll-bar will appear when needed. This will be * A scroll-bar will appear when needed. This will be
* achieved with the IGUIScrollBarOwner structure. * achieved with the IGUIScrollBarOwner structure.
*/ */
class CList : public IGUIScrollBarOwner, public IGUITextOwner class CList : public IGUIObject, public IGUIScrollBarOwner, public IGUITextOwner
{ {
GUI_OBJECT(CList) GUI_OBJECT(CList)
@ -45,7 +45,12 @@ public:
/** /**
* @see IGUIObject#ResetStates() * @see IGUIObject#ResetStates()
*/ */
virtual void ResetStates() { IGUIScrollBarOwner::ResetStates(); } virtual void ResetStates();
/**
* @see IGUIObject#UpdateCachedSize()
*/
virtual void UpdateCachedSize();
/** /**
* Adds an item last to the list. * Adds an item last to the list.
@ -53,6 +58,7 @@ public:
virtual void AddItem(const CStrW& str, const CStrW& data); virtual void AddItem(const CStrW& str, const CStrW& data);
protected: protected:
/** /**
* Sets up text, should be called every time changes has been * Sets up text, should be called every time changes has been
* made that can change the visual. * made that can change the visual.

View File

@ -31,7 +31,6 @@ const CPos COLUMN_SHIFT = CPos(0, 4);
COList::COList(CGUI& pGUI) COList::COList(CGUI& pGUI)
: CList(pGUI), : CList(pGUI),
IGUIObject(pGUI),
m_SpriteHeading(), m_SpriteHeading(),
m_Sortable(), m_Sortable(),
m_SelectedColumn(), m_SelectedColumn(),

View File

@ -38,7 +38,6 @@ CProgressBar::~CProgressBar()
void CProgressBar::HandleMessage(SGUIMessage& Message) void CProgressBar::HandleMessage(SGUIMessage& Message)
{ {
// Important
IGUIObject::HandleMessage(Message); IGUIObject::HandleMessage(Message);
switch (Message.type) switch (Message.type)

View File

@ -20,13 +20,12 @@
#include "CRadioButton.h" #include "CRadioButton.h"
CRadioButton::CRadioButton(CGUI& pGUI) CRadioButton::CRadioButton(CGUI& pGUI)
: CCheckBox(pGUI), IGUIObject(pGUI) : CCheckBox(pGUI)
{ {
} }
void CRadioButton::HandleMessage(SGUIMessage& Message) void CRadioButton::HandleMessage(SGUIMessage& Message)
{ {
// Important
IGUIButtonBehavior::HandleMessage(Message); IGUIButtonBehavior::HandleMessage(Message);
switch (Message.type) switch (Message.type)

View File

@ -61,6 +61,8 @@ void CSlider::IncrementallyChangeValue(const float difference)
void CSlider::HandleMessage(SGUIMessage& Message) void CSlider::HandleMessage(SGUIMessage& Message)
{ {
IGUIObject::HandleMessage(Message);
switch (Message.type) switch (Message.type)
{ {
case GUIM_SETTINGS_UPDATED: case GUIM_SETTINGS_UPDATED:

View File

@ -22,11 +22,12 @@
#include "gui/CGUI.h" #include "gui/CGUI.h"
#include "gui/CGUIScrollBarVertical.h" #include "gui/CGUIScrollBarVertical.h"
#include "gui/CGUIText.h" #include "gui/CGUIText.h"
#include "scriptinterface/ScriptInterface.h"
CText::CText(CGUI& pGUI) CText::CText(CGUI& pGUI)
: IGUIObject(pGUI), : IGUIObject(pGUI),
IGUIScrollBarOwner(pGUI), IGUIScrollBarOwner(*static_cast<IGUIObject*>(this)),
IGUITextOwner(pGUI), IGUITextOwner(*static_cast<IGUIObject*>(this)),
m_BufferZone(), m_BufferZone(),
m_Caption(), m_Caption(),
m_CellID(), m_CellID(),
@ -121,8 +122,21 @@ void CText::SetupText()
} }
} }
void CText::ResetStates()
{
IGUIObject::ResetStates();
IGUIScrollBarOwner::ResetStates();
}
void CText::UpdateCachedSize()
{
IGUIObject::UpdateCachedSize();
IGUITextOwner::UpdateCachedSize();
}
void CText::HandleMessage(SGUIMessage& Message) void CText::HandleMessage(SGUIMessage& Message)
{ {
IGUIObject::HandleMessage(Message);
IGUIScrollBarOwner::HandleMessage(Message); IGUIScrollBarOwner::HandleMessage(Message);
//IGUITextOwner::HandleMessage(Message); <== placed it after the switch instead! //IGUITextOwner::HandleMessage(Message); <== placed it after the switch instead!
@ -237,3 +251,34 @@ bool CText::MouseOverIcon()
return false; return false;
} }
void CText::RegisterScriptFunctions()
{
JSContext* cx = m_pGUI.GetScriptInterface()->GetContext();
JSAutoRequest rq(cx);
JS_DefineFunctions(cx, m_JSObject, CText::JSI_methods);
}
JSFunctionSpec CText::JSI_methods[] =
{
JS_FN("getTextSize", CText::GetTextSize, 0, 0),
JS_FS_END
};
bool CText::GetTextSize(JSContext* cx, uint argc, JS::Value* vp)
{
// No JSAutoRequest needed for these calls
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
CText* thisObj = ScriptInterface::GetPrivate<CText>(cx, args, &JSI_IGUIObject::JSI_class);
if (!thisObj)
{
JSAutoRequest rq(cx);
JS_ReportError(cx, "This is not a CText object!");
return false;
}
thisObj->UpdateText();
ScriptInterface::ToJSVal(cx, args.rval(), thisObj->m_GeneratedTexts[0].GetSize());
return true;
}

View File

@ -26,7 +26,7 @@
/** /**
* Text field that just displays static text. * Text field that just displays static text.
*/ */
class CText : public IGUIScrollBarOwner, public IGUITextOwner class CText : public IGUIObject, public IGUIScrollBarOwner, public IGUITextOwner
{ {
GUI_OBJECT(CText) GUI_OBJECT(CText)
@ -37,7 +37,12 @@ public:
/** /**
* @see IGUIObject#ResetStates() * @see IGUIObject#ResetStates()
*/ */
virtual void ResetStates() { IGUIScrollBarOwner::ResetStates(); } virtual void ResetStates();
/**
* @see IGUIObject#UpdateCachedSize()
*/
virtual void UpdateCachedSize();
/** /**
* Test if mouse position is over an icon * Test if mouse position is over an icon
@ -51,6 +56,8 @@ protected:
*/ */
void SetupText(); void SetupText();
virtual void RegisterScriptFunctions();
/** /**
* @see IGUIObject#HandleMessage() * @see IGUIObject#HandleMessage()
*/ */
@ -61,6 +68,13 @@ protected:
*/ */
virtual void Draw(); virtual void Draw();
/**
* Script accessors to this GUI object.
*/
static JSFunctionSpec JSI_methods[];
static bool GetTextSize(JSContext* cx, uint argc, JS::Value* vp);
/** /**
* Placement of text. Ignored when scrollbars are active. * Placement of text. Ignored when scrollbars are active.
*/ */

View File

@ -27,7 +27,7 @@
CTooltip::CTooltip(CGUI& pGUI) CTooltip::CTooltip(CGUI& pGUI)
: IGUIObject(pGUI), : IGUIObject(pGUI),
IGUITextOwner(pGUI), IGUITextOwner(*static_cast<IGUIObject*>(this)),
m_BufferZone(), m_BufferZone(),
m_Caption(), m_Caption(),
m_Font(), m_Font(),
@ -133,8 +133,15 @@ void CTooltip::SetupText()
SetSetting<CClientArea>("size", size, true); SetSetting<CClientArea>("size", size, true);
} }
void CTooltip::UpdateCachedSize()
{
IGUIObject::UpdateCachedSize();
IGUITextOwner::UpdateCachedSize();
}
void CTooltip::HandleMessage(SGUIMessage& Message) void CTooltip::HandleMessage(SGUIMessage& Message)
{ {
IGUIObject::HandleMessage(Message);
IGUITextOwner::HandleMessage(Message); IGUITextOwner::HandleMessage(Message);
} }

View File

@ -25,7 +25,7 @@
/** /**
* Dynamic tooltips. Similar to CText. * Dynamic tooltips. Similar to CText.
*/ */
class CTooltip : public IGUITextOwner class CTooltip : public IGUIObject, public IGUITextOwner
{ {
GUI_OBJECT(CTooltip) GUI_OBJECT(CTooltip)
@ -36,6 +36,11 @@ public:
protected: protected:
void SetupText(); void SetupText();
/**
* @see IGUIObject#UpdateCachedSize()
*/
void UpdateCachedSize();
/** /**
* @see IGUIObject#HandleMessage() * @see IGUIObject#HandleMessage()
*/ */

View File

@ -117,7 +117,7 @@ void GUITooltip::ShowTooltip(IGUIObject* obj, const CPos& pos, const CStr& style
if (style.empty()) if (style.empty())
return; return;
// Must be a CTooltip*, but we avoid dynamic_cast // Must be a CTooltip*
IGUIObject* tooltipobj = pGUI.FindObjectByName("__tooltip_" + style); IGUIObject* tooltipobj = pGUI.FindObjectByName("__tooltip_" + style);
if (!tooltipobj || !tooltipobj->SettingExists("use_object")) if (!tooltipobj || !tooltipobj->SettingExists("use_object"))
{ {
@ -172,7 +172,7 @@ void GUITooltip::HideTooltip(const CStr& style, CGUI& pGUI)
if (style.empty()) if (style.empty())
return; return;
// Must be a CTooltip*, but we avoid dynamic_cast // Must be a CTooltip*
IGUIObject* tooltipobj = pGUI.FindObjectByName("__tooltip_" + style); IGUIObject* tooltipobj = pGUI.FindObjectByName("__tooltip_" + style);
if (!tooltipobj || !tooltipobj->SettingExists("use_object") || !tooltipobj->SettingExists("hide_object")) if (!tooltipobj || !tooltipobj->SettingExists("use_object") || !tooltipobj->SettingExists("hide_object"))
{ {
@ -204,7 +204,7 @@ void GUITooltip::HideTooltip(const CStr& style, CGUI& pGUI)
static i32 GetTooltipDelay(const CStr& style, CGUI& pGUI) static i32 GetTooltipDelay(const CStr& style, CGUI& pGUI)
{ {
// Must be a CTooltip*, but we avoid dynamic_cast // Must be a CTooltip*
IGUIObject* tooltipobj = pGUI.FindObjectByName("__tooltip_" + style); IGUIObject* tooltipobj = pGUI.FindObjectByName("__tooltip_" + style);
if (!tooltipobj) if (!tooltipobj)

View File

@ -19,11 +19,10 @@
#include "IGUIButtonBehavior.h" #include "IGUIButtonBehavior.h"
#include "gui/CGUI.h"
#include "gui/CGUISprite.h" #include "gui/CGUISprite.h"
IGUIButtonBehavior::IGUIButtonBehavior(CGUI& pGUI) IGUIButtonBehavior::IGUIButtonBehavior(IGUIObject& pObject)
: IGUIObject(pGUI), : m_pObject(pObject),
m_Pressed(), m_Pressed(),
m_PressedRight(), m_PressedRight(),
m_SoundDisabled(), m_SoundDisabled(),
@ -32,94 +31,100 @@ IGUIButtonBehavior::IGUIButtonBehavior(CGUI& pGUI)
m_SoundPressed(), m_SoundPressed(),
m_SoundReleased() m_SoundReleased()
{ {
RegisterSetting("sound_disabled", m_SoundDisabled); m_pObject.RegisterSetting("sound_disabled", m_SoundDisabled);
RegisterSetting("sound_enter", m_SoundEnter); m_pObject.RegisterSetting("sound_enter", m_SoundEnter);
RegisterSetting("sound_leave", m_SoundLeave); m_pObject.RegisterSetting("sound_leave", m_SoundLeave);
RegisterSetting("sound_pressed", m_SoundPressed); m_pObject.RegisterSetting("sound_pressed", m_SoundPressed);
RegisterSetting("sound_released", m_SoundReleased); m_pObject.RegisterSetting("sound_released", m_SoundReleased);
} }
IGUIButtonBehavior::~IGUIButtonBehavior() IGUIButtonBehavior::~IGUIButtonBehavior()
{ {
} }
void IGUIButtonBehavior::ResetStates()
{
m_Pressed = false;
m_PressedRight = false;
}
void IGUIButtonBehavior::HandleMessage(SGUIMessage& Message) void IGUIButtonBehavior::HandleMessage(SGUIMessage& Message)
{ {
// TODO Gee: easier access functions // TODO Gee: easier access functions
switch (Message.type) switch (Message.type)
{ {
case GUIM_MOUSE_ENTER: case GUIM_MOUSE_ENTER:
if (m_Enabled) if (m_pObject.IsEnabled())
PlaySound(m_SoundEnter); m_pObject.PlaySound(m_SoundEnter);
break; break;
case GUIM_MOUSE_LEAVE: case GUIM_MOUSE_LEAVE:
if (m_Enabled) if (m_pObject.IsEnabled())
PlaySound(m_SoundLeave); m_pObject.PlaySound(m_SoundLeave);
break; break;
case GUIM_MOUSE_DBLCLICK_LEFT: case GUIM_MOUSE_DBLCLICK_LEFT:
if (!m_Enabled) if (!m_pObject.IsEnabled())
break; break;
// Since GUIM_MOUSE_PRESS_LEFT also gets called twice in a // Since GUIM_MOUSE_PRESS_LEFT also gets called twice in a
// doubleclick event, we let it handle playing sounds. // doubleclick event, we let it handle playing sounds.
SendEvent(GUIM_DOUBLE_PRESSED, "doublepress"); m_pObject.SendEvent(GUIM_DOUBLE_PRESSED, "doublepress");
break; break;
case GUIM_MOUSE_PRESS_LEFT: case GUIM_MOUSE_PRESS_LEFT:
if (!m_Enabled) if (!m_pObject.IsEnabled())
{ {
PlaySound(m_SoundDisabled); m_pObject.PlaySound(m_SoundDisabled);
break; break;
} }
PlaySound(m_SoundPressed); m_pObject.PlaySound(m_SoundPressed);
SendEvent(GUIM_PRESSED, "press"); m_pObject.SendEvent(GUIM_PRESSED, "press");
m_Pressed = true; m_Pressed = true;
break; break;
case GUIM_MOUSE_DBLCLICK_RIGHT: case GUIM_MOUSE_DBLCLICK_RIGHT:
if (!m_Enabled) if (!m_pObject.IsEnabled())
break; break;
// Since GUIM_MOUSE_PRESS_RIGHT also gets called twice in a // Since GUIM_MOUSE_PRESS_RIGHT also gets called twice in a
// doubleclick event, we let it handle playing sounds. // doubleclick event, we let it handle playing sounds.
SendEvent(GUIM_DOUBLE_PRESSED_MOUSE_RIGHT, "doublepressright"); m_pObject.SendEvent(GUIM_DOUBLE_PRESSED_MOUSE_RIGHT, "doublepressright");
break; break;
case GUIM_MOUSE_PRESS_RIGHT: case GUIM_MOUSE_PRESS_RIGHT:
if (!m_Enabled) if (!m_pObject.IsEnabled())
{ {
PlaySound(m_SoundDisabled); m_pObject.PlaySound(m_SoundDisabled);
break; break;
} }
// Button was right-clicked // Button was right-clicked
PlaySound(m_SoundPressed); m_pObject.PlaySound(m_SoundPressed);
SendEvent(GUIM_PRESSED_MOUSE_RIGHT, "pressright"); m_pObject.SendEvent(GUIM_PRESSED_MOUSE_RIGHT, "pressright");
m_PressedRight = true; m_PressedRight = true;
break; break;
case GUIM_MOUSE_RELEASE_RIGHT: case GUIM_MOUSE_RELEASE_RIGHT:
if (!m_Enabled) if (!m_pObject.IsEnabled())
break; break;
if (m_PressedRight) if (m_PressedRight)
{ {
m_PressedRight = false; m_PressedRight = false;
PlaySound(m_SoundReleased); m_pObject.PlaySound(m_SoundReleased);
} }
break; break;
case GUIM_MOUSE_RELEASE_LEFT: case GUIM_MOUSE_RELEASE_LEFT:
if (!m_Enabled) if (!m_pObject.IsEnabled())
break; break;
if (m_Pressed) if (m_Pressed)
{ {
m_Pressed = false; m_Pressed = false;
PlaySound(m_SoundReleased); m_pObject.PlaySound(m_SoundReleased);
} }
break; break;
@ -130,10 +135,10 @@ void IGUIButtonBehavior::HandleMessage(SGUIMessage& Message)
const CGUISpriteInstance& IGUIButtonBehavior::GetButtonSprite(const CGUISpriteInstance& sprite, const CGUISpriteInstance& sprite_over, const CGUISpriteInstance& sprite_pressed, const CGUISpriteInstance& sprite_disabled) const const CGUISpriteInstance& IGUIButtonBehavior::GetButtonSprite(const CGUISpriteInstance& sprite, const CGUISpriteInstance& sprite_over, const CGUISpriteInstance& sprite_pressed, const CGUISpriteInstance& sprite_disabled) const
{ {
if (!m_Enabled) if (!m_pObject.IsEnabled())
return sprite_disabled || sprite; return sprite_disabled || sprite;
if (!m_MouseHovering) if (!m_pObject.IsMouseOver())
return sprite; return sprite;
if (m_Pressed) if (m_Pressed)

View File

@ -35,10 +35,12 @@ class CGUISpriteInstance;
* Can be used with multiple inheritance alongside * Can be used with multiple inheritance alongside
* IGUISettingsObject and such. * IGUISettingsObject and such.
*/ */
class IGUIButtonBehavior : virtual public IGUIObject class IGUIButtonBehavior
{ {
NONCOPYABLE(IGUIButtonBehavior);
public: public:
IGUIButtonBehavior(CGUI& pGUI); IGUIButtonBehavior(IGUIObject& pObject);
virtual ~IGUIButtonBehavior(); virtual ~IGUIButtonBehavior();
/** /**
@ -61,13 +63,7 @@ protected:
/** /**
* @see IGUIObject#ResetStates() * @see IGUIObject#ResetStates()
*/ */
virtual void ResetStates() virtual void ResetStates();
{
// Notify the gui that we aren't hovered anymore
UpdateMouseOver(nullptr);
m_Pressed = false;
m_PressedRight = false;
}
/** /**
* Everybody knows how a button works, you don't simply press it, * Everybody knows how a button works, you don't simply press it,
@ -85,6 +81,13 @@ protected:
CStrW m_SoundLeave; CStrW m_SoundLeave;
CStrW m_SoundPressed; CStrW m_SoundPressed;
CStrW m_SoundReleased; CStrW m_SoundReleased;
private:
/**
* Reference to the IGUIObject.
* Private, because we don't want to inherit it in multiple classes.
*/
IGUIObject& m_pObject;
}; };
#endif // INCLUDED_IGUIBUTTONBEHAVIOR #endif // INCLUDED_IGUIBUTTONBEHAVIOR

View File

@ -453,6 +453,8 @@ void IGUIObject::CreateJSObject()
m_JSObject.init(cx, m_pGUI.GetScriptInterface()->CreateCustomObject("GUIObject")); m_JSObject.init(cx, m_pGUI.GetScriptInterface()->CreateCustomObject("GUIObject"));
JS_SetPrivate(m_JSObject.get(), this); JS_SetPrivate(m_JSObject.get(), this);
RegisterScriptFunctions();
} }
JSObject* IGUIObject::GetJSObject() JSObject* IGUIObject::GetJSObject()
@ -465,6 +467,11 @@ JSObject* IGUIObject::GetJSObject()
return m_JSObject.get(); return m_JSObject.get();
} }
bool IGUIObject::IsEnabled() const
{
return m_Enabled;
}
bool IGUIObject::IsHidden() const bool IGUIObject::IsHidden() const
{ {
return m_Hidden; return m_Hidden;

View File

@ -129,6 +129,16 @@ public:
//-------------------------------------------------------- //--------------------------------------------------------
//@{ //@{
/**
* Registers the given setting variables with the GUI object.
* Enable XML and JS to modify the given variable.
*
* @param Type Setting type
* @param Name Setting reference name
*/
template<typename T>
void RegisterSetting(const CStr& Name, T& Value);
/** /**
* Returns whether there is a setting with the given name registered. * Returns whether there is a setting with the given name registered.
* *
@ -171,6 +181,11 @@ public:
template <typename T> template <typename T>
void SetSetting(const CStr& Setting, const T& Value, const bool SendMessage); void SetSetting(const CStr& Setting, const T& Value, const bool SendMessage);
/**
* Returns whether this object is set to be hidden or ghost.
*/
bool IsEnabled() const;
/** /**
* Returns whether this is object is set to be hidden. * Returns whether this is object is set to be hidden.
*/ */
@ -181,6 +196,20 @@ public:
*/ */
bool IsHiddenOrGhost() const; bool IsHiddenOrGhost() const;
/**
* Retrieves the configured sound filename from the given setting name and plays that once.
*/
void PlaySound(const CStrW& soundPath) const;
/**
* Send event to this GUI object (HandleMessage and ScriptEvent)
*
* @param type Type of GUI message to be handled
* @param EventName String representation of event name
* @return IN_HANDLED if event was handled, or IN_PASS if skipped
*/
InReaction SendEvent(EGUIMessageType type, const CStr& EventName);
/** /**
* All sizes are relative to resolution, and the calculation * All sizes are relative to resolution, and the calculation
* is not wanted in real time, therefore it is cached, update * is not wanted in real time, therefore it is cached, update
@ -203,10 +232,9 @@ public:
void RegisterScriptHandler(const CStr& Action, const CStr& Code, CGUI& pGUI); void RegisterScriptHandler(const CStr& Action, const CStr& Code, CGUI& pGUI);
/** /**
* Creates the JS Object representing this page upon first use. * Inheriting classes may append JS functions to the JS object representing this class.
* Can be overridden by derived classes to extend it.
*/ */
virtual void CreateJSObject(); virtual void RegisterScriptFunctions() {}
/** /**
* Retrieves the JSObject representing this GUI object. * Retrieves the JSObject representing this GUI object.
@ -227,16 +255,6 @@ protected:
//-------------------------------------------------------- //--------------------------------------------------------
//@{ //@{
/**
* Registers the given setting variables with the GUI object.
* Enable XML and JS to modify the given variable.
*
* @param Type Setting type
* @param Name Setting reference name
*/
template<typename T>
void RegisterSetting(const CStr& Name, T& Value);
public: public:
/** /**
* This function is called with different messages * This function is called with different messages
@ -318,11 +336,6 @@ public:
*/ */
void SetFocus(); void SetFocus();
/**
* Workaround to avoid a dynamic_cast which can be 80 times slower than this.
*/
virtual void* GetTextOwner() { return nullptr; }
protected: protected:
/** /**
* Check if object is focused. * Check if object is focused.
@ -366,15 +379,6 @@ protected:
*/ */
CRect m_CachedActualSize; CRect m_CachedActualSize;
/**
* Send event to this GUI object (HandleMessage and ScriptEvent)
*
* @param type Type of GUI message to be handled
* @param EventName String representation of event name
* @return IN_HANDLED if event was handled, or IN_PASS if skipped
*/
InReaction SendEvent(EGUIMessageType type, const CStr& EventName);
/** /**
* Execute the script for a particular action. * Execute the script for a particular action.
* Does nothing if no script has been registered for that action. * Does nothing if no script has been registered for that action.
@ -404,11 +408,6 @@ protected:
*/ */
void UpdateMouseOver(IGUIObject* const& pMouseOver); void UpdateMouseOver(IGUIObject* const& pMouseOver);
/**
* Retrieves the configured sound filename from the given setting name and plays that once.
*/
void PlaySound(const CStrW& soundPath) const;
//@} //@}
private: private:
//-------------------------------------------------------- //--------------------------------------------------------
@ -416,6 +415,11 @@ private:
//-------------------------------------------------------- //--------------------------------------------------------
//@{ //@{
/**
* Creates the JS object representing this page upon first use.
*/
void CreateJSObject();
/** /**
* Updates some internal data depending on the setting changed. * Updates some internal data depending on the setting changed.
*/ */

View File

@ -22,8 +22,8 @@
#include "gui/CGUI.h" #include "gui/CGUI.h"
#include "gui/IGUIScrollBar.h" #include "gui/IGUIScrollBar.h"
IGUIScrollBarOwner::IGUIScrollBarOwner(CGUI& pGUI) IGUIScrollBarOwner::IGUIScrollBarOwner(IGUIObject& pObject)
: IGUIObject(pGUI) : m_pObject(pObject)
{ {
} }
@ -35,8 +35,6 @@ IGUIScrollBarOwner::~IGUIScrollBarOwner()
void IGUIScrollBarOwner::ResetStates() void IGUIScrollBarOwner::ResetStates()
{ {
IGUIObject::ResetStates();
for (IGUIScrollBar* const& sb : m_ScrollBars) for (IGUIScrollBar* const& sb : m_ScrollBars)
sb->SetBarPressed(false); sb->SetBarPressed(false);
} }
@ -49,7 +47,7 @@ void IGUIScrollBarOwner::AddScrollBar(IGUIScrollBar* scrollbar)
const SGUIScrollBarStyle* IGUIScrollBarOwner::GetScrollBarStyle(const CStr& style) const const SGUIScrollBarStyle* IGUIScrollBarOwner::GetScrollBarStyle(const CStr& style) const
{ {
return m_pGUI.GetScrollBarStyle(style); return m_pObject.GetGUI().GetScrollBarStyle(style);
} }
void IGUIScrollBarOwner::HandleMessage(SGUIMessage& msg) void IGUIScrollBarOwner::HandleMessage(SGUIMessage& msg)

View File

@ -29,12 +29,14 @@ class IGUIScrollBar;
* Base-class this if you want an object to contain * Base-class this if you want an object to contain
* one, or several, scroll-bars. * one, or several, scroll-bars.
*/ */
class IGUIScrollBarOwner : virtual public IGUIObject class IGUIScrollBarOwner
{ {
NONCOPYABLE(IGUIScrollBarOwner);
friend class IGUIScrollBar; friend class IGUIScrollBar;
public: public:
IGUIScrollBarOwner(CGUI& pGUI); IGUIScrollBarOwner(IGUIObject& m_pObject);
virtual ~IGUIScrollBarOwner(); virtual ~IGUIScrollBarOwner();
virtual void Draw(); virtual void Draw();
@ -75,12 +77,18 @@ public:
virtual float GetScrollBarPos(const int index) const; virtual float GetScrollBarPos(const int index) const;
protected: protected:
/** /**
* Predominately you will only have one, but you can have * Predominately you will only have one, but you can have
* as many as you like. * as many as you like.
*/ */
std::vector<IGUIScrollBar*> m_ScrollBars; std::vector<IGUIScrollBar*> m_ScrollBars;
private:
/**
* Reference to the IGUIObject.
* Private, because we don't want to inherit it in multiple classes.
*/
IGUIObject& m_pObject;
}; };
#endif // INCLUDED_IGUISCROLLBAROWNER #endif // INCLUDED_IGUISCROLLBAROWNER

View File

@ -21,12 +21,12 @@
#include "gui/CGUI.h" #include "gui/CGUI.h"
#include "gui/CGUIString.h" #include "gui/CGUIString.h"
#include "gui/scripting/JSInterface_IGUITextOwner.h"
#include <math.h> #include <math.h>
IGUITextOwner::IGUITextOwner(CGUI& pGUI) IGUITextOwner::IGUITextOwner(IGUIObject& pObject)
: IGUIObject(pGUI), m_GeneratedTextsValid(false) : m_pObject(pObject),
m_GeneratedTextsValid()
{ {
} }
@ -34,14 +34,6 @@ IGUITextOwner::~IGUITextOwner()
{ {
} }
void IGUITextOwner::CreateJSObject()
{
IGUIObject::CreateJSObject();
JSI_IGUITextOwner::RegisterScriptFunctions(
m_pGUI.GetScriptInterface()->GetContext(), m_JSObject);
}
CGUIText& IGUITextOwner::AddText() CGUIText& IGUITextOwner::AddText()
{ {
m_GeneratedTexts.emplace_back(); m_GeneratedTexts.emplace_back();
@ -51,7 +43,7 @@ CGUIText& IGUITextOwner::AddText()
CGUIText& IGUITextOwner::AddText(const CGUIString& Text, const CStrW& Font, const float& Width, const float& BufferZone) CGUIText& IGUITextOwner::AddText(const CGUIString& Text, const CStrW& Font, const float& Width, const float& BufferZone)
{ {
// Avoids a move constructor // Avoids a move constructor
m_GeneratedTexts.emplace_back(m_pGUI, Text, Font, Width, BufferZone, this); m_GeneratedTexts.emplace_back(m_pObject.GetGUI(), Text, Font, Width, BufferZone, &m_pObject);
return m_GeneratedTexts.back(); return m_GeneratedTexts.back();
} }
@ -82,24 +74,26 @@ void IGUITextOwner::HandleMessage(SGUIMessage& Message)
void IGUITextOwner::UpdateCachedSize() void IGUITextOwner::UpdateCachedSize()
{ {
// If an ancestor's size changed, this will let us intercept the change and
// update our text positions // update our text positions
IGUIObject::UpdateCachedSize();
m_GeneratedTextsValid = false; m_GeneratedTextsValid = false;
} }
void IGUITextOwner::DrawText(size_t index, const CGUIColor& color, const CPos& pos, float z, const CRect& clipping) void IGUITextOwner::UpdateText()
{ {
if (!m_GeneratedTextsValid) if (!m_GeneratedTextsValid)
{ {
SetupText(); SetupText();
m_GeneratedTextsValid = true; m_GeneratedTextsValid = true;
} }
}
void IGUITextOwner::DrawText(size_t index, const CGUIColor& color, const CPos& pos, float z, const CRect& clipping)
{
UpdateText();
ENSURE(index < m_GeneratedTexts.size() && "Trying to draw a Text Index within a IGUITextOwner that doesn't exist"); ENSURE(index < m_GeneratedTexts.size() && "Trying to draw a Text Index within a IGUITextOwner that doesn't exist");
m_GeneratedTexts.at(index).Draw(m_pGUI, color, pos, z, clipping); m_GeneratedTexts.at(index).Draw(m_pObject.GetGUI(), color, pos, z, clipping);
} }
void IGUITextOwner::CalculateTextPosition(CRect& ObjSize, CPos& TextPos, CGUIText& Text) void IGUITextOwner::CalculateTextPosition(CRect& ObjSize, CPos& TextPos, CGUIText& Text)
@ -108,7 +102,7 @@ void IGUITextOwner::CalculateTextPosition(CRect& ObjSize, CPos& TextPos, CGUITex
// loop through all of the TextCall objects again. // loop through all of the TextCall objects again.
TextPos.x = ObjSize.left; TextPos.x = ObjSize.left;
switch (GetSetting<EVAlign>("text_valign")) switch (m_pObject.GetSetting<EVAlign>("text_valign"))
{ {
case EVAlign_Top: case EVAlign_Top:
TextPos.y = ObjSize.top; TextPos.y = ObjSize.top;
@ -126,21 +120,6 @@ void IGUITextOwner::CalculateTextPosition(CRect& ObjSize, CPos& TextPos, CGUITex
} }
} }
CSize IGUITextOwner::CalculateTextSize()
{
if (!m_GeneratedTextsValid)
{
SetupText();
m_GeneratedTextsValid = true;
}
if (m_GeneratedTexts.empty())
return CSize();
// GUI Object types that use multiple texts may override this function.
return m_GeneratedTexts[0].GetSize();
}
bool IGUITextOwner::MouseOverIcon() bool IGUITextOwner::MouseOverIcon()
{ {
return false; return false;

View File

@ -31,7 +31,6 @@ GUI Object Base - Text Owner
#define INCLUDED_IGUITEXTOWNER #define INCLUDED_IGUITEXTOWNER
#include "gui/IGUIObject.h" #include "gui/IGUIObject.h"
#include "gui/scripting/JSInterface_IGUITextOwner.h"
#include <vector> #include <vector>
@ -42,12 +41,12 @@ class CGUIString;
/** /**
* Framework for handling Output text. * Framework for handling Output text.
*/ */
class IGUITextOwner : virtual public IGUIObject class IGUITextOwner
{ {
friend bool JSI_IGUITextOwner::GetTextSize(JSContext* cx, uint argc, JS::Value* vp); NONCOPYABLE(IGUITextOwner);
public: public:
IGUITextOwner(CGUI& pGUI); IGUITextOwner(IGUIObject& pObject);
virtual ~IGUITextOwner(); virtual ~IGUITextOwner();
/** /**
@ -60,11 +59,6 @@ public:
*/ */
CGUIText& AddText(const CGUIString& Text, const CStrW& Font, const float& Width, const float& BufferZone); CGUIText& AddText(const CGUIString& Text, const CStrW& Font, const float& Width, const float& BufferZone);
/**
* Subscribe the custom JS methods.
*/
void CreateJSObject();
/** /**
* @see IGUIObject#HandleMessage() * @see IGUIObject#HandleMessage()
*/ */
@ -92,18 +86,17 @@ public:
*/ */
virtual bool MouseOverIcon(); virtual bool MouseOverIcon();
/**
* Workaround to avoid a dynamic_cast which can be 80 times slower than this.
*/
virtual void* GetTextOwner() { return this; }
protected: protected:
/** /**
* Setup texts. Functions that sets up all texts when changes have been made. * Setup texts. Functions that sets up all texts when changes have been made.
*/ */
virtual void SetupText() = 0; virtual void SetupText() = 0;
/**
* Regenerate the text in case it is invalid. Should only be called when inevitable.
*/
virtual void UpdateText();
/** /**
* Whether the cached text is currently valid (if not then SetupText will be called by Draw) * Whether the cached text is currently valid (if not then SetupText will be called by Draw)
*/ */
@ -119,10 +112,12 @@ protected:
*/ */
void CalculateTextPosition(CRect& ObjSize, CPos& TextPos, CGUIText& Text); void CalculateTextPosition(CRect& ObjSize, CPos& TextPos, CGUIText& Text);
private:
/** /**
* Calculate the size of the first generated text. * Reference to the IGUIObject.
* Private, because we don't want to inherit it in multiple classes.
*/ */
CSize CalculateTextSize(); IGUIObject& m_pObject;
}; };
#endif // INCLUDED_IGUITEXTOWNER #endif // INCLUDED_IGUITEXTOWNER

View File

@ -141,6 +141,7 @@ CMiniMap::~CMiniMap()
void CMiniMap::HandleMessage(SGUIMessage& Message) void CMiniMap::HandleMessage(SGUIMessage& Message)
{ {
IGUIObject::HandleMessage(Message);
switch (Message.type) switch (Message.type)
{ {
case GUIM_MOUSE_PRESS_LEFT: case GUIM_MOUSE_PRESS_LEFT:

View File

@ -1,55 +0,0 @@
/* Copyright (C) 2019 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include "precompiled.h"
#include "JSInterface_IGUITextOwner.h"
#include "gui/IGUITextOwner.h"
#include "scriptinterface/ScriptInterface.h"
JSFunctionSpec JSI_IGUITextOwner::JSI_methods[] =
{
JS_FN("getTextSize", JSI_IGUITextOwner::GetTextSize, 0, 0),
JS_FS_END
};
void JSI_IGUITextOwner::RegisterScriptFunctions(JSContext* cx, JS::HandleObject obj)
{
JS_DefineFunctions(cx, obj, JSI_methods);
}
bool JSI_IGUITextOwner::GetTextSize(JSContext* cx, uint argc, JS::Value* vp)
{
// No JSAutoRequest needed for these calls
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
IGUIObject* obj = ScriptInterface::GetPrivate<IGUIObject>(cx, args, &JSI_IGUIObject::JSI_class);
if (!obj)
return false;
// Avoid dynamic_cast for performance reasons
IGUITextOwner* objText = static_cast<IGUITextOwner*>(obj->GetTextOwner());
if (!objText)
{
JSAutoRequest rq(cx);
JS_ReportError(cx, "This IGUIObject is not an IGUITextOwner!");
return false;
}
ScriptInterface::ToJSVal(cx, args.rval(), objText->CalculateTextSize());
return true;
}

View File

@ -1,32 +0,0 @@
/* Copyright (C) 2019 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INCLUDED_JSI_IGUITEXTOWNER
#define INCLUDED_JSI_IGUITEXTOWNER
#include "scriptinterface/ScriptInterface.h"
namespace JSI_IGUITextOwner
{
extern JSFunctionSpec JSI_methods[];
void RegisterScriptFunctions(JSContext* cx, JS::HandleObject obj);
bool GetTextSize(JSContext* cx, uint argc, JS::Value* vp);
}
#endif // INCLUDED_JSI_IGUITEXTOWNER