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