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