3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
7 * \author Lars Gullik Bjønnes
9 * Full author contact details are available in file CREDITS
14 #pragma implementation
17 #include "insetfloat.h"
20 #include "BufferView.h"
22 #include "insets/insettext.h"
23 #include "support/LOstream.h"
24 #include "support/lstrings.h"
25 #include "FloatList.h"
26 #include "LaTeXFeatures.h"
30 #include "frontends/LyXView.h"
31 #include "frontends/Dialogs.h"
33 #include "iterators.h"
38 // With this inset it will be possible to support the latex package
39 // float.sty, and I am sure that with this and some additional support
40 // classes we can support similar functionality in other formats
42 // By using float.sty we will have the same handling for all floats, both
43 // for those already in existance (table and figure) and all user created
44 // ones¹. So suddenly we give the users the possibility of creating new
45 // kinds of floats on the fly. (and with a uniform look)
48 // \newfloat{type}{placement}{ext}[within]
49 // type - The "type" of the new class of floats, like program or
50 // algorithm. After the appropriate \newfloat, commands
51 // such as \begin{program} or \end{algorithm*} will be
53 // placement - The default placement for the given class of floats.
54 // They are like in standard LaTeX: t, b, p and h for top,
55 // bottom, page, and here, respectively. On top of that
56 // there is a new type, H, which does not really correspond
57 // to a float, since it means: put it "here" and nowhere else.
58 // Note, however that the H specifier is special and, because
59 // of implementation details cannot be used in the second
60 // argument of \newfloat.
61 // ext - The file name extension of an auxiliary file for the list
62 // of figures (or whatever). LaTeX writes the captions to
64 // within - This (optional) argument determines whether floats of this
65 // class will be numbered within some sectional unit of the
66 // document. For example, if within is equal to chapter, the
67 // floats will be numbered within chapters.
69 // style - plain, boxed, ruled
70 // \floatname{float}{floatname}
73 // \floatplacement{float}{placement}
76 // \restylefloat{float}
78 // \listof{type}{title}
81 // ¹ the algorithm float is defined using the float.sty package. Like this
83 // \newfloat{algorithm}{htbp}{loa}[<sect>]
84 // \floatname{algorithm}{Algorithm}
86 // The intention is that floats should be definable from two places:
88 // - the "gui" (i.e. by the user)
91 // This should only be done for floats defined in a documentclass and that
92 // does not need any additional packages. The two most known floats in this
93 // category is "table" and "figure". Floats defined in layout files are only
94 // stored in lyx files if the user modifies them.
97 // There should be a gui dialog (and also a collection of lyxfuncs) where
98 // the user can modify existing floats and/or create new ones.
100 // The individual floats will also have some settable
101 // variables: wide and placement.
107 // this should not be hardcoded, but be part of the definition
108 // of the float (JMarc)
109 string const caplayout("Caption");
111 string floatname(string const & type, BufferParams const & bp)
113 FloatList const & floats = bp.getLyXTextClass().floats();
114 FloatList::const_iterator it = floats[type];
115 if (it == floats.end())
118 return _(it->second.name());
124 InsetFloat::InsetFloat(BufferParams const & bp, string const & type)
125 : InsetCollapsable(bp), wide_(false)
127 string lab(_("float: "));
128 lab += floatname(type, bp);
130 LyXFont font(LyXFont::ALL_SANE);
133 font.setColor(LColor::collapsable);
137 LyXTextClass const & tclass = bp.getLyXTextClass();
138 if (tclass.hasLayout(caplayout))
139 inset.paragraph()->layout(tclass[caplayout]);
143 InsetFloat::InsetFloat(InsetFloat const & in, bool same_id)
144 : InsetCollapsable(in, same_id), floatType_(in.floatType_),
145 floatPlacement_(in.floatPlacement_), wide_(in.wide_)
149 InsetFloat::~InsetFloat()
155 void InsetFloat::write(Buffer const * buf, ostream & os) const
157 os << "Float " // getInsetName()
158 << floatType_ << '\n';
160 if (!floatPlacement_.empty()) {
161 os << "placement " << floatPlacement_ << "\n";
166 os << "wide false\n";
169 InsetCollapsable::write(buf, os);
173 void InsetFloat::read(Buffer const * buf, LyXLex & lex)
177 string token = lex.getString();
178 if (token == "placement") {
180 floatPlacement_ = lex.getString();
182 // take countermeasures
183 lex.pushToken(token);
186 token = lex.getString();
187 if (token == "wide") {
189 string const tmptoken = lex.getString();
190 if (tmptoken == "true")
191 wide(true, buf->params);
193 wide(false, buf->params);
195 lyxerr << "InsetFloat::Read:: Missing wide!"
197 // take countermeasures
198 lex.pushToken(token);
201 InsetCollapsable::read(buf, lex);
205 void InsetFloat::validate(LaTeXFeatures & features) const
207 if (contains(placement(), "H")) {
208 features.require("float");
211 features.useFloat(floatType_);
212 InsetCollapsable::validate(features);
216 Inset * InsetFloat::clone(Buffer const &, bool same_id) const
218 return new InsetFloat(*const_cast<InsetFloat *>(this), same_id);
222 string const InsetFloat::editMessage() const
224 return _("Opened Float Inset");
228 int InsetFloat::latex(Buffer const * buf,
229 ostream & os, bool fragile, bool fp) const
231 FloatList const & floats = buf->params.getLyXTextClass().floats();
232 string const tmptype = (wide_ ? floatType_ + "*" : floatType_);
233 // Figure out the float placement to use.
234 // From lowest to highest:
235 // - float default placement
236 // - document wide default placement
237 // - specific float placement
239 string const buf_placement = buf->params.float_placement;
240 string const def_placement = floats.defaultPlacement(floatType_);
241 if (!floatPlacement_.empty()
242 && floatPlacement_ != def_placement) {
243 placement = floatPlacement_;
244 } else if (floatPlacement_.empty()
245 && !buf_placement.empty()
246 && buf_placement != def_placement) {
247 placement = buf_placement;
250 // The \n is used to force \begin{<floatname>} to appear in a new line.
251 // The % is needed to prevent two consecutive \n chars in the case
252 // when the current output line is empty.
253 os << "%\n\\begin{" << tmptype << "}";
254 // We only output placement if different from the def_placement.
255 if (!placement.empty()) {
256 os << "[" << placement << "]";
260 int const i = inset.latex(buf, os, fragile, fp);
262 // The \n is used to force \end{<floatname>} to appear in a new line.
263 // In this case, we do not case if the current output line is empty.
264 os << "\n\\end{" << tmptype << "}\n";
270 int InsetFloat::docbook(Buffer const * buf, ostream & os, bool mixcont) const
272 os << "<" << floatType_ << ">";
273 int const i = inset.docbook(buf, os, mixcont);
274 os << "</" << floatType_ << ">";
280 bool InsetFloat::insetAllowed(Inset::Code code) const
282 if (code == Inset::FLOAT_CODE)
284 if (inset.getLockingInset() != const_cast<InsetFloat *>(this))
285 return inset.insetAllowed(code);
286 if ((code == Inset::FOOT_CODE) || (code == Inset::MARGIN_CODE))
292 bool InsetFloat::showInsetDialog(BufferView * bv) const
294 if (!inset.showInsetDialog(bv)) {
295 bv->owner()->getDialogs().showFloat(const_cast<InsetFloat *>(this));
301 string const & InsetFloat::type() const
307 void InsetFloat::placement(string const & p)
309 // FIX: Here we should only allow the placement to be set
315 string const & InsetFloat::placement() const
317 return floatPlacement_;
321 void InsetFloat::wide(bool w, BufferParams const & bp)
325 string lab(_("float:"));
326 lab += floatname(floatType_, bp);
335 bool InsetFloat::wide() const
341 void InsetFloat::addToToc(toc::TocList & toclist, Buffer const * buf) const
343 ParIterator pit(inset.paragraph());
346 // Find a caption layout in one of the (child inset's) pars
347 for (; pit != end; ++pit) {
348 Paragraph * tmp = *pit;
350 if (tmp->layout()->name() == caplayout) {
352 tostr(toclist[type()].size() + 1)
353 + ". " + tmp->asString(buf, false);
354 toc::TocItem const item(tmp, 0 , str);
355 toclist[type()].push_back(item);