]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/Toolbar_pimpl.C
remove LFUN_TOOLBAR_PUSH
[lyx.git] / src / frontends / xforms / Toolbar_pimpl.C
1 /**
2  * \file Toolbar_pimpl.C
3  * Copyright 1995 Matthias Ettrich
4  * Copyright 1995-2001 The LyX Team.
5  * Copyright 1996-1998 Lars Gullik Bjønnes
6  * See the file COPYING.
7  *
8  * \author Lars Gullik Bjønnes, larsbj@lyx.org
9  */
10
11 //  Added pseudo-action handling, asierra 180296
12
13 #include <config.h>
14
15 #ifdef __GNUG__
16 #pragma implementation
17 #endif
18
19 #include "Toolbar_pimpl.h"
20 #include "debug.h"
21 #include "XFormsView.h"
22 #include "lyxfunc.h"
23 #include "FuncStatus.h"
24 #include "BufferView.h"
25 #include "buffer.h"
26 #include "LyXAction.h"
27 #include "MathsSymbols.h"
28 #include "gettext.h"
29 #include "Tooltips.h"
30 #include FORMS_H_LOCATION
31 #include "combox.h"
32 #include "ToolbarDefaults.h"
33
34 #include "support/LAssert.h"
35 #include "support/filetools.h"
36 #include "support/lstrings.h"
37
38 using std::endl;
39
40 extern LyXAction lyxaction;
41
42 // some constants
43 const int standardspacing = 2; // the usual space between items
44 const int sepspace = 6; // extra space
45 const int buttonwidth = 30; // the standard button width
46 const int height = 30; // the height of all items in the toolbar
47
48 Toolbar::Pimpl::toolbarItem::toolbarItem()
49 {
50         action = LFUN_NOACTION;
51         icon = 0;
52 }
53
54
55 Toolbar::Pimpl::toolbarItem::~toolbarItem()
56 {
57         // It seems that now this is taken care of
58         // in the XFormsView destructor. (Lgb)
59         // clean();
60 }
61
62
63 void Toolbar::Pimpl::toolbarItem::clean()
64 {
65         if (icon) {
66                 fl_delete_object(icon);
67                 fl_free_object(icon);
68                 icon = 0;
69         }
70 }
71
72
73 Toolbar::Pimpl::toolbarItem &
74 Toolbar::Pimpl::toolbarItem::operator=(toolbarItem const & ti)
75 {
76         // Are we assigning the object onto itself?
77         if (this == &ti)
78                 return *this;
79
80         // If we already have an icon, release it.
81         clean();
82
83         // do we have to check icon too?
84         action = ti.action;
85         icon = 0; // locally we need to get the icon anew
86
87         return *this;
88 }
89
90
91
92 Toolbar::Pimpl::Pimpl(LyXView * o, Dialogs & d, int x, int y)
93         : owner(static_cast<XFormsView *>(o)), sxpos(x), sypos(y)
94 {
95         combox = 0;
96         tooltip_ = new Tooltips(d);
97 }
98
99
100 Toolbar::Pimpl::~Pimpl()
101 {
102         clean();
103         delete tooltip_;
104 }
105
106
107 void Toolbar::Pimpl::update()
108 {
109         ToolbarList::const_iterator p = toollist.begin();
110         ToolbarList::const_iterator end = toollist.end();
111         for (; p != end; ++p) {
112                 if (p->icon) {
113                         FuncStatus status = owner->getLyXFunc()->getStatus(p->action);
114                         if (status.onoff(true)) {
115                                 // I'd like to use a different color
116                                 // here, but then the problem is to
117                                 // know how to use transparency with
118                                 // Xpm library. It seems pretty
119                                 // complicated to me (JMarc)
120                                 fl_set_object_color(p->icon, FL_LEFT_BCOL, FL_BLUE);
121                                 fl_set_object_boxtype(p->icon, FL_DOWN_BOX);
122                         } else {
123                                 fl_set_object_color(p->icon, FL_MCOL, FL_BLUE);
124                                 fl_set_object_boxtype(p->icon, FL_UP_BOX);
125                         }
126                         if (status.disabled()) {
127                                 // Is there a way here to specify a
128                                 // mask in order to show that the
129                                 // button is disabled? (JMarc)
130                                 fl_deactivate_object(p->icon);
131                         }
132                         else
133                                 fl_activate_object(p->icon);
134                 } else if (p->action == ToolbarDefaults::LAYOUTS && combox) {
135                         if (owner->getLyXFunc()->getStatus(LFUN_LAYOUT).disabled())
136                                 combox->deactivate();
137                         else
138                                 combox->activate();
139                 }
140         }
141 }
142
143
144 // this one is not "C" because combox callbacks are really C++ %-|
145 void Toolbar::Pimpl::layoutSelectedCB(int, void * arg, Combox *)
146 {
147         Toolbar::Pimpl * tb = reinterpret_cast<Toolbar::Pimpl *>(arg);
148
149         tb->layoutSelected();
150 }
151
152
153 void Toolbar::Pimpl::layoutSelected()
154 {
155         string const & layoutguiname = combox->getline();
156         LyXTextClass const & tc =
157                 owner->buffer()->params.getLyXTextClass();
158
159         LyXTextClass::const_iterator end = tc.end();
160         for (LyXTextClass::const_iterator cit = tc.begin();
161              cit != end; ++cit) {
162                 if (_((*cit)->name()) == layoutguiname) {
163                         owner->getLyXFunc()->dispatch(LFUN_LAYOUT, (*cit)->name());
164                         return;
165                 }
166         }
167         lyxerr << "ERROR (Toolbar::Pimpl::layoutSelected): layout not found!"
168                << endl;
169 }
170
171
172 void Toolbar::Pimpl::setLayout(string const & layout)
173 {
174         if (combox) {
175                 LyXTextClass const & tc =
176                         owner->buffer()->params.getLyXTextClass();
177                 combox->select(_(tc[layout]->name()));
178         }
179 }
180
181
182 void Toolbar::Pimpl::updateLayoutList(bool force)
183 {
184         // Update the layout display
185         if (!combox) return;
186
187         // If textclass is different, we need to update the list
188         if (combox->empty() || force) {
189                 combox->clear();
190                 LyXTextClass const & tc =
191                         owner->buffer()->params.getLyXTextClass();
192                 LyXTextClass::const_iterator end = tc.end();
193                 for (LyXTextClass::const_iterator cit = tc.begin();
194                      cit != end; ++cit) {
195                         // ignore obsolete entries
196                         if ((*cit)->obsoleted_by().empty())
197                                 combox->addline(_((*cit)->name()));
198                 }
199         }
200         // we need to do this.
201         combox->redraw();
202 }
203
204
205 void Toolbar::Pimpl::clearLayoutList()
206 {
207         if (combox) {
208                 combox->clear();
209                 combox->redraw();
210         }
211 }
212
213
214 void Toolbar::Pimpl::openLayoutList()
215 {
216         if (combox)
217                 combox->show();
218 }
219
220
221 namespace {
222
223 void ToolbarCB(FL_OBJECT * ob, long ac)
224 {
225         XFormsView * owner = static_cast<XFormsView *>(ob->u_vdata);
226
227         owner->getLyXFunc()->dispatch(int(ac), true);
228 }
229
230
231 extern "C" {
232
233         static
234         void C_Toolbar_ToolbarCB(FL_OBJECT * ob, long data)
235         {
236                 ToolbarCB(ob, data);
237         }
238
239 }
240
241
242 void setPixmap(FL_OBJECT * obj, int action, int buttonwidth, int height)
243 {
244         string arg;
245         string xpm_name;
246
247         const kb_action act = lyxaction.retrieveActionArg(action, arg);
248         string const name = lyxaction.getActionName(act);
249         if (!arg.empty())
250                 xpm_name = subst(name + ' ' + arg, ' ','_');
251         else
252                 xpm_name = name;
253
254         string fullname = LibFileSearch("images", xpm_name, "xpm");
255
256         if (!fullname.empty()) {
257                 lyxerr[Debug::GUI] << "Full icon name is `"
258                                    << fullname << "'" << endl;
259                 fl_set_pixmapbutton_file(obj, fullname.c_str());
260                 return;
261         }
262
263         if (act == LFUN_INSERT_MATH && !arg.empty()) {
264                 char const ** pixmap = get_pixmap_from_symbol(arg.c_str(),
265                                                               buttonwidth,
266                                                               height);
267                 if (pixmap) {
268                         lyxerr[Debug::GUI] << "Using mathed-provided icon"
269                                            << endl;
270                         fl_set_pixmapbutton_data(obj,
271                                                  const_cast<char **>(pixmap));
272                         return;
273                 }
274         }
275
276         lyxerr << "Unable to find icon `" << xpm_name << "'" << endl;
277         fullname = LibFileSearch("images", "unknown", "xpm");
278         if (!fullname.empty()) {
279                 lyxerr[Debug::GUI] << "Using default `unknown' icon"
280                                    << endl;
281                 fl_set_pixmapbutton_file(obj, fullname.c_str());
282         }
283 }
284
285 } // namespace anon
286
287
288 void Toolbar::Pimpl::set(bool doingmain)
289 {
290         // we shouldn't set if we have not cleaned
291         if (!cleaned) return;
292
293         FL_OBJECT * obj;
294
295         if (!doingmain) {
296                 fl_freeze_form(owner->getForm());
297                 fl_addto_form(owner->getForm());
298         }
299
300         ToolbarList::iterator item = toollist.begin();
301         ToolbarList::iterator end = toollist.end();
302         for (; item != end; ++item) {
303                 switch (item->action) {
304                 case ToolbarDefaults::SEPARATOR:
305                         xpos += sepspace;
306                         break;
307                 case ToolbarDefaults::NEWLINE:
308                         // Not supported yet.
309                         break;
310                 case ToolbarDefaults::LAYOUTS:
311                         xpos += standardspacing;
312                         if (!combox)
313                                 combox = new Combox(FL_COMBOX_DROPLIST);
314                         combox->add(xpos, ypos, 135, height, 400);
315                         combox->setcallback(layoutSelectedCB, this);
316                         combox->resize(FL_RESIZE_ALL);
317                         combox->gravity(NorthWestGravity, NorthWestGravity);
318                         xpos += 135;
319                         break;
320                 default:
321                         xpos += standardspacing;
322                         item->icon = obj =
323                                 fl_add_pixmapbutton(FL_NORMAL_BUTTON,
324                                                     xpos, ypos,
325                                                     buttonwidth,
326                                                     height, "");
327                         fl_set_object_resize(obj, FL_RESIZE_ALL);
328                         fl_set_object_gravity(obj,
329                                               NorthWestGravity,
330                                               NorthWestGravity);
331                         fl_set_object_callback(obj, C_Toolbar_ToolbarCB,
332                                                static_cast<long>(item->action));
333                         // Remove the blue feedback rectangle
334                         fl_set_pixmapbutton_focus_outline(obj, 0);
335
336                         // initialise the tooltip
337                         string const tip = _(lyxaction.helpText(obj->argument));
338                         tooltip_->init(obj, tip);
339
340                         // The view that this object belongs to.
341                         obj->u_vdata = owner;
342
343                         setPixmap(obj, item->action, buttonwidth, height);
344                         // we must remember to update the positions
345                         xpos += buttonwidth;
346                         // ypos is constant
347                         /* Here will come a check to see if the new
348                          * pos is within the bounds of the main frame,
349                          * and perhaps wrap the toolbar if not.
350                          */
351                         break;
352                 }
353         }
354
355         if (!doingmain) {
356                 fl_end_form();
357                 fl_unfreeze_form(owner->getForm());
358                 // Should be safe to do this here.
359                 owner->updateLayoutChoice();
360         }
361
362         // set the state of the icons
363         //update();
364
365         cleaned = false;
366 }
367
368
369 void Toolbar::Pimpl::add(int action, bool doclean)
370 {
371         if (doclean && !cleaned) clean();
372
373         // this is what we do if we want to add to an existing
374         // toolbar.
375         if (!doclean && owner) {
376                 // first "hide" the toolbar buttons. This is not a real hide
377                 // actually it deletes and frees the button altogether.
378                 lyxerr << "Toolbar::add: \"hide\" the toolbar buttons."
379                        << endl;
380
381                 lightReset();
382
383                 fl_freeze_form(owner->getForm());
384
385                 ToolbarList::iterator p = toollist.begin();
386                 ToolbarList::iterator end = toollist.end();
387                 for (; p != end; ++p) {
388                         p->clean();
389                 }
390
391                 if (combox) {
392                         delete combox;
393                         combox = 0;
394                 }
395                 fl_unfreeze_form(owner->getForm());
396                 cleaned = true; // this is not completely true, but OK anyway
397         }
398
399         // there exist some special actions not part of
400         // kb_action: SEPARATOR, LAYOUTS
401
402         toolbarItem newItem;
403         newItem.action = action;
404         toollist.push_back(newItem);
405 }
406
407
408 void Toolbar::Pimpl::clean()
409 {
410         //reset(); // I do not understand what this reset() is, anyway
411
412         //now delete all the objects..
413         if (owner)
414                 fl_freeze_form(owner->getForm());
415
416         // G++ vector does not have clear defined
417         //toollist.clear();
418         toollist.erase(toollist.begin(), toollist.end());
419
420         lyxerr[Debug::GUI] << "Combox: " << combox << endl;
421         if (combox) {
422                 delete combox;
423                 combox = 0;
424         }
425
426         if (owner)
427                 fl_unfreeze_form(owner->getForm());
428         lyxerr[Debug::GUI] << "toolbar cleaned" << endl;
429         cleaned = true;
430 }
431
432
433 void Toolbar::Pimpl::reset()
434 {
435         //toollist = 0; // what is this supposed to do?
436         cleaned = false;
437         lightReset();
438 }
439
440
441 void Toolbar::Pimpl::lightReset() {
442         xpos = sxpos - standardspacing;
443         ypos = sypos;
444 }