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