#include "XFormsToolbar.h"
+#include "Color.h"
#include "Tooltips.h"
#include "xforms_helpers.h"
#include "gettext.h"
#include "lyxfunc.h"
+#include "support/lstrings.h"
+
#include "lyx_forms.h"
+#include "lyx_xpm.h"
#include "combox.h"
#include <boost/bind.hpp>
-using lyx::frontend::Box;
-using lyx::frontend::BoxList;
+#include <sstream>
+#include <vector>
+
+using boost::shared_ptr;
using std::distance;
using std::endl;
using std::string;
+using std::vector;
+
+namespace lyx {
+
+using support::compare_ascii_no_case;
+namespace frontend {
// some constants
const int standardspacing = 2; // the usual space between items
XFormsToolbar::toolbarItem::toolbarItem()
- : icon(0)
+ : icon(0),
+ unused_pixmap(0),
+ active_pixmap(0),
+ inactive_pixmap(0),
+ mask(0)
{}
XFormsToolbar::toolbarItem::~toolbarItem()
{
- // Lars said here that ~XFormsView() dealt with the icons.
- // This is not true. But enabling this causes crashes,
- // because somehow we kill the same icon twice :(
- // FIXME
- //kill_icon();
+ kill_icon();
}
void XFormsToolbar::toolbarItem::kill_icon()
{
- if (icon) {
- fl_delete_object(icon);
- fl_free_object(icon);
- icon = 0;
- }
+ if (unused_pixmap)
+ // XForms will take care of cleaning up the other pixmap
+ XFreePixmap(fl_get_display(), unused_pixmap);
+
+ unused_pixmap = 0;
+ active_pixmap = 0;
+ inactive_pixmap = 0;
+ mask = 0;
+ icon = 0;
}
}
+void XFormsToolbar::toolbarItem::generateInactivePixmaps()
+{
+ if (!icon || icon->objclass != FL_PIXMAPBUTTON)
+ return;
+
+ // Store the existing (active) pixmap.
+ fl_get_pixmap_pixmap(icon, &active_pixmap, &mask);
+
+ if (active_pixmap == 0 || mask == 0)
+ return;
+
+ // Ascertain the width and height of the pixmap.
+ Display * display = fl_get_display();
+ unsigned int width;
+ unsigned int height;
+ unsigned int uidummy;
+ int idummy;
+ Window win;
+
+ XGetGeometry(display, active_pixmap, &win, &idummy, &idummy,
+ &width, &height, &uidummy, &uidummy);
+
+ // Produce a darker shade of the button background as the
+ // inactive color. Note the 'hsv.v - 0.2'.
+ unsigned int r, g, b;
+ fl_getmcolor(FL_PIXMAPBUTTON_COL1, &r, &g, &b);
+ HSVColor hsv(RGBColor(r, g, b));
+ hsv.v = std::max(0.0, hsv.v - 0.2);
+ string const inactive_color = X11hexname(RGBColor(hsv));
+
+ // Generate an XPM dataset for a uniformly-colored pixmap with
+ // the same dimensions as active_pixmap.
+
+ // The data set has the form:
+ // "<width> <height> <ncolors> <chars per pixel>",
+ // "o c <inactive_color>",
+ // "oooooooooooooooo", // <width> 'o' chars.
+ // repeated <height> times.
+ std::ostringstream line1_ss;
+ line1_ss << width << ' ' << height << " 1 1";
+ string const line1 = line1_ss.str();
+ string const line2 = "o c " + inactive_color;
+ string const data(width, 'o');
+ vector<char *> inactive_data(height + 2,
+ const_cast<char *>(data.c_str()));
+ inactive_data[0] = const_cast<char *>(line1.c_str());
+ inactive_data[1] = const_cast<char *>(line2.c_str());
+
+ char ** raw_inactive_data = &*inactive_data.begin();
+
+ // Generate a pixmap of this data set.
+ // Together with 'mask' above, this is sufficient to display
+ // an inactive version of our active_pixmap.
+ Screen * screen = ScreenOfDisplay(display, fl_screen);
+
+ XpmCreatePixmapFromData(display, XRootWindowOfScreen(screen),
+ raw_inactive_data, &inactive_pixmap, 0, 0);
+}
+
+} // namespace frontend
+} // namespace lyx
+
Toolbars::ToolbarPtr make_toolbar(ToolbarBackend::Toolbar const & tbb,
LyXView & owner)
{
+ using lyx::frontend::XFormsToolbar;
return Toolbars::ToolbarPtr(new XFormsToolbar(tbb, owner));
}
+namespace lyx {
+namespace frontend {
+
XFormsToolbar::XFormsToolbar(ToolbarBackend::Toolbar const & tbb,
LyXView & o)
- : toolbar_(0),
- toolbar_buttons_(0),
+ : toolbar_buttons_(0),
owner_(static_cast<XFormsView &>(o)),
tooltip_(new Tooltips)
{
position_ = getPosition(tbb.flags);
- BoxList & boxlist = owner_.getBox(position_).children();
- toolbar_ = &boxlist.push_back(Box(0,0));
+ BoxList & boxlist = owner_.getBox(position_)->children();
+ toolbar_ = boxlist.push_back(Box(0,0));
// If the toolbar is horizontal, then it contains three
// vertically-aligned Boxes,the center one of which is to
toolbar_->children().push_back(Box(padding, padding));
- Box & toolbar_center = toolbar_->children().push_back(Box(0,0));
- toolbar_center.set(toolbar_orientation);
- toolbar_buttons_ = &toolbar_center.children();
+ shared_ptr<Box> toolbar_center = toolbar_->children().push_back(Box(0,0));
+ toolbar_center->set(toolbar_orientation);
+ toolbar_buttons_ = &toolbar_center->children();
toolbar_->children().push_back(Box(padding, padding));
- using lyx::frontend::WidgetMap;
owner_.metricsUpdated.connect(boost::bind(&WidgetMap::updateMetrics,
&widgets_));
ToolbarBackend::item_iterator end = tbb.items.end();
for (; it != end; ++it)
add(it->first, it->second);
-
}
XFormsToolbar * ptr = static_cast<XFormsToolbar *>(ob->u_vdata);
XFormsView & owner = ptr->owner_;
- owner.getLyXFunc().dispatch(ptr->funcs[ac], true);
+ owner.getLyXFunc().dispatch(ptr->funcs[ac]);
}
} // extern "C"
void XFormsToolbar::hide(bool update_metrics)
{
- toolbar_->set(Box::Invisible);
+ if (!toolbar_->visible())
+ return;
+
+ toolbar_->set(Box::Invisible);
if (update_metrics)
owner_.updateMetrics();
}
void XFormsToolbar::show(bool update_metrics)
{
- toolbar_->set(Box::Visible);
+ if (toolbar_->visible())
+ return;
+
+ toolbar_->set(Box::Visible);
toolbar_->show();
if (update_metrics)
owner_.updateMetrics();
gravity = NorthEastGravity;
else if (position_ == XFormsView::Bottom)
gravity = SouthWestGravity;
-
+
fl_set_object_gravity(obj, gravity, gravity);
Funcs::iterator fit = funcs.insert(funcs.end(), func);
void XFormsToolbar::update()
{
- ToolbarList::const_iterator p = toollist_.begin();
- ToolbarList::const_iterator end = toollist_.end();
+ ToolbarList::iterator p = toollist_.begin();
+ ToolbarList::iterator end = toollist_.end();
for (; p != end; ++p) {
if (!p->icon)
continue;
fl_set_object_color(p->icon, FL_MCOL, FL_BLUE);
fl_set_object_boxtype(p->icon, FL_UP_BOX);
}
+
+ // This must go here rather than in XFormsToolbar::add, else
+ // LyX aborts with a BadPixmap error.
+ if (!p->active_pixmap)
+ p->generateInactivePixmaps();
+
if (status.enabled()) {
fl_activate_object(p->icon);
+ fl_set_pixmap_pixmap(p->icon,
+ p->active_pixmap,
+ p->mask);
+ p->unused_pixmap = p->inactive_pixmap;
} else {
- // Is there a way here to specify a
- // mask in order to show that the
- // button is disabled? (JMarc)
fl_deactivate_object(p->icon);
+ fl_set_pixmap_pixmap(p->icon,
+ p->inactive_pixmap,
+ p->mask);
+ p->unused_pixmap = p->active_pixmap;
}
}
void XLayoutBox::setEnabled(bool enable)
{
- ::setEnabled(combox_, enable);
+ lyx::frontend::setEnabled(combox_, enable);
}
{
string const layoutguiname = getString(combox_);
- LyXTextClass const & tc = getTextClass(owner_);
-
- LyXTextClass::const_iterator it = tc.begin();
- LyXTextClass::const_iterator const end = tc.end();
- for (; it != end; ++it) {
- string const & name = (*it)->name();
- if (_(name) == layoutguiname) {
- owner_.getLyXFunc()
- .dispatch(FuncRequest(LFUN_LAYOUT, name),
- true);
- return;
- }
- }
- lyxerr << "ERROR (XLayoutBox::selected): layout not found!" << endl;
+ layoutSelected(owner_, layoutguiname);
}
+
+} // namespace frontend
+} // namespace lyx