]> git.lyx.org Git - lyx.git/blob - src/insets/InsetVSpace.cpp
Fix GRAPHICS_EDIT of InsetGraphics
[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 void InsetVSpace::doDispatch(Cursor & cur, FuncRequest & cmd)
55 {
56         switch (cmd.action) {
57
58         case LFUN_INSET_MODIFY: {
59                 InsetVSpaceMailer::string2params(to_utf8(cmd.argument()), space_);
60                 break;
61         }
62
63         case LFUN_MOUSE_RELEASE:
64                 if (!cur.selection())
65                         InsetVSpaceMailer(*this).showDialog(&cur.bv());
66                 break;
67
68         default:
69                 Inset::doDispatch(cur, cmd);
70                 break;
71         }
72 }
73
74
75 void InsetVSpace::read(Lexer & lex)
76 {
77         BOOST_ASSERT(lex.isOK());
78         string vsp;
79         lex >> vsp;
80         if (lex)
81                 space_ = VSpace(vsp);
82
83         string end_token;
84         lex >> end_token;
85         if (end_token != "\\end_inset")
86                 lex.printError("Missing \\end_inset at this point. "
87                                "Read: `$$Token'");
88 }
89
90
91 void InsetVSpace::write(ostream & os) const
92 {
93         os << "VSpace " << space_.asLyXCommand();
94 }
95
96
97 docstring const InsetVSpace::label() const
98 {
99         static docstring const label = _("Vertical Space");
100         return label + " (" + space_.asGUIName() + ')';
101 }
102
103
104 namespace {
105 int const arrow_size = 4;
106 }
107
108
109 void InsetVSpace::metrics(MetricsInfo & mi, Dimension & dim) const
110 {
111         int height = 3 * arrow_size;
112         if (space_.length().len().value() >= 0.0)
113                 height = max(height, space_.inPixels(*mi.base.bv));
114
115         FontInfo font;
116         font.decSize();
117         font.decSize();
118
119         int w = 0;
120         int a = 0;
121         int d = 0;
122         theFontMetrics(font).rectText(label(), w, a, d);
123
124         height = max(height, a + d);
125
126         dim.asc = height / 2 + (a - d) / 2; // align cursor with the
127         dim.des = height - dim.asc;         // label text
128         dim.wid = ADD_TO_VSPACE_WIDTH + 2 * arrow_size + 5 + w;
129         // Cache the inset dimension. 
130         setDimCache(mi, dim);
131 }
132
133
134 void InsetVSpace::draw(PainterInfo & pi, int x, int y) const
135 {
136         Dimension const dim = dimension(*pi.base.bv);
137         x += ADD_TO_VSPACE_WIDTH;
138         int const start = y - dim.asc;
139         int const end   = y + dim.des;
140
141         // y-values for top arrow
142         int ty1, ty2;
143         // y-values for bottom arrow
144         int by1, by2;
145
146         if (space_.kind() == VSpace::VFILL) {
147                 ty1 = ty2 = start;
148                 by1 = by2 = end;
149         } else {
150                 // adding or removing space
151                 bool const added = space_.kind() != VSpace::LENGTH ||
152                                    space_.length().len().value() >= 0.0;
153                 ty1 = added ? (start + arrow_size) : start;
154                 ty2 = added ? start : (start + arrow_size);
155                 by1 = added ? (end - arrow_size) : end;
156                 by2 = added ? end : (end - arrow_size);
157         }
158
159         int const midx = x + arrow_size;
160         int const rightx = midx + arrow_size;
161
162         // first the string
163         int w = 0;
164         int a = 0;
165         int d = 0;
166
167         FontInfo font;
168         font.setColor(Color_added_space);
169         font.decSize();
170         font.decSize();
171         docstring const lab = label();
172         theFontMetrics(font).rectText(lab, w, a, d);
173
174         pi.pain.rectText(x + 2 * arrow_size + 5,
175                          start + (end - start) / 2 + (a - d) / 2,
176                          lab, font, Color_none, Color_none);
177
178         // top arrow
179         pi.pain.line(x, ty1, midx, ty2, Color_added_space);
180         pi.pain.line(midx, ty2, rightx, ty1, Color_added_space);
181
182         // bottom arrow
183         pi.pain.line(x, by1, midx, by2, Color_added_space);
184         pi.pain.line(midx, by2, rightx, by1, Color_added_space);
185
186         // joining line
187         pi.pain.line(midx, ty2, midx, by2, Color_added_space);
188 }
189
190
191 int InsetVSpace::latex(odocstream & os, OutputParams const &) const
192 {
193         os << from_ascii(space_.asLatexCommand(buffer().params())) << '\n';
194         return 1;
195 }
196
197
198 int InsetVSpace::plaintext(odocstream & os, OutputParams const &) const
199 {
200         os << "\n\n";
201         return PLAINTEXT_NEWLINE;
202 }
203
204
205 int InsetVSpace::docbook(odocstream & os, OutputParams const &) const
206 {
207         os << '\n';
208         return 1;
209 }
210
211
212 string const InsetVSpaceMailer::name_ = "vspace";
213
214
215 InsetVSpaceMailer::InsetVSpaceMailer(InsetVSpace & inset)
216         : inset_(inset)
217 {}
218
219
220 string const InsetVSpaceMailer::inset2string(Buffer const &) const
221 {
222         return params2string(inset_.space());
223 }
224
225
226 void InsetVSpaceMailer::string2params(string const & in, VSpace & vspace)
227 {
228         vspace = VSpace();
229         if (in.empty())
230                 return;
231
232         istringstream data(in);
233         Lexer lex(0,0);
234         lex.setStream(data);
235
236         string name;
237         lex >> name;
238         if (!lex || name != name_)
239                 return print_mailer_error("InsetVSpaceMailer", in, 1, name_);
240
241         string vsp;
242         lex >> vsp;
243         if (lex)
244                 vspace = VSpace(vsp);
245 }
246
247
248 string const InsetVSpaceMailer::params2string(VSpace const & vspace)
249 {
250         ostringstream data;
251         data << name_ << ' ' << vspace.asLyXCommand();
252         return data.str();
253 }
254
255
256 } // namespace lyx