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