]> git.lyx.org Git - lyx.git/blob - src/frontends/gtk/GToolbar.C
WS changes
[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 #include <gtkmm.h>
13
14 #include "GToolbar.h"
15 #include "GView.h"
16
17 #include "buffer.h"
18 #include "bufferparams.h"
19 #include "debug.h"
20 #include "funcrequest.h"
21 #include "FuncStatus.h"
22 #include "lyxfunc.h"
23
24 using std::string;
25
26 namespace lyx {
27 namespace frontend {
28
29 namespace {
30
31 GView::Position getPosition(ToolbarBackend::Flags const & flags)
32 {
33         if (flags & ToolbarBackend::TOP)
34                 return GView::Top;
35         if (flags & ToolbarBackend::BOTTOM)
36                 return GView::Bottom;
37         if (flags & ToolbarBackend::LEFT)
38                 return GView::Left;
39         if (flags & ToolbarBackend::RIGHT)
40                 return GView::Right;
41         return GView::Top;
42 }
43
44
45 LyXTextClass const & getTextClass(LyXView const & lv)
46 {
47         return lv.buffer()->params().getLyXTextClass();
48 }
49
50
51 void comboClear(Gtk::Combo & combo)
52 {
53         std::vector<Glib::ustring> strings;
54         strings.push_back("");
55         combo.set_popdown_strings(strings);
56 }
57
58
59 bool comboIsEmpty(Gtk::Combo & combo)
60 {
61         std::vector<Glib::ustring> strings = combo.get_popdown_strings();
62         return (strings.empty() || (strings.size() == 1 && strings[0] == ""));
63 }
64
65 char const * gToolData = "tool_data";
66
67 } // namespace anon
68
69
70 GLayoutBox::GLayoutBox(LyXView & owner,
71                        Gtk::Toolbar & toolbar,
72                        FuncRequest const & func)
73         : owner_(owner),
74           internal_(false)
75 {
76         combo_.set_value_in_list();
77         combo_.get_entry()->set_editable(false);
78         combo_.unset_flags(Gtk::CAN_FOCUS | Gtk::CAN_DEFAULT);
79         combo_.get_entry()->unset_flags(Gtk::CAN_FOCUS | Gtk::CAN_DEFAULT);
80         comboClear(combo_);
81
82         combo_.get_entry()->signal_changed().connect(
83                 SigC::slot(*this,
84                            &GLayoutBox::selected));
85
86         combo_.show();
87         toolbar.tools().push_back(Gtk::Toolbar_Helpers::Element(combo_));
88         toolbar.tools().back().get_widget()->set_data(
89                 gToolData,
90                 reinterpret_cast<void*>(&const_cast<FuncRequest &>(func)));
91 }
92
93
94 void GLayoutBox::set(string const & layout)
95 {
96         LyXTextClass const & tc = getTextClass(owner_);
97
98         internal_ = true;
99         combo_.get_entry()->set_text(tc[layout]->name());
100         internal_ = false;
101 }
102
103
104 void GLayoutBox::update()
105 {
106         LyXTextClass const & tc = getTextClass(owner_);
107
108         std::vector<Glib::ustring> strings;
109
110         LyXTextClass::const_iterator it = tc.begin();
111         LyXTextClass::const_iterator const end = tc.end();
112         for (; it != end; ++it)
113                 if ((*it)->obsoleted_by().empty())
114                         strings.push_back(
115                                 Glib::locale_to_utf8((*it)->name()));
116         internal_ = true;
117         combo_.set_popdown_strings(strings);
118         internal_ = false;
119 }
120
121
122 void GLayoutBox::clear()
123 {
124         internal_ = true;
125         comboClear(combo_);
126         internal_ = false;
127 }
128
129
130 void GLayoutBox::open()
131 {
132         combo_.get_list()->activate();
133 }
134
135
136 void GLayoutBox::setEnabled(bool sensitive)
137 {
138         combo_.set_sensitive(sensitive);
139 }
140
141
142 void GLayoutBox::selected()
143 {
144         if (internal_)
145                 return;
146
147         string layoutGuiName = combo_.get_entry()->get_text();
148         // we get two signal, one of it is empty and useless
149         if (layoutGuiName.empty())
150                 return;
151         LyXTextClass const & tc = getTextClass(owner_);
152
153         LyXTextClass::const_iterator it = tc.begin();
154         LyXTextClass::const_iterator const end = tc.end();
155         for (; it != end; ++it) {
156                 string const & name = (*it)->name();
157                 if (name == layoutGuiName) {
158                         owner_.getLyXFunc().dispatch(
159                                 FuncRequest(LFUN_LAYOUT, name),
160                                 true);
161                         return;
162                 }
163         }
164         lyxerr << "ERROR (GLayoutBox::selected): layout not found! name: "
165                << layoutGuiName << std::endl;
166 }
167
168 } // namespace frontend
169 } // namespace lyx
170
171
172 Toolbars::ToolbarPtr make_toolbar(ToolbarBackend::Toolbar const & tbb,
173                                   LyXView & owner)
174 {
175         using lyx::frontend::GToolbar;
176         return Toolbars::ToolbarPtr(new GToolbar(tbb, owner));
177 }
178
179 namespace lyx {
180 namespace frontend {
181
182 GToolbar::GToolbar(ToolbarBackend::Toolbar const & tbb, LyXView & owner)
183         : owner_(dynamic_cast<GView &>(owner))
184 {
185         ToolbarBackend::item_iterator it = tbb.items.begin();
186         ToolbarBackend::item_iterator end = tbb.items.end();
187         for (; it != end; ++it)
188                 add(it->first, it->second);
189
190         toolbar_.set_toolbar_style(Gtk::TOOLBAR_ICONS);
191
192         GView::Position const position = getPosition(tbb.flags);
193
194         if (position == GView::Left || position == GView::Right)
195                 toolbar_.set_orientation(Gtk::ORIENTATION_VERTICAL);
196
197         owner_.getBox(position).children().push_back(
198                 Gtk::Box_Helpers::Element(toolbar_, Gtk::PACK_SHRINK));
199 }
200
201
202 void GToolbar::add(FuncRequest const & func, string const & tooltip)
203 {
204         switch (func.action) {
205         case ToolbarBackend::SEPARATOR:
206                 toolbar_.tools().push_back(Gtk::Toolbar_Helpers::Space());
207                 break;
208         case ToolbarBackend::MINIBUFFER:
209                 // Not supported yet.
210                 break;
211         case ToolbarBackend::LAYOUTS:
212         {
213                 layout_.reset(new GLayoutBox(owner_, toolbar_, func));
214                 break;
215         }
216         default:
217                 Glib::ustring xpmName =
218                         Glib::locale_to_utf8(toolbarbackend.getIcon(func));
219                 Glib::ustring tip = Glib::locale_to_utf8(tooltip);
220                 if (xpmName.size() == 0) {
221                         toolbar_.tools().push_back(
222                                 Gtk::Toolbar_Helpers::ButtonElem(
223                                         "",
224                                         SigC::bind(SigC::slot(*this, &GToolbar::clicked),
225                                                    FuncRequest(func)),
226                                         tip));
227                 } else {
228                         Gtk::Image * image =
229                                 Gtk::manage(new Gtk::Image(xpmName));
230                         image->show();
231                         toolbar_.tools().push_back(
232                                 Gtk::Toolbar_Helpers::ButtonElem(
233                                         "",
234                                         *image,
235                                         SigC::bind(SigC::slot(*this, &GToolbar::clicked),
236                                                    FuncRequest(func)),
237                                         tip));
238                 }
239                 toolbar_.tools().back().get_content()->set_data(
240                         gToolData,
241                         reinterpret_cast<void*>(&const_cast<FuncRequest &>(func)));
242                 break;
243         }
244 }
245
246
247 void GToolbar::clicked(FuncRequest func)
248 {
249         owner_.getLyXFunc().dispatch(func, true);
250 }
251
252
253 void GToolbar::hide(bool)
254 {
255         toolbar_.hide();
256 }
257
258
259 void GToolbar::show(bool)
260 {
261         toolbar_.show();
262 }
263
264
265 void GToolbar::update()
266 {
267         Gtk::Toolbar_Helpers::ToolList::iterator it =
268                 toolbar_.tools().begin();
269         Gtk::Toolbar_Helpers::ToolList::iterator const end =
270                 toolbar_.tools().end();
271
272         for (; it != end; ++it) {
273                 Gtk::Widget * widget;
274                 switch (it->get_type()) {
275                 case Gtk::TOOLBAR_CHILD_WIDGET:
276                         widget = it->get_widget();
277                         break;
278                 case Gtk::TOOLBAR_CHILD_SPACE:
279                         continue;
280                 default:
281                         widget = it->get_content();
282                 }
283
284                 FuncRequest const & func = *reinterpret_cast<FuncRequest *>(
285                         widget->get_data(gToolData));
286
287                 if (func.action == int(ToolbarBackend::LAYOUTS))
288                         continue;
289
290                 FuncStatus const status = owner_.getLyXFunc().getStatus(func);
291                 bool sensitive = status.enabled();
292                 widget->set_sensitive(sensitive);
293                 if (it->get_type() != Gtk::TOOLBAR_CHILD_BUTTON)
294                         return;
295                 if (status.onoff(true))
296                         static_cast<Gtk::Button*>(widget)->
297                                 set_relief(Gtk::RELIEF_NORMAL);
298                 if (status.onoff(false))
299                         static_cast<Gtk::Button*>(widget)->
300                                 set_relief(Gtk::RELIEF_NONE);
301         }
302 }
303
304 } // namespace frontend
305 } // namespace lyx