lyx_mirror/src/frontends/gtk/GMenubar.C
John Spray 107d32b49f Revert patch from bug 1954, to fix bug 2421
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@13498 a592a061-630c-0410-9148-cb99ea01b6c8
2006-03-26 10:18:52 +00:00

269 lines
6.9 KiB
C

/**
* \file GMenubar.C
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Huang Ying
* \author John Spray
*
* Full author contact details are available in file CREDITS.
*/
#include <config.h>
// Too hard to make concept checks work with this file
#ifdef _GLIBCXX_CONCEPT_CHECKS
#undef _GLIBCXX_CONCEPT_CHECKS
#endif
#ifdef _GLIBCPP_CONCEPT_CHECKS
#undef _GLIBCPP_CONCEPT_CHECKS
#endif
#include "GMenubar.h"
#include "GView.h"
#include "ghelpers.h"
#include "ToolbarBackend.h" // for getIcon
#include "debug.h"
#include "support/lstrings.h"
#include "lyxfunc.h"
using std::string;
namespace lyx {
using support::subst;
namespace frontend {
namespace
{
class LyxMenu : public Gtk::Menu {
public:
LyxMenu() { menu_.reset(new ::Menu); }
::Menu& getBackMenu() { return *menu_.get(); }
void clearBackMenu() { menu_.reset(new ::Menu); }
private:
std::auto_ptr< ::Menu > menu_;
};
// ENCODING: assume that the backend will give us a locale string
Glib::ustring labelTrans(string const & label_src, string const & shortcut)
{
string label = subst(label_src, "_", "__");
string::size_type i = label.find(shortcut);
if (i == string::npos)
return Glib::locale_to_utf8 (label);
label.insert(i, "_");
return Glib::locale_to_utf8 (label);
}
void ClearMenu(Gtk::MenuShell * menu)
{
Gtk::Menu_Helpers::MenuList::iterator m = menu->items().begin();
Gtk::Menu_Helpers::MenuList::iterator end = menu->items().end();
Gtk::Menu * subMenu;
for (; m != end; ++m) {
if ((subMenu = m->get_submenu()) != 0) {
ClearMenu(subMenu);
delete subMenu;
}
}
menu->items().clear();
}
}
GMenubar::GMenubar(LyXView * lyxView, MenuBackend const & /*menuBackend*/) :
view_(lyxView)
{
GView * gview = static_cast<GView*>(lyxView);
Menu const & menu = menubackend.getMenubar();
Menu::const_iterator i = menu.begin();
Menu::const_iterator end = menu.end();
for (; i != end; ++i) {
if (i->kind() != MenuItem::Submenu) {
lyxerr << "ERROR: GMenubar::createMenubar:"
" only submenus can appear in a menubar"
<< std::endl;
continue;
}
Gtk::Menu * gmenu = new LyxMenu;
menubar_.items().push_back(
Gtk::Menu_Helpers::MenuElem(
labelTrans(i->label(), i->shortcut()),
*gmenu));
menubar_.items().back().signal_activate().connect(
sigc::bind(sigc::mem_fun(*this, &GMenubar::onSubMenuActivate), &(*i),
&menubar_.items().back()));
mainMenuNames_.push_back(i->submenuname());
}
menubar_.show();
gview->getBox(GView::Top).children().push_back(
Gtk::Box_Helpers::Element(menubar_, Gtk::PACK_SHRINK));
}
GMenubar::~GMenubar()
{
ClearMenu(&menubar_);
}
void GMenubar::update()
{
}
void GMenubar::openByName(string const & name)
{
Glib::ustring uname = Glib::convert(name, "UTF-8", "ISO-8859-1");
std::vector<Glib::ustring>::iterator it =
std::find(mainMenuNames_.begin(), mainMenuNames_.end(),
uname);
if (it != mainMenuNames_.end()) {
Gtk::MenuItem& mitem = menubar_.items()[it - mainMenuNames_.begin()];
mitem.select();
mitem.activate();
return;
}
lyxerr << "GMenubar::openByName: menu "
<< name << " not found" << std::endl;
}
void GMenubar::onSubMenuActivate(MenuItem const * item,
Gtk::MenuItem * gitem)
{
Gtk::Menu * gmenu = gitem->get_submenu();
ClearMenu(gmenu);
LyxMenu * lyxmenu = static_cast<LyxMenu*>(gmenu);
lyxmenu->clearBackMenu();
Menu * fmenu;
Menu::const_iterator i;
Menu::const_iterator end;
if(!item->submenuname().empty()) {
fmenu = &menubackend.getMenu(item->submenuname());
menubackend.expand(*fmenu, lyxmenu->getBackMenu(), view_);
i = lyxmenu->getBackMenu().begin();
end = lyxmenu->getBackMenu().end();
} else {
fmenu = item->submenu();
i = fmenu->begin();
end = fmenu->end();
}
// Choose size for icons on command items
int iconwidth = 16;
int iconheight = 16;
Gtk::IconSize::lookup(Gtk::ICON_SIZE_MENU, iconwidth, iconheight);
Gtk::Menu * gmenu_new;
for (; i != end; ++i) {
switch (i->kind()) {
case MenuItem::Submenu:
gmenu_new = new LyxMenu;
gmenu->items().push_back(
Gtk::Menu_Helpers::MenuElem(
labelTrans(i->label(), i->shortcut()),
*gmenu_new));
gmenu->items().back().signal_activate().connect(
sigc::bind(sigc::mem_fun(*this, &GMenubar::onSubMenuActivate),
&(*i),
&gmenu->items().back()));
if (!i->status().enabled())
gmenu->items().back().set_sensitive(false);
break;
case MenuItem::Command:
{
FuncStatus const flag = i->status();
bool on = flag.onoff(true);
bool off = flag.onoff(false);
if (on || off) {
gmenu->items().push_back(
Gtk::Menu_Helpers::CheckMenuElem(
labelTrans(i->label(),
i->shortcut())));
Gtk::CheckMenuItem& checkitem =
static_cast<Gtk::CheckMenuItem&>(
gmenu->items().back());
checkitem.set_active(on);
} else {
// Choose an icon from the funcrequest
Gtk::Image * image = getGTKIcon(i->func(), Gtk::ICON_SIZE_MENU);
if (!image) {
// ENCODING, FIXME: does Pixbuf::create_from_file really
// want UTF-8, or does it want filename encoding? Is
// the backend string really in locale encoding?
// This shouldn't break as long as filenames are ASCII
Glib::ustring xpmName =
Glib::locale_to_utf8(toolbarbackend.getIcon(i->func()));
if (xpmName.find("unknown.xpm") == Glib::ustring::npos) {
// Load icon and shrink it for menu size
Glib::RefPtr<Gdk::Pixbuf> bigicon =
Gdk::Pixbuf::create_from_file(xpmName);
Glib::RefPtr<Gdk::Pixbuf> smallicon =
bigicon->scale_simple(iconwidth,iconheight,Gdk::INTERP_TILES);
image = Gtk::manage(new Gtk::Image(smallicon));
}
}
Gtk::ImageMenuItem * imgitem = Gtk::manage(new Gtk::ImageMenuItem);
if (image)
imgitem->set_image(*image);
// This hbox is necessary because add_accel_label is protected,
// and even if you subclass Gtk::MenuItem then add_accel_label
// doesn't do what you'd expect.
Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox);
Gtk::Label * label1 = Gtk::manage(new Gtk::Label(
labelTrans(i->label(), i->shortcut()), true));
Gtk::Label * label2 = Gtk::manage(new Gtk::Label(
" " + i->binding(), false));
hbox->pack_start(*label1, false, false, 0);
hbox->pack_end(*label2, false, false, 0);
imgitem->add(*hbox);
gmenu->append(*imgitem);
imgitem->show_all();
}
Gtk::MenuItem & newitem = gmenu->items().back();
newitem.signal_activate().connect(
sigc::bind(sigc::mem_fun(*this, &GMenubar::onCommandActivate),
&(*i), &newitem));
if (!flag.enabled())
newitem.set_sensitive(false);
break;
}
case MenuItem::Separator:
gmenu->items().push_back(
Gtk::Menu_Helpers::SeparatorElem());
break;
default:
lyxerr << "GMenubar::create_submenu: "
"this should not happen" << std::endl;
break;
}
}
}
void GMenubar::onCommandActivate(MenuItem const * item,
Gtk::MenuItem * /*gitem*/)
{
view_->getLyXFunc().dispatch(item->func());
}
} // namespace frontend
} // namespace lyx