]> git.lyx.org Git - lyx.git/blob - src/insets/insetwrap.C
b1d92c0d40a8070d22503a9e1d8c9f486b318b27
[lyx.git] / src / insets / insetwrap.C
1 /**
2  * \file insetwrap.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Dekel Tsur
7  *
8  * Full author contact details are available in file CREDITS
9  */
10
11 #include <config.h>
12
13 #include "insetwrap.h"
14 #include "insettext.h"
15
16 #include "buffer.h"
17 #include "BufferView.h"
18 #include "debug.h"
19 #include "funcrequest.h"
20 #include "FloatList.h"
21 #include "gettext.h"
22 #include "LaTeXFeatures.h"
23 #include "lyxfont.h"
24 #include "lyxlex.h"
25 #include "lyxtext.h"
26
27 #include "frontends/LyXView.h"
28 #include "frontends/Dialogs.h"
29
30 #include "support/LOstream.h"
31 #include "support/lstrings.h"
32
33 using std::ostream;
34 using std::endl;
35
36 namespace {
37
38 // this should not be hardcoded, but be part of the definition
39 // of the float (JMarc)
40 string const caplayout("Caption");
41 string floatname(string const & type, BufferParams const & bp)
42 {
43         FloatList const & floats = bp.getLyXTextClass().floats();
44         FloatList::const_iterator it = floats[type];
45         if (it == floats.end())
46                 return type;
47
48         return _(it->second.name());
49 }
50
51 } // namespace anon
52
53
54 InsetWrap::InsetWrap(BufferParams const & bp, string const & type)
55         : InsetCollapsable(bp)
56 {
57         string lab(_("wrap: "));
58         lab += floatname(type, bp);
59         setLabel(lab);
60         LyXFont font(LyXFont::ALL_SANE);
61         font.decSize();
62         font.decSize();
63         font.setColor(LColor::collapsable);
64         setLabelFont(font);
65         params_.type = type;
66         params_.width = LyXLength(50, LyXLength::PCW);
67         setInsetName(type);
68         LyXTextClass const & tclass = bp.getLyXTextClass();
69         if (tclass.hasLayout(caplayout))
70                 inset.paragraph()->layout(tclass[caplayout]);
71 }
72
73
74 InsetWrap::InsetWrap(InsetWrap const & in, bool same_id)
75         : InsetCollapsable(in, same_id), params_(in.params_)
76 {}
77
78
79 InsetWrap::~InsetWrap()
80 {
81         InsetWrapMailer mailer(*this);
82         mailer.hideDialog();
83 }
84
85
86 dispatch_result InsetWrap::localDispatch(FuncRequest const & cmd)
87 {
88         Inset::RESULT result = UNDISPATCHED;
89
90         switch (cmd.action) {
91         case LFUN_INSET_MODIFY: {
92                 InsetWrapParams params;
93                 InsetWrapMailer::string2params(cmd.argument, params);
94
95                 params_.placement = params.placement;
96                 params_.width     = params.width;
97
98                 cmd.view()->updateInset(this);
99                 result = DISPATCHED;
100         }
101         break;
102
103         case LFUN_INSET_DIALOG_UPDATE: {
104                 InsetWrapMailer mailer(*this);
105                 mailer.updateDialog(cmd.view());
106         }
107         break;
108
109         default:
110                 result = InsetCollapsable::localDispatch(cmd);
111         }
112
113         return result;
114 }
115
116
117 void InsetWrapParams::write(ostream & os) const
118 {
119         os << "Wrap " // getInsetName()
120            << type << '\n';
121
122         if (!placement.empty()) {
123                 os << "placement " << placement << "\n";
124         }
125         os << "width \"" << width.asString() << "\"\n";
126 }
127
128
129 void InsetWrapParams::read(LyXLex & lex)
130 {
131         if (lex.isOK()) {
132                 lex.next();
133                 string token = lex.getString();
134                 if (token == "placement") {
135                         lex.next();
136                         placement = lex.getString();
137                 } else {
138                         // take countermeasures
139                         lex.pushToken(token);
140                 }
141         }
142         if (lex.isOK()) {
143                 lex.next();
144                 string token = lex.getString();
145                 if (token == "width") {
146                         lex.next();
147                         width = LyXLength(lex.getString());
148                 } else {
149                         lyxerr << "InsetWrap::Read:: Missing 'width'-tag!"
150                                << endl;
151                         // take countermeasures
152                         lex.pushToken(token);
153                 }
154         }
155 }
156
157
158 void InsetWrap::write(Buffer const * buf, ostream & os) const
159 {
160         params_.write(os);
161         InsetCollapsable::write(buf, os);
162 }
163
164
165 void InsetWrap::read(Buffer const * buf, LyXLex & lex)
166 {
167         params_.read(lex);
168         InsetCollapsable::read(buf, lex);
169 }
170
171
172 void InsetWrap::validate(LaTeXFeatures & features) const
173 {
174         features.require("floatflt");
175         InsetCollapsable::validate(features);
176 }
177
178
179 Inset * InsetWrap::clone(Buffer const &, bool same_id) const
180 {
181         return new InsetWrap(*const_cast<InsetWrap *>(this), same_id);
182 }
183
184
185 string const InsetWrap::editMessage() const
186 {
187         return _("Opened Wrap Inset");
188 }
189
190
191 int InsetWrap::latex(Buffer const * buf,
192                       ostream & os, bool fragile, bool fp) const
193 {
194         os << "\\begin{floating" << params_.type << '}';
195         if (!params_.placement.empty()) {
196                 os << '[' << params_.placement << ']';
197         }
198         os  << '{' << params_.width.asLatexString() << "}%\n";
199
200         int const i = inset.latex(buf, os, fragile, fp);
201
202         os << "\\end{floating" << params_.type << "}%\n";
203         return i + 2;
204 }
205
206
207 int InsetWrap::docbook(Buffer const * buf, ostream & os, bool mixcont) const
208 {
209         os << '<' << params_.type << '>';
210         int const i = inset.docbook(buf, os, mixcont);
211         os << "</" << params_.type << '>';
212
213         return i;
214 }
215
216
217 bool InsetWrap::insetAllowed(Inset::Code code) const
218 {
219         switch(code) {
220         case FLOAT_CODE:
221         case FOOT_CODE:
222         case MARGIN_CODE:
223                 return false;
224         default:
225                 return InsetCollapsable::insetAllowed(code);
226         }
227 }
228
229
230 int InsetWrap::getMaxWidth(BufferView * bv, UpdatableInset const * inset)
231         const
232 {
233         if (owner() &&
234             static_cast<UpdatableInset*>(owner())->getMaxWidth(bv, inset) < 0) {
235                 return -1;
236         }
237         if (!params_.width.zero()) {
238                 int const ww1 = latexTextWidth(bv);
239                 int const ww2 = InsetCollapsable::getMaxWidth(bv, inset);
240                 if (ww2 > 0 && ww2 < ww1) {
241                         return ww2;
242                 }
243                 return ww1;
244         }
245         // this should not happen!
246         return InsetCollapsable::getMaxWidth(bv, inset);
247 }
248
249
250 int InsetWrap::latexTextWidth(BufferView * bv) const
251 {
252         return params_.width.inPixels(InsetCollapsable::latexTextWidth(bv));
253 }
254
255
256 string const & InsetWrap::type() const
257 {
258         return params_.type;
259 }
260
261
262 LyXLength const & InsetWrap::pageWidth() const
263 {
264         return params_.width;
265 }
266
267
268 void InsetWrap::pageWidth(LyXLength const & ll)
269 {
270         if (ll != params_.width) {
271                 params_.width = ll;
272                 need_update = FULL;
273         }
274 }
275
276
277 void InsetWrap::placement(string const & p)
278 {
279         params_.placement = p;
280 }
281
282
283 string const & InsetWrap::placement() const
284 {
285         return params_.placement;
286 }
287
288
289 bool InsetWrap::showInsetDialog(BufferView * bv) const
290 {
291         if (!inset.showInsetDialog(bv)) {
292                 InsetWrap * tmp = const_cast<InsetWrap *>(this);
293                 InsetWrapMailer mailer(*tmp);
294                 mailer.showDialog(bv);
295         }
296         return true;
297 }
298
299
300 void InsetWrap::addToToc(toc::TocList & toclist, Buffer const * buf) const
301 {
302         // Now find the caption in the float...
303         // We now tranverse the paragraphs of
304         // the inset...
305         Paragraph * tmp = inset.paragraph();
306         while (tmp) {
307                 if (tmp->layout()->name() == caplayout) {
308                         string const name = floatname(type(), buf->params);
309                         string const str =
310                                 tostr(toclist[name].size() + 1)
311                                 + ". " + tmp->asString(buf, false);
312                         toc::TocItem const item(tmp->id(), 0 , str);
313                         toclist[name].push_back(item);
314                 }
315                 tmp = tmp->next();
316         }
317 }
318
319
320 string const InsetWrapMailer::name_("wrap");
321
322 InsetWrapMailer::InsetWrapMailer(InsetWrap & inset)
323         : inset_(inset)
324 {}
325
326
327 string const InsetWrapMailer::inset2string() const
328 {
329         return params2string(inset_.params());
330 }
331
332
333 void InsetWrapMailer::string2params(string const & in,
334                                     InsetWrapParams & params)
335 {
336         params = InsetWrapParams();
337
338         istringstream data(in);
339         LyXLex lex(0,0);
340         lex.setStream(data);
341
342         if (lex.isOK()) {
343                 lex.next();
344                 string const token = lex.getString();
345                 if (token != name_)
346                         return;
347         }
348
349         // This is part of the inset proper that is usually swallowed
350         // by Buffer::readInset
351         if (lex.isOK()) {
352                 lex.next();
353                 string const token = lex.getString();
354                 if (token != "Wrap" || !lex.eatLine())
355                         return;
356         }
357
358         if (lex.isOK()) {
359                 params.read(lex);
360         }
361 }
362
363
364 string const
365 InsetWrapMailer::params2string(InsetWrapParams const & params)
366 {
367         ostringstream data;
368         data << name_ << ' ';
369         params.write(data);
370
371         return data.str();
372 }