menu_handler.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 # Copyright (c) 2011, Willow Garage, Inc.
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions are met:
8 #
9 # * Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer.
11 # * Redistributions in binary form must reproduce the above copyright
12 # notice, this list of conditions and the following disclaimer in the
13 # documentation and/or other materials provided with the distribution.
14 # * Neither the name of the Willow Garage, Inc. nor the names of its
15 # contributors may be used to endorse or promote products derived from
16 # this software without specific prior written permission.
17 #
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 # POSSIBILITY OF SUCH DAMAGE.
29 
30 # Author: Michael Ferguson
31 
32 import rospy
33 
34 from visualization_msgs.msg import InteractiveMarkerFeedback
35 from visualization_msgs.msg import MenuEntry
36 
37 
39  def __init__(self):
40  self.title = ""
41  self.command = ""
42  self.command_type = 0
43  self.sub_entries = list()
44  self.visible = True
45  self.check_state = 0
46  self.feedback_cb = None
47 
48 
49 ## @brief Simple non-intrusive helper class which creates a menu and maps its
50 ## entries to function callbacks
52  NO_CHECKBOX = 0
53  CHECKED = 1
54  UNCHECKED = 2
55 
56  def __init__(self):
57  self.top_level_handles_ = list() # std::vector<EntryHandle>
58  self.entry_contexts_ = dict() # boost::unordered_map<EntryHandle, EntryContext>
59  self.current_handle_ = 1
60  self.managed_markers_ = set() # std::set<std::string>
61 
62  ## Insert a new menu item
63  def insert(self, title, parent=None, command_type=MenuEntry.FEEDBACK, command="", callback=None):
64  handle = self.doInsert(title, command_type, command, callback)
65  if parent is not None:
66  try:
67  parent_context = self.entry_contexts_[parent]
68  parent_context.sub_entries.append(handle)
69  except:
70  rospy.logerr("Parent menu entry " + str(parent) + " not found.")
71  return None
72  else:
73  self.top_level_handles_.append(handle)
74  return handle
75 
76  ## Specify if an entry should be visible or hidden
77  def setVisible(self, handle, visible):
78  try:
79  context = self.entry_contexts_[handle]
80  context.visible = visible
81  return True
82  except:
83  return False
84 
85  ## Specify if an entry is checked or can't be checked at all
86  def setCheckState(self, handle, check_state):
87  try:
88  context = self.entry_contexts_[handle]
89  context.check_state = check_state
90  return True
91  except:
92  return False
93 
94  ## Get the current state of an entry
95  ## @return CheckState if the entry exists and has checkbox, None otherwise
96  def getCheckState(self, handle):
97  try:
98  context = self.entry_contexts_[handle]
99  return context.check_state
100  except:
101  return None
102 
103  ## Copy current menu state into the marker given by the specified name &
104  ## divert callback for MENU_SELECT feedback to this manager
105  def apply(self, server, marker_name):
106  marker = server.get(marker_name)
107  if not marker:
108  self.managed_markers_.remove(marker_name)
109  return False
110 
111  marker.menu_entries = list()
112  self.pushMenuEntries(self.top_level_handles_, marker.menu_entries, 0)
113 
114  server.insert(marker, self.processFeedback, InteractiveMarkerFeedback.MENU_SELECT)
115  self.managed_markers_.add(marker_name)
116  return True
117 
118  ## Re-apply to all markers that this was applied to previously
119  def reApply(self, server):
120  success = True
121  # self.apply() might remove elements from
122  # self.managed_markers_. To prevent errors, copy the
123  # managed_markers sequence and iterate over the copy
124  managed_markers = list(self.managed_markers_)
125  for marker in managed_markers:
126  success = self.apply(server, marker) and success
127  return success
128 
129  ## @brief Get the title for the given menu entry
130  ## @return The title, None if menu entry does not exist.
131  def getTitle(self, handle):
132  try:
133  return self.entry_contexts_[handle].title
134  except:
135  return None
136 
137  # Call registered callback functions for given feedback command
138  def processFeedback(self, feedback):
139  try:
140  context = self.entry_contexts_[feedback.menu_entry_id]
141  except KeyError:
142  return
143  context.feedback_cb(feedback)
144 
145  # Create and push MenuEntry objects from handles_in onto
146  # entries_out. Calls itself recursively to add the entire menu tree.
147  def pushMenuEntries(self, handles_in, entries_out, parent_handle):
148  for handle in handles_in:
149  try:
150  context = self.entry_contexts_[handle]
151  if not context.visible:
152  continue
153  entries_out.append(self.makeEntry(context, handle, parent_handle))
154  if not self.pushMenuEntries(context.sub_entries, entries_out, handle):
155  return False
156  except:
157  rospy.logerr("Internal error: context handle not found! This is a bug in MenuHandler.")
158  return False
159  return True
160 
161  def makeEntry(self, context, handle, parent_handle):
162  menu_entry = MenuEntry()
163  if context.check_state == self.NO_CHECKBOX:
164  menu_entry.title = context.title
165  elif context.check_state == self.CHECKED:
166  menu_entry.title = "[x] "+context.title
167  elif context.check_state == self.UNCHECKED:
168  menu_entry.title = "[ ] "+context.title
169 
170  menu_entry.command = context.command
171  menu_entry.command_type = context.command_type
172  menu_entry.id = handle
173  menu_entry.parent_id = parent_handle
174 
175  return menu_entry
176 
177  # Insert without adding a top-level entry
178  def doInsert(self, title, command_type, command, feedback_cb):
179  handle = self.current_handle_
180  self.current_handle_ += 1
181 
182  context = EntryContext()
183  context.title = title
184  context.command = command
185  context.command_type = command_type
186  context.visible = True
187  context.check_state = self.NO_CHECKBOX
188  context.feedback_cb = feedback_cb
189 
190  self.entry_contexts_[handle] = context
191  return handle
def insert(self, title, parent=None, command_type=MenuEntry.FEEDBACK, command="", callback=None)
Insert a new menu item.
Definition: menu_handler.py:63
Simple non-intrusive helper class which creates a menu and maps its entries to function callbacks...
Definition: menu_handler.py:51
def setCheckState(self, handle, check_state)
Specify if an entry is checked or can&#39;t be checked at all.
Definition: menu_handler.py:86
def apply(self, server, marker_name)
Copy current menu state into the marker given by the specified name & divert callback for MENU_SELECT...
def doInsert(self, title, command_type, command, feedback_cb)
def getTitle(self, handle)
Get the title for the given menu entry.
def getCheckState(self, handle)
Get the current state of an entry.
Definition: menu_handler.py:96
def reApply(self, server)
Re-apply to all markers that this was applied to previously.
def setVisible(self, handle, visible)
Specify if an entry should be visible or hidden.
Definition: menu_handler.py:77
def makeEntry(self, context, handle, parent_handle)
def pushMenuEntries(self, handles_in, entries_out, parent_handle)


interactive_markers
Author(s): David Gossow
autogenerated on Sun Feb 3 2019 03:24:09