$search
00001 /* 00002 * Copyright (c) 2008, Willow Garage, Inc. 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions are met: 00007 * 00008 * * Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * * Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * * Neither the name of the Willow Garage, Inc. nor the names of its 00014 * contributors may be used to endorse or promote products derived from 00015 * this software without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00018 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00021 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00022 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00023 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00024 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00025 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00026 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00027 * POSSIBILITY OF SUCH DAMAGE. 00028 */ 00029 00030 #include "property_manager.h" 00031 #include "property.h" 00032 #include "rviz/properties/property_tree_widget.h" 00033 00034 #include <ros/console.h> 00035 00036 #include "config.h" 00037 00038 namespace rviz 00039 { 00040 00041 PropertyManager::PropertyManager() 00042 : grid_(0) 00043 , default_user_data_(0) 00044 { 00045 } 00046 00047 PropertyManager::~PropertyManager() 00048 { 00049 clear(); 00050 } 00051 00052 void PropertyManager::addProperty(const PropertyBasePtr& property, const std::string& name, const std::string& prefix, void* user_data) 00053 { 00054 bool inserted = properties_.insert( std::make_pair( std::make_pair(prefix, name), property ) ).second; 00055 ROS_ASSERT(inserted); 00056 00057 if (!user_data) 00058 { 00059 user_data = default_user_data_; 00060 } 00061 00062 property->setUserData( user_data ); 00063 00064 // "connect" the property's changed() callback to this->propertySet(). 00065 property->manager_ = this; 00066 00067 if (config_ && property->getSave()) 00068 { 00069 property->loadFromConfig(config_.get()); 00070 } 00071 00072 if (grid_) 00073 { 00074 property->setPropertyTreeWidget(grid_); 00075 property->writeToGrid(); 00076 } 00077 } 00078 00079 StatusPropertyWPtr PropertyManager::createStatus(const std::string& name, const std::string& prefix, const CategoryPropertyWPtr& parent, void* user_data) 00080 { 00081 StatusPropertyPtr prop(new StatusProperty(name, prefix, parent, user_data)); 00082 addProperty(prop, name, prefix, user_data); 00083 00084 return StatusPropertyWPtr(prop); 00085 } 00086 00087 CategoryPropertyWPtr PropertyManager::createCategory(const std::string& name, const std::string& prefix, const CategoryPropertyWPtr& parent, void* user_data) 00088 { 00089 CategoryPropertyPtr category(new CategoryProperty(name, name, prefix, parent, CategoryProperty::Getter(), CategoryProperty::Setter(), false)); 00090 category->setSave( false ); 00091 addProperty(category, name, prefix, user_data); 00092 00093 return CategoryPropertyWPtr(category); 00094 } 00095 00096 CategoryPropertyWPtr PropertyManager::createCheckboxCategory(const std::string& label, const std::string& name, const std::string& prefix, const boost::function<bool(void)>& getter, 00097 const boost::function<void(bool)>& setter, const CategoryPropertyWPtr& parent, void* user_data) 00098 { 00099 CategoryPropertyPtr category(new CategoryProperty(label, name, prefix, parent, getter, setter, true)); 00100 addProperty(category, name, prefix, user_data); 00101 00102 return CategoryPropertyWPtr(category); 00103 } 00104 00105 void PropertyManager::update() 00106 { 00107 #if 0 00108 if (grid_) 00109 { 00110 if (grid_->IsEditorFocused()) 00111 { 00112 return; 00113 } 00114 } 00115 #endif 00116 00117 S_PropertyBaseWPtr local_props; 00118 { 00119 boost::mutex::scoped_lock lock(changed_mutex_); 00120 00121 local_props.swap(changed_properties_); 00122 } 00123 00124 if (!local_props.empty()) 00125 { 00126 #if 0 00127 if (grid_) 00128 { 00129 grid_->Freeze(); 00130 } 00131 #endif 00132 00133 S_PropertyBaseWPtr::iterator it = local_props.begin(); 00134 S_PropertyBaseWPtr::iterator end = local_props.end(); 00135 for (; it != end; ++it) 00136 { 00137 PropertyBasePtr property = it->lock(); 00138 if (property) 00139 { 00140 if (grid_) 00141 { 00142 property->writeToGrid(); 00143 } 00144 00145 if (config_ && property->getSave()) 00146 { 00147 property->saveToConfig(config_.get()); 00148 } 00149 } 00150 } 00151 00152 if (grid_) 00153 { 00154 grid_->update(); 00155 } 00156 00157 #if 0 00158 if (grid_) 00159 { 00160 grid_->Thaw(); 00161 } 00162 #endif 00163 } 00164 } 00165 00166 void PropertyManager::deleteProperty( const PropertyBasePtr& property ) 00167 { 00168 if ( !property ) 00169 { 00170 return; 00171 } 00172 00173 // "disconnect" from the property's changed() callback. 00174 property->manager_ = 0; 00175 00176 M_Property::iterator it = properties_.begin(); 00177 M_Property::iterator end = properties_.end(); 00178 for (; it != end; ++it) 00179 { 00180 if (it->second == property) 00181 { 00182 // search for any children of this property, and delete them as well 00183 deleteChildren( it->second ); 00184 00185 properties_.erase( it ); 00186 00187 break; 00188 } 00189 } 00190 } 00191 00192 void PropertyManager::deleteProperty( const std::string& name, const std::string& prefix ) 00193 { 00194 M_Property::iterator found_it = properties_.find( std::make_pair( prefix, name ) ); 00195 ROS_ASSERT( found_it != properties_.end() ); 00196 00197 // search for any children of this property, and delete them as well 00198 deleteChildren( found_it->second ); 00199 00200 if( found_it->second ) 00201 { 00202 // "disconnect" from the property's changed() callback. 00203 found_it->second->manager_ = 0; 00204 } 00205 00206 properties_.erase( found_it ); 00207 } 00208 00209 void PropertyManager::changePrefix(const std::string& old_prefix, const std::string& new_prefix) 00210 { 00211 // This kind of sucks... because properties are split into name + prefix, can't just lookup based on the prefix 00212 // so we have to iterate through 00213 M_Property to_add; 00214 std::vector<M_Property::iterator> to_delete; 00215 M_Property::iterator it = properties_.begin(); 00216 M_Property::iterator end = properties_.end(); 00217 for (; it != end; ++it) 00218 { 00219 const std::pair<std::string, std::string>& key = it->first; 00220 const PropertyBasePtr& prop = it->second; 00221 00222 // We want to get everything that started with the old prefix, not just those that are an exact match 00223 size_t pos = key.first.find(old_prefix); 00224 if (pos == 0) 00225 { 00226 std::string np = new_prefix + key.first.substr(old_prefix.size()); 00227 prop->setPrefix(np); 00228 to_add[std::make_pair(np, key.second)] = prop; 00229 to_delete.push_back(it); 00230 } 00231 } 00232 00233 for (size_t i = 0; i < to_delete.size(); ++i) 00234 { 00235 properties_.erase(to_delete[i]); 00236 } 00237 00238 properties_.insert(to_add.begin(), to_add.end()); 00239 } 00240 00241 void PropertyManager::deleteChildren( const PropertyBasePtr& property ) 00242 { 00243 if (!property) 00244 { 00245 return; 00246 } 00247 00248 std::set<PropertyBasePtr> to_delete; 00249 00250 M_Property::iterator prop_it = properties_.begin(); 00251 M_Property::iterator prop_end = properties_.end(); 00252 for ( ; prop_it != prop_end; ++prop_it ) 00253 { 00254 const PropertyBasePtr& child = prop_it->second; 00255 00256 PropertyBaseWPtr parent = child->getParent(); 00257 if ( parent.lock() == property ) 00258 { 00259 to_delete.insert( child ); 00260 } 00261 } 00262 00263 // if (grid_) 00264 // { 00265 // grid_->Freeze(); 00266 // } 00267 00268 std::set<PropertyBasePtr>::iterator del_it = to_delete.begin(); 00269 std::set<PropertyBasePtr>::iterator del_end = to_delete.end(); 00270 for ( ; del_it != del_end; ++del_it ) 00271 { 00272 deleteProperty( *del_it ); 00273 } 00274 00275 to_delete.clear(); 00276 00277 // if (grid_) 00278 // { 00279 // grid_->Thaw(); 00280 // } 00281 } 00282 00283 void PropertyManager::deleteByUserData( void* user_data ) 00284 { 00285 std::set<PropertyBasePtr> to_delete; 00286 00287 M_Property::iterator it = properties_.begin(); 00288 M_Property::iterator end = properties_.end(); 00289 for ( ; it != end; ++it ) 00290 { 00291 const PropertyBasePtr& property = it->second; 00292 00293 if ( property->getUserData() == user_data ) 00294 { 00295 PropertyBasePtr parent = property->getParent().lock(); 00296 if ( !parent || parent->getUserData() != user_data ) 00297 { 00298 to_delete.insert( property ); 00299 } 00300 } 00301 } 00302 00303 // if (grid_) 00304 // { 00305 // grid_->Freeze(); 00306 // } 00307 00308 std::set<PropertyBasePtr>::iterator prop_it = to_delete.begin(); 00309 std::set<PropertyBasePtr>::iterator prop_end = to_delete.end(); 00310 for ( ; prop_it != prop_end; ++prop_it ) 00311 { 00312 deleteProperty( *prop_it ); 00313 } 00314 00315 // if (grid_) 00316 // { 00317 // grid_->Thaw(); 00318 // } 00319 } 00320 00321 void PropertyManager::propertySet( const PropertyBasePtr& property ) 00322 { 00323 boost::mutex::scoped_lock lock(changed_mutex_); 00324 00325 changed_properties_.insert(property); 00326 } 00327 00328 void PropertyManager::save(const boost::shared_ptr<Config>& config) 00329 { 00330 M_Property::iterator it = properties_.begin(); 00331 M_Property::iterator end = properties_.end(); 00332 for ( ; it != end; ++it ) 00333 { 00334 const PropertyBasePtr& property = it->second; 00335 00336 if ( property->getSave() ) 00337 { 00338 property->saveToConfig( config.get() ); 00339 } 00340 } 00341 } 00342 00343 void PropertyManager::load(const boost::shared_ptr<Config>& config, const StatusCallback& cb) 00344 { 00345 config_ = config; 00346 00347 M_Property::iterator it = properties_.begin(); 00348 M_Property::iterator end = properties_.end(); 00349 for ( ; it != end; ++it ) 00350 { 00351 const PropertyBasePtr& property = it->second; 00352 00353 if ( property->getSave() ) 00354 { 00355 std::stringstream ss; 00356 ss << "Loading property [" << property->getPrefix() + property->getName() << "]"; 00357 ROS_DEBUG_STREAM_NAMED("properties", ss.str()); 00358 00359 if (cb) 00360 { 00361 cb(ss.str()); 00362 } 00363 00364 property->loadFromConfig( config.get() ); 00365 } 00366 } 00367 00368 if( grid_ ) 00369 { 00370 grid_->update(); 00371 } 00372 } 00373 00374 void PropertyManager::setPropertyTreeWidget(PropertyTreeWidget* grid) 00375 { 00376 ROS_ASSERT(!grid_); 00377 ROS_ASSERT(grid); 00378 00379 grid_ = grid; 00380 00381 M_Property::iterator it = properties_.begin(); 00382 M_Property::iterator end = properties_.end(); 00383 for (; it != end; ++it) 00384 { 00385 const PropertyBasePtr& property = it->second; 00386 property->setPropertyTreeWidget(grid_); 00387 property->writeToGrid(); 00388 } 00389 } 00390 00391 void PropertyManager::refreshAll() 00392 { 00393 ROS_ASSERT(grid_); 00394 00395 M_Property::iterator it = properties_.begin(); 00396 M_Property::iterator end = properties_.end(); 00397 for (; it != end; ++it) 00398 { 00399 propertySet(it->second); 00400 } 00401 00402 update(); 00403 } 00404 00405 void PropertyManager::clear() 00406 { 00407 properties_.clear(); 00408 } 00409 00410 } // end namespace rviz