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