~ubuntu-branches/ubuntu/maverick/freecad/maverick

« back to all changes in this revision

Viewing changes to src/Gui/InputVector.h

  • Committer: Bazaar Package Importer
  • Author(s): Teemu Ikonen
  • Date: 2009-07-16 18:37:41 UTC
  • Revision ID: james.westby@ubuntu.com-20090716183741-oww9kcxqrk991i1n
Tags: upstream-0.8.2237
ImportĀ upstreamĀ versionĀ 0.8.2237

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
 *   Copyright (c) 2008 Werner Mayer <wmayer@users.sourceforge.net>        *
 
3
 *                                                                         *
 
4
 *   This file is part of the FreeCAD CAx development system.              *
 
5
 *                                                                         *
 
6
 *   This library is free software; you can redistribute it and/or         *
 
7
 *   modify it under the terms of the GNU Library General Public           *
 
8
 *   License as published by the Free Software Foundation; either          *
 
9
 *   version 2 of the License, or (at your option) any later version.      *
 
10
 *                                                                         *
 
11
 *   This library  is distributed in the hope that it will be useful,      *
 
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 
14
 *   GNU Library General Public License for more details.                  *
 
15
 *                                                                         *
 
16
 *   You should have received a copy of the GNU Library General Public     *
 
17
 *   License along with this library; see the file COPYING.LIB. If not,    *
 
18
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 
19
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 
20
 *                                                                         *
 
21
 ***************************************************************************/
 
22
 
 
23
#ifndef GUI_INPUTVECTOR_H
 
24
#define GUI_INPUTVECTOR_H
 
25
 
 
26
#include <cfloat>
 
27
#include <QDialog>
 
28
#include <QMessageBox>
 
29
 
 
30
#include <Gui/propertyeditor/PropertyItem.h>
 
