]> git.lyx.org Git - lyx.git/blob - src/frontends/gtk/GMiniBuffer.C
some tabular fixes for the problems reported by Helge
[lyx.git] / src / frontends / gtk / GMiniBuffer.C
1 /**
2  * \file GMiniBuffer.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Huang Ying
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 // Too hard to make concept checks work with this file
14 #ifdef _GLIBCXX_CONCEPT_CHECKS
15 #undef _GLIBCXX_CONCEPT_CHECKS
16 #endif
17 #ifdef _GLIBCPP_CONCEPT_CHECKS
18 #undef _GLIBCPP_CONCEPT_CHECKS
19 #endif
20
21 #include "GView.h"
22 #include "GMiniBuffer.h"
23 #include "debug.h"
24 #include "bufferview_funcs.h"
25
26 #include "frontends/controllers/ControlCommandBuffer.h"
27
28 #include <boost/bind.hpp>
29 #include <vector>
30
31 using std::string;
32
33 namespace lyx {
34 namespace frontend {
35
36 GMiniBuffer::GMiniBuffer(GView * view, ControlCommandBuffer & control) :
37         controller_(control), view_(view)
38 {
39         listCols_.add(listCol_);
40         listStore_ = Gtk::ListStore::create(listCols_);
41         listView_.set_model(listStore_);
42         listView_.append_column("Completions", listCol_);
43         listView_.signal_key_press_event().connect(
44                 sigc::mem_fun(*this, &GMiniBuffer::onListKeyPress));
45         listView_.signal_focus_in_event().connect(
46                 sigc::mem_fun(*this, &GMiniBuffer::onListFocusIn));
47         listView_.signal_focus_out_event().connect(
48                 sigc::mem_fun(*this, &GMiniBuffer::onFocusOut));
49         listSel_ = listView_.get_selection();
50         listSel_->signal_changed().connect(
51                 sigc::mem_fun(*this, &GMiniBuffer::onSelected));
52
53         listView_.show();
54         scrolledWindow_.set_policy(Gtk::POLICY_AUTOMATIC,
55                                    Gtk::POLICY_AUTOMATIC);
56         scrolledWindow_.set_size_request(300, 150);
57         scrolledWindow_.add(listView_);
58
59         view_->getBox(GView::Bottom).children().push_back(
60                 Gtk::Box_Helpers::Element(scrolledWindow_,Gtk::PACK_SHRINK));
61
62         entry_.signal_key_press_event().connect(
63                 sigc::mem_fun(*this, &GMiniBuffer::onKeyPress));
64         entry_.signal_focus_in_event().connect(
65                 sigc::mem_fun(*this, &GMiniBuffer::onFocusIn));
66         entry_.signal_focus_out_event().connect(
67                 sigc::mem_fun(*this, &GMiniBuffer::onFocusOut));
68         entry_.signal_activate().connect(
69                 sigc::mem_fun(*this, &GMiniBuffer::onCommit));
70         entry_.show();
71
72         view_->getBox(GView::Bottom).children().push_back(
73                 Gtk::Box_Helpers::Element(entry_, Gtk::PACK_SHRINK));
74
75         infoTimer_.reset(new Timeout(1500));
76         idleTimer_.reset(new Timeout(6000));
77         focusTimer_.reset(new Timeout(50));
78         infoCon_ = infoTimer_->timeout.connect(
79                 boost::bind(&GMiniBuffer::infoTimeout, this));
80         idleCon_ = idleTimer_->timeout.connect(
81                 boost::bind(&GMiniBuffer::idleTimeout, this));
82         focusTimer_->timeout.connect(
83                 boost::bind(&GMiniBuffer::focusTimeout, this));
84         idleTimer_->start();
85         messageMode();
86 }
87
88
89 GMiniBuffer::~GMiniBuffer()
90 {
91 }
92
93
94 void GMiniBuffer::message(string const & str)
95 {
96         if (!isEditMode())
97                 setInput(Glib::locale_to_utf8(str));
98 }
99
100
101 void GMiniBuffer::showInfo(Glib::ustring const & info, bool append)
102 {
103         storedInput_ = entry_.get_text();
104         entry_.set_editable(false);
105         infoShown_ = true;
106         if (append)
107                 setInput(storedInput_ + ' ' + info);
108         else
109                 setInput(info);
110         infoTimer_->start();
111 }
112
113
114 void GMiniBuffer::onSelected()
115 {
116         if (!listSel_->count_selected_rows())
117                 return;
118         Gtk::TreeModel::iterator it = listSel_->get_selected();
119         Glib::ustring sel = (*it)[listCol_];
120         setInput(sel + ' ');
121 }
122
123
124 void GMiniBuffer::onCommit()
125 {
126         controller_.dispatch(Glib::locale_from_utf8(entry_.get_text()));
127         messageMode();
128 }
129
130
131 bool GMiniBuffer::onListFocusIn(GdkEventFocus * /*event*/)
132 {
133         if (focusTimer_->running())
134                 focusTimer_->stop();
135         if (infoShown_) {
136                 infoTimer_->stop();
137                 infoTimeout();
138         }
139         return false;
140 }
141
142
143 bool GMiniBuffer::onFocusIn(GdkEventFocus * /*event*/)
144 {
145         if (infoShown_) {
146                 infoTimer_->stop();
147                 infoTimeout();
148         }
149         if (focusTimer_->running()) {
150                 focusTimer_->stop();
151                 return false;
152         }
153         setInput("");
154         idleTimer_->stop();
155         return false;
156 }
157
158
159 bool GMiniBuffer::onFocusOut(GdkEventFocus * /*event*/)
160 {
161         focusTimer_->start();
162         return false;
163 }
164
165
166 void GMiniBuffer::focusTimeout()
167 {
168         if (infoShown_) {
169                 infoTimer_->stop();
170                 infoTimeout();
171         }
172         focusTimer_->stop();
173         setInput("");
174         idleTimer_->start();
175         scrolledWindow_.hide();
176 }
177
178
179 bool GMiniBuffer::onListKeyPress(GdkEventKey * event)
180 {
181         if (infoShown_) {
182                 infoTimer_->stop();
183                 infoTimeout();
184         }
185         switch (event->keyval) {
186         case GDK_Escape:
187                 messageMode();
188                 break;
189         case GDK_Tab:
190                 entry_.grab_focus();
191                 setInput(entry_.get_text() + ' ');
192                 break;
193         }
194         return true;
195 }
196
197
198 bool GMiniBuffer::onKeyPress(GdkEventKey * event)
199 {
200         if (infoShown_) {
201                 infoTimer_->stop();
202                 infoTimeout();
203         }
204         switch (event->keyval) {
205         case GDK_Down:
206         {
207                 Glib::ustring const h =
208                         Glib::locale_to_utf8(controller_.historyDown());
209                 if (h.empty())
210                         showInfo("[End of history]", false);
211                 else
212                         setInput(h);
213                 break;
214         }
215         case GDK_Up:
216         {
217                 Glib::ustring const h =
218                         Glib::locale_to_utf8(controller_.historyUp());
219                 if (h.empty())
220                         showInfo("[Beginning of history]", false);
221                 else
222                         setInput(h);
223                 break;
224         }
225         case GDK_Escape:
226                 messageMode();
227                 break;
228         case GDK_Tab:
229         {
230                 string new_input_locale;
231                 Glib::ustring input = entry_.get_text();
232                 std::vector<string> comp =
233                         controller_.completions(Glib::locale_from_utf8(input),
234                                                 new_input_locale);
235                 Glib::ustring new_input =
236                         Glib::locale_to_utf8(new_input_locale);
237
238                 if (comp.empty() && new_input == input) {
239                         showInfo("[no match]");
240                         break;
241                 }
242
243                 if (comp.empty()) {
244                         setInput(new_input + ' ');
245                         showInfo("[only completion]");
246                         break;
247                 }
248                 setInput(new_input);
249                 listStore_->clear();
250                 std::vector<string>::iterator it;
251                 for (it = comp.begin(); it != comp.end(); ++it)
252                         (*listStore_->append())[listCol_] =
253                                 Glib::locale_to_utf8(*it);
254                 scrolledWindow_.show();
255                 break;
256         }
257         }
258         return true;
259 }
260
261
262 bool GMiniBuffer::isEditMode() const
263 {
264         return entry_.has_focus() || listView_.has_focus();
265 }
266
267
268 void GMiniBuffer::infoTimeout()
269 {
270         infoShown_ = false;
271         setInput(storedInput_);
272         entry_.set_editable(true);
273 }
274
275
276 void GMiniBuffer::idleTimeout()
277 {
278         setInput(Glib::locale_to_utf8(controller_.getCurrentState()));
279 }
280
281
282 void GMiniBuffer::editMode()
283 {
284         entry_.grab_focus();
285 }
286
287
288 void GMiniBuffer::messageMode()
289 {
290         view_->focusWorkArea();
291 }
292
293
294 void GMiniBuffer::setInput(Glib::ustring const & input)
295 {
296         entry_.set_text(input);
297         entry_.set_position(-1);
298 }
299
300 } // namespace frontend
301 } // namespace lyx