]> git.lyx.org Git - lyx.git/blob - src/frontends/gnome/Menubar_pimpl.C
Marko's GNOME patch, some modifications to this, some fixes.
[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 LyXAction lyxaction;
45 extern BufferList bufferlist;
46 extern LastFiles * lastfiles; 
47
48
49
50 Menubar::Pimpl::Pimpl(LyXView * view, MenuBackend const & mb) 
51   : owner_(view), menubackend_(&mb), ignore_action_(false)
52 {
53         // Should we do something here?
54 }
55
56 Menubar::Pimpl::~Pimpl() 
57 {
58         // Should we do something here?
59 }
60
61 void Menubar::Pimpl::set(string const & menu_name) 
62 {
63   // if (current_menu_name_ != menu_name)  // disabled until Lastfiles and Documents are added dynamically to menu
64     {
65       current_menu_name_ = menu_name;
66       // compose new menu
67       vector<Gnome::UI::Info> menus;
68       composeUIInfo(current_menu_name_, menus);
69
70       // set menu
71       Menu_ = menus;
72       mainAppWin->set_menu(Menu_);
73
74       // connect all menu items to correspoding action
75       wid_act_.clear();
76       ignore_action_ = true;
77       connectWidgetToAction(Menu_.gtkobj());
78       ignore_action_ = false;
79
80       // update state of the items
81       update();
82     }
83 }
84
85 void Menubar::Pimpl::callback(int action)
86 {
87   // Dispatch action OR record action to local variable (see connectWidgetToAction)
88   if (!ignore_action_) {
89       Pimpl::update();
90       owner_->getLyXFunc()->Dispatch(action);
91   } else
92       action_ = action;
93 }
94
95 void Menubar::Pimpl::composeUIInfo(string const & menu_name, vector<Gnome::UI::Info> & Menus)
96 {
97   if (!menubackend_->hasMenu(menu_name))
98     {
99       cout << "ERROR:composeUIInfo: Unknown menu `" << menu_name
100            << "'" << endl;
101       return;
102     }
103
104   Menu menu = menubackend_->getMenu(menu_name);
105
106   for (Menu::const_iterator i = menu.begin(); i != menu.end(); ++i)
107     {
108       MenuItem item = (*i);
109       switch(item.kind()) {
110
111       case MenuItem::Command: {
112         string label = item.label();
113         if (label.find(item.shortcut()) != string::npos)
114           label.insert(label.find(item.shortcut()), "_");
115
116         LyXFunc::func_status flag = owner_->getLyXFunc()->getStatus(item.action());
117
118         Gnome::UI::Info gitem;
119         SigC::Slot0<void> cback = bind<int>(slot(this, &Menubar::Pimpl::callback),item.action());
120
121         {
122           using namespace Gnome::MenuItems;
123           string actionname = lyxaction.getActionName(item.action());
124           if ( actionname ==  "buffer-open") gitem = Open(cback);
125           else if ( actionname ==  "lyx-quit") gitem = Exit(cback);
126           else if ( actionname ==  "buffer-close") gitem = Close(cback);
127           else if ( actionname ==  "buffer-write") gitem = Save(cback);
128           else if ( actionname ==  "buffer-write-as") gitem = SaveAs(cback);
129           else if ( actionname ==  "buffer-print") gitem = Print(cback);
130           else if ( actionname ==  "cut") gitem = Cut(cback);
131           else if ( actionname ==  "copy") gitem = Copy(cback);
132           else if ( actionname ==  "paste") gitem = Paste(cback);
133           else if ( actionname ==  "undo") gitem = Gnome::MenuItems::Undo(cback); // confused with class Undo
134           else if ( actionname ==  "redo") gitem = Redo(cback);
135           else if ( actionname ==  "dialog-preferences") gitem = Preferences(cback);
136           else if ( actionname ==  "buffer-new")
137             gitem = Gnome::UI::Item(Gnome::UI::Icon(GNOME_STOCK_MENU_NEW),
138                                     label, cback, lyxaction.helpText(item.action()));
139           else if ( actionname ==  "buffer-new-template")
140             gitem = Gnome::UI::Item(Gnome::UI::Icon(GNOME_STOCK_MENU_NEW), 
141                                     label, cback, lyxaction.helpText(item.action()));
142           else if ( actionname ==  "find-replace" )
143             gitem = Gnome::UI::Item(Gnome::UI::Icon(GNOME_STOCK_MENU_SRCHRPL), 
144                                     label, cback, lyxaction.helpText(item.action()));
145           else if ( actionname ==  "spellchecker" )
146             gitem = Gnome::UI::Item(Gnome::UI::Icon(GNOME_STOCK_MENU_SPELLCHECK), 
147                                     label, cback, lyxaction.helpText(item.action()));
148 //        else if ( actionname ==  "" )
149 //          gitem = Gnome::UI::Item(Gnome::UI::Icon(), 
150 //                                  label, cback, lyxaction.helpText(item.action()));
151           else gitem = Gnome::UI::Item(label, cback, lyxaction.helpText(item.action()));
152         }
153
154         // first handle optional entries.
155         if (item.optional() && (flag & LyXFunc::Disabled)) {
156             lyxerr[Debug::GUI] 
157                 << "Skipping optional item " << item.label() << endl; 
158             break;
159         }
160         if ((flag & LyXFunc::ToggleOn) || (flag & LyXFunc::ToggleOff))
161           gitem = Gnome::UI::ToggleItem(label, cback, lyxaction.helpText(item.action()));
162         
163         Menus.push_back(gitem);
164         break;
165       }
166       
167       case MenuItem::Submenu: {
168         vector<Gnome::UI::Info> submenu;
169         string label = item.label();
170         if (label.find(item.shortcut()) != string::npos)
171           label.insert(label.find(item.shortcut()), "_");
172         composeUIInfo(item.submenu(), submenu);
173         Menus.push_back(Gnome::UI::Menu(label,submenu,label));
174         break;
175       }
176
177       case MenuItem::Separator: {
178         Menus.push_back(Gnome::UI::Separator());
179         break;
180       }
181
182       case MenuItem::Lastfiles: {
183         int ii = 1;
184         for (LastFiles::const_iterator cit = lastfiles->begin();
185              cit != lastfiles->end() && ii < 10; ++cit, ++ii)
186           {
187             int action = lyxaction.getPseudoAction(LFUN_FILE_OPEN, (*cit));
188             string label = "_" + tostr(ii) + ". " + MakeDisplayPath((*cit),30);
189
190             Menus.push_back(Gnome::UI::Item(label,
191                                             bind<int>(slot(this, &Menubar::Pimpl::callback), action),
192                                             label));
193           }
194         break;
195       }
196       
197       case MenuItem::Documents: {
198         std::vector<string> names = bufferlist.getFileNames();
199
200         for (std::vector<string>::const_iterator cit = names.begin();
201              cit != names.end() ; ++cit)
202           {
203             int action = lyxaction.getPseudoAction(LFUN_SWITCHBUFFER, *cit);
204             string label = MakeDisplayPath(*cit, 30);
205
206             Menus.push_back(Gnome::UI::Item(label,
207                                             bind<int>(slot(this, &Menubar::Pimpl::callback), action),
208                                             label));
209             
210           }
211         break;
212       }
213       }
214     }
215 }
216
217 void Menubar::Pimpl::connectWidgetToAction(GnomeUIInfo * guinfo)
218 {
219   for (; guinfo->type !=  GnomeUIInfoType(GNOME_APP_UI_ENDOFINFO); ++guinfo)
220     {
221       if ( guinfo->type == GnomeUIInfoType(GNOME_APP_UI_ITEM) ||
222            guinfo->type == GnomeUIInfoType(GNOME_APP_UI_TOGGLEITEM) )
223         {
224           (*((void(*)(void *, void *))(guinfo->moreinfo)))(NULL, guinfo->user_data);
225           wid_act_.push_back( GtkWidgetToAction( guinfo->widget, action_ ) );
226         }
227       else if ( guinfo->type == GnomeUIInfoType(GNOME_APP_UI_SUBTREE) ||
228                 guinfo->type == GnomeUIInfoType(GNOME_APP_UI_RADIOITEMS) )
229         {
230           connectWidgetToAction(  (GnomeUIInfo *)(guinfo->moreinfo) );
231         }
232     }
233 }
234
235 void Menubar::Pimpl::update()
236 {
237   vector<GtkWidgetToAction>::const_iterator end=wid_act_.end();
238   for (vector<GtkWidgetToAction>::const_iterator i = wid_act_.begin(); i != end; ++i)
239     {
240       GtkWidgetToAction wa = (*i);
241       LyXFunc::func_status flag = owner_->getLyXFunc()->getStatus(wa.action_);
242
243       if ( flag & (LyXFunc::Disabled | LyXFunc::Unknown) ) gtk_widget_set_sensitive(wa.widget_, false);
244       else gtk_widget_set_sensitive(wa.widget_, true);
245
246       if ( flag & LyXFunc::ToggleOn )
247         {
248           ignore_action_=true;
249           gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(wa.widget_), true);
250           ignore_action_=false;
251         }
252
253       if ( flag & LyXFunc::ToggleOff )
254         {
255           ignore_action_=true;
256           gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(wa.widget_), false);
257           ignore_action_=false;
258         }
259     }
260 }
261
262 void Menubar::Pimpl::openByName(string const & name)
263 {
264 //    Pimpl::update();
265 }