]> git.lyx.org Git - features.git/blob - src/insets/insetminipage.C
Replace LString.h with support/std_string.h,
[features.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
23 #include "support/std_sstream.h"
24
25 using std::endl;
26 using std::auto_ptr;
27 using std::ostream;
28
29
30 // Some information about Minipages in LaTeX:
31 // A minipage is a complete miniversion of a page and can contain
32 // its own footnotes, paragraphs, and array, tabular, and multicols
33 // environments. However it cannot contain floats or \marginpar's,
34 // but it can appear inside floats.
35 //
36 // The minipage environment is defined like this:
37 //
38 // \begin{minipage}[pos][height][inner-pos]{width} <text> \end{minipage}
39 //
40 // Where:
41 //     pos [opt] = is the vertical placement of the box with respect
42 //                 to the text baseline, [c], [t] and [b].
43 //     height [opt] = the height of the box
44 //     inner-pos [opt] = the position of the text within the box.
45 //                 It can be t, c, b or s, if unspecified the value
46 //                 of pos is used.
47 //     width = the width of the box
48 //
49 // In LyX we should try to support all these parameters, settable in a
50 // pop-up dialog.
51 // In this pop-up diallog it should also be possible to set all margin
52 // values that is usable in the minipage.
53 // With regard to different formats (like DocBook) I guess a minipage
54 // can be used there also. Perhaps not in the latex way, but we do not
55 // have to output "" for minipages.
56 // (Lgb)
57
58 InsetMinipage::InsetMinipage(BufferParams const & bp)
59         : InsetCollapsable(bp)
60 {
61         setLabel(_("minipage"));
62         LyXFont font(LyXFont::ALL_SANE);
63         font.decSize();
64         font.decSize();
65         font.setColor(LColor::collapsable);
66         setLabelFont(font);
67 #if 0
68         setAutoCollapse(false);
69 #endif
70         inset.setFrameColor(LColor::blue);
71         setInsetName("Minipage");
72 }
73
74
75 InsetMinipage::InsetMinipage(InsetMinipage const & in)
76         : InsetCollapsable(in), params_(in.params_)
77 {}
78
79
80 auto_ptr<InsetBase> InsetMinipage::clone() const
81 {
82         return auto_ptr<InsetBase>(new InsetMinipage(*this));
83 }
84
85
86 InsetMinipage::~InsetMinipage()
87 {
88         InsetMinipageMailer(*this).hideDialog();
89 }
90
91
92 dispatch_result InsetMinipage::localDispatch(FuncRequest const & cmd)
93 {
94         switch (cmd.action) {
95         case LFUN_INSET_MODIFY: {
96                 InsetMinipage::Params params;
97                 InsetMinipageMailer::string2params(cmd.argument, params);
98
99                 params_.pos   = params.pos;
100                 params_.width = params.width;
101
102                 /* FIXME: I refuse to believe we have to live
103                  * with ugliness like this ... */
104                 inset.getLyXText(cmd.view())->fullRebreak();
105                 cmd.view()->updateInset(this);
106                 return DISPATCHED;
107         }
108
109         case LFUN_INSET_DIALOG_UPDATE:
110                 InsetMinipageMailer(*this).updateDialog(cmd.view());
111                 return DISPATCHED;
112
113         default:
114                 return InsetCollapsable::localDispatch(cmd);
115         }
116 }
117
118
119 void InsetMinipage::Params::write(ostream & os) const
120 {
121         os << "Minipage" << '\n'
122            << "position " << pos << '\n'
123            << "inner_position " << inner_pos << '\n'
124            << "height \"" << height.asString() << "\"\n"
125            << "width \"" << width.asString() << "\"\n";
126 }
127
128
129 void InsetMinipage::Params::read(LyXLex & lex)
130 {
131         if (lex.isOK()) {
132                 lex.next();
133                 string const token = lex.getString();
134                 if (token == "position") {
135                         lex.next();
136                         pos = static_cast<Position>(lex.getInteger());
137                 } else {
138                         lyxerr << "InsetMinipage::Read: Missing '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 == "inner_position") {
148                         lex.next();
149                         inner_pos = static_cast<InnerPosition>(lex.getInteger());
150                 } else {
151                         lyxerr << "InsetMinipage::Read: Missing 'inner_position'-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 == "height") {
161                         lex.next();
162                         height = LyXLength(lex.getString());
163                 } else {
164                         lyxerr << "InsetMinipage::Read: Missing 'height'-tag!"
165                                    << endl;
166                         // take countermeasures
167                         lex.pushToken(token);
168                 }
169         }
170         if (lex.isOK()) {
171                 lex.next();
172                 string const token = lex.getString();
173                 if (token == "width") {
174                         lex.next();
175                         width = LyXLength(lex.getString());
176                 } else {
177                         lyxerr << "InsetMinipage::Read: Missing 'width'-tag!"
178                                    << endl;
179                         // take countermeasures
180                         lex.pushToken(token);
181                 }
182         }
183 }
184
185
186 void InsetMinipage::write(Buffer const & buf, ostream & os) const
187 {
188         params_.write(os);
189         InsetCollapsable::write(buf, os);
190 }
191
192
193 void InsetMinipage::read(Buffer const & buf, LyXLex & lex)
194 {
195         params_.read(lex);
196         InsetCollapsable::read(buf, lex);
197 }
198
199
200 void InsetMinipage::metrics(MetricsInfo & mi, Dimension & dim) const
201 {
202         if (collapsed_)
203                 dimension_collapsed(dim);
204         else {
205                 Dimension d;
206                 MetricsInfo m = mi;
207                 m.base.textwidth = params_.width.inPixels(mi.base.textwidth);
208                 InsetCollapsable::metrics(m, d);
209                 switch (params_.pos) {
210                 case top:
211                         dim.asc = d.asc;
212                         dim.des = d.des;
213                         break;
214                 case center:
215                         dim.asc = d.ascent() + d.descent() / 2;
216                         dim.des = dim.asc;
217                         break;
218                 case bottom:
219                         dim.asc = d.des;
220                         dim.des = d.asc;
221                         break;
222                 }
223                 dim.wid = d.wid;
224         }
225         dim_ = dim;
226 }
227
228
229 string const InsetMinipage::editMessage() const
230 {
231         return _("Opened Minipage Inset");
232 }
233
234
235 int InsetMinipage::latex(Buffer const & buf, ostream & os,
236                          LatexRunParams const & runparams) const
237 {
238         string s_pos;
239         switch (params_.pos) {
240         case top:
241                 s_pos += 't';
242                 break;
243         case center:
244                 s_pos += 'c';
245                 break;
246         case bottom:
247                 s_pos += 'b';
248                 break;
249         }
250         os << "\\begin{minipage}[" << s_pos << "]{"
251            << params_.width.asLatexString() << "}%\n";
252
253         int i = inset.latex(buf, os, runparams);
254
255         os << "\\end{minipage}%\n";
256         return i + 2;
257 }
258
259
260 bool InsetMinipage::insetAllowed(InsetOld::Code code) const
261 {
262         if (code == InsetOld::FLOAT_CODE || code == InsetOld::MARGIN_CODE)
263                 return false;
264
265         return InsetCollapsable::insetAllowed(code);
266 }
267
268
269 bool InsetMinipage::showInsetDialog(BufferView * bv) const
270 {
271         if (!inset.showInsetDialog(bv)) {
272                 InsetMinipage * tmp = const_cast<InsetMinipage *>(this);
273                 InsetMinipageMailer mailer(*tmp);
274                 mailer.showDialog(bv);
275         }
276
277         return true;
278 }
279
280
281 int InsetMinipage::latexTextWidth(BufferView * bv) const
282 {
283         return params_.width.inPixels(InsetCollapsable::latexTextWidth(bv));
284 }
285
286
287 InsetMinipage::Params::Params()
288         : pos(center),
289           inner_pos(inner_center),
290           width(100, LyXLength::PCW)
291 {}
292
293
294 string const InsetMinipageMailer:: name_("minipage");
295
296 InsetMinipageMailer::InsetMinipageMailer(InsetMinipage & inset)
297         : inset_(inset)
298 {}
299
300
301 string const InsetMinipageMailer::inset2string(Buffer const &) const
302 {
303         return params2string(inset_.params());
304 }
305
306
307 void InsetMinipageMailer::string2params(string const & in,
308                                         InsetMinipage::Params & params)
309 {
310         params = InsetMinipage::Params();
311
312         if (in.empty())
313                 return;
314
315         istringstream data(STRCONV(in));
316         LyXLex lex(0, 0);
317         lex.setStream(data);
318
319         if (lex.isOK()) {
320                 lex.next();
321                 string const token = lex.getString();
322                 if (token != "minipage")
323                         return;
324         }
325
326         // This is part of the inset proper that is usually swallowed
327         // by Buffer::readInset
328         if (lex.isOK()) {
329                 lex.next();
330                 string const token = lex.getString();
331                 if (token != "Minipage")
332                         return;
333         }
334
335         if (lex.isOK()) {
336                 params.read(lex);
337         }
338 }
339
340
341 string const
342 InsetMinipageMailer::params2string(InsetMinipage::Params const & params)
343 {
344         ostringstream data;
345         data << name_ << ' ';
346         params.write(data);
347         return STRCONV(data.str());
348 }