]> git.lyx.org Git - features.git/blob - src/insets/InsetNewpage.cpp
Refactor OutputParams
[features.git] / src / insets / InsetNewpage.cpp
1 /**
2  * \file InsetNewpage.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author André Pönitz
7  * \author Jürgen Spitzmüller
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "InsetNewpage.h"
15
16 #include "Cursor.h"
17 #include "FuncRequest.h"
18 #include "FuncStatus.h"
19 #include "Lexer.h"
20 #include "MetricsInfo.h"
21 #include "xml.h"
22 #include "texstream.h"
23 #include "Text.h"
24 #include "TextMetrics.h"
25
26 #include "frontends/FontMetrics.h"
27 #include "frontends/Painter.h"
28
29 #include "support/debug.h"
30 #include "support/docstring.h"
31 #include "support/docstream.h"
32 #include "support/gettext.h"
33
34 using namespace std;
35
36
37 namespace lyx {
38
39         InsetNewpage::InsetNewpage() : Inset(nullptr)
40 {}
41
42
43 InsetNewpage::InsetNewpage(InsetNewpageParams const & params)
44         : Inset(nullptr), params_(params)
45 {}
46
47
48 void InsetNewpageParams::write(ostream & os) const
49 {
50         switch (kind) {
51         case InsetNewpageParams::NEWPAGE:
52                 os << "newpage";
53                 break;
54         case InsetNewpageParams::PAGEBREAK:
55                 os <<  "pagebreak";
56                 break;
57         case InsetNewpageParams::CLEARPAGE:
58                 os <<  "clearpage";
59                 break;
60         case InsetNewpageParams::CLEARDOUBLEPAGE:
61                 os <<  "cleardoublepage";
62                 break;
63         case InsetNewpageParams::NOPAGEBREAK:
64                 os <<  "nopagebreak";
65                 break;
66         }
67 }
68
69
70 void InsetNewpageParams::read(Lexer & lex)
71 {
72         lex.setContext("InsetNewpageParams::read");
73         string token;
74         lex >> token;
75
76         if (token == "newpage")
77                 kind = InsetNewpageParams::NEWPAGE;
78         else if (token == "pagebreak")
79                 kind = InsetNewpageParams::PAGEBREAK;
80         else if (token == "clearpage")
81                 kind = InsetNewpageParams::CLEARPAGE;
82         else if (token == "cleardoublepage")
83                 kind = InsetNewpageParams::CLEARDOUBLEPAGE;
84         else if (token == "nopagebreak")
85                 kind = InsetNewpageParams::NOPAGEBREAK;
86         else
87                 lex.printError("Unknown kind");
88 }
89
90
91 void InsetNewpage::write(ostream & os) const
92 {
93         os << "Newpage ";
94         params_.write(os);
95 }
96
97
98 void InsetNewpage::read(Lexer & lex)
99 {
100         params_.read(lex);
101         lex >> "\\end_inset";
102 }
103
104
105 void InsetNewpage::metrics(MetricsInfo & mi, Dimension & dim) const
106 {
107         if (params_.kind == InsetNewpageParams::NOPAGEBREAK) {
108                 frontend::FontMetrics const & fm = theFontMetrics(mi.base.font);
109                 dim.asc = fm.maxAscent();
110                 dim.des = fm.maxDescent();
111                 dim.wid = 3 * fm.width('n');
112                 return;
113         }
114
115         dim.asc = defaultRowHeight();
116         dim.des = defaultRowHeight();
117         dim.wid = mi.base.textwidth;
118 }
119
120
121 void InsetNewpage::draw(PainterInfo & pi, int x, int y) const
122 {
123         if (params_.kind == InsetNewpageParams::NOPAGEBREAK) {
124
125                 FontInfo font;
126                 font.setColor(ColorName());
127
128                 frontend::FontMetrics const & fm = theFontMetrics(pi.base.font);
129                 int const wid = 3 * fm.width('n');
130                 int const asc = fm.maxAscent();
131
132                 int xp[3];
133                 int yp[3];
134
135                 //left side arrow
136                 yp[0] = int(y - 0.875 * asc * 0.75);
137                 yp[1] = int(y - 0.500 * asc * 0.75);
138                 yp[2] = int(y - 0.125 * asc * 0.75);
139                 xp[0] = int(x + wid * 0.25);
140                 xp[1] = int(x + wid * 0.4); 
141                 xp[2] = int(x + wid * 0.25);
142                 pi.pain.lines(xp, yp, 3, ColorName());
143
144                 yp[0] = yp[1] = int(y - 0.500 * asc * 0.75);
145                 xp[0] = int(x + wid * 0.03);
146                 xp[1] = int(x + wid * 0.4); 
147                 pi.pain.lines(xp, yp, 2, ColorName());
148
149                 //right side arrow
150                 yp[0] = int(y - 0.875 * asc * 0.75);
151                 yp[1] = int(y - 0.500 * asc * 0.75);
152                 yp[2] = int(y - 0.125 * asc * 0.75);
153                 xp[0] = int(x + wid * 0.75);
154                 xp[1] = int(x + wid * 0.6); 
155                 xp[2] = int(x + wid * 0.75);
156                 pi.pain.lines(xp, yp, 3, ColorName());
157
158                 yp[0] = yp[1] = int(y - 0.500 * asc * 0.75);
159                 xp[0] = int(x + wid * 0.97);
160                 xp[1] = int(x + wid * 0.6); 
161                 pi.pain.lines(xp, yp, 2, ColorName());
162
163                 //mid-rule
164                 xp[0] = xp[1] = int(x + wid * 0.5);
165                 yp[0] = int(y - 0.875 * asc * 0.75);
166                 yp[1] = int(y - 0.125 * asc * 0.75);
167                 pi.pain.lines(xp, yp, 2, ColorName());
168                 return;
169         }
170
171         using frontend::Painter;
172
173         FontInfo font;
174         font.setColor(ColorName());
175         font.decSize();
176
177         Dimension const dim = dimension(*pi.base.bv);
178
179         int w = 0;
180         int a = 0;
181         int d = 0;
182         theFontMetrics(font).rectText(insetLabel(), w, a, d);
183
184         int const text_start = int(x + (dim.wid - w) / 2);
185         int const text_end = text_start + w;
186
187         pi.pain.rectText(text_start, y + d, insetLabel(), font,
188                 Color_none, Color_none);
189
190         pi.pain.line(x, y, text_start, y,
191                    ColorName(), Painter::line_onoffdash);
192         pi.pain.line(text_end, y, int(x + dim.wid), y,
193                    ColorName(), Painter::line_onoffdash);
194 }
195
196
197 void InsetNewpage::doDispatch(Cursor & cur, FuncRequest & cmd)
198 {
199         switch (cmd.action()) {
200
201         case LFUN_INSET_MODIFY: {
202                 InsetNewpageParams params;
203                 cur.recordUndo();
204                 string2params(to_utf8(cmd.argument()), params);
205                 params_.kind = params.kind;
206                 break;
207         }
208
209         default:
210                 Inset::doDispatch(cur, cmd);
211                 break;
212         }
213 }
214
215
216 bool InsetNewpage::getStatus(Cursor & cur, FuncRequest const & cmd,
217         FuncStatus & status) const
218 {
219         switch (cmd.action()) {
220         // we handle these
221         case LFUN_INSET_MODIFY:
222                 if (cmd.getArg(0) == "newpage") {
223                         InsetNewpageParams params;
224                         string2params(to_utf8(cmd.argument()), params);
225                         status.setOnOff(params_.kind == params.kind);
226                 }
227                 status.setEnabled(true);
228                 return true;
229         default:
230                 return Inset::getStatus(cur, cmd, status);
231         }
232 }
233
234
235 docstring InsetNewpage::insetLabel() const
236 {
237         switch (params_.kind) {
238                 case InsetNewpageParams::NEWPAGE:
239                         return _("New Page");
240                         break;
241                 case InsetNewpageParams::PAGEBREAK:
242                         return _("Page Break");
243                         break;
244                 case InsetNewpageParams::CLEARPAGE:
245                         return _("Clear Page");
246                         break;
247                 case InsetNewpageParams::CLEARDOUBLEPAGE:
248                         return _("Clear Double Page");
249                         break;
250                 case InsetNewpageParams::NOPAGEBREAK:
251                         return _("No Page Break");
252                         break;
253                 default:
254                         return _("New Page");
255                         break;
256         }
257 }
258
259
260 ColorCode InsetNewpage::ColorName() const
261 {
262         switch (params_.kind) {
263                 case InsetNewpageParams::PAGEBREAK:
264                 case InsetNewpageParams::NOPAGEBREAK:
265                         return Color_pagebreak;
266                         break;
267                 case InsetNewpageParams::NEWPAGE:
268                 case InsetNewpageParams::CLEARPAGE:
269                 case InsetNewpageParams::CLEARDOUBLEPAGE:
270                         return Color_newpage;
271                         break;
272         }
273         // not really useful, but to avoids gcc complaints
274         return Color_newpage;
275 }
276
277
278 void InsetNewpage::latex(otexstream & os, OutputParams const & runparams) const
279 {
280         if (runparams.inDeletedInset) {
281                 os << "\\mbox{}\\\\\\makebox[\\columnwidth]{\\dotfill\\ "
282                    << insetLabel() << "\\ \\dotfill}";
283         } else {
284                 switch (params_.kind) {
285                 case InsetNewpageParams::NEWPAGE:
286                         os << "\\newpage" << termcmd;
287                         break;
288                 case InsetNewpageParams::PAGEBREAK:
289                         if (runparams.moving_arg)
290                                 os << "\\protect";
291                         os << "\\pagebreak" << termcmd;
292                         break;
293                 case InsetNewpageParams::CLEARPAGE:
294                         os << "\\clearpage" << termcmd;
295                         break;
296                 case InsetNewpageParams::CLEARDOUBLEPAGE:
297                         os << "\\cleardoublepage" << termcmd;
298                         break;
299                 case InsetNewpageParams::NOPAGEBREAK:
300                         os << "\\nopagebreak" << termcmd;
301                         break;
302                 default:
303                         os << "\\newpage" << termcmd;
304                         break;
305                 }
306         }
307 }
308
309
310 int InsetNewpage::plaintext(odocstringstream & os,
311         OutputParams const &, size_t) const
312 {
313         if (params_.kind ==  InsetNewpageParams::NOPAGEBREAK)
314                 return 0;
315         os << '\n';
316         return PLAINTEXT_NEWLINE;
317 }
318
319
320 void InsetNewpage::docbook(XMLStream & os, OutputParams const &) const
321 {
322         if (params_.kind !=  InsetNewpageParams::NOPAGEBREAK)
323                 os << xml::CR();
324 }
325
326
327 docstring InsetNewpage::xhtml(XMLStream & xs, OutputParams const &) const
328 {
329         if (params_.kind !=  InsetNewpageParams::NOPAGEBREAK)
330                 xs << xml::CompTag("br");
331         return docstring();
332 }
333
334
335 string InsetNewpage::contextMenuName() const
336 {
337         return "context-newpage";
338 }
339
340
341 void InsetNewpage::string2params(string const & in, InsetNewpageParams & params)
342 {
343         params = InsetNewpageParams();
344         if (in.empty())
345                 return;
346
347         istringstream data(in);
348         Lexer lex;
349         lex.setStream(data);
350
351         string name;
352         lex >> name;
353         if (!lex || name != "newpage") {
354                 LYXERR0("Expected arg 2 to be \"wrap\" in " << in);
355                 return;
356         }
357
358         params.read(lex);
359 }
360
361
362 string InsetNewpage::params2string(InsetNewpageParams const & params)
363 {
364         ostringstream data;
365         data << "newpage" << ' ';
366         params.write(data);
367         return data.str();
368 }
369
370
371 } // namespace lyx