]> git.lyx.org Git - lyx.git/blob - src/frontends/gtk/GToolbar.C
Change glob() API to accept a dir parameter.
[lyx.git] / src / frontends / gtk / GToolbar.C
1 /**
2  * \file GToolbar.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  * \author John Spray
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 // Too hard to make concept checks work with this file
15 #ifdef _GLIBCPP_CONCEPT_CHECKS
16 #undef _GLIBCPP_CONCEPT_CHECKS
17 #endif
18
19 #include "GToolbar.h"
20 #include "GView.h"
21
22 #include "ghelpers.h"
23
24 #include "buffer.h"
25 #include "bufferparams.h"
26 #include "debug.h"
27 #include "funcrequest.h"
28 #include "FuncStatus.h"
29 #include "lyxfunc.h"
30
31 using std::string;
32
33 namespace lyx {
34 namespace frontend {
35
36 namespace {
37
38 GView::Position getPosition(ToolbarBackend::Flags const & flags)
39 {
40         if (flags & ToolbarBackend::TOP)
41                 return GView::Top;
42         if (flags & ToolbarBackend::BOTTOM)
43                 return GView::Bottom;
44         if (flags & ToolbarBackend::LEFT)
45                 return GView::Left;
46         if (flags & ToolbarBackend::RIGHT)
47                 return GView::Right;
48         return GView::Top;
49 }
50
51
52 LyXTextClass const & getTextClass(LyXView const & lv)
53 {
54         return lv.buffer()->params().getLyXTextClass();
55 }
56
57 char const * gToolData = "tool_data";
58
59 } // namespace anon
60
61
62 GLayoutBox::GLayoutBox(LyXView & owner,
63                        Gtk::Toolbar & toolbar,
64                        FuncRequest const & func)
65         : owner_(owner),
66           internal_(false)
67 {
68         combo_.signal_changed().connect(
69                 sigc::mem_fun(*this,&GLayoutBox::selected));
70
71         model_ = Gtk::ListStore::create(cols_);
72         combo_.set_model(model_);
73         Gtk::CellRendererText * cell = Gtk::manage(new Gtk::CellRendererText);
74         combo_.pack_start(*cell, true);
75         combo_.add_attribute(*cell,"text",0);
76         combo_.set_wrap_width(2);
77         // Initially there's nothing in the liststore, so set the size
78         // to avoid it jumping too much when the user does something that
79         // causes the first update()
80         combo_.set_size_request(130,-1);
81
82
83         combo_.set_data(
84                 gToolData,
85                 reinterpret_cast<void*>(&const_cast<FuncRequest &>(func)));
86
87         combo_.show();
88
89         Gtk::ToolItem * toolitem = Gtk::manage(new Gtk::ToolItem);
90         toolitem->add(combo_);
91         toolbar.append(*toolitem);
92 }
93
94 void GLayoutBox::set(string const & layout)
95 {
96         LyXTextClass const & tc = getTextClass(owner_);
97         string const target = tc[layout]->name();
98
99         internal_ = true;
100         Gtk::TreeModel::iterator it = model_->children().begin();
101         Gtk::TreeModel::iterator end = model_->children().end();
102         for (; it != end; ++it) {
103                 if ((*it)[cols_.name] == target){
104                         combo_.set_active(it);
105                         internal_ = false;
106                         return;
107                 }
108         }
109         internal_ = false;
110
111         lyxerr << "ERROR (GLayoutBox::set): layout not found! name: "
112                << target << std::endl;
113 }
114
115
116 void GLayoutBox::update()
117 {
118         clear();
119
120         LyXTextClass const & tc = getTextClass(owner_);
121
122         LyXTextClass::const_iterator it = tc.begin();
123         LyXTextClass::const_iterator const end = tc.end();
124
125         internal_ = true;
126         for (; it != end; ++it)
127                 if ((*it)->obsoleted_by().empty()) {
128                         Gtk::TreeModel::iterator iter = model_->append();
129                         Gtk::TreeModel::Row row = *iter;
130                         row[cols_.name] = Glib::locale_to_utf8((*it)->name());
131                 }
132         internal_ = false;
133
134         // now that we've loaded something into the combobox, forget
135         // the initial fixed size and let GTK decide.
136         combo_.set_size_request(-1,-1);
137 }
138
139
140 void GLayoutBox::clear()
141 {
142         internal_ = true;
143         model_->clear();
144         internal_ = false;
145 }
146
147
148 void GLayoutBox::open()
149 {
150         combo_.popup();
151 }
152
153
154 void GLayoutBox::setEnabled(bool sensitive)
155 {
156         combo_.set_sensitive(sensitive);
157 }
158
159
160 void GLayoutBox::selected()
161 {
162         if (internal_)
163                 return;
164
165         Glib::ustring layoutGuiName = (*(combo_.get_active()))[cols_.name];
166
167         // we get two signal, one of them is empty and useless
168         if (layoutGuiName.empty())
169                 return;
170
171         layoutSelected(owner_, layoutGuiName);
172 }
173
174 } // namespace frontend
175 } // namespace lyx
176
177
178 Toolbars::ToolbarPtr make_toolbar(ToolbarBackend::Toolbar const & tbb,
179                                   LyXView & owner)
180 {
181         using lyx::frontend::GToolbar;
182         return Toolbars::ToolbarPtr(new GToolbar(tbb, owner));
183 }
184
185 namespace lyx {
186 namespace frontend {
187
188 GToolbar::GToolbar(ToolbarBackend::Toolbar const & tbb, LyXView & owner)
189         : owner_(dynamic_cast<GView &>(owner))
190 {
191         ToolbarBackend::item_iterator it = tbb.items.begin();
192         ToolbarBackend::item_iterator end = tbb.items.end();
193         for (; it != end; ++it)
194                 add(it->first, it->second);
195
196         toolbar_.set_toolbar_style(Gtk::TOOLBAR_ICONS);
197         toolbar_.show_all();
198
199         GView::Position const position = getPosition(tbb.flags);
200
201         if (position == GView::Left || position == GView::Right)
202                 toolbar_.set_orientation(Gtk::ORIENTATION_VERTICAL);
203
204         owner_.getBox(position).children().push_back(
205                 Gtk::Box_Helpers::Element(toolbar_, Gtk::PACK_SHRINK));
206
207         toolbar_.set_tooltips(true);
208 }
209
210 void GToolbar::add(FuncRequest const & func, string const & tooltip)
211 {
212         switch (func.action) {
213         case ToolbarBackend::SEPARATOR: {
214                 Gtk::SeparatorToolItem * space =
215                         Gtk::manage(new Gtk::SeparatorToolItem);
216                 toolbar_.append(*space);
217                 break;
218         }
219
220         case ToolbarBackend::MINIBUFFER:
221                 // Not supported yet.
222                 break;
223
224         case ToolbarBackend::LAYOUTS: {
225                 layout_.reset(new GLayoutBox(owner_, toolbar_, func));
226                 break;
227         }
228
229         default: {
230                 // choose an icon from the funcrequest
231                 Gtk::BuiltinStockID stockID = getGTKStockIcon(func);
232
233                 Glib::ustring tip = Glib::locale_to_utf8(tooltip);
234
235                 Gtk::ToolButton * toolbutton;
236                 if (stockID != Gtk::Stock::MISSING_IMAGE) {
237                         // Prefer stock gtk graphics
238                         Gtk::IconSize size(Gtk::ICON_SIZE_LARGE_TOOLBAR);
239                         Gtk::Image * image = Gtk::manage(new Gtk::Image(stockID, size));
240                         image->show();
241                         toolbutton = Gtk::manage(new Gtk::ToolButton(*image));
242                 } else {
243                         Glib::ustring xpmName =
244                                 Glib::locale_to_utf8(toolbarbackend.getIcon(func));
245                         Gtk::Image * image = Gtk::manage(new Gtk::Image(xpmName));
246                         image->show();
247                         toolbutton = Gtk::manage(new Gtk::ToolButton(*image));
248                 }
249
250                 // This code is putting a function reference into the GObject data field
251                 // named gToolData.  That's how we know how to update the status of the
252                 // toolitem later.
253                 toolbutton->set_data(gToolData,
254                         reinterpret_cast<void*>(&const_cast<FuncRequest &>(func)));
255
256                 toolbutton->set_tooltip(*toolbar_.get_tooltips_object(),tip);
257
258                 toolbutton->signal_clicked().connect(sigc::bind(sigc::mem_fun(*this,
259                         &GToolbar::clicked), FuncRequest(func)));
260                 toolbar_.append(*toolbutton);
261                 break;
262         }
263
264         }
265 }
266
267
268 void GToolbar::clicked(FuncRequest func)
269 {
270         owner_.getLyXFunc().dispatch(func);
271 }
272
273
274 void GToolbar::hide(bool)
275 {
276         toolbar_.hide();
277 }
278
279
280 void GToolbar::show(bool)
281 {
282         toolbar_.show();
283 }
284
285
286 void GToolbar::update()
287 {
288         int const items = toolbar_.get_n_items();
289
290         for (int i = 0; i < items; ++i) {
291                 Gtk::ToolItem * item = toolbar_.get_nth_item(i);
292
293                 FuncRequest const * func = reinterpret_cast<FuncRequest *>(
294                         item->get_data(gToolData));
295                 if (func) {
296                         FuncStatus const status = owner_.getLyXFunc().getStatus(*func);
297                         item->set_sensitive(status.enabled());
298                 }
299         }
300 }
301
302 } // namespace frontend
303 } // namespace lyx