]> git.lyx.org Git - features.git/blob - src/insets/InsetERT.cpp
Vincent's initial support for ERT instant preview
[features.git] / src / insets / InsetERT.cpp
1 /**
2  * \file InsetERT.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Jürgen Vigna
7  * \author Lars Gullik Bjønnes
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "InsetERT.h"
15
16 #include "Buffer.h"
17 #include "BufferParams.h"
18 #include "BufferView.h"
19 #include "Cursor.h"
20 #include "DispatchResult.h"
21 #include "FuncRequest.h"
22 #include "FuncStatus.h"
23 #include "Language.h"
24 #include "Layout.h"
25 #include "Lexer.h"
26 #include "LyXRC.h"
27 #include "LyXAction.h"
28 #include "MetricsInfo.h"
29 #include "OutputParams.h"
30 #include "ParagraphParameters.h"
31 #include "Paragraph.h"
32 #include "TextClass.h"
33
34 #include "graphics/PreviewImage.h"
35
36 #include "insets/RenderPreview.h"
37
38 #include "frontends/alert.h"
39 #include "frontends/Application.h"
40
41 #include "support/debug.h"
42 #include "support/gettext.h"
43 #include "support/lstrings.h"
44
45 #include <sstream>
46
47 using namespace std;
48 using namespace lyx::support;
49
50 namespace lyx {
51
52 InsetERT::InsetERT(Buffer * buf, CollapseStatus status)
53         : InsetCollapsable(buf), preview_(new RenderPreview(this))
54 {
55         status_ = status;
56 }
57
58
59 InsetERT::InsetERT(InsetERT const & other) : InsetCollapsable(other)
60 {
61         operator=(other);
62 }
63
64 InsetERT & InsetERT::operator=(InsetERT const & other)
65 {
66         if (this == &other)
67                 return *this;
68         InsetCollapsable::operator=(other);
69         buffer_ = other.buffer_;
70         preview_.reset(new RenderPreview(*other.preview_, this));
71
72         return *this;
73 }
74
75
76 InsetERT::~InsetERT()
77 {
78         hideDialogs("ert", this);
79 }
80
81
82 void InsetERT::write(ostream & os) const
83 {
84         os << "ERT" << "\n";
85         InsetCollapsable::write(os);
86 }
87
88
89 int InsetERT::plaintext(odocstream & os, OutputParams const & rp) const
90 {
91         if (!rp.inIndexEntry)
92                 // do not output TeX code
93                 return 0;
94
95         ParagraphList::const_iterator par = paragraphs().begin();
96         ParagraphList::const_iterator end = paragraphs().end();
97
98         while (par != end) {
99                 pos_type siz = par->size();
100                 for (pos_type i = 0; i < siz; ++i) {
101                         char_type const c = par->getChar(i);
102                         // output the active characters
103                         switch (c) {
104                         case '|':
105                         case '!':
106                         case '@':
107                                 os.put(c);
108                                 break;
109                         default:
110                                 break;
111                         }
112                 }
113                 ++par;
114         }
115         return 0;
116 }
117
118
119 int InsetERT::docbook(odocstream & os, OutputParams const &) const
120 {
121         // FIXME can we do the same thing here as for LaTeX?
122         ParagraphList::const_iterator par = paragraphs().begin();
123         ParagraphList::const_iterator end = paragraphs().end();
124
125         int lines = 0;
126         while (par != end) {
127                 pos_type siz = par->size();
128                 for (pos_type i = 0; i < siz; ++i)
129                         os.put(par->getChar(i));
130                 ++par;
131                 if (par != end) {
132                         os << "\n";
133                         ++lines;
134                 }
135         }
136
137         return lines;
138 }
139
140
141 void InsetERT::doDispatch(Cursor & cur, FuncRequest & cmd)
142 {
143         switch (cmd.action) {
144         case LFUN_INSET_MODIFY: {
145                 setStatus(cur, string2params(to_utf8(cmd.argument())));
146                 break;
147         }
148         default:
149                 InsetCollapsable::doDispatch(cur, cmd);
150                 break;
151         }
152 }
153
154
155 bool InsetERT::getStatus(Cursor & cur, FuncRequest const & cmd,
156         FuncStatus & status) const
157 {
158         switch (cmd.action) {
159         case LFUN_INSET_MODIFY:
160                 status.setEnabled(true);
161                 return true;
162                 
163         default:
164                 return InsetCollapsable::getStatus(cur, cmd, status);
165         }
166 }
167
168
169 docstring const InsetERT::buttonLabel(BufferView const & bv) const
170 {
171         if (decoration() == InsetLayout::CLASSIC)
172                 return isOpen(bv) ? _("ERT") : getNewLabel(_("ERT"));
173         else
174                 return getNewLabel(_("ERT"));
175 }
176
177
178 bool InsetERT::showInsetDialog(BufferView * bv) const
179 {
180         bv->showDialog("ert", params2string(status(*bv)), 
181                 const_cast<InsetERT *>(this));
182         return true;
183 }
184
185
186 InsetCollapsable::CollapseStatus InsetERT::string2params(string const & in)
187 {
188         if (in.empty())
189                 return Collapsed;
190         istringstream data(in);
191         Lexer lex;
192         lex.setStream(data);
193         lex.setContext("InsetERT::string2params");
194         lex >> "ert";
195         int s;
196         lex >> s;
197         return static_cast<CollapseStatus>(s);
198 }
199
200
201 string InsetERT::params2string(CollapseStatus status)
202 {
203         ostringstream data;
204         data << "ert" << ' ' << status;
205         return data.str();
206 }
207
208
209 docstring InsetERT::xhtml(XHTMLStream &, OutputParams const &) const
210 {
211         return docstring();
212 }
213
214
215 bool InsetERT::previewState(BufferView * bv) const
216 {
217         if (!editing(bv) && RenderPreview::status() == LyXRC::PREVIEW_ON) {
218                 graphics::PreviewImage const * pimage =
219                         preview_->getPreviewImage(bv->buffer());
220                 return pimage && pimage->image();
221         }
222         return false;
223 }
224
225
226 void InsetERT::addPreview(DocIterator const & inset_pos,
227         graphics::PreviewLoader & ploader) const
228 {
229         preparePreview(inset_pos);
230 }
231
232
233 void InsetERT::preparePreview(DocIterator const & pos) const  
234 {
235         odocstringstream str;  
236         OutputParams runparams(&pos.buffer()->params().encoding());
237         latex(str, runparams);
238         docstring const snippet = str.str();
239         LYXERR(Debug::MACROS, "Preview snippet: " << snippet);  
240         preview_->addPreview(snippet, *pos.buffer());  
241 }
242
243
244 void InsetERT::reloadPreview(DocIterator const & pos) const
245 {
246         preparePreview(pos);
247         preview_->startLoading(*pos.buffer());
248 }
249
250
251 bool InsetERT::notifyCursorLeaves(Cursor const & old, Cursor & cur)
252 {
253         reloadPreview(old);
254         cur.updateFlags(Update::Force);
255         return InsetCollapsable::notifyCursorLeaves(old, cur);
256 }
257
258
259 void InsetERT::draw(PainterInfo & pi, int x, int y) const
260 {
261         use_preview_ = previewState(pi.base.bv);
262
263         if (use_preview_) {
264                 // one pixel gap in front
265                 preview_->draw(pi, x + 1, y);
266                 setPosCache(pi, x, y);
267                 return;
268         }
269         InsetCollapsable::draw(pi, x, y);
270 }
271
272
273 Inset * InsetERT::editXY(Cursor & cur, int x, int y)
274 {
275         if (use_preview_) {
276                 edit(cur, true);
277                 return this;
278         }
279         return InsetCollapsable::editXY(cur, x, y);
280 }
281
282
283 void InsetERT::metrics(MetricsInfo & mi, Dimension & dim) const
284 {
285         if (previewState(mi.base.bv)) {
286                 preview_->metrics(mi, dim);
287                 // insert a one pixel gap in front of the formula
288                 dim.wid += 1;
289                 // Cache the inset dimension.
290                 setDimCache(mi, dim);
291                 Dimension dim_dummy = dim;
292                 MetricsInfo mi_dummy = mi;
293                 InsetCollapsable::metrics(mi_dummy, dim_dummy);
294                 return;
295         }
296         InsetCollapsable::metrics(mi, dim);
297 }
298
299 } // namespace lyx