GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/gui/widgets/pincode.cpp Lines: 1 97 1.0 %
Date: 2018-05-24 20:11:55 Branches: 2 82 2.4 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2011-2018  The ManaPlus Developers
4
 *
5
 *  This file is part of The ManaPlus Client.
6
 *
7
 *  This program is free software; you can redistribute it and/or modify
8
 *  it under the terms of the GNU General Public License as published by
9
 *  the Free Software Foundation; either version 2 of the License, or
10
 *  any later version.
11
 *
12
 *  This program is distributed in the hope that it will be useful,
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 *  GNU General Public License for more details.
16
 *
17
 *  You should have received a copy of the GNU General Public License
18
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
 */
20
21
#include "gui/widgets/pincode.h"
22
23
#include "gui/gui.h"
24
#include "gui/skin.h"
25
26
#include "gui/widgets/button.h"
27
#include "gui/widgets/textfield.h"
28
29
#include "utils/gettext.h"
30
#include "utils/stringutils.h"
31
32
#include "debug.h"
33
34
Skin *Pincode::mSkin = nullptr;
35
int Pincode::mInstances = 0;
36
37
Pincode::Pincode(const Widget2 *const widget,
38
                 TextField *const textField) :
39
    Container(widget),
40
    ActionListener(),
41
    WidgetListener(),
42
    mButtons(),
43
    mText(),
44
    mTextField(textField),
45
    mPadding(0),
46
    mSpacing(2),
47
    mButtonWidth(0),
48
    mButtonHeight(0)
49
{
50
    mAllowLogic = false;
51
    setOpaque(Opaque_false);
52
53
    if (mInstances == 0)
54
    {
55
        if (theme != nullptr)
56
        {
57
            mSkin = theme->load("pin.xml",
58
                "",
59
                true,
60
                Theme::getThemePath());
61
        }
62
    }
63
    mInstances ++;
64
65
    if (mSkin != nullptr)
66
    {
67
        mPadding = mSkin->getPadding();
68
        mSpacing = mSkin->getOption("spacing", 2);
69
    }
70
    setSelectable(false);
71
72
    addButtons();
73
    adjustSize();
74
}
75
76
Pincode::~Pincode()
77
{
78
    if (mWindow != nullptr)
79
        mWindow->removeWidgetListener(this);
80
81
    if (gui != nullptr)
82
        gui->removeDragged(this);
83
84
    mInstances --;
85
    if (mInstances == 0)
86
    {
87
        if (theme != nullptr)
88
            theme->unload(mSkin);
89
    }
90
}
91
92
void Pincode::addButtons()
93
{
94
    int buttonWidth = 0;
95
    int buttonHeight = 0;
96
    for (int f = 0; f < 10; f ++)
97
    {
98
        const std::string str = toString(f);
99
        mButtons[f] = new Button(this,
100
            str,
101
            str,
102
            BUTTON_PIN_SKIN,
103
            this);
104
        mButtons[f]->adjustSize();
105
        const Rect &rect = mButtons[f]->getDimension();
106
        if (rect.width > buttonWidth)
107
            buttonWidth = rect.width;
108
        if (rect.height > buttonHeight)
109
            buttonHeight = rect.height;
110
        add(mButtons[f]);
111
    }
112
    int x = 0;
113
    int y = 0;
114
    const int xSize = buttonWidth + mSpacing;
115
    const int ySize = buttonHeight + mSpacing;
116
    for (int f = 0; f < 10; f ++)
117
    {
118
        mButtons[f]->setPosition(mPadding + x * xSize,
119
            mPadding + y * ySize);
120
        x ++;
121
        if (x > 2)
122
        {
123
            x = 0;
124
            y ++;
125
        }
126
    }
127
    mButtons[10] = new Button(this,
128
        // TRANSLATORS: clear pin code button
129
        _("Clear"),
130
        "clear",
131
        BUTTON_PIN_SKIN,
132
        this);
133
    mButtons[10]->adjustSize();
134
    add(mButtons[10]);
135
    mButtons[10]->setPosition(mPadding + xSize,
136
        mPadding + 3 * ySize);
137
138
    mButtonWidth = buttonWidth;
139
    mButtonHeight = buttonHeight;
140
}
141
142
void Pincode::adjustSize()
143
{
144
    const int pad2 = mPadding * 2;
145
    setSize(pad2 + 3 * mButtonWidth + 2 * mSpacing,
146
        pad2 + 4 * mButtonHeight + 3 * mSpacing);
147
}
148
149
void Pincode::finalCleanup()
150
{
151
    mSkin = nullptr;
152
}
153
154
void Pincode::action(const ActionEvent &event)
155
{
156
    if (event.getId() == "clear")
157
    {
158
        mText.clear();
159
        mTextField->setText(mText);
160
        mTextField->signalEvent();
161
        return;
162
    }
163
    if (mText.size() >= 4)
164
        return;
165
    const Widget *const eventSrc = event.getSource();
166
    for (int f = 0; f < 10; f ++)
167
    {
168
        if (mButtons[f] == eventSrc)
169
        {
170
            const std::string str = toString(f);
171
            mText.append(str);
172
            mTextField->setText(mText);
173
            mTextField->signalEvent();
174
            return;
175
        }
176
    }
177
}
178
179
void Pincode::shuffle(uint32_t seed) const
180
{
181
    int tab[10];
182
    const uint32_t multiplier = 0x3498;
183
    const uint32_t baseSeed = 0x881234;
184
    int k = 2;
185
186
    for (size_t f = 0; f < 10; f ++)
187
        tab[f] = CAST_S32(f);
188
    for (size_t f = 1; f < 10; f ++)
189
    {
190
        seed = baseSeed + seed * multiplier;
191
        const size_t pos = seed % k;
192
        if (f != pos)
193
        {
194
            const int tmp = tab[f];
195
            tab[f] = tab[pos];
196
            tab[pos] = tmp;
197
        }
198
        k = k + 1;
199
    }
200
    for (size_t f = 0; f < 10; f ++)
201
    {
202
        const std::string str = toString(tab[f]);
203
        mButtons[f]->setCaption(str);
204
    }
205

6
}