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