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