]> git.lyx.org Git - lyx.git/blob - src/mathed/InsetMathPhantom.cpp
g-brief loads babel internally. So don't load it ourselves.
[lyx.git] / src / mathed / InsetMathPhantom.cpp
1 /**
2  * \file InsetMathPhantom.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Georg Baum
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "InsetMathPhantom.h"
14
15 #include "LaTeXFeatures.h"
16 #include "MathStream.h"
17
18 #include "MetricsInfo.h"
19
20 #include "frontends/Painter.h"
21
22 #include <algorithm>
23 #include <ostream>
24
25 namespace lyx {
26
27
28 InsetMathPhantom::InsetMathPhantom(Buffer * buf, Kind k)
29         : InsetMathNest(buf, 1), kind_(k)
30 {}
31
32
33 Inset * InsetMathPhantom::clone() const
34 {
35         return new InsetMathPhantom(*this);
36 }
37
38
39 void InsetMathPhantom::metrics(MetricsInfo & mi, Dimension & dim) const
40 {
41         Changer dummy = mi.base.changeEnsureMath();
42         cell(0).metrics(mi, dim);
43 }
44
45
46 void InsetMathPhantom::draw(PainterInfo & pi, int x, int y) const
47 {
48         Changer dummy = pi.base.changeEnsureMath();
49         static int const arrow_size = 4;
50
51         // We first draw the text and then an arrow
52         ColorCode const origcol = pi.base.font.color();
53         if (visibleContents())
54                 pi.base.font.setColor(Color_special);
55         cell(0).draw(pi, x, y);
56         if (visibleContents())
57                 pi.base.font.setColor(origcol);
58         Dimension const dim = dimension(*pi.base.bv);
59
60         if (kind_ == phantom || kind_ == vphantom) {
61                 // y1---------
62                 //           / \.
63                 // y2-----  / | \.
64                 //            |
65                 //            |
66                 // y3-----  \ | /
67                 //           \ /
68                 // y4---------
69                 //          | | |
70                 //         /  |  \.
71                 //        x1  x2 x3
72
73                 int const x2 = x + dim.wid / 2;
74                 int const x1 = x2 - arrow_size;
75                 int const x3 = x2 + arrow_size;
76
77                 int const y1 = y - dim.asc;
78                 int const y2 = y1 + arrow_size;
79                 int const y4 = y + dim.des;
80                 int const y3 = y4 - arrow_size;
81
82                 // top arrow
83                 pi.pain.line(x2, y1, x1, y2, Color_added_space);
84                 pi.pain.line(x2, y1, x3, y2, Color_added_space);
85
86                 // bottom arrow
87                 pi.pain.line(x2, y4, x1, y3, Color_added_space);
88                 pi.pain.line(x2, y4, x3, y3, Color_added_space);
89
90                 // joining line
91                 pi.pain.line(x2, y1, x2, y4, Color_added_space);
92         }
93
94         if (kind_ == phantom || kind_ == hphantom) {
95                 // y1----  /            \.
96                 //        /              \.
97                 // y2--- <---------------->
98                 //        \              /
99                 // y3----  \            /
100                 //       |  |          |  |
101                 //      x1 x2         x3 x4
102
103                 int const x1 = x;
104                 int const x2 = x + arrow_size;
105                 int const x4 = x + dim.wid;
106                 int const x3 = x4 - arrow_size;
107
108                 int const y2 = y + (dim.des - dim.asc) / 2;
109                 int const y1 = y2 - arrow_size;
110                 int const y3 = y2 + arrow_size;
111
112                 // left arrow
113                 pi.pain.line(x1, y2, x2, y3, Color_added_space);
114                 pi.pain.line(x1, y2, x2, y1, Color_added_space);
115
116                 // right arrow
117                 pi.pain.line(x4, y2, x3, y3, Color_added_space);
118                 pi.pain.line(x4, y2, x3, y1, Color_added_space);
119
120                 // joining line
121                 pi.pain.line(x1, y2, x4, y2, Color_added_space);
122         }
123
124         else if (kind_ == mathclap) {
125                 // y1----      \     /
126                 //              \   /
127                 // y2--- -------->-<--------
128                 //              /   \.
129                 // y3----      /     \.
130                 //       |    |   |   |    |
131                 //      x1   x2  x3  x4   x5
132
133                 int const x1 = x;
134                 int const x5 = x + dim.wid;
135                 int const x3 = x + dim.wid / 2;
136                 int const x2 = std::max(x1, x3 - arrow_size);
137                 int const x4 = std::min(x5, x3 + arrow_size);
138
139                 int const y2 = y + (dim.des - dim.asc) / 2;
140                 int const y1 = y2 - arrow_size;
141                 int const y3 = y2 + arrow_size;
142
143                 // left arrow
144                 pi.pain.line(x2, y3, x3, y2, Color_added_space);
145                 pi.pain.line(x2, y1, x3, y2, Color_added_space);
146
147                 // right arrow
148                 pi.pain.line(x4, y3, x3, y2, Color_added_space);
149                 pi.pain.line(x4, y1, x3, y2, Color_added_space);
150
151                 // joining line
152                 pi.pain.line(x1, y2, x5, y2, Color_added_space);
153         }
154
155         else if (kind_ == mathllap) {
156                 // y1----                \.
157                 //                        \.
158                 // y2--- ------------------>
159                 //                        /
160                 // y3----                /
161                 //       |              |  |
162                 //      x1             x2 x3
163
164                 int const x1 = x;
165                 int const x3 = x + dim.wid;
166                 int const x2 = std::max(x1, x3 - arrow_size);
167
168                 int const y2 = y + (dim.des - dim.asc) / 2;
169                 int const y1 = y2 - arrow_size;
170                 int const y3 = y2 + arrow_size;
171
172                 // right arrow
173                 pi.pain.line(x3, y2, x2, y3, Color_added_space);
174                 pi.pain.line(x3, y2, x2, y1, Color_added_space);
175
176                 // joining line
177                 pi.pain.line(x1, y2, x3, y2, Color_added_space);
178         }
179
180         else if (kind_ == mathrlap) {
181                 // y1----  /
182                 //        /
183                 // y2--- <------------------
184                 //        \.
185                 // y3----  \.
186                 //       |  |              |
187                 //      x1 x2             x3
188
189                 int const x1 = x;
190                 int const x3 = x + dim.wid;
191                 int const x2 = std::min(x3, x + arrow_size);
192
193                 int const y2 = y + (dim.des - dim.asc) / 2;
194                 int const y1 = y2 - arrow_size;
195                 int const y3 = y2 + arrow_size;
196
197                 // left arrow
198                 pi.pain.line(x1, y2, x2, y3, Color_added_space);
199                 pi.pain.line(x1, y2, x2, y1, Color_added_space);
200
201                 // joining line
202                 pi.pain.line(x1, y2, x3, y2, Color_added_space);
203         }
204
205         else if (kind_ == smash || kind_ == smasht || kind_ == smashb) {
206                 // y1---------
207                 //            |
208                 // y2-----  \ | /
209                 //           \ /
210                 // y3-------- |
211                 //           / \.
212                 // y4-----  / | \.
213                 //            |
214                 // y5---------
215                 //          | | |
216                 //         /  |  \.
217                 //        x1  x2 x3
218
219                 int const x2 = x + dim.wid / 2;
220                 int const x1 = x2 - arrow_size;
221                 int const x3 = x2 + arrow_size;
222
223                 int const y1 = y - dim.asc;
224                 int const y5 = y + dim.des;
225                 int const y3 = y;
226                 int const y2 = std::max(y1, y3 - arrow_size);
227                 int const y4 = std::min(y5, y3 + arrow_size);
228
229                 // top arrow
230                 if (kind_ != smashb) {
231                         pi.pain.line(x1, y2, x2, y3, Color_added_space);
232                         pi.pain.line(x3, y2, x2, y3, Color_added_space);
233                 }
234
235                 // bottom arrow
236                 if (kind_ != smasht) {
237                         pi.pain.line(x1, y4, x2, y3, Color_added_space);
238                         pi.pain.line(x3, y4, x2, y3, Color_added_space);
239                 }
240
241                 // joining line
242                 if (kind_ == smasht)
243                         pi.pain.line(x2, y1, x2, y3, Color_added_space);
244                 else if (kind_ == smashb)
245                         pi.pain.line(x2, y3, x2, y5, Color_added_space);
246                 else
247                         pi.pain.line(x2, y1, x2, y5, Color_added_space);
248         }
249 }
250
251
252 void InsetMathPhantom::write(TeXMathStream & os) const
253 {
254         MathEnsurer ensurer(os);
255         if (os.fragile())
256                 os << "\\protect";
257         switch (kind_) {
258         case phantom:
259                 os << "\\phantom{";
260                 break;
261         case vphantom:
262                 os << "\\vphantom{";
263                 break;
264         case hphantom:
265                 os << "\\hphantom{";
266                 break;
267         case smash:
268                 os << "\\smash{";
269                 break;
270         case smasht:
271                 os << "\\smash[t]{";
272                 break;
273         case smashb:
274                 os << "\\smash[b]{";
275                 break;
276         case mathclap:
277                 os << "\\mathclap{";
278                 break;
279         case mathllap:
280                 os << "\\mathllap{";
281                 break;
282         case mathrlap:
283                 os << "\\mathrlap{";
284                 break;
285         }
286         os << cell(0) << '}';
287 }
288
289
290 void InsetMathPhantom::normalize(NormalStream & os) const
291 {
292         switch (kind_) {
293         case phantom:
294                 os << "[phantom ";
295                 break;
296         case vphantom:
297                 os << "[vphantom ";
298                 break;
299         case hphantom:
300                 os << "[hphantom ";
301                 break;
302         case smash:
303                 os << "[smash ";
304                 break;
305         case smasht:
306                 os << "[smasht ";
307                 break;
308         case smashb:
309                 os << "[smashb ";
310                 break;
311         case mathclap:
312                 os << "[mathclap ";
313                 break;
314         case mathllap:
315                 os << "[mathllap ";
316                 break;
317         case mathrlap:
318                 os << "[mathrlap ";
319                 break;
320         }
321         os << cell(0) << ']';
322 }
323
324
325 void InsetMathPhantom::infoize(odocstream & os) const
326 {
327         switch (kind_) {
328         case phantom:
329                 os << "Phantom";
330                 break;
331         case vphantom:
332                 os << "Vphantom";
333                 break;
334         case hphantom:
335                 os << "Hphantom";
336                 break;
337         case smash:
338                 os << "Smash";
339                 break;
340         case smasht:
341                 os << "Smashtop";
342                 break;
343         case smashb:
344                 os << "Smashbottom";
345                 break;
346         case mathllap:
347                 os << "Mathllap";
348                 break;
349         case mathclap:
350                 os << "Mathclap";
351                 break;
352         case mathrlap:
353                 os << "Mathrlap";
354                 break;
355         }
356 }
357
358
359 void InsetMathPhantom::validate(LaTeXFeatures & features) const
360 {
361         InsetMathNest::validate(features);
362         switch (kind_) {
363         case phantom:
364         case vphantom:
365         case hphantom:
366         case smash:
367                 break;
368         case smasht:
369         case smashb:
370                 features.require("amsmath");
371                 break;
372         case mathclap:
373         case mathllap:
374         case mathrlap:
375                 features.require("mathtools");
376                 break;
377         }
378 }
379
380
381 bool InsetMathPhantom::visibleContents() const
382 {
383         return kind_ == phantom || kind_ == vphantom || kind_ == hphantom;
384 }
385
386
387 } // namespace lyx