]> git.lyx.org Git - lyx.git/blob - src/insets/insetcollapsable.C
Small clean-up of natbib code
[lyx.git] / src / insets / insetcollapsable.C
1 /* This file is part of
2  * ======================================================
3  * 
4  *           LyX, The Document Processor
5  *       
6  *          Copyright 1998-2001 The LyX Team.
7  *
8  * ======================================================
9  */
10
11 #include <config.h>
12
13 #ifdef __GNUG__
14 #pragma implementation
15 #endif
16
17 #include "insetcollapsable.h"
18 #include "gettext.h"
19 #include "lyxfont.h"
20 #include "BufferView.h"
21 #include "Painter.h"
22 #include "insets/insettext.h"
23 #include "support/LOstream.h"
24 #include "support/lstrings.h"
25 #include "debug.h"
26 #include "lyxtext.h"
27 #include "font.h"
28
29 class LyXText;
30
31 using std::ostream;
32 using std::endl;
33 using std::max;
34
35
36 InsetCollapsable::InsetCollapsable(bool collapsed)
37         : UpdatableInset(), collapsed_(collapsed), 
38           button_length(0), button_top_y(0), button_bottom_y(0),
39           label("Label"),
40 #if 0
41         draw_label(label),
42 #endif
43 #if 0
44         autocollapse(false),
45 #endif
46           oldWidth(0), need_update(FULL),
47           inlined(false)
48 #if 0
49         , change_label_with_text(false)
50 #endif
51 {
52         inset.setOwner(this);
53         inset.setAutoBreakRows(true);
54         inset.setDrawFrame(0, InsetText::ALWAYS);
55         inset.setFrameColor(0, LColor::collapsableframe);
56         setInsetName("Collapsable");
57 }
58
59
60 InsetCollapsable::InsetCollapsable(InsetCollapsable const & in, bool same_id)
61         : UpdatableInset(in, same_id), collapsed_(in.collapsed_), 
62           framecolor(in.framecolor), labelfont(in.labelfont),
63           button_length(0), button_top_y(0), button_bottom_y(0),
64           label(in.label),
65 #if 0
66         draw_label(label),
67 #endif
68 #if 0
69         autocollapse(in.autocollapse),
70 #endif
71           oldWidth(0), need_update(FULL),
72           inlined(in.inlined)
73 #if 0
74         , change_label_with_text(in.change_label_with_text)
75 #endif
76 {
77         inset.init(&(in.inset), same_id);
78         inset.setOwner(this);
79 }
80
81
82 Inset * InsetCollapsable::clone(Buffer const &, bool same_id) const
83 {
84         return new InsetCollapsable(*const_cast<InsetCollapsable *>(this),
85                                                                 same_id);
86 }
87
88
89 bool InsetCollapsable::insertInset(BufferView * bv, Inset * in)
90 {
91         if (!insetAllowed(in->lyxCode())) {
92                 lyxerr << "InsetCollapsable::InsertInset: "
93                         "Unable to insert inset." << endl;
94                 return false;
95         }
96         return inset.insertInset(bv, in);
97 }
98
99
100 void InsetCollapsable::write(Buffer const * buf, ostream & os) const
101 {
102         os << "collapsed " << tostr(collapsed_) << "\n";
103         inset.writeParagraphData(buf, os);
104 }
105
106
107
108 void InsetCollapsable::read(Buffer const * buf, LyXLex & lex)
109 {
110         if (lex.IsOK()) {
111                 lex.next();
112                 string const token = lex.GetString();
113                 if (token == "collapsed") {
114                         lex.next();
115                         collapsed_ = lex.GetBool();
116                 } else {
117                         lyxerr << "InsetCollapsable::Read: Missing collapsed!"
118                                << endl;
119                         // Take countermeasures
120                         lex.pushToken(token);
121                 }
122         }
123         inset.read(buf, lex);
124 #if 0
125         if (collapsed_ && change_label_with_text) {
126                 draw_label = get_new_label();
127         } else {
128                 draw_label = label;
129         }
130 #endif
131 }
132
133
134 //int InsetCollapsable::ascent_collapsed(Painter & pain) const
135 int InsetCollapsable::ascent_collapsed() const
136 {
137         int width = 0;
138         int ascent = 0;
139         int descent = 0;
140 #if 0
141         pain.buttonText(0, 0, draw_label, labelfont, false, 
142                         width, ascent, descent);
143 #else
144         lyxfont::buttonText(label, labelfont, width, ascent, descent);
145 #endif
146         return ascent;
147 }
148
149
150 //int InsetCollapsable::descent_collapsed(Painter & pain) const
151 int InsetCollapsable::descent_collapsed() const
152 {
153         int width = 0;
154         int ascent = 0;
155         int descent = 0;
156 #if 0
157         pain.buttonText(0, 0, draw_label, labelfont, false, 
158                         width, ascent, descent);
159 #else
160         lyxfont::buttonText(label, labelfont, width, ascent, descent);
161 #endif
162         return descent;
163 }
164
165
166 //int InsetCollapsable::width_collapsed(Painter & pain) const
167 int InsetCollapsable::width_collapsed() const
168 {
169         int width;
170         int ascent;
171         int descent;
172 #if 0
173         pain.buttonText(TEXT_TO_INSET_OFFSET, 0, draw_label, labelfont, false,
174                         width, ascent, descent);
175 #else
176         lyxfont::buttonText(label, labelfont, width, ascent, descent);
177 #endif
178         return width + (2*TEXT_TO_INSET_OFFSET);
179 }
180
181
182 int InsetCollapsable::ascent(BufferView * /*bv*/, LyXFont const &) const
183 {
184         return ascent_collapsed();
185 }
186
187
188 int InsetCollapsable::descent(BufferView * bv, LyXFont const & font) const
189 {
190         if (collapsed_) 
191                 return descent_collapsed();
192
193         return descent_collapsed()
194                 + inset.descent(bv, font)
195                 + inset.ascent(bv, font)
196                 + TEXT_TO_BOTTOM_OFFSET;
197 }
198
199
200 int InsetCollapsable::width(BufferView * bv, LyXFont const & font) const
201 {
202         if (collapsed_) 
203                 return width_collapsed();
204
205         int widthCollapsed = width_collapsed();
206
207         return (inset.width(bv, font) > widthCollapsed) ?
208                 inset.width(bv, font) : widthCollapsed;
209 }
210
211
212 void InsetCollapsable::draw_collapsed(Painter & pain, int baseline, float & x) const
213 {
214 #if 0
215         int width = 0;
216         pain.buttonText(int(x) + TEXT_TO_INSET_OFFSET,
217                         baseline, draw_label, labelfont, true, width);
218         x += width + TEXT_TO_INSET_OFFSET;
219 #else
220         pain.buttonText(int(x) + TEXT_TO_INSET_OFFSET,
221                         baseline, label, labelfont);
222         x += width_collapsed();
223 #endif
224 }
225
226
227 void InsetCollapsable::draw(BufferView * bv, LyXFont const & f, 
228                             int baseline, float & x, bool cleared) const
229 {
230         if (nodraw())
231                 return;
232
233         Painter & pain = bv->painter();
234
235         button_length = width_collapsed();
236         button_top_y = -ascent(bv, f);
237         button_bottom_y = -ascent(bv, f) + ascent_collapsed() +
238                 descent_collapsed();
239
240         if (collapsed_) {
241                 draw_collapsed(pain, baseline, x);
242                 x += TEXT_TO_INSET_OFFSET;
243                 return;
244         }
245
246         float old_x = x;
247
248 #if 0
249         UpdatableInset::draw(bv, f, baseline, x, cleared);
250 #else
251         if (!owner())
252                 x += static_cast<float>(scroll());
253 #endif
254         if (!cleared && (inset.need_update == InsetText::FULL ||
255                          inset.need_update == InsetText::INIT ||
256                          top_x != int(x) ||
257                          top_baseline != baseline))
258         {
259 #if 1
260                 // we don't need anymore to clear here we just have to tell
261                 // the underlying LyXText that it should do the RowClear!
262                 inset.setUpdateStatus(bv, InsetText::FULL);
263                 bv->text->status(bv, LyXText::CHANGED_IN_DRAW);
264                 return;
265 #else
266                 int w =  owner() ? width(bv, f) : pain.paperWidth();
267                 int h = ascent(bv, f) + descent(bv, f);
268                 int const tx = (needFullRow() && !owner()) ? 0 : int(x);
269                 int const ty = max(0, baseline - ascent(bv, f));
270
271                 if ((ty + h) > pain.paperHeight())
272                         h = pain.paperHeight();
273                 if ((top_x + w) > pain.paperWidth())
274                         w = pain.paperWidth();
275                 if (baseline < 0)
276                         h += (baseline - ascent(bv, f));
277                 pain.fillRectangle(tx, ty - 1, w, h + 2);
278                 cleared = true;
279 #endif
280         }
281
282         top_x = int(x);
283         top_baseline = baseline;
284
285         int const bl = baseline - ascent(bv, f) + ascent_collapsed();
286
287         draw_collapsed(pain, bl, old_x);
288         inset.draw(bv, f, 
289                    bl + descent_collapsed() + inset.ascent(bv, f),
290                    x, cleared);
291         need_update = NONE;
292 }
293
294
295 void InsetCollapsable::edit(BufferView * bv, int xp, int yp,
296                             unsigned int button)
297 {
298         UpdatableInset::edit(bv, xp, yp, button);
299
300         if (collapsed_) {
301 #if 0
302                 draw_label = label;
303 #endif
304                 collapsed_ = false;
305                 if (!bv->lockInset(this))
306                         return;
307                 bv->updateInset(this, false);
308                 inset.edit(bv);
309         } else {
310                 if (!bv->lockInset(this))
311                         return;
312                 if (yp <= button_bottom_y) {
313                         inset.edit(bv);
314                 } else {
315                         LyXFont font(LyXFont::ALL_SANE);
316                         int yy = ascent(bv, font) + yp -
317                                 (ascent_collapsed() +
318                                  descent_collapsed() +
319                                  inset.ascent(bv, font));
320                         inset.edit(bv, xp, yy, button);
321                 }
322         }
323 }
324
325
326 void InsetCollapsable::edit(BufferView * bv, bool front)
327 {
328         UpdatableInset::edit(bv, front);
329
330         if (collapsed_) {
331 #if 0
332                 draw_label = label;
333 #endif
334                 collapsed_ = false;
335                 if (!bv->lockInset(this))
336                         return;
337                 inset.setUpdateStatus(bv, InsetText::FULL);
338                 bv->updateInset(this, false);
339                 inset.edit(bv, front);
340         } else {
341                 if (!bv->lockInset(this))
342                         return;
343                 inset.edit(bv, front);
344         }
345 }
346
347
348 Inset::EDITABLE InsetCollapsable::editable() const
349 {
350         if (collapsed_)
351                 return IS_EDITABLE;
352         return HIGHLY_EDITABLE;
353 }
354
355
356 void InsetCollapsable::insetUnlock(BufferView * bv)
357 {
358 #if 0
359         if (autocollapse) {
360                 if (change_label_with_text) {
361                         draw_label = get_new_label();
362                 } else {
363                         draw_label = label;
364                 }
365                 collapsed_ = true;
366         }
367 #endif
368         inset.insetUnlock(bv);
369         if (scroll())
370                 scroll(bv, 0.0F);
371         bv->updateInset(this, false);
372 }
373
374
375 void InsetCollapsable::insetButtonPress(BufferView * bv, int x, int y,
376                                         int button)
377 {
378         if (!collapsed_ && (y > button_bottom_y)) {
379                 LyXFont font(LyXFont::ALL_SANE);
380                 int yy = ascent(bv, font) + y -
381                     (ascent_collapsed() +
382                      descent_collapsed() +
383                      inset.ascent(bv, font));
384                 inset.insetButtonPress(bv, x, yy, button);
385         }
386 }
387
388
389 void InsetCollapsable::insetButtonRelease(BufferView * bv,
390                                           int x, int y, int button)
391 {
392         if ((x >= 0)  && (x < button_length) &&
393             (y >= button_top_y) &&  (y <= button_bottom_y)) {
394                 if (collapsed_) {
395 #if 0
396                         draw_label = label;
397 #endif
398                         collapsed_ = false;
399                         inset.insetButtonRelease(bv, 0, 0, button);
400                         inset.setUpdateStatus(bv, InsetText::FULL);
401                         bv->updateInset(this, false);
402                 } else {
403 #if 0
404                         if (change_label_with_text) {
405                                 draw_label = get_new_label();
406                         } else {
407                                 draw_label = label;
408                         }
409 #endif
410                         collapsed_ = true;
411                         bv->unlockInset(this);
412                         bv->updateInset(this, false);
413                 }
414         } else if (!collapsed_ && (y > button_bottom_y)) {
415                 LyXFont font(LyXFont::ALL_SANE);
416                 int yy = ascent(bv, font) + y -
417                     (ascent_collapsed() +
418                      descent_collapsed() +
419                      inset.ascent(bv, font));
420                 inset.insetButtonRelease(bv, x, yy, button);
421         }
422 }
423
424
425 void InsetCollapsable::insetMotionNotify(BufferView * bv,
426                                          int x, int y, int state)
427 {
428         if (y > button_bottom_y) {
429                 LyXFont font(LyXFont::ALL_SANE);
430                 int yy = ascent(bv, font) + y -
431                     (ascent_collapsed() +
432                      descent_collapsed() +
433                      inset.ascent(bv, font));
434                 inset.insetMotionNotify(bv, x, yy, state);
435         }
436 }
437
438
439 void InsetCollapsable::insetKeyPress(XKeyEvent * xke)
440 {
441         inset.insetKeyPress(xke);
442 }
443
444
445 int InsetCollapsable::latex(Buffer const * buf, ostream & os,
446                             bool fragile, bool free_spc) const
447 {
448         return inset.latex(buf, os, fragile, free_spc);
449 }
450
451
452 int InsetCollapsable::getMaxWidth(BufferView * bv,
453                                   UpdatableInset const * inset) const
454 {
455         int const w = UpdatableInset::getMaxWidth(bv, inset);
456
457         if (w < 0) {
458                 // What does a negative max width signify? (Lgb)
459                 // Use the max width of the draw-area (Jug)
460                 return w;
461         }
462         // should be at least 30 pixels !!!
463         return max(30, w - width_collapsed());
464 }
465
466
467 void InsetCollapsable::update(BufferView * bv, LyXFont const & font,
468                               bool reinit)
469 {
470         inset.update(bv, font, reinit);
471 }
472
473
474 UpdatableInset::RESULT
475 InsetCollapsable::localDispatch(BufferView * bv, kb_action action,
476                                 string const & arg)
477 {
478         UpdatableInset::RESULT result = inset.localDispatch(bv, action, arg);
479         if (result == FINISHED)
480                 bv->unlockInset(this);
481         return result;
482 }
483
484
485 bool InsetCollapsable::lockInsetInInset(BufferView * bv, UpdatableInset * in)
486 {
487         if (&inset == in)
488                 return true;
489         return inset.lockInsetInInset(bv, in);
490 }
491
492
493 bool InsetCollapsable::unlockInsetInInset(BufferView * bv, UpdatableInset * in,
494                                           bool lr)
495 {
496         if (&inset == in) {
497                 bv->unlockInset(this);
498                 return true;
499         }
500         return inset.unlockInsetInInset(bv, in, lr);
501 }
502
503
504 bool InsetCollapsable::updateInsetInInset(BufferView * bv, Inset *in)
505 {
506         if (&inset == in)
507                 return true;
508         return inset.updateInsetInInset(bv, in);
509 }
510
511
512 unsigned int InsetCollapsable::insetInInsetY()
513 {
514         return inset.insetInInsetY() - (top_baseline - inset.y());
515 }
516
517
518 void InsetCollapsable::validate(LaTeXFeatures & features) const
519 {
520         inset.validate(features);
521 }
522
523
524 void InsetCollapsable::getCursorPos(BufferView * bv, int & x, int & y) const
525 {
526         inset.getCursorPos(bv, x , y);
527 }
528
529
530 void InsetCollapsable::toggleInsetCursor(BufferView * bv)
531 {
532         inset.toggleInsetCursor(bv);
533 }
534
535
536 void InsetCollapsable::showInsetCursor(BufferView * bv, bool show)
537 {
538         inset.showInsetCursor(bv, show);
539 }
540
541
542 void InsetCollapsable::hideInsetCursor(BufferView * bv)
543 {
544         inset.hideInsetCursor(bv);
545 }
546
547
548 UpdatableInset * InsetCollapsable::getLockingInset() const
549 {
550         UpdatableInset * in = inset.getLockingInset();
551         if (const_cast<InsetText *>(&inset) == in)
552                 return const_cast<InsetCollapsable *>(this);
553         return in;
554 }
555
556
557 UpdatableInset * InsetCollapsable::getFirstLockingInsetOfType(Inset::Code c)
558 {
559         if (c == lyxCode())
560                 return this;
561         return inset.getFirstLockingInsetOfType(c);
562 }
563
564
565 void InsetCollapsable::setFont(BufferView * bv, LyXFont const & font,
566                                bool toggleall, bool selectall)
567 {
568         inset.setFont(bv, font, toggleall, selectall);
569 }
570
571
572 bool InsetCollapsable::doClearArea() const
573 {
574         return inset.doClearArea();
575 }
576
577
578 LyXText * InsetCollapsable::getLyXText(BufferView const * bv,
579                                        bool const recursive) const
580 {
581         return inset.getLyXText(bv, recursive);
582 }
583
584
585 void InsetCollapsable::deleteLyXText(BufferView * bv, bool recursive) const
586 {
587         inset.deleteLyXText(bv, recursive);
588 }
589
590
591 void InsetCollapsable::resizeLyXText(BufferView * bv, bool force) const
592 {
593         inset.resizeLyXText(bv, force);
594         LyXFont font(LyXFont::ALL_SANE);
595         oldWidth = width(bv, font);
596 }
597
598
599 std::vector<string> const InsetCollapsable::getLabelList() const
600 {
601         return inset.getLabelList();
602 }
603
604
605 bool InsetCollapsable::nodraw() const
606 {
607         return inset.nodraw();
608 }
609
610  
611 int InsetCollapsable::scroll(bool recursive) const
612 {
613         int sx = UpdatableInset::scroll(false);
614
615         if (recursive)
616                 sx += inset.scroll(recursive);
617
618         return sx;
619 }
620
621
622 Paragraph * InsetCollapsable::getParFromID(int id) const
623 {
624         return inset.getParFromID(id);
625 }
626
627
628 Paragraph * InsetCollapsable::firstParagraph() const
629 {
630         return inset.firstParagraph();
631 }
632
633
634 LyXCursor const & InsetCollapsable::cursor(BufferView * bv) const
635 {
636         return inset.cursor(bv);
637 }
638
639
640 Inset * InsetCollapsable::getInsetFromID(int id_arg) const
641 {
642         if (id_arg == id())
643                 return const_cast<InsetCollapsable *>(this);
644         return inset.getInsetFromID(id_arg);
645 }
646
647
648 #if 0
649 void InsetCollapsable::open(BufferView * bv, bool flag)
650 {
651         if (flag == !collapsed_)
652                 return;
653         collapsed_ = !flag;
654 #if 0
655         if (collapsed_ && change_label_with_text) {
656                 draw_label = get_new_label();
657         } else {
658                 draw_label = label;
659         }
660 #endif
661         bv->updateInset(this, false);
662 }
663 #else
664 void InsetCollapsable::open(BufferView * bv)
665 {
666         if (!collapsed_) return;
667         
668         collapsed_ = false;
669         bv->updateInset(this, false);
670 }
671
672
673 void InsetCollapsable::close(BufferView * bv)
674 {
675         if (collapsed_) return;
676         
677         collapsed_ = true;
678         bv->updateInset(this, false);
679 }
680 #endif
681
682
683 #if 0
684 void InsetCollapsable::setLabel(string const & l, bool flag)
685 {
686         label = l;
687         change_label_with_text = flag;
688         if (collapsed_ && change_label_with_text) {
689                 draw_label = get_new_label();
690         } else {
691                 draw_label = label;
692         }
693 }
694 #else
695 void InsetCollapsable::setLabel(string const & l)
696 {
697         label = l;
698 }
699 #endif
700
701
702 #if 0
703 string const InsetCollapsable::get_new_label() const
704 {
705         string la;
706         Paragraph::size_type const max_length = 15;
707
708         int n = std::min(max_length, inset.paragraph()->size());
709         int i = 0;
710         int j = 0;
711         for(; i < n && j < inset.paragraph()->size(); ++j) {
712                 if (inset.paragraph()->isInset(j))
713                         continue;
714                 la += inset.paragraph()->getChar(j);
715                 ++i;
716         }
717         if ((i > 0) && (j < inset.paragraph()->size()))
718                 la += "...";
719         if (la.empty())
720                 la = label;
721         return la;
722 }
723 #endif