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