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