android: Update app-specific/MIME type icons
[LibreOffice.git] / starmath / inc / visitors.hxx
blobeaf329034c7d9fac4ecb71f5ab738762a04e3f2f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
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
22 #pragma once
24 #include <sal/config.h>
25 #include <sal/log.hxx>
27 #include "node.hxx"
28 #include "caret.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.
34 class SmVisitor
36 public:
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;
65 protected:
66 ~SmVisitor() {}
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
75 * implementation.
77 class SmDefaultingVisitor : public SmVisitor
79 public:
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;
107 protected:
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
118 public:
119 SmCaretLinesVisitor(OutputDevice& rDevice, SmCaretPos position, Point offset);
120 virtual ~SmCaretLinesVisitor() = default;
121 void Visit(SmTextNode* pNode) override;
122 using SmDefaultingVisitor::Visit;
124 protected:
125 void DoIt();
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;
134 private:
135 OutputDevice& mrDev;
136 SmCaretPos maPos;
137 /** Offset to draw from */
138 Point maOffset;
141 // SmCaretRectanglesVisitor: obtains the set of rectangles to sent to lok
143 class SmCaretRectanglesVisitor final : public SmCaretLinesVisitor
145 public:
146 SmCaretRectanglesVisitor(OutputDevice& rDevice, SmCaretPos position);
147 const tools::Rectangle& getCaret() const { return maCaret; }
149 protected:
150 virtual void ProcessCaretLine(Point from, Point to) override;
151 virtual void ProcessUnderline(Point from, Point to) override;
153 private:
154 tools::Rectangle maCaret;
157 // SmCaretDrawingVisitor
159 /** Visitor for drawing a caret position */
160 class SmCaretDrawingVisitor final : public SmCaretLinesVisitor
162 public:
163 /** Given position and device this constructor will draw the caret */
164 SmCaretDrawingVisitor( OutputDevice& rDevice, SmCaretPos position, Point offset, bool caretVisible );
166 protected:
167 virtual void ProcessCaretLine(Point from, Point to) override;
168 virtual void ProcessUnderline(Point from, Point to) override;
170 private:
171 bool mbCaretVisible;
174 // SmCaretPos2LineVisitor
176 /** Visitor getting a line from a caret position */
177 class SmCaretPos2LineVisitor final : public SmDefaultingVisitor
179 public:
180 /** Given position and device this constructor will compute a line for the caret */
181 SmCaretPos2LineVisitor( OutputDevice *pDevice, SmCaretPos position )
182 : mpDev( pDevice )
183 , maPos( 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 {
193 return maLine;
195 private:
196 SmCaretLine maLine;
197 VclPtr<OutputDevice> mpDev;
198 SmCaretPos maPos;
200 /** Default method for computing lines for pNodes */
201 void DefaultVisit( SmNode* pNode ) override;
204 // SmDrawingVisitor
206 /** Visitor for drawing SmNodes to OutputDevice */
207 class SmDrawingVisitor final : public SmVisitor
209 public:
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 )
217 : mrDev( rDevice )
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;
250 private:
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 */
261 OutputDevice& mrDev;
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.
267 Point maPosition;
270 // SmSetSelectionVisitor
272 /** Set Selection Visitor
273 * Sets the IsSelected( ) property on all SmNodes of the tree
275 class SmSetSelectionVisitor final : public SmDefaultingVisitor
277 public:
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 );
290 private:
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
295 * it.
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 */
302 SmCaretPos maEndPos;
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
306 * selected.
308 bool mbSelecting;
312 // SmCaretPosGraphBuildingVisitor
315 /** A visitor for building a SmCaretPosGraph
317 * Visit invariant:
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
324 * of calls.
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
336 public:
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();
371 private:
372 SmCaretPosGraphEntry* mpRightMost;
373 std::unique_ptr<SmCaretPosGraph> mpGraph;
376 // SmCloningVisitor
378 /** Visitor for cloning a pNode
380 * This visitor creates deep clones.
382 class SmCloningVisitor final : public SmVisitor
384 public:
385 SmCloningVisitor()
386 : mpResult(nullptr)
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;
416 /** Clone a pNode */
417 SmNode* Clone( SmNode* pNode );
418 private:
419 SmNode* mpResult;
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
431 public:
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; }
439 private:
440 /** Reference to drawing device */
441 OutputDevice& mrDev;
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
456 public:
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
466 public:
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;
497 private:
500 * Extract text from a pNode that constitutes a line.
501 * @param pNode
502 * @return
504 void LineToText( SmNode* pNode ) {
505 Separate( );
506 if( pNode ) pNode->Accept( this );
507 Separate( );
511 * Appends rText to the OUStringBuffer ( maCmdText ).
512 * @param rText
513 * @return
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 ' '.
522 * @return
524 void Separate( ){
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: */