1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright 1995 Matthias Ettrich
7 * Copyright 1995-2000 The LyX Team.
9 * This file is Copyright 1996-1998
12 * ====================================================== */
14 // Added pseudo-action handling, asierra 180296
19 #pragma implementation
22 #include "Toolbar_pimpl.h"
26 #include "BufferView.h"
28 #include "LyXAction.h"
29 #include "support/filetools.h"
34 // this one is not "C" because combox callbacks are really C++ %-|
35 extern void LayoutsCB(int, void *);
36 extern char const ** get_pixmap_from_symbol(char const * arg, int, int);
37 extern LyXAction lyxaction;
40 const int standardspacing = 2; // the usual space between items
41 const int sepspace = 6; // extra space
42 const int buttonwidth = 30; // the standard button width
43 const int height = 30; // the height of all items in the toolbar
45 Toolbar::Pimpl::toolbarItem::toolbarItem() {
46 action = LFUN_NOACTION;
51 Toolbar::Pimpl::toolbarItem::~toolbarItem() {
56 void Toolbar::Pimpl::toolbarItem::clean() {
58 fl_delete_object(icon);
65 Toolbar::Pimpl::toolbarItem &
66 Toolbar::Pimpl::toolbarItem::operator=(const toolbarItem & ti) {
67 // do we have to check icon too?
69 icon = 0; // locally we need to get the icon anew
76 Toolbar::Pimpl::Pimpl(LyXView * o, int x, int y)
77 : owner(o), sxpos(x), sypos(y)
87 // timer-cb for bubble-help (Matthias)
89 void BubbleTimerCB(FL_OBJECT *, long data)
91 FL_OBJECT * ob = reinterpret_cast<FL_OBJECT*>(data);
92 // The trick we use to get the help text is to read the
93 // argument of the callback that has been registered for
95 string help = lyxaction.helpText(ob->argument);
96 fl_show_oneliner(help.c_str(), ob->form->x + ob->x,
97 ob->form->y + ob->y + ob->h);
101 extern "C" void C_Toolbar_BubbleTimerCB(FL_OBJECT * ob, long data)
103 BubbleTimerCB(ob, data);
107 // post_handler for bubble-help (Matthias)
109 int BubblePost(FL_OBJECT *ob, int event,
110 FL_Coord /*mx*/, FL_Coord /*my*/,
111 int /*key*/, void */*xev*/)
113 FL_OBJECT * bubble_timer = reinterpret_cast<FL_OBJECT *>(ob->u_cdata);
115 // We do not test for empty help here, since this can never happen
116 if(event == FL_ENTER){
117 fl_set_object_callback(bubble_timer,
118 C_Toolbar_BubbleTimerCB,
119 reinterpret_cast<long>(ob));
120 fl_set_timer(bubble_timer, 1);
122 else if(event != FL_MOTION){
123 fl_set_timer(bubble_timer, 0);
130 extern "C" int C_Toolbar_BubblePost(FL_OBJECT * ob, int event,
131 FL_Coord /*mx*/, FL_Coord /*my*/,
134 return BubblePost(ob, event, 0, 0, key, xev);
139 void Toolbar::Pimpl::activate()
141 ToolbarList::const_iterator p = toollist.begin();
142 for (; p != toollist.end(); ++p) {
144 fl_activate_object(p->icon);
150 void Toolbar::Pimpl::deactivate()
152 ToolbarList::const_iterator p = toollist.begin();
153 for (; p != toollist.end(); ++p) {
155 fl_deactivate_object(p->icon);
160 void Toolbar::Pimpl::update()
162 ToolbarList::const_iterator p = toollist.begin();
163 for (; p != toollist.end(); ++p) {
165 int status = owner->getLyXFunc()->getStatus(p->action);
166 if (status & LyXFunc::ToggleOn) {
167 // I'd like to use a different color
168 // here, but then the problem is to
169 // know how to use transparency with
170 // Xpm library. It seems pretty
171 // complicated to me (JMarc)
172 fl_set_object_color(p->icon, FL_LEFT_BCOL, FL_BLUE);
173 fl_set_object_boxtype(p->icon, FL_DOWN_BOX);
175 fl_set_object_color(p->icon, FL_MCOL, FL_BLUE);
176 fl_set_object_boxtype(p->icon, FL_UP_BOX);
179 if (status & LyXFunc::Disabled) {
180 // Is there a way here to specify a
181 // mask in order to show that the
182 // button is disabled? (JMarc)
183 fl_deactivate_object(p->icon);
186 fl_activate_object(p->icon);
192 void Toolbar::Pimpl::setLayout(int layout) {
194 combox->select(layout+1);
198 void Toolbar::Pimpl::updateLayoutList(bool force)
200 // Update the layout display
203 // If textclass is different, we need to update the list
204 if (combox->empty() || force) {
206 LyXTextClass const & tc =
207 textclasslist.TextClass(owner->buffer()->
209 for (LyXTextClass::const_iterator cit = tc.begin();
210 cit != tc.end(); ++cit) {
211 if ((*cit).obsoleted_by().empty())
212 combox->addline(_((*cit).name().c_str()));
214 combox->addline(("@N" + string(_((*cit).name().c_str()))).c_str());
217 // we need to do this.
221 void Toolbar::Pimpl::clearLayoutList()
229 void Toolbar::Pimpl::openLayoutList()
236 void ToolbarCB(FL_OBJECT * ob, long ac)
238 LyXView * owner = static_cast<LyXView *>(ob->u_vdata);
240 string res = owner->getLyXFunc()->Dispatch(int(ac));
242 lyxerr[Debug::GUI] << "ToolbarCB: Function returned: "
247 extern "C" void C_Toolbar_ToolbarCB(FL_OBJECT * ob, long data)
253 // What are we supposed to do with that??
254 int Toolbar::get_toolbar_func(string const & func)
256 int action = lyxaction.LookupFunc(func.c_str());
258 if (func == "separator"){
259 action = TOOL_SEPARATOR;
260 } else if (func == "layouts"){
261 action = TOOL_LAYOUTS;
270 void setPixmap(FL_OBJECT * obj, int action, int buttonwidth, int height) {
271 string name, arg, xpm_name;
274 if (lyxaction.isPseudoAction(action)) {
275 act = lyxaction.retrieveActionArg(action, arg);
276 name = lyxaction.getActionName(act);
277 xpm_name = subst(name + ' ' + arg, ' ','_');
279 act = (kb_action)action;
280 name = lyxaction.getActionName(action);
284 string fullname = LibFileSearch("images", xpm_name, "xpm");
286 if (!fullname.empty()) {
287 lyxerr[Debug::GUI] << "Full icon name is `"
288 << fullname << "'" << endl;
289 fl_set_pixmapbutton_file(obj, fullname.c_str());
293 if (act == LFUN_INSERT_MATH && !arg.empty()) {
294 lyxerr[Debug::GUI] << "Using mathed-provided icon" << endl;
295 char const ** pixmap = get_pixmap_from_symbol(arg.c_str(),
298 fl_set_pixmapbutton_data(obj, const_cast<char **>(pixmap));
302 lyxerr << "Unable to find icon `" << xpm_name << "'" << endl;
303 fullname = LibFileSearch("images", "unknown", "xpm");
304 if (!fullname.empty()) {
305 lyxerr[Debug::GUI] << "Using default `unknown' icon"
307 fl_set_pixmapbutton_file(obj, fullname.c_str());
311 void Toolbar::Pimpl::set(bool doingmain)
313 // we shouldn't set if we have not cleaned
314 if (!cleaned) return;
319 fl_freeze_form(owner->getForm());
320 fl_addto_form(owner->getForm());
324 // add the time if it don't exist
325 if (bubble_timer == 0)
326 bubble_timer = fl_add_timer(FL_HIDDEN_TIMER,
327 xpos, ypos, 0, 0, "Timer");
330 ToolbarList::iterator item = toollist.begin();
331 for (; item != toollist.end(); ++item) {
332 switch(item->action){
333 case ToolbarDefaults::SEPARATOR:
336 case ToolbarDefaults::NEWLINE:
337 // Not supported yet.
339 case ToolbarDefaults::LAYOUTS:
340 xpos += standardspacing;
342 combox = new Combox(FL_COMBOX_DROPLIST);
343 combox->add(xpos, ypos, 135, height, 400);
344 combox->setcallback(LayoutsCB);
345 combox->resize(FL_RESIZE_ALL);
346 combox->gravity(NorthWestGravity, NorthWestGravity);
350 xpos += standardspacing;
352 fl_add_pixmapbutton(FL_NORMAL_BUTTON,
356 fl_set_object_resize(obj, FL_RESIZE_ALL);
357 fl_set_object_gravity(obj,
360 fl_set_object_callback(obj, C_Toolbar_ToolbarCB,
361 static_cast<long>(item->action));
362 // Remove the blue feedback rectangle
363 fl_set_pixmapbutton_focus_outline(obj, 0);
366 #if FL_REVISION >= 89
367 string help = lyxaction.helpText(item->action);
368 fl_set_object_helper(obj, help.c_str());
370 fl_set_object_posthandler(obj, C_Toolbar_BubblePost);
371 obj->u_cdata = reinterpret_cast<char *>(bubble_timer);
374 // The view that this object belongs to.
375 obj->u_vdata = owner;
377 setPixmap(obj, item->action, buttonwidth, height);
378 // we must remember to update the positions
381 /* Here will come a check to see if the new
382 * pos is within the bounds of the main frame,
383 * and perhaps wrap the toolbar if not.
391 fl_unfreeze_form(owner->getForm());
392 // Should be safe to do this here.
393 owner->updateLayoutChoice();
396 // set the state of the icons
403 void Toolbar::Pimpl::add(int action, bool doclean)
405 if (doclean && !cleaned) clean();
407 // this is what we do if we want to add to an existing
409 if (!doclean && owner) {
410 // first "hide" the toolbar buttons. This is not a real hide
411 // actually it deletes and frees the button altogether.
412 lyxerr << "Toolbar::add: \"hide\" the toolbar buttons."
417 fl_freeze_form(owner->getForm());
419 ToolbarList::iterator p = toollist.begin();
420 for (; p != toollist.end(); ++p) {
428 fl_unfreeze_form(owner->getForm());
429 cleaned = true; // this is not completely true, but OK anyway
432 // there exist some special actions not part of
433 // kb_action: SEPARATOR, LAYOUTS
436 newItem.action = action;
437 toollist.push_back(newItem);
441 void Toolbar::Pimpl::clean()
443 //reset(); // I do not understand what this reset() is, anyway
445 //now delete all the objects..
447 fl_freeze_form(owner->getForm());
449 // G++ vector does not have clear defined
451 toollist.erase(toollist.begin(), toollist.end());
453 lyxerr[Debug::GUI] << "Combox: " << combox << endl;
460 fl_unfreeze_form(owner->getForm());
461 lyxerr[Debug::GUI] << "toolbar cleaned" << endl;
466 void Toolbar::Pimpl::push(int nth)
468 lyxerr[Debug::GUI] << "Toolbar::push: trying to trigger no `"
469 << nth << '\'' << endl;
471 if (nth <= 0 || nth >= int(toollist.size())) {
472 // item nth not found...
476 fl_trigger_object(toollist[nth - 1].icon);
480 void Toolbar::Pimpl::reset()
482 //toollist = 0; // what is this supposed to do?
487 void Toolbar::Pimpl::lightReset() {
488 xpos = sxpos - standardspacing;