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