]> git.lyx.org Git - lyx.git/blob - src/insets/InsetPreview.cpp
2e240da3be317011c5f1fb84c150cf5f2f021a81
[lyx.git] / src / insets / InsetPreview.cpp
1 /**
2  * \file InsetPreview.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Vincent van Ravesteijn
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10 #include "config.h"
11
12 #include "InsetPreview.h"
13
14 #include "Buffer.h"
15 #include "BufferParams.h"
16 #include "BufferView.h"
17 #include "Cursor.h"
18 #include "Lexer.h"
19 #include "MetricsInfo.h"
20 #include "OutputParams.h"
21 #include "RenderPreview.h"
22
23 #include "frontends/Painter.h"
24
25 #include "graphics/PreviewImage.h"
26
27 #include "mathed/MacroTable.h"
28
29 #include "support/lstrings.h"
30
31 #include <sstream>
32
33 using namespace std;
34
35 namespace lyx {
36
37 using support::prefixIs;
38
39
40 InsetPreview::InsetPreview(Buffer * buf) 
41         : InsetText(buf),
42           preview_(new RenderPreview(this)), use_preview_(true)
43 {
44         setDrawFrame(true);
45         setFrameColor(Color_previewframe);
46 }
47
48
49 InsetPreview::~InsetPreview() 
50 {}
51
52
53 InsetPreview::InsetPreview(InsetPreview const & other)
54         : InsetText(other)
55 {
56         preview_.reset(new RenderPreview(*other.preview_, this));
57 }
58
59
60 void InsetPreview::write(ostream & os) const
61 {
62         os << "Preview" << "\n";
63         text().write(os);
64 }
65
66
67 void InsetPreview::addPreview(DocIterator const & inset_pos,
68         graphics::PreviewLoader &) const
69 {
70         preparePreview(inset_pos);
71 }
72
73
74 void InsetPreview::preparePreview(DocIterator const & pos) const  
75 {
76         TexRow texrow;
77         odocstringstream str;
78         otexstream os(str, texrow);
79         Buffer const * buffer = pos.buffer();
80         OutputParams runparams(&buffer->params().encoding());
81         latex(os, runparams);
82         // collect macros at this position in case they are used in a math inset
83         MacroNameSet macros;
84         buffer->listMacroNames(macros);
85         MacroNameSet::iterator it = macros.begin();
86         MacroNameSet::iterator end = macros.end();
87         docstring macro_preamble;
88         for (; it != end; ++it) {
89                 MacroData const * data = buffer->getMacro(*it, pos, true);
90                 if (data) {
91                         odocstringstream macro_def;
92                         data->write(macro_def, true);
93                         docstring const md = macro_def.str();
94                         macro_def << endl;
95                         bool is_newcomm = prefixIs(md, from_ascii("\\newcomm"));
96                         // assure that \newcommand defs are only added once
97                         if (!is_newcomm || !preview_->hasMacroDef(md, *buffer)) {
98                                 if (is_newcomm)
99                                         preview_->addMacroDef(md, *buffer);
100                                 macro_preamble.append(macro_def.str());
101                         }
102                 }
103         }
104         docstring const snippet = macro_preamble + str.str();
105         preview_->addPreview(snippet, *buffer);
106 }
107
108
109 bool InsetPreview::previewState(BufferView * bv) const
110 {
111         if (!editing(bv) && RenderPreview::previewText()) {
112                 graphics::PreviewImage const * pimage =
113                         preview_->getPreviewImage(bv->buffer());
114                 return pimage && pimage->image();
115         }
116         return false;
117 }
118
119
120 void InsetPreview::reloadPreview(DocIterator const & pos) const
121 {
122         preparePreview(pos);
123         preview_->startLoading(*pos.buffer());
124 }
125
126
127 void InsetPreview::draw(PainterInfo & pi, int x, int y) const
128 {
129         use_preview_ = previewState(pi.base.bv);
130
131         if (use_preview_) {
132                 // one pixel gap in front
133                 preview_->draw(pi, x + 1 + TEXT_TO_INSET_OFFSET, y);
134                 setPosCache(pi, x, y);
135                 return;
136         }
137         InsetText::draw(pi, x, y);
138 }
139
140
141 void InsetPreview::edit(Cursor & cur, bool front, EntryDirection entry_from)
142 {
143         cur.push(*this);
144         InsetText::edit(cur, front, entry_from);
145 }
146
147
148 Inset * InsetPreview::editXY(Cursor & cur, int x, int y)
149 {
150         if (use_preview_) {
151                 edit(cur, true, ENTRY_DIRECTION_IGNORE);
152                 return this;
153         }
154         cur.push(*this);
155         return InsetText::editXY(cur, x, y);
156 }
157
158
159 void InsetPreview::metrics(MetricsInfo & mi, Dimension & dim) const
160 {
161         if (previewState(mi.base.bv)) {
162                 preview_->metrics(mi, dim);
163                 mi.base.textwidth += 2 * TEXT_TO_INSET_OFFSET;
164                 
165                 dim.wid = max(dim.wid, 4);
166                 dim.asc = max(dim.asc, 4);
167                 
168                 dim.asc += TEXT_TO_INSET_OFFSET;
169                 dim.des += TEXT_TO_INSET_OFFSET;
170                 dim.wid += TEXT_TO_INSET_OFFSET;
171                 dim_ = dim;
172                 dim.wid += TEXT_TO_INSET_OFFSET;
173                 // insert a one pixel gap
174                 dim.wid += 1;
175                 // Cache the inset dimension.
176                 setDimCache(mi, dim);
177                 Dimension dim_dummy;
178                 MetricsInfo mi_dummy = mi;
179                 InsetText::metrics(mi_dummy, dim_dummy);
180                 return;
181         }
182         InsetText::metrics(mi, dim);
183 }
184
185
186 bool InsetPreview::notifyCursorLeaves(Cursor const & old, Cursor & cur)
187 {
188         reloadPreview(old);
189         cur.screenUpdateFlags(Update::Force);
190         return InsetText::notifyCursorLeaves(old, cur);
191 }
192
193
194 } // namespace lyx