]> git.lyx.org Git - features.git/blob - src/MenuBackend.C
use more std::functors add some of my own, some change to fl_display etc. read the...
[features.git] / src / MenuBackend.C
1 /* This file is part of
2  * ====================================================== 
3  * 
4  *           LyX, The Document Processor
5  *
6  *           Copyright 1995 Matthias Ettrich
7  *           Copyright 1995-2000 The LyX Team.
8  *
9  *
10  * ====================================================== */
11
12 #ifdef __GNUG__
13 #pragma implementation
14 #endif
15
16 #include <config.h>
17 #include <memory>
18 #include "support/LAssert.h"
19 #include "MenuBackend.h"
20 #include "lyxlex.h"
21 #include "LyXAction.h"
22 #include "debug.h"
23 #include "gettext.h"
24 #include "lastfiles.h"
25 #include "bufferlist.h"
26 #include "exporter.h"
27 #include "support/filetools.h"
28 #include "support/lyxfunctional.h"
29
30 extern LyXAction lyxaction;
31 extern LastFiles * lastfiles; 
32 extern BufferList bufferlist;
33
34 using std::endl;
35 using std::vector;
36 using std::pair;
37
38 // This is the global menu definition
39 MenuBackend menubackend;
40
41
42 MenuItem::MenuItem(Kind kind, string const & label, 
43                    string const & command, bool optional) 
44         : kind_(kind), label_(label), optional_(optional)
45 {
46         switch(kind) {
47         case Separator:
48         case Documents:
49         case Lastfiles:
50         case Toc:
51         case References:
52         case ViewFormats:
53         case UpdateFormats:
54         case ExportFormats:
55                 break;
56         case Command:
57                 action_ = lyxaction.LookupFunc(command);
58
59                 if (action_ == LFUN_UNKNOWN_ACTION) {
60                         lyxerr << "MenuItem(): LyX command `"
61                                << command << "' does not exist." << endl; 
62                 }
63                 if (optional_)
64                         lyxerr[Debug::GUI] << "Optional item " 
65                                            << command << endl; 
66                 break;
67         case Submenu:
68                 submenu_ = command;
69                 break;
70         }
71 }
72
73
74 Menu & Menu::add(MenuItem const & i)
75 {
76         items_.push_back(i);
77         return *this;
78 }
79
80
81 Menu & Menu::read(LyXLex & lex)
82 {
83         enum Menutags {
84                 md_item = 1,
85                 md_documents,
86                 md_endmenu,
87                 md_exportformats,
88                 md_lastfiles,
89                 md_optitem,
90                 md_references,
91                 md_separator,
92                 md_submenu,
93                 md_toc,
94                 md_updateformats,
95                 md_viewformats,
96                 md_last
97         };
98
99         struct keyword_item menutags[md_last - 1] = {
100                 { "documents", md_documents },
101                 { "end", md_endmenu },
102                 { "exportformats", md_exportformats },
103                 { "item", md_item },
104                 { "lastfiles", md_lastfiles },
105                 { "optitem", md_optitem }, 
106                 { "references", md_references },
107                 { "separator", md_separator },
108                 { "submenu", md_submenu },
109                 { "toc", md_toc },
110                 { "updateformats", md_updateformats },
111                 { "viewformats", md_viewformats }
112         };
113
114         lex.pushTable(menutags, md_last - 1);
115         if (lyxerr.debugging(Debug::PARSER))
116                 lex.printTable(lyxerr);
117
118         bool quit = false;
119         bool optional = false;
120
121         while (lex.IsOK() && !quit) {
122                 switch(lex.lex()) {
123                 case md_optitem:
124                         optional = true;
125                         // fallback to md_item
126                 case md_item: {
127                         lex.next();
128                         string name = _(lex.GetString());
129                         lex.next();
130                         string const command = lex.GetString();
131                         add(MenuItem(MenuItem::Command, name, 
132                                      command, optional));
133                         optional = false;
134                         break;
135                 }
136
137                 case md_separator:
138                         add(MenuItem(MenuItem::Separator));
139                         break;
140
141                 case md_lastfiles:
142                         add(MenuItem(MenuItem::Lastfiles));
143                         break;
144
145                 case md_documents:
146                         add(MenuItem(MenuItem::Documents));
147                         break;
148
149                 case md_toc:
150                         add(MenuItem(MenuItem::Toc));
151                         break;
152
153                 case md_references:
154                         add(MenuItem(MenuItem::References));
155                         break;
156
157                 case md_viewformats:
158                         add(MenuItem(MenuItem::ViewFormats));
159                         break;
160
161                 case md_updateformats:
162                         add(MenuItem(MenuItem::UpdateFormats));
163                         break;
164
165                 case md_exportformats:
166                         add(MenuItem(MenuItem::ExportFormats));
167                         break;
168
169                 case md_submenu: {
170                         lex.next();
171                         string mlabel = _(lex.GetString());
172                         lex.next();
173                         string mname = lex.GetString();
174                         add(MenuItem(MenuItem::Submenu, mlabel, mname));
175                         break;
176                 }
177
178                 case md_endmenu:
179                         quit = true;
180                         break;
181
182                 default:
183                         lex.printError("menubar::read: "
184                                        "Unknown menu tag: `$$Token'");
185                         break;
186                 }
187         }
188         lex.popTable();
189         return *this;
190 }
191
192
193 void Menu::expand(Menu & tomenu, Buffer * buf) const
194 {
195         for (const_iterator cit = begin();
196              cit != end() ; ++cit) {
197                 switch ((*cit).kind()) {
198                 case MenuItem::Lastfiles: {
199                         int ii = 1;
200                         for (LastFiles::const_iterator lfit = lastfiles->begin();
201                              lfit != lastfiles->end() && ii < 10;
202                              ++lfit, ++ii) {
203                                 string label = tostr(ii) + ". "
204                                         + MakeDisplayPath((*lfit), 30)
205                                         + '|' + tostr(ii);
206                                 int action = lyxaction.
207                                         getPseudoAction(LFUN_FILE_OPEN,
208                                                         (*lfit));
209                                 tomenu.add(MenuItem(MenuItem::Command,
210                                                     label, action));
211                         }
212                 }
213                 break;
214                 
215                 case MenuItem::Documents: {
216                         vector<string> names = bufferlist.getFileNames();
217                         
218                         if (names.empty()) {
219                                 tomenu.add(MenuItem(MenuItem::Command,
220                                                     _("No Documents Open!"),
221                                                     LFUN_NOACTION));
222                                 break;
223                         }
224
225                         for (vector<string>::const_iterator docit = names.begin();
226                              docit != names.end() ; ++docit) {
227                                 int action =
228                                         lyxaction.getPseudoAction(LFUN_SWITCHBUFFER, *docit);
229                                 string label = MakeDisplayPath(*docit, 30);
230                                 tomenu.add(MenuItem(MenuItem::Command,
231                                                     label, action));
232                         }
233                 }
234                 break;
235
236                 case MenuItem::ViewFormats:
237                 case MenuItem::UpdateFormats:
238                 case MenuItem::ExportFormats: {
239                         vector<pair<string,string> > names;
240                         kb_action action;
241                         if ((*cit).kind() == MenuItem::ViewFormats) {
242                                 names = Exporter::GetViewableFormats(buf);
243                                 action = LFUN_PREVIEW;
244                         } else if ((*cit).kind() == MenuItem::UpdateFormats) {
245                                 names = Exporter::GetViewableFormats(buf);
246                                 action = LFUN_UPDATE;
247                         } else {
248                                 names = Exporter::GetExportableFormats(buf);
249                                 action = LFUN_EXPORT;
250                         }
251
252                         for (vector<pair<string,string> >::const_iterator fit = names.begin();
253                              fit != names.end() ; ++fit) {
254                                 int action2 =
255                                         lyxaction.getPseudoAction(action,
256                                                                   (*fit).first);
257                                 string label = (*fit).second;
258                                 tomenu.add(MenuItem(MenuItem::Command,
259                                                     label, action2));
260                         }
261                 }
262                 break;
263
264                         
265                 default:
266                         tomenu.add(*cit);
267                 }
268         }
269 }
270
271
272 void MenuBackend::read(LyXLex & lex)
273 {
274         enum Menutags {
275                 md_menu = 1,
276                 md_menubar,
277                 md_endmenuset,
278                 md_last
279         };
280
281         struct keyword_item menutags[md_last - 1] = {
282                 { "end", md_endmenuset },
283                 { "menu", md_menu },
284                 { "menubar", md_menubar }
285         };
286
287         //consistency check
288         if (compare_no_case(lex.GetString(), "menuset"))
289                 lyxerr << "Menubackend::read: ERROR wrong token:`"
290                        << lex.GetString() << '\'' << endl;
291
292         lex.pushTable(menutags, md_last - 1);
293         if (lyxerr.debugging(Debug::PARSER))
294                 lex.printTable(lyxerr);
295
296         bool quit = false;
297         bool menubar = false;
298
299         while (lex.IsOK() && !quit) {
300                 switch(lex.lex()) {
301                 case md_menubar: 
302                         menubar = true;
303                         // fallback to md_menu
304                 case md_menu: {
305                         lex.next();
306                         string name = lex.GetString();
307                         if (hasMenu(name)) {
308                                 if (getMenu(name).menubar() == menubar) {
309                                         getMenu(name).read(lex);
310                                 } else {
311                                         lex.printError("Cannot append to menu `$$Token' unless it is of the same type");
312                                         return;
313                                 }
314                         } else {                                
315                                 Menu menu(name, menubar);
316                                 menu.read(lex);
317                                 add(menu);
318                         }
319                         menubar = false;
320                         break;
321                 }
322                 case md_endmenuset:
323                         quit = true;
324                         break;
325                 default:
326                         lex.printError("menubackend::read: "
327                                        "Unknown menu tag: `$$Token'");
328                         break;
329                 }
330         }
331         lex.popTable();
332 }
333
334
335 void MenuBackend::defaults()
336 {
337         menulist_.clear();
338
339         lyxerr[Debug::GUI] << "MenuBackend::defaults: using default values" 
340                            << endl;
341
342         Menu file("file");
343         file
344                 .add(MenuItem(MenuItem::Command, _("New...|N"), "buffer-new"))
345                 .add(MenuItem(MenuItem::Command, _("Open...|O"), "buffer-open"))
346                 .add(MenuItem(MenuItem::Submenu, _("Import|I"), "import"))
347                 .add(MenuItem(MenuItem::Command, _("Quit|Q"), "lyx-quit"))
348                 .add(MenuItem(MenuItem::Separator))
349                 .add(MenuItem(MenuItem::Lastfiles));
350         add(file);
351
352         Menu import("import");
353         import
354                 .add(MenuItem(MenuItem::Command,
355                               _("LaTeX...|L"), "buffer-import latex"))
356                 .add(MenuItem(MenuItem::Command,
357                               _("LinuxDoc...|L"), "buffer-import linuxdoc"));
358         add(import);
359  
360         Menu edit("edit");
361         edit
362                 .add(MenuItem(MenuItem::Command, _("Cut"), "cut"))
363                 .add(MenuItem(MenuItem::Command, _("Copy"), "copy"))
364                 .add(MenuItem(MenuItem::Command, _("Paste"), "paste"))
365                 .add(MenuItem(MenuItem::Command, _("Emphasize"), "font-emph"));
366         add(edit);
367
368         Menu documents("documents");
369         documents.add(MenuItem(MenuItem::Documents));
370         add(documents);
371
372         Menu main("main", true);
373         main
374                 .add(MenuItem(MenuItem::Submenu, _("File|F"), "file"))
375                 .add(MenuItem(MenuItem::Submenu, _("Edit|E"), "edit"))
376                 .add(MenuItem(MenuItem::Submenu,
377                               _("Documents|D"), "documents"));
378         add(main);
379
380         Menu main_nobuffer("main_nobuffer", true);
381         main_nobuffer.add(MenuItem(MenuItem::Submenu, _("File|F"), "file"));
382         add(main_nobuffer);
383
384         if (lyxerr.debugging(Debug::GUI)) {
385                 for(const_iterator cit = begin();
386                     cit != end() ; ++cit)
387                         lyxerr << "Menu name: " << cit->name() 
388                                << ", Menubar: " << cit->menubar() 
389                                << endl;
390         }
391 }
392
393
394 void MenuBackend::add(Menu const & menu)
395 {
396         menulist_.push_back(menu);
397 }
398
399
400 bool MenuBackend::hasMenu(string const & name) const
401 {
402         return find_if(begin(), end(),
403                        compare_memfun(&Menu::name, name)) != end();
404 }
405
406
407 Menu const & MenuBackend::getMenu(string const & name) const
408 {
409         const_iterator cit = find_if(begin(), end(),
410                                      compare_memfun(&Menu::name, name));
411         Assert(cit != end());
412         return (*cit);
413 }
414
415
416 Menu & MenuBackend::getMenu(string const & name)
417 {
418         MenuList::iterator it = find_if(menulist_.begin(), menulist_.end(),
419                                         compare_memfun(&Menu::name, name));
420         Assert(it != menulist_.end());
421         return (*it);
422 }