GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/gui/widgets/tabs/setup_input.cpp Lines: 106 198 53.5 %
Date: 2021-03-17 Branches: 95 266 35.7 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2007  Joshua Langley <[email protected]>
4
 *  Copyright (C) 2009  The Mana World Development Team
5
 *  Copyright (C) 2009-2010  The Mana Developers
6
 *  Copyright (C) 2011-2019  The ManaPlus Developers
7
 *  Copyright (C) 2019-2021  Andrei Karas
8
 *
9
 *  This file is part of The ManaPlus Client.
10
 *
11
 *  This program is free software; you can redistribute it and/or modify
12
 *  it under the terms of the GNU General Public License as published by
13
 *  the Free Software Foundation; either version 2 of the License, or
14
 *  any later version.
15
 *
16
 *  This program is distributed in the hope that it will be useful,
17
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 *  GNU General Public License for more details.
20
 *
21
 *  You should have received a copy of the GNU General Public License
22
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
23
 */
24
25
#include "gui/widgets/tabs/setup_input.h"
26
27
#include "configuration.h"
28
29
#include "const/gui/pages.h"
30
31
#include "input/inputactionoperators.h"
32
#include "input/inputmanager.h"
33
#include "input/keyboardconfig.h"
34
35
#include "input/pages/craft.h"
36
#include "input/pages/emotes.h"
37
#include "input/pages/move.h"
38
#include "input/pages/outfits.h"
39
#include "input/pages/shortcuts.h"
40
41
#include "gui/gui.h"
42
#include "gui/setupinputpages.h"
43
44
#include "gui/windows/okdialog.h"
45
46
#include "gui/widgets/button.h"
47
#include "gui/widgets/containerplacer.h"
48
#include "gui/widgets/createwidget.h"
49
#include "gui/widgets/layouthelper.h"
50
#include "gui/widgets/listbox.h"
51
#include "gui/widgets/scrollarea.h"
52
#include "gui/widgets/tabstrip.h"
53
54
#include "gui/models/keylistmodel.h"
55
56
#include "utils/delete2.h"
57
#include "utils/gettext.h"
58
59
#include "debug.h"
60
61
2
Setup_Input::Setup_Input(const Widget2 *const widget) :
62
    SetupTab(widget),
63
4
    mKeyListModel(new KeyListModel),
64


8
    mKeyList(CREATEWIDGETR(ListBox, this, mKeyListModel, "")),
65
    // TRANSLATORS: button in input settings tab
66
2
    mAssignKeyButton(new Button(this, _("Assign"), "assign",
67

2
        BUTTON_SKIN, this)),
68
    // TRANSLATORS: button in input settings tab
69
2
    mUnassignKeyButton(new Button(this, _("Unassign"), "unassign",
70

2
        BUTTON_SKIN, this)),
71
    // TRANSLATORS: button in input settings tab
72
2
    mDefaultButton(new Button(this, _("Default"), "default",
73

2
        BUTTON_SKIN, this)),
74
    // TRANSLATORS: button in input settings tab
75
2
    mResetKeysButton(new Button(this, _("Reset all keys"), "resetkeys",
76

2
        BUTTON_SKIN, this)),
77


8
    mTabs(new TabStrip(this, config.getIntValue("fontSize") + 10, 0)),
78
2
    mScrollArea(new ScrollArea(this, mKeyList,
79

4
        Opaque_true, "setup_input_background.xml")),
80
    mKeySetting(false),
81





76
    mActionDataSize(new int [SETUP_PAGES])
82
{
83
2
    inputManager.setSetupInput(this);
84
    // TRANSLATORS: setting tab name
85
10
    setName(_("Input"));
86
87
4
    mKeyListModel->setSelectedData(0);
88
89
22
    for (int f = 0; f < SETUP_PAGES; f ++)
90
    {
91
        int cnt = 0;
92
2548
        while (!setupActionData[f][cnt].name.empty())
93
836
            cnt ++;
94
20
        mActionDataSize[f] = cnt;
95
    }
96
97
4
    mKeyListModel->setSize(mActionDataSize[0]);
98
2
    refreshKeys();
99
2
    if (gui != nullptr)
100
4
        mKeyList->setFont(gui->getHelpFont());
101
2
    mKeyList->addActionListener(this);
102
103
2
    mScrollArea->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER);
104
2
    mAssignKeyButton->addActionListener(this);
105
4
    mAssignKeyButton->setEnabled(false);
106
2
    mUnassignKeyButton->addActionListener(this);
107
4
    mUnassignKeyButton->setEnabled(false);
108
2
    mResetKeysButton->addActionListener(this);
109
2
    mDefaultButton->addActionListener(this);
110
111
2
    mTabs->addActionListener(this);
112
10
    mTabs->setActionEventId("tabs_");
113
2
    int k = 0;
114
42
    while (pages[k] != nullptr)
115
    {
116

140
        mTabs->addButton(gettext(pages[k]), pages[k], false);
117
20
        k ++;
118
    }
119
120
2
    fixTranslations();
121
122
    // Do the layout
123
4
    LayoutHelper h(this);
