mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-09-22 16:04:07 +00:00
107d32b49f
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@13498 a592a061-630c-0410-9148-cb99ea01b6c8
269 lines
6.9 KiB
C
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
|