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