GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/gui/widgets/tabs/setup_input.cpp Lines: 106 198 53.5 %
Date: 2018-07-14 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-2018  The ManaPlus Developers
7
 *
8
 *  This file is part of The ManaPlus Client.
9
 *
10
 *  This program is free software; you can redistribute it and/or modify
11
 *  it under the terms of the GNU General Public License as published by
12
 *  the Free Software Foundation; either version 2 of the License, or
13
 *  any later version.
14
 *
15
 *  This program is distributed in the hope that it will be useful,
16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 *  GNU General Public License for more details.
19
 *
20
 *  You should have received a copy of the GNU General Public License
21
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
 */
23
24
#include "gui/widgets/tabs/setup_input.h"
25
26
#include "configuration.h"
27
28
#include "const/gui/pages.h"
29
30
#include "input/inputactionoperators.h"
31
#include "input/inputmanager.h"
32
#include "input/keyboardconfig.h"
33
34
#include "input/pages/craft.h"
35
#include "input/pages/emotes.h"
36
#include "input/pages/move.h"
37
#include "input/pages/outfits.h"
38
#include "input/pages/shortcuts.h"
39
40
#include "gui/gui.h"
41
#include "gui/setupinputpages.h"
42
43
#include "gui/windows/okdialog.h"
44
45
#include "gui/widgets/button.h"
46
#include "gui/widgets/containerplacer.h"
47
#include "gui/widgets/createwidget.h"
48
#include "gui/widgets/layouthelper.h"
49
#include "gui/widgets/listbox.h"
50
#include "gui/widgets/scrollarea.h"
51
#include "gui/widgets/tabstrip.h"
52
53
#include "gui/models/keylistmodel.h"
54
55
#include "utils/delete2.h"
56
#include "utils/gettext.h"
57
58
#include "debug.h"
59
60
2
Setup_Input::Setup_Input(const Widget2 *const widget) :
61
    SetupTab(widget),
62
4
    mKeyListModel(new KeyListModel),
63


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

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

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

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

2
        BUTTON_SKIN, this)),
76


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

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





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

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

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

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

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

5
}