124
2
    ContainerPlacer place = h.getPlacer(0, 0);
125
126
2
    place(0, 0, mTabs, 5, 1);
127
4
    place(0, 1, mScrollArea, 5, 5).setPadding(2);
128
2
    place(0, 6, mResetKeysButton, 1, 1);
129
2
    place(2, 6, mAssignKeyButton, 1, 1);
130
2
    place(3, 6, mUnassignKeyButton, 1, 1);
131
2
    place(4, 6, mDefaultButton, 1, 1);
132
133
2
    int width = 600;
134

8
    if (config.getIntValue("screenwidth") >= 730)
135
2
        width += 100;
136
137
2
    setDimension(Rect(0, 0, width, 350));
138
2
}
139
140
6
Setup_Input::~Setup_Input()
141
{
142
2
    delete2(mKeyList)
143
4
    delete2(mKeyListModel)
144
2
    delete2(mAssignKeyButton)
145
2
    delete2(mUnassignKeyButton)
146
2
    delete2(mResetKeysButton)
147
2
    delete [] mActionDataSize;
148
2
    mActionDataSize = nullptr;
149
2
    delete2(mScrollArea)
150
4
}
151
152
void Setup_Input::apply()
153
{
154
    keyUnresolved();
155
    InputActionT key1;
156
    InputActionT key2;
157
158
    if (inputManager.hasConflicts(key1, key2))
159
    {
160
        const std::string str1 = keyToString(key1);
161
        const std::string str2 = keyToString(key2);
162
163
        CREATEWIDGET(OkDialog,
164
            // TRANSLATORS: input settings error header
165
            _("Key Conflict(s) Detected."),
166
            // TRANSLATORS: input settings error
167
            strprintf(_("Conflict \"%s\" and \"%s\" keys. "
168
            "Resolve them, or gameplay may result in strange behaviour."),
169
            gettext(str1.c_str()), gettext(str2.c_str())),
170
            // TRANSLATORS: ok dialog button
171
            _("OK"),
172
            DialogType::ERROR,
173
            Modal_true,
174
            ShowCenter_true,
175
            nullptr,
176
            260);
177
    }
178
    keyboard.setEnabled(true);
179
    inputManager.store();
180
}
181
182
void Setup_Input::cancel()
183
{
184
    keyUnresolved();
185
    inputManager.retrieve();
186
    keyboard.setEnabled(true);
187
    refreshKeys();
188
}
189
190
void Setup_Input::action(const ActionEvent &event)
191
{
192
    const std::string &id = event.getId();
193
    const int selectedData = mKeyListModel->getSelectedData();
194
195
    if (event.getSource() == mKeyList)
196
    {
197
        if (!mKeySetting)
198
        {
199
            const int i(mKeyList->getSelected());
200
            if (i >= 0 && i < mActionDataSize[selectedData])
201
            {
202
                if (setupActionData[selectedData][i].actionId
203
                    == InputAction::NO_VALUE)
204
                {
205
                    mAssignKeyButton->setEnabled(false);
206
                    mUnassignKeyButton->setEnabled(false);
207
                }
208
                else
209
                {
210
                    mAssignKeyButton->setEnabled(true);
211
                    mUnassignKeyButton->setEnabled(true);
212
                }
213
            }
214
        }
215
    }
216
    else if (id == "assign")
217
    {
218
        mKeySetting = true;
219
        mAssignKeyButton->setEnabled(false);
220
        keyboard.setEnabled(false);
221
        const int i(mKeyList->getSelected());
222
        if (i >= 0 && i < mActionDataSize[selectedData])
223
        {
224
            const SetupActionData &key = setupActionData[selectedData][i];
225
            const InputActionT ik = key.actionId;
226
            inputManager.setNewKeyIndex(ik);
227
            mKeyListModel->setElementAt(i, std::string(
228
                gettext(key.name.c_str())).append(": ?"));
229
        }
230
    }
231
    else if (id == "unassign")
232
    {
233
        const int i(mKeyList->getSelected());
234
        if (i >= 0 && i < mActionDataSize[selectedData])
235
        {
236
            const SetupActionData &key = setupActionData[selectedData][i];
237
            const InputActionT ik = key.actionId;
238
            inputManager.setNewKeyIndex(ik);
239
            refreshAssignedKey(mKeyList->getSelected());
240
            inputManager.unassignKey();
241
            inputManager.setNewKeyIndex(InputAction::NO_VALUE);
242
        }
243
        mAssignKeyButton->setEnabled(true);
244
    }
245
    else if (id == "resetkeys")
246
    {
247
        inputManager.resetKeys();
248
        InputManager::update();
249
        refreshKeys();
250
    }
251
    else if (id == "default")
252
    {
253
        const int i(mKeyList->getSelected());
254
        if (i >= 0 && i < mActionDataSize[selectedData])
255
        {
256
            const SetupActionData &key = setupActionData[selectedData][i];
257
            const InputActionT ik = key.actionId;
258
            inputManager.makeDefault(ik);
259
            refreshKeys();
260
        }
261
    }
262
    else if (strStartWith(id, "tabs_"))
263
    {
264
        int k = 0;
265
        std::string str("tabs_");
266
        while (pages[k] != nullptr)
267
        {
268
            if (str + pages[k] == id)
269
                break;
270
            k ++;
271
        }
272
        if ((pages[k] != nullptr) && str + pages[k] == id)
273
        {
274
            mKeyListModel->setSelectedData(k);
275
            mKeyListModel->setSize(mActionDataSize[k]);
276
            refreshKeys();
277
            mKeyList->setSelected(0);
278
        }
279
    }
280
}
281
282
78
void Setup_Input::refreshAssignedKey(const int index)
283
{
284
156
    const int selectedData = mKeyListModel->getSelectedData();
285
78
    const SetupActionData &key = setupActionData[selectedData][index];
286
78
    if (key.actionId == InputAction::NO_VALUE)
287
    {
288
        const std::string str(" \342\200\225\342\200\225\342\200\225"
289
16
            "\342\200\225\342\200\225 ");
290
4
        mKeyListModel->setElementAt(index,
291

24
            str + gettext(key.name.c_str()) + str);
292
    }
293
    else
294
    {
295
370
        std::string str = gettext(key.name.c_str());
296
74
        unsigned int sz = 20;
297
74
        if (mainGraphics->mWidth > 800)
298
            sz = 30;
299
514
        while (str.size() < sz)
300
440
            str.append(" ");
301
222
        mKeyListModel->setElementAt(index, strprintf("%s: %s", str.c_str(),
302
296
            inputManager.getKeyStringLong(key.actionId).c_str()));
303
    }
304
78
}
305
306
void Setup_Input::newKeyCallback(const InputActionT index)
307
{
308
    mKeySetting = false;
309
    const int i = keyToSetupData(index);
310
    if (i >= 0)
311
        refreshAssignedKey(i);
312
    mAssignKeyButton->setEnabled(true);
313
}
314
315
int Setup_Input::keyToSetupData(const InputActionT index) const
316
{
317
    const int selectedData = mKeyListModel->getSelectedData();
318
    for (int i = 0; i < mActionDataSize[selectedData]; i++)
319
    {
320
        const SetupActionData &key = setupActionData[selectedData][i];
321
        if (key.actionId == index)
322
            return i;
323
    }
324
    return -1;
325
}
326
327
std::string Setup_Input::keyToString(const InputActionT index) const
328
{
329
    for (int f = 0; f < SETUP_PAGES; f ++)
330
    {
331
        for (int i = 0; i < mActionDataSize[f]; i++)
332
        {
333
            const SetupActionData &key = setupActionData[f][i];
334
            if (key.actionId == index)
335
                return key.name;
336
        }
337
    }
338
    // TRANSLATORS: unknown key name
339
    return _("unknown");
340
}
341
342
2
void Setup_Input::refreshKeys()
343
{
344
4
    const int selectedData = mKeyListModel->getSelectedData();
345
80
    for (int i = 0; i < mActionDataSize[selectedData]; i++)
346
78
        refreshAssignedKey(i);
347
2
}
348
349
void Setup_Input::keyUnresolved()
350
{
351
    if (mKeySetting)
352
    {
353
        newKeyCallback(inputManager.getNewKeyIndex());
354
        inputManager.setNewKeyIndex(InputAction::NO_VALUE);
355
    }
356
}
357
358
10
void Setup_Input::fixTranslation(SetupActionData *const actionDatas,
359
                                 const InputActionT actionStart,
360
                                 const InputActionT actionEnd,
361
                                 const std::string &text)
