/** * \file insetminipage.C * This file is part of LyX, the document processor. * Licence details can be found in the file COPYING. * * \author Jürgen Vigna * \author Lars Gullik Bjønnes * * Full author contact details are available in file CREDITS. */ #include #include "insetminipage.h" #include "BufferView.h" #include "debug.h" #include "dispatchresult.h" #include "funcrequest.h" #include "gettext.h" #include "LColor.h" #include "lyxlex.h" #include "metricsinfo.h" #include "paragraph.h" #include "support/std_sstream.h" using std::string; using std::endl; using std::auto_ptr; using std::istringstream; using std::ostream; using std::ostringstream; // Some information about Minipages in LaTeX: // A minipage is a complete miniversion of a page and can contain // its own footnotes, paragraphs, and array, tabular, and multicols // environments. However it cannot contain floats or \marginpar's, // but it can appear inside floats. // // The minipage environment is defined like this: // // \begin{minipage}[pos][height][inner-pos]{width} \end{minipage} // // Where: // pos [opt] = is the vertical placement of the box with respect // to the text baseline, [c], [t] and [b]. // height [opt] = the height of the box // inner-pos [opt] = the position of the text within the box. // It can be t, c, b or s, if unspecified the value // of pos is used. // width = the width of the box // // In LyX we should try to support all these parameters, settable in a // pop-up dialog. // In this pop-up diallog it should also be possible to set all margin // values that is usable in the minipage. // With regard to different formats (like DocBook) I guess a minipage // can be used there also. Perhaps not in the latex way, but we do not // have to output "" for minipages. // (Lgb) InsetMinipage::InsetMinipage(BufferParams const & bp) : InsetCollapsable(bp) { setLabel(_("minipage")); LyXFont font(LyXFont::ALL_SANE); font.decSize(); font.decSize(); font.setColor(LColor::collapsable); setLabelFont(font); #if 0 setAutoCollapse(false); #endif inset.setFrameColor(LColor::blue); setInsetName("Minipage"); } InsetMinipage::InsetMinipage(InsetMinipage const & in) : InsetCollapsable(in), params_(in.params_) {} auto_ptr InsetMinipage::clone() const { return auto_ptr(new InsetMinipage(*this)); } InsetMinipage::~InsetMinipage() { InsetMinipageMailer(*this).hideDialog(); } DispatchResult InsetMinipage::priv_dispatch(FuncRequest const & cmd, idx_type & idx, pos_type & pos) { switch (cmd.action) { case LFUN_INSET_MODIFY: { InsetMinipage::Params params; InsetMinipageMailer::string2params(cmd.argument, params); params_.pos = params.pos; params_.width = params.width; /* FIXME: I refuse to believe we have to live * with ugliness like this ... */ inset.getLyXText(cmd.view())->fullRebreak(); cmd.view()->updateInset(this); return DispatchResult(true, true); } case LFUN_INSET_DIALOG_UPDATE: InsetMinipageMailer(*this).updateDialog(cmd.view()); return DispatchResult(true, true); default: return InsetCollapsable::priv_dispatch(cmd, idx, pos); } } void InsetMinipage::Params::write(ostream & os) const { os << "Minipage" << '\n' << "position " << pos << '\n' << "inner_position " << inner_pos << '\n' << "height \"" << height.asString() << "\"\n" << "width \"" << width.asString() << "\"\n"; } void InsetMinipage::Params::read(LyXLex & lex) { if (lex.isOK()) { lex.next(); string const token = lex.getString(); if (token == "position") { lex.next(); pos = static_cast(lex.getInteger()); } else { lyxerr << "InsetMinipage::Read: Missing 'position'-tag!" << endl; // take countermeasures lex.pushToken(token); } } if (lex.isOK()) { lex.next(); string const token = lex.getString(); if (token == "inner_position") { lex.next(); inner_pos = static_cast(lex.getInteger()); } else { lyxerr << "InsetMinipage::Read: Missing 'inner_position'-tag!" << endl; // take countermeasures lex.pushToken(token); } } if (lex.isOK()) { lex.next(); string const token = lex.getString(); if (token == "height") { lex.next(); height = LyXLength(lex.getString()); } else { lyxerr << "InsetMinipage::Read: Missing 'height'-tag!" << endl; // take countermeasures lex.pushToken(token); } } if (lex.isOK()) { lex.next(); string const token = lex.getString(); if (token == "width") { lex.next(); width = LyXLength(lex.getString()); } else { lyxerr << "InsetMinipage::Read: Missing 'width'-tag!" << endl; // take countermeasures lex.pushToken(token); } } } void InsetMinipage::write(Buffer const & buf, ostream & os) const { params_.write(os); InsetCollapsable::write(buf, os); } void InsetMinipage::read(Buffer const & buf, LyXLex & lex) { params_.read(lex); InsetCollapsable::read(buf, lex); } void InsetMinipage::metrics(MetricsInfo & mi, Dimension & dim) const { if (isOpen()) { Dimension d; MetricsInfo m = mi; m.base.textwidth = params_.width.inPixels(mi.base.textwidth); InsetCollapsable::metrics(m, d); switch (params_.pos) { case top: dim.asc = d.asc; dim.des = d.des; break; case center: dim.asc = d.ascent() + d.descent() / 2; dim.des = dim.asc; break; case bottom: dim.asc = d.des; dim.des = d.asc; break; } dim.wid = d.wid; } else dimension_collapsed(dim); dim_ = dim; } string const InsetMinipage::editMessage() const { return _("Opened Minipage Inset"); } int InsetMinipage::latex(Buffer const & buf, ostream & os, OutputParams const & runparams) const { string s_pos; switch (params_.pos) { case top: s_pos += 't'; break; case center: s_pos += 'c'; break; case bottom: s_pos += 'b'; break; } os << "\\begin{minipage}[" << s_pos << "]{" << params_.width.asLatexString() << "}%\n"; int i = inset.latex(buf, os, runparams); os << "\\end{minipage}%\n"; return i + 2; } bool InsetMinipage::insetAllowed(InsetOld::Code code) const { if (code == InsetOld::FLOAT_CODE || code == InsetOld::MARGIN_CODE) return false; return InsetCollapsable::insetAllowed(code); } bool InsetMinipage::showInsetDialog(BufferView * bv) const { if (!inset.showInsetDialog(bv)) { InsetMinipage * tmp = const_cast(this); InsetMinipageMailer mailer(*tmp); mailer.showDialog(bv); } return true; } int InsetMinipage::latexTextWidth(BufferView * bv) const { return params_.width.inPixels(InsetCollapsable::latexTextWidth(bv)); } InsetMinipage::Params::Params() : pos(center), inner_pos(inner_center), width(100, LyXLength::PCW) {} string const InsetMinipageMailer:: name_("minipage"); InsetMinipageMailer::InsetMinipageMailer(InsetMinipage & inset) : inset_(inset) {} string const InsetMinipageMailer::inset2string(Buffer const &) const { return params2string(inset_.params()); } void InsetMinipageMailer::string2params(string const & in, InsetMinipage::Params & params) { params = InsetMinipage::Params(); if (in.empty()) return; istringstream data(in); LyXLex lex(0, 0); lex.setStream(data); if (lex.isOK()) { lex.next(); string const token = lex.getString(); if (token != "minipage") return; } // This is part of the inset proper that is usually swallowed // by Buffer::readInset if (lex.isOK()) { lex.next(); string const token = lex.getString(); if (token != "Minipage") return; } if (lex.isOK()) { params.read(lex); } } string const InsetMinipageMailer::params2string(InsetMinipage::Params const & params) { ostringstream data; data << name_ << ' '; params.write(data); return data.str(); }