Ticket #3788: gui_subsystem_code_refactoring.patch

File gui_subsystem_code_refactoring.patch, 31.4 KB (added by Sergey Kushnirenko, 5 years ago)
  • source/gui/CButton.cpp

     
    5353{
    5454}
    5555
     56void CButton::ResetStates() { IGUIButtonBehavior::ResetStates(); }
     57
    5658void CButton::SetupText()
    5759{
    5860    if (!GetGUI())
  • source/gui/CButton.h

     
    3737    /**
    3838     * @see IGUIObject#ResetStates()
    3939     */
    40     virtual void ResetStates() { IGUIButtonBehavior::ResetStates(); }
     40    virtual void ResetStates();
    4141
    4242    /**
    4343     * @see IGUIObject#HandleMessage()
  • source/gui/CCheckBox.cpp

     
    5959{
    6060}
    6161
     62void CCheckBox::ResetStates() { IGUIButtonBehavior::ResetStates(); }
     63
    6264void CCheckBox::SetupText()
    6365{
    6466    if (!GetGUI())
  • source/gui/CCheckBox.h

     
    3838    /**
    3939     * @see IGUIObject#ResetStates()
    4040     */
    41     virtual void ResetStates() { IGUIButtonBehavior::ResetStates(); }
     41    virtual void ResetStates();
    4242
    4343    /**
    4444     * @see IGUIObject#HandleMessage()
  • source/gui/CDropDown.cpp

     
    470470            GUI<CGUISpriteInstance>::GetSettingPointer(this, "sprite2_pressed", sprite2_second);
    471471            GetGUI()->DrawSprite(GUI<>::FallBackSprite(*sprite2_second, *sprite2), cell_id, bz+0.05f, rect);
    472472        }
    473         else if (m_MouseHovering)
     473        else if (IsMouseHovering())
    474474        {
    475475            GUI<CGUISpriteInstance>::GetSettingPointer(this, "sprite2_over", sprite2_second);
    476476            GetGUI()->DrawSprite(GUI<>::FallBackSprite(*sprite2_second, *sprite2), cell_id, bz+0.05f, rect);
  • source/gui/CGUI.cpp

     
    170170            case SDL_BUTTON_LEFT:
    171171                if (pNearest)
    172172                {
    173                     double timeElapsed = timer_Time() - pNearest->m_LastClickTime[SDL_BUTTON_LEFT];
    174                     pNearest->m_LastClickTime[SDL_BUTTON_LEFT] = timer_Time();
     173                    double timeElapsed = timer_Time() - pNearest->GetLastClickTime(SDL_BUTTON_LEFT);
     174                    pNearest->SetLastClickTime(SDL_BUTTON_LEFT, timer_Time());
    175175
    176176                    //Double click?
    177177                    if (timeElapsed < SELECT_DBLCLICK_RATE)
     
    187187            case SDL_BUTTON_RIGHT:
    188188                if (pNearest)
    189189                {
    190                     double timeElapsed = timer_Time() - pNearest->m_LastClickTime[SDL_BUTTON_RIGHT];
    191                     pNearest->m_LastClickTime[SDL_BUTTON_RIGHT] = timer_Time();
     190                    double timeElapsed = timer_Time() - pNearest->GetLastClickTime(SDL_BUTTON_RIGHT);
     191                    pNearest->SetLastClickTime(SDL_BUTTON_RIGHT, timer_Time());
    192192
    193193                    //Double click?
    194194                    if (timeElapsed < SELECT_DBLCLICK_RATE)
  • source/gui/CInput.cpp

     
    7575{
    7676}
    7777
     78void CInput::ResetStates() { IGUIScrollBarOwner::ResetStates(); }
     79
    7880void CInput::UpdateBufferPositionSetting()
    7981{
    80     int* bufferPos = (int*)m_Settings["buffer_position"].m_pSetting;
     82    int* bufferPos = (int*)RefSetting("buffer_position").m_pSetting;
    8183    *bufferPos = m_iBufferPos;
    8284}
    8385
    8486void CInput::ClearComposedText()
    8587{
    86     CStrW* pCaption = (CStrW*)m_Settings["caption"].m_pSetting;
     88    CStrW* pCaption = (CStrW*)RefSetting("caption").m_pSetting;
    8789    pCaption->erase(m_iInsertPos, m_iComposedLength);
    8890    m_iBufferPos = m_iInsertPos;
    8991    UpdateBufferPositionSetting();
     
    106108    else if (ev->ev.type == SDL_TEXTINPUT)
    107109    {
    108110        // Text has been committed, either single key presses or through an IME
    109         CStrW* pCaption = (CStrW*)m_Settings["caption"].m_pSetting;
     111        CStrW* pCaption = (CStrW*)RefSetting("caption").m_pSetting;
    110112        std::wstring text = wstring_from_utf8(ev->ev.text.text);
    111113
    112114        m_WantedX = 0.0f;
     
    139141    {
    140142        // Text is being composed with an IME
    141143        // TODO: indicate this by e.g. underlining the uncommitted text
    142         CStrW* pCaption = (CStrW*)m_Settings["caption"].m_pSetting;
     144        CStrW* pCaption = (CStrW*)RefSetting("caption").m_pSetting;
    143145        const char* rawText = ev->ev.edit.text;
    144146        int rawLength = strlen(rawText);
    145147        std::wstring wtext = wstring_from_utf8(rawText);
     
    188190        // Since the GUI framework doesn't handle to set settings
    189191        //  in Unicode (CStrW), we'll simply retrieve the actual
    190192        //  pointer and edit that.
    191         CStrW* pCaption = (CStrW*)m_Settings["caption"].m_pSetting;
     193        CStrW* pCaption = (CStrW*)RefSetting("caption").m_pSetting;
    192194        bool shiftKeyPressed = g_keys[SDLK_RSHIFT] || g_keys[SDLK_LSHIFT];
    193195
    194196        int szChar = 0;
     
    527529
    528530InReaction CInput::ManuallyHandleHotkeyEvent(const SDL_Event_* ev)
    529531{
    530     CStrW* pCaption = (CStrW*)m_Settings["caption"].m_pSetting;
     532    CStrW* pCaption = (CStrW*)RefSetting("caption").m_pSetting;
    531533    bool shiftKeyPressed = g_keys[SDLK_RSHIFT] || g_keys[SDLK_LSHIFT];
    532534
    533535    std::string hotkey = static_cast<const char*>(ev->ev.user.data1);
     
    882884        if (m_ComposingText)
    883885            break;
    884886
    885         CStrW* pCaption = (CStrW*)m_Settings["caption"].m_pSetting;
     887        CStrW* pCaption = (CStrW*)RefSetting("caption").m_pSetting;
    886888
    887889        if (pCaption->empty())
    888890            break;
     
    11351137            mask_char = maskStr[0];
    11361138    }
    11371139    else
    1138         pCaption = (CStrW*)m_Settings["caption"].m_pSetting;
     1140        pCaption = (CStrW*)RefSetting("caption").m_pSetting;
    11391141
    11401142    CGUISpriteInstance* sprite = NULL;
    11411143    CGUISpriteInstance* sprite_selectarea = NULL;
     
    19521954
    19531955void CInput::DeleteCurSelection()
    19541956{
    1955     CStrW* pCaption = (CStrW*)m_Settings["caption"].m_pSetting;
     1957    CStrW* pCaption = (CStrW*)RefSetting("caption").m_pSetting;
    19561958
    19571959    int virtualFrom;
    19581960    int virtualTo;
  • source/gui/CInput.h

     
    4343    /**
    4444     * @see IGUIObject#ResetStates()
    4545     */
    46     virtual void ResetStates() { IGUIScrollBarOwner::ResetStates(); }
     46    virtual void ResetStates();
    4747
    4848    // Check where the mouse is hovering, and get the appropriate text position.
    4949    //  return is the text-position index.
  • source/gui/CList.cpp

     
    6565{
    6666}
    6767
     68void CList::ResetStates() { IGUIScrollBarOwner::ResetStates(); }
     69
    6870void CList::SetupText()
    6971{
    7072    if (!GetGUI())
  • source/gui/CList.h

     
    4040    /**
    4141     * @see IGUIObject#ResetStates()
    4242     */
    43     virtual void ResetStates() { IGUIScrollBarOwner::ResetStates(); }
     43    virtual void ResetStates();
    4444
    4545    /**
    4646     * Adds an item last to the list.
  • source/gui/CText.cpp

     
    6262{
    6363}
    6464
     65void CText::ResetStates() { IGUIScrollBarOwner::ResetStates(); }
     66
    6567void CText::SetupText()
    6668{
    6769    if (!GetGUI())
  • source/gui/CText.h

     
    3636    /**
    3737     * @see IGUIObject#ResetStates()
    3838     */
    39     virtual void ResetStates() { IGUIScrollBarOwner::ResetStates(); }
     39    virtual void ResetStates();
    4040
    4141    /**
    4242     * Test if mouse position is over an icon
  • source/gui/GUIutil.cpp

     
    320320{
    321321    ENSURE(pObject != NULL);
    322322
    323     std::map<CStr, SGUISetting>::const_iterator it = pObject->m_Settings.find(Setting);
    324     if (it == pObject->m_Settings.end())
     323   
     324    if (!pObject->SettingExists(Setting))
    325325    {
    326326        LOGWARNING("setting %s was not found on object %s",
    327327            Setting.c_str(),
     
    329329        return PSRETURN_GUI_InvalidSetting;
    330330    }
    331331
    332     if (it->second.m_pSetting == NULL)
     332    auto& ref = pObject->RefSetting(Setting);
     333    if (ref.m_pSetting == NULL)
    333334        return PSRETURN_GUI_InvalidSetting;
    334335
    335336#ifndef NDEBUG
     
    337338#endif
    338339
    339340    // Get value
    340     Value = (T*)(it->second.m_pSetting);
     341    Value = (T*)(ref.m_pSetting);
    341342
    342343    return PSRETURN_OK;
    343344}
     
    382383#endif
    383384
    384385    // Set value
    385     *(T*)pObject->m_Settings[Setting].m_pSetting = Value;
     386    *(T*)pObject->RefSetting(Setting).m_pSetting = Value;
    386387
    387388    //
    388389    //  Some settings needs special attention at change
  • source/gui/IGUIButtonBehavior.cpp

     
    146146        GUI<CColor>::GetSetting(this, "textcolor_disabled", color2);
    147147        return GUI<>::FallBackColor(color2, color);
    148148    }
    149     else if (m_MouseHovering)
     149    else if (IsMouseHovering())
    150150    {
    151151        if (m_Pressed)
    152152        {
     
    163163        return color;
    164164}
    165165
     166void IGUIButtonBehavior::ResetStates()
     167{
     168    // Notify the gui that we aren't hovered anymore
     169    UpdateMouseOver(NULL);
     170    m_Pressed = false;
     171    m_PressedRight = false;
     172}
     173
    166174void IGUIButtonBehavior::DrawButton(const CRect& rect, const float& z, CGUISpriteInstance& sprite, CGUISpriteInstance& sprite_over, CGUISpriteInstance& sprite_pressed, CGUISpriteInstance& sprite_disabled, int cell_id)
    167175{
    168176    if (!GetGUI())
     
    173181
    174182    if (!enabled)
    175183        GetGUI()->DrawSprite(GUI<>::FallBackSprite(sprite_disabled, sprite), cell_id, z, rect);
    176     else if (m_MouseHovering)
     184    else if (IsMouseHovering())
    177185    {
    178186        if (m_Pressed)
    179187            GetGUI()->DrawSprite(GUI<>::FallBackSprite(sprite_pressed, sprite), cell_id, z, rect);
  • source/gui/IGUIButtonBehavior.h

     
    8989    /**
    9090     * @see IGUIObject#ResetStates()
    9191     */
    92     virtual void ResetStates()
    93     {
    94         // Notify the gui that we aren't hovered anymore
    95         UpdateMouseOver(NULL);
    96         m_Pressed = false;
    97         m_PressedRight = false;
    98     }
     92    virtual void ResetStates();
    9993
    10094    /**
    10195     * Everybody knows how a button works, you don't simply press it,
  • source/gui/IGUIObject.cpp

     
    2424#include "ps/CLogger.h"
    2525#include "scriptinterface/ScriptInterface.h"
    2626
     27class IGUIObject::Impl
     28{
     29public:
     30    // Name of object
     31    CStr                                    name;
    2732
     33    // Constructed on the heap, will be destroyed along with the the object
     34    // TODO Gee: really the above?
     35    vector_pObjects                         children;
     36
     37    // Pointer to parent
     38    IGUIObject                              *pParent = nullptr;
     39
     40    //This represents the last click time for each mouse button
     41    std::vector<double>                     lastClickTime = std::vector<double>(6);
     42
     43    // Is mouse hovering the object? used with the function MouseOver()
     44    bool                                    mouseHovering = false;
     45
     46    // An object can't function stand alone
     47    CGUI                                    *pGUI = nullptr;
     48
     49    // Internal storage for registered script handlers.
     50    std::map<CStr, JS::Heap<JSObject*> >    scriptHandlers;
     51
     52    // Cached JSObject representing this GUI object
     53    DefPersistentRooted<JSObject*>          JSObject;
     54
     55    /**
     56    * Settings pool, all an object's settings are located here
     57    * If a derived object has got more settings that the base
     58    * settings, it's because they have a new version of the
     59    * function SetupSettings().
     60    *
     61    * @see SetupSettings()
     62    */
     63    std::map<CStr, SGUISetting>             settings;
     64};
     65
    2866IGUIObject::IGUIObject()
    29     : m_pGUI(NULL), m_pParent(NULL), m_MouseHovering(false), m_LastClickTime()
     67    : m_d(new Impl)
    3068{
    3169    AddSetting(GUIST_bool,          "enabled");
    3270    AddSetting(GUIST_bool,          "hidden");
     
    4785    GUI<bool>::SetSetting(this, "absolute", true);
    4886}
    4987
     88const CStr& IGUIObject::GetName() const { return m_d->name; }
     89void IGUIObject::SetName(const CStr& Name) { m_d->name = Name; }
     90vector_pObjects::iterator IGUIObject::begin() { return m_d->children.begin(); }
     91vector_pObjects::iterator IGUIObject::end() { return m_d->children.end(); }
     92void IGUIObject::SetParent(IGUIObject* pParent) { m_d->pParent = pParent; }
     93double IGUIObject::GetLastClickTime(int name) const { return m_d->lastClickTime[name]; } //TODO: possible need check for array range
     94void IGUIObject::SetLastClickTime(int name, double time) { m_d->lastClickTime[name] = time; } //TODO: possible need check for array range
     95bool IGUIObject::IsMouseHovering() const { return m_d->mouseHovering; }
     96void IGUIObject::SetMouseHovering(bool hover) { m_d->mouseHovering = hover; }
     97CGUI* IGUIObject::GetGUI() { return m_d->pGUI; }
     98const CGUI* IGUIObject::GetGUI() const { return m_d->pGUI; }
     99SGUISetting& IGUIObject::RefSetting(const CStr& name) { return m_d->settings[name]; }
     100const SGUISetting& IGUIObject::RefSetting(const CStr& name) const { return m_d->settings[name]; }
     101std::map<CStr, SGUISetting>& IGUIObject::GetSettings() { return m_d->settings; }
     102const std::map<CStr, SGUISetting>& IGUIObject::GetSettings() const { return m_d->settings; }
     103
     104JS::Heap<JSObject*>* IGUIObject::GetJsEventHandler(const CStr& eventName)
     105{
     106    auto it = m_d->scriptHandlers.find(eventName);
     107    if (it == m_d->scriptHandlers.end())
     108        return nullptr;
     109
     110    return &it->second;
     111}
     112
     113void IGUIObject::ResetStates()
     114{
     115    // Notify the gui that we aren't hovered anymore
     116    UpdateMouseOver(NULL);
     117}
     118
    50119IGUIObject::~IGUIObject()
    51120{
    52     for (const std::pair<CStr, SGUISetting>& p : m_Settings)
     121    for (const auto& p : m_d->settings)
    53122        switch (p.second.m_Type)
    54123        {
    55124            // delete() needs to know the type of the variable - never delete a void*
     
    60129            debug_warn(L"Invalid setting type");
    61130        }
    62131
    63     if (m_pGUI)
    64         JS_RemoveExtraGCRootsTracer(m_pGUI->GetScriptInterface()->GetJSRuntime(), Trace, this);
     132    if (GetGUI())
     133        JS_RemoveExtraGCRootsTracer(GetGUI()->GetScriptInterface()->GetJSRuntime(), Trace, this);
    65134}
    66135
    67136//-------------------------------------------------------------------
     
    69138//-------------------------------------------------------------------
    70139void IGUIObject::SetGUI(CGUI* const& pGUI)
    71140{
    72     if (!m_pGUI)
     141    if (!m_d->pGUI)
    73142        JS_AddExtraGCRootsTracer(pGUI->GetScriptInterface()->GetJSRuntime(), Trace, this);
    74     m_pGUI = pGUI;
     143    m_d->pGUI = pGUI;
    75144}
    76145
     146vector_pObjects& IGUIObject::GetChildren() { return m_d->children; }
     147
    77148void IGUIObject::AddChild(IGUIObject* pChild)
    78149{
    79150//  ENSURE(pChild);
     
    80151
    81152    pChild->SetParent(this);
    82153
    83     m_Children.push_back(pChild);
     154    GetChildren().push_back(pChild);
    84155
    85156    // If this (not the child) object is already attached
    86157    //  to a CGUI, it pGUI pointer will be non-null.
     
    99170        {
    100171            // If anything went wrong, reverse what we did and throw
    101172            //  an exception telling it never added a child
    102             m_Children.erase(m_Children.end()-1);
     173            GetChildren().pop_back();
    103174
    104175            throw;
    105176        }
     
    110181void IGUIObject::AddToPointersMap(map_pObjects& ObjectMap)
    111182{
    112183    // Just don't do anything about the top node
    113     if (m_pParent == NULL)
     184    if (m_d->pParent == NULL)
    114185        return;
    115186
    116187    // Now actually add this one
    117188    //  notice we won't add it if it's doesn't have any parent
    118189    //  (i.e. being the base object)
    119     if (m_Name.empty())
     190    const auto& name = GetName();
     191    if (name.empty())
    120192    {
    121193        throw PSERROR_GUI_ObjectNeedsName();
    122194    }
    123     if (ObjectMap.count(m_Name) > 0)
     195    if (ObjectMap.count(name) > 0)
    124196    {
    125         throw PSERROR_GUI_NameAmbiguity(m_Name.c_str());
     197        throw PSERROR_GUI_NameAmbiguity(name.c_str());
    126198    }
    127199    else
    128200    {
    129         ObjectMap[m_Name] = this;
     201        ObjectMap[name] = this;
    130202    }
    131203}
    132204
     
    138210void IGUIObject::AddSetting(const EGUISettingType& Type, const CStr& Name)
    139211{
    140212    // Is name already taken?
    141     if (m_Settings.count(Name) >= 1)
     213    if (m_d->settings.count(Name) >= 1)
    142214        return;
    143215
    144216    // Construct, and set type
    145     m_Settings[Name].m_Type = Type;
     217    m_d->settings[Name].m_Type = Type;
    146218
    147219    switch (Type)
    148220    {
    149221#define TYPE(type) \
    150222    case GUIST_##type: \
    151         m_Settings[Name].m_pSetting = new type(); \
     223        m_d->settings[Name].m_pSetting = new type(); \
    152224        break;
    153225
    154226        // Construct the setting.
     
    189261    // Check if this is the object being hovered.
    190262    if (pMouseOver == this)
    191263    {
    192         if (!m_MouseHovering)
     264        if (!IsMouseHovering())
    193265        {
    194266            // It wasn't hovering, so that must mean it just entered
    195267            SendEvent(GUIM_MOUSE_ENTER, "mouseenter");
     
    196268        }
    197269
    198270        // Either way, set to true
    199         m_MouseHovering = true;
     271        SetMouseHovering(true);
    200272
    201273        // call mouse over
    202274        SendEvent(GUIM_MOUSE_OVER, "mousemove");
     
    203275    }
    204276    else // Some other object (or none) is hovered
    205277    {
    206         if (m_MouseHovering)
     278        if (IsMouseHovering())
    207279        {
    208             m_MouseHovering = false;
     280            SetMouseHovering(false);
    209281            SendEvent(GUIM_MOUSE_LEAVE, "mouseleave");
    210282        }
    211283    }
     
    218290    //  we need to make no further updates on this function
    219291    //  in derived classes.
    220292    //return (GetSettingsInfo().count(Setting) >= 1);
    221     return (m_Settings.count(Setting) >= 1);
     293    return (m_d->settings.count(Setting) >= 1);
    222294}
    223295
    224296PSRETURN IGUIObject::SetSetting(const CStr& Setting, const CStrW& Value, const bool& SkipMessage)
     
    227299        return PSRETURN_GUI_InvalidSetting;
    228300
    229301    // Get setting
    230     SGUISetting set = m_Settings[Setting];
     302    SGUISetting set = m_d->settings[Setting];
    231303
    232304#define TYPE(type) \
    233305    else if (set.m_Type == GUIST_##type) \
     
    259331    if (!SettingExists(Setting))
    260332        return LogInvalidSettings(Setting);
    261333
    262     if (m_Settings.find(Setting) == m_Settings.end())
    263         return LogInvalidSettings(Setting);
     334    Type = RefSetting(Setting).m_Type;
    264335
    265     Type = m_Settings.find(Setting)->second.m_Type;
    266 
    267336    return PSRETURN_OK;
    268337}
    269338
     
    292361{
    293362    // Important, we're not using GetParent() for these
    294363    //  checks, that could screw it up
    295     if (m_pParent)
     364    if (m_d->pParent)
    296365    {
    297         if (m_pParent->m_pParent == NULL)
     366        if (m_d->pParent->m_d->pParent == NULL)
    298367            return NULL;
    299368    }
    300369
    301     return m_pParent;
     370    return m_d->pParent;
    302371}
    303372
    304373void IGUIObject::UpdateCachedSize()
     
    315384    // If absolute="false" and the object has got a parent,
    316385    //  use its cached size instead of the screen. Notice
    317386    //  it must have just been cached for it to work.
    318     if (absolute == false && m_pParent && !IsRootObject())
    319         m_CachedActualSize = ca.GetClientArea(m_pParent->m_CachedActualSize);
     387    if (absolute == false && m_d->pParent && !IsRootObject())
     388        m_CachedActualSize = ca.GetClientArea(m_d->pParent->m_CachedActualSize);
    320389    else
    321390        m_CachedActualSize = ca.GetClientArea(CRect(0.f, 0.f, g_xres * g_GuiScale, g_yres * g_GuiScale));
    322391
     
    433502{
    434503    // m_ScriptHandlers is only rooted after SetGUI() has been called (which sets up the GC trace callbacks),
    435504    // so we can't safely store objects in it if the GUI hasn't been set yet.
    436     ENSURE(m_pGUI && "A GUI must be associated with the GUIObject before adding ScriptHandlers!");
    437     m_ScriptHandlers[Action] = JS::Heap<JSObject*>(Function);
     505    ENSURE(m_d->pGUI && "A GUI must be associated with the GUIObject before adding ScriptHandlers!");
     506    m_d->scriptHandlers[Action] = JS::Heap<JSObject*>(Function);
    438507}
    439508
    440509InReaction IGUIObject::SendEvent(EGUIMessageType type, const CStr& EventName)
     
    441510{
    442511    PROFILE2_EVENT("gui event");
    443512    PROFILE2_ATTR("type: %s", EventName.c_str());
    444     PROFILE2_ATTR("object: %s", m_Name.c_str());
     513    PROFILE2_ATTR("object: %s", GetName().c_str());
    445514
    446515    SGUIMessage msg(type);
    447516    HandleMessage(msg);
     
    453522
    454523void IGUIObject::ScriptEvent(const CStr& Action)
    455524{
    456     std::map<CStr, JS::Heap<JSObject*>>::iterator it = m_ScriptHandlers.find(Action);
    457     if (it == m_ScriptHandlers.end())
     525    auto it = m_d->scriptHandlers.find(Action);
     526    if (it == m_d->scriptHandlers.end())
    458527        return;
    459528
    460     JSContext* cx = m_pGUI->GetScriptInterface()->GetContext();
     529    JSContext* cx = m_d->pGUI->GetScriptInterface()->GetContext();
    461530    JSAutoRequest rq(cx);
    462531
    463532    // Set up the 'mouse' parameter
    464533    JS::RootedValue mouse(cx);
    465     m_pGUI->GetScriptInterface()->Eval("({})", &mouse);
    466     m_pGUI->GetScriptInterface()->SetProperty(mouse, "x", m_pGUI->m_MousePos.x, false);
    467     m_pGUI->GetScriptInterface()->SetProperty(mouse, "y", m_pGUI->m_MousePos.y, false);
    468     m_pGUI->GetScriptInterface()->SetProperty(mouse, "buttons", m_pGUI->m_MouseButtons, false);
     534    m_d->pGUI->GetScriptInterface()->Eval("({})", &mouse);
     535    m_d->pGUI->GetScriptInterface()->SetProperty(mouse, "x", m_d->pGUI->m_MousePos.x, false);
     536    m_d->pGUI->GetScriptInterface()->SetProperty(mouse, "y", m_d->pGUI->m_MousePos.y, false);
     537    m_d->pGUI->GetScriptInterface()->SetProperty(mouse, "buttons", m_d->pGUI->m_MouseButtons, false);
    469538
    470539    JS::AutoValueVector paramData(cx);
    471540    paramData.append(mouse);
     
    482551
    483552void IGUIObject::ScriptEvent(const CStr& Action, JS::HandleValue Argument)
    484553{
    485     std::map<CStr, JS::Heap<JSObject*>>::iterator it = m_ScriptHandlers.find(Action);
    486     if (it == m_ScriptHandlers.end())
     554    auto it = m_d->scriptHandlers.find(Action);
     555    if (it == m_d->scriptHandlers.end())
    487556        return;
    488557
    489     JSContext* cx = m_pGUI->GetScriptInterface()->GetContext();
     558    JSContext* cx = m_d->pGUI->GetScriptInterface()->GetContext();
    490559    JSAutoRequest rq(cx);
    491560    JS::AutoValueVector paramData(cx);
    492561    paramData.append(Argument.get());
     
    502571
    503572JSObject* IGUIObject::GetJSObject()
    504573{
    505     JSContext* cx = m_pGUI->GetScriptInterface()->GetContext();
     574    JSContext* cx = m_d->pGUI->GetScriptInterface()->GetContext();
    506575    JSAutoRequest rq(cx);
    507576    // Cache the object when somebody first asks for it, because otherwise
    508577    // we end up doing far too much object allocation. TODO: Would be nice to
    509578    // not have these objects hang around forever using up memory, though.
    510     if (m_JSObject.uninitialized())
     579    if (m_d->JSObject.uninitialized())
    511580    {
    512         m_JSObject.set(cx, m_pGUI->GetScriptInterface()->CreateCustomObject("GUIObject"));
    513         JS_SetPrivate(m_JSObject.get(), this);
     581        m_d->JSObject.set(cx, m_d->pGUI->GetScriptInterface()->CreateCustomObject("GUIObject"));
     582        JS_SetPrivate(m_d->JSObject.get(), this);
    514583    }
    515     return m_JSObject.get();
     584    return m_d->JSObject.get();
    516585}
    517586
    518587CStr IGUIObject::GetPresentableName() const
     
    519588{
    520589    // __internal(), must be at least 13 letters to be able to be
    521590    //  an internal name
    522     if (m_Name.length() <= 12)
    523         return m_Name;
     591    const auto& name = GetName();
     592    if (name.length() <= 12)
     593        return name;
    524594
    525     if (m_Name.substr(0, 10) == "__internal")
     595    if (name.substr(0, 10) == "__internal")
    526596        return CStr("[unnamed object]");
    527597    else
    528         return m_Name;
     598        return name;
    529599}
    530600
    531601void IGUIObject::SetFocus()
     
    540610
    541611bool IGUIObject::IsRootObject() const
    542612{
    543     return GetGUI() != 0 && m_pParent == GetGUI()->m_BaseObject;
     613    return GetGUI() != 0 && m_d->pParent == GetGUI()->m_BaseObject;
    544614}
    545615
    546616void IGUIObject::TraceMember(JSTracer* trc)
    547617{
    548     for (std::pair<const CStr, JS::Heap<JSObject*>>& handler : m_ScriptHandlers)
     618    for (auto& handler : m_d->scriptHandlers)
    549619        JS_CallHeapObjectTracer(trc, &handler.second, "IGUIObject::m_ScriptHandlers");
    550620}
    551621
  • source/gui/IGUIObject.h

     
    155155    //@{
    156156
    157157    /// Get object name, name is unique
    158     const CStr& GetName() const { return m_Name; }
     158    const CStr& GetName() const;
    159159
    160160    /// Get object name
    161     void SetName(const CStr& Name) { m_Name = Name; }
     161    void SetName(const CStr& Name);
    162162
     163    CGUI* GetGUI();
     164    const CGUI* GetGUI() const;
     165
     166    /**
     167    * Take focus!
     168    */
     169    void SetFocus();
     170
    163171    // Get Presentable name.
    164172    //  Will change all internally set names to something like "<unnamed object>"
    165173    CStr GetPresentableName() const;
    166174
    167175    /**
     176    * This function is called with different messages
     177    * for instance when the mouse enters the object.
     178    *
     179    * @param Message GUI Message
     180    */
     181    virtual void HandleMessage(SGUIMessage& UNUSED(Message)) {}
     182
     183    /**
    168184     * Adds object and its children to the map, it's name being the
    169185     * first part, and the second being itself.
    170186     *
     
    201217    //--------------------------------------------------------
    202218    //@{
    203219
    204     vector_pObjects::iterator begin() { return m_Children.begin(); }
    205     vector_pObjects::iterator end() { return m_Children.end(); }
     220    vector_pObjects::iterator begin();
     221    vector_pObjects::iterator end();
    206222
    207223    //@}
    208224    //--------------------------------------------------------
     
    220236     */
    221237    bool SettingExists(const CStr& Setting) const;
    222238
     239    std::map<CStr, SGUISetting>& GetSettings();
     240    const std::map<CStr, SGUISetting>& GetSettings() const;
     241    SGUISetting& RefSetting(const CStr& name);
     242    const SGUISetting& RefSetting(const CStr& name) const;
     243
    223244    /**
     245    * Add a setting to m_Settings
     246    *
     247    * @param Type Setting type
     248    * @param Name Setting reference name
     249    */
     250    void AddSetting(const EGUISettingType& Type, const CStr& Name);
     251
     252    /**
    224253     * All sizes are relative to resolution, and the calculation
    225254     * is not wanted in real time, therefore it is cached, update
    226255     * the cached size with this function.
     
    277306    //--------------------------------------------------------
    278307    //@{
    279308
    280     /**
    281      * Add a setting to m_Settings
    282      *
    283      * @param Type Setting type
    284      * @param Name Setting reference name
    285      */
    286     void AddSetting(const EGUISettingType& Type, const CStr& Name);
    287309
    288310    /**
    289311     * Calls Destroy on all children, and deallocates all memory.
     
    291313     */
    292314    virtual void Destroy();
    293315
    294 public:
    295     /**
    296      * This function is called with different messages
    297      * for instance when the mouse enters the object.
    298      *
    299      * @param Message GUI Message
     316    /*
     317     * Return children of this widget
    300318     */
    301     virtual void HandleMessage(SGUIMessage& UNUSED(Message)) {}
     319    vector_pObjects& GetChildren();
    302320
    303 protected:
    304321    /**
    305322     * Draws the object.
    306323     *
     
    352369    /**
    353370     * Set parent of this object
    354371     */
    355     void SetParent(IGUIObject* pParent) { m_pParent = pParent; }
     372    void SetParent(IGUIObject* pParent);
    356373
    357374    /**
    358375     * Reset internal state of this object
    359376     */
    360     virtual void ResetStates()
    361     {
    362         // Notify the gui that we aren't hovered anymore
    363         UpdateMouseOver(NULL);
    364     }
     377    virtual void ResetStates();
    365378
    366 public:
    367     CGUI* GetGUI() { return m_pGUI; }
    368     const CGUI* GetGUI() const { return m_pGUI; }
    369 
    370     /**
    371      * Take focus!
    372      */
    373     void SetFocus();
    374 
    375379protected:
    376380    /**
    377381     * Check if object is focused.
     
    443447
    444448    void SetScriptHandler(const CStr& Action, JS::HandleObject Function);
    445449
     450    double GetLastClickTime(int name) const;
     451    void SetLastClickTime(int name, double time);
     452
    446453    /**
     454    * This is an array of true or false, each element is associated with
     455    * a string representing a setting. Number of elements is equal to
     456    * number of settings.
     457    *
     458    * A true means the setting has been manually set in the file when
     459    * read. This is important to know because I don't want to force
     460    * the user to include its \<styles\>-XML-files first, so somehow
     461    * the GUI needs to know which settings were set, and which is meant
     462    * to.
     463    */
     464
     465    // More variables
     466    bool IsMouseHovering() const;
     467    void SetMouseHovering(bool hover);
     468
     469    /**
    447470     * Inputes the object that is currently hovered, this function
    448471     * updates this object accordingly (i.e. if it's the object
    449472     * being inputted one thing happens, and not, another).
     
    493516
    494517    void TraceMember(JSTracer* trc);
    495518
    496     // Variables
     519    JS::Heap<JSObject*>* GetJsEventHandler(const CStr& eventName);
    497520
    498 protected:
    499     // Name of object
    500     CStr                                    m_Name;
    501 
    502     // Constructed on the heap, will be destroyed along with the the object
    503     // TODO Gee: really the above?
    504     vector_pObjects                         m_Children;
    505 
    506     // Pointer to parent
    507     IGUIObject                              *m_pParent;
    508 
    509     //This represents the last click time for each mouse button
    510     double m_LastClickTime[6];
    511 
    512     /**
    513      * This is an array of true or false, each element is associated with
    514      * a string representing a setting. Number of elements is equal to
    515      * number of settings.
    516      *
    517      * A true means the setting has been manually set in the file when
    518      * read. This is important to know because I don't want to force
    519      * the user to include its \<styles\>-XML-files first, so somehow
    520      * the GUI needs to know which settings were set, and which is meant
    521      * to.
    522      */
    523 
    524     // More variables
    525 
    526     // Is mouse hovering the object? used with the function MouseOver()
    527     bool                                    m_MouseHovering;
    528 
    529     /**
    530      * Settings pool, all an object's settings are located here
    531      * If a derived object has got more settings that the base
    532      * settings, it's because they have a new version of the
    533      * function SetupSettings().
    534      *
    535      * @see SetupSettings()
    536      */
    537     public:
    538     std::map<CStr, SGUISetting>             m_Settings;
    539 
    540 private:
    541     // An object can't function stand alone
    542     CGUI                                    *m_pGUI;
    543 
    544     // Internal storage for registered script handlers.
    545     std::map<CStr, JS::Heap<JSObject*> > m_ScriptHandlers;
    546 
    547     // Cached JSObject representing this GUI object
    548     DefPersistentRooted<JSObject*>           m_JSObject;
     521    class Impl;
     522    std::unique_ptr<Impl> m_d;
    549523};
    550524
    551525
  • source/gui/MiniMap.cpp

     
    7070    AddSetting(GUIST_CStrW,     "tooltip");
    7171    AddSetting(GUIST_CStr,      "tooltip_style");
    7272    m_Clicking = false;
    73     m_MouseHovering = false;
    7473
    7574    // Register Relax NG validator
    7675    CXeromyces::AddValidator(g_VFS, "pathfinder", "simulation/data/pathfinder.rng");
     
    143142    switch (Message.type)
    144143    {
    145144    case GUIM_MOUSE_PRESS_LEFT:
    146         if (m_MouseHovering)
     145        if (IsMouseHovering())
    147146        {
    148147            SetCameraPos();
    149148            m_Clicking = true;
     
    150149        }
    151150        break;
    152151    case GUIM_MOUSE_RELEASE_LEFT:
    153         if (m_MouseHovering && m_Clicking)
     152        if (IsMouseHovering() && m_Clicking)
    154153            SetCameraPos();
    155154        m_Clicking = false;
    156155        break;
    157156    case GUIM_MOUSE_DBLCLICK_LEFT:
    158         if (m_MouseHovering && m_Clicking)
     157        if (IsMouseHovering() && m_Clicking)
    159158            SetCameraPos();
    160159        m_Clicking = false;
    161160        break;
    162161    case GUIM_MOUSE_ENTER:
    163         m_MouseHovering = true;
     162        SetMouseHovering(true);
    164163        break;
    165164    case GUIM_MOUSE_LEAVE:
    166165        m_Clicking = false;
    167         m_MouseHovering = false;
     166        SetMouseHovering(false);
    168167        break;
    169168    case GUIM_MOUSE_RELEASE_RIGHT:
    170169        CMiniMap::FireWorldClickEvent(SDL_BUTTON_RIGHT, 1);
     
    173172        CMiniMap::FireWorldClickEvent(SDL_BUTTON_RIGHT, 2);
    174173        break;
    175174    case GUIM_MOUSE_MOTION:
    176         if (m_MouseHovering && m_Clicking)
     175        if (IsMouseHovering() && m_Clicking)
    177176            SetCameraPos();
    178177        break;
    179178    case GUIM_MOUSE_WHEEL_DOWN:
  • source/gui/scripting/JSInterface_IGUIObject.cpp

     
    8989    if (propName.substr(0, 2) == "on")
    9090    {
    9191        CStr eventName(CStr(propName.substr(2)).LowerCase());
    92         std::map<CStr, JS::Heap<JSObject*>>::iterator it = e->m_ScriptHandlers.find(eventName);
    93         if (it == e->m_ScriptHandlers.end())
     92        auto* jsHeapObjectPtr = e->GetJsEventHandler(eventName);
     93        if (jsHeapObjectPtr == nullptr)
    9494            vp.setNull();
    9595        else
    96             vp.setObject(*it->second.get());
     96            vp.setObject(*jsHeapObjectPtr->get());
    9797        return true;
    9898    }
    9999