]> git.lyx.org Git - lyx.git/blob - src/mathed/formula.C
Remove the inset and view member functions from PreviewedInset.
[lyx.git] / src / mathed / formula.C
1 /**
2  * \file formula.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Alejandro Aguilar Sierra
7  * \author André Pönitz
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "formula.h"
15 #include "math_cursor.h"
16 #include "math_parser.h"
17 #include "math_hullinset.h"
18 #include "math_mathmlstream.h"
19 #include "textpainter.h"
20
21 #include "BufferView.h"
22 #include "debug.h"
23 #include "latexrunparams.h"
24 #include "LColor.h"
25
26 #include "frontends/Painter.h"
27
28 #include "graphics/PreviewedInset.h"
29 #include "graphics/PreviewImage.h"
30
31 #include "support/std_sstream.h"
32
33 #include <boost/bind.hpp>
34
35 using std::string;
36 using std::ostream;
37 using std::ostringstream;
38 using std::vector;
39 using std::auto_ptr;
40 using std::endl;
41
42
43 class InsetFormula::PreviewImpl : public PreviewedInset {
44 public:
45         ///
46         PreviewImpl(InsetFormula const & p) : parent_(p) {}
47
48 private:
49         ///
50         bool previewWanted(Buffer const &) const;
51         ///
52         string const latexString(Buffer const &) const;
53         ///
54         InsetFormula const & parent_;
55 };
56
57
58 InsetFormula::InsetFormula(bool chemistry)
59         : par_(MathAtom(new MathHullInset)),
60           preview_(new PreviewImpl(*this))
61 {
62         preview_->connect(boost::bind(&InsetFormula::statusChanged, this));
63         if (chemistry)
64                 mutate("chemistry");
65 }
66
67
68 InsetFormula::InsetFormula(InsetFormula const & other)
69         : InsetFormulaBase(other),
70           par_(other.par_),
71           preview_(new PreviewImpl(*this))
72 {
73         preview_->connect(boost::bind(&InsetFormula::statusChanged, this));
74 }
75
76
77 InsetFormula::InsetFormula(BufferView *)
78         : par_(MathAtom(new MathHullInset)),
79           preview_(new PreviewImpl(*this))
80 {
81         preview_->connect(boost::bind(&InsetFormula::statusChanged, this));
82 }
83
84
85 InsetFormula::InsetFormula(string const & data)
86         : par_(MathAtom(new MathHullInset)),
87           preview_(new PreviewImpl(*this))
88 {
89         preview_->connect(boost::bind(&InsetFormula::statusChanged, this));
90         if (!data.size())
91                 return;
92         if (!mathed_parse_normal(par_, data))
93                 lyxerr << "cannot interpret '" << data << "' as math" << endl;
94 }
95
96
97 InsetFormula::~InsetFormula()
98 {}
99
100
101 auto_ptr<InsetBase> InsetFormula::clone() const
102 {
103         return auto_ptr<InsetBase>(new InsetFormula(*this));
104 }
105
106
107 void InsetFormula::write(Buffer const &, ostream & os) const
108 {
109         WriteStream wi(os, false, false);
110         os << par_->fileInsetLabel() << ' ';
111         par_->write(wi);
112 }
113
114
115 int InsetFormula::latex(Buffer const &, ostream & os,
116                         LatexRunParams const & runparams) const
117 {
118         WriteStream wi(os, runparams.moving_arg, true);
119         par_->write(wi);
120         return wi.line();
121 }
122
123
124 int InsetFormula::ascii(Buffer const &, ostream & os, int) const
125 {
126         if (0 && display()) {
127                 Dimension dim;
128                 TextMetricsInfo mi;
129                 par()->metricsT(mi, dim);
130                 TextPainter tpain(dim.width(), dim.height());
131                 par()->drawT(tpain, 0, dim.ascent());
132                 tpain.show(os, 3);
133                 // reset metrics cache to "real" values
134                 //metrics();
135                 return tpain.textheight();
136         } else {
137                 WriteStream wi(os, false, true);
138                 wi << ' ' << (par_->asNestInset()->cell(0)) << ' ';
139                 return wi.line();
140         }
141 }
142
143
144 int InsetFormula::linuxdoc(Buffer const & buf, ostream & os) const
145 {
146         return docbook(buf, os, false);
147 }
148
149
150 int InsetFormula::docbook(Buffer const & buf, ostream & os, bool) const
151 {
152         MathMLStream ms(os);
153         ms << MTag("equation");
154         ms <<   MTag("alt");
155         ms <<    "<[CDATA[";
156         int res = ascii(buf, ms.os(), 0);
157         ms <<    "]]>";
158         ms <<   ETag("alt");
159         ms <<   MTag("math");
160         ms <<    par_;
161         ms <<   ETag("math");
162         ms << ETag("equation");
163         return ms.line() + res;
164 }
165
166
167 void InsetFormula::read(Buffer const &, LyXLex & lex)
168 {
169         mathed_parse_normal(par_, lex);
170         // remove extra 'mathrm' for chemistry stuff.
171         // will be re-added on write
172         if (par_->asHullInset()->getType() =="chemistry")  {
173                 lyxerr << "this is chemistry" << endl;
174                 if (par_->cell(0).size() == 1) {
175                         lyxerr << "this is size 1" << endl;
176                         if (par_->cell(0)[0]->asFontInset()) {
177                                 lyxerr << "this is a font inset "
178                                        << "replacing " << par_.nucleus()->cell(0) <<
179                                         " with " << par_->cell(0)[0]->cell(0) << endl;
180                         }
181                 }
182         }
183         //metrics();
184 }
185
186
187 //ostream & operator<<(ostream & os, LyXCursor const & c)
188 //{
189 //      os << '[' << c.x() << ' ' << c.y() << ' ' << c.pos() << ']';
190 //      return os;
191 //}
192
193
194 void InsetFormula::draw(PainterInfo & pi, int x, int y) const
195 {
196         cache(pi.base.bv);
197         // This initiates the loading of the preview, so should come
198         // before the metrics are computed.
199         Buffer const * buffer_ptr = pi.base.bv ? pi.base.bv->buffer() : 0;
200         bool const use_preview = buffer_ptr && preview_->previewReady(*buffer_ptr);
201
202         int const w = dim_.wid;
203         int const d = dim_.des;
204         int const a = dim_.asc;
205         int const h = a + d;
206
207         if (use_preview) {
208                 pi.pain.image(x + 1, y - a, w, h,   // one pixel gap in front
209                               *(preview_->pimage()->image()));
210         } else {
211                 PainterInfo p(pi.base.bv);
212                 p.base.style = LM_ST_TEXT;
213                 p.base.font  = pi.base.font;
214                 p.base.font.setColor(LColor::math);
215                 if (lcolor.getX11Name(LColor::mathbg)
216                             != lcolor.getX11Name(LColor::background))
217                         p.pain.fillRectangle(x, y - a, w, h, LColor::mathbg);
218
219                 if (mathcursor &&
220                                 const_cast<InsetFormulaBase const *>(mathcursor->formula()) == this)
221                 {
222                         mathcursor->drawSelection(pi);
223                         //p.pain.rectangle(x, y - a, w, h, LColor::mathframe);
224                 }
225
226                 par_->draw(p, x + offset_, y);
227         }
228
229         xo_ = x;
230         yo_ = y;
231 }
232
233
234 void InsetFormula::getLabelList(Buffer const & buffer,
235                                 vector<string> & res) const
236 {
237         par()->getLabelList(buffer, res);
238 }
239
240
241 InsetOld::Code InsetFormula::lyxCode() const
242 {
243         return InsetOld::MATH_CODE;
244 }
245
246
247 void InsetFormula::validate(LaTeXFeatures & features) const
248 {
249         par_->validate(features);
250 }
251
252
253 bool InsetFormula::insetAllowed(InsetOld::Code code) const
254 {
255         return
256                    code == InsetOld::LABEL_CODE
257                 || code == InsetOld::REF_CODE
258                 || code == InsetOld::ERT_CODE;
259 }
260
261
262 void InsetFormula::metrics(MetricsInfo & m, Dimension & dim) const
263 {
264         view_ = m.base.bv;
265         Buffer const * buffer_ptr = m.base.bv ? m.base.bv->buffer() : 0;
266         if (buffer_ptr && preview_->previewReady(*buffer_ptr)) {
267                 dim.asc = preview_->pimage()->ascent();
268                 dim.des = preview_->pimage()->descent();
269                 // insert a one pixel gap in front of the formula
270                 dim.wid = 1 + preview_->pimage()->width();
271                 if (display())
272                         dim.des += 12;
273         } else {
274                 MetricsInfo mi = m;
275                 mi.base.style = LM_ST_TEXT;
276                 mi.base.font.setColor(LColor::math);
277                 par()->metrics(mi, dim);
278                 dim.asc += 1;
279                 dim.des += 1;
280         }
281
282         if (display()) {
283                 offset_ = (m.base.textwidth - dim.wid) / 2;
284                 dim.wid = m.base.textwidth;
285         } else {
286                 offset_ = 0;
287         }
288
289         dim_ = dim;
290 }
291
292
293 void InsetFormula::mutate(string const & type)
294 {
295         par_.nucleus()->mutate(type);
296 }
297
298
299 //
300 // preview stuff
301 //
302
303 void InsetFormula::statusChanged() const
304 {
305         if (view())
306                 view()->updateInset(this);
307 }
308
309
310 void InsetFormula::addPreview(lyx::graphics::PreviewLoader & ploader) const
311 {
312         preview_->addPreview(ploader);
313 }
314
315
316 void InsetFormula::generatePreview(Buffer const & buffer) const
317 {
318         preview_->generatePreview(buffer);
319 }
320
321
322 bool InsetFormula::PreviewImpl::previewWanted(Buffer const &) const
323 {
324         return !parent_.par_->asNestInset()->editing();
325 }
326
327
328 string const InsetFormula::PreviewImpl::latexString(Buffer const &) const
329 {
330         ostringstream ls;
331         WriteStream wi(ls, false, false);
332         parent_.par_->write(wi);
333         return ls.str();
334 }