1 #include "text_editor.hpp"
2 #include "util/gtk_util.hpp"
3 
4 namespace horizon {
5 
TextEditor(Lines mode)6 TextEditor::TextEditor(Lines mode)
7 {
8     entry = Gtk::manage(new Gtk::Entry());
9     entry->signal_activate().connect([this] { s_signal_activate.emit(); });
10     entry->signal_changed().connect([this] { s_signal_changed.emit(); });
11     entry_focus_out_conn = entry->signal_focus_out_event().connect([this](GdkEventFocus *ev) -> bool {
12         s_signal_lost_focus.emit();
13         return false;
14     });
15     if (mode == Lines::MULTI) {
16         entry->signal_key_press_event().connect([this](GdkEventKey *ev) {
17             if (ev->keyval == GDK_KEY_Return && (ev->state & Gdk::SHIFT_MASK)) {
18                 entry_focus_out_conn.disconnect();
19                 auto txt = get_text();
20                 auto pos = entry->get_position();
21                 txt.insert(pos, "\n");
22                 set_transition_duration(100);
23                 set_text(txt, Select::NO);
24                 auto iter = view->get_buffer()->begin();
25                 iter.forward_cursor_positions(pos + 1);
26                 view->get_buffer()->place_cursor(iter);
27                 return true;
28             }
29             return false;
30         });
31     }
32 
33     auto sc = Gtk::manage(new Gtk::ScrolledWindow);
34     sc->set_shadow_type(Gtk::SHADOW_IN);
35     sc->set_min_content_height(100);
36     view = Gtk::manage(new Gtk::TextView);
37     view->set_top_margin(4);
38     view->set_bottom_margin(4);
39     view->set_left_margin(4);
40     view->set_right_margin(4);
41     view->get_buffer()->signal_changed().connect([this] { s_signal_changed.emit(); });
42     view->signal_key_press_event().connect(
43             [this](GdkEventKey *ev) {
44                 if (ev->keyval == GDK_KEY_Return && (ev->state & Gdk::SHIFT_MASK)) {
45                     s_signal_activate.emit();
46                     return true;
47                 }
48                 return false;
49             },
50             false);
51     view->signal_focus_out_event().connect([this](GdkEventFocus *ev) {
52         s_signal_lost_focus.emit();
53         return false;
54     });
55     sc->add(*view);
56 
57 
58     set_homogeneous(false);
59     set_interpolate_size(true);
60     set_transition_duration(0);
61     set_transition_type(Gtk::STACK_TRANSITION_TYPE_CROSSFADE);
62     {
63         auto lbox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL, 2));
64         lbox->pack_start(*entry, true, true, 0);
65         if (mode == Lines::MULTI) {
66             auto la = Gtk::manage(new Gtk::Label("Press Shift+Enter to insert a line break"));
67             la->get_style_context()->add_class("dim-label");
68             la->set_xalign(0);
69             make_label_small(la);
70             lbox->pack_start(*la, false, false, 0);
71         }
72         add(*lbox, "entry");
73         lbox->show_all();
74     }
75     {
76         auto lbox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL, 2));
77         lbox->pack_start(*sc, true, true, 0);
78         auto la = Gtk::manage(new Gtk::Label("Press Shift+Enter to finish editing"));
79         la->get_style_context()->add_class("dim-label");
80         la->set_xalign(0);
81         make_label_small(la);
82         lbox->pack_start(*la, false, false, 0);
83         add(*lbox, "view");
84         lbox->show_all();
85     }
86 
87     set_visible_child("entry");
88 }
89 
set_text(const std::string & text,Select select)90 void TextEditor::set_text(const std::string &text, Select select)
91 {
92     if (text.find('\n') != std::string::npos) {
93         view->get_buffer()->set_text(text);
94         if (select == Select::YES)
95             view->grab_focus();
96         // view->get_buffer()->select_range(view->get_buffer()->begin(), view->get_buffer()->end());
97         set_visible_child("view");
98     }
99     else {
100         entry->set_text(Glib::strescape(text));
101         if (select == Select::YES)
102             entry->select_region(0, -1);
103         set_visible_child("entry");
104     }
105 }
106 
get_text() const107 std::string TextEditor::get_text() const
108 {
109     if (get_visible_child_name() == "entry")
110         return Glib::strcompress(entry->get_text());
111     else
112         return view->get_buffer()->get_text();
113 }
114 
115 } // namespace horizon
116