]> git.lyx.org Git - lyx.git/blob - src/insets/insetwrap.C
Bug: 1074
[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.paragraphs.begin()->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 bool InsetWrap::showInsetDialog(BufferView * bv) const
257 {
258         if (!inset.showInsetDialog(bv)) {
259                 InsetWrap * tmp = const_cast<InsetWrap *>(this);
260                 InsetWrapMailer mailer(*tmp);
261                 mailer.showDialog(bv);
262         }
263         return true;
264 }
265
266
267 void InsetWrap::addToToc(toc::TocList & toclist, Buffer const * buf) const
268 {
269         // Now find the caption in the float...
270         ParagraphList::iterator tmp = inset.paragraphs.begin();
271         ParagraphList::iterator end = inset.paragraphs.end();
272
273         for (; tmp != end; ++tmp) {
274                 if (tmp->layout()->name() == caplayout) {
275                         string const name = floatname(params_.type, buf->params);
276                         string const str =
277                                 tostr(toclist[name].size() + 1)
278                                 + ". " + tmp->asString(buf, false);
279                         toc::TocItem const item(tmp->id(), 0 , str);
280                         toclist[name].push_back(item);
281                 }
282         }
283 }
284
285
286 string const InsetWrapMailer::name_("wrap");
287
288 InsetWrapMailer::InsetWrapMailer(InsetWrap & inset)
289         : inset_(inset)
290 {}
291
292
293 string const InsetWrapMailer::inset2string() const
294 {
295         return params2string(inset_.params());
296 }
297
298
299 void InsetWrapMailer::string2params(string const & in,
300                                     InsetWrapParams & params)
301 {
302         params = InsetWrapParams();
303
304         if (in.empty())
305                 return;
306         
307         istringstream data(in);
308         LyXLex lex(0,0);
309         lex.setStream(data);
310
311         if (lex.isOK()) {
312                 lex.next();
313                 string const token = lex.getString();
314                 if (token != name_)
315                         return;
316         }
317
318         // This is part of the inset proper that is usually swallowed
319         // by Buffer::readInset
320         if (lex.isOK()) {
321                 lex.next();
322                 string const token = lex.getString();
323                 if (token != "Wrap" || !lex.eatLine())
324                         return;
325         }
326
327         if (lex.isOK()) {
328                 params.read(lex);
329         }
330 }
331
332
333 string const
334 InsetWrapMailer::params2string(InsetWrapParams const & params)
335 {
336         ostringstream data;
337         data << name_ << ' ';
338         params.write(data);
339
340         return data.str();
341 }