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

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

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

5
}