1 #pragma once
2 #include "source_base.hpp"
3 #include <boost/optional.hpp>
4 #include <functional>
5 #include <gtkmm.h>
6 #include <unordered_map>
7 
8 class SelectionDialogBase {
9   class ListViewText : public Gtk::TreeView {
10     class ColumnRecord : public Gtk::TreeModel::ColumnRecord {
11     public:
ColumnRecord()12       ColumnRecord() {
13         add(text);
14         add(index);
15       }
16       Gtk::TreeModelColumn<std::string> text;
17       Gtk::TreeModelColumn<unsigned int> index;
18     };
19 
20   public:
21     bool use_markup;
22     ColumnRecord column_record;
23     ListViewText(bool use_markup);
24     void append(const std::string &value);
25     void erase_rows();
26     void clear();
27 
28   private:
29     Glib::RefPtr<Gtk::ListStore> list_store;
30     Gtk::CellRendererText cell_renderer;
31     unsigned int size = 0;
32   };
33 
34   class SearchEntry : public Gtk::SearchEntry {
35   public:
SearchEntry()36     SearchEntry() : Gtk::SearchEntry() {}
on_key_press_event(GdkEventKey * event)37     bool on_key_press_event(GdkEventKey *event) override { return Gtk::SearchEntry::on_key_press_event(event); };
38   };
39 
40 public:
41   SelectionDialogBase(Source::BaseView *view, const boost::optional<Gtk::TextIter> &start_iter, bool show_search_entry, bool use_markup);
~SelectionDialogBase()42   virtual ~SelectionDialogBase() {}
43   void add_row(const std::string &row);
44   void erase_rows();
45   void set_cursor_at_last_row();
46   void show();
47   void hide();
48 
is_visible()49   bool is_visible() { return window.is_visible(); }
get_position(int & root_x,int & root_y)50   void get_position(int &root_x, int &root_y) { window.get_position(root_x, root_y); }
51 
52   std::function<void()> on_show;
53   std::function<void()> on_hide;
54   std::function<void(boost::optional<unsigned int> index, const std::string &text)> on_change;
55   std::function<void(unsigned int index, const std::string &text, bool hide_window)> on_select;
56   std::function<void(const std::string &text)> on_search_entry_changed;
57   Source::Mark start_mark;
58 
59 protected:
60   void cursor_changed();
61 
62   Source::BaseView *view;
63   Gtk::Window window;
64   Gtk::Box vbox;
65   Gtk::ScrolledWindow scrolled_window;
66   ListViewText list_view_text;
67   SearchEntry search_entry;
68   bool show_search_entry;
69 
70   boost::optional<unsigned int> last_index;
71 };
72 
73 class SelectionDialog : public SelectionDialogBase {
74   SelectionDialog(Source::BaseView *view, const boost::optional<Gtk::TextIter> &start_iter, bool show_search_entry, bool use_markup);
75   static std::unique_ptr<SelectionDialog> instance;
76 
77 public:
78   bool on_key_press(GdkEventKey *event);
79 
create(Source::BaseView * view,bool show_search_entry=true,bool use_markup=false)80   static void create(Source::BaseView *view, bool show_search_entry = true, bool use_markup = false) {
81     instance = std::unique_ptr<SelectionDialog>(new SelectionDialog(view, view->get_buffer()->get_insert()->get_iter(), show_search_entry, use_markup));
82   }
create(bool show_search_entry=true,bool use_markup=false)83   static void create(bool show_search_entry = true, bool use_markup = false) {
84     instance = std::unique_ptr<SelectionDialog>(new SelectionDialog(nullptr, {}, show_search_entry, use_markup));
85   }
get()86   static std::unique_ptr<SelectionDialog> &get() { return instance; }
87 };
88 
89 class CompletionDialog : public SelectionDialogBase {
90   CompletionDialog(Source::BaseView *view, const Gtk::TextIter &start_iter);
91   static std::unique_ptr<CompletionDialog> instance;
92 
93 public:
94   bool on_key_release(GdkEventKey *event);
95   bool on_key_press(GdkEventKey *event);
96 
create(Source::BaseView * view,const Gtk::TextIter & start_iter)97   static void create(Source::BaseView *view, const Gtk::TextIter &start_iter) {
98     instance = std::unique_ptr<CompletionDialog>(new CompletionDialog(view, start_iter));
99   }
get()100   static std::unique_ptr<CompletionDialog> &get() { return instance; }
101 
102 private:
103   void select(bool hide_window = true);
104 
105   int show_offset;
106   bool row_in_entry = false;
107 };
108