3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Angus Leeming
8 * Full author contact details are available in file CREDITS
13 #include "insets/renderers.h"
16 #include "BufferView.h"
18 #include "metricsinfo.h"
20 #include "frontends/font_metrics.h"
21 #include "frontends/LyXView.h"
22 #include "frontends/Painter.h"
24 #include "graphics/GraphicsImage.h"
26 #include "support/filetools.h"
29 using namespace lyx::support;
31 namespace grfx = lyx::graphics;
33 RenderInset::RenderInset()
37 RenderInset::RenderInset(RenderInset const &)
39 // Cached variables are not copied
43 RenderInset::~RenderInset()
47 RenderInset & RenderInset::operator=(RenderInset const &)
49 // Cached variables are not copied
54 BufferView * RenderInset::view() const
56 return view_.lock().get();
60 ButtonRenderer::ButtonRenderer()
65 RenderInset * ButtonRenderer::clone() const
67 return new ButtonRenderer(*this);
71 void ButtonRenderer::update(string const & text, bool editable)
78 void ButtonRenderer::metrics(MetricsInfo & mi, Dimension & dim) const
82 LyXFont font(LyXFont::ALL_SANE);
86 font_metrics::buttonText(text_, font, dim.wid, dim.asc, dim.des);
88 font_metrics::rectText(text_, font, dim.wid, dim.asc, dim.des);
94 void ButtonRenderer::draw(PainterInfo & pi, int x, int y) const
97 view_ = pi.base.bv->owner()->view();
99 // Draw it as a box with the LaTeX text
100 LyXFont font(LyXFont::ALL_SANE);
101 font.setColor(LColor::command).decSize();
104 pi.pain.buttonText(x + 2, y, text_, font);
106 pi.pain.rectText(x + 2, y, text_, font,
107 LColor::commandbg, LColor::commandframe);
112 GraphicRenderer::GraphicRenderer()
117 GraphicRenderer::GraphicRenderer(GraphicRenderer const & other)
118 : RenderInset(other),
119 loader_(other.loader_),
120 params_(other.params_),
125 RenderInset * GraphicRenderer::clone() const
127 return new GraphicRenderer(*this);
131 void GraphicRenderer::update(grfx::Params const & params)
135 if (!params_.filename.empty()) {
136 Assert(AbsolutePath(params_.filename));
137 loader_.reset(params_.filename, params_);
142 bool GraphicRenderer::hasFileChanged() const
144 unsigned long const new_checksum = loader_.checksum();
145 bool const file_has_changed = checksum_ != new_checksum;
146 if (file_has_changed)
147 checksum_ = new_checksum;
148 return file_has_changed;
152 boost::signals::connection GraphicRenderer::connect(slot_type const & slot) const
154 return loader_.connect(slot);
158 string const GraphicRenderer::statusMessage() const
160 switch (loader_.status()) {
161 case grfx::WaitingToLoad:
162 return _("Not shown.");
164 return _("Loading...");
165 case grfx::Converting:
166 return _("Converting to loadable format...");
168 return _("Loaded into memory. Must now generate pixmap.");
169 case grfx::ScalingEtc:
170 return _("Scaling etc...");
172 return _("Ready to display");
173 case grfx::ErrorNoFile:
174 return _("No file found!");
175 case grfx::ErrorConverting:
176 return _("Error converting to loadable format");
177 case grfx::ErrorLoading:
178 return _("Error loading file into memory");
179 case grfx::ErrorGeneratingPixmap:
180 return _("Error generating the pixmap");
181 case grfx::ErrorUnknown:
182 return _("No image");
188 bool GraphicRenderer::readyToDisplay() const
190 if (!loader_.image() || loader_.status() != grfx::Ready)
192 return loader_.image()->isDrawable();
196 void GraphicRenderer::metrics(MetricsInfo & mi, Dimension & dim) const
198 bool image_ready = readyToDisplay();
200 dim.asc = image_ready ? loader_.image()->getHeight() : 50;
204 dim.wid = loader_.image()->getWidth() +
205 2 * Inset::TEXT_TO_INSET_OFFSET;
209 LyXFont msgFont(mi.base.font);
210 msgFont.setFamily(LyXFont::SANS_FAMILY);
212 string const justname = OnlyFilename(params_.filename);
213 if (!justname.empty()) {
214 msgFont.setSize(LyXFont::SIZE_FOOTNOTE);
215 font_width = font_metrics::width(justname, msgFont);
218 string const msg = statusMessage();
220 msgFont.setSize(LyXFont::SIZE_TINY);
221 font_width = std::max(font_width,
222 font_metrics::width(msg, msgFont));
225 dim.wid = std::max(50, font_width + 15);
232 void GraphicRenderer::draw(PainterInfo & pi, int x, int y) const
235 view_ = pi.base.bv->owner()->view();
238 // Comment this out and see if anything goes wrong.
239 // The explanation for why it _was_ needed once upon a time is below.
241 // MakeAbsPath returns filename_ unchanged if it is absolute
243 string const file_with_path =
244 MakeAbsPath(params_.filename, view_->buffer()->filePath());
246 // A 'paste' operation creates a new inset with the correct filepath,
247 // but then the 'old' inset stored in the 'copy' operation is actually
248 // added to the buffer.
250 // Thus, pasting a graphic into a new buffer with different
251 // buffer->filePath() will result in the image being displayed in LyX even
252 // though the relative path now points at nothing at all. Subsequent
253 // loading of the file into LyX will therefore fail.
255 // We should ensure that the filepath is correct.
256 if (file_with_path != loader_.filename()) {
257 params_.filename = file_with_path;
262 if (params_.display != grfx::NoDisplay &&
263 loader_.status() == grfx::WaitingToLoad)
264 loader_.startLoading();
266 if (params_.display != grfx::NoDisplay && !loader_.monitoring())
267 loader_.startMonitoring();
269 // This will draw the graphics. If the graphics has not been loaded yet,
270 // we draw just a rectangle.
272 if (readyToDisplay()) {
273 pi.pain.image(x + Inset::TEXT_TO_INSET_OFFSET,
275 dim_.wid - 2 * Inset::TEXT_TO_INSET_OFFSET,
280 pi.pain.rectangle(x + Inset::TEXT_TO_INSET_OFFSET,
282 dim_.wid - 2 * Inset::TEXT_TO_INSET_OFFSET,
283 dim_.asc + dim_.des);
285 // Print the file name.
286 LyXFont msgFont = pi.base.font;
287 msgFont.setFamily(LyXFont::SANS_FAMILY);
288 string const justname = OnlyFilename(params_.filename);
290 if (!justname.empty()) {
291 msgFont.setSize(LyXFont::SIZE_FOOTNOTE);
292 pi.pain.text(x + Inset::TEXT_TO_INSET_OFFSET + 6,
293 y - font_metrics::maxAscent(msgFont) - 4,
297 // Print the message.
298 string const msg = statusMessage();
300 msgFont.setSize(LyXFont::SIZE_TINY);
301 pi.pain.text(x + Inset::TEXT_TO_INSET_OFFSET + 6,
302 y - 4, msg, msgFont);