00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "PreCompiled.h"
00025
00026 #ifndef _PreComp_
00027 # include <QAction>
00028 # include <QMenu>
00029 # include <QFont>
00030 # include <QFontMetrics>
00031 # include <QImage>
00032 # include <QPainter>
00033 # include <Inventor/actions/SoSearchAction.h>
00034 # include <Inventor/nodes/SoAnnotation.h>
00035 # include <Inventor/nodes/SoBaseColor.h>
00036 # include <Inventor/nodes/SoDrawStyle.h>
00037 # include <Inventor/nodes/SoFont.h>
00038 # include <Inventor/nodes/SoText2.h>
00039 # include <Inventor/nodes/SoAsciiText.h>
00040 # include <Inventor/nodes/SoTranslation.h>
00041 # include <Inventor/nodes/SoRotationXYZ.h>
00042 # include <Inventor/nodes/SoImage.h>
00043 # include <Inventor/nodes/SoCoordinate3.h>
00044 # include <Inventor/nodes/SoLineSet.h>
00045 # include <Inventor/nodes/SoPointSet.h>
00046 #endif
00047 # include <Inventor/draggers/SoTranslate2Dragger.h>
00048
00049 #include "ViewProviderAnnotation.h"
00050 #include <App/Annotation.h>
00051 #include <App/PropertyGeo.h>
00052 #include <App/PropertyStandard.h>
00053 #include <Gui/BitmapFactory.h>
00054 #include "SoFCSelection.h"
00055 #include "SoTextLabel.h"
00056 #include "Application.h"
00057 #include "Document.h"
00058
00059 using namespace Gui;
00060
00061 const char* ViewProviderAnnotation::JustificationEnums[]= {"Left","Right","Center",NULL};
00062 const char* ViewProviderAnnotation::RotationAxisEnums[]= {"X","Y","Z",NULL};
00063
00064 PROPERTY_SOURCE(Gui::ViewProviderAnnotation, Gui::ViewProviderDocumentObject)
00065
00066
00067 ViewProviderAnnotation::ViewProviderAnnotation()
00068 {
00069 ADD_PROPERTY(TextColor,(1.0f,1.0f,1.0f));
00070 ADD_PROPERTY(Justification,((long)0));
00071 Justification.setEnums(JustificationEnums);
00072 ADD_PROPERTY(FontSize,(12));
00073 ADD_PROPERTY(FontName,("Arial"));
00074 ADD_PROPERTY(LineSpacing,(1.0));
00075 ADD_PROPERTY(Rotation,(0));
00076 ADD_PROPERTY(RotationAxis,((long)2));
00077 RotationAxis.setEnums(RotationAxisEnums);
00078
00079 pFont = new SoFont();
00080 pFont->ref();
00081 pLabel = new SoText2();
00082 pLabel->ref();
00083 pLabel3d = new SoAsciiText();
00084 pLabel3d->ref();
00085 pColor = new SoBaseColor();
00086 pColor->ref();
00087 pTranslation = new SoTranslation();
00088 pTranslation->ref();
00089 pRotationXYZ = new SoRotationXYZ();
00090 pRotationXYZ->ref();
00091
00092 RotationAxis.touch();
00093 TextColor.touch();
00094 FontSize.touch();
00095 FontName.touch();
00096
00097 sPixmap = "Tree_Annotation";
00098 }
00099
00100 ViewProviderAnnotation::~ViewProviderAnnotation()
00101 {
00102 pFont->unref();
00103 pLabel->unref();
00104 pLabel3d->unref();
00105 pColor->unref();
00106 pTranslation->unref();
00107 pRotationXYZ->unref();
00108 }
00109
00110 void ViewProviderAnnotation::onChanged(const App::Property* prop)
00111 {
00112 if (prop == &TextColor) {
00113 const App::Color& c = TextColor.getValue();
00114 pColor->rgb.setValue(c.r,c.g,c.b);
00115 }
00116 else if (prop == &Justification) {
00117 if (Justification.getValue() == 0) {
00118 pLabel->justification = SoText2::LEFT;
00119 pLabel3d->justification = SoAsciiText::LEFT;
00120 }
00121 else if (Justification.getValue() == 1) {
00122 pLabel->justification = SoText2::RIGHT;
00123 pLabel3d->justification = SoAsciiText::RIGHT;
00124 }
00125 else if (Justification.getValue() == 2) {
00126 pLabel->justification = SoText2::CENTER;
00127 pLabel3d->justification = SoAsciiText::CENTER;
00128 }
00129 }
00130 else if (prop == &FontSize) {
00131 pFont->size = FontSize.getValue();
00132 }
00133 else if (prop == &FontName) {
00134 pFont->name = FontName.getValue();
00135 }
00136 else if (prop == &LineSpacing) {
00137 pLabel->spacing = LineSpacing.getValue();
00138 pLabel3d->spacing = LineSpacing.getValue();
00139 }
00140 else if (prop == &RotationAxis) {
00141 if (RotationAxis.getValue() == 0) {
00142 pRotationXYZ->axis = SoRotationXYZ::X;
00143 }
00144 else if (RotationAxis.getValue() == 1) {
00145 pRotationXYZ->axis = SoRotationXYZ::Y;
00146 }
00147 else if (RotationAxis.getValue() == 2) {
00148 pRotationXYZ->axis = SoRotationXYZ::Z;
00149 }
00150 }
00151 else if (prop == &Rotation) {
00152 pRotationXYZ->angle = (Rotation.getValue()/360)*(2*M_PI);
00153 }
00154 else {
00155 ViewProviderDocumentObject::onChanged(prop);
00156 }
00157 }
00158
00159 std::vector<std::string> ViewProviderAnnotation::getDisplayModes(void) const
00160 {
00161
00162 std::vector<std::string> StrList;
00163 StrList.push_back("Screen");
00164 StrList.push_back("World");
00165 return StrList;
00166 }
00167
00168 void ViewProviderAnnotation::setDisplayMode(const char* ModeName)
00169 {
00170 if (strcmp(ModeName, "Screen") == 0)
00171 setDisplayMaskMode("Screen");
00172 else if (strcmp(ModeName, "World")==0)
00173 setDisplayMaskMode("World");
00174
00175 ViewProviderDocumentObject::setDisplayMode(ModeName);
00176 }
00177
00178 void ViewProviderAnnotation::attach(App::DocumentObject* f)
00179 {
00180 ViewProviderDocumentObject::attach(f);
00181
00182 SoAnnotation* anno = new SoAnnotation();
00183 SoAnnotation* anno3d = new SoAnnotation();
00184
00185 SoFCSelection* textsep = new SoFCSelection();
00186 textsep->objectName = pcObject->getNameInDocument();
00187 textsep->documentName = pcObject->getDocument()->getName();
00188 textsep->subElementName = "Main";
00189 textsep->addChild(pTranslation);
00190 textsep->addChild(pRotationXYZ);
00191 textsep->addChild(pColor);
00192 textsep->addChild(pFont);
00193 textsep->addChild(pLabel);
00194
00195 SoFCSelection* textsep3d = new SoFCSelection();
00196 textsep3d->objectName = pcObject->getNameInDocument();
00197 textsep3d->documentName = pcObject->getDocument()->getName();
00198 textsep3d->subElementName = "Main";
00199 textsep3d->addChild(pTranslation);
00200 textsep3d->addChild(pRotationXYZ);
00201 textsep3d->addChild(pColor);
00202 textsep3d->addChild(pFont);
00203 textsep3d->addChild(pLabel3d);
00204
00205 anno->addChild(textsep);
00206 anno3d->addChild(textsep3d);
00207
00208 addDisplayMaskMode(anno, "Screen");
00209 addDisplayMaskMode(anno3d, "World");
00210 }
00211
00212 void ViewProviderAnnotation::updateData(const App::Property* prop)
00213 {
00214 if (prop->getTypeId() == App::PropertyStringList::getClassTypeId() &&
00215 strcmp(prop->getName(),"LabelText") == 0) {
00216 const std::vector<std::string> lines = static_cast<const App::PropertyStringList*>(prop)->getValues();
00217 int index=0;
00218 pLabel->string.setNum((int)lines.size());
00219 pLabel3d->string.setNum((int)lines.size());
00220 for (std::vector<std::string>::const_iterator it = lines.begin(); it != lines.end(); ++it) {
00221 pLabel->string.set1Value(index, SbString(it->c_str()));
00222 pLabel3d->string.set1Value(index, SbString(it->c_str()));
00223 index++;
00224 }
00225 }
00226 else if (prop->getTypeId() == App::PropertyVector::getClassTypeId() &&
00227 strcmp(prop->getName(),"Position") == 0) {
00228 Base::Vector3f v = static_cast<const App::PropertyVector*>(prop)->getValue();
00229 pTranslation->translation.setValue(v.x,v.y,v.z);
00230 }
00231
00232 ViewProviderDocumentObject::updateData(prop);
00233 }
00234
00235
00236
00237 const char* ViewProviderAnnotationLabel::JustificationEnums[]= {"Left","Right","Center",NULL};
00238
00239 PROPERTY_SOURCE(Gui::ViewProviderAnnotationLabel, Gui::ViewProviderDocumentObject)
00240
00241
00242 ViewProviderAnnotationLabel::ViewProviderAnnotationLabel()
00243 {
00244 ADD_PROPERTY(TextColor,(1.0f,1.0f,1.0f));
00245 ADD_PROPERTY(BackgroundColor,(0.0f,0.333f,1.0f));
00246 ADD_PROPERTY(Justification,((long)0));
00247 Justification.setEnums(JustificationEnums);
00248 QFont fn;
00249 ADD_PROPERTY(FontSize,(fn.pointSize()));
00250 ADD_PROPERTY(FontName,((const char*)fn.family().toAscii()));
00251 ADD_PROPERTY(Frame,(true));
00252
00253 pColor = new SoBaseColor();
00254 pColor->ref();
00255 pBaseTranslation = new SoTranslation();
00256 pBaseTranslation->ref();
00257 pTextTranslation = new SoTransform();
00258 pTextTranslation->ref();
00259 pCoords = new SoCoordinate3();
00260 pCoords->ref();
00261 pImage = new SoImage();
00262 pImage->ref();
00263
00264 BackgroundColor.touch();
00265
00266 sPixmap = "Tree_Annotation";
00267 }
00268
00269 ViewProviderAnnotationLabel::~ViewProviderAnnotationLabel()
00270 {
00271 pColor->unref();
00272 pBaseTranslation->unref();
00273 pTextTranslation->unref();
00274 pCoords->unref();
00275 pImage->unref();
00276 }
00277
00278 void ViewProviderAnnotationLabel::onChanged(const App::Property* prop)
00279 {
00280 if (prop == &BackgroundColor) {
00281 const App::Color& c = BackgroundColor.getValue();
00282 pColor->rgb.setValue(c.r,c.g,c.b);
00283 }
00284 if (prop == &TextColor || prop == &BackgroundColor ||
00285 prop == &Justification || prop == &FontSize ||
00286 prop == &FontName || prop == &Frame) {
00287 if (getObject()) {
00288 App::Property* label = getObject()->getPropertyByName("LabelText");
00289 if (label && label->getTypeId() == App::PropertyStringList::getClassTypeId())
00290 drawImage(static_cast<App::PropertyStringList*>(label)->getValues());
00291 }
00292 }
00293 else {
00294 ViewProviderDocumentObject::onChanged(prop);
00295 }
00296 }
00297
00298 std::vector<std::string> ViewProviderAnnotationLabel::getDisplayModes(void) const
00299 {
00300
00301 std::vector<std::string> StrList;
00302 StrList.push_back("Line");
00303 StrList.push_back("Object");
00304 return StrList;
00305 }
00306
00307 void ViewProviderAnnotationLabel::setDisplayMode(const char* ModeName)
00308 {
00309 if (strcmp(ModeName, "Line") == 0)
00310 setDisplayMaskMode("Line");
00311 else if (strcmp(ModeName, "Object")==0)
00312 setDisplayMaskMode("Object");
00313
00314 ViewProviderDocumentObject::setDisplayMode(ModeName);
00315 }
00316
00317 void ViewProviderAnnotationLabel::attach(App::DocumentObject* f)
00318 {
00319 ViewProviderDocumentObject::attach(f);
00320
00321
00322 SoSeparator* textsep = new SoAnnotation();
00323 textsep->addChild(pBaseTranslation);
00324 textsep->addChild(pImage);
00325
00326
00327 SoSeparator* linesep = new SoAnnotation();
00328 linesep->addChild(pBaseTranslation);
00329 linesep->addChild(pColor);
00330 linesep->addChild(pCoords);
00331 linesep->addChild(new SoLineSet());
00332 SoDrawStyle *ds = new SoDrawStyle();
00333 ds->pointSize.setValue(3.0f);
00334 linesep->addChild(ds);
00335 linesep->addChild(new SoPointSet());
00336 linesep->addChild(pTextTranslation);
00337 linesep->addChild(pImage);
00338
00339 addDisplayMaskMode(linesep, "Line");
00340 addDisplayMaskMode(textsep, "Object");
00341 }
00342
00343 void ViewProviderAnnotationLabel::updateData(const App::Property* prop)
00344 {
00345 if (prop->getTypeId() == App::PropertyStringList::getClassTypeId() &&
00346 strcmp(prop->getName(),"LabelText") == 0) {
00347 drawImage(static_cast<const App::PropertyStringList*>(prop)->getValues());
00348 }
00349 else if (prop->getTypeId() == App::PropertyVector::getClassTypeId() &&
00350 strcmp(prop->getName(),"BasePosition") == 0) {
00351 Base::Vector3f v = static_cast<const App::PropertyVector*>(prop)->getValue();
00352 pBaseTranslation->translation.setValue(v.x,v.y,v.z);
00353 }
00354 else if (prop->getTypeId() == App::PropertyVector::getClassTypeId() &&
00355 strcmp(prop->getName(),"TextPosition") == 0) {
00356 Base::Vector3f v = static_cast<const App::PropertyVector*>(prop)->getValue();
00357 pCoords->point.set1Value(1, SbVec3f(v.x,v.y,v.z));
00358 pTextTranslation->translation.setValue(v.x,v.y,v.z);
00359 }
00360
00361 ViewProviderDocumentObject::updateData(prop);
00362 }
00363
00364 bool ViewProviderAnnotationLabel::doubleClicked(void)
00365 {
00366 Gui::Application::Instance->activeDocument()->setEdit(this);
00367 return true;
00368 }
00369
00370 void ViewProviderAnnotationLabel::setupContextMenu(QMenu* menu, QObject* receiver, const char* member)
00371 {
00372 menu->addAction(QObject::tr("Move annotation"), receiver, member);
00373 }
00374
00375 void ViewProviderAnnotationLabel::dragStartCallback(void *data, SoDragger *)
00376 {
00377
00378 Gui::Application::Instance->activeDocument()->openCommand("Transform");
00379 }
00380
00381 void ViewProviderAnnotationLabel::dragFinishCallback(void *data, SoDragger *)
00382 {
00383
00384 Gui::Application::Instance->activeDocument()->commitCommand();
00385 }
00386
00387 void ViewProviderAnnotationLabel::dragMotionCallback(void *data, SoDragger *drag)
00388 {
00389 ViewProviderAnnotationLabel* that = reinterpret_cast<ViewProviderAnnotationLabel*>(data);
00390 const SbMatrix& mat = drag->getMotionMatrix();
00391 App::DocumentObject* obj = that->getObject();
00392 if (obj && obj->getTypeId() == App::AnnotationLabel::getClassTypeId()) {
00393 static_cast<App::AnnotationLabel*>(obj)->TextPosition.setValue(mat[3][0],mat[3][1],mat[3][2]);
00394 }
00395 }
00396
00397 bool ViewProviderAnnotationLabel::setEdit(int ModNum)
00398 {
00399 SoSearchAction sa;
00400 sa.setInterest(SoSearchAction::FIRST);
00401 sa.setSearchingAll(FALSE);
00402 sa.setNode(this->pTextTranslation);
00403 sa.apply(pcRoot);
00404 SoPath * path = sa.getPath();
00405 if (path) {
00406 TranslateManip * manip = new TranslateManip;
00407 SoDragger* dragger = manip->getDragger();
00408 dragger->addStartCallback(dragStartCallback, this);
00409 dragger->addFinishCallback(dragFinishCallback, this);
00410 dragger->addMotionCallback(dragMotionCallback, this);
00411 return manip->replaceNode(path);
00412 }
00413
00414 return false;
00415 }
00416
00417 void ViewProviderAnnotationLabel::unsetEdit(int ModNum)
00418 {
00419 SoSearchAction sa;
00420 sa.setType(TranslateManip::getClassTypeId());
00421 sa.setInterest(SoSearchAction::FIRST);
00422 sa.apply(pcRoot);
00423 SoPath * path = sa.getPath();
00424
00425
00426 if (!path)
00427 return;
00428
00429 TranslateManip * manip = static_cast<TranslateManip*>(path->getTail());
00430 SoTransform* transform = this->pTextTranslation;
00431 manip->replaceManip(path, transform);
00432 }
00433
00434 void ViewProviderAnnotationLabel::drawImage(const std::vector<std::string>& s)
00435 {
00436 if (s.empty()) {
00437 pImage->image = SoSFImage();
00438 this->hide();
00439 return;
00440 }
00441
00442 QFont font(QString::fromAscii(this->FontName.getValue()), (int)this->FontSize.getValue());
00443 QFontMetrics fm(font);
00444 int w = 0;
00445 int h = fm.height() * s.size();
00446 const App::Color& b = this->BackgroundColor.getValue();
00447 QColor brush;
00448 brush.setRgbF(b.r,b.g,b.b);
00449 const App::Color& t = this->TextColor.getValue();
00450 QColor front;
00451 front.setRgbF(t.r,t.g,t.b);
00452
00453 QStringList lines;
00454 for (std::vector<std::string>::const_iterator it = s.begin(); it != s.end(); ++it) {
00455 QString line = QString::fromUtf8(it->c_str());
00456 w = std::max<int>(w, fm.width(line));
00457 lines << line;
00458 }
00459
00460 QImage image(w+10,h+10,QImage::Format_ARGB32_Premultiplied);
00461 image.fill(0x00000000);
00462 QPainter painter(&image);
00463 painter.setRenderHint(QPainter::Antialiasing);
00464
00465 bool drawFrame = this->Frame.getValue();
00466 if (drawFrame) {
00467 painter.setPen(QPen(QColor(0,0,127), 2, Qt::SolidLine, Qt::RoundCap,
00468 Qt::RoundJoin));
00469 painter.setBrush(QBrush(brush, Qt::SolidPattern));
00470 QRectF rectangle(0.0, 0.0, w+10, h+10);
00471 painter.drawRoundedRect(rectangle, 5, 5);
00472 }
00473
00474 painter.setPen(front);
00475
00476 Qt::Alignment align = Qt::AlignVCenter;
00477 if (Justification.getValue() == 0)
00478 align = Qt::AlignVCenter | Qt::AlignLeft;
00479 else if (Justification.getValue() == 1)
00480 align = Qt::AlignVCenter | Qt::AlignRight;
00481 else
00482 align = Qt::AlignVCenter | Qt::AlignHCenter;
00483 QString text = lines.join(QLatin1String("\n"));
00484 painter.setFont(font);
00485 painter.drawText(5,5,w,h,align,text);
00486 painter.end();
00487
00488 SoSFImage sfimage;
00489 Gui::BitmapFactory().convert(image, sfimage);
00490 pImage->image = sfimage;
00491 }