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)
: IGUIObject(pGUI),
IGUIButtonBehavior(pGUI),
IGUITextOwner(pGUI),
IGUIButtonBehavior(*static_cast<IGUIObject*>(this)),
IGUITextOwner(*static_cast<IGUIObject*>(this)),
m_BufferZone(),
m_CellID(),
m_Caption(),
@ -72,9 +72,21 @@ void CButton::SetupText()
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)
{
// Important
IGUIObject::HandleMessage(Message);
IGUIButtonBehavior::HandleMessage(Message);
IGUITextOwner::HandleMessage(Message);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -28,8 +28,8 @@
CList::CList(CGUI& pGUI)
: IGUIObject(pGUI),
IGUITextOwner(pGUI),
IGUIScrollBarOwner(pGUI),
IGUITextOwner(*static_cast<IGUIObject*>(this)),
IGUIScrollBarOwner(*static_cast<IGUIObject*>(this)),
m_Modified(false),
m_PrevSelectedItem(-1),
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)
{
IGUIObject::HandleMessage(Message);
IGUIScrollBarOwner::HandleMessage(Message);
//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
* achieved with the IGUIScrollBarOwner structure.
*/
class CList : public IGUIScrollBarOwner, public IGUITextOwner
class CList : public IGUIObject, public IGUIScrollBarOwner, public IGUITextOwner
{
GUI_OBJECT(CList)
@ -45,7 +45,12 @@ public:
/**
* @see IGUIObject#ResetStates()
*/
virtual void ResetStates() { IGUIScrollBarOwner::ResetStates(); }
virtual void ResetStates();
/**
* @see IGUIObject#UpdateCachedSize()
*/
virtual void UpdateCachedSize();
/**
* Adds an item last to the list.
@ -53,6 +58,7 @@ public:
virtual void AddItem(const CStrW& str, const CStrW& data);
protected:
/**
* Sets up text, should be called every time changes has been
* made that can change the visual.

View File

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

View File

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

View File

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

View File

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

View File

@ -22,11 +22,12 @@
#include "gui/CGUI.h"
#include "gui/CGUIScrollBarVertical.h"
#include "gui/CGUIText.h"
#include "scriptinterface/ScriptInterface.h"
CText::CText(CGUI& pGUI)
: IGUIObject(pGUI),
IGUIScrollBarOwner(pGUI),
IGUITextOwner(pGUI),
IGUIScrollBarOwner(*static_cast<IGUIObject*>(this)),
IGUITextOwner(*static_cast<IGUIObject*>(this)),
m_BufferZone(),
m_Caption(),
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)
{
IGUIObject::HandleMessage(Message);
IGUIScrollBarOwner::HandleMessage(Message);
//IGUITextOwner::HandleMessage(Message); <== placed it after the switch instead!
@ -237,3 +251,34 @@ bool CText::MouseOverIcon()
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.
*/
class CText : public IGUIScrollBarOwner, public IGUITextOwner
class CText : public IGUIObject, public IGUIScrollBarOwner, public IGUITextOwner
{
GUI_OBJECT(CText)
@ -37,7 +37,12 @@ public:
/**
* @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
@ -51,6 +56,8 @@ protected:
*/
void SetupText();
virtual void RegisterScriptFunctions();
/**
* @see IGUIObject#HandleMessage()
*/
@ -61,6 +68,13 @@ protected:
*/
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.
*/

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -453,6 +453,8 @@ void IGUIObject::CreateJSObject()
m_JSObject.init(cx, m_pGUI.GetScriptInterface()->CreateCustomObject("GUIObject"));
JS_SetPrivate(m_JSObject.get(), this);
RegisterScriptFunctions();
}
JSObject* IGUIObject::GetJSObject()
@ -465,6 +467,11 @@ JSObject* IGUIObject::GetJSObject()
return m_JSObject.get();
}
bool IGUIObject::IsEnabled() const
{
return m_Enabled;
}
bool IGUIObject::IsHidden() const
{
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.
*
@ -171,6 +181,11 @@ public:
template <typename T>
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.
*/
@ -181,6 +196,20 @@ public:
*/
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
* 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);
/**
* Creates the JS Object representing this page upon first use.
* Can be overridden by derived classes to extend it.
* Inheriting classes may append JS functions to the JS object representing this class.
*/
virtual void CreateJSObject();
virtual void RegisterScriptFunctions() {}
/**
* 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:
/**
* This function is called with different messages
@ -318,11 +336,6 @@ public:
*/
void SetFocus();
/**
* Workaround to avoid a dynamic_cast which can be 80 times slower than this.
*/
virtual void* GetTextOwner() { return nullptr; }
protected:
/**
* Check if object is focused.
@ -366,15 +379,6 @@ protected:
*/
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.
* Does nothing if no script has been registered for that action.
@ -404,11 +408,6 @@ protected:
*/
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:
//--------------------------------------------------------
@ -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.
*/

View File

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

View File

@ -29,12 +29,14 @@ class IGUIScrollBar;
* Base-class this if you want an object to contain
* one, or several, scroll-bars.
*/
class IGUIScrollBarOwner : virtual public IGUIObject
class IGUIScrollBarOwner
{
NONCOPYABLE(IGUIScrollBarOwner);
friend class IGUIScrollBar;
public:
IGUIScrollBarOwner(CGUI& pGUI);
IGUIScrollBarOwner(IGUIObject& m_pObject);
virtual ~IGUIScrollBarOwner();
virtual void Draw();
@ -75,12 +77,18 @@ public:
virtual float GetScrollBarPos(const int index) const;
protected:
/**
* Predominately you will only have one, but you can have
* as many as you like.
*/
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

View File

@ -21,12 +21,12 @@
#include "gui/CGUI.h"
#include "gui/CGUIString.h"
#include "gui/scripting/JSInterface_IGUITextOwner.h"
#include <math.h>
IGUITextOwner::IGUITextOwner(CGUI& pGUI)
: IGUIObject(pGUI), m_GeneratedTextsValid(false)
IGUITextOwner::IGUITextOwner(IGUIObject& pObject)
: 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()
{
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)
{
// 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();
}
@ -82,24 +74,26 @@ void IGUITextOwner::HandleMessage(SGUIMessage& Message)
void IGUITextOwner::UpdateCachedSize()
{
// If an ancestor's size changed, this will let us intercept the change and
// update our text positions
IGUIObject::UpdateCachedSize();
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)
{
SetupText();
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");
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)
@ -108,7 +102,7 @@ void IGUITextOwner::CalculateTextPosition(CRect& ObjSize, CPos& TextPos, CGUITex
// loop through all of the TextCall objects again.
TextPos.x = ObjSize.left;
switch (GetSetting<EVAlign>("text_valign"))
switch (m_pObject.GetSetting<EVAlign>("text_valign"))
{
case EVAlign_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()
{
return false;

View File

@ -31,7 +31,6 @@ GUI Object Base - Text Owner
#define INCLUDED_IGUITEXTOWNER
#include "gui/IGUIObject.h"
#include "gui/scripting/JSInterface_IGUITextOwner.h"
#include <vector>
@ -42,12 +41,12 @@ class CGUIString;
/**
* 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:
IGUITextOwner(CGUI& pGUI);
IGUITextOwner(IGUIObject& pObject);
virtual ~IGUITextOwner();
/**
@ -60,11 +59,6 @@ public:
*/
CGUIText& AddText(const CGUIString& Text, const CStrW& Font, const float& Width, const float& BufferZone);
/**
* Subscribe the custom JS methods.
*/
void CreateJSObject();
/**
* @see IGUIObject#HandleMessage()
*/
@ -92,18 +86,17 @@ public:
*/
virtual bool MouseOverIcon();
/**
* Workaround to avoid a dynamic_cast which can be 80 times slower than this.
*/
virtual void* GetTextOwner() { return this; }
protected:
/**
* Setup texts. Functions that sets up all texts when changes have been made.
*/
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)
*/
@ -119,10 +112,12 @@ protected:
*/
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

View File

@ -141,6 +141,7 @@ CMiniMap::~CMiniMap()
void CMiniMap::HandleMessage(SGUIMessage& Message)
{
IGUIObject::HandleMessage(Message);
switch (Message.type)
{
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