]> git.lyx.org Git - features.git/blob - src/insets/InsetPhantom.cpp
Rename XHTMLStream to XMLStream, move it to another file, and prepare for DocBook...
[features.git] / src / insets / InsetPhantom.cpp
1 /**
2  * \file InsetPhantom.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Uwe Stöhr
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "InsetPhantom.h"
14
15 #include "Buffer.h"
16 #include "BufferParams.h"
17 #include "BufferView.h"
18 #include "BufferParams.h"
19 #include "Cursor.h"
20 #include "Dimension.h"
21 #include "DispatchResult.h"
22 #include "Exporter.h"
23 #include "FuncRequest.h"
24 #include "FuncStatus.h"
25 #include "InsetIterator.h"
26 #include "LaTeXFeatures.h"
27 #include "Lexer.h"
28 #include "MetricsInfo.h"
29 #include "OutputParams.h"
30 #include "texstream.h"
31 #include "TextClass.h"
32
33 #include "support/docstream.h"
34 #include "support/gettext.h"
35 #include "support/lstrings.h"
36 #include "support/Translator.h"
37
38 #include "frontends/Application.h"
39 #include "frontends/FontMetrics.h"
40 #include "frontends/Painter.h"
41
42 #include <algorithm>
43 #include <sstream>
44
45 using namespace std;
46
47 namespace lyx {
48
49 namespace {
50
51 typedef Translator<string, InsetPhantomParams::Type> PhantomTranslator;
52 typedef Translator<docstring, InsetPhantomParams::Type> PhantomTranslatorLoc;
53
54 PhantomTranslator const init_phantomtranslator()
55 {
56         PhantomTranslator translator("Phantom", InsetPhantomParams::Phantom);
57         translator.addPair("HPhantom", InsetPhantomParams::HPhantom);
58         translator.addPair("VPhantom", InsetPhantomParams::VPhantom);
59         return translator;
60 }
61
62
63 PhantomTranslatorLoc const init_phantomtranslator_loc()
64 {
65         PhantomTranslatorLoc translator(_("Phantom"), InsetPhantomParams::Phantom);
66         translator.addPair(_("HPhantom"), InsetPhantomParams::HPhantom);
67         translator.addPair(_("VPhantom"), InsetPhantomParams::VPhantom);
68         return translator;
69 }
70
71
72 PhantomTranslator const & phantomtranslator()
73 {
74         static PhantomTranslator const translator =
75             init_phantomtranslator();
76         return translator;
77 }
78
79
80 PhantomTranslatorLoc const & phantomtranslator_loc()
81 {
82         static PhantomTranslatorLoc const translator =
83             init_phantomtranslator_loc();
84         return translator;
85 }
86
87 } // namespace
88
89
90 InsetPhantomParams::InsetPhantomParams()
91         : type(Phantom)
92 {}
93
94
95 void InsetPhantomParams::write(ostream & os) const
96 {
97         string const label = phantomtranslator().find(type);
98         os << "Phantom " << label << "\n";
99 }
100
101
102 void InsetPhantomParams::read(Lexer & lex)
103 {
104         string label;
105         lex >> label;
106         if (lex)
107                 type = phantomtranslator().find(label);
108 }
109
110
111 /////////////////////////////////////////////////////////////////////
112 //
113 // InsetPhantom
114 //
115 /////////////////////////////////////////////////////////////////////
116
117 InsetPhantom::InsetPhantom(Buffer * buf, string const & label)
118         : InsetCollapsible(buf)
119 {
120         setDrawFrame(false);
121         params_.type = phantomtranslator().find(label);
122 }
123
124
125 InsetPhantom::~InsetPhantom()
126 {
127         hideDialogs("phantom", this);
128 }
129
130
131 docstring InsetPhantom::layoutName() const
132 {
133         return from_ascii("Phantom:" + phantomtranslator().find(params_.type));
134 }
135
136
137 void InsetPhantom::draw(PainterInfo & pi, int x, int y) const
138 {
139         // draw the text
140         InsetCollapsible::draw(pi, x, y);
141
142         // draw the inset marker
143         drawMarkers(pi, x, y);
144
145         // draw the arrow(s)
146         static int const arrow_size = 4;
147         ColorCode const origcol = pi.base.font.color();
148         pi.base.font.setColor(Color_special);
149         pi.base.font.setColor(origcol);
150         Dimension const dim = dimension(*pi.base.bv);
151
152         if (params_.type == InsetPhantomParams::Phantom ||
153                 params_.type == InsetPhantomParams::VPhantom) {
154                 // y1---------
155                 //           / \.
156                 // y2-----  / | \.
157                 //            |
158                 //            |
159                 // y3-----  \ | /
160                 //           \ /
161                 // y4---------
162                 //          | | |
163                 //         /  |  \.
164                 //        x1  x2 x3
165
166                 int const x2 = x + dim.wid / 2;
167                 int const x1 = x2 - arrow_size;
168                 int const x3 = x2 + arrow_size;
169
170                 int const y1 = y - dim.asc;
171                 int const y2 = y1 + arrow_size;
172                 int const y4 = y + dim.des;
173                 int const y3 = y4 - arrow_size;
174
175                 // top arrow
176                 pi.pain.line(x2, y1, x1, y2, Color_added_space);
177                 pi.pain.line(x2, y1, x3, y2, Color_added_space);
178
179                 // bottom arrow
180                 pi.pain.line(x2, y4, x1, y3, Color_added_space);
181                 pi.pain.line(x2, y4, x3, y3, Color_added_space);
182
183                 // joining line
184                 pi.pain.line(x2, y1, x2, y4, Color_added_space);
185         }
186
187         if (params_.type == InsetPhantomParams::Phantom ||
188                 params_.type == InsetPhantomParams::HPhantom) {
189                 // y1----   /          \.
190                 //        /              \.
191                 // y2--- <---------------->
192                 //        \              /
193                 // y3----   \          /
194                 //       |   |        |   |
195                 //      x1  x2       x3  x4
196
197                 x += leftOffset(pi.base.bv);
198                 int const x1 = x;
199                 int const x2 = x + arrow_size;
200                 int const x4 = x + dim.wid - leftOffset(pi.base.bv) - rightOffset(pi.base.bv);
201                 int const x3 = x4 - arrow_size;
202
203                 int const y2 = y + (dim.des - dim.asc) / 2;
204                 int const y1 = y2 - arrow_size;
205                 int const y3 = y2 + arrow_size;
206
207                 // left arrow
208                 pi.pain.line(x1, y2, x2, y3, Color_added_space);
209                 pi.pain.line(x1, y2, x2, y1, Color_added_space);
210
211                 // right arrow
212                 pi.pain.line(x4, y2, x3, y3, Color_added_space);
213                 pi.pain.line(x4, y2, x3, y1, Color_added_space);
214
215                 // joining line
216                 pi.pain.line(x1, y2, x4, y2, Color_added_space);
217         }
218 }
219
220
221 void InsetPhantom::write(ostream & os) const
222 {
223         params_.write(os);
224         InsetCollapsible::write(os);
225 }
226
227
228 void InsetPhantom::read(Lexer & lex)
229 {
230         params_.read(lex);
231         InsetCollapsible::read(lex);
232 }
233
234
235 void InsetPhantom::setButtonLabel()
236 {
237         docstring const label = phantomtranslator_loc().find(params_.type);
238         setLabel(label);
239 }
240
241
242 bool InsetPhantom::showInsetDialog(BufferView * bv) const
243 {
244         bv->showDialog("phantom", params2string(params()),
245                 const_cast<InsetPhantom *>(this));
246         return true;
247 }
248
249
250 void InsetPhantom::doDispatch(Cursor & cur, FuncRequest & cmd)
251 {
252         switch (cmd.action()) {
253
254         case LFUN_INSET_MODIFY:
255                 cur.recordUndoInset(this);
256                 string2params(to_utf8(cmd.argument()), params_);
257                 setButtonLabel();
258                 cur.forceBufferUpdate();
259                 break;
260
261         case LFUN_INSET_DIALOG_UPDATE:
262                 cur.bv().updateDialog("phantom", params2string(params()));
263                 break;
264
265         default:
266                 InsetCollapsible::doDispatch(cur, cmd);
267                 break;
268         }
269 }
270
271
272 bool InsetPhantom::getStatus(Cursor & cur, FuncRequest const & cmd,
273                 FuncStatus & flag) const
274 {
275         switch (cmd.action()) {
276
277         case LFUN_INSET_MODIFY:
278                 if (cmd.getArg(0) == "phantom") {
279                         InsetPhantomParams params;
280                         string2params(to_utf8(cmd.argument()), params);
281                         flag.setOnOff(params_.type == params.type);
282                 }
283                 flag.setEnabled(true);
284                 return true;
285
286         case LFUN_INSET_DIALOG_UPDATE:
287                 flag.setEnabled(true);
288                 return true;
289
290         default:
291                 return InsetCollapsible::getStatus(cur, cmd, flag);
292         }
293 }
294
295
296 docstring InsetPhantom::toolTip(BufferView const &, int, int) const
297 {
298         docstring const res = phantomtranslator_loc().find(params_.type);
299         return toolTipText(res + from_ascii(": "));
300 }
301
302
303 void InsetPhantom::latex(otexstream & os, OutputParams const & runparams) const
304 {
305         if (runparams.moving_arg)
306                 os << "\\protect";
307
308         switch (params_.type) {
309         case InsetPhantomParams::Phantom:
310                 os << "\\phantom{";
311                 break;
312         case InsetPhantomParams::HPhantom:
313                 os << "\\hphantom{";
314                 break;
315         case InsetPhantomParams::VPhantom:
316                 os << "\\vphantom{";
317                 break;
318         default:
319                 os << "\\phantom{";
320                 break;
321         }
322         InsetCollapsible::latex(os, runparams);
323         os << "}";
324 }
325
326
327 int InsetPhantom::plaintext(odocstringstream & os,
328                             OutputParams const & runparams, size_t max_length) const
329 {
330         switch (params_.type) {
331         case InsetPhantomParams::Phantom:
332                 os << '[' << buffer().B_("phantom") << ":";
333                 break;
334         case InsetPhantomParams::HPhantom:
335                 os << '[' << buffer().B_("hphantom") << ":";
336                 break;
337         case InsetPhantomParams::VPhantom:
338                 os << '[' << buffer().B_("vphantom") << ":";
339                 break;
340         default:
341                 os << '[' << buffer().B_("phantom") << ":";
342                 break;
343         }
344         InsetCollapsible::plaintext(os, runparams, max_length);
345         os << "]";
346
347         return PLAINTEXT_NEWLINE;
348 }
349
350
351 int InsetPhantom::docbook(odocstream & os, OutputParams const & runparams) const
352 {
353         docstring cmdname;
354         switch (params_.type) {
355         case InsetPhantomParams::Phantom:
356         case InsetPhantomParams::HPhantom:
357         case InsetPhantomParams::VPhantom:
358         default:
359                 cmdname = from_ascii("phantom");
360                 break;
361         }
362         os << "<" + cmdname + ">";
363         int const i = InsetCollapsible::docbook(os, runparams);
364         os << "</" + cmdname + ">";
365
366         return i;
367 }
368
369
370 docstring InsetPhantom::xhtml(XMLStream &, OutputParams const &) const
371 {
372         return docstring();
373 }
374
375 string InsetPhantom::contextMenuName() const
376 {
377         return "context-phantom";
378 }
379
380
381 string InsetPhantom::params2string(InsetPhantomParams const & params)
382 {
383         ostringstream data;
384         data << "phantom" << ' ';
385         params.write(data);
386         return data.str();
387 }
388
389
390 void InsetPhantom::string2params(string const & in, InsetPhantomParams & params)
391 {
392         params = InsetPhantomParams();
393
394         if (in.empty())
395                 return;
396
397         istringstream data(in);
398         Lexer lex;
399         lex.setStream(data);
400         lex.setContext("InsetPhantom::string2params");
401         lex >> "phantom" >> "Phantom";
402
403         params.read(lex);
404 }
405
406
407 } // namespace lyx