]> git.lyx.org Git - lyx.git/blob - src/frontends/gnome/Menubar_pimpl.C
John's KDE FormRef patch
[lyx.git] / src / frontends / gnome / Menubar_pimpl.C
1 // -*- C++ -*-
2 /* This file is part of
3  * ====================================================== 
4  * 
5  *           LyX, The Document Processor
6  *       
7  *          Copyright 2000 The LyX Team.
8  *
9  * ====================================================== */
10
11 #ifdef __GNUG__
12 #pragma implementation
13 #endif
14
15 #include <config.h>
16
17 #include <algorithm>
18 #include <cctype>
19 #include "support/lstrings.h"
20 #include "support/filetools.h"
21 #include "support/StrPool.h"
22 #include "support/LAssert.h"
23 #include "debug.h"
24 #include "LyXAction.h"
25 #include "lyxfunc.h"
26 #include "kbmap.h"
27 #include "bufferlist.h"
28 #include "lastfiles.h"
29 #include "LyXView.h"
30 #include "MenuBackend.h"
31 #include "Menubar_pimpl.h"
32
33 #include "mainapp.h"
34
35 using SigC::slot;
36 using SigC::bind;
37
38 using std::endl;
39
40 // temporary solution for LyXView
41 extern GLyxAppWin * mainAppWin;
42
43 // Some constants
44 extern kb_keymap * toplevel_keymap;
45 extern LyXAction lyxaction;
46 extern BufferList bufferlist;
47 extern LastFiles * lastfiles; 
48
49
50
51 Menubar::Pimpl::Pimpl(LyXView * view, MenuBackend const & mb) 
52   : owner_(view), menubackend_(&mb), ignore_action_(false)
53 {
54         // Should we do something here?
55 }
56
57 Menubar::Pimpl::~Pimpl() 
58 {
59         // Should we do something here?
60 }
61
62 void Menubar::Pimpl::set(string const & menu_name) 
63 {
64   // if (current_menu_name_ != menu_name)  // disabled until Lastfiles and Documents are added dynamically to menu
65     {
66       current_menu_name_ = menu_name;
67       // compose new menu
68       vector<Gnome::UI::Info> menus;
69       composeUIInfo(current_menu_name_, menus);
70
71       // set menu
72       Menu_ = menus;
73       mainAppWin->set_menu(Menu_);
74
75       // connect all menu items to correspoding action
76       wid_act_.clear();
77       ignore_action_ = true;
78       connectWidgetToAction(Menu_.gtkobj());
79       ignore_action_ = false;
80
81       // update state of the items
82       update();
83     }
84 }
85
86 void Menubar::Pimpl::callback(int action)
87 {
88   // Dispatch action OR record action to local variable (see connectWidgetToAction)
89   if (!ignore_action_) {
90       Pimpl::update();
91       owner_->getLyXFunc()->Dispatch(action);
92   } else
93       action_ = action;
94 }
95
96 void Menubar::Pimpl::composeUIInfo(string const & menu_name, vector<Gnome::UI::Info> & Menus)
97 {
98   if (!menubackend_->hasMenu(menu_name))
99     {
100       cout << "ERROR:composeUIInfo: Unknown menu `" << menu_name
101            << "'" << endl;
102       return;
103     }
104
105   Menu menu = menubackend_->getMenu(menu_name);
106
107   for (Menu::const_iterator i = menu.begin(); i != menu.end(); ++i)
108     {
109       MenuItem item = (*i);
110       switch(item.kind()) {
111
112       case MenuItem::Command: {
113         string label = item.label();
114         if (label.find(item.shortcut()) != string::npos)
115           label.insert(label.find(item.shortcut()), "_");
116
117         LyXFunc::func_status flag = owner_->getLyXFunc()->getStatus(item.action());
118
119         Gnome::UI::Info gitem;
120         SigC::Slot0<void> cback = bind<int>(slot(this, &Menubar::Pimpl::callback),item.action());
121
122         {
123           using namespace Gnome::MenuItems;
124           int ac = item.action();
125           kb_action action;
126           string argument;
127           if (lyxaction.isPseudoAction(ac))
128             action = lyxaction.retrieveActionArg(ac, argument);
129           else
130             action = static_cast<kb_action>(ac);
131
132           switch(action) {
133           case LFUN_MENUOPEN:
134             gitem = Open(cback);
135             break;
136           case LFUN_QUIT:
137             gitem = Exit(cback);
138             break;
139           case LFUN_CLOSEBUFFER:
140             gitem = Close(cback);
141             break;
142           case LFUN_MENUWRITE:
143             gitem = Save(cback);
144             break;
145           case LFUN_MENUWRITEAS:
146             gitem = SaveAs(cback);
147             break;
148           case LFUN_BUFFER_PRINT:
149             gitem = Print(cback);
150             break;
151           case LFUN_CUT:
152             gitem = Cut(cback);
153             break;
154           case LFUN_COPY:
155             gitem = Copy(cback);
156             break;
157           case LFUN_PASTE:
158             gitem = Paste(cback);
159             break;
160           case LFUN_UNDO:
161             gitem = Gnome::MenuItems::Undo(cback); // confused with class Undo
162             break;
163           case LFUN_REDO:
164             gitem = Redo(cback);
165             break;
166           case LFUN_DIALOG_PREFERENCES:
167             gitem = Preferences(cback);
168             break;
169           case LFUN_MENUNEW:
170             gitem = Gnome::UI::Item(Gnome::UI::Icon(GNOME_STOCK_MENU_NEW),
171                                     label, cback, lyxaction.helpText(item.action()));
172             break;
173           case LFUN_MENUNEWTMPLT:
174             gitem = Gnome::UI::Item(Gnome::UI::Icon(GNOME_STOCK_MENU_NEW), 
175                                     label, cback, lyxaction.helpText(item.action()));
176             break;
177           case LFUN_MENUSEARCH:
178             gitem = Gnome::UI::Item(Gnome::UI::Icon(GNOME_STOCK_MENU_SRCHRPL), 
179                                     label, cback, lyxaction.helpText(item.action()));
180             break;
181           case LFUN_SPELLCHECK:
182             gitem = Gnome::UI::Item(Gnome::UI::Icon(GNOME_STOCK_MENU_SPELLCHECK), 
183                                     label, cback, lyxaction.helpText(item.action()));
184             break;
185           default:
186             gitem = Gnome::UI::Item(label, cback, lyxaction.helpText(item.action()));
187             break;
188           }
189         }
190
191         // first handle optional entries.
192         if (item.optional() && (flag & LyXFunc::Disabled)) {
193             lyxerr[Debug::GUI] 
194                 << "Skipping optional item " << item.label() << endl; 
195             break;
196         }
197         if ((flag & LyXFunc::ToggleOn) || (flag & LyXFunc::ToggleOff))
198           gitem = Gnome::UI::ToggleItem(label, cback, lyxaction.helpText(item.action()));
199
200         Menus.push_back(gitem);
201         break;
202       }
203       
204       case MenuItem::Submenu: {
205         vector<Gnome::UI::Info> submenu;
206         string label = item.label();
207         if (label.find(item.shortcut()) != string::npos)
208           label.insert(label.find(item.shortcut()), "_");
209         composeUIInfo(item.submenu(), submenu);
210         Menus.push_back(Gnome::UI::Menu(label,submenu,label));
211         break;
212       }
213
214       case MenuItem::Separator: {
215         Menus.push_back(Gnome::UI::Separator());
216         break;
217       }
218
219       case MenuItem::Lastfiles: {
220         int ii = 1;
221         for (LastFiles::const_iterator cit = lastfiles->begin();
222              cit != lastfiles->end() && ii < 10; ++cit, ++ii)
223           {
224             int action = lyxaction.getPseudoAction(LFUN_FILE_OPEN, (*cit));
225             string label = "_" + tostr(ii) + ". " + MakeDisplayPath((*cit),30);
226
227             Menus.push_back(Gnome::UI::Item(label,
228                                             bind<int>(slot(this, &Menubar::Pimpl::callback), action),
229                                             label));
230           }
231         break;
232       }
233       
234       case MenuItem::Documents: {
235         std::vector<string> names = bufferlist.getFileNames();
236
237         for (std::vector<string>::const_iterator cit = names.begin();
238              cit != names.end() ; ++cit)
239           {
240             int action = lyxaction.getPseudoAction(LFUN_SWITCHBUFFER, *cit);
241             string label = MakeDisplayPath(*cit, 30);
242
243             Menus.push_back(Gnome::UI::Item(label,
244                                             bind<int>(slot(this, &Menubar::Pimpl::callback), action),
245                                             label));
246             
247           }
248         break;
249       }
250       }
251     }
252 }
253
254 void Menubar::Pimpl::connectWidgetToAction(GnomeUIInfo * guinfo)
255 {
256   for (; guinfo->type !=  GnomeUIInfoType(GNOME_APP_UI_ENDOFINFO); ++guinfo)
257     {
258       if ( guinfo->type == GnomeUIInfoType(GNOME_APP_UI_ITEM) ||
259            guinfo->type == GnomeUIInfoType(GNOME_APP_UI_TOGGLEITEM) )
260         {
261           (*((void(*)(void *, void *))(guinfo->moreinfo)))(NULL, guinfo->user_data);
262           wid_act_.push_back( GtkWidgetToAction( guinfo->widget, action_ ) );
263         }
264       else if ( guinfo->type == GnomeUIInfoType(GNOME_APP_UI_SUBTREE) ||
265                 guinfo->type == GnomeUIInfoType(GNOME_APP_UI_RADIOITEMS) )
266         {
267           connectWidgetToAction(  (GnomeUIInfo *)(guinfo->moreinfo) );
268         }
269     }
270 }
271
272 void Menubar::Pimpl::update()
273 {
274   vector<GtkWidgetToAction>::const_iterator end=wid_act_.end();
275   for (vector<GtkWidgetToAction>::const_iterator i = wid_act_.begin(); i != end; ++i)
276     {
277       GtkWidgetToAction wa = (*i);
278       LyXFunc::func_status flag = owner_->getLyXFunc()->getStatus(wa.action_);
279
280       if ( flag & (LyXFunc::Disabled | LyXFunc::Unknown) ) gtk_widget_set_sensitive(wa.widget_, false);
281       else gtk_widget_set_sensitive(wa.widget_, true);
282
283       if ( flag & LyXFunc::ToggleOn )
284         {
285           ignore_action_=true;
286           gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(wa.widget_), true);
287           ignore_action_=false;
288         }
289
290       if ( flag & LyXFunc::ToggleOff )
291         {
292           ignore_action_=true;
293           gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(wa.widget_), false);
294           ignore_action_=false;
295         }
296     }
297 }
298
299 void Menubar::Pimpl::openByName(string const &)
300 {
301 //    Pimpl::update();
302 }