31
 
 
32
namespace Gui {
 
33
 
 
34
/** This is the base dialog class that defines the interface for
 
35
 * specifying a direction vector by the user.
 
36
 * @author Werner Mayer
 
37
 */
 
38
class GuiExport LocationDialog : public QDialog
 
39
{
 
40
    Q_OBJECT
 
41
 
 
42
protected:
 
43
    LocationDialog(QWidget* parent = 0, Qt::WFlags fl = 0);
 
44
    virtual ~LocationDialog();
 
45
 
 
46
private Q_SLOTS:
 
47
    void on_direction_activated(int);
 
48
 
 
49
public:
 
50
    virtual Base::Vector3f getDirection() const = 0;
 
51
    Base::Vector3f getUserDirection(bool* ok=0) const;
 
52
 
 
53
private:
 
54
    virtual void directionActivated(int) = 0;
 
55
};
 
56
 
 
57
/* TRANSLATOR Gui::LocationDialog */
 
58
 
 
59
/** This is the template class that implements the interface of LocationDialog.
 
60
 * The template argument can be the Ui interface class built by uic out of a
 
61
 * .ui file.
 
62
 * This class might be very useful for dialogs where a combo box is used to
 
63
 * define a direction vector by the user. For such classes the programmer don't
 
64
 * to write a subclass to implement the appropriate singals/slots. Instead it's
 
65
 * possible to omit this further class and use LocationInterface parametrized
 
66
 * with the generated Ui class.
 
67
 * @author Werner Mayer
 
68
 */
 
69
template <class Ui>
 
70
class LocationInterface : public LocationDialog, public Ui
 
71
{
 
72
public:
 
73
    LocationInterface(QWidget* parent = 0, Qt::WFlags fl = 0)  : LocationDialog(parent, fl)
 
74
    {
 
75
        this->setupUi(this);
 
76
        // Vector3f declared to use with QVariant see Gui/propertyeditor/PropertyItem.h
 
77
        this->direction->setItemData(0, QVariant::fromValue<Base::Vector3f>(Base::Vector3f(1,0,0)));
 
78
        this->direction->setItemData(1, QVariant::fromValue<Base::Vector3f>(Base::Vector3f(0,1,0)));
 
79
        this->direction->setItemData(2, QVariant::fromValue<Base::Vector3f>(Base::Vector3f(0,0,1)));
 
80
    }
 
81
    virtual ~LocationInterface(){}
 
82
 
 
83
    Base::Vector3f getPosition() const
 
84
    {
 
85
        return Base::Vector3f((float)this->xPos->value(),
 
86
                              (float)this->yPos->value(),
 
87
                              (float)this->zPos->value());
 
88
    }
 
89
 
 
90
    Base::Vector3f getDirection() const
 
91
    {
 
92
        QVariant data = this->direction->itemData (this->direction->currentIndex());
 
93
        if (data.canConvert<Base::Vector3f>()) {
 
94
            return data.value<Base::Vector3f>();
 
95
        }
 
96
        else {
 
97
            return Base::Vector3f(0,0,1);
 
98
        }
 
99
    }
 
100
 
 
101
private:
 
102
    void directionActivated(int index)
 
103
    {
 
104
        // last item is selected to define direction by user
 
105
        if (index+1 == this->direction->count()) {
 
106
            bool ok;
 
107
            Base::Vector3f dir = this->getUserDirection(&ok);
 
108
            if (ok) {
 
109
                if (dir.Length() < FLT_EPSILON) {
 
110
                    QMessageBox::critical(this, LocationDialog::tr("Wrong direction"),
 
111
                        LocationDialog::tr("Direction must not be the null vector"));
 
112
                    return;
 
113
                }
 
114
 
 
115
                // check if the user-defined direction is already there
 
116
                for (int i=0; i<this->direction->count()-1; i++) {
 
117
                    QVariant data = this->direction->itemData (i);
 
118
                    if (data.canConvert<Base::Vector3f>()) {
 
119
                        const Base::Vector3f val = data.value<Base::Vector3f>();
 
120
                        if (val == dir) {
 
121
                            this->direction->setCurrentIndex(i);
 
122
                            return;
 
123
                        }
 
124
                    }
 
125
                }
 
126
 
 
127
                // add a new item before the very last item
 
128
                QString display = QString::fromAscii("(%1,%2,%3)")
 
129
                    .arg(dir.x)
 
130
                    .arg(dir.y)
 
131
                    .arg(dir.z);
 
132
                this->direction->insertItem(this->direction->count()-1, display,
 
133
                    QVariant::fromValue<Base::Vector3f>(dir));
 
134
                this->direction->setCurrentIndex(this->direction->count()-2);
 
135
            }
 
136
        }
 
137
    }
 
138
};
 
139
 
 
140
/** This template class does basically the same as LocationInterface unless
 
141
 * that the Ui class is used as composition not as further base class.
 
142
 * @author Werner Mayer
 
143
 */
 
144
template <class Ui>
 
145
class LocationInterfaceComp : public Ui
 
146
{
 
147
public:
 
148
    LocationInterfaceComp(QDialog *dlg)
 
149
    {
 
150
        this->setupUi(dlg);
 
151
        // Vector3f declared to use with QVariant see Gui/propertyeditor/PropertyItem.h
 
152
        this->direction->setItemData(0, QVariant::fromValue<Base::Vector3f>(Base::Vector3f(1,0,0)));
 
153
        this->direction->setItemData(1, QVariant::fromValue<Base::Vector3f>(Base::Vector3f(0,1,0)));
 
154
        this->direction->setItemData(2, QVariant::fromValue<Base::Vector3f>(Base::Vector3f(0,0,1)));
 
155
    }
 
156
    ~LocationInterfaceComp()
 
157
    {
 
158
    }
 
159
 
 
160
    Base::Vector3f getPosition() const
 
161
    {
 
162
        return Base::Vector3f((float)this->xPos->value(),
 
163
                              (float)this->yPos->value(),
 
164
                              (float)this->zPos->value());
 
165
    }
 
166
 
 
167
    Base::Vector3f getDirection() const
 
168
    {
 
169
        QVariant data = this->direction->itemData (this->direction->currentIndex());
 
170
        if (data.canConvert<Base::Vector3f>()) {
 
171
            return data.value<Base::Vector3f>();
 
172
        }
 
173
        else {
 
174
            return Base::Vector3f(0,0,1);
 
175
        }
 
176
    }
 
177
 
 
178
public:
 
179
    void directionActivated(LocationDialog* dlg, int index)
 
180
    {
 
181
        // last item is selected to define direction by user
 
182
        if (index+1 == this->direction->count()) {
 
183
            bool ok;
 
184
            Base::Vector3f dir = dlg->getUserDirection(&ok);
 
185
            if (ok) {
 
186
                if (dir.Length() < FLT_EPSILON) {
 
187
                    QMessageBox::critical(dlg, LocationDialog::tr("Wrong direction"),
 
188
                        LocationDialog::tr("Direction must not be the null vector"));
 
189
                    return;
 
190
                }
 
191
 
 
192
                // check if the user-defined direction is already there
 
193
                for (int i=0; i<this->direction->count()-1; i++) {
 
194
                    QVariant data = this->direction->itemData (i);
 
195
                    if (data.canConvert<Base::Vector3f>()) {
 
196
                        const Base::Vector3f val = data.value<Base::Vector3f>();
 
197
                        if (val == dir) {
 
198
                            this->direction->setCurrentIndex(i);
 
199
                            return;
 
200
                        }
 
201
                    }
 
202
                }
 
203
 
 
204
                // add a new item before the very last item
 
205
                QString display = QString::fromAscii("(%1,%2,%3)")
 
206
                    .arg(dir.x)
 
207
                    .arg(dir.y)
 
208
                    .arg(dir.z);
 
209
                this->direction->insertItem(this->direction->count()-1, display,
 
210
                    QVariant::fromValue<Base::Vector3f>(dir));
 
211
                this->direction->setCurrentIndex(this->direction->count()-2);
 
212
            }
 
213
        }
 
214
    }
 
215
};
 
216
 
 
217
/** This template class is the parent dialog using LocationInterfaceComp and
 
218
 * implements the pure virtual method directionActivated().
 
219
 * @author Werner Mayer
 
220
 */
 
221
template <class Ui>
 
222
class LocationDialogComp : public LocationDialog
 
223
{
 
224
public:
 
225
    LocationDialogComp(QWidget* parent = 0, Qt::WFlags fl = 0)
 
226
      : LocationDialog(parent, fl), ui(this)
 
227
    {
 
228
    }
 
229
    virtual ~LocationDialogComp()
 
230
    {
 
231
        // no need to delete child widgets, Qt does it all for us
 
232
    }
 
233
 
 
234
    Base::Vector3f getDirection() const
 
235
    {
 
236
        return ui.getDirection();
 
237
    }
 
238
 
 
239
private:
 
240
    void directionActivated(int index)
 
241
    {
 
242
        ui.directionActivated(this,index);
 
243
    }
 
244
 
 
245
protected:
 
246
    LocationInterfaceComp<Ui> ui;
 
247
};
 
248
 
 
249
} // namespace Gui
 
250
 
 
251
#endif // GUI_INPUTVECTOR_H