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