]> git.lyx.org Git - lyx.git/blob - src/insets/insetwrap.C
e54e1fa6298ac49e8463f6501adc5c1d9e1240c8
[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, true);
99                 result = DISPATCHED;
100         }
101         break;
102         default:
103                 result = InsetCollapsable::localDispatch(cmd);
104         }
105
106         return result;
107 }
108
109
110 void InsetWrapParams::write(ostream & os) const
111 {
112         os << "Wrap " // getInsetName()
113            << type << '\n';
114
115         if (!placement.empty()) {
116                 os << "placement " << placement << "\n";
117         }
118         os << "width \"" << width.asString() << "\"\n";
119 }
120
121
122 void InsetWrapParams::read(LyXLex & lex)
123 {
124         if (lex.isOK()) {
125                 lex.next();
126                 string token = lex.getString();
127                 if (token == "placement") {
128                         lex.next();
129                         placement = lex.getString();
130                 } else {
131                         // take countermeasures
132                         lex.pushToken(token);
133                 }
134         }
135         if (lex.isOK()) {
136                 lex.next();
137                 string token = lex.getString();
138                 if (token == "width") {
139                         lex.next();
140                         width = LyXLength(lex.getString());
141                 } else {
142                         lyxerr << "InsetWrap::Read:: Missing 'width'-tag!"
143                                << endl;
144                         // take countermeasures
145                         lex.pushToken(token);
146                 }
147         }
148 }
149
150
151 void InsetWrap::write(Buffer const * buf, ostream & os) const
152 {
153         params_.write(os);
154         InsetCollapsable::write(buf, os);
155 }
156
157
158 void InsetWrap::read(Buffer const * buf, LyXLex & lex)
159 {
160         params_.read(lex);
161         InsetCollapsable::read(buf, lex);
162 }
163
164
165 void InsetWrap::validate(LaTeXFeatures & features) const
166 {
167         features.require("floatflt");
168         InsetCollapsable::validate(features);
169 }
170
171
172 Inset * InsetWrap::clone(Buffer const &, bool same_id) const
173 {
174         return new InsetWrap(*const_cast<InsetWrap *>(this), same_id);
175 }
176
177
178 string const InsetWrap::editMessage() const
179 {
180         return _("Opened Wrap Inset");
181 }
182
183
184 int InsetWrap::latex(Buffer const * buf,
185                       ostream & os, bool fragile, bool fp) const
186 {
187         os << "\\begin{floating" << params_.type << '}';
188         if (!params_.placement.empty()) {
189                 os << '[' << params_.placement << ']';
190         }
191         os  << '{' << params_.width.asLatexString() << "}%\n";
192
193         int const i = inset.latex(buf, os, fragile, fp);
194
195         os << "\\end{floating" << params_.type << "}%\n";
196         return i + 2;
197 }
198
199
200 int InsetWrap::docbook(Buffer const * buf, ostream & os, bool mixcont) const
201 {
202         os << '<' << params_.type << '>';
203         int const i = inset.docbook(buf, os, mixcont);
204         os << "</" << params_.type << '>';
205
206         return i;
207 }
208
209
210 bool InsetWrap::insetAllowed(Inset::Code code) const
211 {
212         switch(code) {
213         case FLOAT_CODE:
214         case FOOT_CODE:
215         case MARGIN_CODE:
216                 return false;
217         default:
218                 return InsetCollapsable::insetAllowed(code);
219         }
220 }
221
222
223 int InsetWrap::getMaxWidth(BufferView * bv, UpdatableInset const * inset)
224         const
225 {
226         if (owner() &&
227             static_cast<UpdatableInset*>(owner())->getMaxWidth(bv, inset) < 0) {
228                 return -1;
229         }
230         if (!params_.width.zero()) {
231                 int const ww1 = latexTextWidth(bv);
232                 int const ww2 = InsetCollapsable::getMaxWidth(bv, inset);
233                 if (ww2 > 0 && ww2 < ww1) {
234                         return ww2;
235                 }
236                 return ww1;
237         }
238         // this should not happen!
239         return InsetCollapsable::getMaxWidth(bv, inset);
240 }
241
242
243 int InsetWrap::latexTextWidth(BufferView * bv) const
244 {
245         return params_.width.inPixels(InsetCollapsable::latexTextWidth(bv));
246 }
247
248
249 string const & InsetWrap::type() const
250 {
251         return params_.type;
252 }
253
254
255 LyXLength const & InsetWrap::pageWidth() const
256 {
257         return params_.width;
258 }
259
260
261 void InsetWrap::pageWidth(LyXLength const & ll)
262 {
263         if (ll != params_.width) {
264                 params_.width = ll;
265                 need_update = FULL;
266         }
267 }
268
269
270 void InsetWrap::placement(string const & p)
271 {
272         params_.placement = p;
273 }
274
275
276 string const & InsetWrap::placement() const
277 {
278         return params_.placement;
279 }
280
281
282 bool InsetWrap::showInsetDialog(BufferView * bv) const
283 {
284         if (!inset.showInsetDialog(bv)) {
285                 InsetWrap * tmp = const_cast<InsetWrap *>(this);
286                 InsetWrapMailer mailer(*tmp);
287                 mailer.showDialog();
288         }
289         return true;
290 }
291
292
293 void InsetWrap::addToToc(toc::TocList & toclist, Buffer const * buf) const
294 {
295         // Now find the caption in the float...
296         // We now tranverse the paragraphs of
297         // the inset...
298         Paragraph * tmp = inset.paragraph();
299         while (tmp) {
300                 if (tmp->layout()->name() == caplayout) {
301                         string const name = floatname(type(), buf->params);
302                         string const str =
303                                 tostr(toclist[name].size() + 1)
304                                 + ". " + tmp->asString(buf, false);
305                         toc::TocItem const item(tmp->id(), 0 , str);
306                         toclist[name].push_back(item);
307                 }
308                 tmp = tmp->next();
309         }
310 }
311
312
313 string const InsetWrapMailer::name_("wrap");
314
315 InsetWrapMailer::InsetWrapMailer(InsetWrap & inset)
316         : inset_(inset)
317 {}
318
319
320 string const InsetWrapMailer::inset2string() const
321 {
322         return params2string(inset_.params());
323 }
324
325
326 void InsetWrapMailer::string2params(string const & in,
327                                     InsetWrapParams & params)
328 {
329         params = InsetWrapParams();
330
331         istringstream data(in);
332         LyXLex lex(0,0);
333         lex.setStream(data);
334
335         if (lex.isOK()) {
336                 lex.next();
337                 string const token = lex.getString();
338                 if (token != name_)
339                         return;
340         }
341
342         // This is part of the inset proper that is usually swallowed
343         // by Buffer::readInset
344         if (lex.isOK()) {
345                 lex.next();
346                 string const token = lex.getString();
347                 if (token != "Wrap" || !lex.eatLine())
348                         return;
349         }
350
351         params.read(lex);
352 }
353
354
355 string const
356 InsetWrapMailer::params2string(InsetWrapParams const & params)
357 {
358         ostringstream data;
359         data << name_ << ' ';
360         params.write(data);
361
362         return data.str();
363 }