1 #pragma once
2 #include "source.hpp"
3 #include <boost/optional.hpp>
4 #include <gtkmm.h>
5 #include <iostream>
6 #include <list>
7 #include <map>
8 #include <sigc++/sigc++.h>
9 #include <type_traits>
10 #include <vector>
11 
12 class Notebook : public Gtk::Paned {
13   class TabLabel : public Gtk::EventBox {
14   public:
15     TabLabel(const std::function<void()> &on_close);
16     Gtk::Label label;
17   };
18 
19   class CursorLocation {
20   public:
CursorLocation(Source::View * view,const Gtk::TextIter & iter)21     CursorLocation(Source::View *view, const Gtk::TextIter &iter) : view(view), mark(iter, false) {}
22     Source::View *view;
23     Source::Mark mark;
24   };
25 
26   Notebook();
27 
28 public:
get()29   static Notebook &get() {
30     static Notebook instance;
31     return instance;
32   }
33 
34   std::vector<Gtk::Notebook> notebooks;
35 
36   size_t size();
37   Source::View *get_view(size_t index);
38   Source::View *get_current_view();
39   std::vector<Source::View *> &get_views();
40   enum class Position {
41     left,
42     right,
43     infer,
44     split
45   };
46   bool open(Source::View *view);
47   bool open(const boost::filesystem::path &file_path, Position position = Position::infer);
48   void install_rust();
49   void open_uri(const std::string &uri);
50   void configure(size_t index);
51   bool save(size_t index);
52   bool save_current();
53   bool close(size_t index);
54   bool close(Source::View *view);
55   bool close_current();
56   void next();
57   void previous();
58   void toggle_split();
59   std::vector<std::pair<size_t, Source::View *>> get_notebook_views();
60 
61   Gtk::Label status_location;
62   Gtk::Label status_file_path;
63   Gtk::Label status_branch;
64   Gtk::Label status_diagnostics;
65   Gtk::Label status_state;
66   void update_status(Source::BaseView *view);
67   void clear_status();
68 
69   std::function<void(Source::View *)> on_focus_page;
70   std::function<void(Source::View *)> on_change_page;
71   std::function<void(Source::View *)> on_close_page;
72 
73   /// Cursor history
74   std::list<CursorLocation> cursor_locations;
75   std::list<CursorLocation>::iterator current_cursor_location = cursor_locations.end();
76   bool disable_next_update_cursor_locations = false;
77   void delete_cursor_locations(Source::View *view);
78 
79 private:
80   /// Throws on out of bounds arguments
81   Source::View *get_view(size_t notebook_index, int page);
82   void focus_view(Source::View *view);
83   /// Throws if view is not found
84   size_t get_index(Source::View *view);
85   /// Throws on out of bounds index
86   std::pair<size_t, int> get_notebook_page(size_t index);
87   /// Throws if view is not found
88   std::pair<size_t, int> get_notebook_page(Source::View *view);
89 
90   std::vector<Source::View *> source_views; //Is NOT freed in destructor, this is intended for quick program exit.
91   std::vector<std::unique_ptr<Gtk::Widget>> source_maps;
92   std::vector<std::unique_ptr<Gtk::ScrolledWindow>> scrolled_windows;
93   std::vector<std::unique_ptr<Gtk::Box>> hboxes;
94   std::vector<std::unique_ptr<TabLabel>> tab_labels;
95 
96   bool split = false;
97   boost::optional<size_t> last_index;
98 
99   void set_current_view(Source::View *view);
100   Source::View *current_view = nullptr;
101   Source::View *intermediate_view = nullptr;
102 
103   bool save_modified_dialog(size_t index);
104 };
105