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