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
29 #include "support/lstrings.h"
43 class LyxMenu : public Gtk::Menu {
45 LyxMenu() { menu_.reset(new ::Menu); }
47 ::Menu& getBackMenu() { return *menu_.get(); }
49 void clearBackMenu() { menu_.reset(new ::Menu); }
51 std::auto_ptr< ::Menu > menu_;
55 // ENCODING: assume that the backend will give us a locale string
56 Glib::ustring labelTrans(string const & label_src, string const & shortcut)
58 string label = subst(label_src, "_", "__");
59 string::size_type i = label.find(shortcut);
60 if (i == string::npos)
61 return Glib::locale_to_utf8 (label);
63 return Glib::locale_to_utf8 (label);
67 void ClearMenu(Gtk::MenuShell * menu)
69 Gtk::Menu_Helpers::MenuList::iterator m = menu->items().begin();
70 Gtk::Menu_Helpers::MenuList::iterator end = menu->items().end();
72 for (; m != end; ++m) {
73 if ((subMenu = m->get_submenu()) != 0) {
78 menu->items().clear();
85 GMenubar::GMenubar(LyXView * lyxView, MenuBackend const & /*menuBackend*/) :
88 GView * gview = static_cast<GView*>(lyxView);
89 Menu const & menu = menubackend.getMenubar();
90 Menu::const_iterator i = menu.begin();
91 Menu::const_iterator end = menu.end();
92 for (; i != end; ++i) {
93 if (i->kind() != MenuItem::Submenu) {
94 lyxerr << "ERROR: GMenubar::createMenubar:"
95 " only submenus can appear in a menubar"
99 Gtk::Menu * gmenu = new LyxMenu;
100 menubar_.items().push_back(
101 Gtk::Menu_Helpers::MenuElem(
102 labelTrans(i->label(), i->shortcut()),
104 menubar_.items().back().signal_activate().connect(
105 sigc::bind(sigc::mem_fun(*this, &GMenubar::onSubMenuActivate), &(*i),
106 &menubar_.items().back()));
107 mainMenuNames_.push_back(i->submenuname());
110 gview->getBox(GView::Top).children().push_back(
111 Gtk::Box_Helpers::Element(menubar_, Gtk::PACK_SHRINK));
115 GMenubar::~GMenubar()
117 ClearMenu(&menubar_);
121 void GMenubar::update()
126 void GMenubar::openByName(string const & name)
128 Glib::ustring uname = Glib::convert(name, "UTF-8", "ISO-8859-1");
129 std::vector<Glib::ustring>::iterator it =
130 std::find(mainMenuNames_.begin(), mainMenuNames_.end(),
132 if (it != mainMenuNames_.end()) {
133 Gtk::MenuItem& mitem = menubar_.items()[it - mainMenuNames_.begin()];
138 lyxerr << "GMenubar::openByName: menu "
139 << name << " not found" << std::endl;
143 void GMenubar::onSubMenuActivate(MenuItem const * item,
144 Gtk::MenuItem * gitem)
146 Gtk::Menu * gmenu = gitem->get_submenu();
148 LyxMenu * lyxmenu = static_cast<LyxMenu*>(gmenu);
149 lyxmenu->clearBackMenu();
152 Menu::const_iterator i;
153 Menu::const_iterator end;
154 if(!item->submenuname().empty()) {
155 fmenu = &menubackend.getMenu(item->submenuname());
156 menubackend.expand(*fmenu, lyxmenu->getBackMenu(), view_);
157 i = lyxmenu->getBackMenu().begin();
158 end = lyxmenu->getBackMenu().end();
160 fmenu = item->submenu();
165 // Choose size for icons on command items
168 Gtk::IconSize::lookup(Gtk::ICON_SIZE_MENU, iconwidth, iconheight);
170 Gtk::Menu * gmenu_new;
171 for (; i != end; ++i) {
173 case MenuItem::Submenu:
174 gmenu_new = new LyxMenu;
175 gmenu->items().push_back(
176 Gtk::Menu_Helpers::MenuElem(
177 labelTrans(i->label(), i->shortcut()),
179 gmenu->items().back().signal_activate().connect(
180 sigc::bind(sigc::mem_fun(*this, &GMenubar::onSubMenuActivate),
182 &gmenu->items().back()));
183 if (!i->status().enabled())
184 gmenu->items().back().set_sensitive(false);
186 case MenuItem::Command:
188 FuncStatus const flag = i->status();
189 bool on = flag.onoff(true);
190 bool off = flag.onoff(false);
193 gmenu->items().push_back(
194 Gtk::Menu_Helpers::CheckMenuElem(
195 labelTrans(i->label(),
197 Gtk::CheckMenuItem& checkitem =
198 static_cast<Gtk::CheckMenuItem&>(
199 gmenu->items().back());
200 checkitem.set_active(on);
202 // Choose an icon from the funcrequest
203 Gtk::Image * image = getGTKIcon(i->func(), Gtk::ICON_SIZE_MENU);
205 // ENCODING, FIXME: does Pixbuf::create_from_file really
206 // want UTF-8, or does it want filename encoding? Is
207 // the backend string really in locale encoding?
208 // This shouldn't break as long as filenames are ASCII
209 Glib::ustring xpmName =
210 Glib::locale_to_utf8(toolbarbackend.getIcon(i->func()));
211 if (xpmName.find("unknown.xpm") == Glib::ustring::npos) {
212 // Load icon and shrink it for menu size
213 Glib::RefPtr<Gdk::Pixbuf> bigicon =
214 Gdk::Pixbuf::create_from_file(xpmName);
215 Glib::RefPtr<Gdk::Pixbuf> smallicon =
216 bigicon->scale_simple(iconwidth,iconheight,Gdk::INTERP_TILES);
217 image = Gtk::manage(new Gtk::Image(smallicon));
221 Gtk::ImageMenuItem * imgitem = Gtk::manage(new Gtk::ImageMenuItem);
223 imgitem->set_image(*image);
225 // This hbox is necessary because add_accel_label is protected,
226 // and even if you subclass Gtk::MenuItem then add_accel_label
227 // doesn't do what you'd expect.
228 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox);
229 Gtk::Label * label1 = Gtk::manage(new Gtk::Label(
230 labelTrans(i->label(), i->shortcut()), true));
231 Gtk::Label * label2 = Gtk::manage(new Gtk::Label(
232 " " + i->binding(), false));
233 hbox->pack_start(*label1, false, false, 0);
234 hbox->pack_end(*label2, false, false, 0);
237 gmenu->append(*imgitem);
240 Gtk::MenuItem & newitem = gmenu->items().back();
241 newitem.signal_activate().connect(
242 sigc::bind(sigc::mem_fun(*this, &GMenubar::onCommandActivate),
245 newitem.set_sensitive(false);
248 case MenuItem::Separator:
249 gmenu->items().push_back(
250 Gtk::Menu_Helpers::SeparatorElem());
253 lyxerr << "GMenubar::create_submenu: "
254 "this should not happen" << std::endl;
261 void GMenubar::onCommandActivate(MenuItem const * item,
262 Gtk::MenuItem * /*gitem*/)
264 view_->getLyXFunc().dispatch(item->func());
267 } // namespace frontend