Goby v2
liaison_scope.h
1 // Copyright 2009-2018 Toby Schneider (http://gobysoft.org/index.wt/people/toby)
2 // GobySoft, LLC (2013-)
3 // Massachusetts Institute of Technology (2007-2014)
4 // Community contributors (see AUTHORS file)
5 //
6 //
7 // This file is part of the Goby Underwater Autonomy Project Libraries
8 // ("The Goby Libraries").
9 //
10 // The Goby Libraries are free software: you can redistribute them and/or modify
11 // them under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 2.1 of the License, or
13 // (at your option) any later version.
14 //
15 // The Goby Libraries are distributed in the hope that they will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with Goby. If not, see <http://www.gnu.org/licenses/>.
22 
23 #ifndef LIAISONSCOPE20110609H
24 #define LIAISONSCOPE20110609H
25 
26 #include <boost/circular_buffer.hpp>
27 #include <boost/thread.hpp>
28 
29 #include <Wt/WBorder>
30 #include <Wt/WBoxLayout>
31 #include <Wt/WColor>
32 #include <Wt/WCssDecorationStyle>
33 #include <Wt/WEvent>
34 #include <Wt/WSortFilterProxyModel>
35 #include <Wt/WStandardItemModel>
36 #include <Wt/WText>
37 #include <Wt/WTimer>
38 #include <Wt/WTreeView>
39 #include <Wt/WVBoxLayout>
40 
41 #include "goby/common/liaison_container.h"
42 #include "goby/moos/moos_node.h"
43 #include "goby/moos/protobuf/liaison_config.pb.h"
44 
45 namespace Wt
46 {
47 class WStandardItemModel;
48 }
49 
50 namespace goby
51 {
52 namespace common
53 {
55 {
56  public:
57  LiaisonScope(ZeroMQService* zeromq_service, const protobuf::LiaisonConfig& cfg,
58  Wt::WContainerWidget* parent = 0);
59 
60  void moos_inbox(CMOOSMsg& msg);
61 
62  void handle_message(CMOOSMsg& msg, bool fresh_message);
63 
64  static std::vector<Wt::WStandardItem*> create_row(CMOOSMsg& msg);
65  static void attach_pb_rows(const std::vector<Wt::WStandardItem*>& items, CMOOSMsg& msg);
66  static void update_row(CMOOSMsg& msg, const std::vector<Wt::WStandardItem*>& items);
67 
68  void loop();
69 
70  void pause();
71  void resume();
72  bool is_paused()
73  {
74  return (controls_div_->paused_mail_thread_ &&
75  controls_div_->paused_mail_thread_->joinable());
76  }
77 
78  private:
79  void handle_global_key(Wt::WKeyEvent event);
80 
81  void focus()
82  {
83  if (last_scope_state_ == ACTIVE)
84  resume();
85  else if (last_scope_state_ == UNKNOWN)
86  scope_timer_.start();
87 
88  last_scope_state_ = UNKNOWN;
89  }
90 
91  void unfocus()
92  {
93  if (last_scope_state_ == UNKNOWN)
94  {
95  last_scope_state_ = is_paused() ? STOPPED : ACTIVE;
96  pause();
97  }
98  }
99 
100  void cleanup()
101  {
102  // we must resume the scope as this stops the background thread, allowing the ZeroMQService for the scope to be safely deleted. This is inelegant, but a by product of how Wt destructs the root object *after* this class (and thus all the local class objects).
103  resume();
104  }
105 
106  private:
107  ZeroMQService* zeromq_service_;
108  const protobuf::MOOSScopeConfig& moos_scope_config_;
109 
110  Wt::WStringListModel* history_model_;
111  Wt::WStandardItemModel* model_;
112  Wt::WSortFilterProxyModel* proxy_;
113 
114  Wt::WVBoxLayout* main_layout_;
115 
116  Wt::WTimer scope_timer_;
117  enum ScopeState
118  {
119  ACTIVE = 1,
120  STOPPED = 2,
121  UNKNOWN = 0
122  };
123  ScopeState last_scope_state_;
124 
125  struct SubscriptionsContainer : Wt::WContainerWidget
126  {
127  SubscriptionsContainer(LiaisonScope* node, Wt::WStandardItemModel* model,
128  Wt::WStringListModel* history_model,
129  std::map<std::string, int>& msg_map,
130  Wt::WContainerWidget* parent = 0);
131 
132  void handle_add_subscription();
133  void handle_remove_subscription(Wt::WPushButton* clicked_anchor);
134  void add_subscription(std::string type);
135 
136  void refresh_with_newest();
137  void refresh_with_newest(const std::string& type);
138 
139  LiaisonScope* node_;
140 
141  Wt::WStandardItemModel* model_;
142  Wt::WStringListModel* history_model_;
143  std::map<std::string, int>& msg_map_;
144 
145  Wt::WText* add_text_;
146  Wt::WLineEdit* subscribe_filter_text_;
147  Wt::WPushButton* subscribe_filter_button_;
148  Wt::WBreak* subscribe_break_;
149  Wt::WText* remove_text_;
150 
151  std::set<std::string> subscriptions_;
152  };
153 
154  SubscriptionsContainer* subscriptions_div_;
155 
156  struct HistoryContainer : Wt::WContainerWidget
157  {
158  HistoryContainer(MOOSNode* node, Wt::WVBoxLayout* main_layout,
159  Wt::WAbstractItemModel* model,
160  const protobuf::MOOSScopeConfig& moos_scope_config,
161  Wt::WContainerWidget* parent = 0);
162 
163  void handle_add_history();
164  void handle_remove_history(std::string type);
165  void add_history(const goby::common::protobuf::MOOSScopeConfig::HistoryConfig& config);
166  void toggle_history_plot(Wt::WWidget* plot);
167  void display_message(CMOOSMsg& msg);
168  void flush_buffer();
169 
170  struct MVC
171  {
172  std::string key;
173  Wt::WContainerWidget* container;
174  Wt::WStandardItemModel* model;
175  Wt::WTreeView* tree;
176  Wt::WSortFilterProxyModel* proxy;
177  };
178 
179  MOOSNode* node_;
180  Wt::WVBoxLayout* main_layout_;
181 
182  const protobuf::MOOSScopeConfig& moos_scope_config_;
183  std::map<std::string, MVC> history_models_;
184  Wt::WText* hr_;
185  Wt::WText* add_text_;
186  Wt::WComboBox* history_box_;
187  Wt::WPushButton* history_button_;
188 
189  boost::circular_buffer<CMOOSMsg> buffer_;
190  };
191 
192  HistoryContainer* history_header_div_;
193 
194  struct ControlsContainer : Wt::WContainerWidget
195  {
196  ControlsContainer(Wt::WTimer* timer, bool start_paused, LiaisonScope* scope,
197  SubscriptionsContainer* subscriptions_div,
198  HistoryContainer* history_header_div, Wt::WContainerWidget* parent = 0);
199  ~ControlsContainer();
200 
201  void handle_play_pause(bool toggle_state);
202 
203  void pause();
204  void resume();
205 
206  void run_paused_mail();
207  boost::shared_ptr<boost::thread> paused_mail_thread_;
208 
209  Wt::WTimer* timer_;
210 
211  Wt::WPushButton* play_pause_button_;
212 
213  Wt::WText* spacer_;
214  Wt::WText* play_state_;
215  bool is_paused_;
216  LiaisonScope* scope_;
217  SubscriptionsContainer* subscriptions_div_;
218  HistoryContainer* history_header_div_;
219  };
220 
221  ControlsContainer* controls_div_;
222 
223  struct RegexFilterContainer : Wt::WContainerWidget
224  {
225  RegexFilterContainer(Wt::WStandardItemModel* model, Wt::WSortFilterProxyModel* proxy,
226  const protobuf::MOOSScopeConfig& moos_scope_config,
227  Wt::WContainerWidget* parent = 0);
228 
229  void handle_set_regex_filter();
230  void handle_clear_regex_filter();
231  void toggle_regex_examples_table();
232 
233  Wt::WStandardItemModel* model_;
234  Wt::WSortFilterProxyModel* proxy_;
235 
236  Wt::WText* hr_;
237  Wt::WText* set_text_;
238  Wt::WComboBox* regex_column_select_;
239  Wt::WText* expression_text_;
240  Wt::WLineEdit* regex_filter_text_;
241  Wt::WPushButton* regex_filter_button_;
242  Wt::WPushButton* regex_filter_clear_;
243  Wt::WPushButton* regex_filter_examples_;
244 
245  Wt::WBreak* break_;
246  Wt::WTable* regex_examples_table_;
247  };
248 
249  RegexFilterContainer* regex_filter_div_;
250 
251  Wt::WTreeView* scope_tree_view_;
252 
253  // maps CMOOSMsg::GetKey into row
254  std::map<std::string, int> msg_map_;
255 
256  WContainerWidget* bottom_fill_;
257 };
258 
259 class LiaisonScopeMOOSTreeView : public Wt::WTreeView
260 {
261  public:
262  LiaisonScopeMOOSTreeView(const protobuf::MOOSScopeConfig& moos_scope_config,
263  Wt::WContainerWidget* parent = 0);
264 
265  private:
266  // void handle_double_click(const Wt::WModelIndex& index, const Wt::WMouseEvent& event);
267 };
268 
269 class LiaisonScopeMOOSModel : public Wt::WStandardItemModel
270 {
271  public:
272  LiaisonScopeMOOSModel(const protobuf::MOOSScopeConfig& moos_scope_config,
273  Wt::WContainerWidget* parent = 0);
274 };
275 
276 } // namespace common
277 } // namespace goby
278 
279 #endif
The global namespace for the Goby project.