$search
00001 /********************************************************************* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Copyright (c) 2008, Willow Garage, Inc. 00005 * All rights reserved. 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions 00009 * are met: 00010 * 00011 * * Redistributions of source code must retain the above copyright 00012 * notice, this list of conditions and the following disclaimer. 00013 * * Redistributions in binary form must reproduce the above 00014 * copyright notice, this list of conditions and the following 00015 * disclaimer in the documentation and/or other materials provided 00016 * with the distribution. 00017 * * Neither the name of Willow Garage, Inc. nor the names of its 00018 * contributors may be used to endorse or promote products derived 00019 * from this software without specific prior written permission. 00020 * 00021 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00022 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00023 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00024 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00025 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00026 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00027 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00028 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00029 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00030 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00031 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00032 * POSSIBILITY OF SUCH DAMAGE. 00033 ********************************************************************/ 00034 00035 #include "topic_display.h" 00036 00037 namespace rxtools 00038 { 00039 00040 class TopicNameData : public wxTreeItemData 00041 { 00042 public: 00043 std::string name; 00044 }; 00045 00046 TopicDisplay::TopicDisplay(wxWindow* parent, const std::string& message_type, bool auto_refresh, const wxSize& size) 00047 : GenTopicDisplay(parent, wxID_ANY, wxDefaultPosition, size) 00048 , message_type_(message_type) 00049 { 00050 timer_ = new wxTimer(this); 00051 00052 Connect(wxEVT_TIMER, wxTimerEventHandler(TopicDisplay::tick), NULL, this); 00053 00054 if (auto_refresh) 00055 { 00056 timer_->Start(1000); 00057 } 00058 00059 root_id_ = topic_tree_->AddRoot(wxT("/")); 00060 00061 refreshTopics(); 00062 } 00063 00064 TopicDisplay::~TopicDisplay() 00065 { 00066 delete timer_; 00067 } 00068 00069 void TopicDisplay::checkIsTopic(wxTreeEvent& event) 00070 { 00071 if (topic_tree_->GetItemData(event.GetItem()) == NULL) 00072 { 00073 event.Veto(); 00074 } 00075 } 00076 00077 void TopicDisplay::onItemActivated(wxTreeEvent& event) 00078 { 00079 if (topic_tree_->GetItemData(event.GetItem()) == NULL) 00080 { 00081 event.Skip(); 00082 } 00083 else 00084 { 00085 wxPostEvent(this, event); 00086 } 00087 } 00088 00089 void TopicDisplay::refreshTopics() 00090 { 00091 ros::master::V_TopicInfo topics; 00092 ros::master::getTopics(topics); 00093 00094 // Set all items in cache to tentatively delete 00095 for (M_TopicInfo::iterator i = topic_cache_.begin(); i != topic_cache_.end(); ++i) 00096 { 00097 i->second.save_ = false; 00098 } 00099 00100 // Loop through all published topics 00101 ros::master::V_TopicInfo::iterator it = topics.begin(); 00102 ros::master::V_TopicInfo::iterator end = topics.end(); 00103 for (; it != end; ++it) 00104 { 00105 const ros::master::TopicInfo& topic = *it; 00106 if (!message_type_.empty() && topic.datatype != message_type_) 00107 { 00108 continue; 00109 } 00110 00111 M_TopicInfo::iterator j = topic_cache_.find(topic.name); 00112 if (j == topic_cache_.end()) 00113 { 00114 // Topic not in cache yet. Find right place to put it in the tree 00115 std::istringstream iss(topic.name); 00116 std::string token; 00117 00118 wxTreeItemId id = root_id_; 00119 00120 while (getline(iss, token, '/')) 00121 { 00122 if (!token.empty()) 00123 { 00124 wxTreeItemIdValue cookie; 00125 00126 wxTreeItemId child; 00127 00128 child = topic_tree_->GetFirstChild(id, cookie); 00129 00130 bool exists = false; 00131 while (child.IsOk()) 00132 { 00133 if (topic_tree_->GetItemText(child) == wxString::FromAscii(token.c_str())) 00134 { 00135 exists = true; 00136 break; 00137 } 00138 00139 child = topic_tree_->GetNextChild(id, cookie); 00140 } 00141 00142 if (exists) 00143 { 00144 id = child; 00145 } 00146 else 00147 { 00148 id = topic_tree_->AppendItem(id, wxString::FromAscii(token.c_str())); 00149 } 00150 } 00151 } 00152 00153 // Add to Cache 00154 TopicInfo cache_item; 00155 cache_item.item_ = id; 00156 cache_item.save_ = true; 00157 cache_item.type_ = topic.datatype; 00158 topic_cache_[topic.name] = cache_item; 00159 00160 // Put data in tree item and rename 00161 TopicNameData* data = new TopicNameData(); 00162 data->name = topic.name; 00163 topic_tree_->SetItemText(id, wxString::FromAscii(token.c_str()) + wxT(" (") + wxString::FromAscii(topic.datatype.c_str()) + wxT(")")); 00164 topic_tree_->SetItemData(id, data); 00165 topic_tree_->SetItemBold(id, true); 00166 } 00167 else 00168 { 00169 // Topic already in cache -- keep it there. 00170 j->second.save_ = true; 00171 } 00172 } 00173 00174 std::vector<M_TopicInfo::iterator> to_erase; 00175 00176 // Tentatively delete all items in cache which should be removed 00177 for (M_TopicInfo::iterator i = topic_cache_.begin(); i != topic_cache_.end(); i++) 00178 { 00179 if (i->second.save_ == false) 00180 { 00181 to_erase.push_back(i); 00182 } 00183 } 00184 00185 // Actually delete all items and purge parents as necessary 00186 for (std::vector<M_TopicInfo::iterator>::iterator i = to_erase.begin(); i != to_erase.end(); i++) 00187 { 00188 // Delete item 00189 wxTreeItemId id = (*i)->second.item_; 00190 wxTreeItemId parent_id = topic_tree_->GetItemParent(id); 00191 topic_tree_->Delete(id); 00192 00193 // Delete all childless parents 00194 while (parent_id != root_id_) 00195 { 00196 if (topic_tree_->HasChildren(parent_id)) 00197 { 00198 break; 00199 } 00200 else 00201 { 00202 id = parent_id; 00203 parent_id = topic_tree_->GetItemParent(id); 00204 topic_tree_->Delete(id); 00205 } 00206 } 00207 00208 // Erase item from cache 00209 topic_cache_.erase(*i); 00210 } 00211 00212 // Refresh the display 00213 Refresh(); 00214 } 00215 00216 void TopicDisplay::tick(wxTimerEvent& event) 00217 { 00218 refreshTopics(); 00219 } 00220 00221 void TopicDisplay::getSelectedTopics(V_string& topics) 00222 { 00223 wxArrayTreeItemIds selections; 00224 00225 topic_tree_->GetSelections(selections); 00226 00227 for (unsigned int i = 0; i < selections.GetCount(); i++) 00228 { 00229 wxTreeItemId id = selections.Item(i); 00230 if (topic_tree_->GetItemData(id) != NULL) 00231 { 00232 TopicNameData* s = (TopicNameData*) topic_tree_->GetItemData(id); 00233 topics.push_back(s->name); 00234 } 00235 } 00236 } 00237 00238 void TopicDisplay::setMultiselectAllowed(bool allowed) 00239 { 00240 long tree_style = topic_tree_->GetWindowStyle(); 00241 00242 if (allowed) 00243 { 00244 tree_style &= ~wxTR_SINGLE; 00245 tree_style |= wxTR_MULTIPLE; 00246 } 00247 else 00248 { 00249 tree_style &= ~wxTR_MULTIPLE; 00250 tree_style |= wxTR_SINGLE; 00251 } 00252 00253 topic_tree_->SetWindowStyle(tree_style); 00254 topic_tree_->Refresh(); 00255 } 00256 00257 } // namespace rxtools