]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/FormCitation.C
controller-view split of FormLog and FormVCLog.
[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  * \author Angus Leeming <a.leeming@ic.ac.uk>
12  */
13
14 #include <algorithm>
15
16 #ifdef __GNUG__
17 #pragma implementation
18 #endif
19
20 #include <config.h>
21 #include "ControlCitation.h"
22 #include "FormCitation.h"
23 #include "form_citation.h"
24 #include "gettext.h"
25 #include "support/lstrings.h"
26 #include "xforms_helpers.h"
27 #include "xformsBC.h"
28
29 using std::find;
30 using std::max;
31 using std::min;
32 using std::pair;
33 using std::sort;
34 using std::vector;
35
36 typedef FormCB<ControlCitation, FormDB<FD_form_citation> > base_class;
37
38 FormCitation::FormCitation(ControlCitation & c)
39         : base_class(c, _("Citation"))
40 {}
41
42
43 void FormCitation::apply()
44 {
45         controller().params().setCmdName("cite");
46         controller().params().setContents(getStringFromVector(citekeys));
47
48         string const after  = fl_get_input(dialog_->input_after);
49         controller().params().setOptions(after);
50 }
51
52
53 void FormCitation::hide()
54 {
55         citekeys.clear();
56         bibkeys.clear();
57
58         FormBase::hide();
59 }
60
61
62 void FormCitation::build()
63 {
64         dialog_.reset(build_citation());
65
66         fl_set_input_return(dialog_->input_after,  FL_RETURN_CHANGED);
67         fl_set_input_return(dialog_->input_before, FL_RETURN_CHANGED);
68
69         fl_set_button(dialog_->button_search_type, 0);
70         fl_set_object_label(dialog_->button_search_type, _("Simple"));
71
72         // Manage the ok, apply, restore and cancel/close buttons
73         bc().setOK(dialog_->button_ok);
74         bc().setApply(dialog_->button_apply);
75         bc().setCancel(dialog_->button_cancel);
76         bc().setUndoAll(dialog_->button_restore);
77
78         bc().addReadOnly(dialog_->button_add);
79         bc().addReadOnly(dialog_->button_del);
80         bc().addReadOnly(dialog_->button_up);
81         bc().addReadOnly(dialog_->button_down);
82         bc().addReadOnly(dialog_->choice_style);
83         bc().addReadOnly(dialog_->input_before);
84         bc().addReadOnly(dialog_->input_after);
85
86         bc().refresh();
87 }
88
89
90 ButtonPolicy::SMInput FormCitation::input(FL_OBJECT * ob, long)
91 {
92         ButtonPolicy::SMInput activate = ButtonPolicy::SMI_NOOP;
93
94         if (ob == dialog_->browser_bib) {
95                 fl_deselect_browser(dialog_->browser_cite);
96
97                 unsigned int const sel = fl_get_browser(dialog_->browser_bib);
98                 if (sel < 1 || sel > bibkeys.size())
99                         return ButtonPolicy::SMI_NOOP;
100
101                 // Put into browser_info the additional info associated with
102                 // the selected browser_bib key
103                 fl_clear_browser(dialog_->browser_info);
104                 string const tmp = formatted( controller().
105                                               getBibkeyInfo(bibkeys[sel-1]),
106                                               dialog_->browser_info->w-10 );
107                 fl_add_browser_line(dialog_->browser_info, tmp.c_str());
108
109                 // Highlight the selected browser_bib key in browser_cite if
110                 // present
111                 vector<string>::const_iterator cit =
112                         find(citekeys.begin(), citekeys.end(), bibkeys[sel-1]);
113
114                 if (cit != citekeys.end()) {
115                         int const n = int(cit - citekeys.begin());
116                         fl_select_browser_line(dialog_->browser_cite, n+1);
117                         fl_set_browser_topline(dialog_->browser_cite, n+1);
118                 }
119
120                 if (!controller().isReadonly()) {
121                         if (cit != citekeys.end()) {
122                                 setBibButtons(OFF);
123                                 setCiteButtons(ON);
124                         } else {
125                                 setBibButtons(ON);
126                                 setCiteButtons(OFF);
127                         }
128                 }
129
130         } else if (ob == dialog_->browser_cite) {
131                 unsigned int const sel = fl_get_browser(dialog_->browser_cite);
132                 if (sel < 1 || sel > citekeys.size())
133                         return ButtonPolicy::SMI_NOOP;
134
135                 if (!controller().isReadonly()) {
136                         setBibButtons(OFF);
137                         setCiteButtons(ON);
138                 }
139
140                 // Highlight the selected browser_cite key in browser_bib
141                 vector<string>::const_iterator cit =
142                         find(bibkeys.begin(), bibkeys.end(), citekeys[sel-1]);
143
144                 if (cit != bibkeys.end()) {
145                         int const n = int(cit - bibkeys.begin());
146                         fl_select_browser_line(dialog_->browser_bib, n+1);
147                         fl_set_browser_topline(dialog_->browser_bib, n+1);
148
149                         // Put into browser_info the additional info associated
150                         // with the selected browser_cite key
151                         fl_clear_browser(dialog_->browser_info);
152                         string const tmp =
153                                 formatted( controller(). 
154                                            getBibkeyInfo(bibkeys[n]),
155                                            dialog_->browser_info->w-10 );
156                         fl_add_browser_line(dialog_->browser_info, tmp.c_str());
157                 }
158
159         } else if (ob == dialog_->button_add) {
160                 unsigned int const sel = fl_get_browser(dialog_->browser_bib);
161                 if (sel < 1 || sel > bibkeys.size())
162                         return ButtonPolicy::SMI_NOOP;
163
164                 // Add the selected browser_bib key to browser_cite
165                 fl_addto_browser(dialog_->browser_cite,
166                                   bibkeys[sel-1].c_str());
167                 citekeys.push_back(bibkeys[sel-1]);
168
169                 int const n = int(citekeys.size());
170                 fl_select_browser_line(dialog_->browser_cite, n);
171
172                 setBibButtons(OFF);
173                 setCiteButtons(ON);
174                 activate = ButtonPolicy::SMI_VALID;
175
176         } else if (ob == dialog_->button_del) {
177                 unsigned int const sel = fl_get_browser(dialog_->browser_cite);
178                 if (sel < 1 || sel > citekeys.size())
179                         return ButtonPolicy::SMI_NOOP;
180
181                 // Remove the selected key from browser_cite
182                 fl_delete_browser_line(dialog_->browser_cite, sel) ;
183                 citekeys.erase(citekeys.begin() + sel-1);
184
185                 setBibButtons(ON);
186                 setCiteButtons(OFF);
187                 activate = ButtonPolicy::SMI_VALID;
188
189         } else if (ob == dialog_->button_up) {
190                 unsigned int const sel = fl_get_browser(dialog_->browser_cite);
191                 if (sel < 2 || sel > citekeys.size())
192                         return ButtonPolicy::SMI_NOOP;
193
194                 // Move the selected key up one line
195                 vector<string>::iterator it = citekeys.begin() + sel-1;
196                 string const tmp = *it;
197
198                 fl_delete_browser_line(dialog_->browser_cite, sel);
199                 citekeys.erase(it);
200
201                 fl_insert_browser_line(dialog_->browser_cite, sel-1, tmp.c_str());
202                 fl_select_browser_line(dialog_->browser_cite, sel-1);
203                 citekeys.insert(it-1, tmp);
204                 setCiteButtons(ON);
205                 activate = ButtonPolicy::SMI_VALID;
206
207         } else if (ob == dialog_->button_down) {
208                 unsigned int const sel = fl_get_browser(dialog_->browser_cite);
209                 if (sel < 1 || sel > citekeys.size()-1)
210                         return ButtonPolicy::SMI_NOOP;
211
212                 // Move the selected key down one line
213                 vector<string>::iterator it = citekeys.begin() + sel-1;
214                 string const tmp = *it;
215
216                 fl_delete_browser_line(dialog_->browser_cite, sel);
217                 citekeys.erase(it);
218
219                 fl_insert_browser_line(dialog_->browser_cite, sel+1, tmp.c_str());
220                 fl_select_browser_line(dialog_->browser_cite, sel+1);
221                 citekeys.insert(it+1, tmp);
222                 setCiteButtons(ON);
223                 activate = ButtonPolicy::SMI_VALID;
224
225         } else if (ob == dialog_->button_search_type) {
226                 if (fl_get_button(dialog_->button_search_type))
227                         fl_set_object_label(dialog_->button_search_type,
228                                             _("Regex"));
229                 else
230                         fl_set_object_label(dialog_->button_search_type,
231                                             _("Simple"));
232                 return ButtonPolicy::SMI_NOOP;
233                 
234         } else if (ob == dialog_->button_previous ||
235                    ob == dialog_->button_next) {
236
237                 string const str = fl_get_input(dialog_->input_search);
238
239                 ControlCitation::Direction const dir =
240                         (ob == dialog_->button_previous) ?
241                         ControlCitation::BACKWARD : ControlCitation::FORWARD;
242
243                 ControlCitation::Search const type =
244                         fl_get_button(dialog_->button_search_type) ?
245                         ControlCitation::REGEX : ControlCitation::SIMPLE;
246
247                 vector<string>::const_iterator start = bibkeys.begin();
248                 int const sel = fl_get_browser(dialog_->browser_bib);
249                 if (sel >= 1 && sel <= bibkeys.size())
250                         start += sel-1;
251
252                 // Find the NEXT instance...
253                 if (dir == ControlCitation::FORWARD)
254                         start += 1;
255                 else
256                         start -= 1;
257
258                 vector<string>::const_iterator const cit =
259                         searchKeys(controller(), bibkeys, str, start,
260                                    type, dir);
261
262                 if (cit == bibkeys.end())
263                         return ButtonPolicy::SMI_NOOP;
264
265                 int const found = int(cit - bibkeys.begin()) + 1;
266                 if (found == sel)
267                         return ButtonPolicy::SMI_NOOP;
268
269                 // Update the display
270                 int const top = max(found-5, 1);
271                 fl_set_browser_topline(dialog_->browser_bib, top);
272                 fl_select_browser_line(dialog_->browser_bib, found);
273                 input(dialog_->browser_bib, 0);
274
275         } else if (ob == dialog_->choice_style ||
276                    ob == dialog_->input_before ||
277                    ob == dialog_->input_after) {
278                 activate = ButtonPolicy::SMI_VALID;
279         }
280
281         return activate;
282 }
283
284
285 void FormCitation::update()
286 {
287         // Make the list of all available bibliography keys
288         bibkeys = controller().getBibkeys();
289         updateBrowser(dialog_->browser_bib, bibkeys);
290
291         // Ditto for the keys cited in this inset
292         citekeys = getVectorFromString(controller().params().getContents());
293         updateBrowser(dialog_->browser_cite, citekeys);
294
295         // No keys have been selected yet, so...
296         fl_clear_browser(dialog_->browser_info);
297         setBibButtons(OFF);
298         setCiteButtons(OFF);
299
300         int noKeys = int(max(bibkeys.size(), citekeys.size()));
301
302         // Place bounds, so that 4 <= noKeys <= 10
303         noKeys = max(4, min(10, noKeys));
304
305         // Re-size the form to accommodate the new browser size
306         int const size = 20 * noKeys;
307         bool const bibPresent = (bibkeys.size() > 0);
308         setSize(size, bibPresent);
309
310         fl_set_input(dialog_->input_after,
311                      controller().params().getOptions().c_str());
312 }
313
314
315 void FormCitation::updateBrowser(FL_OBJECT * browser,
316                                  vector<string> const & keys) const
317 {
318         fl_clear_browser(browser);
319
320         for (vector<string>::size_type i = 0; i < keys.size(); ++i)
321                 fl_add_browser_line(browser, keys[i].c_str());
322 }
323
324
325 void FormCitation::setBibButtons(State status) const
326 {
327         setEnabled(dialog_->button_add, (status == ON));
328 }
329
330
331 void FormCitation::setCiteButtons(State status) const
332 {
333         int const sel     = fl_get_browser(dialog_->browser_cite);
334         int const maxline = fl_get_browser_maxline(dialog_->browser_cite);
335         bool const activate      = (status == ON);
336         bool const activate_up   = (activate && sel != 1);
337         bool const activate_down = (activate && sel != maxline);
338
339         setEnabled(dialog_->button_del,  activate);
340         setEnabled(dialog_->button_up,   activate_up);
341         setEnabled(dialog_->button_down, activate_down);
342 }
343
344
345 void FormCitation::setSize(int hbrsr, bool bibPresent) const
346 {
347         bool const natbib = false; // will eventually be input
348         hbrsr = max(hbrsr, 175); // limit max size of cite/bib brsrs
349
350         // dh1, dh2, dh3 are the vertical separation between elements.
351         // These can be specified because the browser height is fixed
352         // so they are not changed by dynamic resizing
353         static int const dh1 = 30; // top of form to top of cite/bib brsrs;
354                                    // bottom of cite/bib brsrs to top of info;
355                                    // bottom of info to top search frame;
356                                    // bottom of search frame to top next elemnt;
357                                    // bottom of style to top input_before;
358                                    // bottom of text to top ok/cancel buttons.
359         static int const dh2 = 10; // bottom of input_before to top input_after;
360                                    // bottom of ok/cancel buttons to bottom form
361         static int const dh3 = 5;  // spacing between add/delete/... buttons.
362
363         int const wbrsr  = dialog_->browser_cite->w;
364         static int const hinfo  = dialog_->browser_info->h;
365         static int const hframe = dialog_->frame_search->h;
366         static int const hstyle = dialog_->choice_style->h;
367         static int const htext  = dialog_->input_after->h;
368         static int const hok    = dialog_->button_ok->h;
369
370         int hform = dh1 + hbrsr + dh1 + hframe + dh1;
371         if (bibPresent) hform += hinfo + dh1;
372         if (natbib) hform += hstyle + dh1 + htext + dh2;
373         hform += htext + dh1 + hok + dh2;
374
375         if (hform != minh_) {
376                 minh_ = hform;
377                 fl_set_form_size(dialog_->form, minw_, minh_);
378         } else
379                 return;
380
381         int x = 0;
382         int y = 0;
383         fl_set_object_geometry(dialog_->box, x, y, minw_, minh_);
384
385         x = dialog_->browser_cite->x;
386         y += dh1; 
387         fl_set_object_geometry(dialog_->browser_cite, x, y, wbrsr, hbrsr);
388         x = dialog_->browser_bib->x;
389         fl_set_object_geometry(dialog_->browser_bib,  x, y, wbrsr, hbrsr);
390
391         x = dialog_->button_add->x;
392         fl_set_object_position(dialog_->button_add,  x, y);
393         y += dh3 + dialog_->button_add->h;
394         fl_set_object_position(dialog_->button_del,  x, y);
395         y += dh3 + dialog_->button_del->h;
396         fl_set_object_position(dialog_->button_up,   x, y);
397         y += dh3 + dialog_->button_up->h;
398         fl_set_object_position(dialog_->button_down, x, y);
399
400         y = dh1 + hbrsr + dh1; // in position for next element
401
402         if (bibPresent) {
403                 x = dialog_->browser_info->x;
404                 fl_set_object_position(dialog_->browser_info, x, y);
405                 fl_show_object(dialog_->browser_info);
406                 y += hinfo + dh1;
407         } else
408                 fl_hide_object(dialog_->browser_info);
409
410         x = dialog_->frame_search->x;
411         // ??? The frame height seems to be reduced. Use geometry to enforce it.
412         fl_set_object_geometry(dialog_->frame_search, x, y,
413                                dialog_->frame_search->w, hframe);
414         //fl_set_object_position(dialog_->frame_search, x, y);
415
416         x = dialog_->input_search->x;
417         y += 15;
418         fl_set_object_position(dialog_->input_search, x, y);
419
420         x = dialog_->button_previous->x;
421         y += dialog_->input_search->h + 5;
422         fl_set_object_position(dialog_->button_previous, x, y);
423
424         x = dialog_->button_next->x;
425         y += dialog_->button_previous->h + 5;
426         fl_set_object_position(dialog_->button_next, x, y);
427
428         x = dialog_->button_search_type->x;
429         y = dialog_->button_previous->y;
430         fl_set_object_position(dialog_->button_search_type, x, y);
431
432         y = dialog_->frame_search->y + hframe + dh1;
433         
434         if (natbib) {
435                 x = dialog_->choice_style->x;
436                 fl_set_object_position(dialog_->choice_style, x, y);
437                 fl_show_object(dialog_->choice_style);
438                 x = dialog_->input_before->x;
439                 y += hstyle + dh1;
440                 fl_set_object_position(dialog_->input_before, x, y);
441                 fl_show_object(dialog_->input_before);
442                 y += htext + dh2;
443         } else {
444                 fl_hide_object(dialog_->choice_style);
445                 fl_hide_object(dialog_->input_before);
446         }
447
448         x = dialog_->input_after->x;
449         fl_set_object_position(dialog_->input_after, x, y);
450
451         y += htext + dh1;
452         x = dialog_->button_restore->x;
453         fl_set_object_position(dialog_->button_restore, x, y);
454         x = dialog_->button_ok->x;
455         fl_set_object_position(dialog_->button_ok, x, y);
456         x = dialog_->button_apply->x;
457         fl_set_object_position(dialog_->button_apply, x, y);
458         x = dialog_->button_cancel->x;
459         fl_set_object_position(dialog_->button_cancel, x, y);
460 }