]> git.lyx.org Git - lyx.git/blobdiff - src/frontends/xforms/XFormsToolbar.C
Change glob() API to accept a dir parameter.
[lyx.git] / src / frontends / xforms / XFormsToolbar.C
index 0bbaf0d7416b118a7d309440d033f34fcd7fef79..ccee31a916989d0a83ffd05f9378ebc8ebea209e 100644 (file)
@@ -15,6 +15,7 @@
 
 #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
@@ -70,27 +82,31 @@ LyXTextClass const & getTextClass(LyXView const & lv)
 
 
 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;
 }
 
 
@@ -110,24 +126,89 @@ XFormsToolbar::toolbarItem::operator=(toolbarItem const & ti)
 }
 
 
+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
@@ -155,13 +236,12 @@ XFormsToolbar::XFormsToolbar(ToolbarBackend::Toolbar const & tbb,
 
        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_));
 
@@ -170,7 +250,6 @@ XFormsToolbar::XFormsToolbar(ToolbarBackend::Toolbar const & tbb,
        ToolbarBackend::item_iterator end = tbb.items.end();
        for (; it != end; ++it)
                add(it->first, it->second);
-
 }
 
 
@@ -197,7 +276,7 @@ void C_ToolbarCB(FL_OBJECT * ob, long ac)
 
        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"
@@ -207,7 +286,10 @@ void C_ToolbarCB(FL_OBJECT * ob, long ac)
 
 void XFormsToolbar::hide(bool update_metrics)
 {
-       toolbar_->set(Box::Invisible);
+       if (!toolbar_->visible())
+               return;
+
+       toolbar_->set(Box::Invisible);
        if (update_metrics)
                owner_.updateMetrics();
 }
@@ -215,7 +297,10 @@ void XFormsToolbar::hide(bool update_metrics)
 
 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();
@@ -264,7 +349,7 @@ void XFormsToolbar::add(FuncRequest const & func, string const & tooltip)
                        gravity = NorthEastGravity;
                else if (position_ == XFormsView::Bottom)
                        gravity = SouthWestGravity;
-               
+
                fl_set_object_gravity(obj, gravity, gravity);
 
                Funcs::iterator fit = funcs.insert(funcs.end(), func);
@@ -290,8 +375,8 @@ void XFormsToolbar::add(FuncRequest const & func, string const & tooltip)
 
 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;
@@ -311,13 +396,24 @@ void XFormsToolbar::update()
                        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;
                }
        }
 
@@ -417,7 +513,7 @@ void XLayoutBox::open()
 
 void XLayoutBox::setEnabled(bool enable)
 {
-       ::setEnabled(combox_, enable);
+       lyx::frontend::setEnabled(combox_, enable);
 }
 
 
@@ -425,18 +521,8 @@ void XLayoutBox::selected()
 {
        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