17 #include <QFontMetrics>
29 #include "boost/bind.hpp"
30 #include "libQtSignalAdapters/Qt2Func.h"
31 #include "libQtSignalAdapters/ConnectionFactories.h"
48 QRect rect = QFontMetrics(this->font()).boundingRect(text);
49 QSize s(rect.width()*1.0+5, 4*rect.height()*1.2+5);
69 BaseWidget(parent,
"transform_3d_widget",
"Transform 3D")
71 this->setToolTip(
"Display and manipulate an affine (rotation+translation) matrix");
73 mBlockChanges =
false;
75 QVBoxLayout* toptopLayout =
new QVBoxLayout(
this);
76 toptopLayout->setMargin(4);
77 QHBoxLayout* mLayout =
new QHBoxLayout;
78 mLayout->setMargin(0);
79 toptopLayout->addLayout(mLayout);
82 mTextEdit->setSizePolicy(QSizePolicy::MinimumExpanding,QSizePolicy::Maximum);
83 mTextEdit->setLineWrapMode(QTextEdit::NoWrap);
84 mTextEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
85 mTextEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
86 connect(mTextEdit, SIGNAL(textChanged()),
this, SLOT(textEditChangedSlot()));
88 mLayout->addWidget(mTextEdit, 1);
90 QVBoxLayout* buttonLayout =
new QVBoxLayout;
91 mLayout->addLayout(buttonLayout);
92 buttonLayout->setMargin(0);
95 QIcon(
":/icons/open_icon_library/system-run-5.png"),
98 SLOT(toggleEditSlot()),
100 mEditAction->setCheckable(
true);
103 QIcon(
":/icons/matrix_inverse.png"),
105 "Toggle Invert Matrix",
106 SLOT(toggleInvertSlot()),
108 mInvertAction->setCheckable(
true);
109 mInvertAction->setChecked(
false);
110 this->updateInvertAction();
114 aGroupBox =
new QFrame(
this);
115 QVBoxLayout* aLayout =
new QVBoxLayout;
116 aGroupBox->setLayout(aLayout);
117 aGroupBox->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
118 aGroupBox->setLineWidth(3);
119 aLayout->setMargin(4);
120 toptopLayout->addWidget(aGroupBox);
122 this->addAngleControls(
"xAngle",
"X Angle", 0, aLayout);
123 this->addAngleControls(
"yAngle",
"Y Angle", 1, aLayout);
124 this->addAngleControls(
"zAngle",
"Z Angle", 2, aLayout);
126 tGroupBox =
new QFrame(
this);
127 QVBoxLayout* tLayout =
new QVBoxLayout;
128 tGroupBox->setLayout(tLayout);
129 tGroupBox->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
130 tGroupBox->setLineWidth(3);
131 tLayout->setMargin(4);
132 toptopLayout->addWidget(tGroupBox);
134 this->addTranslationControls(
"xTranslation",
"X", 0, tLayout);
135 this->addTranslationControls(
"yTranslation",
"Y", 1, tLayout);
136 this->addTranslationControls(
"zTranslation",
"Z", 2, tLayout);
138 this->setMatrixInternal(Transform3D::Identity());
140 toptopLayout->addStretch();
145 void Transform3DWidget::textEditChangedSlot()
148 Transform3D M = Transform3D::fromString(mTextEdit->toPlainText(), &ok);
152 if (
similar(M, this->getMatrixInternal()))
155 this->setMatrixInternal(M);
158 void Transform3DWidget::toggleEditSlot()
160 bool visible = tGroupBox->isVisible();
165 void Transform3DWidget::toggleInvertSlot()
173 void Transform3DWidget::updateInvertAction()
175 if (mInvertAction->isChecked())
177 this->setActionText(mInvertAction,
"Inverted Matrix",
"The matrix is shown inverted");
181 this->setActionText(mInvertAction,
"Noninverted Matrix",
"The matrix is shown as is. Press to show inverted");
185 void Transform3DWidget::setActionText(QAction* action, QString text, QString tip)
189 action->setText(text);
190 action->setStatusTip(tip);
191 action->setWhatsThis(tip);
192 action->setToolTip(tip);
197 mTextEdit->setReadOnly(!edit);
198 aGroupBox->setVisible(edit);
199 tGroupBox->setVisible(edit);
202 void Transform3DWidget::addAngleControls(QString uid, QString name,
int index, QVBoxLayout* layout)
204 QHBoxLayout* hLayout =
new QHBoxLayout;
207 connect(adapter.get(), SIGNAL(
changed()),
this, SLOT(changedSlot()));
208 adapter->setInternal2Display(180/
M_PI);
211 QSize mMinBarSize = QSize(20,20);
214 hLayout->addWidget(pad);
217 QtSignalAdapters::connect1<void(QPointF)>(pad, SIGNAL(mouseMoved(QPointF)),
218 boost::bind(&Transform3DWidget::rotateSlot,
this, _1, index));
220 layout->addLayout(hLayout);
221 mAngleAdapter[index] = adapter;
224 void Transform3DWidget::addTranslationControls(QString uid, QString name,
int index, QVBoxLayout* layout)
226 QHBoxLayout* hLayout =
new QHBoxLayout;
229 connect(adapter.get(), SIGNAL(
changed()),
this, SLOT(changedSlot()));
230 adapter->setInternal2Display(1.0);
231 hLayout->addWidget(
new SpinBoxGroupWidget(
this, adapter));
233 QSize mMinBarSize = QSize(20,20);
234 MousePadWidget* pad =
new MousePadWidget(
this, mMinBarSize);
235 pad->setFixedYPos(
true);
236 hLayout->addWidget(pad);
239 QtSignalAdapters::connect1<void(QPointF)>(pad, SIGNAL(mouseMoved(QPointF)),
240 boost::bind(&Transform3DWidget::translateSlot,
this, _1, index));
242 layout->addLayout(hLayout);
243 mTranslationAdapter[index] = adapter;
246 void Transform3DWidget::rotateSlot(QPointF delta,
int index)
248 double scale = M_PI_2;
249 double factor = scale * delta.x();
250 double current = mAngleAdapter[index]->getValue();
251 mAngleAdapter[index]->setValue(current + factor);
254 void Transform3DWidget::translateSlot(QPointF delta,
int index)
257 double factor = scale * delta.x();
258 double current = mTranslationAdapter[index]->getValue();
259 mTranslationAdapter[index]->setValue(current + factor);
269 this->setMatrixInternal(this->convertToFromExternal(M));
274 return this->convertToFromExternal(this->getMatrixInternal());
279 if (mInvertAction->isChecked())
289 void Transform3DWidget::setMatrixInternal(
const Transform3D& M)
291 mDecomposition.
reset(M);
296 Transform3D Transform3DWidget::getMatrixInternal()
const
304 void Transform3DWidget::changedSlot()
306 if (recursive || mBlockChanges)
309 Vector3D xyz(mAngleAdapter[0]->getValue(),mAngleAdapter[1]->getValue(),mAngleAdapter[2]->getValue());
312 Vector3D t(mTranslationAdapter[0]->getValue(),mTranslationAdapter[1]->getValue(),mTranslationAdapter[2]->getValue());
325 double wrapAngle(
double angle)
327 angle = fmod(angle,
M_PI * 2);
340 mTextEdit->blockSignals(
true);
341 int textPos = mTextEdit->textCursor().position();
342 mTextEdit->setText(M);
343 QTextCursor cursor = mTextEdit->textCursor();
344 cursor.setPosition(textPos);
345 mTextEdit->setTextCursor(cursor);
346 mTextEdit->blockSignals(
false);
350 mBlockChanges =
true;
352 mAngleAdapter[0]->setValue(wrapAngle(xyz[0]));
353 mAngleAdapter[1]->setValue(wrapAngle(xyz[1]));
354 mAngleAdapter[2]->setValue(wrapAngle(xyz[2]));
357 mTranslationAdapter[0]->setValue(t[0]);
358 mTranslationAdapter[1]->setValue(t[1]);
359 mTranslationAdapter[2]->setValue(t[2]);
361 this->updateInvertAction();
363 mBlockChanges =
false;