summaryrefslogtreecommitdiff
path: root/wx+/choice_enum.h
blob: a590861a0e5e4e5c300b3cd505f7678e97d7d9d2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// *****************************************************************************
// * This file is part of the FreeFileSync project. It is distributed under    *
// * GNU General Public License: https://www.gnu.org/licenses/gpl-3.0          *
// * Copyright (C) Zenju (zenju AT freefilesync DOT org) - All Rights Reserved *
// *****************************************************************************

#ifndef CHOICE_ENUM_H_132413545345687
#define CHOICE_ENUM_H_132413545345687

#include <unordered_map>
#include <vector>
#include <wx/choice.h>

//handle mapping of enum values to wxChoice controls
/*
Example:

Member variable:
    zen::EnumDescrList<EnumOnError> enumDescrMap;

Constructor code:
    enumDescrMap.
    add(ON_ERROR_POPUP,  "Show pop-up",    "Show pop-up on errors or warnings"). <- add localization
    add(ON_ERROR_IGNORE, "Ignore errors",  "Hide all error and warning messages").
    add(ON_ERROR_EXIT,   "Exit instantly", "Abort synchronization immediately");

Set enum value:
    setEnumVal(enumDescrMap, *m_choiceHandleError, value);

Get enum value:
    value = getEnumVal(enumDescrMap, *m_choiceHandleError)

Update enum tooltips (after user changed selection):
    updateTooltipEnumVal(enumDescrMap, *m_choiceHandleError);
*/

namespace zen
{
template <class Enum>
struct EnumDescrList
{
    EnumDescrList& add(Enum value, const wxString& text, const wxString& tooltip = {})
    {
        descrList.push_back({value, {text, tooltip}});
        return *this;
    }

    using DescrList = std::vector<std::pair<Enum, std::pair<wxString, wxString>>>;
    DescrList descrList;

    std::unordered_map<const wxChoice*, std::vector<wxString>> itemsSetLast;
};
template <class Enum> void setEnumVal(const EnumDescrList<Enum>& mapping, wxChoice& ctrl, Enum value);
template <class Enum> Enum getEnumVal(const EnumDescrList<Enum>& mapping, const wxChoice& ctrl);
template <class Enum> void updateTooltipEnumVal(const EnumDescrList<Enum>& mapping, wxChoice& ctrl);














//--------------- impelementation -------------------------------------------
template <class Enum>
void setEnumVal(EnumDescrList<Enum>& mapping, wxChoice& ctrl, Enum value)
{
    auto& itemsSetLast = mapping.itemsSetLast[&ctrl];

    std::vector<wxString> items;
    for (auto it = mapping.descrList.begin(); it != mapping.descrList.end(); ++it)
        items.push_back(it->second.first);

    if (items != itemsSetLast)
    {
        ctrl.Set(items); //expensive as fuck! => only call when absolutely needed!
        itemsSetLast = std::move(items);
    }
    //-----------------------------------------------------------------

    const auto it = std::find_if(mapping.descrList.begin(), mapping.descrList.end(), [&](const auto& mapItem) { return mapItem.first == value; });
    if (it != mapping.descrList.end())
    {
        if (const wxString& tooltip = it->second.second;
            !tooltip.empty())
            ctrl.SetToolTip(tooltip);
        else
            ctrl.UnsetToolTip();

        const int selectedPos = it - mapping.descrList.begin();
        ctrl.SetSelection(selectedPos);
    }
    else assert(false);
}

template <class Enum>
Enum getEnumVal(const EnumDescrList<Enum>& mapping, const wxChoice& ctrl)
{
    const int selectedPos = ctrl.GetSelection();

    if (0 <= selectedPos && selectedPos < std::ssize(mapping.descrList))
        return mapping.descrList[selectedPos].first;
    else
    {
        assert(false);
        return Enum(0);
    }
}

template <class Enum> void updateTooltipEnumVal(const EnumDescrList<Enum>& mapping, wxChoice& ctrl)
{
    const int selectedPos = ctrl.GetSelection();

    if (0 <= selectedPos && selectedPos < std::ssize(mapping.descrList))
    {
        if (const auto& [text, tooltip] = mapping.descrList[selectedPos].second;
            !tooltip.empty())
            ctrl.SetToolTip(tooltip);
        else
            ctrl.UnsetToolTip();
    }
    else assert(false);
}
}

#endif //CHOICE_ENUM_H_132413545345687
bgstack15