]> git.lyx.org Git - lyx.git/blob - src/frontends/gtk/GMenubar.C
Wrap most of the frontend code up inside namespace lyx::frontend.
[lyx.git] / src / frontends / gtk / GMenubar.C
1 /**
2  * \file GMenubar.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Huang Ying
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12 #include <gtkmm.h>
13
14 #include "GMenubar.h"
15 #include "GView.h"
16 #include "debug.h"
17 #include "lyxfunc.h"
18
19 using std::string;
20
21 namespace lyx {
22 namespace frontend {
23
24 namespace
25 {
26
27 class LyxMenu : public Gtk::Menu
28 {
29 public:
30         LyxMenu() { menu_.reset(new ::Menu); }
31
32         ::Menu& getBackMenu() { return *menu_.get(); }
33
34         void clearBackMenu() { menu_.reset(new ::Menu); }
35 private:
36         std::auto_ptr< ::Menu > menu_;
37 };
38
39
40 Glib::ustring labelTrans(string const & label, string const & shortcut)
41 {
42         string labelN = label;
43         string::size_type i = label.find(shortcut);
44         if (i == string::npos)
45                 return Glib::locale_to_utf8(label);
46         labelN.insert(i, "_");
47         return Glib::locale_to_utf8(labelN);
48 }
49
50
51 void ClearMenu(Gtk::MenuShell * menu)
52 {
53         Gtk::Menu_Helpers::MenuList::iterator m, end;
54         m = menu->items().begin();
55         end = menu->items().end();
56         Gtk::Menu * subMenu;
57         for (; m != end; ++m) {
58                 if ((subMenu = m->get_submenu()) != 0) {
59                         ClearMenu(subMenu);
60                         delete subMenu;
61                 }
62         }
63         menu->items().clear();
64 }
65
66
67 }
68
69
70 GMenubar::GMenubar(LyXView *lyxView, MenuBackend const & /*menuBackend*/) :
71         view_(lyxView)
72 {
73         GView * gview = static_cast<GView*>(lyxView);
74         Menu const & menu = menubackend.getMenubar();
75         Menu::const_iterator i = menu.begin();
76         Menu::const_iterator end = menu.end();
77         for (; i != end; ++i) {
78                 if (i->kind() != MenuItem::Submenu) {
79                         lyxerr << "ERROR: GMenubar::createMenubar:"
80                                 " only submenus can appear in a menubar"
81                                << std::endl;
82                         continue;
83                 }
84                 Gtk::Menu * gmenu = new LyxMenu;
85                 menubar_.items().push_back(
86                         Gtk::Menu_Helpers::MenuElem(
87                                 labelTrans(i->label(), i->shortcut()),
88                                 *gmenu));
89                 menubar_.items().back().signal_activate().connect(
90                         SigC::bind(SigC::slot(*this, &GMenubar::onSubMenuActivate), &(*i),
91                                    &menubar_.items().back()));
92                 mainMenuNames_.push_back(i->submenuname());
93         }
94         menubar_.show();
95         gview->getBox(GView::Top).children().push_back(
96                 Gtk::Box_Helpers::Element(menubar_, Gtk::PACK_SHRINK));
97 }
98
99
100 GMenubar::~GMenubar()
101 {
102         ClearMenu(&menubar_);
103 }
104
105
106 void GMenubar::update()
107 {
108 }
109
110
111 void GMenubar::openByName(string const & name)
112 {
113         Glib::ustring uname = Glib::locale_to_utf8(name);
114         std::vector<Glib::ustring>::iterator it =
115                 std::find(mainMenuNames_.begin(), mainMenuNames_.end(),
116                           uname);
117         if (it != mainMenuNames_.end()) {
118                 Gtk::MenuItem& mitem = menubar_.items()[it - mainMenuNames_.begin()];
119                 mitem.select();
120                 mitem.activate();
121                 return;
122         }
123         lyxerr << "GMenubar::openByName: menu "
124                << name << " not found" << std::endl;
125 }
126
127
128 bool GMenubar::submenuDisabled(MenuItem const * item)
129 {
130         Menu & from = menubackend.getMenu(item->submenuname());
131         Menu to;
132         menubackend.expand(from, to, view_);
133         Menu::const_iterator i = to.begin();
134         Menu::const_iterator end = to.end();
135         for (; i != end; ++i) {
136                 switch (i->kind()) {
137                 case MenuItem::Submenu:
138                         if (!submenuDisabled(&(*i)))
139                                 return false;
140                         break;
141                 case MenuItem::Command:
142                 {
143                         FuncStatus const flag =
144                                 view_->getLyXFunc().getStatus(i->func());
145                         if (flag.enabled())
146                                 return false;
147                         break;
148                 }
149                 default:
150                         break;
151                 }
152         }
153         return true;
154 }
155
156
157 void GMenubar::onSubMenuActivate(MenuItem const * item,
158                                  Gtk::MenuItem * gitem)
159 {
160         Gtk::Menu * gmenu = gitem->get_submenu();
161         ClearMenu(gmenu);
162         LyxMenu * lyxmenu = static_cast<LyxMenu*>(gmenu);
163         lyxmenu->clearBackMenu();
164         Menu * fmenu = &menubackend.getMenu(item->submenuname());
165         menubackend.expand(*fmenu, lyxmenu->getBackMenu(), view_);
166         Menu::const_iterator i = lyxmenu->getBackMenu().begin();
167         Menu::const_iterator end = lyxmenu->getBackMenu().end();
168         Gtk::Menu * gmenu_new;
169         for (; i != end; ++i) {
170                 switch (i->kind()) {
171                 case MenuItem::Submenu:
172                         gmenu_new = new LyxMenu;
173                         gmenu->items().push_back(
174                                 Gtk::Menu_Helpers::MenuElem(
175                                         labelTrans(i->label(), i->shortcut()),
176                                         *gmenu_new));
177                         gmenu->items().back().signal_activate().connect(
178                                 SigC::bind(SigC::slot(*this, &GMenubar::onSubMenuActivate),
179                                            &(*i),
180                                            &gmenu->items().back()));
181                         if (submenuDisabled(&(*i)))
182                                 gmenu->items().back().set_sensitive(false);
183                         break;
184                 case MenuItem::Command:
185                 {
186 #ifdef WITH_WARNINGS
187 #warning Bindings are not inserted into the menu labels here. (Lgb)
188 #endif
189                         FuncStatus const flag =
190                                 view_->getLyXFunc().getStatus(i->func());
191                         bool on = flag.onoff(true);
192                         bool off = flag.onoff(false);
193
194                         if (on || off) {
195                                 gmenu->items().push_back(
196                                         Gtk::Menu_Helpers::CheckMenuElem(
197                                                 labelTrans(i->label(),
198                                                            i->shortcut())));
199                                 Gtk::CheckMenuItem& citem =
200                                         static_cast<Gtk::CheckMenuItem&>(
201                                                 gmenu->items().back());
202                                 citem.set_active(on);
203                         } else {
204                                 gmenu->items().push_back(
205                                         Gtk::Menu_Helpers::MenuElem(
206                                                 labelTrans(i->label(),
207                                                            i->shortcut())));
208                         }
209                         Gtk::MenuItem & item = gmenu->items().back();
210                         item.signal_activate().connect(
211                                 SigC::bind(SigC::slot(*this, &GMenubar::onCommandActivate),
212                                            &(*i), &item));
213                         if (!flag.enabled())
214                                 item.set_sensitive(false);
215                         break;
216                 }
217                 case MenuItem::Separator:
218                         gmenu->items().push_back(
219                                 Gtk::Menu_Helpers::SeparatorElem());
220                         break;
221                 default:
222                         lyxerr << "GMenubar::create_submenu: "
223                                 "this should not happen" << std::endl;
224                         break;
225                 }
226         }
227 }
228
229
230 void GMenubar::onCommandActivate(MenuItem const * item,
231                                        Gtk::MenuItem * /*gitem*/)
232 {
233         view_->getLyXFunc().dispatch(item->func(), true);
234 }
235
236 } // namespace frontend
237 } // namespace lyx