]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/FormCitation.C
FormBase extends its reach into the codebase and gains a ButtonController
[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
14 #include FORMS_H_LOCATION
15
16 #include <algorithm>
17
18 #ifdef __GNUG__
19 #pragma implementation
20 #endif
21
22
23 #include "Dialogs.h"
24 #include "FormCitation.h"
25 #include "LyXView.h"
26 #include "buffer.h"
27 #include "form_citation.h"
28 #include "lyxfunc.h"
29 #include "support/filetools.h"
30
31 using std::vector;
32 using std::pair;
33 using std::max;
34 using std::min;
35 using std::find;
36
37 static int min_wform;
38
39 FormCitation::FormCitation(LyXView * lv, Dialogs * d)
40         : FormCommand(lv, d, _("Citation")), dialog_(0)
41 {
42         // let the dialog be shown
43         // These are permanent connections so we won't bother
44         // storing a copy because we won't be disconnecting.
45         d->showCitation.connect(slot(this, &FormCitation::showInset));
46         d->createCitation.connect(slot(this, &FormCitation::createInset));
47 }
48
49
50 FormCitation::~FormCitation()
51 {
52         delete dialog_;
53 }
54
55
56 void FormCitation::clearStore()
57 {
58         citekeys.clear();
59         bibkeys.clear();
60         bibkeysInfo.clear();
61 }
62
63
64 void FormCitation::build()
65 {
66         dialog_ = build_citation();
67         min_wform = dialog_->form->w;
68 }
69
70
71 FL_FORM * const FormCitation::form() const
72 {
73         if( dialog_ ) // no need to test for dialog_->form
74                 return dialog_->form;
75         else
76                 return 0;
77 }
78
79
80 void FormCitation::update()
81 {
82         bibkeys.clear();
83         bibkeysInfo.clear();
84
85         vector<pair<string,string> > blist =
86                 lv_->buffer()->getBibkeyList();
87
88         for( unsigned int i = 0; i < blist.size(); ++i ) {
89                 bibkeys.push_back(blist[i].first);
90                 bibkeysInfo.push_back(blist[i].second);
91         }
92         blist.clear();
93
94         citekeys.clear();
95         string tmp, keys( params.getContents() );
96         keys = frontStrip( split(keys, tmp, ',') );
97         while( !tmp.empty() ) {
98                 citekeys.push_back( tmp );
99                 keys = frontStrip( split(keys, tmp, ',') );
100         }
101
102         updateBrowser( dialog_->bibBrsr,  bibkeys );
103         updateBrowser( dialog_->citeBrsr, citekeys );
104         fl_clear_browser( dialog_->infoBrsr );
105
106         // No keys have been selected yet, so...
107         setBibButtons( OFF );
108         setCiteButtons( OFF );
109
110         int noKeys = max( bibkeys.size(), citekeys.size() );
111
112         // Place bounds, so that 4 <= noKeys <= 10
113         noKeys = max( 4, min(10, noKeys) );
114
115         // Re-size the form to accommodate the new browser size
116         int size = 20 * noKeys;
117         bool bibPresent = ( bibkeys.size() > 0 );
118         setSize( size, bibPresent );
119
120         fl_set_input( dialog_->textAftr, params.getOptions().c_str() );
121 }
122
123
124 void FormCitation::updateBrowser( FL_OBJECT * browser,
125                                   vector<string> const & keys ) const
126 {
127         fl_clear_browser( browser );
128
129         for( unsigned int i = 0; i < keys.size(); ++i )
130                 fl_add_browser_line( browser, keys[i].c_str() );
131 }
132
133
134 void FormCitation::setBibButtons( State status ) const
135 {
136         switch (status) {
137         case ON:
138                 fl_activate_object( dialog_->addBtn );
139                 fl_set_object_lcol( dialog_->addBtn, FL_BLACK );
140                 break;
141
142         case OFF:
143                 fl_deactivate_object( dialog_->addBtn );
144                 fl_set_object_lcol( dialog_->addBtn, FL_INACTIVE );
145                 break;
146
147         default:
148                 break;
149         }
150 }
151
152
153 void FormCitation::setCiteButtons( State status ) const
154 {
155         switch( status ) {
156         case ON:
157         {
158                 fl_activate_object( dialog_->delBtn );
159                 fl_set_object_lcol( dialog_->delBtn, FL_BLACK );
160
161                 int sel = fl_get_browser( dialog_->citeBrsr );
162
163                 if( sel != 1 ) {
164                         fl_activate_object( dialog_->upBtn );
165                         fl_set_object_lcol( dialog_->upBtn, FL_BLACK );
166                 } else {
167                         fl_deactivate_object( dialog_->upBtn );
168                         fl_set_object_lcol( dialog_->upBtn, FL_INACTIVE );
169                 }
170
171                 if( sel != fl_get_browser_maxline(dialog_->citeBrsr)) {
172                         fl_activate_object( dialog_->downBtn );
173                         fl_set_object_lcol( dialog_->downBtn, FL_BLACK );
174                 } else {
175                         fl_deactivate_object( dialog_->downBtn );
176                         fl_set_object_lcol( dialog_->downBtn, FL_INACTIVE );
177                 }
178
179                 break;
180         }
181         case OFF:
182         {
183                 fl_deactivate_object( dialog_->delBtn );
184                 fl_set_object_lcol( dialog_->delBtn, FL_INACTIVE );
185
186                 fl_deactivate_object( dialog_->upBtn );
187                 fl_set_object_lcol( dialog_->upBtn, FL_INACTIVE );
188
189                 fl_deactivate_object( dialog_->downBtn );
190                 fl_set_object_lcol( dialog_->downBtn, FL_INACTIVE );
191         }
192         default:
193                 break;
194         }
195 }
196
197
198 void FormCitation::setSize( int hbrsr, bool bibPresent ) const
199 {
200         bool const natbib = false; // will eventually be input
201         hbrsr = max( hbrsr, 175 ); // limit max size of cite/bib brsrs
202
203         // dh1, dh2, dh3 are the vertical separation between elements.
204         // These can be specified because the browser height is fixed
205         // so they are not changed by dynamic resizing
206         static int const dh1 = 30; // top of form to top of cite/bib brsrs;
207                                    // bottom of cite/bib brsrs to top of info;
208                                    // bottom of info to top next element;
209                                    // bottom of style to top textBefore;
210                                    // bottom of text to top ok/cancel buttons.
211         static int const dh2 = 10; // bottom of textBefore to top textAftr;
212                                    // bottom of ok/cancel buttons to bottom form
213         static int const dh3 = 5;  // spacing between add/delete/... buttons.
214
215         int const wbrsr  = dialog_->citeBrsr->w;
216         static int const hinfo  = dialog_->infoBrsr->h;
217         static int const hstyle = dialog_->style->h;
218         static int const htext  = dialog_->textAftr->h;
219         static int const hok    = dialog_->ok->h;
220
221         int const wform = dialog_->form->w;
222         int hform = dh1 + hbrsr + dh1;
223         if( bibPresent ) hform += hinfo + dh1;
224         if( natbib ) hform += hstyle + dh1 + htext + dh2;
225         hform += htext + dh1 + hok + dh2;
226
227         bool const sizeSet = ( hform != dialog_->form->h );
228         if( sizeSet ) fl_set_form_size( dialog_->form, wform, hform );
229
230         // No vertical resizing is allowed
231         // min_wform set in build()
232         fl_set_form_minsize( dialog_->form, min_wform,   hform );
233         fl_set_form_maxsize( dialog_->form, 3*min_wform, hform );
234
235         if( !sizeSet ) return;
236
237         int x = 0;
238         int y = 0;
239         fl_set_object_geometry( dialog_->box, x, y, wform, hform );
240
241         x = dialog_->citeBrsr->x;
242         y += dh1; 
243         fl_set_object_geometry( dialog_->citeBrsr, x, y, wbrsr, hbrsr );
244         x = dialog_->bibBrsr->x;
245         fl_set_object_geometry( dialog_->bibBrsr,  x, y, wbrsr, hbrsr );
246
247         x = dialog_->addBtn->x;
248         fl_set_object_position( dialog_->addBtn,  x, y );
249         y += dh3 + dialog_->addBtn->h;
250         fl_set_object_position( dialog_->delBtn,  x, y );
251         y += dh3 + dialog_->delBtn->h;
252         fl_set_object_position( dialog_->upBtn,   x, y );
253         y += dh3 + dialog_->upBtn->h;
254         fl_set_object_position( dialog_->downBtn, x, y );
255
256         y = dh1 + hbrsr + dh1; // in position for next element
257
258         if( bibPresent ) {
259                 x = dialog_->infoBrsr->x;
260                 fl_set_object_position( dialog_->infoBrsr, x, y );
261                 fl_show_object( dialog_->infoBrsr );
262                 y += hinfo + dh1;
263         } else
264                 fl_hide_object( dialog_->infoBrsr );
265
266         if( natbib ) {
267                 x = dialog_->style->x;
268                 fl_set_object_position( dialog_->style, x, y );
269                 fl_show_object( dialog_->style );
270                 x = dialog_->textBefore->x;
271                 y += hstyle + dh1;
272                 fl_set_object_position( dialog_->textBefore, x, y );
273                 fl_show_object( dialog_->textBefore );
274                 y += htext + dh2;
275         } else {
276                 fl_hide_object( dialog_->style );
277                 fl_hide_object( dialog_->textBefore );
278         }
279
280         x = dialog_->textAftr->x;
281         fl_set_object_position( dialog_->textAftr, x, y );
282
283         x = dialog_->ok->x;
284         y += htext + dh1;
285         fl_set_object_position( dialog_->ok,       x, y );
286         x = dialog_->cancel->x;
287         fl_set_object_position( dialog_->cancel,   x, y );
288 }
289
290
291 #ifdef WITH_WARNINGS
292 #warning convert this to use the buttoncontroller
293 #endif
294 bool FormCitation::input( long data )
295 {
296         State cb = static_cast<FormCitation::State>( data );
297
298         switch( cb ) {
299         case BIBBRSR:
300         {
301                 fl_deselect_browser( dialog_->citeBrsr );
302                 
303                 unsigned int sel = fl_get_browser( dialog_->bibBrsr );
304                 if( sel < 1 || sel > bibkeys.size() ) break;
305
306                 // Put into infoBrsr the additional info associated with
307                 // the selected bibBrsr key
308                 fl_clear_browser( dialog_->infoBrsr );
309                 fl_add_browser_line( dialog_->infoBrsr,
310                                      bibkeysInfo[sel-1].c_str() );
311
312                 // Highlight the selected bibBrsr key in citeBrsr if present
313                 vector<string>::iterator it =
314                         find( citekeys.begin(), citekeys.end(), bibkeys[sel-1] );
315
316                 if( it != citekeys.end() ) {
317                         int n = it - citekeys.begin();
318                         fl_select_browser_line( dialog_->citeBrsr, n+1 );
319                         fl_set_browser_topline( dialog_->citeBrsr, n+1 );
320                 }
321
322                 if( !lv_->buffer()->isReadonly() ) {
323                         if( it != citekeys.end() ) {
324                                 setBibButtons( OFF );
325                                 setCiteButtons( ON );
326                         } else {
327                                 setBibButtons( ON );
328                                 setCiteButtons( OFF );
329                         }
330                 }
331         }
332         break;
333         case CITEBRSR:
334         {
335                 unsigned int sel = fl_get_browser( dialog_->citeBrsr );
336                 if( sel < 1 || sel > citekeys.size() ) break;
337
338                 if( !lv_->buffer()->isReadonly() ) {
339                         setBibButtons( OFF );
340                         setCiteButtons( ON );
341                 }
342
343                 // Highlight the selected citeBrsr key in bibBrsr
344                 vector<string>::iterator it =
345                         find( bibkeys.begin(), bibkeys.end(), citekeys[sel-1] );
346
347                 if (it != bibkeys.end()) {
348                         int n = it - bibkeys.begin();
349                         fl_select_browser_line( dialog_->bibBrsr, n+1 );
350                         fl_set_browser_topline( dialog_->bibBrsr, n+1 );
351
352                         // Put into infoBrsr the additional info associated with
353                         // the selected citeBrsr key
354                         fl_clear_browser( dialog_->infoBrsr );
355                         fl_add_browser_line( dialog_->infoBrsr,
356                                              bibkeysInfo[n].c_str() );
357                 }
358         }
359         break;
360         case ADD:
361         {
362                 if( lv_->buffer()->isReadonly() ) break;
363
364                 unsigned int sel = fl_get_browser( dialog_->bibBrsr );
365                 if( sel < 1 || sel > bibkeys.size() ) break;
366
367                 // Add the selected bibBrsr key to citeBrsr
368                 fl_addto_browser( dialog_->citeBrsr,
369                                   bibkeys[sel-1].c_str() );
370                 citekeys.push_back( bibkeys[sel-1] );
371
372                 int n = citekeys.size();
373                 fl_select_browser_line( dialog_->citeBrsr, n );
374
375                 setBibButtons( OFF );
376                 setCiteButtons( ON );
377         }
378         break;
379         case DELETE:
380         {
381                 if( lv_->buffer()->isReadonly() ) break;
382
383                 unsigned int sel = fl_get_browser( dialog_->citeBrsr );
384                 if( sel < 1 || sel > citekeys.size() ) break;
385
386                 // Remove the selected key from citeBrsr
387                 fl_delete_browser_line( dialog_->citeBrsr, sel ) ;
388                 citekeys.erase( citekeys.begin() + sel-1 );
389
390                 setBibButtons( ON );
391                 setCiteButtons( OFF );
392         }
393         break;
394         case UP:
395         {
396                 if( lv_->buffer()->isReadonly() ) break;
397
398                 unsigned int sel = fl_get_browser( dialog_->citeBrsr );
399                 if( sel < 2 || sel > citekeys.size() ) break;
400
401                 // Move the selected key up one line
402                 vector<string>::iterator it = citekeys.begin() + sel-1;
403                 string tmp = *it;
404
405                 fl_delete_browser_line( dialog_->citeBrsr, sel );
406                 citekeys.erase( it );
407
408                 fl_insert_browser_line( dialog_->citeBrsr, sel-1, tmp.c_str() );
409                 fl_select_browser_line( dialog_->citeBrsr, sel-1 );
410                 citekeys.insert( it-1, tmp );
411                 setCiteButtons( ON );
412         }
413         break;
414         case DOWN:
415         {
416                 if( lv_->buffer()->isReadonly() ) break;
417
418                 unsigned int sel = fl_get_browser( dialog_->citeBrsr );
419                 if( sel < 1 || sel > citekeys.size()-1 ) break;
420
421                 // Move the selected key down one line
422                 vector<string>::iterator it = citekeys.begin() + sel-1;
423                 string tmp = *it;
424
425                 fl_delete_browser_line( dialog_->citeBrsr, sel );
426                 citekeys.erase( it );
427
428                 fl_insert_browser_line( dialog_->citeBrsr, sel+1, tmp.c_str() );
429                 fl_select_browser_line( dialog_->citeBrsr, sel+1 );
430                 citekeys.insert( it+1, tmp );
431                 setCiteButtons( ON );
432         }
433         break;
434         default:
435                 break;
436         }
437         return true;
438 }
439
440
441 void FormCitation::apply()
442 {
443         if(lv_->buffer()->isReadonly()) return;
444
445         string contents;
446         for(unsigned int i = 0; i < citekeys.size(); ++i) {
447                 if (i > 0) contents += ", ";
448                 contents += citekeys[i];
449         }
450
451         params.setContents(contents);
452         params.setOptions(fl_get_input(dialog_->textAftr));
453
454         if (inset_ != 0) {
455                 // Only update if contents have changed
456                 if(params != inset_->params()) {
457                         inset_->setParams(params);
458                         lv_->view()->updateInset(inset_, true);
459                 }
460         } else {
461                 lv_->getLyXFunc()->Dispatch(LFUN_CITATION_INSERT,
462                                             params.getAsString());
463         }
464 }