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