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"
30 #include "support/docstring.h"
47 class LyxMenu : public Gtk::Menu {
49 LyxMenu() { menu_.reset(new ::Menu); }
51 ::Menu& getBackMenu() { return *menu_.get(); }
53 void clearBackMenu() { menu_.reset(new ::Menu); }
55 std::auto_ptr< ::Menu > menu_;
59 Glib::ustring labelTrans(docstring const & label_src,
60 docstring const & shortcut)
62 docstring label = subst(label_src,
64 lyx::from_ascii("__"));
65 docstring::size_type i = label.find(shortcut);
66 if (i == docstring::npos)
67 return lyx::to_utf8(label);
68 label.insert(i, lyx::from_ascii("_"));
69 return lyx::to_utf8(label);
73 void ClearMenu(Gtk::MenuShell * menu)
75 Gtk::Menu_Helpers::MenuList::iterator m = menu->items().begin();
76 Gtk::Menu_Helpers::MenuList::iterator end = menu->items().end();
78 for (; m != end; ++m) {
79 if ((subMenu = m->get_submenu()) != 0) {
84 menu->items().clear();
91 GMenubar::GMenubar(LyXView * lyxView, MenuBackend const & /*menuBackend*/) :
94 GView * gview = static_cast<GView*>(lyxView);
95 Menu const & menu = menubackend.getMenubar();
96 Menu::const_iterator i = menu.begin();
97 Menu::const_iterator end = menu.end();
98 for (; i != end; ++i) {
99 if (i->kind() != MenuItem::Submenu) {
100 lyxerr << "ERROR: GMenubar::createMenubar:"
101 " only submenus can appear in a menubar"
105 Gtk::Menu * gmenu = new LyxMenu;
106 menubar_.items().push_back(
107 Gtk::Menu_Helpers::MenuElem(
108 labelTrans(i->label(), i->shortcut()),
110 menubar_.items().back().signal_activate().connect(
111 sigc::bind(sigc::mem_fun(*this, &GMenubar::onSubMenuActivate), &(*i),
112 &menubar_.items().back()));
113 mainMenuNames_.push_back(lyx::to_utf8(i->submenuname()));
116 gview->getBox(GView::Top).children().push_back(
117 Gtk::Box_Helpers::Element(menubar_, Gtk::PACK_SHRINK));
121 GMenubar::~GMenubar()
123 ClearMenu(&menubar_);
127 void GMenubar::update()
132 void GMenubar::openByName(docstring const & name)
134 Glib::ustring uname = lyx::to_utf8(name);
135 std::vector<Glib::ustring>::iterator it =
136 std::find(mainMenuNames_.begin(), mainMenuNames_.end(),
138 if (it != mainMenuNames_.end()) {
139 Gtk::MenuItem& mitem = menubar_.items()[it - mainMenuNames_.begin()];
144 lyxerr << "GMenubar::openByName: menu "
145 << lyx::to_utf8(name) << " not found" << std::endl;
149 void GMenubar::onSubMenuActivate(MenuItem const * item,
150 Gtk::MenuItem * gitem)
152 Gtk::Menu * gmenu = gitem->get_submenu();
154 LyxMenu * lyxmenu = static_cast<LyxMenu*>(gmenu);
155 lyxmenu->clearBackMenu();
158 Menu::const_iterator i;
159 Menu::const_iterator end;
160 if(!item->submenuname().empty()) {
161 fmenu = &menubackend.getMenu(item->submenuname());
162 menubackend.expand(*fmenu, lyxmenu->getBackMenu(), view_->buffer());
163 i = lyxmenu->getBackMenu().begin();
164 end = lyxmenu->getBackMenu().end();
166 fmenu = item->submenu();
171 // Choose size for icons on command items
174 Gtk::IconSize::lookup(Gtk::ICON_SIZE_MENU, iconwidth, iconheight);
176 Gtk::Menu * gmenu_new;
177 for (; i != end; ++i) {
179 case MenuItem::Submenu:
180 gmenu_new = new LyxMenu;
181 gmenu->items().push_back(
182 Gtk::Menu_Helpers::MenuElem(
183 labelTrans(i->label(), i->shortcut()),
185 gmenu->items().back().signal_activate().connect(
186 sigc::bind(sigc::mem_fun(*this, &GMenubar::onSubMenuActivate),
188 &gmenu->items().back()));
189 if (!i->status().enabled())
190 gmenu->items().back().set_sensitive(false);
192 case MenuItem::Command:
194 FuncStatus const flag = i->status();
195 bool on = flag.onoff(true);
196 bool off = flag.onoff(false);
199 gmenu->items().push_back(
200 Gtk::Menu_Helpers::CheckMenuElem(
201 labelTrans(i->label(),
203 Gtk::CheckMenuItem& checkitem =
204 static_cast<Gtk::CheckMenuItem&>(
205 gmenu->items().back());
206 checkitem.set_active(on);
208 // Choose an icon from the funcrequest
209 Gtk::Image * image = getGTKIcon(i->func(), Gtk::ICON_SIZE_MENU);
211 // ENCODING, FIXME: does Pixbuf::create_from_file really
212 // want UTF-8, or does it want filename encoding? Is
213 // the backend string really in locale encoding?
214 // This shouldn't break as long as filenames are ASCII
215 Glib::ustring xpmName =
216 Glib::locale_to_utf8(toolbarbackend.getIcon(i->func()));
217 if (xpmName.find("unknown.xpm") == Glib::ustring::npos) {
218 // Load icon and shrink it for menu size
219 Glib::RefPtr<Gdk::Pixbuf> bigicon =
220 Gdk::Pixbuf::create_from_file(xpmName);
221 Glib::RefPtr<Gdk::Pixbuf> smallicon =
222 bigicon->scale_simple(iconwidth,iconheight,Gdk::INTERP_TILES);
223 image = Gtk::manage(new Gtk::Image(smallicon));
227 Gtk::ImageMenuItem * imgitem = Gtk::manage(new Gtk::ImageMenuItem);
229 imgitem->set_image(*image);
231 // This hbox is necessary because add_accel_label is protected,
232 // and even if you subclass Gtk::MenuItem then add_accel_label
233 // doesn't do what you'd expect.
234 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox);
235 Gtk::Label * label1 = Gtk::manage(new Gtk::Label(
236 labelTrans(i->label(), i->shortcut()), true));
237 Gtk::Label * label2 =
238 Gtk::manage(new Gtk::Label(
239 " " + lyx::to_utf8(i->binding()), false));
240 hbox->pack_start(*label1, false, false, 0);
241 hbox->pack_end(*label2, false, false, 0);
244 gmenu->append(*imgitem);
247 Gtk::MenuItem & newitem = gmenu->items().back();
248 newitem.signal_activate().connect(
249 sigc::bind(sigc::mem_fun(*this, &GMenubar::onCommandActivate),
252 newitem.set_sensitive(false);
255 case MenuItem::Separator:
256 gmenu->items().push_back(
257 Gtk::Menu_Helpers::SeparatorElem());
260 lyxerr << "GMenubar::create_submenu: "
261 "this should not happen" << std::endl;
268 void GMenubar::onCommandActivate(MenuItem const * item,
269 Gtk::MenuItem * /*gitem*/)
271 view_.dispatch(item->func());
274 } // namespace frontend