]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/Toolbar_pimpl.C
Yet more dialog tweaking from Rob.
[lyx.git] / src / frontends / xforms / Toolbar_pimpl.C
1 /**
2  * \file Toolbar_pimpl.C
3  * Copyright 1995 Matthias Ettrich
4  * Copyright 1996-1998 Lars Gullik Bjønnes
5  * This file is part of LyX, the document processor.
6  * Licence details can be found in the file COPYING.
7  *
8  * \author Lars Gullik Bjønnes
9  *
10  * Full author contact details are available in file CREDITS
11  */
12
13 //  Added pseudo-action handling, asierra 180296
14
15 #include <config.h>
16
17 #ifdef __GNUG__
18 #pragma implementation
19 #endif
20
21 #include "Toolbar_pimpl.h"
22 #include "debug.h"
23 #include "XFormsView.h"
24 #include "lyxfunc.h"
25 #include "FuncStatus.h"
26 #include "buffer.h"
27 #include "funcrequest.h"
28 #include "gettext.h"
29 #include "Tooltips.h"
30 #include FORMS_H_LOCATION
31 #include "combox.h"
32 #include "ToolbarDefaults.h"
33 #include "LyXAction.h"
34
35 #include "support/LAssert.h"
36 #include "support/filetools.h"
37 #include "support/lstrings.h"
38
39 using std::endl;
40
41 // some constants
42 const int standardspacing = 2; // the usual space between items
43 const int sepspace = 6; // extra space
44 const int buttonwidth = 30; // the standard button width
45 const int height = 30; // the height of all items in the toolbar
46
47 Toolbar::Pimpl::toolbarItem::toolbarItem()
48         : action(LFUN_NOACTION), icon(0)
49 {}
50
51
52 Toolbar::Pimpl::toolbarItem::~toolbarItem()
53 {
54         // Lars said here that ~XFormsView() dealt with the icons.
55         // This is not true. But enabling this causes crashes,
56         // because somehow we kill the same icon twice :(
57         // FIXME
58         //kill_icon();
59 }
60
61
62 void Toolbar::Pimpl::toolbarItem::kill_icon()
63 {
64         if (icon) {
65                 fl_delete_object(icon);
66                 fl_free_object(icon);
67                 icon = 0;
68         }
69 }
70
71
72 Toolbar::Pimpl::toolbarItem &
73 Toolbar::Pimpl::toolbarItem::operator=(toolbarItem const & ti)
74 {
75         if (this == &ti)
76                 return *this;
77
78         // If we already have an icon, release it.
79         // But we don't copy the icon from ti
80         kill_icon();
81  
82         action = ti.action;
83
84         return *this;
85 }
86
87
88
89 Toolbar::Pimpl::Pimpl(LyXView * o, int x, int y)
90         : owner_(static_cast<XFormsView *>(o)), xpos(x), ypos(y)
91 {
92         combox_ = 0;
93         tooltip_ = new Tooltips();
94 }
95
96
97 Toolbar::Pimpl::~Pimpl()
98 {
99         fl_freeze_form(owner_->getForm());
100
101         // G++ vector does not have clear defined
102         //toollist.clear();
103         toollist_.erase(toollist_.begin(), toollist_.end());
104
105         delete combox_;
106
107         fl_unfreeze_form(owner_->getForm());
108         delete tooltip_;
109 }
110
111
112 void Toolbar::Pimpl::update()
113 {
114         ToolbarList::const_iterator p = toollist_.begin();
115         ToolbarList::const_iterator end = toollist_.end();
116         for (; p != end; ++p) {
117                 if (p->action == ToolbarDefaults::LAYOUTS && combox_) {
118                         if (owner_->getLyXFunc().getStatus(LFUN_LAYOUT).disabled())
119                                 combox_->deactivate();
120                         else
121                                 combox_->activate();
122                         continue;
123                 }
124
125                 if (!p->icon)
126                         continue;
127  
128                 FuncStatus const status = owner_->getLyXFunc().getStatus(p->action);
129                 if (status.onoff(true)) {
130                         // I'd like to use a different color
131                         // here, but then the problem is to
132                         // know how to use transparency with
133                         // Xpm library. It seems pretty
134                         // complicated to me (JMarc)
135                         fl_set_object_color(p->icon, FL_LEFT_BCOL, FL_BLUE);
136                         fl_set_object_boxtype(p->icon, FL_DOWN_BOX);
137                 } else {
138                         fl_set_object_color(p->icon, FL_MCOL, FL_BLUE);
139                         fl_set_object_boxtype(p->icon, FL_UP_BOX);
140                 }
141                 if (status.disabled()) {
142                         // Is there a way here to specify a
143                         // mask in order to show that the
144                         // button is disabled? (JMarc)
145                         fl_deactivate_object(p->icon);
146                 }
147                 else
148                         fl_activate_object(p->icon);
149         }
150 }
151
152
153 // this one is not "C" because combox callbacks are really C++ %-|
154 void Toolbar::Pimpl::layoutSelectedCB(int, void * arg, Combox *)
155 {
156         reinterpret_cast<Toolbar::Pimpl *>(arg)->layoutSelected();
157 }
158
159
160 void Toolbar::Pimpl::layoutSelected()
161 {
162         string const & layoutguiname = combox_->getline();
163         LyXTextClass const & tc =
164                 owner_->buffer()->params.getLyXTextClass();
165
166         LyXTextClass::const_iterator end = tc.end();
167         for (LyXTextClass::const_iterator cit = tc.begin();
168              cit != end; ++cit) {
169                 if (_((*cit)->name()) == layoutguiname) {
170                         owner_->getLyXFunc().dispatch(FuncRequest(LFUN_LAYOUT, (*cit)->name()));
171                         return;
172                 }
173         }
174         lyxerr << "ERROR (Toolbar::Pimpl::layoutSelected): layout not found!"
175                << endl;
176 }
177
178
179 void Toolbar::Pimpl::setLayout(string const & layout)
180 {
181         if (combox_) {
182                 LyXTextClass const & tc =
183                         owner_->buffer()->params.getLyXTextClass();
184                 combox_->select(_(tc[layout]->name()));
185         }
186 }
187
188
189 void Toolbar::Pimpl::updateLayoutList(bool force)
190 {
191         // Update the layout display
192         if (!combox_) return;
193
194         // If textclass is different, we need to update the list
195         if (combox_->empty() || force) {
196                 combox_->clear();
197                 LyXTextClass const & tc =
198                         owner_->buffer()->params.getLyXTextClass();
199                 LyXTextClass::const_iterator end = tc.end();
200                 for (LyXTextClass::const_iterator cit = tc.begin();
201                      cit != end; ++cit) {
202                         // ignore obsolete entries
203                         if ((*cit)->obsoleted_by().empty())
204                                 combox_->addline(_((*cit)->name()));
205                 }
206         }
207         // we need to do this.
208         combox_->redraw();
209 }
210
211
212 void Toolbar::Pimpl::clearLayoutList()
213 {
214         if (combox_) {
215                 combox_->clear();
216                 combox_->redraw();
217         }
218 }
219
220
221 void Toolbar::Pimpl::openLayoutList()
222 {
223         if (combox_)
224                 combox_->show();
225 }
226
227
228 namespace {
229
230 void ToolbarCB(FL_OBJECT * ob, long ac)
231 {
232         XFormsView * owner = static_cast<XFormsView *>(ob->u_vdata);
233
234         owner->getLyXFunc().dispatch(int(ac), true);
235 }
236
237
238 extern "C" {
239
240         static
241         void C_Toolbar_ToolbarCB(FL_OBJECT * ob, long data)
242         {
243                 ToolbarCB(ob, data);
244         }
245
246 }
247
248
249 void setPixmap(FL_OBJECT * obj, int action)
250 {
251         string xpm_name;
252         FuncRequest ev = lyxaction.retrieveActionArg(action);
253  
254         string const name = lyxaction.getActionName(ev.action);
255         if (!ev.argument.empty())
256                 xpm_name = subst(name + ' ' + ev.argument, ' ','_');
257         else
258                 xpm_name = name;
259
260         string fullname = LibFileSearch("images", xpm_name, "xpm");
261
262         if (ev.action == LFUN_INSERT_MATH && !ev.argument.empty()) {
263                 string arg = ev.argument.substr(1);
264                 fullname = LibFileSearch("images/math/", arg, "xpm");
265         }
266  
267         if (!fullname.empty()) {
268                 lyxerr[Debug::GUI] << "Full icon name is `"
269                                    << fullname << "'" << endl;
270                 fl_set_pixmapbutton_file(obj, fullname.c_str());
271                 return;
272         }
273
274         lyxerr << "Unable to find icon `" << xpm_name << "'" << endl;
275         fullname = LibFileSearch("images", "unknown", "xpm");
276         if (!fullname.empty()) {
277                 lyxerr[Debug::GUI] << "Using default `unknown' icon"
278                                    << endl;
279                 fl_set_pixmapbutton_file(obj, fullname.c_str());
280         }
281 }
282
283 } // namespace anon
284
285
286 void Toolbar::Pimpl::add(int action)
287 {
288         FL_OBJECT * obj;
289
290         toolbarItem item;
291         item.action = action;
292  
293         switch (action) {
294         case ToolbarDefaults::SEPARATOR:
295                 xpos += sepspace;
296                 break;
297         case ToolbarDefaults::NEWLINE:
298                 // Not supported yet.
299                 break;
300         case ToolbarDefaults::LAYOUTS:
301                 xpos += standardspacing;
302                 if (!combox_)
303                         combox_ = new Combox(FL_COMBOX_DROPLIST);
304                 combox_->add(xpos, ypos, 135, height, 400);
305                 combox_->setcallback(layoutSelectedCB, this);
306                 combox_->resize(FL_RESIZE_ALL);
307                 combox_->gravity(NorthWestGravity, NorthWestGravity);
308                 xpos += 135;
309                 break;
310         default:
311                 xpos += standardspacing;
312                 item.icon = obj =
313                         fl_add_pixmapbutton(FL_NORMAL_BUTTON,
314                                             xpos, ypos,
315                                             buttonwidth,
316                                             height, "");
317                 fl_set_object_resize(obj, FL_RESIZE_ALL);
318                 fl_set_object_gravity(obj,
319                                       NorthWestGravity,
320                                       NorthWestGravity);
321                 fl_set_object_callback(obj, C_Toolbar_ToolbarCB,
322                                        static_cast<long>(action));
323                 // Remove the blue feedback rectangle
324                 fl_set_pixmapbutton_focus_outline(obj, 0);
325
326                 // initialise the tooltip
327                 string const tip = _(lyxaction.helpText(obj->argument));
328                 tooltip_->init(obj, tip);
329
330                 // The view that this object belongs to.
331                 obj->u_vdata = owner_;
332
333                 setPixmap(obj, action);
334                 // we must remember to update the positions
335                 xpos += buttonwidth;
336                 // ypos is constant
337                 /* Here will come a check to see if the new
338                  * pos is within the bounds of the main frame,
339                  * and perhaps wrap the toolbar if not.
340                  */
341                 break;
342         }
343  
344         toollist_.push_back(item);
345 }