]> git.lyx.org Git - lyx.git/blob - src/insets/render_graphic.C
the exception safety patch
[lyx.git] / src / insets / render_graphic.C
1 /**
2  * \file render_graphic.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Angus Leeming
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "render_graphic.h"
14
15 #include "insets/inset.h"
16
17 #include "gettext.h"
18 #include "LColor.h"
19 #include "metricsinfo.h"
20
21 #include "frontends/font_metrics.h"
22 #include "frontends/Painter.h"
23
24 #include "graphics/GraphicsImage.h"
25
26 #include "support/filetools.h"
27
28 namespace graphics = lyx::graphics;
29
30 using lyx::support::AbsolutePath;
31 using lyx::support::OnlyFilename;
32
33 using std::string;
34 using std::auto_ptr;
35
36
37 RenderGraphic::RenderGraphic()
38         : checksum_(0)
39 {}
40
41
42 RenderGraphic::RenderGraphic(RenderGraphic const & other)
43         : RenderBase(other),
44           loader_(other.loader_),
45           params_(other.params_),
46           checksum_(0)
47 {}
48
49
50 auto_ptr<RenderBase> RenderGraphic::clone() const
51 {
52         return auto_ptr<RenderBase>(new RenderGraphic(*this));
53 }
54
55
56 void RenderGraphic::update(graphics::Params const & params)
57 {
58         params_ = params;
59
60         if (!params_.filename.empty()) {
61                 BOOST_ASSERT(AbsolutePath(params_.filename));
62                 loader_.reset(params_.filename, params_);
63         }
64 }
65
66
67 bool RenderGraphic::hasFileChanged() const
68 {
69         unsigned long const new_checksum = loader_.checksum();
70         bool const file_has_changed = checksum_ != new_checksum;
71         if (file_has_changed)
72                 checksum_ = new_checksum;
73         return file_has_changed;
74 }
75
76
77 boost::signals::connection RenderGraphic::connect(slot_type const & slot) const
78 {
79         return loader_.connect(slot);
80 }
81
82
83 namespace {
84
85 string const statusMessage(graphics::ImageStatus status)
86 {
87         switch (status) {
88         case graphics::WaitingToLoad:
89                 return _("Not shown.");
90         case graphics::Loading:
91                 return _("Loading...");
92         case graphics::Converting:
93                 return _("Converting to loadable format...");
94         case graphics::Loaded:
95                 return _("Loaded into memory. Must now generate pixmap.");
96         case graphics::ScalingEtc:
97                 return _("Scaling etc...");
98         case graphics::Ready:
99                 return _("Ready to display");
100         case graphics::ErrorNoFile:
101                 return _("No file found!");
102         case graphics::ErrorConverting:
103                 return _("Error converting to loadable format");
104         case graphics::ErrorLoading:
105                 return _("Error loading file into memory");
106         case graphics::ErrorGeneratingPixmap:
107                 return _("Error generating the pixmap");
108         case graphics::ErrorUnknown:
109                 return _("No image");
110         }
111         return string();
112 }
113
114
115 bool readyToDisplay(graphics::Loader const & loader)
116 {
117         if (!loader.image() || loader.status() != graphics::Ready)
118                 return false;
119         return loader.image()->isDrawable();
120 }
121
122 } // namespace anon
123
124
125 void RenderGraphic::metrics(MetricsInfo & mi, Dimension & dim) const
126 {
127         bool image_ready = readyToDisplay(loader_);
128
129         dim.asc = image_ready ? loader_.image()->getHeight() : 50;
130         dim.des = 0;
131
132         if (image_ready) {
133                 dim.wid = loader_.image()->getWidth() +
134                         2 * InsetOld::TEXT_TO_INSET_OFFSET;
135         } else {
136                 int font_width = 0;
137
138                 LyXFont msgFont(mi.base.font);
139                 msgFont.setFamily(LyXFont::SANS_FAMILY);
140
141                 string const justname = OnlyFilename(params_.filename);
142                 if (!justname.empty()) {
143                         msgFont.setSize(LyXFont::SIZE_FOOTNOTE);
144                         font_width = font_metrics::width(justname, msgFont);
145                 }
146
147                 string const msg = statusMessage(loader_.status());
148                 if (!msg.empty()) {
149                         msgFont.setSize(LyXFont::SIZE_TINY);
150                         font_width = std::max(font_width,
151                                               font_metrics::width(msg, msgFont));
152                 }
153
154                 dim.wid = std::max(50, font_width + 15);
155         }
156
157         dim_ = dim;
158 }
159
160
161 void RenderGraphic::draw(PainterInfo & pi, int x, int y) const
162 {
163         if (params_.display != graphics::NoDisplay &&
164             loader_.status() == graphics::WaitingToLoad)
165                 loader_.startLoading();
166
167         if (params_.display != graphics::NoDisplay &&
168             !loader_.monitoring())
169                 loader_.startMonitoring();
170
171         // This will draw the graphics. If the graphics has not been loaded yet,
172         // we draw just a rectangle.
173
174         if (readyToDisplay(loader_)) {
175                 pi.pain.image(x + InsetOld::TEXT_TO_INSET_OFFSET,
176                               y - dim_.asc,
177                               dim_.wid - 2 * InsetOld::TEXT_TO_INSET_OFFSET,
178                               dim_.asc + dim_.des,
179                               *loader_.image());
180
181         } else {
182                 pi.pain.rectangle(x + InsetOld::TEXT_TO_INSET_OFFSET,
183                                   y - dim_.asc,
184                                   dim_.wid - 2 * InsetOld::TEXT_TO_INSET_OFFSET,
185                                   dim_.asc + dim_.des,
186                                   LColor::foreground);
187
188                 // Print the file name.
189                 LyXFont msgFont = pi.base.font;
190                 msgFont.setFamily(LyXFont::SANS_FAMILY);
191                 string const justname = OnlyFilename(params_.filename);
192
193                 if (!justname.empty()) {
194                         msgFont.setSize(LyXFont::SIZE_FOOTNOTE);
195                         pi.pain.text(x + InsetOld::TEXT_TO_INSET_OFFSET + 6,
196                                    y - font_metrics::maxAscent(msgFont) - 4,
197                                    justname, msgFont);
198                 }
199
200                 // Print the message.
201                 string const msg = statusMessage(loader_.status());
202                 if (!msg.empty()) {
203                         msgFont.setSize(LyXFont::SIZE_TINY);
204                         pi.pain.text(x + InsetOld::TEXT_TO_INSET_OFFSET + 6,
205                                      y - 4, msg, msgFont);
206                 }
207         }
208 }