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