]> git.lyx.org Git - lyx.git/blob - src/insets/insetcollapsable.C
9e843c286220a31024032f61baed1a2e41dc7aa5
[lyx.git] / src / insets / insetcollapsable.C
1 /* This file is part of
2  * ======================================================
3  * 
4  *           LyX, The Document Processor
5  *       
6  *          Copyright (C) 1998 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
27 class LyXText;
28
29 using std::ostream;
30
31 InsetCollapsable::InsetCollapsable()
32         : UpdatableInset()
33 {
34     inset = new InsetText;
35     inset->setOwner(this);
36     collapsed = true;
37     label = "Label";
38     autocollapse = true;
39     inset->SetAutoBreakRows(true);
40     inset->SetDrawFrame(0, InsetText::ALWAYS);
41     inset->SetFrameColor(0, LColor::footnoteframe);
42     button_length = button_top_y = button_bottom_y = 0;
43     setInsetName("Collapsable");
44     widthCollapsed = oldWidth = 0;
45     need_update = FULL;
46 }
47
48
49 Inset * InsetCollapsable::Clone() const
50 {
51     InsetCollapsable * result = new InsetCollapsable();
52     result->inset->init(inset);
53     result->inset->setOwner(result);
54
55     result->collapsed = collapsed;
56     return result;
57 }
58
59
60 bool InsetCollapsable::InsertInset(BufferView * bv, Inset * in)
61 {
62     if (!InsertInsetAllowed(in)) {
63         lyxerr << "InsetCollapsable::InsertInset: "
64                 "Unable to insert inset." << endl;
65         return false;
66     }
67     
68     return inset->InsertInset(bv, in);
69 }
70
71
72 void InsetCollapsable::Write(Buffer const * buf, ostream & os) const
73 {
74     os << "collapsed " << tostr(collapsed) << "\n";
75     inset->WriteParagraphData(buf, os);
76 }
77
78
79
80 void InsetCollapsable::Read(Buffer const * buf, LyXLex & lex)
81 {
82     if (lex.IsOK()) {
83         lex.next();
84         string token = lex.GetString();
85         if (token == "collapsed") {
86             lex.next();
87             collapsed = lex.GetBool();
88         }
89     }
90     inset->Read(buf, lex);
91 }
92
93
94 int InsetCollapsable::ascent_collapsed(Painter & pain, LyXFont const &) const
95 {
96     int width = 0, ascent = 0, descent = 0;
97     pain.buttonText(0, 0, label.c_str(), labelfont, false, 
98                     width, ascent, descent);
99     return ascent;
100 }
101
102
103 int InsetCollapsable::descent_collapsed(Painter & pain, LyXFont const &) const
104 {
105     int width = 0, ascent = 0, descent = 0;
106     pain.buttonText(0, 0, label.c_str(), labelfont, false, 
107                     width, ascent, descent);
108     return descent;
109 }
110
111
112 int InsetCollapsable::width_collapsed(Painter & pain, LyXFont const &) const
113 {
114     int width, ascent, descent;
115     pain.buttonText(TEXT_TO_INSET_OFFSET, 0, label.c_str(), labelfont, false,
116                     width, ascent, descent);
117     return width + (2*TEXT_TO_INSET_OFFSET);
118 }
119
120
121 int InsetCollapsable::ascent(Painter & pain, LyXFont const & font) const
122 {
123     if (collapsed) 
124         return ascent_collapsed(pain, font);
125     else 
126         return inset->ascent(pain, font) + TEXT_TO_TOP_OFFSET;
127 }
128
129
130 int InsetCollapsable::descent(Painter & pain, LyXFont const & font) const
131 {
132     if (collapsed) 
133         return descent_collapsed(pain, font);
134     else 
135         return inset->descent(pain, font) + TEXT_TO_BOTTOM_OFFSET;
136 }
137
138
139 int InsetCollapsable::width(Painter & pain, LyXFont const & font) const
140 {
141     if (collapsed) 
142         return widthCollapsed;
143
144     return inset->width(pain, font) + widthCollapsed;
145 }
146
147
148 void InsetCollapsable::draw_collapsed(Painter & pain, LyXFont const &,
149                                       int baseline, float & x) const
150 {
151     int width = 0;
152     pain.buttonText(int(x) + TEXT_TO_INSET_OFFSET,
153                     baseline, label.c_str(), labelfont, true, width);
154     x += width + TEXT_TO_INSET_OFFSET;
155 }
156
157
158 void InsetCollapsable::draw(BufferView * bv, LyXFont const & f, 
159                             int baseline, float & x, bool cleared) const
160 {
161     Painter & pain = bv->painter();
162
163     button_length = widthCollapsed;
164     button_top_y = -ascent_collapsed(pain, f);
165     button_bottom_y = descent_collapsed(pain, f);
166     if (collapsed) {
167         draw_collapsed(pain, f, baseline, x);
168         x += TEXT_TO_INSET_OFFSET;
169         return;
170     }
171
172     if (!cleared && ((inset->need_update == InsetText::FULL) ||
173                      (top_x!=int(x)) || (top_baseline!=baseline))) {
174         int w =  owner()? width(pain, f) : pain.paperWidth();
175         int h = ascent(pain,f) + descent(pain, f);
176         int tx = (needFullRow() && !owner())? 0:int(x);
177         int ty = baseline - ascent(pain,f);
178         
179         if (ty < 0)
180             ty = 0;
181         if ((ty + h) > pain.paperHeight())
182             h = pain.paperHeight();
183         if ((top_x + w) > pain.paperWidth())
184             w = pain.paperWidth();
185         pain.fillRectangle(tx, ty-1, w, h+2);
186         cleared = true;
187     }
188
189     // not needed if collapsed
190     top_x = int(x);
191     top_baseline = baseline;
192
193     draw_collapsed(pain, f, baseline, x);
194     inset->draw(bv, f, baseline, x, cleared);
195     need_update = NONE;
196 }
197
198
199 void InsetCollapsable::Edit(BufferView * bv, int x, int y, unsigned int button)
200 {
201     UpdatableInset::Edit(bv, x, y, button);
202
203     if (collapsed && autocollapse) {
204         collapsed = false;
205         if (!bv->lockInset(this))
206             return;
207         bv->updateInset(this, false);
208         inset->Edit(bv, 0, 0, button);
209     } else if (!collapsed) {
210         if (!bv->lockInset(this))
211             return;
212         inset->Edit(bv, x-widthCollapsed, y, button);
213     }
214 }
215
216
217 Inset::EDITABLE InsetCollapsable::Editable() const
218 {
219         if (collapsed)
220                 return IS_EDITABLE;
221         return HIGHLY_EDITABLE;
222 }
223
224
225 void InsetCollapsable::InsetUnlock(BufferView * bv)
226 {
227     if (autocollapse) {
228         collapsed = true;
229     }
230     inset->InsetUnlock(bv);
231     bv->updateInset(this, false);
232 }
233
234
235 void InsetCollapsable::InsetButtonPress(BufferView * bv,int x,int y,int button)
236 {
237     if (!collapsed && (x >= button_length)) {
238         inset->InsetButtonPress(bv, x-widthCollapsed, y, button);
239     }
240 }
241
242
243 void InsetCollapsable::InsetButtonRelease(BufferView * bv,
244                                           int x, int y, int button)
245 {
246     if ((x >= 0)  && (x < button_length) &&
247         (y >= button_top_y) &&  (y < button_bottom_y)) {
248         if (collapsed) {
249             collapsed = false;
250             inset->InsetButtonRelease(bv, 0, 0, button);
251             bv->updateInset(this, false);
252         } else {
253             collapsed = true;
254             bv->unlockInset(this);
255             bv->updateInset(this, false);
256         }
257     } else if (!collapsed && (x >= button_length) && (y >= button_top_y)) {
258         inset->InsetButtonRelease(bv, x-widthCollapsed, y, button);
259     }
260 }
261
262
263 void InsetCollapsable::InsetMotionNotify(BufferView * bv,
264                                          int x, int y, int state)
265 {
266     if (x >= button_length) {
267         inset->InsetMotionNotify(bv, x-widthCollapsed, y, state);
268     }
269 }
270
271
272 void InsetCollapsable::InsetKeyPress(XKeyEvent * xke)
273 {
274     inset->InsetKeyPress(xke);
275 }
276
277
278 int InsetCollapsable::Latex(Buffer const * buf, ostream & os, bool fragile, bool free_spc) const
279 {
280     return inset->Latex(buf, os, fragile, free_spc);
281 }
282
283
284 int InsetCollapsable::getMaxWidth(Painter & pain,
285                                   UpdatableInset const * inset) const
286 {
287     int w;
288     if (owner())
289         w = static_cast<UpdatableInset*>(owner())->getMaxWidth(pain,inset);
290     else
291         w = pain.paperWidth();
292
293     if (w < 0)
294         return w;
295
296     return w; // - top_x - widthCollapsed;
297 }
298
299
300 int InsetCollapsable::getMaxTextWidth(Painter & pain,
301                                       UpdatableInset const * inset) const
302 {
303     return getMaxWidth(pain, inset) - widthCollapsed;
304 }
305
306
307 void InsetCollapsable::update(BufferView * bv, LyXFont const & font,
308                               bool dodraw)
309 {
310     if (!widthCollapsed) {
311         widthCollapsed = width_collapsed(bv->painter(), font);
312         inset->deleteLyXText(bv);
313         need_update = FULL;
314         if (owner()) {
315                 owner()->update(bv, font, dodraw);
316                 return;
317         }
318     }
319     if (oldWidth != width(bv->painter(), font)) {
320         oldWidth = width(bv->painter(), font);
321         inset->deleteLyXText(bv);
322         need_update = FULL;
323         if (owner()) {
324                 owner()->update(bv, font, dodraw);
325                 return;
326         }
327     }
328     inset->update(bv, font, dodraw);
329 }
330
331 UpdatableInset::RESULT
332 InsetCollapsable::LocalDispatch(BufferView * bv, int action, string const & arg)
333 {
334     UpdatableInset::RESULT result = inset->LocalDispatch(bv, action, arg);
335     if (result == FINISHED)
336         bv->unlockInset(this);
337     return result;
338 }
339
340 bool InsetCollapsable::LockInsetInInset(BufferView * bv, UpdatableInset * in)
341 {
342     if (inset == in)
343         return true;
344     return inset->LockInsetInInset(bv, in);
345 }
346
347
348 bool InsetCollapsable::UnlockInsetInInset(BufferView * bv, UpdatableInset * in,
349                                           bool lr)
350 {
351     if (inset == in) {
352         bv->unlockInset(this);
353         return true;
354     }
355     return inset->UnlockInsetInInset(bv, in, lr);
356 }
357
358
359 bool InsetCollapsable::UpdateInsetInInset(BufferView * bv, Inset *in)
360 {
361     if (in == inset)
362         return true;
363     return inset->UpdateInsetInInset(bv, in);
364 }
365
366
367 int InsetCollapsable::InsetInInsetY()
368 {
369     return inset->InsetInInsetY();
370 }
371
372
373 void InsetCollapsable::Validate(LaTeXFeatures & features) const
374 {
375     inset->Validate(features);
376 }
377
378
379 void InsetCollapsable::GetCursorPos(BufferView * bv, int & x, int & y) const
380 {
381     inset->GetCursorPos(bv, x , y);
382 }
383
384
385 void InsetCollapsable::ToggleInsetCursor(BufferView * bv)
386 {
387     inset->ToggleInsetCursor(bv);
388 }
389
390
391 UpdatableInset * InsetCollapsable::GetLockingInset()
392 {
393     UpdatableInset * in = inset->GetLockingInset();
394     if (inset == in)
395         return this;
396     return in;
397 }
398
399
400 UpdatableInset * InsetCollapsable::GetFirstLockingInsetOfType(Inset::Code c)
401 {
402     if (c == LyxCode())
403         return this;
404     return inset->GetFirstLockingInsetOfType(c);
405 }
406
407
408 void InsetCollapsable::SetFont(BufferView * bv,
409                                LyXFont const & font, bool toggleall)
410 {
411     inset->SetFont(bv, font, toggleall);
412 }
413
414 bool InsetCollapsable::doClearArea() const
415 {
416     return inset->doClearArea();
417 }
418
419
420 LyXText * InsetCollapsable::getLyXText(BufferView * bv) const
421 {
422     return inset->getLyXText(bv);
423 }
424
425
426 void InsetCollapsable::deleteLyXText(BufferView * bv)
427 {
428     inset->deleteLyXText(bv);
429 }