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