ViewProviderAnnotation.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) 2008 Werner Mayer <wmayer[at]users.sourceforge.net>     *
00003  *                                                                         *
00004  *   This file is part of the FreeCAD CAx development system.              *
00005  *                                                                         *
00006  *   This library is free software; you can redistribute it and/or         *
00007  *   modify it under the terms of the GNU Library General Public           *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2 of the License, or (at your option) any later version.      *
00010  *                                                                         *
00011  *   This library  is distributed in the hope that it will be useful,      *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00014  *   GNU Library General Public License for more details.                  *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Library General Public     *
00017  *   License along with this library; see the file COPYING.LIB. If not,    *
00018  *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
00019  *   Suite 330, Boston, MA  02111-1307, USA                                *
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     // add modes
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); // causes problems
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     // add modes
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     // plain image
00322     SoSeparator* textsep = new SoAnnotation();
00323     textsep->addChild(pBaseTranslation);
00324     textsep->addChild(pImage);
00325 
00326     // image with line
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     // This is called when a manipulator is about to manipulating
00378     Gui::Application::Instance->activeDocument()->openCommand("Transform");
00379 }
00380 
00381 void ViewProviderAnnotationLabel::dragFinishCallback(void *data, SoDragger *)
00382 {
00383     // This is called when a manipulator has done manipulating
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     // No transform manipulator found.
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 }

Generated on Wed Nov 23 19:00:58 2011 for FreeCAD by  doxygen 1.6.1