$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 00033 #include <ros/console.h> 00034 00035 #include <wx/wx.h> 00036 #include <wx/propgrid/propgrid.h> 00037 #include <wx/confbase.h> 00038 00039 namespace rviz 00040 { 00041 00042 PropertyManager::PropertyManager() 00043 : grid_(0) 00044 , default_user_data_(0) 00045 { 00046 } 00047 00048 PropertyManager::~PropertyManager() 00049 { 00050 clear(); 00051 } 00052 00053 void PropertyManager::addProperty(const PropertyBasePtr& property, const std::string& name, const std::string& prefix, void* user_data) 00054 { 00055 bool inserted = properties_.insert( std::make_pair( std::make_pair(prefix, name), property ) ).second; 00056 ROS_ASSERT(inserted); 00057 00058 if (!user_data) 00059 { 00060 user_data = default_user_data_; 00061 } 00062 00063 property->setUserData( user_data ); 00064 property->addChangedListener( boost::bind( &PropertyManager::propertySet, this, _1 ) ); 00065 00066 if (config_ && property->getSave()) 00067 { 00068 property->loadFromConfig(config_.get()); 00069 } 00070 00071 if (grid_) 00072 { 00073 property->setPropertyGrid(grid_); 00074 property->writeToGrid(); 00075 property->setPGClientData(); 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_->Refresh(); 00155 } 00156 00157 #if 0 00158 if (grid_) 00159 { 00160 grid_->Thaw(); 00161 } 00162 #endif 00163 } 00164 00165 static bool do_refresh = false; 00166 if (do_refresh) 00167 { 00168 grid_->Refresh(); 00169 } 00170 } 00171 00172 void PropertyManager::deleteProperty( const PropertyBasePtr& property ) 00173 { 00174 if ( !property ) 00175 { 00176 return; 00177 } 00178 00179 M_Property::iterator it = properties_.begin(); 00180 M_Property::iterator end = properties_.end(); 00181 for (; it != end; ++it) 00182 { 00183 if (it->second == property) 00184 { 00185 // search for any children of this property, and delete them as well 00186 deleteChildren( it->second ); 00187 00188 grid_->Freeze(); 00189 00190 properties_.erase( it ); 00191 00192 grid_->Thaw(); 00193 00194 break; 00195 } 00196 } 00197 } 00198 00199 void PropertyManager::deleteProperty( const std::string& name, const std::string& prefix ) 00200 { 00201 M_Property::iterator found_it = properties_.find( std::make_pair( prefix, name ) ); 00202 ROS_ASSERT( found_it != properties_.end() ); 00203 00204 // search for any children of this property, and delete them as well 00205 deleteChildren( found_it->second ); 00206 00207 if (grid_) 00208 { 00209 grid_->Freeze(); 00210 } 00211 00212 properties_.erase( found_it ); 00213 00214 if (grid_) 00215 { 00216 grid_->Thaw(); 00217 } 00218 } 00219 00220 void PropertyManager::changePrefix(const std::string& old_prefix, const std::string& new_prefix) 00221 { 00222 // This kind of sucks... because properties are split into name + prefix, can't just lookup based on the prefix 00223 // so we have to iterate through 00224 M_Property to_add; 00225 std::vector<M_Property::iterator> to_delete; 00226 M_Property::iterator it = properties_.begin(); 00227 M_Property::iterator end = properties_.end(); 00228 for (; it != end; ++it) 00229 { 00230 const std::pair<std::string, std::string>& key = it->first; 00231 const PropertyBasePtr& prop = it->second; 00232 00233 // We want to get everything that started with the old prefix, not just those that are an exact match 00234 size_t pos = key.first.find(old_prefix); 00235 if (pos == 0) 00236 { 00237 std::string np = new_prefix + key.first.substr(old_prefix.size()); 00238 prop->setPrefix(np); 00239 to_add[std::make_pair(np, key.second)] = prop; 00240 to_delete.push_back(it); 00241 } 00242 } 00243 00244 for (size_t i = 0; i < to_delete.size(); ++i) 00245 { 00246 properties_.erase(to_delete[i]); 00247 } 00248 00249 properties_.insert(to_add.begin(), to_add.end()); 00250 } 00251 00252 void PropertyManager::deleteChildren( const PropertyBasePtr& property ) 00253 { 00254 if (!property) 00255 { 00256 return; 00257 } 00258 00259 std::set<PropertyBasePtr> to_delete; 00260 00261 M_Property::iterator prop_it = properties_.begin(); 00262 M_Property::iterator prop_end = properties_.end(); 00263 for ( ; prop_it != prop_end; ++prop_it ) 00264 { 00265 const PropertyBasePtr& child = prop_it->second; 00266 00267 PropertyBaseWPtr parent = child->getParent(); 00268 if ( parent.lock() == property ) 00269 { 00270 to_delete.insert( child ); 00271 } 00272 } 00273 00274 if (grid_) 00275 { 00276 grid_->Freeze(); 00277 } 00278 00279 std::set<PropertyBasePtr>::iterator del_it = to_delete.begin(); 00280 std::set<PropertyBasePtr>::iterator del_end = to_delete.end(); 00281 for ( ; del_it != del_end; ++del_it ) 00282 { 00283 deleteProperty( *del_it ); 00284 } 00285 00286 to_delete.clear(); 00287 00288 if (grid_) 00289 { 00290 grid_->Thaw(); 00291 } 00292 } 00293 00294 void PropertyManager::deleteByUserData( void* user_data ) 00295 { 00296 std::set<PropertyBasePtr> to_delete; 00297 00298 M_Property::iterator it = properties_.begin(); 00299 M_Property::iterator end = properties_.end(); 00300 for ( ; it != end; ++it ) 00301 { 00302 const PropertyBasePtr& property = it->second; 00303 00304 if ( property->getUserData() == user_data ) 00305 { 00306 PropertyBasePtr parent = property->getParent().lock(); 00307 if ( !parent || parent->getUserData() != user_data ) 00308 { 00309 to_delete.insert( property ); 00310 } 00311 } 00312 } 00313 00314 if (grid_) 00315 { 00316 grid_->Freeze(); 00317 } 00318 00319 std::set<PropertyBasePtr>::iterator prop_it = to_delete.begin(); 00320 std::set<PropertyBasePtr>::iterator prop_end = to_delete.end(); 00321 for ( ; prop_it != prop_end; ++prop_it ) 00322 { 00323 deleteProperty( *prop_it ); 00324 } 00325 00326 if (grid_) 00327 { 00328 grid_->Thaw(); 00329 } 00330 } 00331 00332 void PropertyManager::propertyChanging( wxPropertyGridEvent& event ) 00333 { 00334 00335 } 00336 00337 void PropertyManager::propertyChanged( wxPropertyGridEvent& event ) 00338 { 00339 wxPGProperty* property = event.GetProperty(); 00340 00341 void* client_data = property->GetClientData(); 00342 if ( client_data ) 00343 { 00344 PropertyBase* property = reinterpret_cast<PropertyBase*>(client_data); 00345 00346 property->readFromGrid(); 00347 } 00348 } 00349 00350 void PropertyManager::propertySet( const PropertyBasePtr& property ) 00351 { 00352 boost::mutex::scoped_lock lock(changed_mutex_); 00353 00354 changed_properties_.insert(property); 00355 } 00356 00357 void PropertyManager::save(const boost::shared_ptr<wxConfigBase>& config) 00358 { 00359 M_Property::iterator it = properties_.begin(); 00360 M_Property::iterator end = properties_.end(); 00361 for ( ; it != end; ++it ) 00362 { 00363 const PropertyBasePtr& property = it->second; 00364 00365 if ( property->getSave() ) 00366 { 00367 property->saveToConfig( config.get() ); 00368 } 00369 } 00370 } 00371 00372 void PropertyManager::load(const boost::shared_ptr<wxConfigBase>& config, const StatusCallback& cb) 00373 { 00374 config_ = config; 00375 00376 M_Property::iterator it = properties_.begin(); 00377 M_Property::iterator end = properties_.end(); 00378 for ( ; it != end; ++it ) 00379 { 00380 const PropertyBasePtr& property = it->second; 00381 00382 if ( property->getSave() ) 00383 { 00384 std::stringstream ss; 00385 ss << "Loading property [" << property->getPrefix() + property->getName() << "]"; 00386 ROS_DEBUG_STREAM_NAMED("properties", ss.str()); 00387 00388 if (cb) 00389 { 00390 cb(ss.str()); 00391 } 00392 00393 property->loadFromConfig( config.get() ); 00394 } 00395 } 00396 } 00397 00398 void PropertyManager::setPropertyGrid(wxPropertyGrid* grid) 00399 { 00400 ROS_ASSERT(!grid_); 00401 ROS_ASSERT(grid); 00402 00403 grid_ = grid; 00404 00405 M_Property::iterator it = properties_.begin(); 00406 M_Property::iterator end = properties_.end(); 00407 for (; it != end; ++it) 00408 { 00409 const PropertyBasePtr& property = it->second; 00410 property->setPropertyGrid(grid_); 00411 property->writeToGrid(); 00412 property->setPGClientData(); 00413 } 00414 } 00415 00416 void PropertyManager::refreshAll() 00417 { 00418 ROS_ASSERT(grid_); 00419 00420 M_Property::iterator it = properties_.begin(); 00421 M_Property::iterator end = properties_.end(); 00422 for (; it != end; ++it) 00423 { 00424 propertySet(it->second); 00425 } 00426 00427 update(); 00428 } 00429 00430 void PropertyManager::clear() 00431 { 00432 if (grid_) 00433 { 00434 grid_->Freeze(); 00435 } 00436 00437 M_Property::iterator it = properties_.begin(); 00438 M_Property::iterator end = properties_.end(); 00439 for (; it != end; ++it) 00440 { 00441 it->second->reset(); 00442 } 00443 properties_.clear(); 00444 00445 if (grid_) 00446 { 00447 grid_->Clear(); 00448 grid_->Thaw(); 00449 } 00450 } 00451 00452 }