2 * \file XFormsToolbar.C
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Lars Gullik Bjønnes
7 * \author Jean-Marc Lasgouttes
9 * Full author contact details are available in file CREDITS.
12 // Added pseudo-action handling, asierra 180296
16 #include "XFormsToolbar.h"
19 #include "xforms_helpers.h"
22 #include "bufferparams.h"
24 #include "funcrequest.h"
25 #include "FuncStatus.h"
29 #include "lyx_forms.h"
32 #include <boost/bind.hpp>
34 using lyx::frontend::Box;
35 using lyx::frontend::BoxList;
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
50 XFormsView::Position getPosition(ToolbarBackend::Flags const & flags)
52 if (flags & ToolbarBackend::TOP)
53 return XFormsView::Top;
54 if (flags & ToolbarBackend::BOTTOM)
55 return XFormsView::Bottom;
56 if (flags & ToolbarBackend::LEFT)
57 return XFormsView::Left;
58 if (flags & ToolbarBackend::RIGHT)
59 return XFormsView::Right;
60 return XFormsView::Top;
64 LyXTextClass const & getTextClass(LyXView const & lv)
66 return lv.buffer()->params().getLyXTextClass();
72 XFormsToolbar::toolbarItem::toolbarItem()
77 XFormsToolbar::toolbarItem::~toolbarItem()
79 // Lars said here that ~XFormsView() dealt with the icons.
80 // This is not true. But enabling this causes crashes,
81 // because somehow we kill the same icon twice :(
87 void XFormsToolbar::toolbarItem::kill_icon()
90 fl_delete_object(icon);
97 XFormsToolbar::toolbarItem &
98 XFormsToolbar::toolbarItem::operator=(toolbarItem const & ti)
103 // If we already have an icon, release it.
104 // But we don't copy the icon from ti
114 Toolbars::ToolbarPtr make_toolbar(ToolbarBackend::Toolbar const & tbb,
117 return Toolbars::ToolbarPtr(new XFormsToolbar(tbb, owner));
121 XFormsToolbar::XFormsToolbar(ToolbarBackend::Toolbar const & tbb,
125 owner_(static_cast<XFormsView &>(o)),
126 tooltip_(new Tooltips)
128 position_ = getPosition(tbb.flags);
129 BoxList & boxlist = owner_.getBox(position_).children();
130 toolbar_ = &boxlist.push_back(Box(0,0));
132 // If the toolbar is horizontal, then it contains three
133 // vertically-aligned Boxes,the center one of which is to
134 // contain the buttons, aligned horizontally.
135 // The other two provide some visual padding.
137 // If it is vertical, then this is swapped around.
139 Box::Orientation const toolbar_orientation =
140 (position_ == XFormsView::Left ||
141 position_ == XFormsView::Right)
142 ? Box::Vertical : Box::Horizontal;
144 Box::Orientation const padding_orientation =
145 (toolbar_orientation == Box::Vertical)
146 ? Box::Horizontal : Box::Vertical;
148 toolbar_->set(padding_orientation);
150 // A bit of a hack, but prevents 'M-x' causing the addition of
153 (tbb.name == "minibuffer") ?
154 0 : 2 + abs(fl_get_border_width());
156 toolbar_->children().push_back(Box(padding, padding));
158 Box & toolbar_center = toolbar_->children().push_back(Box(0,0));
159 toolbar_center.set(toolbar_orientation);
160 toolbar_buttons_ = &toolbar_center.children();
162 toolbar_->children().push_back(Box(padding, padding));
164 using lyx::frontend::WidgetMap;
165 owner_.metricsUpdated.connect(boost::bind(&WidgetMap::updateMetrics,
168 // Populate the toolbar.
169 ToolbarBackend::item_iterator it = tbb.items.begin();
170 ToolbarBackend::item_iterator end = tbb.items.end();
171 for (; it != end; ++it)
172 add(it->first, it->second);
177 XFormsToolbar::~XFormsToolbar()
179 fl_freeze_form(owner_.getForm());
181 // G++ vector does not have clear defined
183 toollist_.erase(toollist_.begin(), toollist_.end());
185 fl_unfreeze_form(owner_.getForm());
193 void C_ToolbarCB(FL_OBJECT * ob, long ac)
195 if (!ob || !ob->u_vdata)
198 XFormsToolbar * ptr = static_cast<XFormsToolbar *>(ob->u_vdata);
199 XFormsView & owner = ptr->owner_;
200 owner.getLyXFunc().dispatch(ptr->funcs[ac], true);
208 void XFormsToolbar::hide(bool update_metrics)
210 toolbar_->set(Box::Invisible);
212 owner_.updateMetrics();
216 void XFormsToolbar::show(bool update_metrics)
218 toolbar_->set(Box::Visible);
221 owner_.updateMetrics();
225 void XFormsToolbar::add(FuncRequest const & func, string const & tooltip)
230 switch (func.action) {
231 case ToolbarBackend::SEPARATOR:
232 toolbar_buttons_->push_back(Box(sepspace, sepspace));
235 case ToolbarBackend::MINIBUFFER:
237 // XForms uses the same widget to display the buffer messages
238 // and to input commands.
241 case ToolbarBackend::LAYOUTS:
242 layout_.reset(new XLayoutBox(owner_, *this));
248 toolbar_buttons_->push_back(Box(standardspacing,
252 fl_add_pixmapbutton(FL_NORMAL_BUTTON,
255 widgets_.add(obj, *toolbar_buttons_, buttonwidth, height);
257 fl_set_object_resize(obj, FL_RESIZE_ALL);
260 if (position_ == XFormsView::Top ||
261 position_ == XFormsView::Left)
262 gravity = NorthWestGravity;
263 else if (position_ == XFormsView::Right)
264 gravity = NorthEastGravity;
265 else if (position_ == XFormsView::Bottom)
266 gravity = SouthWestGravity;
268 fl_set_object_gravity(obj, gravity, gravity);
270 Funcs::iterator fit = funcs.insert(funcs.end(), func);
271 int const index = distance(funcs.begin(), fit);
272 fl_set_object_callback(obj, C_ToolbarCB, index);
273 // Remove the blue feedback rectangle
274 fl_set_pixmapbutton_focus_outline(obj, 0);
276 tooltip_->init(obj, tooltip);
278 // The view that this object belongs to.
281 string const xpm = toolbarbackend.getIcon(func);
282 fl_set_pixmapbutton_file(obj, xpm.c_str());
287 toollist_.push_back(item);
291 void XFormsToolbar::update()
293 ToolbarList::const_iterator p = toollist_.begin();
294 ToolbarList::const_iterator end = toollist_.end();
295 for (; p != end; ++p) {
299 FuncStatus const status =
300 owner_.getLyXFunc().getStatus(p->func);
302 if (status.onoff(true)) {
303 // I'd like to use a different color
304 // here, but then the problem is to
305 // know how to use transparency with
306 // Xpm library. It seems pretty
307 // complicated to me (JMarc)
308 fl_set_object_color(p->icon, FL_LEFT_BCOL, FL_BLUE);
309 fl_set_object_boxtype(p->icon, FL_DOWN_BOX);
311 fl_set_object_color(p->icon, FL_MCOL, FL_BLUE);
312 fl_set_object_boxtype(p->icon, FL_UP_BOX);
314 if (status.enabled()) {
315 fl_activate_object(p->icon);
317 // Is there a way here to specify a
318 // mask in order to show that the
319 // button is disabled? (JMarc)
320 fl_deactivate_object(p->icon);
324 bool const enable = owner_.getLyXFunc().
325 getStatus(FuncRequest(LFUN_LAYOUT)).enabled();
328 layout_->setEnabled(enable);
335 void C_LayoutBoxSelectedCB(FL_OBJECT * ob, long)
337 if (!ob || !ob->u_vdata)
339 XLayoutBox * ptr = static_cast<XLayoutBox *>(ob->u_vdata);
346 XLayoutBox::XLayoutBox(LyXView & owner, XFormsToolbar & toolbar)
349 toolbar.toolbar_buttons_->push_back(Box(standardspacing, 0));
351 combox_ = fl_add_combox(FL_DROPLIST_COMBOX,
352 0, 0, 135, height, "");
354 toolbar.widgets_.add(combox_, *toolbar.toolbar_buttons_, 135, height);
356 fl_set_combox_browser_height(combox_, 400);
357 fl_set_object_boxtype(combox_, FL_DOWN_BOX);
358 fl_set_object_color(combox_, FL_MCOL, FL_MCOL);
359 fl_set_object_gravity(combox_, FL_NorthWest, FL_NorthWest);
360 fl_set_object_resize(combox_, FL_RESIZE_ALL);
362 combox_->u_vdata = this;
363 fl_set_object_callback(combox_, C_LayoutBoxSelectedCB, 0);
367 void XLayoutBox::set(string const & layout)
369 LyXTextClass const & tc = getTextClass(owner_);
371 string const layoutname = _(tc[layout]->name());
373 int const nnames = fl_get_combox_maxitems(combox_);
374 for (int i = 1; i <= nnames; ++i) {
375 string const name = fl_get_combox_line(combox_, i);
376 if (name == layoutname) {
377 fl_set_combox(combox_, i);
384 void XLayoutBox::update()
386 LyXTextClass const & tc = getTextClass(owner_);
388 fl_clear_combox(combox_);
390 LyXTextClass::const_iterator it = tc.begin();
391 LyXTextClass::const_iterator const end = tc.end();
392 for (; it != end; ++it) {
393 // ignore obsolete entries
394 if ((*it)->obsoleted_by().empty()) {
395 string const & name = _((*it)->name());
396 fl_addto_combox(combox_, name.c_str());
400 // we need to do this.
401 fl_redraw_object(combox_);
405 void XLayoutBox::clear()
407 fl_clear_combox(combox_);
408 fl_redraw_object(combox_);
412 void XLayoutBox::open()
414 fl_show_combox_browser(combox_);
418 void XLayoutBox::setEnabled(bool enable)
420 ::setEnabled(combox_, enable);
424 void XLayoutBox::selected()
426 string const layoutguiname = getString(combox_);
428 LyXTextClass const & tc = getTextClass(owner_);
430 LyXTextClass::const_iterator it = tc.begin();
431 LyXTextClass::const_iterator const end = tc.end();
432 for (; it != end; ++it) {
433 string const & name = (*it)->name();
434 if (_(name) == layoutguiname) {
436 .dispatch(FuncRequest(LFUN_LAYOUT, name),
441 lyxerr << "ERROR (XLayoutBox::selected): layout not found!" << endl;