]> git.lyx.org Git - lyx.git/blob - src/insets/InsetVSpace.cpp
This should be the last of the commits refactoring the InsetLayout code.
[lyx.git] / src / insets / InsetVSpace.cpp
1 /**
2  * \file InsetVSpace.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author various
7  * \author André Pönitz
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "InsetVSpace.h"
15
16 #include "Buffer.h"
17 #include "Cursor.h"
18 #include "Dimension.h"
19 #include "DispatchResult.h"
20 #include "FuncRequest.h"
21 #include "support/gettext.h"
22 #include "Lexer.h"
23 #include "Text.h"
24 #include "MetricsInfo.h"
25 #include "OutputParams.h"
26
27 #include "frontends/FontMetrics.h"
28 #include "frontends/Painter.h"
29
30 #include <sstream>
31
32 using namespace std;
33
34 namespace lyx {
35
36 namespace {
37
38 int const ADD_TO_VSPACE_WIDTH = 5;
39
40 } // namespace anon
41
42
43 InsetVSpace::InsetVSpace(VSpace const & space)
44         : space_(space)
45 {}
46
47
48 InsetVSpace::~InsetVSpace()
49 {
50         InsetVSpaceMailer(*this).hideDialog();
51 }
52
53
54 Inset * InsetVSpace::clone() const
55 {
56         return new InsetVSpace(*this);
57 }
58
59
60 void InsetVSpace::doDispatch(Cursor & cur, FuncRequest & cmd)
61 {
62         switch (cmd.action) {
63
64         case LFUN_INSET_MODIFY: {
65                 InsetVSpaceMailer::string2params(to_utf8(cmd.argument()), space_);
66                 break;
67         }
68
69         case LFUN_MOUSE_RELEASE:
70                 if (!cur.selection())
71                         InsetVSpaceMailer(*this).showDialog(&cur.bv());
72                 break;
73
74         default:
75                 Inset::doDispatch(cur, cmd);
76                 break;
77         }
78 }
79
80
81 void InsetVSpace::read(Buffer const &, Lexer & lex)
82 {
83         BOOST_ASSERT(lex.isOK());
84         string vsp;
85         lex >> vsp;
86         if (lex)
87                 space_ = VSpace(vsp);
88
89         string end_token;
90         lex >> end_token;
91         if (end_token != "\\end_inset")
92                 lex.printError("Missing \\end_inset at this point. "
93                                "Read: `$$Token'");
94 }
95
96
97 void InsetVSpace::write(Buffer const &, ostream & os) const
98 {
99         os << "VSpace " << space_.asLyXCommand();
100 }
101
102
103 docstring const InsetVSpace::label() const
104 {
105         static docstring const label = _("Vertical Space");
106         return label + " (" + space_.asGUIName() + ')';
107 }
108
109
110 namespace {
111 int const arrow_size = 4;
112 }
113
114
115 void InsetVSpace::metrics(MetricsInfo & mi, Dimension & dim) const
116 {
117         int height = 3 * arrow_size;
118         if (space_.length().len().value() >= 0.0)
119                 height = max(height, space_.inPixels(*mi.base.bv));
120
121         FontInfo font;
122         font.decSize();
123         font.decSize();
124
125         int w = 0;
126         int a = 0;
127         int d = 0;
128         theFontMetrics(font).rectText(label(), w, a, d);
129
130         height = max(height, a + d);
131
132         dim.asc = height / 2 + (a - d) / 2; // align cursor with the
133         dim.des = height - dim.asc;         // label text
134         dim.wid = ADD_TO_VSPACE_WIDTH + 2 * arrow_size + 5 + w;
135         // Cache the inset dimension. 
136         setDimCache(mi, dim);
137 }
138
139
140 void InsetVSpace::draw(PainterInfo & pi, int x, int y) const
141 {
142         Dimension const dim = dimension(*pi.base.bv);
143         x += ADD_TO_VSPACE_WIDTH;
144         int const start = y - dim.asc;
145         int const end   = y + dim.des;
146
147         // y-values for top arrow
148         int ty1, ty2;
149         // y-values for bottom arrow
150         int by1, by2;
151
152         if (space_.kind() == VSpace::VFILL) {
153                 ty1 = ty2 = start;
154                 by1 = by2 = end;
155         } else {
156                 // adding or removing space
157                 bool const added = space_.kind() != VSpace::LENGTH ||
158                                    space_.length().len().value() >= 0.0;
159                 ty1 = added ? (start + arrow_size) : start;
160                 ty2 = added ? start : (start + arrow_size);
161                 by1 = added ? (end - arrow_size) : end;
162                 by2 = added ? end : (end - arrow_size);
163         }
164
165         int const midx = x + arrow_size;
166         int const rightx = midx + arrow_size;
167
168         // first the string
169         int w = 0;
170         int a = 0;
171         int d = 0;
172
173         FontInfo font;
174         font.setColor(Color_added_space);
175         font.decSize();
176         font.decSize();
177         docstring const lab = label();
178         theFontMetrics(font).rectText(lab, w, a, d);
179
180         pi.pain.rectText(x + 2 * arrow_size + 5,
181                          start + (end - start) / 2 + (a - d) / 2,
182                          lab, font, Color_none, Color_none);
183
184         // top arrow
185         pi.pain.line(x, ty1, midx, ty2, Color_added_space);
186         pi.pain.line(midx, ty2, rightx, ty1, Color_added_space);
187
188         // bottom arrow
189         pi.pain.line(x, by1, midx, by2, Color_added_space);
190         pi.pain.line(midx, by2, rightx, by1, Color_added_space);
191
192         // joining line
193         pi.pain.line(midx, ty2, midx, by2, Color_added_space);
194 }
195
196
197 int InsetVSpace::latex(Buffer const & buf, odocstream & os,
198                        OutputParams const &) const
199 {
200         os << from_ascii(space_.asLatexCommand(buf.params())) << '\n';
201         return 1;
202 }
203
204
205 int InsetVSpace::plaintext(Buffer const &, odocstream & os,
206                            OutputParams const &) const
207 {
208         os << "\n\n";
209         return PLAINTEXT_NEWLINE;
210 }
211
212
213 int InsetVSpace::docbook(Buffer const &, odocstream & os,
214                          OutputParams const &) const
215 {
216         os << '\n';
217         return 1;
218 }
219
220
221 string const InsetVSpaceMailer::name_ = "vspace";
222
223
224 InsetVSpaceMailer::InsetVSpaceMailer(InsetVSpace & inset)
225         : inset_(inset)
226 {}
227
228
229 string const InsetVSpaceMailer::inset2string(Buffer const &) const
230 {
231         return params2string(inset_.space());
232 }
233
234
235 void InsetVSpaceMailer::string2params(string const & in, VSpace & vspace)
236 {
237         vspace = VSpace();
238         if (in.empty())
239                 return;
240
241         istringstream data(in);
242         Lexer lex(0,0);
243         lex.setStream(data);
244
245         string name;
246         lex >> name;
247         if (!lex || name != name_)
248                 return print_mailer_error("InsetVSpaceMailer", in, 1, name_);
249
250         string vsp;
251         lex >> vsp;
252         if (lex)
253                 vspace = VSpace(vsp);
254 }
255
256
257 string const InsetVSpaceMailer::params2string(VSpace const & vspace)
258 {
259         ostringstream data;
260         data << name_ << ' ' << vspace.asLyXCommand();
261         return data.str();
262 }
263
264
265 } // namespace lyx