]> git.lyx.org Git - lyx.git/blob - src/frontends/gtk/GMenubar.C
Add ShowFile dialog
[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
13 #include "GMenubar.h"
14 #include "GView.h"
15 #include "debug.h"
16 #include "lyxfunc.h"
17
18 using std::string;
19
20 namespace lyx {
21 namespace frontend {
22
23 namespace
24 {
25
26 class LyxMenu : public Gtk::Menu {
27 public:
28         LyxMenu() { menu_.reset(new ::Menu); }
29
30         ::Menu& getBackMenu() { return *menu_.get(); }
31
32         void clearBackMenu() { menu_.reset(new ::Menu); }
33 private:
34         std::auto_ptr< ::Menu > menu_;
35 };
36
37
38 Glib::ustring labelTrans(string const & label, string const & shortcut)
39 {
40         string labelN = label;
41         string::size_type i = label.find(shortcut);
42         if (i == string::npos)
43                 return Glib::locale_to_utf8(label);
44         labelN.insert(i, "_");
45         return Glib::locale_to_utf8(labelN);
46 }
47
48
49 void ClearMenu(Gtk::MenuShell * menu)
50 {
51         Gtk::Menu_Helpers::MenuList::iterator m = menu->items().begin();
52         Gtk::Menu_Helpers::MenuList::iterator end = menu->items().end();
53         Gtk::Menu * subMenu;
54         for (; m != end; ++m) {
55                 if ((subMenu = m->get_submenu()) != 0) {
56                         ClearMenu(subMenu);
57                         delete subMenu;
58                 }
59         }
60         menu->items().clear();
61 }
62
63
64 }
65
66
67 GMenubar::GMenubar(LyXView * lyxView, MenuBackend const & /*menuBackend*/) :
68         view_(lyxView)
69 {
70         GView * gview = static_cast<GView*>(lyxView);
71         Menu const & menu = menubackend.getMenubar();
72         Menu::const_iterator i = menu.begin();
73         Menu::const_iterator end = menu.end();
74         for (; i != end; ++i) {
75                 if (i->kind() != MenuItem::Submenu) {
76                         lyxerr << "ERROR: GMenubar::createMenubar:"
77                                 " only submenus can appear in a menubar"
78                                << std::endl;
79                         continue;
80                 }
81                 Gtk::Menu * gmenu = new LyxMenu;
82                 menubar_.items().push_back(
83                         Gtk::Menu_Helpers::MenuElem(
84                                 labelTrans(i->label(), i->shortcut()),
85                                 *gmenu));
86                 menubar_.items().back().signal_activate().connect(
87                         sigc::bind(sigc::mem_fun(*this, &GMenubar::onSubMenuActivate), &(*i),
88                                    &menubar_.items().back()));
89                 mainMenuNames_.push_back(i->submenuname());
90         }
91         menubar_.show();
92         gview->getBox(GView::Top).children().push_back(
93                 Gtk::Box_Helpers::Element(menubar_, Gtk::PACK_SHRINK));
94 }
95
96
97 GMenubar::~GMenubar()
98 {
99         ClearMenu(&menubar_);
100 }
101
102
103 void GMenubar::update()
104 {
105 }
106
107
108 void GMenubar::openByName(string const & name)
109 {
110         Glib::ustring uname = Glib::locale_to_utf8(name);
111         std::vector<Glib::ustring>::iterator it =
112                 std::find(mainMenuNames_.begin(), mainMenuNames_.end(),
113                           uname);
114         if (it != mainMenuNames_.end()) {
115                 Gtk::MenuItem& mitem = menubar_.items()[it - mainMenuNames_.begin()];
116                 mitem.select();
117                 mitem.activate();
118                 return;
119         }
120         lyxerr << "GMenubar::openByName: menu "
121                << name << " not found" << std::endl;
122 }
123
124
125 bool GMenubar::submenuDisabled(MenuItem const * item)
126 {
127         Menu * from = item->submenu();
128         Menu to;
129         menubackend.expand(*from, to, view_);
130         Menu::const_iterator i = to.begin();
131         Menu::const_iterator end = to.end();
132         for (; i != end; ++i) {
133                 switch (i->kind()) {
134                 case MenuItem::Submenu:
135                         if (!submenuDisabled(&(*i)))
136                                 return false;
137                         break;
138                 case MenuItem::Command:
139                 {
140                         FuncStatus const flag =
141                                 view_->getLyXFunc().getStatus(i->func());
142                         if (flag.enabled())
143                                 return false;
144                         break;
145                 }
146                 default:
147                         break;
148                 }
149         }
150         return true;
151 }
152
153
154 void GMenubar::onSubMenuActivate(MenuItem const * item,
155                                  Gtk::MenuItem * gitem)
156 {
157         Gtk::Menu * gmenu = gitem->get_submenu();
158         ClearMenu(gmenu);
159         LyxMenu * lyxmenu = static_cast<LyxMenu*>(gmenu);
160         lyxmenu->clearBackMenu();
161         Menu * fmenu = item->submenuname().empty() ?
162                 item->submenu() :
163                 &menubackend.getMenu(item->submenuname());
164
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::mem_fun(*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                         FuncStatus const flag =
187                                 view_->getLyXFunc().getStatus(i->func());
188                         bool on = flag.onoff(true);
189                         bool off = flag.onoff(false);
190
191                         if (on || off) {
192                                 gmenu->items().push_back(
193                                         Gtk::Menu_Helpers::CheckMenuElem(
194                                                 labelTrans(i->label(),
195                                                            i->shortcut())));
196                                 Gtk::CheckMenuItem& citem =
197                                         static_cast<Gtk::CheckMenuItem&>(
198                                                 gmenu->items().back());
199                                 citem.set_active(on);
200                         } else {
201                                 // This is necessary because add_accel_label is protected,
202                                 // and even if you subclass Gtk::MenuItem then add_accel_label
203                                 // doesn't do what you'd expect.
204                                 Gtk::MenuItem * item = Gtk::manage(new Gtk::MenuItem);
205                                 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox);
206                                 Gtk::Label * label1 = Gtk::manage(new Gtk::Label(
207                                         labelTrans(i->label(), i->shortcut()), true));
208                                 Gtk::Label * label2 = Gtk::manage(new Gtk::Label(
209                                         "   " + i->binding(), false));
210                                 hbox->pack_start(*label1, false, false, 0);
211                                 hbox->pack_end(*label2, false, false, 0);
212                                 item->add(*hbox);
213
214                                 gmenu->append(*item);
215                                 item->show_all();
216                         }
217                         Gtk::MenuItem & item = gmenu->items().back();
218                         item.signal_activate().connect(
219                                 sigc::bind(sigc::mem_fun(*this, &GMenubar::onCommandActivate),
220                                            &(*i), &item));
221                         if (!flag.enabled())
222                                 item.set_sensitive(false);
223                         break;
224                 }
225                 case MenuItem::Separator:
226                         gmenu->items().push_back(
227                                 Gtk::Menu_Helpers::SeparatorElem());
228                         break;
229                 default:
230                         lyxerr << "GMenubar::create_submenu: "
231                                 "this should not happen" << std::endl;
232                         break;
233                 }
234         }
235 }
236
237
238 void GMenubar::onCommandActivate(MenuItem const * item,
239                                        Gtk::MenuItem * /*gitem*/)
240 {
241         view_->getLyXFunc().dispatch(item->func(), true);
242 }
243
244 } // namespace frontend
245 } // namespace lyx