362
{
363
10
    int k = 0;
364
365
1232
    while (!actionDatas[k].name.empty())
366
    {
367
404
        SetupActionData &data = actionDatas[k];
368
369
404
        const InputActionT actionId = data.actionId;
370

404
        if (actionId >= actionStart && actionId <= actionEnd)
371
        {
372
1038
            data.name = strprintf(gettext(text.c_str()),
373
692
                actionId - actionStart + 1);
374
        }
375
404
        k ++;
376
    }
377
10
}
378
379
2
void Setup_Input::fixTranslations()
380
{
381
8
    fixTranslation(setupActionDataShortcuts,
382
        InputAction::SHORTCUT_1,
383
        InputAction::SHORTCUT_20,
384
2
        "Item Shortcut %d");
385
386
8
    fixTranslation(setupActionDataEmotes,
387
        InputAction::EMOTE_1,
388
        InputAction::EMOTE_48,
389
2
        "Emote Shortcut %d");
390
391
8
    fixTranslation(setupActionDataCraft,
392
        InputAction::CRAFT_1,
393
        InputAction::CRAFT_9,
394
2
        "Craft shortcut %d");
395
396
8
    fixTranslation(setupActionDataOutfits,
397
        InputAction::OUTFIT_1,
398
        InputAction::OUTFIT_48,
399
2
        "Outfit Shortcut %d");
400
401
8
    fixTranslation(setupActionDataMove,
402
        InputAction::MOVE_TO_POINT_1,
403
        InputAction::MOVE_TO_POINT_48,
404
2
        "Move to point Shortcut %d");
405

5
}