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