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