]> git.lyx.org Git - lyx.git/blob - src/frontends/gnome/FormRef.C
More preference work from Angus
[lyx.git] / src / frontends / gnome / FormRef.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
12 #include <config.h>
13
14 #ifdef __GNUG__
15 #pragma implementation
16 #endif
17
18
19 #include "gettext.h"
20 #include "Dialogs.h"
21 #include "FormRef.h"
22 #include "LyXView.h"
23 #include "buffer.h"
24 #include "lyxfunc.h"
25
26 #include <gtk--/box.h>
27 #include <gtk--/buttonbox.h>
28 #include <gtk--/alignment.h>
29 #include <gtk--/separator.h>
30 #include <gtk--/label.h>
31 #include <gtk--/scrolledwindow.h>
32 #include <gtk--/entry.h>
33 #include <gtk--/table.h>
34
35 #include <gtk--/menu.h>
36 #include <gtk--/menuitem.h>
37
38 // temporary solution for LyXView
39 #include "mainapp.h"
40 extern GLyxAppWin * mainAppWin;
41
42 using SigC::bind;
43
44 // configuration keys
45 static string const CONF_ENTRY_NAME("FormRef_name");
46
47 // goto button labels
48 static string const GOTO_REF_LABEL(N_("Goto reference"));
49 static string const GOTO_BACK_LABEL(N_("Go back"));
50
51 FormRef::FormRef(LyXView * lv, Dialogs * d)
52         : lv_(lv), d_(d), inset_(0), u_(0), h_(0), ih_(0), dialog_(NULL)
53 {
54   // let the dialog be shown
55   // These are permanent connections so we won't bother
56   // storing a copy because we won't be disconnecting.
57   d->showRef.connect(slot(this, &FormRef::showInset));
58   d->createRef.connect(slot(this, &FormRef::createInset));
59 }
60
61
62 FormRef::~FormRef()
63 {
64   hide();
65 }
66
67 void FormRef::showInset( InsetCommand * const inset )
68 {
69   if( dialog_!=NULL || inset == 0 ) return;
70   
71   inset_ = inset;
72   ih_ = inset_->hide.connect(slot(this, &FormRef::hide));
73
74   acttype_ = EDIT;
75   
76   params = inset->params();
77   showStageAction();
78 }
79
80
81 void FormRef::createInset( string const & arg )
82 {
83   if( dialog_!=NULL ) return;
84   
85   acttype_ = INSERT;
86
87   params.setFromString( arg );
88
89   refs = lv_->buffer()->getLabelList();
90
91   if (refs.empty()) showStageError(_("*** No labels found in document ***"));
92   else showStageSelect();
93 }
94
95 void FormRef::showStageError(string const & mess)
96 {
97   if (!dialog_)
98     {
99       using namespace Gtk::Box_Helpers;
100
101       Gtk::Alignment * alig = manage( new Gtk::Alignment(0.5, 0.5, 0, 0) );
102       Gtk::Box * box = manage( new Gtk::HBox() );
103
104       b_cancel = Gtk::wrap( GTK_BUTTON( gnome_stock_button(GNOME_STOCK_BUTTON_CANCEL) ) );
105
106       box->set_spacing(4);
107
108       box->children().push_back(Element(*manage( new Gtk::Label(mess) ), false, false));
109       box->children().push_back(Element(*manage(new Gtk::VSeparator()), false, false));
110       box->children().push_back(Element(*b_cancel, false, false));
111
112       alig->add(*box);
113
114       // packing dialog to main window
115       dialog_ = alig;
116       mainAppWin->add_action(*dialog_, _(" Reference "));
117
118       // setting focus
119       gtk_widget_grab_focus (GTK_WIDGET(b_cancel->gtkobj()));
120
121       // connecting signals
122       b_cancel->clicked.connect(slot(mainAppWin, &GLyxAppWin::remove_action));
123       dialog_->destroy.connect(slot(this, &FormRef::free));
124
125       u_ = d_->updateBufferDependent.connect(slot(this, &FormRef::update));
126       h_ = d_->hideBufferDependent.connect(slot(this, &FormRef::hide));
127     }
128 }
129       
130
131 void FormRef::showStageSelect()
132 {
133   if (!dialog_)
134     {
135       using namespace Gtk::Box_Helpers;
136
137       Gtk::Box * mbox = manage( new Gtk::HBox() );
138       Gtk::ButtonBox * bbox = manage( new Gtk::VButtonBox() );
139       Gtk::Alignment * alig = manage( new Gtk::Alignment(0.5, 0.5, 0, 0) );
140       Gtk::ScrolledWindow * sw = manage( new Gtk::ScrolledWindow() );
141
142       // constructing CList
143       vector<string> colnames;
144       colnames.push_back("INVISIBLE");
145       list_ = manage( new Gtk::CList(colnames) );
146
147       // populating CList
148       vector<string> r;
149       vector<string>::const_iterator end = refs.end();
150       for (vector<string>::const_iterator it = refs.begin(); it != end; ++it)
151         {
152           r.clear();
153           r.push_back(*(it));
154           list_->rows().push_back(r);
155         }
156       list_->rows()[0].select(); // there is always at least one item. otherwise we go to stateError
157       
158       b_ok = Gtk::wrap( GTK_BUTTON( gnome_stock_button(GNOME_STOCK_BUTTON_OK) ) );
159       b_cancel = Gtk::wrap( GTK_BUTTON( gnome_stock_button(GNOME_STOCK_BUTTON_CANCEL) ) );
160
161       // policy
162       list_->set_selection_mode(GTK_SELECTION_BROWSE); // this ensures that we have always item selected
163       list_->column_titles_hide();
164
165       sw->set_policy(GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
166
167       // set up spacing
168       mbox->set_spacing(2);
169       bbox->set_spacing(4);
170
171       // pack widgets
172       sw->add(*list_);
173
174       bbox->children().push_back(Element(*b_ok, false, false));
175       bbox->children().push_back(Element(*b_cancel, false, false));
176
177       alig->add( *bbox );
178       
179       mbox->children().push_back(Element(*sw, true, true));
180       mbox->children().push_back(Element(*manage(new Gtk::VSeparator()), false, false));
181       mbox->children().push_back(Element(*alig, false, false));
182       
183       // packing dialog to main window
184       dialog_ = mbox;
185       mainAppWin->add_action(*dialog_, _(" Reference: Select reference "), true);
186
187       // setting focus
188       GTK_WIDGET_SET_FLAGS (GTK_WIDGET(b_ok->gtkobj()), GTK_CAN_DEFAULT);
189       GTK_WIDGET_SET_FLAGS (GTK_WIDGET(b_cancel->gtkobj()), GTK_CAN_DEFAULT);
190       GTK_WIDGET_SET_FLAGS (GTK_WIDGET(list_->gtkobj()), GTK_CAN_DEFAULT);
191       gtk_widget_grab_focus (GTK_WIDGET(list_->gtkobj()));
192       gtk_widget_grab_default (GTK_WIDGET(b_ok->gtkobj()));
193
194       // connecting signals
195       b_ok->clicked.connect(slot(this, &FormRef::moveFromSelectToAction));
196       b_cancel->clicked.connect(slot(mainAppWin, &GLyxAppWin::remove_action));
197
198       dialog_->destroy.connect(slot(this, &FormRef::free));
199
200       u_ = d_->updateBufferDependent.connect(slot(this, &FormRef::update));
201       h_ = d_->hideBufferDependent.connect(slot(this, &FormRef::hide));
202     }
203 }
204
205 void FormRef::moveFromSelectToAction()
206 {
207   params.setContents( list_->selection()[0][0].get_text() );
208
209   // moves to stage "search"
210   mainAppWin->remove_action();
211   showStageAction();
212 }
213
214 void FormRef::showStageAction()
215 {
216   if (!dialog_)
217     {
218       using namespace Gtk::Box_Helpers;
219
220       Gtk::Table * table = manage( new Gtk::Table(2, 2, FALSE) );
221       Gtk::Box * mbox = manage( new Gtk::HBox() );
222       Gtk::ButtonBox * bbox = manage( new Gtk::HButtonBox() );
223
224       b_goto = manage(new Gnome::PixButton(GOTO_REF_LABEL, GNOME_STOCK_PIXMAP_JUMP_TO));
225       gototype_ = GOREF;
226       
227       name_ = manage( new Gnome::Entry() );
228
229       choice_ = manage( new Gtk::OptionMenu() );
230       
231       b_ok = Gtk::wrap( GTK_BUTTON( gnome_stock_button(GNOME_STOCK_BUTTON_OK) ) );
232       b_cancel = Gtk::wrap( GTK_BUTTON( gnome_stock_button(GNOME_STOCK_BUTTON_CANCEL) ) );
233       
234       // set up spacing
235       table->set_row_spacings(4);
236       table->set_col_spacings(4);
237
238       mbox->set_spacing(4);
239
240       bbox->set_spacing(4);
241       bbox->set_layout(GTK_BUTTONBOX_SPREAD);
242
243       // configure entries
244       name_->set_history_id(CONF_ENTRY_NAME);
245       name_->set_max_saved(10);
246       name_->load_history();
247       name_->set_use_arrows_always(true);
248       if( lv_->buffer()->isLatex() ) name_->set_sensitive(false); // Name is irrelevant to LaTeX documents
249
250       // fill choice
251       Gtk::Menu * menu = manage( new Gtk::Menu() );
252       Gtk::MenuItem * e;
253       
254       e = manage( new Gtk::MenuItem(_("Ref")) );
255       e->activate.connect(bind<Type>(slot(this, &FormRef::changeType), REF));
256       e->show();
257       menu->append( *e );
258
259       e = manage( new Gtk::MenuItem(_("Page")) );
260       e->activate.connect(bind<Type>(slot(this, &FormRef::changeType), PAGEREF));
261       e->show();
262       menu->append( *e );
263
264       e = manage( new Gtk::MenuItem(_("TextRef")) );
265       e->activate.connect(bind<Type>(slot(this, &FormRef::changeType), VREF));
266       e->show();
267       menu->append( *e );
268
269       e = manage( new Gtk::MenuItem(_("TextPage")) );
270       e->activate.connect(bind<Type>(slot(this, &FormRef::changeType), VPAGEREF));
271       e->show();
272       menu->append( *e );
273
274       e = manage( new Gtk::MenuItem(_("PrettyRef")) );
275       e->activate.connect(bind<Type>(slot(this, &FormRef::changeType), PRETTYREF));
276       e->show();
277       menu->append( *e );
278
279       choice_-> set_menu ( *menu );
280
281       switch ( getType() ) {
282       case REF:         { choice_-> set_history(0); break; }
283       case PAGEREF:     { choice_-> set_history(1); break; }
284       case VREF:        { choice_-> set_history(2); break; }
285       case VPAGEREF:    { choice_-> set_history(3); break; }
286       case PRETTYREF:   { choice_-> set_history(4); break; }
287       }
288
289       changeType( getType() );
290       
291       // filling widgets with data
292       name_->get_entry()->set_text(params.getOptions());
293       
294
295       // pack widgets
296       bbox->children().push_back(Element(*b_goto, false, false));
297       bbox->children().push_back(Element(*b_ok, false, false));
298       bbox->children().push_back(Element(*b_cancel, false, false));
299       
300       table->attach( *manage( new Gtk::Label(_("Type:")) ), 0, 1, 0, 1, 0, 0 );
301       table->attach( *manage( new Gtk::Label(_("Name:")) ), 0, 1, 1, 2, 0, 0 );
302       table->attach( *choice_, 1, 2, 0, 1 );
303       table->attach( *name_, 1, 2, 1, 2 );
304
305       mbox->children().push_back(Element(*table, true, true));
306       mbox->children().push_back(Element(*manage( new Gtk::VSeparator() ), false, false ));
307       mbox->children().push_back(Element(*bbox, false, false));
308
309       // packing dialog to main window
310       dialog_ = mbox;
311       mainAppWin->add_action(*dialog_, string(_(" Reference: ")) + params.getContents() + string(" "));
312
313       // setting focus
314       GTK_WIDGET_SET_FLAGS (GTK_WIDGET(b_cancel->gtkobj()), GTK_CAN_DEFAULT);
315       GTK_WIDGET_SET_FLAGS (GTK_WIDGET(b_ok->gtkobj()), GTK_CAN_DEFAULT);
316       GTK_WIDGET_SET_FLAGS (GTK_WIDGET(b_goto->gtkobj()), GTK_CAN_DEFAULT);
317       gtk_widget_grab_default (GTK_WIDGET(b_ok->gtkobj()));
318       gtk_widget_grab_focus (GTK_WIDGET(choice_->gtkobj()));
319
320       // connecting signals
321       b_cancel->clicked.connect(slot(mainAppWin, &GLyxAppWin::remove_action));
322       b_ok->clicked.connect(slot(this, &FormRef::apply));
323       b_goto->clicked.connect(slot(this, &FormRef::gotoRef));
324
325       dialog_->destroy.connect(slot(this, &FormRef::free));
326
327       u_ = d_->updateBufferDependent.connect(slot(this, &FormRef::update));
328       h_ = d_->hideBufferDependent.connect(slot(this, &FormRef::hide));
329     }
330 }
331
332 void FormRef::update(bool buffchanged)
333 {
334   if (buffchanged) hide();
335 }
336
337 void FormRef::hide()
338 {
339   if (dialog_!=NULL) mainAppWin->remove_action();
340 }
341
342 void FormRef::free()
343 {
344   if (dialog_!=NULL)
345     {
346       dialog_ = NULL;
347       u_.disconnect();
348       h_.disconnect();
349       inset_ = 0;
350       ih_.disconnect();
351     }
352 }
353
354 void FormRef::gotoRef()
355 {
356   switch (gototype_) {
357   case GOREF:
358     {
359       lv_->getLyXFunc()-> Dispatch(LFUN_REF_GOTO, params.getContents());
360
361       gototype_ = GOBACK;
362       b_goto->set_text(GOTO_BACK_LABEL);
363       break;
364     }
365   case GOBACK:
366     {
367       lv_->getLyXFunc()->Dispatch(LFUN_REF_BACK);
368
369       gototype_ = GOREF;
370       b_goto->set_text(GOTO_REF_LABEL);
371       break;
372     }
373   }
374 }
375
376 void FormRef::apply()
377 {
378   if ( lv_->buffer()->isReadonly() )
379     return;
380   
381   params.setCmdName(getName(reftype_));
382   params.setOptions(name_->get_entry()->get_text());
383   
384   if (inset_ != 0)
385     {
386       // Only update if contents have changed
387       if (params != inset_->params())
388         {
389           inset_->setParams(params);
390           lv_->view()->updateInset(inset_, true);
391         }
392     }
393   else
394     {
395       lv_->getLyXFunc()->Dispatch(LFUN_REF_INSERT,
396                                   params.getAsString());
397     }
398
399   // save configuration
400   name_->save_history();
401   
402   // hide the dialog
403   hide();
404 }
405
406 void FormRef::changeType(Type t)
407 {
408   reftype_ = t;
409 }
410
411 FormRef::Type FormRef::getType() const
412 {
413   Type type;
414   
415   if( params.getCmdName() == "ref" )
416     type = REF;
417   
418   else if( params.getCmdName() == "pageref" )
419     type = PAGEREF;
420   
421   else if( params.getCmdName() == "vref" )
422     type = VREF;
423   
424   else if( params.getCmdName() == "vpageref" )
425     type = VPAGEREF;
426   
427   else
428     type = PRETTYREF;
429   
430   return type;
431 }
432
433
434 string FormRef::getName( Type type ) const
435 {
436   string name;
437   
438   switch( type ) {
439   case REF:
440     name = "ref";
441     break;
442   case PAGEREF:
443     name = "pageref";
444     break;
445   case VREF:
446     name = "vref";
447     break;
448   case VPAGEREF:
449     name = "vpageref";
450     break;
451   case PRETTYREF:
452     name = "prettyref";
453     break;
454   }
455   
456   return name;
457 }