]> git.lyx.org Git - lyx.git/blob - src/insets/insetminipage.C
Get rid of trailing whitespace 'noise' in future patches for the
[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 #include "insetminipage.h"
15
16 #include "BufferView.h"
17 #include "debug.h"
18 #include "funcrequest.h"
19 #include "gettext.h"
20 #include "lyxlex.h"
21 #include "metricsinfo.h"
22 #include "paragraph.h"
23
24 #include "support/std_sstream.h"
25
26 using std::endl;
27 using std::auto_ptr;
28 using std::istringstream;
29 using std::ostream;
30 using std::ostringstream;
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)
63 {
64         setLabel(_("minipage"));
65         LyXFont font(LyXFont::ALL_SANE);
66         font.decSize();
67         font.decSize();
68         font.setColor(LColor::collapsable);
69         setLabelFont(font);
70 #if 0
71         setAutoCollapse(false);
72 #endif
73         inset.setFrameColor(LColor::blue);
74         setInsetName("Minipage");
75 }
76
77
78 InsetMinipage::InsetMinipage(InsetMinipage const & in)
79         : InsetCollapsable(in), params_(in.params_)
80 {}
81
82
83 auto_ptr<InsetBase> InsetMinipage::clone() const
84 {
85         return auto_ptr<InsetBase>(new InsetMinipage(*this));
86 }
87
88
89 InsetMinipage::~InsetMinipage()
90 {
91         InsetMinipageMailer(*this).hideDialog();
92 }
93
94
95 dispatch_result InsetMinipage::localDispatch(FuncRequest const & cmd)
96 {
97         switch (cmd.action) {
98         case LFUN_INSET_MODIFY: {
99                 InsetMinipage::Params params;
100                 InsetMinipageMailer::string2params(cmd.argument, params);
101
102                 params_.pos   = params.pos;
103                 params_.width = params.width;
104
105                 /* FIXME: I refuse to believe we have to live
106                  * with ugliness like this ... */
107                 inset.getLyXText(cmd.view())->fullRebreak();
108                 cmd.view()->updateInset(this);
109                 return DISPATCHED;
110         }
111
112         case LFUN_INSET_DIALOG_UPDATE:
113                 InsetMinipageMailer(*this).updateDialog(cmd.view());
114                 return DISPATCHED;
115
116         default:
117                 return InsetCollapsable::localDispatch(cmd);
118         }
119 }
120
121
122 void InsetMinipage::Params::write(ostream & os) const
123 {
124         os << "Minipage" << '\n'
125            << "position " << pos << '\n'
126            << "inner_position " << inner_pos << '\n'
127            << "height \"" << height.asString() << "\"\n"
128            << "width \"" << width.asString() << "\"\n";
129 }
130
131
132 void InsetMinipage::Params::read(LyXLex & lex)
133 {
134         if (lex.isOK()) {
135                 lex.next();
136                 string const token = lex.getString();
137                 if (token == "position") {
138                         lex.next();
139                         pos = static_cast<Position>(lex.getInteger());
140                 } else {
141                         lyxerr << "InsetMinipage::Read: Missing 'position'-tag!"
142                                    << endl;
143                         // take countermeasures
144                         lex.pushToken(token);
145                 }
146         }
147         if (lex.isOK()) {
148                 lex.next();
149                 string const token = lex.getString();
150                 if (token == "inner_position") {
151                         lex.next();
152                         inner_pos = static_cast<InnerPosition>(lex.getInteger());
153                 } else {
154                         lyxerr << "InsetMinipage::Read: Missing 'inner_position'-tag!"
155                                    << endl;
156                         // take countermeasures
157                         lex.pushToken(token);
158                 }
159         }
160         if (lex.isOK()) {
161                 lex.next();
162                 string const token = lex.getString();
163                 if (token == "height") {
164                         lex.next();
165                         height = LyXLength(lex.getString());
166                 } else {
167                         lyxerr << "InsetMinipage::Read: Missing 'height'-tag!"
168                                    << endl;
169                         // take countermeasures
170                         lex.pushToken(token);
171                 }
172         }
173         if (lex.isOK()) {
174                 lex.next();
175                 string const token = lex.getString();
176                 if (token == "width") {
177                         lex.next();
178                         width = LyXLength(lex.getString());
179                 } else {
180                         lyxerr << "InsetMinipage::Read: Missing 'width'-tag!"
181                                    << endl;
182                         // take countermeasures
183                         lex.pushToken(token);
184                 }
185         }
186 }
187
188
189 void InsetMinipage::write(Buffer const & buf, ostream & os) const
190 {
191         params_.write(os);
192         InsetCollapsable::write(buf, os);
193 }
194
195
196 void InsetMinipage::read(Buffer const & buf, LyXLex & lex)
197 {
198         params_.read(lex);
199         InsetCollapsable::read(buf, lex);
200 }
201
202
203 void InsetMinipage::metrics(MetricsInfo & mi, Dimension & dim) const
204 {
205         if (collapsed_)
206                 dimension_collapsed(dim);
207         else {
208                 Dimension d;
209                 MetricsInfo m = mi;
210                 m.base.textwidth = params_.width.inPixels(mi.base.textwidth);
211                 InsetCollapsable::metrics(m, d);
212                 switch (params_.pos) {
213                 case top:
214                         dim.asc = d.asc;
215                         dim.des = d.des;
216                         break;
217                 case center:
218                         dim.asc = d.ascent() + d.descent() / 2;
219                         dim.des = dim.asc;
220                         break;
221                 case bottom:
222                         dim.asc = d.des;
223                         dim.des = d.asc;
224                         break;
225                 }
226                 dim.wid = d.wid;
227         }
228         dim_ = dim;
229 }
230
231
232 string const InsetMinipage::editMessage() const
233 {
234         return _("Opened Minipage Inset");
235 }
236
237
238 int InsetMinipage::latex(Buffer const & buf, ostream & os,
239                          LatexRunParams const & runparams) const
240 {
241         string s_pos;
242         switch (params_.pos) {
243         case top:
244                 s_pos += 't';
245                 break;
246         case center:
247                 s_pos += 'c';
248                 break;
249         case bottom:
250                 s_pos += 'b';
251                 break;
252         }
253         os << "\\begin{minipage}[" << s_pos << "]{"
254            << params_.width.asLatexString() << "}%\n";
255
256         int i = inset.latex(buf, os, runparams);
257
258         os << "\\end{minipage}%\n";
259         return i + 2;
260 }
261
262
263 bool InsetMinipage::insetAllowed(InsetOld::Code code) const
264 {
265         if (code == InsetOld::FLOAT_CODE || code == InsetOld::MARGIN_CODE)
266                 return false;
267
268         return InsetCollapsable::insetAllowed(code);
269 }
270
271
272 bool InsetMinipage::showInsetDialog(BufferView * bv) const
273 {
274         if (!inset.showInsetDialog(bv)) {
275                 InsetMinipage * tmp = const_cast<InsetMinipage *>(this);
276                 InsetMinipageMailer mailer(*tmp);
277                 mailer.showDialog(bv);
278         }
279
280         return true;
281 }
282
283
284 int InsetMinipage::latexTextWidth(BufferView * bv) const
285 {
286         return params_.width.inPixels(InsetCollapsable::latexTextWidth(bv));
287 }
288
289
290 InsetMinipage::Params::Params()
291         : pos(center),
292           inner_pos(inner_center),
293           width(100, LyXLength::PCW)
294 {}
295
296
297 string const InsetMinipageMailer:: name_("minipage");
298
299 InsetMinipageMailer::InsetMinipageMailer(InsetMinipage & inset)
300         : inset_(inset)
301 {}
302
303
304 string const InsetMinipageMailer::inset2string(Buffer const &) const
305 {
306         return params2string(inset_.params());
307 }
308
309
310 void InsetMinipageMailer::string2params(string const & in,
311                                         InsetMinipage::Params & params)
312 {
313         params = InsetMinipage::Params();
314
315         if (in.empty())
316                 return;
317
318         istringstream data(STRCONV(in));
319         LyXLex lex(0, 0);
320         lex.setStream(data);
321
322         if (lex.isOK()) {
323                 lex.next();
324                 string const token = lex.getString();
325                 if (token != "minipage")
326                         return;
327         }
328
329         // This is part of the inset proper that is usually swallowed
330         // by Buffer::readInset
331         if (lex.isOK()) {
332                 lex.next();
333                 string const token = lex.getString();
334                 if (token != "Minipage")
335                         return;
336         }
337
338         if (lex.isOK()) {
339                 params.read(lex);
340         }
341 }
342
343
344 string const
345 InsetMinipageMailer::params2string(InsetMinipage::Params const & params)
346 {
347         ostringstream data;
348         data << name_ << ' ';
349         params.write(data);
350         return STRCONV(data.str());
351 }