]> git.lyx.org Git - lyx.git/blob - src/insets/InsetPreview.cpp
Comply with rule-of-three
[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/InsetMathHull.h"
28 #include "mathed/MacroTable.h"
29
30 #include <sstream>
31
32 using namespace std;
33
34 namespace lyx {
35
36
37 InsetPreview::InsetPreview(Buffer * buf) 
38         : InsetText(buf),
39           preview_(new RenderPreview(this)), use_preview_(true)
40 {
41         setDrawFrame(true);
42         setFrameColor(Color_previewframe);
43 }
44
45
46 InsetPreview::~InsetPreview() 
47 {}
48
49
50 InsetPreview::InsetPreview(InsetPreview const & other)
51         : InsetText(other)
52 {
53         preview_.reset(new RenderPreview(*other.preview_, this));
54 }
55
56
57 InsetPreview & InsetPreview::operator=(InsetPreview const & other)
58 {
59         if (&other == this)
60                 return *this;
61
62         InsetText::operator=(other);
63         preview_.reset(new RenderPreview(*other.preview_, this));
64
65         return *this;
66 }
67
68
69 void InsetPreview::write(ostream & os) const
70 {
71         os << "Preview" << "\n";
72         text().write(os);
73 }
74
75
76 void InsetPreview::addPreview(DocIterator const & inset_pos,
77         graphics::PreviewLoader &) const
78 {
79         preparePreview(inset_pos);
80 }
81
82
83 void InsetPreview::preparePreview(DocIterator const & pos) const  
84 {
85         TexRow texrow;
86         odocstringstream str;
87         otexstream os(str, texrow);
88         OutputParams runparams(&pos.buffer()->params().encoding());
89         latex(os, runparams);
90
91         // collect macros at this position
92         MacroNameSet macros;
93         pos.buffer()->listMacroNames(macros);
94
95         // look for math insets and collect definitions for the used macros
96         MacroNameSet defs;
97         DocIterator dit = doc_iterator_begin(pos.buffer(), this);
98         DocIterator const dend = doc_iterator_end(pos.buffer(), this);
99         if (!dit.nextInset())
100                 dit.forwardInset();
101         for (; dit != dend; dit.forwardInset()) {
102                 InsetMath * im = dit.nextInset()->asInsetMath();
103                 InsetMathHull * hull = im ? im->asHullInset() : 0;
104                 if (!hull)
105                         continue;
106                 for (idx_type idx = 0; idx < hull->nargs(); ++idx)
107                         hull->usedMacros(hull->cell(idx), pos, macros, defs);
108         }
109         MacroNameSet::iterator it = defs.begin();
110         MacroNameSet::iterator end = defs.end();
111         docstring macro_preamble;
112         for (; it != end; ++it)
113                 macro_preamble.append(*it);
114
115         docstring const snippet = macro_preamble + str.str();
116         preview_->addPreview(snippet, *pos.buffer());
117 }
118
119
120 bool InsetPreview::previewState(BufferView * bv) const
121 {
122         if (!editing(bv) && RenderPreview::previewText()) {
123                 graphics::PreviewImage const * pimage =
124                         preview_->getPreviewImage(bv->buffer());
125                 return pimage && pimage->image();
126         }
127         return false;
128 }
129
130
131 void InsetPreview::reloadPreview(DocIterator const & pos) const
132 {
133         preparePreview(pos);
134         preview_->startLoading(*pos.buffer());
135 }
136
137
138 void InsetPreview::draw(PainterInfo & pi, int x, int y) const
139 {
140         use_preview_ = previewState(pi.base.bv);
141
142         if (use_preview_) {
143                 // one pixel gap in front
144                 preview_->draw(pi, x + 1 + TEXT_TO_INSET_OFFSET, y);
145                 setPosCache(pi, x, y);
146                 return;
147         }
148         InsetText::draw(pi, x, y);
149 }
150
151
152 void InsetPreview::edit(Cursor & cur, bool front, EntryDirection entry_from)
153 {
154         cur.push(*this);
155         InsetText::edit(cur, front, entry_from);
156 }
157
158
159 Inset * InsetPreview::editXY(Cursor & cur, int x, int y)
160 {
161         if (use_preview_) {
162                 edit(cur, true, ENTRY_DIRECTION_IGNORE);
163                 return this;
164         }
165         cur.push(*this);
166         return InsetText::editXY(cur, x, y);
167 }
168
169
170 void InsetPreview::metrics(MetricsInfo & mi, Dimension & dim) const
171 {
172         if (previewState(mi.base.bv)) {
173                 preview_->metrics(mi, dim);
174                 mi.base.textwidth += 2 * TEXT_TO_INSET_OFFSET;
175                 
176                 dim.wid = max(dim.wid, 4);
177                 dim.asc = max(dim.asc, 4);
178                 
179                 dim.asc += TEXT_TO_INSET_OFFSET;
180                 dim.des += TEXT_TO_INSET_OFFSET;
181                 dim.wid += TEXT_TO_INSET_OFFSET;
182                 dim_ = dim;
183                 dim.wid += TEXT_TO_INSET_OFFSET;
184                 // insert a one pixel gap
185                 dim.wid += 1;
186                 // Cache the inset dimension.
187                 setDimCache(mi, dim);
188                 Dimension dim_dummy;
189                 MetricsInfo mi_dummy = mi;
190                 InsetText::metrics(mi_dummy, dim_dummy);
191                 return;
192         }
193         InsetText::metrics(mi, dim);
194 }
195
196
197 bool InsetPreview::notifyCursorLeaves(Cursor const & old, Cursor & cur)
198 {
199         reloadPreview(old);
200         cur.screenUpdateFlags(Update::Force);
201         return InsetText::notifyCursorLeaves(old, cur);
202 }
203
204
205 } // namespace lyx