GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/gui/widgets/tabs/setup_input.cpp Lines: 97 188 51.6 %
Date: 2017-11-29 Branches: 100 278 36.0 %

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-2017  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
4
Setup_Input::Setup_Input(const Widget2 *const widget) :
61
    SetupTab(widget),
62
8
    mKeyListModel(new KeyListModel),
63


16
    mKeyList(CREATEWIDGETR(ListBox, this, mKeyListModel, "")),
64
    // TRANSLATORS: button in input settings tab
65

8
    mAssignKeyButton(new Button(this, _("Assign"), "assign", this)),
66
    // TRANSLATORS: button in input settings tab
67

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

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

8
    mResetKeysButton(new Button(this, _("Reset all keys"), "resetkeys", this)),
72


16
    mTabs(new TabStrip(this, config.getIntValue("fontSize") + 10)),
73
4
    mScrollArea(new ScrollArea(this, mKeyList,
74

8
        Opaque_true, "setup_input_background.xml")),
75
    mKeySetting(false),
76





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

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

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

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

808
        if (actionId >= actionStart && actionId <= actionEnd)
365
        {
366
2768
            data.name = strprintf(gettext(text.c_str()),
367
1384
                actionId - actionStart + 1);
368
        }
369
808
        k ++;
370
    }
371
20
}
372
373
4
void Setup_Input::fixTranslations()
374
{
375

16
    fixTranslation(setupActionDataShortcuts,
376
        InputAction::SHORTCUT_1,
377
        InputAction::SHORTCUT_20,
378
        "Item Shortcut %d");
379
380

16
    fixTranslation(setupActionDataEmotes,
381
        InputAction::EMOTE_1,
382
        InputAction::EMOTE_48,
383
        "Emote Shortcut %d");
384
385

16
    fixTranslation(setupActionDataCraft,
386
        InputAction::CRAFT_1,
387
        InputAction::CRAFT_9,
388
        "Craft shortcut %d");
389
390

16
    fixTranslation(setupActionDataOutfits,
391
        InputAction::OUTFIT_1,
392
        InputAction::OUTFIT_48,
393
        "Outfit Shortcut %d");
394
395

16
    fixTranslation(setupActionDataMove,
396
        InputAction::MOVE_TO_POINT_1,
397
        InputAction::MOVE_TO_POINT_48,
398
        "Move to point Shortcut %d");
399

10
}