3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
9 * Full author contact details are available in file CREDITS.
14 // Too hard to make concept checks work with this file
15 #ifdef _GLIBCXX_CONCEPT_CHECKS
16 #undef _GLIBCXX_CONCEPT_CHECKS
18 #ifdef _GLIBCPP_CONCEPT_CHECKS
19 #undef _GLIBCPP_CONCEPT_CHECKS
26 #include "ToolbarBackend.h" // for getIcon
39 class LyxMenu : public Gtk::Menu {
41 LyxMenu() { menu_.reset(new ::Menu); }
43 ::Menu& getBackMenu() { return *menu_.get(); }
45 void clearBackMenu() { menu_.reset(new ::Menu); }
47 std::auto_ptr< ::Menu > menu_;
51 Glib::ustring labelTrans(string const & label, string const & shortcut)
53 string labelN = label;
54 string::size_type i = label.find(shortcut);
55 if (i == string::npos)
56 return Glib::locale_to_utf8(label);
57 labelN.insert(i, "_");
58 return Glib::locale_to_utf8(labelN);
62 void ClearMenu(Gtk::MenuShell * menu)
64 Gtk::Menu_Helpers::MenuList::iterator m = menu->items().begin();
65 Gtk::Menu_Helpers::MenuList::iterator end = menu->items().end();
67 for (; m != end; ++m) {
68 if ((subMenu = m->get_submenu()) != 0) {
73 menu->items().clear();
80 GMenubar::GMenubar(LyXView * lyxView, MenuBackend const & /*menuBackend*/) :
83 GView * gview = static_cast<GView*>(lyxView);
84 Menu const & menu = menubackend.getMenubar();
85 Menu::const_iterator i = menu.begin();
86 Menu::const_iterator end = menu.end();
87 for (; i != end; ++i) {
88 if (i->kind() != MenuItem::Submenu) {
89 lyxerr << "ERROR: GMenubar::createMenubar:"
90 " only submenus can appear in a menubar"
94 Gtk::Menu * gmenu = new LyxMenu;
95 menubar_.items().push_back(
96 Gtk::Menu_Helpers::MenuElem(
97 labelTrans(i->label(), i->shortcut()),
99 menubar_.items().back().signal_activate().connect(
100 sigc::bind(sigc::mem_fun(*this, &GMenubar::onSubMenuActivate), &(*i),
101 &menubar_.items().back()));
102 mainMenuNames_.push_back(i->submenuname());
105 gview->getBox(GView::Top).children().push_back(
106 Gtk::Box_Helpers::Element(menubar_, Gtk::PACK_SHRINK));
110 GMenubar::~GMenubar()
112 ClearMenu(&menubar_);
116 void GMenubar::update()
121 void GMenubar::openByName(string const & name)
123 Glib::ustring uname = Glib::locale_to_utf8(name);
124 std::vector<Glib::ustring>::iterator it =
125 std::find(mainMenuNames_.begin(), mainMenuNames_.end(),
127 if (it != mainMenuNames_.end()) {
128 Gtk::MenuItem& mitem = menubar_.items()[it - mainMenuNames_.begin()];
133 lyxerr << "GMenubar::openByName: menu "
134 << name << " not found" << std::endl;
138 void GMenubar::onSubMenuActivate(MenuItem const * item,
139 Gtk::MenuItem * gitem)
141 Gtk::Menu * gmenu = gitem->get_submenu();
143 LyxMenu * lyxmenu = static_cast<LyxMenu*>(gmenu);
144 lyxmenu->clearBackMenu();
145 Menu * fmenu = item->submenuname().empty() ?
147 &menubackend.getMenu(item->submenuname());
149 // Choose size for icons on command items
152 Gtk::IconSize::lookup(Gtk::ICON_SIZE_MENU, iconwidth, iconheight);
154 menubackend.expand(*fmenu, lyxmenu->getBackMenu(), view_);
155 Menu::const_iterator i = lyxmenu->getBackMenu().begin();
156 Menu::const_iterator end = lyxmenu->getBackMenu().end();
157 Gtk::Menu * gmenu_new;
158 for (; i != end; ++i) {
160 case MenuItem::Submenu:
161 gmenu_new = new LyxMenu;
162 gmenu->items().push_back(
163 Gtk::Menu_Helpers::MenuElem(
164 labelTrans(i->label(), i->shortcut()),
166 gmenu->items().back().signal_activate().connect(
167 sigc::bind(sigc::mem_fun(*this, &GMenubar::onSubMenuActivate),
169 &gmenu->items().back()));
170 if (!i->status().enabled())
171 gmenu->items().back().set_sensitive(false);
173 case MenuItem::Command:
175 FuncStatus const flag = i->status();
176 bool on = flag.onoff(true);
177 bool off = flag.onoff(false);
180 gmenu->items().push_back(
181 Gtk::Menu_Helpers::CheckMenuElem(
182 labelTrans(i->label(),
184 Gtk::CheckMenuItem& citem =
185 static_cast<Gtk::CheckMenuItem&>(
186 gmenu->items().back());
187 citem.set_active(on);
189 // Choose an icon from the funcrequest
190 Gtk::BuiltinStockID stockID = getGTKStockIcon(i->func());
191 Gtk::Image * image = NULL;
192 // Prefer stock graphics
193 if (stockID != Gtk::Stock::MISSING_IMAGE) {
194 image = Gtk::manage(new Gtk::Image(stockID, Gtk::ICON_SIZE_MENU));
196 Glib::ustring xpmName =
197 Glib::locale_to_utf8(toolbarbackend.getIcon(i->func()));
198 if (xpmName.find("unknown.xpm") == Glib::ustring::npos) {
199 // Load icon and shrink it for menu size
200 Glib::RefPtr<Gdk::Pixbuf> bigicon =
201 Gdk::Pixbuf::create_from_file(xpmName);
202 Glib::RefPtr<Gdk::Pixbuf> smallicon =
203 bigicon->scale_simple(iconwidth,iconheight,Gdk::INTERP_TILES);
204 image = Gtk::manage(new Gtk::Image(smallicon));
208 Gtk::ImageMenuItem * item = Gtk::manage(new Gtk::ImageMenuItem);
210 item->set_image(*image);
212 // This hbox is necessary because add_accel_label is protected,
213 // and even if you subclass Gtk::MenuItem then add_accel_label
214 // doesn't do what you'd expect.
215 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox);
216 Gtk::Label * label1 = Gtk::manage(new Gtk::Label(
217 labelTrans(i->label(), i->shortcut()), true));
218 Gtk::Label * label2 = Gtk::manage(new Gtk::Label(
219 " " + i->binding(), false));
220 hbox->pack_start(*label1, false, false, 0);
221 hbox->pack_end(*label2, false, false, 0);
224 gmenu->append(*item);
227 Gtk::MenuItem & item = gmenu->items().back();
228 item.signal_activate().connect(
229 sigc::bind(sigc::mem_fun(*this, &GMenubar::onCommandActivate),
232 item.set_sensitive(false);
235 case MenuItem::Separator:
236 gmenu->items().push_back(
237 Gtk::Menu_Helpers::SeparatorElem());
240 lyxerr << "GMenubar::create_submenu: "
241 "this should not happen" << std::endl;
248 void GMenubar::onCommandActivate(MenuItem const * item,
249 Gtk::MenuItem * /*gitem*/)
251 view_->getLyXFunc().dispatch(item->func());
254 } // namespace frontend