~michael-sheldon/ubuntu-keyboard/fix-oxide-dismiss-test

« back to all changes in this revision

Viewing changes to src/lib/logic/keyareaconverter.cpp

  • Committer: Thomas Moenicke
  • Date: 2013-07-19 12:05:07 UTC
  • Revision ID: thomas.moenicke@canonical.com-20130719120507-lzw5oq50xm567x0j
initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This file is part of Maliit Plugins
 
3
 *
 
4
 * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
 
5
 *
 
6
 * Contact: Mohammad Anwari <Mohammad.Anwari@nokia.com>
 
7
 *
 
8
 * Redistribution and use in source and binary forms, with or without modification,
 
9
 * are permitted provided that the following conditions are met:
 
10
 *
 
11
 * Redistributions of source code must retain the above copyright notice, this list
 
12
 * of conditions and the following disclaimer.
 
13
 * Redistributions in binary form must reproduce the above copyright notice, this list
 
14
 * of conditions and the following disclaimer in the documentation and/or other materials
 
15
 * provided with the distribution.
 
16
 * Neither the name of Nokia Corporation nor the names of its contributors may be
 
17
 * used to endorse or promote products derived from this software without specific
 
18
 * prior written permission.
 
19
 *
 
20
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
 
21
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 
22
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 
23
 * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 
24
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 
25
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
26
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 
27
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 
28
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
29
 *
 
30
 */
 
31
 
 
32
#include "keyareaconverter.h"
 
33
 
 
34
#include "models/styleattributes.h"
 
35
#include "models/area.h"
 
36
#include "models/keyarea.h"
 
37
#include "models/key.h"
 
38
#include "logic/keyboardloader.h"
 
39
#include "logic/dynamiclayout.h"
 
