creativity  v1.3.0
Agent-based model of creativity and piracy
GUI.hpp
1 #pragma once
2 #include "creativity/cmdargs/GUI.hpp"
3 #include "creativity/gui/GraphArea.hpp"
4 #include <eris/noncopyable.hpp>
5 #include <eris/Position.hpp>
6 #include <eris/types.hpp>
7 #include <glibmm/refptr.h>
8 #include <sigc++/connection.h>
9 #include <gtkmm/widget.h>
10 #include <gtkmm/builder.h> // IWYU pragma: keep
11 #include <boost/geometry/core/cs.hpp>
12 #include <boost/geometry/geometries/point.hpp>
13 #include <boost/geometry/index/rtree.hpp>
14 #include <unordered_map>
15 #include <list>
16 #include <chrono>
17 #include <functional>
18 #include <string>
19 #include <type_traits>
20 #include <utility>
21 #include <vector>
22 #include <thread>
23 #include <mutex>
24 #include <condition_variable>
25 #include <memory>
26 
27 namespace Gdk { class Cursor; }
28 namespace Glib { class Dispatcher; }
29 namespace Gtk { class Application; }
30 namespace Gtk { class FileFilter; }
31 namespace Gtk { class ScrolledWindow; }
32 namespace Gtk { class TreeView; }
33 namespace Gtk { class Window; }
34 namespace creativity { class Creativity; }
35 namespace creativity { namespace state { class State; } }
36 
37 namespace creativity {
39 namespace gui {
40 
41 // Forward declarations
42 class ReaderStore;
43 class BookStore;
44 class InfoWindow;
45 
49 class GUI : eris::noncopyable {
50  public:
51  struct Parameter; // forward declaration
52 
56  GUI(
64 
73  std::function<void(Parameter param)> configure,
74 
80  std::function<void()> initialize,
81 
84  std::function<void(eris::eris_time_t end)> change_periods,
85 
91  std::function<void()> run,
92 
95  std::function<void()> stop,
96 
98  std::function<void()> step,
99 
101  std::function<void()> quit
102  );
103 
104  // Destructor: tells the thread to quit and then waits until it does
105  virtual ~GUI();
106 
109  void start(const cmdargs::GUI &args);
110 
114  void checkEvents();
115 
119  void waitEvents();
120 
130  void newStates(eris::eris_time_t switch_to = (eris::eris_time_t) -1);
131 
137  void initialized();
138 
140  void running();
141 
147  void progress(eris::eris_time_t t, eris::eris_time_t end, double speed);
148 
154  void stopped(bool more);
155 
158  void error(std::string message);
159 
161  enum class ParamType {
162  save_as,
163  load,
164  seed,
165  threads
166  };
172  struct Parameter {
176  union {
177  bool bl;
178  unsigned long ul;
179  long l;
180  unsigned int ui;
181  int i;
182  double dbl;
183  std::chrono::milliseconds dur_ms;
184  void *ptr;
185  };
186  };
187 
190  class Event {
191  public:
193  enum class Type {
194  configure,
195  initialize,
196  periods,
197  run,
198  stop,
199  step,
200  quit,
201  none
202  };
203 
207  operator bool();
208 
210  Type type = Type::none;
211 
216 
220  unsigned long ul;
221 
222  private:
223  friend class GUI;
225  Event() = default;
227  Event(Type t);
229  Event(const Parameter &p);
231  Event(Type t, unsigned long ul);
232  };
233 
237  void waitForEvent(Event::Type t);
238 
241  static std::string pos_to_string(const eris::Position &pos);
242 
243  private:
245  Creativity &creativity_;
246 
248  std::thread gui_thread_{};
249 
253  Glib::RefPtr<Gtk::Application> app_;
254 
258  Glib::RefPtr<Gtk::Builder> builder_;
259 
261  std::shared_ptr<Gtk::Window> main_window_;
262 
264  std::string main_window_title_;
265 
267  bool thread_running_{false};
268 
270  bool piracy_tick_added_ = false;
271 
273  bool public_tick_added_ = false;
274 
276  std::unordered_map<std::string, double> default_override_;
277 
281  std::unique_ptr<Glib::Dispatcher> dispatcher_;
282 
288  std::mutex mutex_;
289 
291  std::condition_variable cv_;
292 
296  void processEvents_(std::unique_lock<decltype(mutex_)> &lock);
297 
299  class Signal {
300  public:
302  enum class Type {
310  new_states,
311  initialized,
312  running,
313  progress,
314  stopped,
315  error,
316  quit,
317  none
318  };
319 
321  Type type = Type::none;
322 
324  std::string message;
326  bool boolean;
328  std::vector<uint64_t> uls;
330  std::vector<double> doubles;
331 
333  Signal() = default;
335  Signal(Type type) : type(type) {}
337  Signal(Type type, const std::string &message) : type{type}, message{message} {}
339  Signal(Type type, bool b) : type{type}, boolean{b} {}
341  Signal(Type type, double d) : type{type}, doubles(1, d) {}
343  template<typename UIntT, typename = typename std::enable_if<std::is_integral<UIntT>::value and std::is_unsigned<UIntT>::value>::type>
344  Signal(Type type, UIntT ul) : type{type}, uls(1, ul) {}
346  };
347 
349  std::list<Signal> signal_queue_;
350 
352  void queueSignal(Signal &&s);
353 
355  std::list<Event> event_queue_;
356 
360  template <typename... Args>
361  void queueEvent(Args&&... args);
362 
363  friend class GraphArea;
364 
366  void thr_signal();
367 
374  void thr_run(const cmdargs::GUI &args);
375 
392  void thr_connect_vis_setting(
393  const std::string &field,
394  bool &enabled,
395  GraphArea::Colour &colour,
396  bool affects_rtree = false,
397  const std::vector<std::string> &needs_all = {},
398  const std::vector<std::string> &needs_any = {});
399 
415  void thr_connect_vis_enabled(
416  const std::string &field,
417  bool &enabled,
418  bool affects_rtree = false,
419  const std::vector<std::string> &needs_all = {},
420  const std::vector<std::string> &needs_any = {});
421 
433  void thr_connect_vis_colour(
434  const std::string &field,
435  GraphArea::Colour &colour,
436  const std::vector<std::string> &needs_all = {},
437  const std::vector<std::string> &needs_any = {});
438 
443  void thr_connect_vis_deps(
444  Gtk::Widget *widget,
445  const std::vector<std::string> &needs_all,
446  const std::vector<std::string> &needs_any);
447 
451  void thr_update_parameters();
452 
455  void thr_set_state(eris::eris_time_t t);
456 
458  eris::eris_time_t state_curr_ = (eris::eris_time_t) -1;
459 
464  eris::eris_time_t state_num_ = 0;
465 
472  void thr_info_dialog(eris::eris_id_t member_id);
473 
476  void loadSim();
477 
480  void saveSim();
481 
484  void initializeSim();
485 
489  void runSim();
490 
492  std::unique_ptr<GraphArea> graph_;
493 
495  Gtk::ScrolledWindow *rdr_win_;
496 
498  Gtk::ScrolledWindow *bk_win_;
499 
502  template <class T>
503  typename std::enable_if<std::is_base_of<Gtk::Widget, T>::value, T*>::type
504  widget(const std::string &widget_name) {
505  T* widget;
506  builder_->get_widget(widget_name, widget);
507  return widget;
508  }
509 
511  double sb(const std::string &widget_name);
512 
514  int sb_int(const std::string &widget_name);
515 
519  std::string save_, load_;
520 
521  // The file filter. Access via fileFilter().
522  mutable Glib::RefPtr<Gtk::FileFilter> ff_;
523 
525  decltype(ff_) fileFilter() const;
526 
527  // The callbacks for GUI thread events
528  std::function<void(GUI::Parameter)> on_configure_;
529  std::function<void()> on_initialize_;
530  std::function<void(unsigned int count)> on_change_periods_;
531  std::function<void()> on_run_;
532  std::function<void()> on_stop_;
533  std::function<void()> on_step_;
534  std::function<void()> on_quit_;
535 
537  void handleEvent(const GUI::Event &event);
538 
540  std::unordered_map<eris::eris_id_t, std::unique_ptr<InfoWindow>> info_windows_;
541 
542  using rt_point = boost::geometry::model::point<double, 2, boost::geometry::cs::cartesian>;
543  using rt_val = std::pair<rt_point, eris::eris_id_t>;
544  using RTree = boost::geometry::index::rtree<rt_val, boost::geometry::index::rstar<16>>;
545 
553  std::vector<rt_val> thr_nearest(const rt_point &point, int n = 1);
554 
558  void thr_reset_rtrees();
559 
563  void thr_init_rtree(RTree &rt, const std::shared_ptr<const state::State> &state) const;
564 
565  std::function<bool(GdkEventMotion* event)> motion_handler_;
566  sigc::connection motion_handler_conn_;
567  Glib::RefPtr<Gdk::Cursor> hand_;
568 
571  struct temporal_data {
572  Glib::RefPtr<ReaderStore> rdr_model;
573  std::unique_ptr<Gtk::TreeView> rdr_tree;
574  Glib::RefPtr<BookStore> bk_model;
575  std::unique_ptr<Gtk::TreeView> bk_tree;
576  std::unique_ptr<RTree> rtree;
577  };
578 
580  std::list<std::pair<eris::eris_time_t, temporal_data>> temporal_cache_;
583  unsigned int temporal_cache_size_ = 10;
584 
585 };
586 
587 template <typename... Args>
588 void GUI::queueEvent(Args&&... args) {
589  std::unique_lock<std::mutex> lock(mutex_);
590  event_queue_.push_back(Event(std::forward<Args>(args)...));
591  lock.unlock();
592  cv_.notify_all();
593 }
594 
595 } }
Definition: BookStore.hpp:14
Definition: CLI.hpp:5
Primary namespace for all Creativity library code.
Definition: config.hpp:4
CmdArgs/Simulator subclass for graphical simulator command-line arguments.
Definition: GUI.hpp:11
Definition: BookInfoWindow.hpp:6
Definition: GUI.hpp:27
Parameter parameter
Will be set to a list of configured GUI::Parameters if this is a setup event.
Definition: GUI.hpp:215
Simple class containing event information.
Definition: GUI.hpp:190
Definition: Variable.hpp:389
Gtk drawing area upon which the simulation state visualization is drawn.
Definition: GraphArea.hpp:20
Gtk dialog for showing reader or book info.
Definition: InfoWindow.hpp:23
The parameter struct for passing a configured value back from the GUI.
Definition: GUI.hpp:172
Definition: Policy.hpp:125
ParamType
Parameter types for a Parameter.
Definition: GUI.hpp:161
Class that runs a GUI in a thread, collecting its events into a queue to be processed periodically (e...
Definition: GUI.hpp:49
ParamType param
The parameter type.
Definition: GUI.hpp:174
Cairo::RefPtr< Cairo::SolidPattern > Colour
Typedef of Colour to the appropriate ref-pointed Cairo class.
Definition: GraphArea.hpp:69
Central class for a creativity simulation; this class handles setting up the simulation according to ...
Definition: Creativity.hpp:22
Type
The types of events that the GUI thread can send to the main thread.
Definition: GUI.hpp:193
unsigned long ul
unsigned long integer value associated with the event.
Definition: GUI.hpp:220