]> git.lyx.org Git - features.git/blob - src/frontends/xforms/XFormsToolbar.C
69f8e07eb382809b5579577886d270579de2e1a3
[features.git] / src / frontends / xforms / XFormsToolbar.C
1 /**
2  * \file XFormsToolbar.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Lars Gullik Bjønnes
7  * \author Jean-Marc Lasgouttes
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 //  Added pseudo-action handling, asierra 180296
13
14 #include <config.h>
15
16 #include "XFormsToolbar.h"
17
18 #include "Tooltips.h"
19 #include "xforms_helpers.h"
20 #include "XFormsView.h"
21
22 #include "buffer.h"
23 #include "bufferparams.h"
24 #include "debug.h"
25 #include "funcrequest.h"
26 #include "FuncStatus.h"
27 #include "gettext.h"
28 #include "lyxfunc.h"
29
30 #include "lyx_forms.h"
31 #include "combox.h"
32
33 #include <boost/bind.hpp>
34
35 using lyx::frontend::Box;
36 using lyx::frontend::BoxList;
37
38 using std::distance;
39 using std::endl;
40 using std::string;
41
42
43 // some constants
44 const int standardspacing = 2; // the usual space between items
45 const int sepspace = 6; // extra space
46 const int buttonwidth = 30; // the standard button width
47 const int height = 30; // the height of all items in the toolbar
48
49 XFormsToolbar::toolbarItem::toolbarItem()
50         : icon(0)
51 {}
52
53
54 XFormsToolbar::toolbarItem::~toolbarItem()
55 {
56         // Lars said here that ~XFormsView() dealt with the icons.
57         // This is not true. But enabling this causes crashes,
58         // because somehow we kill the same icon twice :(
59         // FIXME
60         //kill_icon();
61 }
62
63
64 /// Display toolbar, not implemented. But moved out of line so that
65 /// linking will work properly.
66 void XFormsToolbar::displayToolbar(ToolbarBackend::Toolbar const & /*tb*/,
67                                     bool /*show*/)
68 {}
69
70
71 void XFormsToolbar::toolbarItem::kill_icon()
72 {
73         if (icon) {
74                 fl_delete_object(icon);
75                 fl_free_object(icon);
76                 icon = 0;
77         }
78 }
79
80
81 XFormsToolbar::toolbarItem &
82 XFormsToolbar::toolbarItem::operator=(toolbarItem const & ti)
83 {
84         if (this == &ti)
85                 return *this;
86
87         // If we already have an icon, release it.
88         // But we don't copy the icon from ti
89         kill_icon();
90
91         func = ti.func;
92
93         return *this;
94 }
95
96
97
98 XFormsToolbar::XFormsToolbar(LyXView * o)
99         : toolbar_(0),
100           toolbar_buttons_(0),
101           owner_(static_cast<XFormsView *>(o)),
102           combox_(0)
103 {
104         tooltip_ = new Tooltips;
105
106         using lyx::frontend::WidgetMap;
107         owner_->metricsUpdated.connect(boost::bind(&WidgetMap::updateMetrics,
108                                                    &widgets_));
109 }
110
111
112 XFormsToolbar::~XFormsToolbar()
113 {
114         fl_freeze_form(owner_->getForm());
115
116         // G++ vector does not have clear defined
117         //toollist.clear();
118         toollist_.erase(toollist_.begin(), toollist_.end());
119
120         fl_unfreeze_form(owner_->getForm());
121         delete tooltip_;
122 }
123
124
125 void XFormsToolbar::update()
126 {
127         ToolbarList::const_iterator p = toollist_.begin();
128         ToolbarList::const_iterator end = toollist_.end();
129         for (; p != end; ++p) {
130                 if (p->func.action == int(ToolbarBackend::LAYOUTS) && combox_) {
131                         LyXFunc const & lf = owner_->getLyXFunc();
132                         bool const enable =
133                                 lf.getStatus(FuncRequest(LFUN_LAYOUT)).enabled();
134                         setEnabled(combox_, enable);
135                         continue;
136                 }
137
138                 if (!p->icon)
139                         continue;
140
141                 FuncStatus const status = owner_->getLyXFunc().getStatus(p->func);
142                 if (status.onoff(true)) {
143                         // I'd like to use a different color
144                         // here, but then the problem is to
145                         // know how to use transparency with
146                         // Xpm library. It seems pretty
147                         // complicated to me (JMarc)
148                         fl_set_object_color(p->icon, FL_LEFT_BCOL, FL_BLUE);
149                         fl_set_object_boxtype(p->icon, FL_DOWN_BOX);
150                 } else {
151                         fl_set_object_color(p->icon, FL_MCOL, FL_BLUE);
152                         fl_set_object_boxtype(p->icon, FL_UP_BOX);
153                 }
154                 if (status.enabled()) {
155                         fl_activate_object(p->icon);
156                 } else {
157                         // Is there a way here to specify a
158                         // mask in order to show that the
159                         // button is disabled? (JMarc)
160                         fl_deactivate_object(p->icon);
161                 }
162         }
163 }
164
165
166 namespace {
167
168 void C_layoutSelectedCB(FL_OBJECT * ob, long)
169 {
170         if (!ob || !ob->u_vdata)
171                 return;
172         XFormsToolbar * ptr = static_cast<XFormsToolbar *>(ob->u_vdata);
173         ptr->layoutSelected();
174 }
175
176 } // namespace anon
177
178
179 void XFormsToolbar::layoutSelected()
180 {
181         if (!combox_)
182                 return;
183
184         string const & layoutguiname = getString(combox_);
185         LyXTextClass const & tc =
186                 owner_->buffer()->params().getLyXTextClass();
187
188         LyXTextClass::const_iterator end = tc.end();
189         for (LyXTextClass::const_iterator cit = tc.begin();
190              cit != end; ++cit) {
191                 if (_((*cit)->name()) == layoutguiname) {
192                         owner_->getLyXFunc().dispatch(FuncRequest(LFUN_LAYOUT, (*cit)->name()), true);
193                         return;
194                 }
195         }
196         lyxerr << "ERROR (XFormsToolbar::layoutSelected): layout not found!"
197                << endl;
198 }
199
200
201 void XFormsToolbar::setLayout(string const & layout)
202 {
203         if (!combox_)
204                 return;
205
206         LyXTextClass const & tc = owner_->buffer()->params().getLyXTextClass();
207         string const layoutname = _(tc[layout]->name());
208
209         int const nnames = fl_get_combox_maxitems(combox_);
210         for (int i = 1; i <= nnames; ++i) {
211                 string const name = fl_get_combox_line(combox_, i);
212                 if (name == layoutname) {
213                         fl_set_combox(combox_, i);
214                         break;
215                 }
216         }
217 }
218
219
220 void XFormsToolbar::updateLayoutList()
221 {
222         if (!combox_)
223                 return;
224
225         fl_clear_combox(combox_);
226         LyXTextClass const & tc = owner_->buffer()->params().getLyXTextClass();
227         LyXTextClass::const_iterator end = tc.end();
228         for (LyXTextClass::const_iterator cit = tc.begin();
229              cit != end; ++cit) {
230                 // ignore obsolete entries
231                 if ((*cit)->obsoleted_by().empty()) {
232                         string const & name = _((*cit)->name());
233                         fl_addto_combox(combox_, name.c_str());
234                 }
235         }
236
237         // we need to do this.
238         fl_redraw_object(combox_);
239 }
240
241
242 void XFormsToolbar::clearLayoutList()
243 {
244         if (!combox_)
245                 return;
246
247         Toolbar::clearLayoutList();
248         fl_clear_combox(combox_);
249         fl_redraw_object(combox_);
250 }
251
252
253 void XFormsToolbar::openLayoutList()
254 {
255         if (!combox_)
256                 return;
257
258         fl_show_combox_browser(combox_);
259 }
260
261
262 namespace {
263
264 void ToolbarCB(FL_OBJECT * ob, long ac)
265 {
266         if (!ob || !ob->u_vdata)
267                 return;
268
269         XFormsToolbar * ptr = static_cast<XFormsToolbar *>(ob->u_vdata);
270         XFormsView * owner = ptr->owner_;
271         owner->getLyXFunc().dispatch(ptr->funcs[ac], true);
272 }
273
274
275 extern "C" {
276
277 void C_Toolbar_ToolbarCB(FL_OBJECT * ob, long data)
278 {
279         ToolbarCB(ob, data);
280 }
281
282 }
283
284 } // namespace anon
285
286
287 void XFormsToolbar::add(ToolbarBackend::Toolbar const & tb)
288 {
289         // we can only handle one toolbar
290         if (!toollist_.empty())
291                 return;
292
293         // The toolbar contains three vertically-aligned Boxes,
294         // the center one of which is to contain the buttons,
295         // aligned horizontally.
296         // The other two provide some visual padding.
297         BoxList & boxlist = owner_->getBox(XFormsView::Top).children();
298         toolbar_ = &boxlist.push_back(Box(0,0));
299
300         int const padding = 2 + abs(fl_get_border_width());
301         toolbar_->children().push_back(Box(0, padding));
302
303         Box & toolbar_center = toolbar_->children().push_back(Box(0,0));
304         toolbar_center.set(Box::Horizontal);
305         toolbar_buttons_ = &toolbar_center.children();
306
307         toolbar_->children().push_back(Box(0, padding));
308
309         // Add the buttons themselves.
310         funcs.clear();
311
312         ToolbarBackend::item_iterator it = tb.items.begin();
313         ToolbarBackend::item_iterator end = tb.items.end();
314         for (; it != end; ++it)
315                 add(it->first, it->second);
316 }
317
318
319 void XFormsToolbar::add(FuncRequest const & func, string const & tooltip)
320 {
321         toolbarItem item;
322         item.func = func;
323
324         switch (func.action) {
325         case ToolbarBackend::SEPARATOR:
326                 toolbar_buttons_->push_back(Box(sepspace, 0));
327                 break;
328         case ToolbarBackend::MINIBUFFER:
329                 // Not implemented
330                 break;
331         case ToolbarBackend::LAYOUTS:
332                 toolbar_buttons_->push_back(Box(standardspacing, 0));
333                 if (combox_)
334                         break;
335
336                 combox_ = fl_add_combox(FL_DROPLIST_COMBOX,
337                                         0, 0, 135, height, "");
338
339                 widgets_.add(combox_, *toolbar_buttons_, 135, height);
340
341                 fl_set_combox_browser_height(combox_, 400);
342                 fl_set_object_boxtype(combox_, FL_DOWN_BOX);
343                 fl_set_object_color(combox_, FL_MCOL, FL_MCOL);
344                 fl_set_object_gravity(combox_, FL_NorthWest, FL_NorthWest);
345                 fl_set_object_resize(combox_, FL_RESIZE_ALL);
346
347                 combox_->u_vdata = this;
348                 fl_set_object_callback(combox_, C_layoutSelectedCB, 0);
349                 break;
350         default: {
351                 FL_OBJECT * obj;
352
353                 toolbar_buttons_->push_back(Box(standardspacing, 0));
354                 item.icon = obj =
355                         fl_add_pixmapbutton(FL_NORMAL_BUTTON,
356                                             0, 0, 0, 0, "");
357
358                 widgets_.add(obj, *toolbar_buttons_, buttonwidth, height);
359
360                 fl_set_object_resize(obj, FL_RESIZE_ALL);
361                 fl_set_object_gravity(obj,
362                                       NorthWestGravity,
363                                       NorthWestGravity);
364
365                 Funcs::iterator fit = funcs.insert(funcs.end(), func);
366                 int const index = distance(funcs.begin(), fit);
367                 fl_set_object_callback(obj, C_Toolbar_ToolbarCB, index);
368                 // Remove the blue feedback rectangle
369                 fl_set_pixmapbutton_focus_outline(obj, 0);
370
371                 tooltip_->init(obj, tooltip);
372
373                 // The view that this object belongs to.
374                 obj->u_vdata = this;
375
376                 string const xpm = toolbarbackend.getIcon(func);
377                 fl_set_pixmapbutton_file(obj, xpm.c_str());
378                 break;
379         }
380         }
381
382         toollist_.push_back(item);
383 }