]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/FormCitation.C
Some forgotten files and Anguses citation patch.
[lyx.git] / src / frontends / xforms / FormCitation.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 #include <algorithm>
14
15 #include "gettext.h"
16 #include FORMS_H_LOCATION
17 #include "xform_macros.h"
18 #include "FormCitation.h"
19 #include "Dialogs.h"
20 #include "LyXView.h"
21 #include "lyxfunc.h"
22 #include "insets/insetcite.h"
23 #include "form_citation.h"
24 #include "buffer.h"
25 #include "BufferView.h"
26 #include "support/filetools.h"
27
28 #ifdef __GNUG__
29 #pragma implementation
30 #endif
31
32 using std::vector;
33 using std::pair;
34 using std::max;
35 using std::min;
36 using std::find;
37
38 C_RETURNCB(FormCitation, WMHideCB)
39 C_GENERICCB(FormCitation, OKCB)
40 C_GENERICCB(FormCitation, CancelCB)
41 C_GENERICCB(FormCitation, InputCB)
42
43 FormCitation::FormCitation(LyXView * lv, Dialogs * d)
44         : dialog_(0), lv_(lv), d_(d), h_(0), inset_(0), dialogIsOpen(false)
45 {
46         // let the dialog be shown
47         // These are permanent connections so we won't bother
48         // storing a copy because we won't be disconnecting.
49         d->showCitation.connect(slot(this, &FormCitation::showInset));
50         d->createCitation.connect(slot(this, &FormCitation::createInset));
51         d->hideCitation.connect(slot(this, &FormCitation::hideInset));
52 }
53
54
55 FormCitation::~FormCitation()
56 {
57         free();
58 }
59
60
61 void FormCitation::build()
62 {
63   dialog_ = build_citation();
64 }
65
66
67 void FormCitation::showInset( InsetCitation * inset )
68 {
69         if( dialogIsOpen || inset == 0 ) return;
70
71         inset_ = inset;
72
73         textAfter = inset->getOptions();
74         updateCitekeys(inset->getContents());
75         show();
76 }
77
78
79 void FormCitation::createInset( string const & arg )
80 {
81         if( dialogIsOpen ) return;
82
83         string keys;
84         if (contains(arg, "|")) {
85                 keys = token(arg, '|', 0);
86                 textAfter = token(arg, '|', 1);
87         } else {
88                 keys = arg;
89                 textAfter.erase();
90         }
91
92         updateCitekeys(keys);
93         show();
94 }
95
96
97 void FormCitation::hideInset(InsetCitation * ti)
98 {
99         if (inset_ == ti) {
100                 inset_ = 0;
101                 hide();
102         }
103 }
104
105
106 void FormCitation::show()
107 {
108         if (!dialog_) {
109                 build();
110                 fl_set_form_atclose(dialog_->form_citation,
111                                     C_FormCitationWMHideCB, 0);
112         }
113
114         update();  // make sure its up-to-date
115
116         dialogIsOpen = true;
117         if (dialog_->form_citation->visible) {
118                 fl_raise_form(dialog_->form_citation);
119         } else {
120                 fl_show_form(dialog_->form_citation,
121                              FL_PLACE_MOUSE | FL_FREE_SIZE,
122                              FL_TRANSIENT,
123                              _("Citation"));
124                 u_ = d_->updateBufferDependent.
125                          connect(slot(this, &FormCitation::update));
126                 h_ = d_->hideBufferDependent.
127                          connect(slot(this, &FormCitation::hide));
128         }
129 }
130
131
132 void FormCitation::update()
133 {
134         bibkeys.clear();
135         bibkeysInfo.clear();
136
137         vector<pair<string,string> > blist =
138                 lv_->buffer()->getBibkeyList();
139
140         for( unsigned int i = 0; i < blist.size(); ++i ) {
141                 bibkeys.push_back(blist[i].first);
142                 bibkeysInfo.push_back(blist[i].second);
143         }
144
145         blist.clear();
146
147         fl_freeze_form( dialog_->form_citation );
148
149         updateBrowser( dialog_->bibBrsr, bibkeys );
150         updateBrowser( dialog_->citeBrsr, citekeys );
151         fl_clear_browser( dialog_->infoBrsr );
152
153         // No keys have been selected yet, so...
154         setBibButtons( OFF );
155         setCiteButtons( OFF );
156
157         int noKeys = max( bibkeys.size(), citekeys.size() );
158
159         // Place bounds, so that 4 <= noKeys <= 15
160         noKeys = max( 4, min(15, noKeys) );
161
162         // Re-size the form to accommodate the new browser size
163         int size = 20 * noKeys;
164         bool bibPresent = ( bibkeys.size() > 0 );
165         setSize( size, bibPresent );
166
167         fl_set_input( dialog_->textAftr, textAfter.c_str() );
168
169         fl_unfreeze_form( dialog_->form_citation );
170 }
171
172
173 void FormCitation::updateCitekeys( string const & keysIn )
174 {
175         citekeys.clear();
176
177         string tmp;
178         string keys = keysIn;
179         keys = frontStrip( split(keys, tmp, ',') );
180         while( !tmp.empty() ) {
181                 citekeys.push_back( tmp );
182                 keys = frontStrip( split(keys, tmp, ',') );
183         }
184 }
185
186
187 void FormCitation::updateBrowser( FL_OBJECT * browser,
188                                   vector<string> const & keys ) const
189 {
190         fl_clear_browser( browser );
191
192         for( unsigned int i = 0; i < keys.size(); ++i )
193                 fl_add_browser_line( browser, keys[i].c_str() );
194 }
195
196
197 void FormCitation::setBibButtons( State status ) const
198 {
199         switch (status) {
200         case ON:
201                 fl_activate_object( dialog_->addBtn );
202                 fl_set_object_lcol( dialog_->addBtn, FL_BLACK );
203                 break;
204
205         case OFF:
206                 fl_deactivate_object( dialog_->addBtn );
207                 fl_set_object_lcol( dialog_->addBtn, FL_INACTIVE );
208                 break;
209
210         default:
211                 break;
212         }
213 }
214
215
216 void FormCitation::setCiteButtons( State status ) const
217 {
218         switch( status ) {
219         case ON:
220         {
221                 fl_activate_object( dialog_->delBtn );
222                 fl_set_object_lcol( dialog_->delBtn, FL_BLACK );
223
224                 int sel = fl_get_browser( dialog_->citeBrsr );
225
226                 if( sel != 1 ) {
227                         fl_activate_object( dialog_->upBtn );
228                         fl_set_object_lcol( dialog_->upBtn, FL_BLACK );
229                 } else {
230                         fl_deactivate_object( dialog_->upBtn );
231                         fl_set_object_lcol( dialog_->upBtn, FL_INACTIVE );
232                 }
233
234                 if( sel != fl_get_browser_maxline(dialog_->citeBrsr)) {
235                         fl_activate_object( dialog_->downBtn );
236                         fl_set_object_lcol( dialog_->downBtn, FL_BLACK );
237                 } else {
238                         fl_deactivate_object( dialog_->downBtn );
239                         fl_set_object_lcol( dialog_->downBtn, FL_INACTIVE );
240                 }
241
242                 break;
243         }
244         case OFF:
245         {
246                 fl_deactivate_object( dialog_->delBtn );
247                 fl_set_object_lcol( dialog_->delBtn, FL_INACTIVE );
248
249                 fl_deactivate_object( dialog_->upBtn );
250                 fl_set_object_lcol( dialog_->upBtn, FL_INACTIVE );
251
252                 fl_deactivate_object( dialog_->downBtn );
253                 fl_set_object_lcol( dialog_->downBtn, FL_INACTIVE );
254         }
255         default:
256                 break;
257         }
258 }
259
260
261 void FormCitation::setSize( int brsrHeight, bool bibPresent ) const
262 {
263         int const infoHeight  = 110;
264         int const otherHeight = 140;
265         brsrHeight = max( brsrHeight, 175 );
266         int formHeight = brsrHeight + otherHeight;
267
268         if( bibPresent ) formHeight += infoHeight + 30;
269         fl_set_form_size( dialog_->form_citation, 430, formHeight );
270
271         // No resizing is alowed in the y-direction
272         fl_set_form_minsize( dialog_->form_citation, 430, formHeight );
273         fl_set_form_maxsize( dialog_->form_citation, 1000, formHeight );
274
275         int ypos = 0;
276         fl_set_object_geometry( dialog_->box,      0,   ypos, 430, formHeight );
277         ypos += 30;
278         fl_set_object_geometry( dialog_->citeBrsr, 10,  ypos, 180, brsrHeight );
279         fl_set_object_geometry( dialog_->bibBrsr,  240, ypos, 180, brsrHeight );
280         fl_set_object_geometry( dialog_->addBtn,   200, ypos,  30, 30 );
281         ypos += 35;
282         fl_set_object_geometry( dialog_->delBtn,   200, ypos,  30, 30 );
283         ypos += 35;
284         fl_set_object_geometry( dialog_->upBtn,    200, ypos,  30, 30 );
285         ypos += 35;
286         fl_set_object_geometry( dialog_->downBtn,  200, ypos,  30, 30 );
287
288         ypos = brsrHeight+30; // base of Citation/Bibliography browsers
289
290         // awaiting natbib support
291         fl_hide_object( dialog_->style );
292
293         if( bibPresent ) {
294                 ypos += 30;
295                 fl_set_object_geometry( dialog_->infoBrsr, 10, ypos, 410, infoHeight );
296                 fl_show_object( dialog_->infoBrsr );
297                 ypos += infoHeight;
298         }
299         else
300                 fl_hide_object( dialog_->infoBrsr );
301
302         ypos += 20;
303         // awaiting natbib support
304         fl_hide_object( dialog_->textBefore );
305
306         fl_set_object_position(dialog_->textAftr, 100, ypos);
307 //      fl_set_object_geometry( dialog_->textAftr, 100, ypos,   250, 30 );
308         fl_set_object_geometry( dialog_->ok,       230, ypos+50, 90, 30 );
309         fl_set_object_geometry( dialog_->cancel,   330, ypos+50, 90, 30 );
310 }
311
312
313 void FormCitation::input( State cb )
314 {
315         switch( cb ) {
316         case BIBBRSR:
317         {
318                 fl_deselect_browser( dialog_->citeBrsr );
319                 
320                 unsigned int sel = fl_get_browser( dialog_->bibBrsr );
321                 if( sel < 1 || sel > bibkeys.size() ) break;
322
323                 // Put into infoBrsr the additional info associated with
324                 // the selected bibBrsr key
325                 fl_clear_browser( dialog_->infoBrsr );
326                 fl_add_browser_line( dialog_->infoBrsr,
327                                      bibkeysInfo[sel-1].c_str() );
328
329                 // Highlight the selected bibBrsr key in citeBrsr if present
330                 vector<string>::iterator it =
331                         find( citekeys.begin(), citekeys.end(), bibkeys[sel-1] );
332
333                 if( it != citekeys.end() ) {
334                         int n = it - citekeys.begin();
335                         fl_select_browser_line( dialog_->citeBrsr, n+1 );
336                         fl_set_browser_topline( dialog_->citeBrsr, n+1 );
337                 }
338
339                 if( !lv_->buffer()->isReadonly() ) {
340                         if( it != citekeys.end() ) {
341                                 setBibButtons( OFF );
342                                 setCiteButtons( ON );
343                         } else {
344                                 setBibButtons( ON );
345                                 setCiteButtons( OFF );
346                         }
347                 }
348         }
349         break;
350         case CITEBRSR:
351         {
352                 unsigned int sel = fl_get_browser( dialog_->citeBrsr );
353                 if( sel < 1 || sel > citekeys.size() ) break;
354
355                 if( !lv_->buffer()->isReadonly() ) {
356                         setBibButtons( OFF );
357                         setCiteButtons( ON );
358                 }
359
360                 // Highlight the selected citeBrsr key in bibBrsr
361                 vector<string>::iterator it =
362                         find( bibkeys.begin(), bibkeys.end(), citekeys[sel-1] );
363
364                 if (it != bibkeys.end()) {
365                         int n = it - bibkeys.begin();
366                         fl_select_browser_line( dialog_->bibBrsr, n+1 );
367                         fl_set_browser_topline( dialog_->bibBrsr, n+1 );
368
369                         // Put into infoBrsr the additional info associated with
370                         // the selected citeBrsr key
371                         fl_clear_browser( dialog_->infoBrsr );
372                         fl_add_browser_line( dialog_->infoBrsr,
373                                              bibkeysInfo[n].c_str() );
374                 }
375         }
376         break;
377         case ADD:
378         {
379                 if( lv_->buffer()->isReadonly() ) break;
380
381                 unsigned int sel = fl_get_browser( dialog_->bibBrsr );
382                 if( sel < 1 || sel > bibkeys.size() ) break;
383
384                 // Add the selected bibBrsr key to citeBrsr
385                 fl_addto_browser( dialog_->citeBrsr,
386                                   bibkeys[sel-1].c_str() );
387                 citekeys.push_back( bibkeys[sel-1] );
388
389                 int n = citekeys.size();
390                 fl_select_browser_line( dialog_->citeBrsr, n );
391
392                 setBibButtons( OFF );
393                 setCiteButtons( ON );
394         }
395         break;
396         case DELETE:
397         {
398                 if( lv_->buffer()->isReadonly() ) break;
399
400                 unsigned int sel = fl_get_browser( dialog_->citeBrsr );
401                 if( sel < 1 || sel > citekeys.size() ) break;
402
403                 // Remove the selected key from citeBrsr
404                 fl_delete_browser_line( dialog_->citeBrsr, sel ) ;
405                 citekeys.erase( citekeys.begin() + sel-1 );
406
407                 setBibButtons( ON );
408                 setCiteButtons( OFF );
409         }
410         break;
411         case UP:
412         {
413                 if( lv_->buffer()->isReadonly() ) break;
414
415                 unsigned int sel = fl_get_browser( dialog_->citeBrsr );
416                 if( sel < 2 || sel > citekeys.size() ) break;
417
418                 // Move the selected key up one line
419                 vector<string>::iterator it = citekeys.begin() + sel-1;
420                 string tmp = *it;
421
422                 fl_delete_browser_line( dialog_->citeBrsr, sel );
423                 citekeys.erase( it );
424
425                 fl_insert_browser_line( dialog_->citeBrsr, sel-1, tmp.c_str() );
426                 fl_select_browser_line( dialog_->citeBrsr, sel-1 );
427                 citekeys.insert( it-1, tmp );
428                 setCiteButtons( ON );
429         }
430         break;
431         case DOWN:
432         {
433                 if( lv_->buffer()->isReadonly() ) break;
434
435                 unsigned int sel = fl_get_browser( dialog_->citeBrsr );
436                 if( sel < 1 || sel > citekeys.size()-1 ) break;
437
438                 // Move the selected key down one line
439                 vector<string>::iterator it = citekeys.begin() + sel-1;
440                 string tmp = *it;
441
442                 fl_delete_browser_line( dialog_->citeBrsr, sel );
443                 citekeys.erase( it );
444
445                 fl_insert_browser_line( dialog_->citeBrsr, sel+1, tmp.c_str() );
446                 fl_select_browser_line( dialog_->citeBrsr, sel+1 );
447                 citekeys.insert( it+1, tmp );
448                 setCiteButtons( ON );
449         }
450         break;
451         default:
452                 break;
453         }
454 }
455
456
457 void FormCitation::apply()
458 {
459         if( lv_->buffer()->isReadonly() ) return;
460
461         string tmp;
462         for( unsigned int i = 0; i < citekeys.size(); ++i ) {
463                 if (i > 0) tmp += ", ";
464                 tmp += citekeys[i];
465         }
466
467         textAfter = fl_get_input(dialog_->textAftr);
468
469         if( inset_ != 0 )
470         {
471                 inset_->setContents( tmp );
472                 inset_->setOptions( textAfter );
473                 lv_->view()->updateInset( inset_, true );
474         } else {
475                 string arg = tmp + '|' + textAfter;
476                 lv_->getLyXFunc()->Dispatch( LFUN_INSERT_CITATION, arg.c_str() );
477         }
478 }
479
480
481 void FormCitation::hide()
482 {
483         if (dialog_
484             && dialog_->form_citation
485             && dialog_->form_citation->visible) {
486                 fl_hide_form(dialog_->form_citation);
487                 u_.disconnect();
488                 h_.disconnect();
489         }
490
491         // free up the dialog for another inset
492         inset_ = 0;
493         dialogIsOpen = false;
494 }
495
496
497 void FormCitation::free()
498 {
499         // we don't need to delete u and h here because
500         // hide() does that after disconnecting.
501         if (dialog_) {
502                 if (dialog_->form_citation
503                     && dialog_->form_citation->visible) {
504                         hide();
505                 }
506                 fl_free_form(dialog_->form_citation);
507                 delete dialog_;
508                 dialog_ = 0;
509         }
510 }
511
512
513 int FormCitation::WMHideCB(FL_FORM * form, void *)
514 {
515         // Ensure that the signals (u and h) are disconnected even if the
516         // window manager is used to close the dialog.
517         FormCitation * pre = static_cast<FormCitation*>(form->u_vdata);
518         pre->hide();
519         return FL_CANCEL;
520 }
521
522
523 void FormCitation::OKCB(FL_OBJECT * ob, long)
524 {
525         FormCitation * pre = static_cast<FormCitation*>(ob->form->u_vdata);
526         pre->apply();
527         pre->hide();
528 }
529
530
531 void FormCitation::CancelCB(FL_OBJECT * ob, long)
532 {
533         FormCitation * pre = static_cast<FormCitation*>(ob->form->u_vdata);
534         pre->hide();
535 }
536
537
538 void FormCitation::InputCB(FL_OBJECT * ob, long data)
539 {
540         FormCitation * pre = static_cast<FormCitation*>(ob->form->u_vdata);
541         pre->input( static_cast<FormCitation::State>(data) );
542 }