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