40
 
 
41
namespace MaliitKeyboard {
 
42
namespace Logic {
 
43
 
 
44
//! \class KeyAreaConverter
 
45
//! Reads keyboard layouts and converts them into key areas. It can apply
 
46
//! styling attributes, making the key areas ready for rendering.
 
47
//! Explicit functions are used for the different key areas, instead of a
 
48
//! generic lookup. This makes the class easier to use and better documents
 
49
//! the valid combinations.
 
50
 
 
51
namespace {
 
52
//! \brief Creates a key area from a keyboard.
 
53
//! \param attributes The styling attributes that get applied to the key area.
 
54
//! \param source The keyboard layout used for the key area.
 
55
//! \param orientation The layout orientation.
 
56
//! \param is_extended_keyarea Whether the resulting key area is used for
 
57
//!        extended keys (optional).
 
58
KeyArea createFromKeyboard(StyleAttributes *attributes,
 
59
                           const Keyboard &source,
 
60
                           LayoutHelper::Orientation orientation,
 
61
                           bool is_extended_keyarea = false)
 
62
{
 
63
    DynamicLayout::instance()->initDynamicLayout();
 
64
 
 
65
    // An ad-hoc geometry updater that also uses styling information.
 
66
    KeyArea ka;
 
67
    Keyboard kb(source);
 
68
 
 
69
    uiConst->calculateNumberOfRows(kb);
 
70
 
 
71
    if (not attributes) {
 
72
        qCritical() << __PRETTY_FUNCTION__
 
73
                    << "No style given, aborting.";
 
74
        return ka;
 
75
    }
 
76
 
 
77
    attributes->setStyleName(kb.style_name);
 
78
 
 
79
    Font font;
 
80
    font.setName(uiConst->fontFamily());
 
81
    font.setSize(uiConst->fontSize(orientation));
 
82
    font.setColor(uiConst->fontColor());
 
83
 
 
84
    Font small_font(font);
 
85
    small_font.setSize(uiConst->fontSizeSmall(orientation));
 
86
 
 
87
    static const QMargins bg_margins( uiConst->keyAreaBorders() );
 
88
 
 
89
    const qreal max_width( uiConst->windowGeometryRect(qGuiApp->primaryScreen()->orientation()).width() );
 
90
    const qreal key_height(uiConst->keyHeight(orientation));
 
91
    const qreal keypadHeight = uiConst->keypadHeight(orientation);
 
92
 
 
93
    const qreal padding = attributes->keyAreaPadding(orientation);
 
94
 
 
95
 
 
96
 
 
97
    QPoint pos(0, 0);
 
98
    QVector<int> row_indices;
 
99
    int spacer_count = 0;
 
100
    qreal consumed_width = 0;
 
101
 
 
102
    QVector<int> margins = uiConst->calculateMargins(orientation, kb);
 
103
    qreal margin = margins[0];
 
104
 
 
105
    int row = 0;
 
106
    for (int index = 0; index < kb.keys.count(); ++index) {
 
107
        row_indices.append(index);
 
108
        Key &key(kb.keys[index]);
 
109
        const KeyDescription &desc(kb.key_descriptions.at(index));
 
110
 
 
111
        int width = 0;
 
112
        pos.setY((key_height + uiConst->spaceBetweenRows(orientation)) * desc.row + uiConst->keypadTopMargin(orientation));
 
113
        bool at_row_start((index == 0)
 
114
                          || (kb.key_descriptions.at(index - 1).row < desc.row));
 
115
        bool at_row_end((index + 1 == kb.keys.count())
 
116
                        || (index + 1 < kb.keys.count()
 
117
                            && kb.key_descriptions.at(index + 1).row > desc.row));
 
118
 
 
119
        if (at_row_end)
 
120
            row++;
 
121
 
 
122
        if (desc.left_spacer || desc.right_spacer) {
 
123
            ++spacer_count;
 
124
        }
 
125
 
 
126
        width = uiConst->keyWidth(orientation, desc.width);
 
127
 
 
128
        const qreal key_margin((at_row_start || at_row_end) ? margin + padding : margin * 2);
 
129
 
 
130
        Area area;
 
131
        area.setBackground(uiConst->keyBackground(key.style(), KeyDescription::NormalState));
 
132
        area.setBackgroundBorders(bg_margins);
 
133
        area.setSize(QSize(width + key_margin, key_height));
 
134
        key.setArea(area);
 
135
 
 
136
        key.setOrigin(pos);
 
137
        key.setMargins(QMargins(at_row_start ? padding : margin, margin,
 
138
                                at_row_end   ? padding : margin, margin));
 
139
 
 
140
        const QString &text(key.label().text());
 
141
        key.rLabel().setFont(text.count() > 1 ? small_font : font);
 
142
 
 
143
        if (key.icon().isEmpty()) {
 
144
            key.setIcon(attributes->icon(desc.icon,
 
145
                                         KeyDescription::NormalState));
 
146
        } else {
 
147
            key.setIcon(attributes->customIcon(key.icon()));
 
148
        }
 
149
 
 
150
        pos.rx() += key.rect().width();
 
151
 
 
152
        if (at_row_end) {
 
153
            if (not is_extended_keyarea
 
154
                && spacer_count > 0 && pos.x() < max_width + 1) {
 
155
                const int spacer_width = qMax<int>(0, max_width - pos.x()) / spacer_count;
 
156
                pos.setX(0);
 
157
                int right_x = 0;
 
158
 
 
159
                Q_FOREACH (int row_index, row_indices) {
 
160
                    Key &k(kb.keys[row_index]);
 
161
                    const KeyDescription &d(kb.key_descriptions.at(row_index));
 
162
 
 
163
                    QRect r(k.rect());
 
164
                    QMargins m(k.margins());
 
165
                    int extra_width = 0;
 
166
 
 
167
                    if (d.left_spacer) {
 
168
                        m.setLeft(m.left() + spacer_width);
 
169
                        extra_width += spacer_width;
 
170
                    }
 
171
 
 
172
                    if (d.right_spacer) {
 
173
                        m.setRight(m.right() + spacer_width);
 
174
                        extra_width += spacer_width;
 
175
                    }
 
176
 
 
177
                    k.setMargins(m);
 
178
 
 
179
                    r.translate(right_x - r.left(), 0);
 
180
                    r.setWidth(r.width() + extra_width);
 
181
                    k.setOrigin(r.topLeft());
 
182
                    k.rArea().setSize(r.size());
 
183
 
 
184
                    right_x = r.x() + r.width();
 
185
                }
 
186
            }
 
187
 
 
188
            consumed_width = qMax<qreal>(consumed_width, key.rect().x()
 
189
                                                         + key.rect().width()
 
190
                                                         + padding);
 
191
 
 
192
            row_indices.clear();
 
193
            pos.setX(0);
 
194
            spacer_count = 0;
 
195
        }
 
196
    }
 
197
 
 
198
    Area area;
 
199
    area.setBackground(attributes->keyAreaBackground());
 
200
    area.setBackgroundBorders( uiConst->keyAreaBorders() );
 
201
 
 
202
    area.setSize(QSize((is_extended_keyarea ? consumed_width : max_width),
 
203
                       keypadHeight
 
204
                       ));
 
205
 
 
206
    ka.setArea(area);
 
207
    ka.setOrigin(is_extended_keyarea ? QPoint(0, -attributes->verticalOffset(orientation))
 
208
                                     : QPoint(0, uiConst->wordRibbonHeight(orientation)));
 
209
    ka.setKeys(kb.keys);
 
210
 
 
211
    return ka;
 
212
}
 
213
}
 
214
 
 
215
 
 
216
//! \param attributes The styling attributes that should be applied to the
 
217
//!                   created key areas.
 
218
//! \param loader The keyboard layout loader.
 
219
KeyAreaConverter::KeyAreaConverter(StyleAttributes *attributes,
 
220
                                   KeyboardLoader *loader)
 
221
    : m_attributes(attributes)
 
222
    , m_loader(loader)
 
223
    , m_orientation(LayoutHelper::Landscape)
 
224
{
 
225
    if (not attributes || not loader) {
 
226
        qFatal("Neither attributes nor loader can be null.");
 
227
    }
 
228
}
 
229
 
 
230
 
 
231
KeyAreaConverter::~KeyAreaConverter()
 
232
{}
 
233
 
 
234
 
 
235
//! \brief Sets the layout orientation used for creating key areas.
 
236
//! \param orientation The layout orientation. Default: landscape.
 
237
void KeyAreaConverter::setLayoutOrientation(LayoutHelper::Orientation orientation)
 
238
{
 
239
    m_orientation = orientation;
 
240
}
 
241
 
 
242
//! \brief Returns the main key area.
 
243
KeyArea KeyAreaConverter::keyArea() const
 
244
{
 
245
    return createFromKeyboard(m_attributes, m_loader->keyboard(), m_orientation);
 
246
}
 
247
 
 
248
 
 
249
//! \brief Returns the next key area (right of main key area).
 
250
KeyArea KeyAreaConverter::nextKeyArea() const
 
251
{
 
252
    return createFromKeyboard(m_attributes, m_loader->nextKeyboard(), m_orientation);
 
253
}
 
254
 
 
255
 
 
256
//! \brief Returns the previous key area (left of main key area).
 
257
KeyArea KeyAreaConverter::previousKeyArea() const
 
258
{
 
259
    return createFromKeyboard(m_attributes, m_loader->previousKeyboard(), m_orientation);
 
260
}
 
261
 
 
262
 
 
263
//! \brief Returns the main key area with shift bindings activated.
 
264
KeyArea KeyAreaConverter::shiftedKeyArea() const
 
265
{
 
266
    return createFromKeyboard(m_attributes, m_loader->shiftedKeyboard(), m_orientation);
 
267
}
 
268
 
 
269
 
 
270
//! \brief Returns the symbols key area.
 
271
//! \param page The symbols page to return (optional).
 
272
KeyArea KeyAreaConverter::symbolsKeyArea(int page) const
 
273
{
 
274
    return createFromKeyboard(m_attributes, m_loader->symbolsKeyboard(page), m_orientation);
 
275
}
 
276
 
 
277
 
 
278
//! \brief Returns the main key area with dead key bindings activated.
 
279
//! \param dead The key used to look up the dead keys.
 
280
KeyArea KeyAreaConverter::deadKeyArea(const Key &dead) const
 
281
{
 
282
    return createFromKeyboard(m_attributes, m_loader->deadKeyboard(dead), m_orientation);
 
283
}
 
284
 
 
285
 
 
286
//! \brief Returns the main key area with dead key bindings activated.
 
287
//! \param dead The key used to look up the dead keys.
 
288
KeyArea KeyAreaConverter::shiftedDeadKeyArea(const Key &dead) const
 
289
{
 
290
    return createFromKeyboard(m_attributes, m_loader->shiftedDeadKeyboard(dead), m_orientation);
 
291
}
 
292
 
 
293
 
 
294
//! Returns an extended key area.
 
295
//! \param key The key used to look up the extended key binding.
 
296
KeyArea KeyAreaConverter::extendedKeyArea(const Key &key) const
 
297
{
 
298
    return createFromKeyboard(m_attributes, m_loader->extendedKeyboard(key), m_orientation, true);
 
299
}
 
300
 
 
301
 
 
302
//! Returns the number key area.
 
303
KeyArea KeyAreaConverter::numberKeyArea() const
 
304
{
 
305
    return createFromKeyboard(m_attributes, m_loader->numberKeyboard(), m_orientation);
 
306
}
 
307
 
 
308
 
 
309
//! Returns the phone number key area.
 
310
KeyArea KeyAreaConverter::phoneNumberKeyArea() const
 
311
{
 
312
    return createFromKeyboard(m_attributes, m_loader->phoneNumberKeyboard(), m_orientation);
 
313
}
 
314
 
 
315
}} // namespace Logic, MaliitKeyboard