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 <scdllapi.h>
23 #include <address.hxx>
24 #include "csvsplits.hxx"
25 #include <o3tl/typed_flags_set.hxx>
26 #include <rtl/ref.hxx>
27 #include <vcl/customweld.hxx>
28 #include "AccessibleCsvControl.hxx"
29 
30 namespace com::sun::star::accessibility { class XAccessible; }
31 
32 /** Minimum character count for a column in separators mode. */
33 const sal_Int32 CSV_MINCOLWIDTH         = 8;
34 /** Maximum length of a cell string. */
35 const sal_Int32 CSV_MAXSTRLEN          = 0x7FFF;
36 /** Transparency for header color of selected columns. */
37 const sal_uInt16 CSV_HDR_TRANSPARENCY   = 85;
38 /** Minimum distance to border for auto scroll. */
39 const sal_Int32 CSV_SCROLL_DIST         = 3;
40 
41 //! TODO make string array dynamic
42 const sal_Int32 CSV_PREVIEW_LINES       = 32; // maximum count of preview lines
43 /** Maximum count of columns. */
44 const sal_Int32 CSV_MAXCOLCOUNT         = MAXCOLCOUNT;
45 
46 /** Default column data type. */
47 const sal_Int32 CSV_TYPE_DEFAULT        = 0;
48 /** Multi selection with different types. */
49 const sal_Int32 CSV_TYPE_MULTI          = -1;
50 /** No column selected. */
51 const sal_Int32 CSV_TYPE_NOSELECTION    = -2;
52 
53 // External used column types.
54 const sal_uInt8 SC_COL_STANDARD         = 1;
55 const sal_uInt8 SC_COL_TEXT             = 2;
56 const sal_uInt8 SC_COL_MDY              = 3;
57 const sal_uInt8 SC_COL_DMY              = 4;
58 const sal_uInt8 SC_COL_YMD              = 5;
59 const sal_uInt8 SC_COL_SKIP             = 9;
60 const sal_uInt8 SC_COL_ENGLISH          = 10;
61 
62 /** Exported data of a column (data used in the dialog). */
63 struct ScCsvExpData
64 {
65     sal_Int32                   mnIndex;        /// Index of a column.
66     sal_uInt8                   mnType;         /// External type of the column.
67 
ScCsvExpDataScCsvExpData68     ScCsvExpData() : mnIndex( 0 ), mnType( SC_COL_STANDARD ) {}
ScCsvExpDataScCsvExpData69     ScCsvExpData( sal_Int32 nIndex, sal_uInt8 nType ) :
70                                     mnIndex( nIndex ), mnType( nType ) {}
71 };
72 
73 typedef ::std::vector< ScCsvExpData > ScCsvExpDataVec;
74 
75 /** Specifies which element should be used to perform an action. */
76 enum ScMoveMode
77 {
78     MOVE_NONE,                  /// No action.
79     MOVE_FIRST,                 /// First element in current context.
80     MOVE_LAST,                  /// Last element in current context.
81     MOVE_PREV,                  /// Predecessor of current element in current context.
82     MOVE_NEXT,                  /// Successor of current element in current context.
83     MOVE_PREVPAGE,              /// Previous page relative to current context.
84     MOVE_NEXTPAGE               /// Next page relative to current context.
85 };
86 
87 /** Flags for comparison of old and new control layout data. */
88 enum class ScCsvDiff : sal_uInt32 {
89     Equal          = 0x0000,
90     PosCount       = 0x0001,
91     PosOffset      = 0x0002,
92     HeaderWidth    = 0x0004,
93     CharWidth      = 0x0008,
94     LineCount      = 0x0010,
95     LineOffset     = 0x0020,
96     HeaderHeight   = 0x0040,
97     LineHeight     = 0x0080,
98     RulerCursor    = 0x0100,
99     GridCursor     = 0x0200,
100 
101     HorizontalMask = PosCount | PosOffset | HeaderWidth | CharWidth,
102     VerticalMask   = LineCount | LineOffset | HeaderHeight | LineHeight
103 };
104 namespace o3tl {
105     template<> struct typed_flags<ScCsvDiff> : is_typed_flags<ScCsvDiff, 0x03ff> {};
106 }
107 
108 
109 /** A structure containing all layout data valid for both ruler and data grid
110     (i.e. scroll position or column width). */
111 struct ScCsvLayoutData
112 {
113     // horizontal settings
114     sal_Int32                   mnPosCount;         /// Number of positions.
115     sal_Int32                   mnPosOffset;        /// Horizontal scroll offset.
116 
117     sal_Int32                   mnWinWidth;         /// Width of ruler and data grid.
118     sal_Int32                   mnHdrWidth;         /// Width of the header column.
119     sal_Int32                   mnCharWidth;        /// Pixel width of one character.
120 
121     // vertical settings
122     sal_Int32                   mnLineCount;        /// Number of data lines.
123     sal_Int32                   mnLineOffset;       /// Index of first visible line (0-based).
124 
125     sal_Int32                   mnWinHeight;        /// Height of entire data grid (incl. header).
126     sal_Int32                   mnHdrHeight;        /// Height of the header line.
127     sal_Int32                   mnLineHeight;       /// Height of a data line.
128 
129     // cursor settings
130     sal_Int32                   mnPosCursor;        /// Position of ruler cursor.
131     sal_Int32                   mnColCursor;        /// Position of grid column cursor.
132 
133     mutable sal_Int32           mnNoRepaint;        /// >0 = no repaint.
134     bool                        mbAppRTL;           /// true = application in RTL mode.
135 
136     explicit                    ScCsvLayoutData();
137 
138     /** Returns differences to rData.
139         @descr  For each difference the appropriate bit is set in the returned value. */
140     ScCsvDiff                   GetDiff( const ScCsvLayoutData& rData ) const;
141 };
142 
operator ==(const ScCsvLayoutData & rData1,const ScCsvLayoutData & rData2)143 inline bool operator==( const ScCsvLayoutData& rData1, const ScCsvLayoutData& rData2 )
144 {
145     return rData1.GetDiff( rData2 ) == ScCsvDiff::Equal;
146 }
147 
operator !=(const ScCsvLayoutData & rData1,const ScCsvLayoutData & rData2)148 inline bool operator!=( const ScCsvLayoutData& rData1, const ScCsvLayoutData& rData2 )
149 {
150     return !(rData1 == rData2);
151 }
152 
153 /** Enumeration of possible commands to change any settings of the CSV controls.
154     @descr  Controls have to send commands instead of changing their settings directly.
155     This helps to keep the different controls consistent to each other.
156     A command can contain 0 to 2 sal_Int32 parameters. In the description of each
157     command the required parameters are shown in brackets. [-] means no parameter. */
158 enum ScCsvCmdType
159 {
160     // misc
161     CSVCMD_NONE,                /// No command. [-]
162     CSVCMD_REPAINT,             /// Repaint all controls. [-]
163 
164     // modify horizontal dimensions
165     CSVCMD_SETPOSCOUNT,         /// Change position/column count. [character count]
166     CSVCMD_SETPOSOFFSET,        /// Change position offset (scroll pos). [position]
167     CSVCMD_SETHDRWIDTH,         /// Change width of the header column. [width in pixel]
168     CSVCMD_SETCHARWIDTH,        /// Change character pixel width. [width in pixel]
169 
170     // modify vertical dimensions
171     CSVCMD_SETLINECOUNT,        /// Change number of data lines. [line count]
172     CSVCMD_SETLINEOFFSET,       /// Change first visible line. [line index]
173     CSVCMD_SETHDRHEIGHT,        /// Change height of top header line. [height in pixel]
174     CSVCMD_SETLINEHEIGHT,       /// Change data line pixel height. [height in pixel}
175 
176     // cursors/positions
177     CSVCMD_MOVERULERCURSOR,     /// Move ruler cursor to new position. [position]
178     CSVCMD_MOVEGRIDCURSOR,      /// Move data grid cursor to new column. [position]
179     CSVCMD_MAKEPOSVISIBLE,      /// Move to make passed position visible (for mouse tracking). [position]
180 
181     // table contents
182     CSVCMD_NEWCELLTEXTS,        /// Recalculate splits and cell texts. [-]
183     CSVCMD_UPDATECELLTEXTS,     /// Update cell texts with current split settings. [-]
184     CSVCMD_SETCOLUMNTYPE,       /// Change data type of selected columns. [column type]
185     CSVCMD_EXPORTCOLUMNTYPE,    /// Send selected column type to external controls. [-]
186     CSVCMD_SETFIRSTIMPORTLINE,  /// Set number of first imported line. [line index]
187 
188     // splits
189     CSVCMD_INSERTSPLIT,         /// Insert a split. [position]
190     CSVCMD_REMOVESPLIT,         /// Remove a split. [position]
191     CSVCMD_TOGGLESPLIT,         /// Inserts or removes a split. [position]
192     CSVCMD_MOVESPLIT,           /// Move a split. [old position, new position]
193     CSVCMD_REMOVEALLSPLITS      /// Remove all splits. [-]
194 };
195 
196 /** Data for a CSV control command. The stored position data is always character based,
197     it's never a column index (required for internal consistency). */
198 class ScCsvCmd
199 {
200 private:
201     ScCsvCmdType                meType;         /// The command.
202     sal_Int32                   mnParam1;       /// First parameter.
203     sal_Int32                   mnParam2;       /// Second parameter.
204 
205 public:
ScCsvCmd()206     explicit             ScCsvCmd() : meType( CSVCMD_NONE ),
207                                     mnParam1( CSV_POS_INVALID ), mnParam2( CSV_POS_INVALID ) {}
208 
209     inline void                 Set( ScCsvCmdType eType, sal_Int32 nParam1, sal_Int32 nParam2 );
210 
GetType() const211     ScCsvCmdType         GetType() const     { return meType; }
GetParam1() const212     sal_Int32            GetParam1() const   { return mnParam1; }
GetParam2() const213     sal_Int32            GetParam2() const   { return mnParam2; }
214 };
215 
Set(ScCsvCmdType eType,sal_Int32 nParam1,sal_Int32 nParam2)216 inline void ScCsvCmd::Set( ScCsvCmdType eType, sal_Int32 nParam1, sal_Int32 nParam2 )
217 {
218     meType = eType; mnParam1 = nParam1; mnParam2 = nParam2;
219 }
220 
221 /** Base class for the CSV ruler and the data grid control. Implements command handling. */
222 class SC_DLLPUBLIC ScCsvControl : public weld::CustomWidgetController
223 {
224 private:
225     Link<ScCsvControl&,void>    maCmdHdl;           /// External command handler.
226     ScCsvCmd                    maCmd;              /// Data of last command.
227     const ScCsvLayoutData&      mrData;             /// Shared layout data.
228 
229     bool                        mbValidGfx;         /// Content of virtual devices valid?
230 
231 protected:
232     rtl::Reference<ScAccessibleCsvControl> mxAccessible; /// Reference to the accessible implementation object.
233 
234 public:
235     explicit                    ScCsvControl(const ScCsvLayoutData& rData);
236     virtual                     ~ScCsvControl() override;
237 
238     // event handling ---------------------------------------------------------
239 
240     virtual void                GetFocus() override;
241     virtual void                LoseFocus() override;
242 
243     /** Sends a GetFocus or LoseFocus event to the accessibility object. */
244     void                        AccSendFocusEvent( bool bFocused );
245     /** Sends a caret changed event to the accessibility object. */
246     void                        AccSendCaretEvent();
247     /** Sends a visible area changed event to the accessibility object. */
248     void                        AccSendVisibleEvent();
249     /** Sends a selection changed event to the accessibility object. */
250     void                        AccSendSelectionEvent();
251     /** Sends a table model changed event for changed cell contents to the accessibility object. */
252     void                        AccSendTableUpdateEvent( sal_uInt32 nFirstColumn, sal_uInt32 nLastColumn, bool bAllRows = true );
253     /** Sends a table model changed event for an inserted column to the accessibility object. */
254     void                        AccSendInsertColumnEvent( sal_uInt32 nFirstColumn, sal_uInt32 nLastColumn );
255     /** Sends a table model changed event for a removed column to the accessibility object. */
256     void                        AccSendRemoveColumnEvent( sal_uInt32 nFirstColumn, sal_uInt32 nLastColumn );
257 
GetAccessible()258     ScAccessibleCsvControl*     GetAccessible() { return mxAccessible.get(); }
259 
260     // repaint helpers --------------------------------------------------------
261 
262     /** Sets the graphic invalid (next Redraw() will not use cached graphic). */
InvalidateGfx()263     void                 InvalidateGfx() { mbValidGfx = false; }
264     /** Sets the graphic valid (next Redraw() will use cached graphic). */
ValidateGfx()265     void                 ValidateGfx() { mbValidGfx = true; }
266     /** Returns true, if cached graphic is valid. */
IsValidGfx() const267     bool                 IsValidGfx() const { return mbValidGfx; }
268 
269     /** Repaints all controls.
270         @param bInvalidate  true = invalidates graphics of this control (not all). */
271     void                        Repaint( bool bInvalidate = false );
272     /** Increases no-repaint counter (controls do not repaint until the last EnableRepaint()). */
273     void                        DisableRepaint();
274     /** Decreases no-repaint counter and repaints if counter reaches 0. */
275     void                        EnableRepaint();
276     /** Returns true, if controls will not repaint. */
IsNoRepaint() const277     bool                 IsNoRepaint() const { return mrData.mnNoRepaint > 0; }
278 
279     // command handling -------------------------------------------------------
280 
281     /** Sets a new command handler. */
SetCmdHdl(const Link<ScCsvControl &,void> & rHdl)282     void                 SetCmdHdl( const Link<ScCsvControl&,void>& rHdl ) { maCmdHdl = rHdl; }
283     /** Returns data of the last command. */
GetCmd() const284     const ScCsvCmd&      GetCmd() const { return maCmd; }
285 
286     /** Executes a command by calling command handler. */
287     void                        Execute(
288                                     ScCsvCmdType eType,
289                                     sal_Int32 nParam1 = CSV_POS_INVALID,
290                                     sal_Int32 nParam2 = CSV_POS_INVALID );
291 
292     // layout helpers ---------------------------------------------------------
293 
294     /** Returns a reference to the current layout data. */
GetLayoutData() const295     const ScCsvLayoutData& GetLayoutData() const { return mrData; }
296     /** Returns true, if the Right-to-Left layout mode is active. */
IsRTL() const297     bool                 IsRTL() const { return mrData.mbAppRTL; }
298 
299     /** Returns the number of available positions. */
GetPosCount() const300     sal_Int32            GetPosCount() const { return mrData.mnPosCount; }
301     /** Returns the number of visible positions. */
302     sal_Int32                   GetVisPosCount() const;
303     /** Returns the first visible position. */
GetFirstVisPos() const304     sal_Int32            GetFirstVisPos() const { return mrData.mnPosOffset; }
305     /** Returns the last visible position. */
GetLastVisPos() const306     sal_Int32            GetLastVisPos() const { return GetFirstVisPos() + GetVisPosCount(); }
307     /** Returns highest possible position for first visible character. */
308     sal_Int32                   GetMaxPosOffset() const;
309 
310     /** Returns true, if it is allowed to set a split at nPos. */
311     bool                        IsValidSplitPos( sal_Int32 nPos ) const;
312     /** Returns true, if nPos is an allowed AND visible split position. */
313     bool                        IsVisibleSplitPos( sal_Int32 nPos ) const;
314 
315     /** Returns the width of the header column. */
GetHdrWidth() const316     sal_Int32            GetHdrWidth() const { return mrData.mnHdrWidth; }
317     /** Returns the width of one character column. */
GetCharWidth() const318     sal_Int32            GetCharWidth() const { return mrData.mnCharWidth; }
319     /** Returns the start position of the header column. */
320     sal_Int32                   GetHdrX() const;
321     /** Returns the X position of the first pixel of the data area. */
322     sal_Int32                   GetFirstX() const;
323     /** Returns the X position of the last pixel of the data area. */
324     sal_Int32                   GetLastX() const;
325     /** Returns output X coordinate of the specified position. */
326     sal_Int32                   GetX( sal_Int32 nPos ) const;
327     /** Returns position from output coordinate. */
328     sal_Int32                   GetPosFromX( sal_Int32 nX ) const;
329 
330     /** Returns the number of data lines. */
GetLineCount() const331     sal_Int32            GetLineCount() const { return mrData.mnLineCount; }
332     /** Returns the number of visible lines (including partly visible bottom line). */
333     sal_Int32                   GetVisLineCount() const;
334     /** Returns index of first visible line. */
GetFirstVisLine() const335     sal_Int32            GetFirstVisLine() const { return mrData.mnLineOffset; }
336     /** Returns index of last visible line. */
337     sal_Int32                   GetLastVisLine() const;
338     /** Returns highest possible index for first line. */
339     sal_Int32                   GetMaxLineOffset() const;
340 
341     /** Returns true, if nLine is a valid line index. */
342     bool                        IsValidLine( sal_Int32 nLine ) const;
343     /** Returns true, if nLine is a valid and visible line index. */
344     bool                        IsVisibleLine( sal_Int32 nLine ) const;
345 
346     /** Returns the height of the header line. */
GetHdrHeight() const347     sal_Int32            GetHdrHeight() const { return mrData.mnHdrHeight; }
348     /** Returns the height of one line. */
GetLineHeight() const349     sal_Int32            GetLineHeight() const { return mrData.mnLineHeight; }
350     /** Returns output Y coordinate of the specified line. */
351     sal_Int32                   GetY( sal_Int32 nLine ) const;
352     /** Returns line index from output coordinate. */
353     sal_Int32                   GetLineFromY( sal_Int32 nY ) const;
354 
355     /** Returns the ruler cursor position. */
GetRulerCursorPos() const356     sal_Int32            GetRulerCursorPos() const { return mrData.mnPosCursor; }
357     /** Returns the data grid cursor position (not column index!). */
GetGridCursorPos() const358     sal_Int32            GetGridCursorPos() const { return mrData.mnColCursor; }
359 
360     // static helpers ---------------------------------------------------------
361 
362     /** Inverts a rectangle in the specified output device. */
363     static void                 ImplInvertRect( OutputDevice& rOutDev, const tools::Rectangle& rRect );
364 
365     /** Returns direction code for the keys LEFT, RIGHT, HOME, END.
366         @param bHomeEnd  false = ignore HOME and END key. */
367     static ScMoveMode           GetHorzDirection( sal_uInt16 nCode, bool bHomeEnd );
368     /** Returns direction code for the keys UP, DOWN, HOME, END, PAGE UP, PAGE DOWN.
369         @param bHomeEnd  false = ignore HOME and END key. */
370     static ScMoveMode           GetVertDirection( sal_uInt16 nCode, bool bHomeEnd );
371 };
372 
373 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
374