/src/libreoffice/include/svtools/ruler.hxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
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 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
11 | | * Licensed to the Apache Software Foundation (ASF) under one or more |
12 | | * contributor license agreements. See the NOTICE file distributed |
13 | | * with this work for additional information regarding copyright |
14 | | * ownership. The ASF licenses this file to you under the Apache |
15 | | * License, Version 2.0 (the "License"); you may not use this file |
16 | | * except in compliance with the License. You may obtain a copy of |
17 | | * the License at http://www.apache.org/licenses/LICENSE-2.0 . |
18 | | */ |
19 | | |
20 | | #pragma once |
21 | | |
22 | | #include <memory> |
23 | | #include <map> |
24 | | #include <vector> |
25 | | #include <svtools/svtdllapi.h> |
26 | | #include <tools/link.hxx> |
27 | | #include <tools/fract.hxx> |
28 | | #include <vcl/window.hxx> |
29 | | #include <vcl/glyphitem.hxx> |
30 | | |
31 | | class MouseEvent; |
32 | | enum class FieldUnit : sal_uInt16; |
33 | | |
34 | | /************************************************************************* |
35 | | |
36 | | Description |
37 | | ============ |
38 | | |
39 | | class Ruler |
40 | | |
41 | | This class is used for displaying a ruler, but it can also be used |
42 | | for setting or moving tabs and margins. |
43 | | |
44 | | -------------------------------------------------------------------------- |
45 | | |
46 | | WinBits |
47 | | |
48 | | WB_HORZ ruler is displayed horizontally |
49 | | WB_VERT ruler is displayed vertically |
50 | | WB_3DLOOK 3D look |
51 | | WB_BORDER border at the bottom/right margin |
52 | | WB_EXTRAFIELD Field in the upper left corner for |
53 | | displaying and selecting tabs, origin of coordinates, ... |
54 | | WB_RIGHT_ALIGNED Marks the vertical ruler as right aligned |
55 | | |
56 | | -------------------------------------------------------------------------- |
57 | | |
58 | | All ruler parameters are set in pixel units. This way double conversions |
59 | | and rounding errors are avoided and the ruler displays the margins |
60 | | at their actual position in the document. Because of this, the application can, |
61 | | for example in tables, do its own roundings and the positions on the ruler will |
62 | | still match those in the document. However, for the ruler to know how the |
63 | | document is displayed on the screen, some additional values have to be configured |
64 | | |
65 | | SetWinPos() sets the offset of the ruler's edit window. In doing so, |
66 | | the width of the window can also be configured. If there is a 0 among the |
67 | | values passed to the function, the position/width is automatically set to |
68 | | the width of the ruler. |
69 | | |
70 | | SetPagePos() sets the offset of the page relative to the edit window and the |
71 | | width of the page. If there is a 0 among the values passed to the function, |
72 | | the position/width is automatically set as if the page filled the whole edit window. |
73 | | |
74 | | SetBorderPos() sets the offset of the border. The position is relative to |
75 | | the upper/left margin of the window. This is needed when there are a horizontal |
76 | | and a vertical ruler visible at the same time. Example: |
77 | | aHRuler.SetBorderPos( aVRuler.GetSizePixel().Width()-1 ); |
78 | | |
79 | | SetNullOffset() sets the origin relative to the page. |
80 | | |
81 | | All the other values (margins, indentation, tabs, ...) refer to the origin, |
82 | | which is set with SetNullOffset(). |
83 | | |
84 | | The values are computed as described below: |
85 | | |
86 | | - WinPos (if both windows have the same parent) |
87 | | |
88 | | Point aHRulerPos = aHRuler.GetPosPixel(); |
89 | | Point aEditWinPos = aEditWin.GetPosPixel(); |
90 | | aHRuler.SetWinPos( aEditWinPos().X() - aHRulerPos.X() ); |
91 | | |
92 | | - PagePos |
93 | | |
94 | | Point aPagePos = aEditWin.LogicToPixel( aEditWin.GetPagePos() ); |
95 | | aHRuler.SetPagePos( aPagePos().X() ); |
96 | | |
97 | | - All other values |
98 | | |
99 | | Add the logical values, recompute as position and subtract the |
100 | | previously saved pixel positions (of PagePos and Null Offset). |
101 | | |
102 | | -------------------------------------------------------------------------- |
103 | | |
104 | | SetUnit() and SetZoom() configure which unit is used to display |
105 | | the values on the ruler. The following units are accepted: |
106 | | |
107 | | FieldUnit::MM |
108 | | FieldUnit::CM (Default) |
109 | | FieldUnit::M |
110 | | FieldUnit::KM |
111 | | FieldUnit::INCH |
112 | | FieldUnit::FOOT |
113 | | FieldUnit::MILE |
114 | | FieldUnit::POINT |
115 | | FieldUnit::PICA |
116 | | |
117 | | -------------------------------------------------------------------------- |
118 | | |
119 | | SetMargin1() sets the upper/left margin and SetMargin2() sets the |
120 | | bottom/right margin. If these methods are called without arguments, |
121 | | no margins are displayed. Otherwise, the following arguments can be passed: |
122 | | |
123 | | long nPos - offset in pixels relative to the origin |
124 | | sal_uInt16 nStyle - bit style: |
125 | | RULER_MARGIN_SIZEABLE |
126 | | margin size can be changed |
127 | | |
128 | | The following bits can be set in addition |
129 | | to these styles: |
130 | | RULER_STYLE_INVISIBLE |
131 | | |
132 | | |
133 | | SetBorders() sets an array of margins. To do this, an array of type RulerBorder |
134 | | has to be passed. In the array, the following values have to be initialized: |
135 | | |
136 | | long nPos - offset in pixels relative to the origin |
137 | | long nWidth - column spacing in pixels (can also be 0, for example, |
138 | | for table columns) |
139 | | sal_uInt16 nStyle - bit style: |
140 | | RulerBorderStyle::Sizeable |
141 | | Column spacing can be changed. This flag should |
142 | | only be set if the size of the spacing is changed, |
143 | | not that of a cell. |
144 | | RulerBorderStyle::Moveable |
145 | | Column spacing/border can be moved. Whenever |
146 | | table borders are to be moved, this flag should |
147 | | be set instead of SIZEABLE (SIZEABLE indicates |
148 | | that the size of a spacing, not that of a single |
149 | | cell can be changed). |
150 | | RulerBorderStyle::Variable |
151 | | Not all of the column spacings are equal |
152 | | RulerBorderStyle::Table |
153 | | Table border. Whenever this style is set, the column |
154 | | width must be 0. |
155 | | RulerBorderStyle::Snap |
156 | | Auxiliary line. Whenever this style is set, the |
157 | | column width must be 0. |
158 | | RulerBorderStyle::Margin |
159 | | Margin. Whenever this style is set, the column |
160 | | width must be 0. |
161 | | |
162 | | The following bits can be set in addition |
163 | | to these styles: |
164 | | RULER_STYLE_INVISIBLE |
165 | | |
166 | | SetIndents() sets an array of indents. This method may only be used for horizontal |
167 | | rulers. A Ruler Indent must be passed as an argument, with the following values |
168 | | initialized: |
169 | | |
170 | | long nPos - offset relative to the origin in pixels |
171 | | sal_uInt16 nStyle - bit style: |
172 | | RulerIndentStyle::Top (indent of the first line) |
173 | | RulerIndentStyle::Bottom (left/right indent) |
174 | | RulerIndentStyle::Border (Vertical line that shows the border distance) |
175 | | The following bits can be set in addition |
176 | | to these styles: |
177 | | RULER_STYLE_DONTKNOW (for old position or for |
178 | | ambiguity) |
179 | | RULER_STYLE_INVISIBLE |
180 | | |
181 | | SetTabs() sets an array of tabs. This method may only be used for horizontal rulers. |
182 | | An array of type RulerTab must be passed as an argument, with the following values |
183 | | initialized: |
184 | | |
185 | | long nPos - offset relative to the origin in pixels |
186 | | sal_uInt16 nStyle - bit style: |
187 | | RULER_TAB_DEFAULT (can't be selected) |
188 | | RULER_TAB_LEFT |
189 | | RULER_TAB_CENTER |
190 | | RULER_TAB_RIGHT |
191 | | RULER_TAB_DECIMAL |
192 | | The following bits can be set in addition |
193 | | to these styles: |
194 | | RULER_STYLE_DONTKNOW (for old position of for |
195 | | ambiguity) |
196 | | RULER_STYLE_INVISIBLE |
197 | | |
198 | | SetLines() displays position lines in the ruler. An array of type RulerLine must be passed, with |
199 | | the following values initialized: |
200 | | |
201 | | long nPos - offset relative to the origin in pixels |
202 | | sal_uInt16 nStyle - bit style (has to be 0 currently) |
203 | | |
204 | | -------------------------------------------------------------------------- |
205 | | |
206 | | If the user should also be able to change the margins tabs, borders, ... |
207 | | in the ruler, a bit more effort is necessary. In this case, the StartDrag(), |
208 | | Drag() and EndDrag() methods have to be overridden. For the StartDrag() method |
209 | | it is possible to prevent dragging by returning FALSE. In the drag handler, |
210 | | the drag position must be queried and the values must be moved to the new |
211 | | position. This is done by calling the particular Set methods. While in the |
212 | | drag handler, the values are just cached and only afterward the ruler is redrawn. |
213 | | All the handlers can also be set as links with the particular Set..Hdl() methods. |
214 | | |
215 | | - StartDrag() |
216 | | Is called when dragging is started. If FALSE is returned, the dragging. |
217 | | won't be executed. If TRUE is returned, the dragging will be permitted. |
218 | | If the handler isn't overridden, FALSE will be returned. |
219 | | |
220 | | - EndDrag() |
221 | | Is called at the end of dragging. |
222 | | |
223 | | - Drag() |
224 | | Is called when dragging takes place. |
225 | | |
226 | | - Click() |
227 | | This handler is called when no element has been clicked on. |
228 | | The position can be queried with GetClickPos(). This way it is possible |
229 | | to, for example, set tabs in the ruler. After calling the click handler, |
230 | | the drag, if any, is immediately triggered. This makes it possible to |
231 | | set a new tab in the click handler and then immediately move it. |
232 | | |
233 | | - DoubleClick() |
234 | | This handler is called when a double-click has been performed outside |
235 | | the special panel. The methods GetClickType(), GetClickAryPos() and |
236 | | GetClickPos() can be used to query what has been clicked on. |
237 | | This way you can, for example, show the tab dialog when a double-click |
238 | | is performed on a tab. |
239 | | |
240 | | In the drag handler it is possible to query what has been dragged and where |
241 | | it has been dragged. There are the following query methods: |
242 | | |
243 | | - GetDragType() |
244 | | Returns what has been dragged. |
245 | | RulerType::Margin1 |
246 | | RulerType::Margin2 |
247 | | RulerType::Border |
248 | | RulerType::Indent |
249 | | RulerType::Tab |
250 | | |
251 | | - GetDragPos() |
252 | | Returns the pixel position to which the user has moved the mouse |
253 | | relative to the set zero-offset. |
254 | | |
255 | | - GetDragAryPos() |
256 | | Returns the index in the array if a border, an indent or a tab |
257 | | is being dragged. Attention: During a drag process, the array position |
258 | | of the item that has been set before the drag is returned. |
259 | | Therefore, it is for example also possible, to no longer show a tab |
260 | | if the mouse is dragged out of the ruler in bottom/right direction. |
261 | | |
262 | | - GetDragSize() |
263 | | If Borders are dragged, this can be used to query whether the size |
264 | | resp. which side or the position should be changed. |
265 | | RulerDragSize::Move or 0 - Move |
266 | | RulerDragSize::N1 - left/upper border |
267 | | RulerDragSize::N2 - right/bottom border |
268 | | |
269 | | - IsDragDelete() |
270 | | This method can be used to query whether the mouse has been |
271 | | moved out of the window at the bottom/right while dragging. |
272 | | By this, it can for example be determined whether the user |
273 | | wants to delete a tab. |
274 | | |
275 | | - IsDragCanceled() |
276 | | Using this Handler, it can be queried in the EndDrag handler |
277 | | whether the action was canceled by the user releasing the |
278 | | mouse at the top/left of the window or by pressing ESC. |
279 | | In this case, the values are not applied. If during the |
280 | | dragging, the mouse is dragged out of the window at the |
281 | | top/left, the old values are displayed automatically without |
282 | | the Drag handler being called. |
283 | | But if the user has moved the value to the old position, the |
284 | | method returns 'false' nevertheless. |
285 | | If this should be avoided, the application must remember the |
286 | | old value in the StartDrag handler and compare the value in the |
287 | | EndDrag handler. |
288 | | |
289 | | - GetDragModifier() |
290 | | Returns the modifier keys that were pressed when the Drag process |
291 | | was started. See MouseEvent. |
292 | | |
293 | | - GetClickPos() |
294 | | Returns the pixel position at which the user has pressed the mouse |
295 | | with respect to the configured null-offset. |
296 | | |
297 | | - GetClickType() |
298 | | Returns what is applied by double click: |
299 | | RulerType::DontKnow (no element in the ruler area) |
300 | | RulerType::Outside (outside of the ruler area) |
301 | | RulerType::Margin1 (only Margin1 border) |
302 | | RulerType::Margin2 (only Margin2 border) |
303 | | RulerType::Border (Border: GetClickAryPos()) |
304 | | RulerType::Indent (indent: GetClickAryPos()) |
305 | | RulerType::Tab (Tab: GetClickAryPos()) |
306 | | |
307 | | - GetClickAryPos() |
308 | | Returns the index in the array if a Border, an Indent or a Tab |
309 | | is applied via DoubleClick. |
310 | | |
311 | | - GetType() |
312 | | This method can be used to carry out a HitTest, |
313 | | in order to possibly also apply sth to an Item using the right |
314 | | mouse button by catching the MouseButtonDown handler. As |
315 | | parameters, the window position and possibly a pointer to a |
316 | | sal_uInt16 are passed, in order to determine the array position |
317 | | of a Tab, an Indent, or a Border. The following values are |
318 | | returned as type: |
319 | | RulerType::DontKnow (no element in the ruler area) |
320 | | RulerType::Outside (outside of the ruler area) |
321 | | RulerType::Margin1 (only Margin1 border) |
322 | | RulerType::Margin2 (only Margin2 border) |
323 | | RulerType::Border (Border: GetClickAryPos()) |
324 | | RulerType::Indent (indent: GetClickAryPos()) |
325 | | RulerType::Tab (Tab: GetClickAryPos()) |
326 | | |
327 | | If the drag process should be canceled, this can be done using CancelDrag(). |
328 | | There are the following methods for controlling the Drag: |
329 | | |
330 | | - IsDrag() |
331 | | Returns 'true' if the ruler is in a drag process. |
332 | | |
333 | | - CancelDrag() |
334 | | Cancels the drag process, if one is being carried out. During this, |
335 | | the old values are restored and the Drag and the EndDrag handlers |
336 | | are called. |
337 | | |
338 | | In order to trigger a Drag from the document, there are the following |
339 | | methods: |
340 | | |
341 | | - StartDocDrag() |
342 | | This method is passed the MouseEvent of the document window |
343 | | and what should be dragged. If RulerType::DontKnow is passed |
344 | | as DragType, the ruler decides what should be dragged. In case |
345 | | of the other types, the Drag is only started if a respective |
346 | | element was found at the given position. |
347 | | This is for example necessary if indents and columns are located |
348 | | at the same X position. |
349 | | The return value indicates whether the Drag has been triggered. |
350 | | If a Drag is triggered, the ruler takes over the normal drag |
351 | | control and behaves as if the ruler had been clicked directly. |
352 | | Thus, the ruler captures the mouse and also takes over control |
353 | | of the Cancel (via keyboard, or if the mouse is moved outside |
354 | | of the ruler above it or left of it). All handlers are called, |
355 | | too (including the StartDrag handler). If a MouseEvent with |
356 | | ClickCount 2 is passed, the DoubleClick handler is also called, |
357 | | respectively. |
358 | | |
359 | | -------------------------------------------------------------------------- |
360 | | |
361 | | For the extra field, the content can be determined and there are handlers |
362 | | that can be used to handle specific actions. |
363 | | |
364 | | - ExtraDown() |
365 | | This handler is called when the mouse is pressed in the extra field. |
366 | | |
367 | | - SetExtraType() |
368 | | With this method, it can be defined what should be displayed in |
369 | | the extra field. |
370 | | - ExtraType what should be displayed in the extra field |
371 | | RulerExtra::DontKnow (nothing) |
372 | | RulerExtra::NullOffset (coordinate axes) |
373 | | RulerExtra::Tab (Tab) |
374 | | - sal_uInt16 nStyle bit field as style: |
375 | | RULER_STYLE_HIGHLIGHT (selected) |
376 | | RULER_TAB_... (a Tab style) |
377 | | |
378 | | - GetExtraClick() |
379 | | Returns the number of mouse clicks. By this, it is for example |
380 | | also possible to trigger an action by a DoubleClick in the |
381 | | extra field. |
382 | | |
383 | | - GetExtraModifier() |
384 | | Returns the modifier keys that were pressed when the extra field |
385 | | was clicked. See MouseEvent. |
386 | | |
387 | | -------------------------------------------------------------------------- |
388 | | |
389 | | Further helper functions: |
390 | | |
391 | | - static Ruler::DrawTab() |
392 | | With this method, a Tab can be output on an OutputDevice. |
393 | | By this, it is also possible to show the Tabs in dialogs like |
394 | | they are drawn in the ruler. |
395 | | |
396 | | This method outputs the Tab centred at the given position. The size |
397 | | of the tabs can be defined by the defines RULER_TAB_WIDTH and |
398 | | RULER_TAB_HEIGHT. |
399 | | |
400 | | -------------------------------------------------------------------------- |
401 | | |
402 | | Tips for the use of the ruler: |
403 | | |
404 | | - For the ruler, neither in the Drag mode nor elsewhere, the setting |
405 | | of the values must be bracketed in SetUpdateMode(). The ruler itself |
406 | | takes care that, if multiple values are set, they are automatically |
407 | | grouped together and output flicker-free. |
408 | | |
409 | | - Initially, the sizes, positions and values should be set first for the |
410 | | ruler, before it is displayed. This is important because otherwise |
411 | | many values are calculated unnecessarily. |
412 | | |
413 | | - When the document window, in which the ruler resides, becomes active |
414 | | resp. unactive, the methods Activate() and Deactivate() should be |
415 | | called by the ruler. That is so because the display is switched according |
416 | | to the settings and the system. |
417 | | |
418 | | - For example, while dragging Tabs and Indents, the old positions should |
419 | | also be shown if possible. For that, while setting the Tabs and Indents, |
420 | | the old positions should be inserted first into the array in addition |
421 | | and be linked with the style RULER_STYLE_DONTKNOW. After that, the |
422 | | remaining values should be set in the array. |
423 | | |
424 | | - In case of multiple selected paragraphs and table cells, the Tabs and |
425 | | Indents should be displayed in grey in front of the first cell resp. |
426 | | the first paragraph. This can also be achieved by the style |
427 | | RULER_STYLE_DONTKNOW. |
428 | | |
429 | | - The measuring arrow should always be shown when the Alt key (WW-Like) |
430 | | is pressed during the drag. Maybe, this setting should be configurable |
431 | | always and possibly the measuring arrows always be shown while |
432 | | dragging. For all settings, the values should always be rounded to the |
433 | | multiple of one value because the screen resolution is very imprecise. |
434 | | |
435 | | - DoubleClicks should be handled in the following way (GetClickType()): |
436 | | - RulerType::DontKnow |
437 | | RulerType::Margin1 |
438 | | RulerType::Margin2 |
439 | | If the conditions GetClickPos() <= GetMargin1() or |
440 | | GetClickPos() >= GetMargin2() are met or the type is equal to |
441 | | RulerType::Margin1 or RulerType::Margin2, a side dialog should |
442 | | be displayed in which the focus is at the respective border. |
443 | | - RulerType::Border |
444 | | A column or table dialog should be shown in which the focus |
445 | | is at the respective column that can be queried using |
446 | | GetClickAryPos(). |
447 | | - RulerType::Indent |
448 | | The dialog, in which the indents can be configured, should be |
449 | | shown. In this, the focus should be on the indent which can |
450 | | be queried using GetClickAryPos(). |
451 | | - RulerType::Tab |
452 | | A TabDialog should be displayed in which the Tab, that can be |
453 | | queried using GetClickAryPos(), should be selected. |
454 | | |
455 | | *************************************************************************/ |
456 | | |
457 | | |
458 | | constexpr WinBits WB_EXTRAFIELD = 0x00004000; |
459 | | constexpr WinBits WB_RIGHT_ALIGNED = 0x00008000; |
460 | | constexpr auto WB_STDRULER = WB_HORZ; |
461 | | |
462 | | // tdf#84949 - TabAlign is used to identify the current tabulator alignment |
463 | | enum class RulerType { DontKnow, Outside, |
464 | | Margin1, Margin2, |
465 | | Border, Indent, Tab, TabAlign }; |
466 | | |
467 | | enum class RulerExtra { DontKnow, NullOffset, Tab }; |
468 | | |
469 | | constexpr sal_uInt16 RULER_STYLE_HIGHLIGHT = 0x8000; |
470 | | constexpr sal_uInt16 RULER_STYLE_DONTKNOW = 0x4000; |
471 | | constexpr sal_uInt16 RULER_STYLE_INVISIBLE = 0x2000; |
472 | | |
473 | | enum class RulerDragSize { |
474 | | Move, |
475 | | N1, |
476 | | N2 |
477 | | }; |
478 | | |
479 | | constexpr auto RULER_MOUSE_BORDERMOVE = 5; |
480 | | constexpr auto RULER_MOUSE_BORDERWIDTH = 5; |
481 | | constexpr auto RULER_MOUSE_MARGINWIDTH = 3; |
482 | | |
483 | | |
484 | | enum class RulerMarginStyle { |
485 | | NONE = 0x0000, |
486 | | Sizeable = 0x0001, |
487 | | Invisible = 0x0002 |
488 | | }; |
489 | | namespace o3tl { |
490 | | template<> struct typed_flags<RulerMarginStyle> : is_typed_flags<RulerMarginStyle, 0x0003> {}; |
491 | | } |
492 | | |
493 | | |
494 | | enum class RulerBorderStyle { |
495 | | Sizeable = 0x0001, |
496 | | Moveable = 0x0002, |
497 | | Variable = 0x0004, |
498 | | Invisible = 0x0008 |
499 | | }; |
500 | | namespace o3tl { |
501 | | template<> struct typed_flags<RulerBorderStyle> : is_typed_flags<RulerBorderStyle, 0x000f> {}; |
502 | | } |
503 | | |
504 | | struct RulerBorder |
505 | | { |
506 | | tools::Long nPos; |
507 | | tools::Long nWidth; |
508 | | RulerBorderStyle nStyle; |
509 | | tools::Long nMinPos; //minimum/maximum position, supported for table borders/rows |
510 | | tools::Long nMaxPos; |
511 | | }; |
512 | | |
513 | | enum class RulerIndentStyle { |
514 | | Top, Bottom |
515 | | }; |
516 | | |
517 | | struct RulerIndent |
518 | | { |
519 | | tools::Long nPos; |
520 | | RulerIndentStyle nStyle; |
521 | | bool bInvisible; |
522 | | }; |
523 | | |
524 | | |
525 | | constexpr sal_uInt16 RULER_TAB_LEFT = 0x0000; |
526 | | constexpr sal_uInt16 RULER_TAB_RIGHT = 0x0001; |
527 | | constexpr sal_uInt16 RULER_TAB_CENTER = 0x0002; |
528 | | constexpr sal_uInt16 RULER_TAB_DECIMAL = 0x0003; |
529 | | constexpr sal_uInt16 RULER_TAB_DEFAULT = 0x0004; |
530 | | constexpr sal_uInt16 RULER_TAB_STYLE = 0x000F; |
531 | | constexpr sal_uInt16 RULER_TAB_RTL = 0x0010; |
532 | | |
533 | | struct RulerTab |
534 | | { |
535 | | tools::Long nPos; |
536 | | sal_uInt16 nStyle; |
537 | | }; |
538 | | |
539 | | |
540 | | struct RulerLine |
541 | | { |
542 | | tools::Long nPos; |
543 | | }; |
544 | | |
545 | | |
546 | | struct RulerSelection |
547 | | { |
548 | | tools::Long nPos; |
549 | | RulerType eType; |
550 | | sal_uInt16 nAryPos; |
551 | | RulerDragSize mnDragSize; |
552 | | bool bSize; |
553 | | bool bSizeBar; |
554 | | bool bExpandTest; |
555 | | |
556 | | RulerSelection() |
557 | 7.87k | : nPos(0) |
558 | 7.87k | , eType(RulerType::DontKnow) |
559 | 7.87k | , nAryPos(0) |
560 | 7.87k | , mnDragSize(RulerDragSize::Move) |
561 | 7.87k | , bSize(false) |
562 | 7.87k | , bSizeBar(false) |
563 | 7.87k | , bExpandTest( false ) |
564 | 7.87k | {} |
565 | | }; |
566 | | |
567 | | |
568 | | struct RulerUnitData |
569 | | { |
570 | | MapUnit eMapUnit; // MAP_UNIT for calculation |
571 | | tools::Long nTickUnit; // Unit divider |
572 | | double nTick1; // Minimal step |
573 | | double nTick2; // Tick quarter unit |
574 | | double nTick3; // Tick half unit |
575 | | double nTick4; // Tick whole unit |
576 | | char aUnitStr[8]; // Unit string |
577 | | }; |
578 | | |
579 | | |
580 | | // Data for drawing ruler tabstops |
581 | | struct RulerTabData |
582 | | { |
583 | | sal_uInt16 DPIScaleFactor; |
584 | | sal_uInt16 width; |
585 | | sal_uInt16 height; |
586 | | sal_uInt16 height2; |
587 | | sal_uInt16 width2; |
588 | | sal_uInt16 cwidth; |
589 | | sal_uInt16 cwidth2; |
590 | | sal_uInt16 cwidth3; |
591 | | sal_uInt16 cwidth4; |
592 | | sal_uInt16 dheight; |
593 | | sal_uInt16 dheight2; |
594 | | sal_uInt16 dwidth; |
595 | | sal_uInt16 dwidth2; |
596 | | sal_uInt16 dwidth3; |
597 | | sal_uInt16 dwidth4; |
598 | | sal_uInt16 textoff; |
599 | | }; |
600 | | |
601 | | |
602 | | class ImplRulerData; |
603 | | |
604 | | class SVT_DLLPUBLIC Ruler : public vcl::Window |
605 | | { |
606 | | private: |
607 | | ScopedVclPtr<VirtualDevice> maVirDev; |
608 | | MapMode maMapMode; |
609 | | tools::Long mnBorderOff; |
610 | | tools::Long mnWinOff; |
611 | | tools::Long mnWinWidth; |
612 | | tools::Long mnWidth; |
613 | | tools::Long mnHeight; |
614 | | tools::Long mnVirOff; |
615 | | tools::Long mnVirWidth; |
616 | | tools::Long mnVirHeight; |
617 | | tools::Long mnBorderWidth; |
618 | | tools::Long mnStartDragPos; |
619 | | tools::Long mnDragPos; |
620 | | std::unique_ptr<ImplRulerData> mpSaveData; |
621 | | ImplRulerData* mpData; |
622 | | std::unique_ptr<ImplRulerData> mpDragData; |
623 | | tools::Rectangle maExtraRect; |
624 | | WinBits mnWinStyle; |
625 | | sal_uInt16 mnUnitIndex; |
626 | | sal_uInt16 mnDragAryPos; |
627 | | RulerDragSize mnDragSize; |
628 | | sal_uInt16 mnDragModifier; |
629 | | sal_uInt16 mnExtraStyle; |
630 | | tools::Long mnCharWidth; |
631 | | tools::Long mnLineHeight; |
632 | | |
633 | | RulerExtra meExtraType; |
634 | | RulerType meDragType; |
635 | | FieldUnit meUnit; |
636 | | double maZoom; |
637 | | bool mbCalc; |
638 | | bool mbFormat; |
639 | | bool mbDrag; |
640 | | bool mbDragDelete; |
641 | | bool mbDragCanceled; |
642 | | bool mbAutoWinWidth; |
643 | | bool mbActive; |
644 | | sal_uInt8 mnUpdateFlags; |
645 | | |
646 | | RulerSelection maHoverSelection; |
647 | | |
648 | | Link<Ruler*,void> maDoubleClickHdl; |
649 | | |
650 | | std::unique_ptr<RulerSelection> mxCurrentHitTest; |
651 | | std::unique_ptr<RulerSelection> mxPreviousHitTest; |
652 | | |
653 | | std::map<OUString, SalLayoutGlyphs> maTextGlyphs; |
654 | | |
655 | | SVT_DLLPRIVATE void ImplVDrawLine(vcl::RenderContext& rRenderContext, tools::Long nX1, tools::Long nY1, tools::Long nX2, tools::Long nY2 ); |
656 | | SVT_DLLPRIVATE void ImplVDrawRect(vcl::RenderContext& rRenderContext, tools::Long nX1, tools::Long nY1, tools::Long nX2, tools::Long nY2 ); |
657 | | SVT_DLLPRIVATE void ImplVDrawText(vcl::RenderContext& rRenderContext, tools::Long nX, tools::Long nY, const OUString& rText, |
658 | | tools::Long nMin = LONG_MIN, tools::Long nMax = LONG_MAX ); |
659 | | |
660 | | SVT_DLLPRIVATE void ImplDrawTicks(vcl::RenderContext& rRenderContext, |
661 | | tools::Long nMin, tools::Long nMax, tools::Long nStart, tools::Long nVirTop, tools::Long nVirBottom); |
662 | | SVT_DLLPRIVATE void ImplDrawBorders(vcl::RenderContext& rRenderContext, |
663 | | tools::Long nMin, tools::Long nMax, tools::Long nVirTop, tools::Long nVirBottom); |
664 | | SVT_DLLPRIVATE static void ImplDrawIndent(vcl::RenderContext& rRenderContext, |
665 | | const tools::Polygon& rPoly, bool bIsHit); |
666 | | SVT_DLLPRIVATE void ImplDrawIndents(vcl::RenderContext& rRenderContext, |
667 | | tools::Long nMin, tools::Long nMax, tools::Long nVirTop, tools::Long nVirBottom); |
668 | | SVT_DLLPRIVATE void ImplDrawTab(vcl::RenderContext& rRenderContext, const Point& rPos, sal_uInt16 nStyle); |
669 | | SVT_DLLPRIVATE void ImplDrawTabs(vcl::RenderContext& rRenderContext, |
670 | | tools::Long nMin, tools::Long nMax, tools::Long nVirTop, tools::Long nVirBottom); |
671 | | |
672 | | using Window::ImplInit; |
673 | | SVT_DLLPRIVATE void ImplInit( WinBits nWinBits ); |
674 | | SVT_DLLPRIVATE void ImplInitSettings( bool bFont, bool bForeground, bool bBackground ); |
675 | | SVT_DLLPRIVATE void ImplCalc(); |
676 | | SVT_DLLPRIVATE void ImplFormat(vcl::RenderContext const & rRenderContext); |
677 | | SVT_DLLPRIVATE void ImplInitExtraField( bool bUpdate ); |
678 | | SVT_DLLPRIVATE void ImplInvertLines(vcl::RenderContext& rRenderContext); |
679 | | SVT_DLLPRIVATE void ImplDraw(vcl::RenderContext& rRenderContext); |
680 | | SVT_DLLPRIVATE void ImplDrawExtra(vcl::RenderContext& rRenderContext); |
681 | | SVT_DLLPRIVATE void ImplUpdate( bool bMustCalc = false ); |
682 | | |
683 | | virtual void ApplySettings(vcl::RenderContext& rRenderContext) override; |
684 | | |
685 | | SVT_DLLPRIVATE bool ImplDoHitTest( const Point& rPosition, |
686 | | RulerSelection* pHitTest, |
687 | | bool bRequiredStyle = false, |
688 | | RulerIndentStyle nRequiredStyle = RulerIndentStyle::Top, |
689 | | tools::Long nTolerance = 1 ) const; |
690 | | SVT_DLLPRIVATE bool ImplDocHitTest( const Point& rPos, |
691 | | RulerType eDragType, |
692 | | RulerSelection* pHitTest, |
693 | | tools::Long nTolerance = 1 ) const; |
694 | | SVT_DLLPRIVATE bool ImplStartDrag( RulerSelection const * pHitTest, sal_uInt16 nModifier ); |
695 | | SVT_DLLPRIVATE void ImplDrag( const Point& rPos ); |
696 | | SVT_DLLPRIVATE void ImplEndDrag(); |
697 | | |
698 | | Ruler (const Ruler &) = delete; |
699 | | Ruler& operator= (const Ruler &) = delete; |
700 | | |
701 | | protected: |
702 | 996 | tools::Long GetRulerVirHeight() const { return mnVirHeight;} |
703 | 0 | const MapMode& GetCurrentMapMode() const { return maMapMode; } |
704 | | const RulerUnitData& GetCurrentRulerUnit() const; |
705 | | |
706 | | public: |
707 | | Ruler( vcl::Window* pParent, WinBits nWinStyle = WB_STDRULER ); |
708 | | virtual ~Ruler() override; |
709 | | virtual void dispose() override; |
710 | | |
711 | | virtual void MouseButtonDown( const MouseEvent& rMEvt ) override; |
712 | | virtual void MouseMove( const MouseEvent& rMEvt ) override; |
713 | | virtual void Tracking( const TrackingEvent& rTEvt ) override; |
714 | | virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override; |
715 | | virtual void Resize() override; |
716 | | virtual void StateChanged( StateChangedType nStateChange ) override; |
717 | | virtual void DataChanged( const DataChangedEvent& rDCEvt ) override; |
718 | | |
719 | | virtual bool StartDrag(); |
720 | | virtual void Drag(); |
721 | | virtual void EndDrag(); |
722 | | virtual void Click(); |
723 | | void DoubleClick(); |
724 | | virtual void ExtraDown(); |
725 | | |
726 | | void Activate() override; |
727 | | void Deactivate() override; |
728 | | |
729 | | void SetWinPos( tools::Long nOff, tools::Long nWidth = 0 ); |
730 | 996 | tools::Long GetWinOffset() const { return mnWinOff; } |
731 | | void SetPagePos( tools::Long nOff = 0, tools::Long nWidth = 0 ); |
732 | | tools::Long GetPageOffset() const; |
733 | | void SetBorderPos( tools::Long nOff = 0 ); |
734 | 0 | tools::Long GetBorderOffset() const { return mnBorderOff; } |
735 | 0 | const tools::Rectangle& GetExtraRect() const { return maExtraRect; } |
736 | | |
737 | | void SetUnit( FieldUnit eNewUnit ); |
738 | 0 | FieldUnit GetUnit() const { return meUnit; } |
739 | | void SetZoom( double fNewZoom ); |
740 | | |
741 | | void SetExtraType( RulerExtra eNewExtraType, sal_uInt16 nStyle = 0 ); |
742 | | |
743 | | bool StartDocDrag( const MouseEvent& rMEvt, |
744 | | RulerType eDragType, |
745 | | tools::Long nTolerance = 1 ); |
746 | 0 | RulerType GetDragType() const { return meDragType; } |
747 | 0 | tools::Long GetDragPos() const { return mnDragPos; } |
748 | 0 | sal_uInt16 GetDragAryPos() const { return mnDragAryPos; } |
749 | 0 | RulerDragSize GetDragSize() const { return mnDragSize; } |
750 | 0 | bool IsDragDelete() const { return mbDragDelete; } |
751 | 0 | bool IsDragCanceled() const { return mbDragCanceled; } |
752 | 0 | sal_uInt16 GetDragModifier() const { return mnDragModifier; } |
753 | 1.99k | bool IsDrag() const { return mbDrag; } |
754 | | void CancelDrag(); |
755 | 0 | tools::Long GetClickPos() const { return mnDragPos; } |
756 | 0 | RulerType GetClickType() const { return meDragType; } |
757 | | |
758 | 0 | const RulerSelection& GetHoverSelection() const { return maHoverSelection; } |
759 | | |
760 | | RulerType GetRulerType( const Point& rPos, sal_uInt16* pAryPos = nullptr ); |
761 | | |
762 | | void SetNullOffset( tools::Long nPos ); |
763 | | tools::Long GetNullOffset() const; |
764 | 996 | void SetMargin1() { SetMargin1( 0, RulerMarginStyle::Invisible ); } |
765 | | void SetMargin1( tools::Long nPos, RulerMarginStyle nMarginStyle = RulerMarginStyle::Sizeable ); |
766 | | tools::Long GetMargin1() const; |
767 | 996 | void SetMargin2() { SetMargin2( 0, RulerMarginStyle::Invisible ); } |
768 | | void SetMargin2( tools::Long nPos, RulerMarginStyle nMarginStyle = RulerMarginStyle::Sizeable ); |
769 | | tools::Long GetMargin2() const; |
770 | | |
771 | | void SetLeftFrameMargin( tools::Long nPos ); |
772 | | void SetRightFrameMargin( tools::Long nPos ); |
773 | | void SetLines( sal_uInt32 n = 0, const RulerLine* pLineAry = nullptr ); |
774 | | void SetBorders( sal_uInt32 n = 0, const RulerBorder* pBrdAry = nullptr ); |
775 | | void SetIndents( sal_uInt32 n = 0, const RulerIndent* pIndentAry = nullptr ); |
776 | | |
777 | | void SetTabs( sal_uInt32 n = 0, const RulerTab* pTabAry = nullptr ); |
778 | | const std::vector<RulerTab>& GetTabs() const; |
779 | | |
780 | | static void DrawTab(vcl::RenderContext& rRenderContext, const Color &rFillColor, |
781 | | const Point& rPos, sal_uInt16 nStyle); |
782 | | |
783 | | void SetStyle( WinBits nStyle ); |
784 | 0 | WinBits GetStyle() const { return mnWinStyle; } |
785 | | |
786 | 3.93k | void SetDoubleClickHdl( const Link<Ruler*,void>& rLink ) { maDoubleClickHdl = rLink; } |
787 | | |
788 | | void SetTextRTL(bool bRTL); |
789 | 3.93k | void SetCharWidth( tools::Long nWidth ) { mnCharWidth = nWidth ; } |
790 | 3.93k | void SetLineHeight( tools::Long nHeight ) { mnLineHeight = nHeight ; } |
791 | | |
792 | | void DrawTicks(); |
793 | | |
794 | | virtual rtl::Reference<comphelper::OAccessible> CreateAccessible() override; |
795 | | }; |
796 | | |
797 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |