Warning, /office/calligra/plugins/formulashape/ARCHITECTURE is written in an unsupported language. File is not indexed.
0001 This text provides a very short introduction to the architecture of 0002 the formula shape. At this time it's work in progress. 0003 0004 0005 Part I: Components 0006 0007 Part I describes the organization of the code and what can be found 0008 where. 0009 0010 0011 Subdirectories 0012 ============== 0013 0014 elements/ classes for XML elements in MathML 0015 fonts/ some fonts with mathematical characters 0016 pics/ pictures for the icons 0017 scripts/ a python script that generates the Dictionary class 0018 templates/ MathML templates (currently only one) - seems unused. 0019 tests/ test code (run it by 'make tests') 0020 0021 0022 Classes in the top directory 0023 ============================ 0024 0025 Shape classes 0026 ------------- 0027 KoFormulaShapePlugin All these classes are standard KoShape classes 0028 KoFormulaShapeFactory 0029 KoFormulaShape 0030 KoFormulaToolFactory 0031 KoFormulaTool 0032 FormulaToolWidget 0033 FormulaToolWidget.ui 0034 0035 FormulaDocument This class inherits KoDocument. A formula and 0036 a chart are special shapes because they are 0037 their own document types, defined in ODF. This 0038 also means that they can be saved in a 0039 subdirectory or inline inside the XML tree. 0040 0041 FormulaCommand Commands for text editing (See the command design pattern) 0042 FormulaCommandUpdate ? 0043 0044 Formula classes 0045 --------------- 0046 0047 The following classes are central in the loading, rendering and 0048 editing of formulas. 0049 0050 AttributeManager Manages attributes for elements (mostly 0051 styling for rendering) 0052 Dictionary Dictionary of MathML elements and entities 0053 ElementFactory A factory that generates an Element from a tagname 0054 FormulaCursor Points to a position in the MathML tree 0055 Also handles selections. 0056 FormulaData A QObject wrapper around a FormulaElement (see below) 0057 Allows communication with the formula tool 0058 FormulaEditor A class to perform programmatical manipulations 0059 of a formula. The tool goes through this class 0060 when editing. 0061 FormulaRenderer Renders a formula in two steps: 0062 1. Calls layout() on each element 0063 2. Calls paint() on each element. 0064 Also helps when something is updated through 0065 the FormulaEditor. 0066 0067 0068 Classes in elements/ 0069 -------------------- 0070 0071 These classes store the actual data of the formula. Each class 0072 represents a type of element and has its own layout and rendering 0073 function. 0074 0075 The base class for them all is the BasicElement. This is the base 0076 class for all elements and defines the API for rendering and 0077 editing. 0078 0079 The classes forms the following inheritance tree: 0080 0081 BasicElement Element base class 0082 RowElement A container for other elements aligned in a row. 0083 ActionElement 0084 EncloseElement 0085 ErrorElement 0086 FencedElement 0087 FormulaElement 0088 PaddedElement 0089 PhantomElement 0090 SquareRootElement 0091 StyleElement 0092 TableDataElement 0093 AnnotationElement 0094 FixedElement A base class for MathML elements with 0095 a fixed number of children 0096 FractionElement 0097 MultiscriptElement 0098 RootElement 0099 SubSupElement 0100 UnderOverElement 0101 SpaceElement 0102 TableElement 0103 TableRowElement 0104 TokenElement A base class for MathML token 0105 elements. The inherited classes all 0106 hold some form of token (text or string). 0107 GlyphElement 0108 IdentifierElement 0109 NumberElement 0110 OperatorElement 0111 StringElement 0112 TextElement 0113 UnknownElement Used when an unknown MathML tag is parsed. 0114 0115 0116 Structurally, a formula tree in the formula shape always has a 0117 FormulaElement as the top node. This node has a size which is the 0118 union of all the child element's sizes. 0119 0120 0121 Part II: Functional description 0122 0123 Part II contains high-level descriptions on key processes such as 0124 rendering and editing. 0125 0126 0127 Rendering 0128 ========= 0129 0130 Rendering is done in the following steps (see more details below): 0131 0132 1. Call layout() on the top element, which in turn calls layout() 0133 recursively on all its children. This establishes the minimum size 0134 of the formula tree. 0135 2. Call stretch() on the top element, which in turn calls stretch() 0136 recursively on all its children. This establishes the maximum size 0137 of the formula tree. 0138 3. Given the layout created in step 1 and 2, call paint() on the top 0139 element, which calls paint() recursively on its children and 0140 then paints itself. 0141 0142 0143 Editing 0144 ======= 0145 0146 This chapter describes the editing process and how the data structures 0147 are manipulated. 0148 0149 Cursor position 0150 --------------- 0151 0152 Before we can describe the editing process, we have to define what a 0153 _position_ in a formula is. There are two ways a position can be 0154 interpreted: 0155 0156 The formula shape uses a tree of objects which all ultimately inherit 0157 the BasicElement class. All elements except those inheriting the 0158 TokenElement class can hold one or more children. All elements which 0159 have child elements are either using implicit row elements or actually 0160 inheriting the RowElement. A token element is one of identifier (tag: 0161 mi), number (tag: mn) or operator (tag: mo). 0162 0163 A position is an integer number that goes from 0 to n where n is the 0164 number of children (most elements) or number of characters (token 0165 elements). Position #0 is before the first child/character, #1 is 0166 after the first child/character, and #n is after the last child 0167 element / character. 0168 0169 The _cursor position_ is a combination of an object, the so-called 0170 "Current Element" and a numeric position inside that object. We will 0171 denote this [<object>,position] here. 0172 0173 Consider the formula 'sqrt(a+b)' which in MathML is expressed: 0174 <mroot> 0175 <mrow> 0176 <mi>a</mi> 0177 <mo>+</mo> 0178 <mi>b</mi> 0179 </mrow> 0180 </mroot> 0181 0182 The cursor can have the following positions (marked with '*' and 0183 '¤'). Possible positions inside a token element are shown as '¤' and 0184 possible positions inside an (inferred) row element are shown as '*'. 0185 0186 *sqrt(*¤a¤*¤+¤*¤b¤*)* 0187 0188 Since the formula is always embedded into an implicit FormulaElemnt, 0189 the representaiton of this tree inside the formula shape is (with the 0190 same positions as above marked): 0191 0192 <formula>* 0193 <mroot> 0194 <mrow>* 0195 <mi>¤a¤</mi>* 0196 <mo>¤+¤</mo>* 0197 <mi>¤b¤</mi>* 0198 </mrow> 0199 </mroot>* 0200 </formula> 0201 0202 So the cursor position for the first and last asterisk is [<formula>,0] and 0203 [<formula>,1] respectively. The cursor positions inside the root are 0204 [<mrow>,0], ..., [<mrow>,3]. The <mrow> element is implicit inside 0205 the <mroot> element and not visible from the outside. 0206 0207 0208 Selection 0209 --------- 0210 0211 The class that keeps track of a cursor position is the FormulaCursor. 0212 The same class also keeps track of the current selection. The 0213 selection is defined as the objects between two different cursor 0214 positions inside the same object. One end of the selection is the 0215 current cursor position. The other end is the so called _mark_, which 0216 is represented by an integer position in the same object as the 0217 cursor. This means that the selection can only span subobjects inside 0218 the same parent. 0219 0220 0221 Editing 0222 ------- 0223 0224 The root object of the formula tree inside the formula shape is a 0225 FormulaElement. This FormulaElement is embedded into a FormulaData 0226 object which is a QObject. The purpose of the FormulaData object is to 0227 connect the formula tree with the outside world in the form of the 0228 shape and the formula tool. 0229 0230 The formula shape inherits the standard KoShape base class and the 0231 formula tool inherits KoToolBase. This means that all events (mouse, 0232 keyboard, etc) are channeled into the FormulaTool which interprets the 0233 events and uses a FormulaEditor object to perform the actual 0234 changes. The formula tool also opens an option widget in the 0235 docker. This widget is created by the FormulaToolWidget class and 0236 communicates with the formula tool using signals and slots. 0237 0238 The rest to be written.