GraphModeler.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This program is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU General Public License as published by the Free  *
00007 * Software Foundation; either version 2 of the License, or (at your option)   *
00008 * any later version.                                                          *
00009 *                                                                             *
00010 * This program is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    *
00013 * more details.                                                               *
00014 *                                                                             *
00015 * You should have received a copy of the GNU General Public License along     *
00016 * with this program; if not, write to the Free Software Foundation, Inc., 51  *
00017 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.                   *
00018 *******************************************************************************
00019 *                            SOFA :: Applications                             *
00020 *                                                                             *
00021 * Authors: M. Adam, J. Allard, B. Andre, P-J. Bensoussan, S. Cotin, C. Duriez,*
00022 * H. Delingette, F. Falipou, F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza,  *
00023 * M. Nesme, P. Neumann, J-P. de la Plata Alcade, F. Poyer and F. Roy          *
00024 *                                                                             *
00025 * Contact information: contact@sofa-framework.org                             *
00026 ******************************************************************************/
00027 #include "GraphModeler.h"
00028 #include "AddPreset.h"
00029 
00030 #include <sofa/simulation/tree/Simulation.h>
00031 #include <sofa/gui/qt/FileManagement.h> //static functions to manage opening/ saving of files
00032 #include <sofa/helper/system/FileRepository.h>
00033 #include <sofa/helper/system/SetDirectory.h>
00034 #include <sofa/simulation/common/TransformationVisitor.h>
00035 
00036 #include <sofa/component/visualmodel/VisualModelImpl.h>
00037 
00038 #ifdef SOFA_QT4
00039 #include <Q3Header>
00040 #include <Q3PopupMenu>
00041 #include <QMessageBox>
00042 #else
00043 #include <qheader.h> 
00044 #include <qpopupmenu.h>
00045 #include <qmessagebox.h> 
00046 #endif
00047 
00048 namespace sofa
00049 {
00050 
00051   namespace gui
00052   {
00053 
00054     namespace qt
00055     {
00056 
00057 
00058 #ifndef SOFA_QT4
00059       typedef QPopupMenu Q3PopupMenu;
00060 #endif
00061 
00062       GNode *GraphModeler::addGNode(GNode *parent, GNode *child, bool saveHistory)
00063       {
00064     GNode *lastRoot = getRoot();
00065     if (!child)
00066       { 
00067         child = new GNode(); 
00068         if (!parent)
00069           child->setName("Root");
00070       }
00071 
00072 
00073     graphListener->addChild(parent, child);
00074 
00075     if (parent != NULL)
00076         parent->addChild(child);
00077     else
00078       {
00079         //Set up the root
00080         firstChild()->setExpandable(true);
00081         firstChild()->setOpen(true);
00082         historyOperation.clear();
00083         currentStateHistory=historyOperation.end();
00084       }
00085 
00086     if (saveHistory)
00087       {
00088         Operation adding(graphListener->items[child], child, Operation::ADD_OBJECT);
00089         historyOperation.push_front(adding);
00090       }
00091     if (!parent) deleteComponent(graphListener->items[lastRoot]);
00092     return child;
00093       }
00094 
00095       BaseObject *GraphModeler::addComponent(GNode *parent, ClassInfo* entry, std::string templateName, bool saveHistory)
00096       {
00097     BaseObject *object=NULL;;
00098     if (!parent || !entry) return object;
00099 
00100     
00101 
00102     xml::ObjectElement description("Default", entry->className.c_str() );
00103 
00104     if (!templateName.empty()) description.setAttribute("template", templateName.c_str());
00105     
00106 
00107     ClassCreator* c;
00108 
00109     if (entry->creatorMap.size() <= 1)
00110         c=entry->creatorMap.begin()->second;
00111     else
00112       {
00113         if (templateName.empty())
00114           {
00115         c=entry->creatorMap.find(entry->defaultTemplate)->second; templateName=entry->defaultTemplate;
00116           }
00117         else    
00118           c=entry->creatorMap.find(templateName)->second;
00119       }
00120 
00121     if (c->canCreate(parent->getContext(), &description))
00122       {
00123         object = c->createInstance(parent->getContext(), NULL);
00124         graphListener->addObject(parent, object);
00125         if (saveHistory)
00126           {
00127         Operation adding(graphListener->items[object], object, Operation::ADD_OBJECT);
00128         historyOperation.push_front(adding);
00129           }
00130       }
00131     else
00132       {
00133         BaseObject* reference = parent->getContext()->getMechanicalState();
00134 
00135         if (!reference)
00136           {
00137         const QString caption("Creation Impossible");
00138         const QString warning=QString("No MechanicalState found in your Node ") + QString(parent->getName().c_str());
00139         if ( QMessageBox::warning ( this, caption,warning, QMessageBox::Cancel | QMessageBox::Default | QMessageBox::Escape, QMessageBox::Ignore ) == QMessageBox::Cancel ) 
00140           return object;        
00141           }
00142         else if (entry->className.find("Mapping") != std::string::npos) ;//we accept the mappings as no initialization of the object has been done
00143         else
00144           {
00145         const QString caption("Creation Impossible");
00146         const QString warning=
00147           QString("Your component won't be created: \n \t * <") 
00148           + QString(reference->getTemplateName().c_str()) + QString("> DOFs are used in the Node ") + QString(parent->getName().c_str()) + QString("\n\t * <")
00149           + QString(templateName.c_str()) + QString("> is the type of your ") + QString(entry->className.c_str());
00150         if ( QMessageBox::warning ( this, caption,warning, QMessageBox::Cancel | QMessageBox::Default | QMessageBox::Escape, QMessageBox::Ignore ) == QMessageBox::Cancel ) 
00151           return object;
00152           }
00153         object = c->createInstance(parent->getContext(), NULL);
00154         graphListener->addObject(parent, object);
00155       }
00156     return object;
00157       }
00158 
00159 
00160 
00161 
00162     void GraphModeler::dropEvent(QDropEvent* event)
00163     {
00164       QPushButton *push = (QPushButton *)event->source();
00165       if (push)  push->setDown(false);
00166 
00167       QString text;
00168       Q3TextDrag::decode(event, text);
00169 
00170       std::string filename(text.ascii());
00171       std::string test = filename; test.resize(4);
00172 
00173       if (test == "file")
00174         {
00175 #ifdef WIN32
00176           filename = filename.substr(8); //removing file:///
00177 #else
00178           filename = filename.substr(7); //removing file://
00179 #endif
00180         
00181           if (filename[filename.size()-1] == '\n')
00182         {
00183           filename.resize(filename.size()-1);
00184           filename[filename.size()-1]='\0';
00185         }
00186           
00187           emit(fileOpen(filename));
00188         }
00189       else
00190         {
00191           
00192           if (library.find(event->source()) != library.end())
00193         {
00194           std::string templateName =  text.ascii();
00195           addComponent(getGNode(event->pos()), library.find(event->source())->second.first, templateName );
00196         }
00197           else
00198         {
00199           if (text == QString("GNode"))
00200             {
00201               GNode* node=getGNode(event->pos()); 
00202               if (node)  addGNode(node);
00203             }
00204         }
00205         }
00206     }
00207 
00208 
00209 
00210 
00211       BaseObject *GraphModeler::getObject(Q3ListViewItem *item)
00212       { 
00213     std::map<core::objectmodel::Base*, Q3ListViewItem* >::iterator it;
00214     for (it = graphListener->items.begin();it != graphListener->items.end();it++)
00215       {
00216         if (it->second == item) 
00217           {
00218         return dynamic_cast< BaseObject *>(it->first);
00219           }
00220       }
00221     return NULL;
00222       }
00223 
00224 
00225       GNode *GraphModeler::getGNode(const QPoint &pos)
00226       {
00227     Q3ListViewItem *item = itemAt(pos);
00228     if (!item) return NULL;
00229     return getGNode(item);
00230       }
00231 
00232 
00233 
00234       GNode *GraphModeler::getGNode(Q3ListViewItem *item)
00235       {
00236     if (!item) return NULL;
00237     sofa::core::objectmodel::Base *object;
00238     std::map<core::objectmodel::Base*, Q3ListViewItem* >::iterator it;
00239     for (it = graphListener->items.begin();it != graphListener->items.end();it++)
00240       {
00241         if (it->second == item) 
00242           {
00243         object = it->first;
00244         break;
00245           }
00246       }
00247     if (it == graphListener->items.end()) return NULL;
00248     
00249     if (dynamic_cast<GNode*>(it->first)) return dynamic_cast<GNode*>(it->first);
00250     else
00251       {
00252         item = item->parent();
00253         for (it = graphListener->items.begin();it != graphListener->items.end();it++)
00254           {
00255         if (it->second == item) 
00256           {
00257             object = it->first;
00258             break;
00259           }
00260           }
00261         if (it == graphListener->items.end()) return NULL;
00262         if (dynamic_cast<GNode*>(it->first)) return dynamic_cast<GNode*>(it->first);
00263         else return NULL;
00264       }
00265       }
00266 
00267       
00268       void GraphModeler::openModifyObject()
00269       {
00270     Q3ListViewItem *item = currentItem();
00271     openModifyObject(item);
00272       }
00273 
00274       void GraphModeler::openModifyObject(Q3ListViewItem *item)
00275       {
00276     if (!item) return;
00277 
00278     std::map<core::objectmodel::Base*, Q3ListViewItem* >::iterator it;
00279     for (it = graphListener->items.begin();it != graphListener->items.end();it++)
00280       {
00281         if (it->second == item) 
00282           {
00283         break;
00284           }
00285       }
00286     if (it == graphListener->items.end()) return;
00287 
00288 
00289     //Unicity and identification of the windows
00290     current_Id_modifyDialog = it->first;
00291     std::map< void*, QDialog* >::iterator testWindow =  map_modifyObjectWindow.find( current_Id_modifyDialog);
00292     if ( testWindow != map_modifyObjectWindow.end())
00293       {
00294         //Object already being modified: no need to open a new window 
00295         (*testWindow).second->raise();
00296         return;
00297       }
00298     
00299     ModifyObjectModeler *dialogModify = new ModifyObjectModeler ( current_Id_modifyDialog, it->first, item,this,item->text(0));
00300     map_modifyObjectWindow.insert( std::make_pair(current_Id_modifyDialog, dialogModify));
00301     //If the item clicked is a node, we add it to the list of the element modified
00302 
00303     map_modifyDialogOpened.insert ( std::make_pair ( current_Id_modifyDialog, it->first ) );
00304 
00305     dialogModify->show();
00306     dialogModify->raise();  
00307     //connect ( this, SIGNAL ( closeDialog() ), dialogModify, SLOT ( closeNow() ) );
00308 
00309       }
00310 
00311       void GraphModeler::doubleClick(Q3ListViewItem *item)
00312       {
00313     if (!item) return;
00314     item->setOpen ( !item->isOpen() );
00315     openModifyObject(item);
00316 
00317       }
00318       void GraphModeler::rightClick(Q3ListViewItem *item, const QPoint &point, int index)
00319       {
00320     if (!item) return;
00321     bool isNode=getObject(item)==NULL;
00322     
00323     Q3PopupMenu *contextMenu = new Q3PopupMenu ( this, "ContextMenu" );
00324     if (isNode)
00325       {
00326         contextMenu->insertItem("Collapse", this, SLOT( collapseNode()));
00327         contextMenu->insertItem("Expand"  , this, SLOT( expandNode()));   
00328         contextMenu->insertSeparator ();
00329         contextMenu->insertItem("Load"  , this, SLOT( loadNode()));
00330         contextMenu->insertItem(QIconSet(), tr( "Preset"), preset);
00331         contextMenu->insertItem("Save"  , this, SLOT( saveNode()));
00332       }
00333     int index_menu = contextMenu->insertItem("Delete"  , this, SLOT( deleteComponent()));
00334 
00335     if (isNode)
00336       {
00337         if ( !isNodeErasable ( getGNode(item) ) )
00338           contextMenu->setItemEnabled ( index_menu,false );
00339       }
00340     else
00341       {
00342         if ( !isObjectErasable ( getObject(item) ))
00343           contextMenu->setItemEnabled ( index_menu,false );
00344       }
00345 
00346     contextMenu->insertItem("Modify"  , this, SLOT( openModifyObject()));
00347     contextMenu->popup ( point, index );
00348     
00349       }
00350 
00351       
00352       void GraphModeler::collapseNode()
00353       {
00354     collapseNode(currentItem());
00355       }
00356 
00357       void GraphModeler::collapseNode(Q3ListViewItem* item)
00358       {
00359     if (!item) return;
00360 
00361     Q3ListViewItem* child;
00362     child = item->firstChild();
00363     while ( child != NULL )
00364       {
00365         child->setOpen ( false );
00366         child = child->nextSibling();
00367       }
00368     item->setOpen ( true );
00369       }
00370 
00371       void GraphModeler::expandNode()
00372       {
00373     expandNode(currentItem());
00374       }
00375 
00376       void GraphModeler::expandNode(Q3ListViewItem* item)
00377       {
00378     if (!item) return;
00379 
00380     item->setOpen ( true );
00381     if ( item != NULL )
00382     {
00383       Q3ListViewItem* child;
00384       child = item->firstChild();
00385       while ( child != NULL )
00386       {
00387         item = child;
00388         child->setOpen ( true );
00389         expandNode(item);
00390         child = child->nextSibling();
00391       }
00392     }
00393       }
00394 
00395       GNode *GraphModeler::loadNode()
00396       {
00397     return loadNode(currentItem()); 
00398       }
00399 
00400       GNode *GraphModeler::loadNode(Q3ListViewItem* item, std::string filename)
00401       {
00402     if (!item) return NULL;
00403     GNode *node = getGNode(item);
00404     if (filename.empty())
00405       {
00406         QString s = getOpenFileName ( this, NULL,"Scenes (*.scn *.xml *.simu *.pscn)", "open file dialog",  "Choose a file to open" );
00407         if (s.length() >0)
00408           {
00409         filename = s.ascii();
00410           }
00411         else return NULL;
00412       }
00413     xml::BaseElement* newXML=NULL;
00414     
00415     newXML = xml::loadFromFile (filename.c_str() );
00416     if (newXML == NULL) return NULL;
00417     if (!newXML->init()) std::cerr<< "Objects initialization failed.\n";
00418     GNode *newNode = dynamic_cast<GNode*> ( newXML->getObject() );
00419     if (newNode) addGNode(node,newNode); 
00420     return newNode;      
00421       }
00422 
00423       void GraphModeler::loadPreset(std::string presetName)
00424       {
00425 
00426 
00427     xml::BaseElement* newXML = xml::loadFromFile (presetName.c_str() );
00428     if (newXML == NULL) return;
00429 
00430     xml::BaseElement::child_iterator<> it(newXML->begin());
00431     bool elementPresent[3]={false,false,false};
00432     for (; it!=newXML->end();++it)
00433       {
00434         if (it->getType() == std::string("MeshLoader") || it->getType() == std::string("SparseGrid")) elementPresent[0] = true;
00435         else if (it->getName() == std::string("VisualNode") || it->getType() == std::string("OglModel")) elementPresent[1] = true;
00436         else if (it->getName() == std::string("CollisionNode")) elementPresent[2] = true;
00437       }
00438 
00439     if (!DialogAdd) 
00440       {
00441         DialogAdd = new AddPreset(this,"AddPreset", elementPresent);
00442         DialogAdd->setPath(sofa::helper::system::DataRepository.getFirstPath());
00443       }
00444 
00445     DialogAdd->setPresetFile(presetName);
00446     GNode *node=getGNode(currentItem());
00447     DialogAdd->setParentNode(node); 
00448 
00449     DialogAdd->show();
00450     DialogAdd->raise();
00451       }
00452 
00453            
00454       void GraphModeler::loadPreset(GNode *parent, std::string presetFile, 
00455                     std::string *filenames, 
00456                     std::string *translation,
00457                     std::string *rotation,
00458                     std::string scale)
00459       {
00460 
00461        
00462     xml::BaseElement* newXML=NULL;
00463     
00464     newXML = xml::loadFromFile (presetFile.c_str() );
00465     if (newXML == NULL) return;
00466 
00467     bool collisionNodeFound=false;
00468     xml::BaseElement *meshMecha=NULL;
00469     xml::BaseElement::child_iterator<> it(newXML->begin());
00470     for (; it!=newXML->end();++it)
00471       {
00472 
00473         if (it->getType() == std::string("MechanicalObject"))
00474           {
00475         updatePresetNode(*it, std::string(), translation, rotation, scale);
00476           }             
00477         if (it->getType() == std::string("MeshLoader") || it->getType() == std::string("SparseGrid"))
00478           {
00479         updatePresetNode(*it, filenames[0], translation, rotation, scale);
00480         meshMecha = it;
00481           }             
00482         if (it->getType() == std::string("OglModel"))
00483           {
00484         updatePresetNode(*it, filenames[1], translation, rotation, scale);
00485           }
00486 
00487         if (it->getName() == std::string("VisualNode"))
00488           {
00489         xml::BaseElement* visualXML = it;
00490         
00491         xml::BaseElement::child_iterator<> it_visual(visualXML->begin());
00492         for (;it_visual!=visualXML->end();++it_visual)
00493           {
00494             if (it_visual->getType() == std::string("OglModel"))
00495               {
00496             updatePresetNode(*it_visual, filenames[1], translation, rotation, scale);
00497               }
00498           }
00499           }
00500         if (it->getName() == std::string("CollisionNode"))
00501           {
00502         collisionNodeFound=true;
00503         xml::BaseElement* collisionXML = it;
00504         
00505         xml::BaseElement::child_iterator<> it_collision(collisionXML->begin());
00506         for (;it_collision!=collisionXML->end();++it_collision)
00507           {
00508             
00509             if (it_collision->getType() == std::string("MechanicalObject"))
00510               {
00511             updatePresetNode(*it_collision, std::string(), translation, rotation, scale);
00512               }             
00513             if (it_collision->getType() == std::string("MeshLoader"))
00514               {
00515             updatePresetNode(*it_collision, filenames[2], translation, rotation, scale);
00516               }                                     
00517           }
00518           }
00519       }
00520     
00521 
00522     
00523     if (!newXML->init()) std::cerr<< "Objects initialization failed.\n";
00524     GNode *presetNode = dynamic_cast<GNode*> ( newXML->getObject() );
00525     if (presetNode) addGNode(parent,presetNode); 
00526       }
00527 
00528       void GraphModeler::updatePresetNode(xml::BaseElement &elem, std::string meshFile, std::string *translation, std::string *rotation, std::string scale)
00529       { 
00530     if (elem.presenceAttribute(std::string("filename"))) elem.setAttribute(std::string("filename"), meshFile.c_str());
00531 
00532     if (elem.presenceAttribute(std::string("dx"))) elem.setAttribute(std::string("dx"), translation[0].c_str());
00533     if (elem.presenceAttribute(std::string("dy"))) elem.setAttribute(std::string("dy"), translation[1].c_str());
00534     if (elem.presenceAttribute(std::string("dz"))) elem.setAttribute(std::string("dz"), translation[2].c_str());
00535 
00536     if (elem.presenceAttribute(std::string("rx"))) elem.setAttribute(std::string("rx"), rotation[0].c_str());
00537     if (elem.presenceAttribute(std::string("ry"))) elem.setAttribute(std::string("ry"), rotation[1].c_str());
00538     if (elem.presenceAttribute(std::string("rz"))) elem.setAttribute(std::string("rz"), rotation[2].c_str());
00539     
00540     if (elem.presenceAttribute(std::string("scale"))) elem.setAttribute(std::string("scale"), scale.c_str());
00541       }
00542 
00543 
00544       void GraphModeler::saveNode()
00545       {
00546     saveNode(currentItem());
00547       }
00548 
00549       void GraphModeler::saveNode(Q3ListViewItem* item)
00550       {
00551     if (!item) return;
00552     GNode *node = getGNode(item);
00553     if (!node) return;
00554 
00555     QString s = sofa::gui::qt::getSaveFileName ( this, NULL, "Scenes (*.scn *.xml)", "save file dialog", "Choose where the scene will be saved" );
00556     if ( s.length() >0 )
00557       getSimulation()->printXML(node, s.ascii());      
00558       }
00559 
00560       void GraphModeler::clearGraph()
00561       {
00562     deleteComponent(firstChild());  
00563       }
00564 
00565       void GraphModeler::deleteComponent(Q3ListViewItem* item, bool saveHistory)
00566       {
00567     if (!item) return;
00568     
00569     GNode *parent = getGNode(item->parent());
00570     bool isNode   = getObject(item)==NULL;
00571     if (!isNode && isObjectErasable(getObject(item)))
00572       {
00573         BaseObject* object = getObject(item);
00574         graphListener->removeObject(getGNode(item), getObject(item)); 
00575 
00576         if (saveHistory)
00577           {
00578         Operation removal(item, getObject(item),Operation::DELETE_OBJECT);
00579         historyOperation.push_front(removal);       
00580           }
00581         //OPERATION DELETE: to remove in order to be able to undo operation
00582         parent->removeObject(object);
00583         delete object;
00584       }
00585     else
00586       {
00587         if (!isNodeErasable(getGNode(item))) return;
00588         GNode *node = getGNode(item);
00589         graphListener->removeChild(parent, node); 
00590 
00591         if (saveHistory)
00592           {
00593         Operation removal(item, getGNode(item),Operation::DELETE_OBJECT);
00594         historyOperation.push_front(removal);
00595           }
00596         if (!parent && childCount() == 0) addGNode(NULL);
00597         //OPERATION DELETE: to remove in order to be able to undo operation
00598         getSimulation()->unload (node);
00599       }
00600 
00601       }
00602       void GraphModeler::deleteComponent()
00603       {
00604     Q3ListViewItem *item = currentItem();
00605     deleteComponent(item);
00606       }
00607 
00608       void GraphModeler::modifyUnlock ( void *Id )
00609       { 
00610     map_modifyDialogOpened.erase( Id );
00611     map_modifyObjectWindow.erase( Id );
00612       }
00613 
00614       
00615 
00616 
00617       void GraphModeler::editUndo()
00618       {
00619     std::cout << "Undo \n";
00620     std::cout << historyOperation.size() << " size of the history\n";
00621     if (currentStateHistory == historyOperation.begin()) return;
00622     currentStateHistory--;
00623       }
00624 
00625       void GraphModeler::editRedo()
00626       {
00627     std::cout << "Redo \n";
00628       }
00629 
00630       void GraphModeler::keyPressEvent ( QKeyEvent * e )
00631       {
00632     switch ( e->key() )
00633       {
00634       case Qt::Key_Delete :
00635         {
00636           deleteComponent();
00637           break;
00638         }
00639       default:
00640         {
00641           e->ignore();
00642           break;
00643         }
00644       }
00645       }
00646       /*****************************************************************************************************************/
00647       // Test if a node can be erased in the graph : the condition is that none of its children has a menu modify opened
00648       bool GraphModeler::isNodeErasable ( core::objectmodel::Base* element )
00649       {
00650     std::map< void*, core::objectmodel::Base*>::iterator it;
00651     for (it = map_modifyDialogOpened.begin(); it != map_modifyDialogOpened.end();it++)
00652     {
00653 
00654       if (dynamic_cast< BaseObject* >(it->second))
00655         {
00656           if (getGNode(graphListener->items[it->second]) == element) return false;
00657         }     
00658       else if (it->second == element) return false;
00659 
00660     }
00661     
00662     std::map< core::objectmodel::Base*, Q3ListViewItem*>::iterator it_item;
00663     it_item = graphListener->items.find(element);
00664 
00665     Q3ListViewItem *child = it_item->second->firstChild();
00666     while (child != NULL)
00667     {
00668       for (it_item = graphListener->items.begin(); it_item != graphListener->items.end();it_item++)
00669       {
00670         if  (it_item->second == child) 
00671         {
00672           if (!isNodeErasable(it_item->first)) return false;
00673           break; 
00674         }
00675       }   
00676       child = child->nextSibling();
00677     }
00678     return true;        
00679       }
00680 
00681       bool GraphModeler::isObjectErasable ( core::objectmodel::Base* element )
00682       {
00683     std::map< void*, core::objectmodel::Base*>::iterator it;
00684     for (it = map_modifyDialogOpened.begin(); it != map_modifyDialogOpened.end();it++)
00685     {
00686       if (it->second == element) return false;
00687     }
00688     
00689     return true;        
00690       }
00691 
00692     }
00693   }
00694 }

Generated on Sun Nov 23 02:28:34 2008 for Sofa by  doxygen 1.5.7.1