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 RenderInset::RenderInset()
35 RenderInset::RenderInset(RenderInset const &)
37 // Cached variables are not copied
41 RenderInset::~RenderInset()
45 RenderInset & RenderInset::operator=(RenderInset const &)
47 // Cached variables are not copied
52 BufferView * RenderInset::view() const
54 return view_.lock().get();
58 ButtonRenderer::ButtonRenderer()
63 RenderInset * ButtonRenderer::clone() const
65 return new ButtonRenderer(*this);
69 void ButtonRenderer::update(string const & text, bool editable)
76 void ButtonRenderer::metrics(MetricsInfo & mi, Dimension & dim) const
80 LyXFont font(LyXFont::ALL_SANE);
84 font_metrics::buttonText(text_, font, dim.wid, dim.asc, dim.des);
86 font_metrics::rectText(text_, font, dim.wid, dim.asc, dim.des);
92 void ButtonRenderer::draw(PainterInfo & pi, int x, int y) const
95 view_ = pi.base.bv->owner()->view();
97 // Draw it as a box with the LaTeX text
98 LyXFont font(LyXFont::ALL_SANE);
99 font.setColor(LColor::command).decSize();
102 pi.pain.buttonText(x + 2, y, text_, font);
104 pi.pain.rectText(x + 2, y, text_, font,
105 LColor::commandbg, LColor::commandframe);
110 GraphicRenderer::GraphicRenderer()
115 GraphicRenderer::GraphicRenderer(GraphicRenderer const & other)
116 : RenderInset(other),
117 loader_(other.loader_),
118 params_(other.params_),
123 RenderInset * GraphicRenderer::clone() const
125 return new GraphicRenderer(*this);
129 void GraphicRenderer::update(grfx::Params const & params)
133 if (!params_.filename.empty()) {
134 Assert(AbsolutePath(params_.filename));
135 loader_.reset(params_.filename, params_);
140 bool GraphicRenderer::hasFileChanged() const
142 unsigned long const new_checksum = loader_.checksum();
143 bool const file_has_changed = checksum_ != new_checksum;
144 if (file_has_changed)
145 checksum_ = new_checksum;
146 return file_has_changed;
150 boost::signals::connection GraphicRenderer::connect(slot_type const & slot) const
152 return loader_.connect(slot);
156 string const GraphicRenderer::statusMessage() const
158 switch (loader_.status()) {
159 case grfx::WaitingToLoad:
160 return _("Not shown.");
162 return _("Loading...");
163 case grfx::Converting:
164 return _("Converting to loadable format...");
166 return _("Loaded into memory. Must now generate pixmap.");
167 case grfx::ScalingEtc:
168 return _("Scaling etc...");
170 return _("Ready to display");
171 case grfx::ErrorNoFile:
172 return _("No file found!");
173 case grfx::ErrorConverting:
174 return _("Error converting to loadable format");
175 case grfx::ErrorLoading:
176 return _("Error loading file into memory");
177 case grfx::ErrorGeneratingPixmap:
178 return _("Error generating the pixmap");
179 case grfx::ErrorUnknown:
180 return _("No image");
186 bool GraphicRenderer::readyToDisplay() const
188 if (!loader_.image() || loader_.status() != grfx::Ready)
190 return loader_.image()->isDrawable();
194 void GraphicRenderer::metrics(MetricsInfo & mi, Dimension & dim) const
196 bool image_ready = readyToDisplay();
198 dim.asc = image_ready ? loader_.image()->getHeight() : 50;
202 dim.wid = loader_.image()->getWidth() +
203 2 * Inset::TEXT_TO_INSET_OFFSET;
207 LyXFont msgFont(mi.base.font);
208 msgFont.setFamily(LyXFont::SANS_FAMILY);
210 string const justname = OnlyFilename(params_.filename);
211 if (!justname.empty()) {
212 msgFont.setSize(LyXFont::SIZE_FOOTNOTE);
213 font_width = font_metrics::width(justname, msgFont);
216 string const msg = statusMessage();
218 msgFont.setSize(LyXFont::SIZE_TINY);
219 font_width = std::max(font_width,
220 font_metrics::width(msg, msgFont));
223 dim.wid = std::max(50, font_width + 15);
230 void GraphicRenderer::draw(PainterInfo & pi, int x, int y) const
233 view_ = pi.base.bv->owner()->view();
236 // Comment this out and see if anything goes wrong.
237 // The explanation for why it _was_ needed once upon a time is below.
239 // MakeAbsPath returns filename_ unchanged if it is absolute
241 string const file_with_path =
242 MakeAbsPath(params_.filename, view_->buffer()->filePath());
244 // A 'paste' operation creates a new inset with the correct filepath,
245 // but then the 'old' inset stored in the 'copy' operation is actually
246 // added to the buffer.
248 // Thus, pasting a graphic into a new buffer with different
249 // buffer->filePath() will result in the image being displayed in LyX even
250 // though the relative path now points at nothing at all. Subsequent
251 // loading of the file into LyX will therefore fail.
253 // We should ensure that the filepath is correct.
254 if (file_with_path != loader_.filename()) {
255 params_.filename = file_with_path;
260 if (params_.display != grfx::NoDisplay &&
261 loader_.status() == grfx::WaitingToLoad)
262 loader_.startLoading();
264 if (params_.display != grfx::NoDisplay && !loader_.monitoring())
265 loader_.startMonitoring();
267 // This will draw the graphics. If the graphics has not been loaded yet,
268 // we draw just a rectangle.
270 if (readyToDisplay()) {
271 pi.pain.image(x + Inset::TEXT_TO_INSET_OFFSET,
273 dim_.wid - 2 * Inset::TEXT_TO_INSET_OFFSET,
278 pi.pain.rectangle(x + Inset::TEXT_TO_INSET_OFFSET,
280 dim_.wid - 2 * Inset::TEXT_TO_INSET_OFFSET,
281 dim_.asc + dim_.des);
283 // Print the file name.
284 LyXFont msgFont = pi.base.font;
285 msgFont.setFamily(LyXFont::SANS_FAMILY);
286 string const justname = OnlyFilename(params_.filename);
288 if (!justname.empty()) {
289 msgFont.setSize(LyXFont::SIZE_FOOTNOTE);
290 pi.pain.text(x + Inset::TEXT_TO_INSET_OFFSET + 6,
291 y - font_metrics::maxAscent(msgFont) - 4,
295 // Print the message.
296 string const msg = statusMessage();
298 msgFont.setSize(LyXFont::SIZE_TINY);
299 pi.pain.text(x + Inset::TEXT_TO_INSET_OFFSET + 6,
300 y - 4, msg, msgFont);