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