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