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