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