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