]> git.lyx.org Git - lyx.git/blob - src/insets/insetminipage.C
Collapse all those LFUN_XYZ_APPLY to a single LFUN_INSET_APPLY.
[lyx.git] / src / insets / insetminipage.C
1 /**
2  * \file insetminipage.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Jürgen Vigna
7  * \author Lars Gullik Bjønnes
8  *
9  * Full author contact details are available in file CREDITS
10  */
11
12 #include <config.h>
13
14
15 #include "insetminipage.h"
16 #include "gettext.h"
17 #include "lyxfont.h"
18 #include "BufferView.h"
19 #include "frontends/LyXView.h"
20 #include "frontends/Dialogs.h"
21 #include "lyxtext.h"
22 #include "insets/insettext.h"
23 #include "support/LOstream.h"
24 #include "support/lstrings.h"
25 #include "debug.h"
26 #include "gettext.h"
27 #include "lyxlex.h"
28
29 using std::ostream;
30 using std::endl;
31
32
33 // Some information about Minipages in LaTeX:
34 // A minipage is a complete miniversion of a page and can contain
35 // its own footnotes, paragraphs, and array, tabular, and multicols
36 // environments. However it cannot contain floats or \marginpar's,
37 // but it can appear inside floats.
38 //
39 // The minipage environment is defined like this:
40 //
41 // \begin{minipage}[pos][height][inner-pos]{width} <text> \end{minipage}
42 //
43 // Where:
44 //     pos [opt] = is the vertical placement of the box with respect
45 //                 to the text baseline, [c], [t] and [b].
46 //     height [opt] = the height of the box
47 //     inner-pos [opt] = the position of the text within the box.
48 //                 It can be t, c, b or s, if unspecified the value
49 //                 of pos is used.
50 //     width = the width of the box
51 //
52 // In LyX we should try to support all these parameters, settable in a
53 // pop-up dialog.
54 // In this pop-up diallog it should also be possible to set all margin
55 // values that is usable in the minipage.
56 // With regard to different formats (like DocBook) I guess a minipage
57 // can be used there also. Perhaps not in the latex way, but we do not
58 // have to output "" for minipages.
59 // (Lgb)
60
61 InsetMinipage::InsetMinipage(BufferParams const & bp)
62         : InsetCollapsable(bp), pos_(center),
63           inner_pos_(inner_center), width_(100, LyXLength::PCW)
64 {
65         setLabel(_("minipage"));
66         LyXFont font(LyXFont::ALL_SANE);
67         font.decSize();
68         font.decSize();
69         font.setColor(LColor::collapsable);
70         setLabelFont(font);
71 #if 0
72         setAutoCollapse(false);
73 #endif
74
75 #if 0
76 #ifdef WITH_WARNINGS
77 #warning Remove this color definitions before 1.2.0 final!
78 #endif
79         // just for experimentation :)
80         setBackgroundColor(LColor::green);
81 #endif
82
83         inset.setFrameColor(0, LColor::blue);
84         setInsetName("Minipage");
85 }
86
87
88 InsetMinipage::InsetMinipage(InsetMinipage const & in, bool same_id)
89         : InsetCollapsable(in, same_id),
90           pos_(in.pos_), inner_pos_(in.inner_pos_),
91           height_(in.height_), width_(in.width_)
92 {}
93
94
95 Inset * InsetMinipage::clone(Buffer const &, bool same_id) const
96 {
97         return new InsetMinipage(*const_cast<InsetMinipage *>(this), same_id);
98 }
99
100
101 InsetMinipage::~InsetMinipage()
102 {
103         hideDialog();
104 }
105
106
107 void InsetMinipage::write(Buffer const * buf, ostream & os) const
108 {
109         os << getInsetName() << '\n'
110            << "position " << pos_ << '\n'
111            << "inner_position " << inner_pos_ << '\n'
112            << "height \"" << height_.asString() << "\"\n"
113            << "width \"" << width_.asString() << "\"\n";
114         InsetCollapsable::write(buf, os);
115 }
116
117
118 void InsetMinipage::read(Buffer const * buf, LyXLex & lex)
119 {
120         if (lex.isOK()) {
121                 lex.next();
122                 string const token = lex.getString();
123                 if (token == "position") {
124                         lex.next();
125                         pos_ = static_cast<Position>(lex.getInteger());
126                 } else {
127                         lyxerr << "InsetMinipage::Read: Missing 'position'-tag!"
128                                    << endl;
129                         // take countermeasures
130                         lex.pushToken(token);
131                 }
132         }
133         if (lex.isOK()) {
134                 lex.next();
135                 string const token = lex.getString();
136                 if (token == "inner_position") {
137                         lex.next();
138                         inner_pos_ = static_cast<InnerPosition>(lex.getInteger());
139                 } else {
140                         lyxerr << "InsetMinipage::Read: Missing 'inner_position'-tag!"
141                                    << endl;
142                         // take countermeasures
143                         lex.pushToken(token);
144                 }
145         }
146         if (lex.isOK()) {
147                 lex.next();
148                 string const token = lex.getString();
149                 if (token == "height") {
150                         lex.next();
151                         height_ = LyXLength(lex.getString());
152                 } else {
153                         lyxerr << "InsetMinipage::Read: Missing 'height'-tag!"
154                                    << endl;
155                         // take countermeasures
156                         lex.pushToken(token);
157                 }
158         }
159         if (lex.isOK()) {
160                 lex.next();
161                 string const token = lex.getString();
162                 if (token == "width") {
163                         lex.next();
164                         width_ = LyXLength(lex.getString());
165                 } else {
166                         lyxerr << "InsetMinipage::Read: Missing 'width'-tag!"
167                                    << endl;
168                         // take countermeasures
169                         lex.pushToken(token);
170                 }
171         }
172         InsetCollapsable::read(buf, lex);
173 }
174
175
176 int InsetMinipage::ascent(BufferView * bv, LyXFont const & font) const
177 {
178         if (collapsed_)
179                 return ascent_collapsed();
180         else {
181                 // Take placement into account.
182                 int i = 0;
183                 switch (pos_) {
184                 case top:
185                         i = InsetCollapsable::ascent(bv, font);
186                         break;
187                 case center:
188                         i = (InsetCollapsable::ascent(bv, font)
189                              + InsetCollapsable::descent(bv, font)) / 2;
190                         break;
191                 case bottom:
192                         i = InsetCollapsable::descent(bv, font);
193                         break;
194                 }
195                 return i;
196         }
197 }
198
199
200 int InsetMinipage::descent(BufferView * bv, LyXFont const & font) const
201 {
202         if (collapsed_)
203                 return descent_collapsed();
204         else {
205                 // Take placement into account.
206                 int i = 0;
207                 switch (pos_) {
208                 case top:
209                         i = InsetCollapsable::descent(bv, font);
210                         break;
211                 case center:
212                         i = (InsetCollapsable::ascent(bv, font)
213                              + InsetCollapsable::descent(bv, font)) / 2;
214                         break;
215                 case bottom:
216                         i = InsetCollapsable::ascent(bv, font);
217                         break;
218                 }
219                 return i;
220         }
221 }
222
223
224 string const InsetMinipage::editMessage() const
225 {
226         return _("Opened Minipage Inset");
227 }
228
229
230 int InsetMinipage::latex(Buffer const * buf,
231                          ostream & os, bool fragile, bool fp) const
232 {
233         string s_pos;
234         switch (pos_) {
235         case top:
236                 s_pos += 't';
237                 break;
238         case center:
239                 s_pos += 'c';
240                 break;
241         case bottom:
242                 s_pos += 'b';
243                 break;
244         }
245         os << "\\begin{minipage}[" << s_pos << "]{"
246            << width_.asLatexString() << "}%\n";
247
248         int i = inset.latex(buf, os, fragile, fp);
249
250         os << "\\end{minipage}%\n";
251         return i + 2;
252 }
253
254
255 bool InsetMinipage::insetAllowed(Inset::Code code) const
256 {
257         if ((code == Inset::FLOAT_CODE) || (code == Inset::MARGIN_CODE))
258                 return false;
259
260         return InsetCollapsable::insetAllowed(code);
261 }
262
263
264 InsetMinipage::Position InsetMinipage::pos() const
265 {
266         return pos_;
267 }
268
269
270 void InsetMinipage::pos(InsetMinipage::Position p)
271 {
272         if (pos_ != p) {
273                 pos_ = p;
274                 need_update = FULL;
275         }
276 }
277
278
279 InsetMinipage::InnerPosition InsetMinipage::innerPos() const
280 {
281         return inner_pos_;
282 }
283
284
285 void InsetMinipage::innerPos(InsetMinipage::InnerPosition ip)
286 {
287         inner_pos_ = ip;
288 }
289
290
291 LyXLength const & InsetMinipage::pageHeight() const
292 {
293         return height_;
294 }
295
296
297 void InsetMinipage::pageHeight(LyXLength const & ll)
298 {
299         if (height_ != ll) {
300                 height_ = ll;
301                 need_update = FULL;
302         }
303 }
304
305
306 LyXLength const & InsetMinipage::pageWidth() const
307 {
308         return width_;
309 }
310
311
312 void InsetMinipage::pageWidth(LyXLength const & ll)
313 {
314         if (ll != width_) {
315                 width_ = ll;
316                 need_update = FULL;
317         }
318 }
319
320
321 bool InsetMinipage::showInsetDialog(BufferView * bv) const
322 {
323         if (!inset.showInsetDialog(bv))
324                 bv->owner()->getDialogs().showMinipage(const_cast<InsetMinipage *>(this));
325         return true;
326 }
327
328
329 int InsetMinipage::getMaxWidth(BufferView * bv, UpdatableInset const * inset)
330         const
331 {
332         if (owner() &&
333             static_cast<UpdatableInset*>(owner())->getMaxWidth(bv, inset) < 0) {
334                 return -1;
335         }
336         if (!width_.zero()) {
337                 int ww1 = latexTextWidth(bv);
338                 int ww2 = InsetCollapsable::getMaxWidth(bv, inset);
339                 if (ww2 > 0 && ww2 < ww1) {
340                         return ww2;
341                 }
342                 return ww1;
343         }
344         // this should not happen!
345         return InsetCollapsable::getMaxWidth(bv, inset);
346 }
347
348
349 int InsetMinipage::latexTextWidth(BufferView * bv) const
350 {
351         return width_.inPixels(InsetCollapsable::latexTextWidth(bv));
352 }