]> git.lyx.org Git - lyx.git/blob - src/insets/render_graphic.C
31d4605b117778504a61b4afb6e48a546a2712fc
[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::support::AbsolutePath;
35 using lyx::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                 BOOST_ASSERT(AbsolutePath(params_.filename));
71                 loader_.reset(params_.filename, params_);
72         }
73 }
74
75
76 namespace {
77
78 bool displayGraphic(graphics::Params const & params)
79 {
80         return params.display != graphics::NoDisplay &&
81                 lyxrc.display_graphics != graphics::NoDisplay;
82 }
83
84
85 string const statusMessage(graphics::Params const & params,
86                            graphics::ImageStatus status)
87 {
88         if (!displayGraphic(params))
89                 return _("Not shown.");
90
91         switch (status) {
92         case graphics::WaitingToLoad:
93                 return _("Not shown.");
94         case graphics::Loading:
95                 return _("Loading...");
96         case graphics::Converting:
97                 return _("Converting to loadable format...");
98         case graphics::Loaded:
99                 return _("Loaded into memory. Generating pixmap...");
100         case graphics::ScalingEtc:
101                 return _("Scaling etc...");
102         case graphics::Ready:
103                 return _("Ready to display");
104         case graphics::ErrorNoFile:
105                 return _("No file found!");
106         case graphics::ErrorConverting:
107                 return _("Error converting to loadable format");
108         case graphics::ErrorLoading:
109                 return _("Error loading file into memory");
110         case graphics::ErrorGeneratingPixmap:
111                 return _("Error generating the pixmap");
112         case graphics::ErrorUnknown:
113                 return _("No image");
114         }
115         return string();
116 }
117
118
119 bool readyToDisplay(graphics::Loader const & loader)
120 {
121         if (!loader.image() || loader.status() != graphics::Ready)
122                 return false;
123         return loader.image()->isDrawable();
124 }
125
126 } // namespace anon
127
128
129 void RenderGraphic::metrics(MetricsInfo & mi, Dimension & dim) const
130 {
131         bool image_ready = displayGraphic(params_) && readyToDisplay(loader_);
132
133         dim.asc = image_ready ? loader_.image()->getHeight() : 50;
134         dim.des = 0;
135
136         if (image_ready) {
137                 dim.wid = loader_.image()->getWidth() +
138                         2 * InsetOld::TEXT_TO_INSET_OFFSET;
139         } else {
140                 int font_width = 0;
141
142                 LyXFont msgFont(mi.base.font);
143                 msgFont.setFamily(LyXFont::SANS_FAMILY);
144
145                 string const justname = OnlyFilename(params_.filename);
146                 if (!justname.empty()) {
147                         msgFont.setSize(LyXFont::SIZE_FOOTNOTE);
148                         font_width = font_metrics::width(justname, msgFont);
149                 }
150
151                 string const msg = statusMessage(params_, loader_.status());
152                 if (!msg.empty()) {
153                         msgFont.setSize(LyXFont::SIZE_TINY);
154                         font_width = std::max(font_width,
155                                               font_metrics::width(msg, msgFont));
156                 }
157
158                 dim.wid = std::max(50, font_width + 15);
159         }
160
161         dim_ = dim;
162 }
163
164
165 void RenderGraphic::draw(PainterInfo & pi, int x, int y) const
166 {
167         if (displayGraphic(params_)) {
168                 if (loader_.status() == graphics::WaitingToLoad)
169                         loader_.startLoading();
170                 if (!loader_.monitoring())
171                         loader_.startMonitoring();
172         }
173
174         // This will draw the graphics. If the graphics has not been
175         // loaded yet, we draw just a rectangle.
176
177         if (displayGraphic(params_) && readyToDisplay(loader_)) {
178                 pi.pain.image(x + InsetOld::TEXT_TO_INSET_OFFSET,
179                               y - dim_.asc,
180                               dim_.wid - 2 * InsetOld::TEXT_TO_INSET_OFFSET,
181                               dim_.asc + dim_.des,
182                               *loader_.image());
183
184         } else {
185                 pi.pain.rectangle(x + InsetOld::TEXT_TO_INSET_OFFSET,
186                                   y - dim_.asc,
187                                   dim_.wid - 2 * InsetOld::TEXT_TO_INSET_OFFSET,
188                                   dim_.asc + dim_.des,
189                                   LColor::foreground);
190
191                 // Print the file name.
192                 LyXFont msgFont = pi.base.font;
193                 msgFont.setFamily(LyXFont::SANS_FAMILY);
194                 string const justname = OnlyFilename(params_.filename);
195
196                 if (!justname.empty()) {
197                         msgFont.setSize(LyXFont::SIZE_FOOTNOTE);
198                         pi.pain.text(x + InsetOld::TEXT_TO_INSET_OFFSET + 6,
199                                    y - font_metrics::maxAscent(msgFont) - 4,
200                                    justname, msgFont);
201                 }
202
203                 // Print the message.
204                 string const msg = statusMessage(params_, loader_.status());
205                 if (!msg.empty()) {
206                         msgFont.setSize(LyXFont::SIZE_TINY);
207                         pi.pain.text(x + InsetOld::TEXT_TO_INSET_OFFSET + 6,
208                                      y - 4, msg, msgFont);
209                 }
210         }
211 }