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