1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 /** Visitors are an easy way to automating operations with nodes.
12 * The available visitors are:
13 * SmVisitor base class
14 * SmDefaultingVisitor default visitor
15 * SmDrawingVisitor draws formula
16 * SmCaretPosGraphBuildingVisitor position of the node inside starmath code
17 * SmCloningVisitor duplicate nodes
18 * SmNodeToTextVisitor create code from nodes
24 #include <sal/config.h>
25 #include <sal/log.hxx>
30 /** Base class for visitors that visits a tree of SmNodes
31 * @remarks all methods have been left abstract to ensure that implementers
32 * don't forget to implement one.
37 virtual void Visit( SmTableNode
* pNode
) = 0;
38 virtual void Visit( SmBraceNode
* pNode
) = 0;
39 virtual void Visit( SmBracebodyNode
* pNode
) = 0;
40 virtual void Visit( SmOperNode
* pNode
) = 0;
41 virtual void Visit( SmAlignNode
* pNode
) = 0;
42 virtual void Visit( SmAttributeNode
* pNode
) = 0;
43 virtual void Visit( SmFontNode
* pNode
) = 0;
44 virtual void Visit( SmUnHorNode
* pNode
) = 0;
45 virtual void Visit( SmBinHorNode
* pNode
) = 0;
46 virtual void Visit( SmBinVerNode
* pNode
) = 0;
47 virtual void Visit( SmBinDiagonalNode
* pNode
) = 0;
48 virtual void Visit( SmSubSupNode
* pNode
) = 0;
49 virtual void Visit( SmMatrixNode
* pNode
) = 0;
50 virtual void Visit( SmPlaceNode
* pNode
) = 0;
51 virtual void Visit( SmTextNode
* pNode
) = 0;
52 virtual void Visit( SmSpecialNode
* pNode
) = 0;
53 virtual void Visit( SmGlyphSpecialNode
* pNode
) = 0;
54 virtual void Visit( SmMathSymbolNode
* pNode
) = 0;
55 virtual void Visit( SmBlankNode
* pNode
) = 0;
56 virtual void Visit( SmErrorNode
* pNode
) = 0;
57 virtual void Visit( SmLineNode
* pNode
) = 0;
58 virtual void Visit( SmExpressionNode
* pNode
) = 0;
59 virtual void Visit( SmPolyLineNode
* pNode
) = 0;
60 virtual void Visit( SmRootNode
* pNode
) = 0;
61 virtual void Visit( SmRootSymbolNode
* pNode
) = 0;
62 virtual void Visit( SmRectangleNode
* pNode
) = 0;
63 virtual void Visit( SmVerticalBraceNode
* pNode
) = 0;
69 // SmDefaultingVisitor
72 /** Visitor that uses DefaultVisit for handling visits by default
74 * This abstract baseclass is useful for visitors where many methods share the same
77 class SmDefaultingVisitor
: public SmVisitor
80 void Visit( SmTableNode
* pNode
) override
;
81 void Visit( SmBraceNode
* pNode
) override
;
82 void Visit( SmBracebodyNode
* pNode
) override
;
83 void Visit( SmOperNode
* pNode
) override
;
84 void Visit( SmAlignNode
* pNode
) override
;
85 void Visit( SmAttributeNode
* pNode
) override
;
86 void Visit( SmFontNode
* pNode
) override
;
87 void Visit( SmUnHorNode
* pNode
) override
;
88 void Visit( SmBinHorNode
* pNode
) override
;
89 void Visit( SmBinVerNode
* pNode
) override
;
90 void Visit( SmBinDiagonalNode
* pNode
) override
;
91 void Visit( SmSubSupNode
* pNode
) override
;
92 void Visit( SmMatrixNode
* pNode
) override
;
93 void Visit( SmPlaceNode
* pNode
) override
;
94 void Visit( SmTextNode
* pNode
) override
;
95 void Visit( SmSpecialNode
* pNode
) override
;
96 void Visit( SmGlyphSpecialNode
* pNode
) override
;
97 void Visit( SmMathSymbolNode
* pNode
) override
;
98 void Visit( SmBlankNode
* pNode
) override
;
99 void Visit( SmErrorNode
* pNode
) override
;
100 void Visit( SmLineNode
* pNode
) override
;
101 void Visit( SmExpressionNode
* pNode
) override
;
102 void Visit( SmPolyLineNode
* pNode
) override
;
103 void Visit( SmRootNode
* pNode
) override
;
104 void Visit( SmRootSymbolNode
* pNode
) override
;
105 void Visit( SmRectangleNode
* pNode
) override
;
106 void Visit( SmVerticalBraceNode
* pNode
) override
;
108 ~SmDefaultingVisitor() {}
110 /** Method invoked by Visit methods by default */
111 virtual void DefaultVisit( SmNode
* pNode
) = 0;
114 // SmCaretLinesVisitor: ancestor of caret rectangle enumeration and drawing visitors
116 class SmCaretLinesVisitor
: public SmDefaultingVisitor
119 SmCaretLinesVisitor(OutputDevice
& rDevice
, SmCaretPos position
, Point offset
);
120 virtual ~SmCaretLinesVisitor() = default;
121 void Visit(SmTextNode
* pNode
) override
;
122 using SmDefaultingVisitor::Visit
;
127 OutputDevice
& getDev() { return mrDev
; }
128 virtual void ProcessCaretLine(Point from
, Point to
) = 0;
129 virtual void ProcessUnderline(Point from
, Point to
) = 0;
131 /** Default method for drawing pNodes */
132 void DefaultVisit(SmNode
* pNode
) override
;
137 /** Offset to draw from */
141 // SmCaretRectanglesVisitor: obtains the set of rectangles to sent to lok
143 class SmCaretRectanglesVisitor final
: public SmCaretLinesVisitor
146 SmCaretRectanglesVisitor(OutputDevice
& rDevice
, SmCaretPos position
);
147 const tools::Rectangle
& getCaret() const { return maCaret
; }
150 virtual void ProcessCaretLine(Point from
, Point to
) override
;
151 virtual void ProcessUnderline(Point from
, Point to
) override
;
154 tools::Rectangle maCaret
;
157 // SmCaretDrawingVisitor
159 /** Visitor for drawing a caret position */
160 class SmCaretDrawingVisitor final
: public SmCaretLinesVisitor
163 /** Given position and device this constructor will draw the caret */
164 SmCaretDrawingVisitor( OutputDevice
& rDevice
, SmCaretPos position
, Point offset
, bool caretVisible
);
167 virtual void ProcessCaretLine(Point from
, Point to
) override
;
168 virtual void ProcessUnderline(Point from
, Point to
) override
;
174 // SmCaretPos2LineVisitor
176 /** Visitor getting a line from a caret position */
177 class SmCaretPos2LineVisitor final
: public SmDefaultingVisitor
180 /** Given position and device this constructor will compute a line for the caret */
181 SmCaretPos2LineVisitor( OutputDevice
*pDevice
, SmCaretPos position
)
185 SAL_WARN_IF( !position
.IsValid(), "starmath", "Cannot draw invalid position!" );
187 maPos
.pSelectedNode
->Accept( this );
189 virtual ~SmCaretPos2LineVisitor() {}
190 void Visit( SmTextNode
* pNode
) override
;
191 using SmDefaultingVisitor::Visit
;
192 const SmCaretLine
& GetResult( ) const {
197 VclPtr
<OutputDevice
> mpDev
;
200 /** Default method for computing lines for pNodes */
201 void DefaultVisit( SmNode
* pNode
) override
;
206 /** Visitor for drawing SmNodes to OutputDevice */
207 class SmDrawingVisitor final
: public SmVisitor
210 /** Create an instance of SmDrawingVisitor, and use it to draw a formula
211 * @param rDevice Device to draw on
212 * @param position Offset on device to draw the formula
213 * @param pTree Formula tree to draw
214 * @remarks This constructor will do the drawing, no need to anything more.
216 SmDrawingVisitor( OutputDevice
&rDevice
, Point position
, SmNode
* pTree
)
218 , maPosition( position
)
220 pTree
->Accept( this );
222 virtual ~SmDrawingVisitor() {}
223 void Visit( SmTableNode
* pNode
) override
;
224 void Visit( SmBraceNode
* pNode
) override
;
225 void Visit( SmBracebodyNode
* pNode
) override
;
226 void Visit( SmOperNode
* pNode
) override
;
227 void Visit( SmAlignNode
* pNode
) override
;
228 void Visit( SmAttributeNode
* pNode
) override
;
229 void Visit( SmFontNode
* pNode
) override
;
230 void Visit( SmUnHorNode
* pNode
) override
;
231 void Visit( SmBinHorNode
* pNode
) override
;
232 void Visit( SmBinVerNode
* pNode
) override
;
233 void Visit( SmBinDiagonalNode
* pNode
) override
;
234 void Visit( SmSubSupNode
* pNode
) override
;
235 void Visit( SmMatrixNode
* pNode
) override
;
236 void Visit( SmPlaceNode
* pNode
) override
;
237 void Visit( SmTextNode
* pNode
) override
;
238 void Visit( SmSpecialNode
* pNode
) override
;
239 void Visit( SmGlyphSpecialNode
* pNode
) override
;
240 void Visit( SmMathSymbolNode
* pNode
) override
;
241 void Visit( SmBlankNode
* pNode
) override
;
242 void Visit( SmErrorNode
* pNode
) override
;
243 void Visit( SmLineNode
* pNode
) override
;
244 void Visit( SmExpressionNode
* pNode
) override
;
245 void Visit( SmPolyLineNode
* pNode
) override
;
246 void Visit( SmRootNode
* pNode
) override
;
247 void Visit( SmRootSymbolNode
* pNode
) override
;
248 void Visit( SmRectangleNode
* pNode
) override
;
249 void Visit( SmVerticalBraceNode
* pNode
) override
;
251 /** Draw the children of a pNode
252 * This the default method, use by most pNodes
254 void DrawChildren( SmStructureNode
* pNode
);
256 /** Draw an SmTextNode or a subclass of this */
257 void DrawTextNode( SmTextNode
* pNode
);
258 /** Draw an SmSpecialNode or a subclass of this */
259 void DrawSpecialNode( SmSpecialNode
* pNode
);
260 /** OutputDevice to draw on */
262 /** Position to draw on the mrDev
263 * @remarks This variable is used to pass parameters in DrawChildren( ), this means
264 that after a call to DrawChildren( ) the contents of this method is undefined
265 so if needed cache it locally on the stack.
270 // SmSetSelectionVisitor
272 /** Set Selection Visitor
273 * Sets the IsSelected( ) property on all SmNodes of the tree
275 class SmSetSelectionVisitor final
: public SmDefaultingVisitor
278 SmSetSelectionVisitor( SmCaretPos startPos
, SmCaretPos endPos
, SmNode
* pNode
);
279 virtual ~SmSetSelectionVisitor() {}
280 void Visit( SmBinHorNode
* pNode
) override
;
281 void Visit( SmUnHorNode
* pNode
) override
;
282 void Visit( SmFontNode
* pNode
) override
;
283 void Visit( SmTextNode
* pNode
) override
;
284 void Visit( SmExpressionNode
* pNode
) override
;
285 void Visit( SmLineNode
* pNode
) override
;
286 void Visit( SmAlignNode
* pNode
) override
;
287 using SmDefaultingVisitor::Visit
;
288 /** Set IsSelected on all pNodes of pSubTree */
289 static void SetSelectedOnAll( SmNode
* pSubTree
, bool IsSelected
= true );
291 /** Visit a selectable pNode
292 * Can be used to handle pNodes that can be selected, that doesn't have more SmCaretPos'
293 * than 0 and 1 inside them. SmTextNode should be handle separately!
294 * Also note that pNodes such as SmBinVerNode cannot be selected, don't this method for
297 void DefaultVisit( SmNode
* pNode
) override
;
298 void VisitCompositionNode( SmStructureNode
* pNode
);
299 /** Caret position where the selection starts */
300 SmCaretPos maStartPos
;
301 /** Caret position where the selection ends */
303 /** The current state of this visitor
304 * This property changes when the visitor meets either maStartPos
305 * or maEndPos. This means that anything visited in between will be
312 // SmCaretPosGraphBuildingVisitor
315 /** A visitor for building a SmCaretPosGraph
318 * Each pNode, except SmExpressionNode, SmBinHorNode and a few others, constitutes an entry
319 * in a line. Consider the line entry "H", this entry creates one carat position, here
320 * denoted by | in "H|".
322 * Parameter variables:
323 * The following variables are used to transfer parameters into calls and results out
325 * pRightMost : SmCaretPosGraphEntry*
327 * Prior to a Visit call:
328 * pRightMost: A pointer to right most position in front of the current line entry.
330 * After a Visit call:
331 * pRightMost: A pointer to the right most position in the called line entry, if no there's
332 * no caret positions in called line entry don't change this variable.
334 class SmCaretPosGraphBuildingVisitor final
: public SmVisitor
337 /** Builds a caret position graph for pRootNode */
338 explicit SmCaretPosGraphBuildingVisitor( SmNode
* pRootNode
);
339 virtual ~SmCaretPosGraphBuildingVisitor();
340 void Visit( SmTableNode
* pNode
) override
;
341 void Visit( SmBraceNode
* pNode
) override
;
342 void Visit( SmBracebodyNode
* pNode
) override
;
343 void Visit( SmOperNode
* pNode
) override
;
344 void Visit( SmAlignNode
* pNode
) override
;
345 void Visit( SmAttributeNode
* pNode
) override
;
346 void Visit( SmFontNode
* pNode
) override
;
347 void Visit( SmUnHorNode
* pNode
) override
;
348 void Visit( SmBinHorNode
* pNode
) override
;
349 void Visit( SmBinVerNode
* pNode
) override
;
350 void Visit( SmBinDiagonalNode
* pNode
) override
;
351 void Visit( SmSubSupNode
* pNode
) override
;
352 void Visit( SmMatrixNode
* pNode
) override
;
353 void Visit( SmPlaceNode
* pNode
) override
;
354 void Visit( SmTextNode
* pNode
) override
;
355 void Visit( SmSpecialNode
* pNode
) override
;
356 void Visit( SmGlyphSpecialNode
* pNode
) override
;
357 void Visit( SmMathSymbolNode
* pNode
) override
;
358 void Visit( SmBlankNode
* pNode
) override
;
359 void Visit( SmErrorNode
* pNode
) override
;
360 void Visit( SmLineNode
* pNode
) override
;
361 void Visit( SmExpressionNode
* pNode
) override
;
362 void Visit( SmPolyLineNode
* pNode
) override
;
363 void Visit( SmRootNode
* pNode
) override
;
364 void Visit( SmRootSymbolNode
* pNode
) override
;
365 void Visit( SmRectangleNode
* pNode
) override
;
366 void Visit( SmVerticalBraceNode
* pNode
) override
;
367 SmCaretPosGraph
* takeGraph()
369 return mpGraph
.release();
372 SmCaretPosGraphEntry
* mpRightMost
;
373 std::unique_ptr
<SmCaretPosGraph
> mpGraph
;
378 /** Visitor for cloning a pNode
380 * This visitor creates deep clones.
382 class SmCloningVisitor final
: public SmVisitor
388 virtual ~SmCloningVisitor() {}
389 void Visit( SmTableNode
* pNode
) override
;
390 void Visit( SmBraceNode
* pNode
) override
;
391 void Visit( SmBracebodyNode
* pNode
) override
;
392 void Visit( SmOperNode
* pNode
) override
;
393 void Visit( SmAlignNode
* pNode
) override
;
394 void Visit( SmAttributeNode
* pNode
) override
;
395 void Visit( SmFontNode
* pNode
) override
;
396 void Visit( SmUnHorNode
* pNode
) override
;
397 void Visit( SmBinHorNode
* pNode
) override
;
398 void Visit( SmBinVerNode
* pNode
) override
;
399 void Visit( SmBinDiagonalNode
* pNode
) override
;
400 void Visit( SmSubSupNode
* pNode
) override
;
401 void Visit( SmMatrixNode
* pNode
) override
;
402 void Visit( SmPlaceNode
* pNode
) override
;
403 void Visit( SmTextNode
* pNode
) override
;
404 void Visit( SmSpecialNode
* pNode
) override
;
405 void Visit( SmGlyphSpecialNode
* pNode
) override
;
406 void Visit( SmMathSymbolNode
* pNode
) override
;
407 void Visit( SmBlankNode
* pNode
) override
;
408 void Visit( SmErrorNode
* pNode
) override
;
409 void Visit( SmLineNode
* pNode
) override
;
410 void Visit( SmExpressionNode
* pNode
) override
;
411 void Visit( SmPolyLineNode
* pNode
) override
;
412 void Visit( SmRootNode
* pNode
) override
;
413 void Visit( SmRootSymbolNode
* pNode
) override
;
414 void Visit( SmRectangleNode
* pNode
) override
;
415 void Visit( SmVerticalBraceNode
* pNode
) override
;
417 SmNode
* Clone( SmNode
* pNode
);
420 /** Clone children of pSource and give them to pTarget */
421 void CloneKids( SmStructureNode
* pSource
, SmStructureNode
* pTarget
);
422 /** Clone attributes on a pNode */
423 static void CloneNodeAttr( SmNode
const * pSource
, SmNode
* pTarget
);
427 // SmSelectionRectanglesVisitor: collect selection
429 class SmSelectionRectanglesVisitor
: public SmDefaultingVisitor
432 SmSelectionRectanglesVisitor(OutputDevice
& rDevice
, SmNode
* pTree
);
433 virtual ~SmSelectionRectanglesVisitor() = default;
434 void Visit( SmTextNode
* pNode
) override
;
435 using SmDefaultingVisitor::Visit
;
437 const tools::Rectangle
& GetSelection() { return maSelectionArea
; }
440 /** Reference to drawing device */
442 /** The current area that is selected */
443 tools::Rectangle maSelectionArea
;
444 /** Extend the area that must be selected */
445 void ExtendSelectionArea(const tools::Rectangle
& rArea
) { maSelectionArea
.Union(rArea
); }
446 /** Default visiting method */
447 void DefaultVisit( SmNode
* pNode
) override
;
448 /** Visit the children of a given pNode */
449 void VisitChildren( SmNode
* pNode
);
452 // SmSelectionDrawingVisitor
454 class SmSelectionDrawingVisitor final
: public SmSelectionRectanglesVisitor
457 /** Draws a selection on rDevice for the selection on pTree */
458 SmSelectionDrawingVisitor( OutputDevice
& rDevice
, SmNode
* pTree
, const Point
& rOffset
);
461 // SmNodeToTextVisitor
463 /** Extract command text from pNodes */
464 class SmNodeToTextVisitor final
: public SmVisitor
467 SmNodeToTextVisitor( SmNode
* pNode
, OUString
&rText
);
468 virtual ~SmNodeToTextVisitor() {}
470 void Visit( SmTableNode
* pNode
) override
;
471 void Visit( SmBraceNode
* pNode
) override
;
472 void Visit( SmBracebodyNode
* pNode
) override
;
473 void Visit( SmOperNode
* pNode
) override
;
474 void Visit( SmAlignNode
* pNode
) override
;
475 void Visit( SmAttributeNode
* pNode
) override
;
476 void Visit( SmFontNode
* pNode
) override
;
477 void Visit( SmUnHorNode
* pNode
) override
;
478 void Visit( SmBinHorNode
* pNode
) override
;
479 void Visit( SmBinVerNode
* pNode
) override
;
480 void Visit( SmBinDiagonalNode
* pNode
) override
;
481 void Visit( SmSubSupNode
* pNode
) override
;
482 void Visit( SmMatrixNode
* pNode
) override
;
483 void Visit( SmPlaceNode
* pNode
) override
;
484 void Visit( SmTextNode
* pNode
) override
;
485 void Visit( SmSpecialNode
* pNode
) override
;
486 void Visit( SmGlyphSpecialNode
* pNode
) override
;
487 void Visit( SmMathSymbolNode
* pNode
) override
;
488 void Visit( SmBlankNode
* pNode
) override
;
489 void Visit( SmErrorNode
* pNode
) override
;
490 void Visit( SmLineNode
* pNode
) override
;
491 void Visit( SmExpressionNode
* pNode
) override
;
492 void Visit( SmPolyLineNode
* pNode
) override
;
493 void Visit( SmRootNode
* pNode
) override
;
494 void Visit( SmRootSymbolNode
* pNode
) override
;
495 void Visit( SmRectangleNode
* pNode
) override
;
496 void Visit( SmVerticalBraceNode
* pNode
) override
;
500 * Extract text from a pNode that constitutes a line.
504 void LineToText( SmNode
* pNode
) {
506 if( pNode
) pNode
->Accept( this );
511 * Appends rText to the OUStringBuffer ( maCmdText ).
515 void Append( std::u16string_view rText
) {
516 maCmdText
.append( rText
);
520 * Append a blank for separation, if needed.
521 * It is needed if last char is not ' '.
525 if( !maCmdText
.isEmpty() && maCmdText
[ maCmdText
.getLength() - 1 ] != ' ' )
526 maCmdText
.append(' ');
529 /** Output text generated from the pNodes */
530 OUStringBuffer maCmdText
;
533 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */