Version 5.4.3.2, tag libreoffice-5.4.3.2
[LibreOffice.git] / include / svx / gridctrl.hxx
blob5a49a5835255256f09552ca29713d12b80b2cd7c
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/.
9 * This file incorporates work covered by the following license notice:
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 .
19 #ifndef INCLUDED_SVX_GRIDCTRL_HXX
20 #define INCLUDED_SVX_GRIDCTRL_HXX
22 #include <com/sun/star/sdbc/XRowSet.hpp>
23 #include <com/sun/star/sdbc/XRowSetListener.hpp>
24 #include <com/sun/star/sdb/XRowsChangeListener.hpp>
25 #include <com/sun/star/beans/PropertyChangeEvent.hpp>
26 #include <com/sun/star/util/XNumberFormatter.hpp>
27 #include <com/sun/star/util/Date.hpp>
28 #include <com/sun/star/container/XIndexAccess.hpp>
29 #include <vcl/fixed.hxx>
30 #include <vcl/field.hxx>
32 #include <vcl/button.hxx>
33 #include <tools/ref.hxx>
34 #include <svtools/editbrowsebox.hxx>
35 #include <osl/mutex.hxx>
36 #include <comphelper/propmultiplex.hxx>
37 #include <svtools/transfer.hxx>
38 #include <svx/svxdllapi.h>
39 #include <o3tl/typed_flags_set.hxx>
40 #include <vector>
42 class DbGridControl;
43 class CursorWrapper;
45 bool CompareBookmark(const css::uno::Any& aLeft, const css::uno::Any& aRight);
47 namespace svxform
49 class DataColumn;
52 enum class GridRowStatus
54 Clean,
55 Modified,
56 Deleted,
57 Invalid
61 // DbGridRow, description of rows
64 class DbGridRow : public SvRefBase
66 css::uno::Any m_aBookmark; // Bookmark of the row, can be set
67 ::std::vector< ::svxform::DataColumn* >
68 m_aVariants;
69 GridRowStatus m_eStatus;
70 bool m_bIsNew;
71 // row is no longer valid
72 // is removed on the next positioning
73 public:
74 DbGridRow():m_eStatus(GridRowStatus::Clean), m_bIsNew(true) { }
75 DbGridRow(CursorWrapper* pCur, bool bPaintCursor);
76 void SetState(CursorWrapper* pCur, bool bPaintCursor);
78 virtual ~DbGridRow() override;
80 bool HasField(sal_uInt32 nPos) const { return nPos < m_aVariants.size(); }
81 const ::svxform::DataColumn& GetField(sal_uInt32 nPos) const { return *m_aVariants[ nPos ]; }
83 void SetStatus(GridRowStatus _eStat) { m_eStatus = _eStat; }
84 GridRowStatus GetStatus() const { return m_eStatus; }
85 void SetNew(bool _bNew) { m_bIsNew = _bNew; }
86 bool IsNew() const { return m_bIsNew; }
88 const css::uno::Any& GetBookmark() const { return m_aBookmark; }
90 bool IsValid() const { return m_eStatus == GridRowStatus::Clean || m_eStatus == GridRowStatus::Modified; }
91 bool IsModified() const { return m_eStatus == GridRowStatus::Modified; }
94 typedef tools::SvRef<DbGridRow> DbGridRowRef;
97 // DbGridControl
99 class DbGridColumn;
100 typedef ::std::vector< DbGridColumn* > DbGridColumns;
103 class FmGridListener
105 public:
106 virtual void selectionChanged() = 0;
107 virtual void columnChanged() = 0;
109 protected:
110 ~FmGridListener() {}
113 #define GRID_COLUMN_NOT_FOUND SAL_MAX_UINT16
116 // InitWindowFacet, describing which aspect of a column's Window to (re-)initialize
118 enum class InitWindowFacet
120 Font = 0x01,
121 Foreground = 0x02,
122 Background = 0x04,
123 WritingMode = 0x08,
124 All = 0x0F
126 namespace o3tl
128 template<> struct typed_flags<InitWindowFacet> : is_typed_flags<InitWindowFacet, 0x0f> {};
132 // these options are or'ed and indicate, which of the single
133 // features can be released, default is readonly which means 0
134 enum class DbGridControlOptions
136 Readonly = 0x00,
137 Insert = 0x01,
138 Update = 0x02,
139 Delete = 0x04
141 namespace o3tl
143 template<> struct typed_flags<DbGridControlOptions> : is_typed_flags<DbGridControlOptions, 0x07> {};
146 // StatusIds for Controls of the Bar
147 // important for invalidation
148 enum class DbGridControlNavigationBarState
150 NONE,
151 Text,
152 Absolute,
154 Count,
155 First,
156 Next,
157 Prev,
158 Last,
159 New,
160 Undo // related to SID_FM_RECORD_UNDO
163 class FmXGridSourcePropListener;
164 class DisposeListenerGridBridge;
165 class SVX_DLLPUBLIC DbGridControl : public svt::EditBrowseBox
167 friend class FmXGridSourcePropListener;
168 friend class GridFieldValueListener;
169 friend class DisposeListenerGridBridge;
171 public:
173 // NavigationBar
175 class NavigationBar: public Control
177 class AbsolutePos : public NumericField
179 public:
180 AbsolutePos(vcl::Window* pParent, WinBits nStyle);
182 virtual void KeyInput(const KeyEvent& rEvt) override;
183 virtual void LoseFocus() override;
186 friend class NavigationBar::AbsolutePos;
188 // zusaetzliche Controls
189 VclPtr<FixedText> m_aRecordText;
190 VclPtr<AbsolutePos> m_aAbsolute; // absolute positioning
191 VclPtr<FixedText> m_aRecordOf;
192 VclPtr<FixedText> m_aRecordCount;
194 VclPtr<ImageButton> m_aFirstBtn; // ImageButton for 'go to the first record'
195 VclPtr<ImageButton> m_aPrevBtn; // ImageButton for 'go to the previous record'
196 VclPtr<ImageButton> m_aNextBtn; // ImageButton for 'go to the next record'
197 VclPtr<ImageButton> m_aLastBtn; // ImageButton for 'go to the last record'
198 VclPtr<ImageButton> m_aNewBtn; // ImageButton for 'go to a new record'
199 sal_Int32 m_nCurrentPos;
201 bool m_bPositioning; // protect PositionDataSource against recursion
203 public:
204 NavigationBar(vcl::Window* pParent);
205 virtual ~NavigationBar() override;
206 virtual void dispose() override;
208 // Status methods for Controls
209 void InvalidateAll(sal_Int32 nCurrentPos, bool bAll = false);
210 void InvalidateState(DbGridControlNavigationBarState nWhich) {SetState(nWhich);}
211 void SetState(DbGridControlNavigationBarState nWhich);
212 bool GetState(DbGridControlNavigationBarState nWhich) const;
213 sal_uInt16 ArrangeControls();
215 protected:
216 virtual void Resize() override;
217 virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override;
218 virtual void StateChanged( StateChangedType nType ) override;
220 private:
221 DECL_LINK(OnClick, Button*, void);
223 void PositionDataSource(sal_Int32 nRecord);
226 friend class DbGridControl::NavigationBar;
228 private:
229 Link<DbGridControlNavigationBarState,int> m_aMasterStateProvider;
230 Link<DbGridControlNavigationBarState,bool> m_aMasterSlotExecutor;
232 css::uno::Reference< css::util::XNumberFormatter > m_xFormatter;
233 css::uno::Reference< css::uno::XComponentContext > m_xContext;
235 DbGridColumns m_aColumns; // Column description
236 VclPtr<NavigationBar> m_aBar;
237 DbGridRowRef m_xDataRow; // Row which can be modified
238 // comes from the data cursor
239 DbGridRowRef m_xSeekRow, // Row to which the iterator can set
240 // comes from the data cursor
242 m_xEmptyRow; // record set to insert
244 ImplSVEvent * m_nAsynAdjustEvent;
246 // if we modify the row for the new record, we automatically insert a "new new row".
247 // But if somebody else inserts a new record into the data source, we have to do the same.
248 // For that reason we have to listen to some properties of our data source.
249 rtl::Reference<::comphelper::OPropertyChangeMultiplexer> m_pDataSourcePropMultiplexer;
250 FmXGridSourcePropListener* m_pDataSourcePropListener;
251 css::uno::Reference< css::sdb::XRowsChangeListener>
252 m_xRowSetListener; // get notification when rows were changed
254 void* m_pFieldListeners;
255 // property listeners for field values
257 DisposeListenerGridBridge* m_pCursorDisposeListener;
258 // need to know about the diposing of the seek cursor
259 // construct analogous to the data source proplistener/multiplexer above :
260 // DisposeListenerGridBridge is a bridge from FmXDisposeListener which I don't want to be derived from
262 FmGridListener* m_pGridListener;
264 protected:
265 CursorWrapper* m_pDataCursor; // Cursor for Updates
266 CursorWrapper* m_pSeekCursor; // Cursor for Seeking
268 private:
269 // iteration variables
270 DbGridRowRef m_xCurrentRow;
271 DbGridRowRef m_xPaintRow; // Row to be displayed
272 sal_Int32 m_nSeekPos; // Position of the SeekCursor
273 sal_Int32 m_nTotalCount; // is set when the data cursor finished counting the
274 // records. Initial value is -1
275 osl::Mutex m_aDestructionSafety;
276 osl::Mutex m_aAdjustSafety;
278 css::util::Date
279 m_aNullDate; // NullDate of the Numberformatter;
281 BrowserMode m_nMode;
282 sal_Int32 m_nCurrentPos; // Current position;
283 ImplSVEvent * m_nDeleteEvent; // EventId for asychronous deletion of rows
284 DbGridControlOptions m_nOptions; // What is the able to do (Insert, Update, Delete)
285 // default readonly
286 DbGridControlOptions m_nOptionMask; // the mask of options to be enabled in setDataSource
287 // (with respect to the data source capabilities)
288 // defaults to (insert | update | delete)
289 sal_uInt16 m_nLastColId;
290 long m_nLastRowId;
292 bool m_bDesignMode : 1; // default = sal_False
293 bool m_bRecordCountFinal : 1;
294 bool m_bNavigationBar : 1;
296 bool m_bSynchDisplay : 1;
297 bool m_bHandle : 1;
298 bool m_bFilterMode : 1;
299 bool m_bWantDestruction : 1;
300 bool m_bInAdjustDataSource : 1;
301 bool m_bPendingAdjustRows : 1; // if an async adjust is pending, is it for AdjustRows or AdjustDataSource ?
302 bool m_bHideScrollbars : 1;
304 protected:
305 bool m_bUpdating : 1; // are any updates being executed right now?
307 protected:
308 virtual bool SeekRow(long nRow) override;
309 virtual void VisibleRowsChanged( long nNewTopRow, sal_uInt16 nNumRows) override;
310 virtual void PaintCell(OutputDevice& rDev, const tools::Rectangle& rRect, sal_uInt16 nColId) const override;
311 virtual RowStatus GetRowStatus(long nRow) const override;
312 virtual bool CursorMoving(long nNewRow, sal_uInt16 nNewCol) override;
313 virtual void CursorMoved() override;
314 virtual void ArrangeControls(sal_uInt16& nX, sal_uInt16 nY) override;
315 virtual sal_uInt32 GetTotalCellWidth(long nRow, sal_uInt16 nColId) override;
316 virtual void Command(const CommandEvent& rEvt) override;
317 virtual bool PreNotify(NotifyEvent& rEvt) override;
318 virtual void KeyInput(const KeyEvent& rEvt) override;
319 virtual void StateChanged( StateChangedType nType ) override;
320 virtual void DataChanged( const DataChangedEvent& rDCEvt ) override;
321 virtual void Select() override;
323 virtual ::svt::CellController* GetController(long nRow, sal_uInt16 nCol) override;
325 virtual void CellModified() override;
326 virtual bool SaveModified() override;
327 virtual bool IsModified() const override;
329 virtual sal_uInt16 AppendColumn(const OUString& rName, sal_uInt16 nWidth, sal_uInt16 nPos = HEADERBAR_APPEND, sal_uInt16 nId = (sal_uInt16)-1) override;
330 void RemoveColumn(sal_uInt16 nId);
331 DbGridColumn* CreateColumn(sal_uInt16 nId) const;
332 virtual void ColumnMoved(sal_uInt16 nId) override;
333 virtual bool SaveRow() override;
334 virtual bool IsTabAllowed(bool bForward) const override;
336 /// hide a column
337 virtual void HideColumn(sal_uInt16 nId);
338 /// show a column
339 virtual void ShowColumn(sal_uInt16 nId);
341 /** This is called before executing a context menu for a row. rMenu contains the initial entries
342 handled by this base class' method (which always has to be called).
343 Derived classes may alter the menu in any way and handle any additional entries in
344 PostExecuteColumnContextMenu.
345 All disabled entries will be removed before executing the menu, so be careful with separators
346 near entries you probably wish to disable ...
348 virtual void PreExecuteRowContextMenu(sal_uInt16 nRow, PopupMenu& rMenu);
349 /** After executing the context menu for a row this method is called.
351 virtual void PostExecuteRowContextMenu(sal_uInt16 nRow, const PopupMenu& rMenu, sal_uInt16 nExecutionResult);
353 /// @throws css::uno::RuntimeException
354 void DataSourcePropertyChanged(const css::beans::PropertyChangeEvent& evt);
356 void FieldValueChanged(sal_uInt16 _nId);
357 void FieldListenerDisposing(sal_uInt16 _nId);
359 void disposing(sal_uInt16 _nId);
361 // own overridables
362 /// called when the current row changed
363 virtual void onRowChange();
364 /// called when the current column changed
365 virtual void onColumnChange();
367 // DragSourceHelper overridables
368 virtual void StartDrag( sal_Int8 nAction, const Point& rPosPixel ) override;
370 void executeRowContextMenu( long _nRow, const Point& _rPreferredPos );
372 public:
373 DbGridControl(
374 css::uno::Reference< css::uno::XComponentContext > const & _rxContext,
375 vcl::Window* pParent,
376 WinBits nBits);
378 virtual ~DbGridControl() override;
379 virtual void dispose() override;
381 virtual void Init() override;
382 virtual void InitColumnsByFields(const css::uno::Reference< css::container::XIndexAccess >& xFields) = 0;
383 virtual void RemoveRows() override;
385 /** GetCellText returns the text at the given position
386 @param _nRow
387 the number of the row
388 @param _nColId
389 the ID of the column
390 @return
391 the text out of the cell
393 virtual OUString GetCellText(long _nRow, sal_uInt16 _nColId) const override;
395 void RemoveRows(bool bNewCursor);
397 const css::uno::Reference< css::util::XNumberFormatter >& getNumberFormatter() const {return m_xFormatter;}
399 // the data source
400 // the options can restrict but not extend the update abilities
401 void setDataSource(const css::uno::Reference< css::sdbc::XRowSet >& rCursor,
402 DbGridControlOptions nOpts = DbGridControlOptions::Insert | DbGridControlOptions::Update | DbGridControlOptions::Delete);
403 virtual void Dispatch(sal_uInt16 nId) override;
405 CursorWrapper* getDataSource() const {return m_pDataCursor;}
406 const DbGridColumns& GetColumns() const {return m_aColumns;}
408 void EnableHandle(bool bEnable);
409 bool HasHandle() const {return m_bHandle;}
410 void InsertHandleColumn();
412 // which position does the column with the id in the View have, the handle column doesn't count
413 sal_uInt16 GetViewColumnPos( sal_uInt16 nId ) const { sal_uInt16 nPos = GetColumnPos(nId); return (nPos==BROWSER_INVALIDID) ? GRID_COLUMN_NOT_FOUND : nPos-1; }
415 // which position does the column with the id in m_aColumns have, that means the css::sdbcx::Container
416 // returned from the GetColumns (may be different from the position returned by GetViewColumnPos
417 // if there are hidden columns)
418 sal_uInt16 GetModelColumnPos( sal_uInt16 nId ) const;
420 // the number of columns in the model
421 sal_uInt16 GetViewColCount() const { return ColCount() - 1; }
422 sal_uInt16 GetModelColCount() const { return (sal_uInt16)m_aColumns.size(); }
423 // reverse to GetViewColumnPos: Id of position, the first non-handle column has position 0
424 sal_uInt16 GetColumnIdFromViewPos( sal_uInt16 nPos ) const { return GetColumnId(nPos + 1); }
425 sal_uInt16 GetColumnIdFromModelPos( sal_uInt16 nPos ) const;
427 virtual void SetDesignMode(bool bMode);
428 bool IsDesignMode() const {return m_bDesignMode;}
429 bool IsOpen() const {return m_pSeekCursor != nullptr;}
431 void SetFilterMode(bool bMode);
432 bool IsFilterMode() const {return m_bFilterMode;}
433 bool IsFilterRow(long nRow) const {return m_bFilterMode && nRow == 0;}
435 void EnableNavigationBar(bool bEnable);
436 bool HasNavigationBar() const {return m_bNavigationBar;}
438 DbGridControlOptions GetOptions() const {return m_nOptions;}
439 NavigationBar& GetNavigationBar() {return *m_aBar.get();}
440 DbGridControlOptions SetOptions(DbGridControlOptions nOpt);
441 // The new options are interpreted with respect to the current data source. If it is unable
442 // to update, to insert or to restore, the according options are ignored. If the grid isn't
443 // connected to a data source, all options except OPT_READONLY are ignored.
445 const css::util::Date& getNullDate() const {return m_aNullDate;}
447 // positioning
448 void MoveToPosition(sal_uInt32 nPos);
449 void MoveToFirst();
450 void MoveToNext();
451 void MoveToPrev();
452 void MoveToLast();
453 void AppendNew();
455 // adjustment of the cursors in case the data cursor has been
456 // moved from the outside.
457 // the flag indicates if an adjustment of the row count should be
458 // done as well
459 void AdjustDataSource(bool bFull = false);
460 void Undo();
462 virtual void BeginCursorAction();
463 virtual void EndCursorAction();
465 // is the current line being updated
466 bool IsUpdating() const {return m_bUpdating;}
468 void RowRemoved( long nRow, long nNumRows = 1, bool bDoPaint = true );
469 void RowInserted( long nRow, long nNumRows = 1, bool bDoPaint = true );
470 void RowModified( long nRow );
472 void resetCurrentRow();
474 bool getDisplaySynchron() const { return m_bSynchDisplay; }
475 void setDisplaySynchron(bool bSync);
476 // when set to sal_False, the display is no longer in sync with the current cursor position
477 // (means that in AdjustDataSource we are jumping to a row not belonging to CursorPosition)
478 // when using this, you should know what you are doing, because for example entering data
479 // in a row in the display that is not in sync with the position of the cursor can be very critical
481 const DbGridRowRef& GetCurrentRow() const {return m_xCurrentRow;}
483 void SetStateProvider(const Link<DbGridControlNavigationBarState,int>& rProvider) { m_aMasterStateProvider = rProvider; }
484 // if this link is set the given provider will be asked for the state of my items.
485 // the return values are interpreted as follows :
486 // <0 -> not specified (use default mechanism to determine the state)
487 // ==0 -> the item is disabled
488 // >0 -> the item is enabled
489 void SetSlotExecutor(const Link<DbGridControlNavigationBarState,bool>& rExecutor) { m_aMasterSlotExecutor = rExecutor; }
490 // analogous : if this link is set, all nav-bar slots will be routed through it when executed
491 // if the handler returns nonzero, no further handling of the slot occurs
493 void EnablePermanentCursor(bool bEnable);
494 bool IsPermanentCursorEnabled() const;
496 /** forces both scrollbars to be hidden
498 For the horizontal scrollbar, this is overruled by enabling the navigation bar: A navigation
499 bar <b>always</b> implies a horizontal scroll bar
500 @seealso EnableNavigationBar
502 void ForceHideScrollbars();
504 const css::uno::Reference< css::uno::XComponentContext >&
505 getContext() const { return m_xContext; }
507 /// returns <TRUE/> if the text of the given cell can be copied into the clipboard
508 bool canCopyCellText(sal_Int32 _nRow, sal_uInt16 _nColId);
509 /// copies the text of the given cell into the clipboard
510 void copyCellText(sal_Int32 _nRow, sal_uInt16 _nColId);
512 // select in listener handling
513 void setGridListener( FmGridListener* _pListener ) { m_pGridListener = _pListener; }
515 // helper class to grant access to selected methods from within the DbCellControl class
516 struct GrantControlAccess
518 friend class DbCellControl;
519 friend class RowSetEventListener;
520 protected:
521 GrantControlAccess() { }
524 /// called when a controller needs to be re-initialized
525 void refreshController(sal_uInt16 _nColId, GrantControlAccess _aAccess);
527 CursorWrapper* GetSeekCursor(GrantControlAccess /*_aAccess*/) const { return m_pSeekCursor; }
528 const DbGridRowRef& GetSeekRow(GrantControlAccess /*_aAccess*/) const { return m_xSeekRow; }
529 void SetSeekPos(sal_Int32 nPos,GrantControlAccess /*_aAccess*/) {m_nSeekPos = nPos;}
532 @return
533 The count of additional controls of the control area.
535 virtual sal_Int32 GetAccessibleControlCount() const override;
537 /** Creates the accessible object of an additional control.
538 @param _nIndex
539 The 0-based index of the control.
540 @return
541 The XAccessible interface of the specified control.
543 virtual css::uno::Reference<
544 css::accessibility::XAccessible >
545 CreateAccessibleControl( sal_Int32 _nIndex ) override;
547 // IAccessibleTableProvider
548 /** Creates the accessible object of a data table cell.
549 @param nRow The row index of the cell.
550 @param nColumnId The column ID of the cell.
551 @return The XAccessible interface of the specified cell. */
552 virtual css::uno::Reference<
553 css::accessibility::XAccessible >
554 CreateAccessibleCell( sal_Int32 nRow, sal_uInt16 nColumnId ) override;
556 protected:
557 void RecalcRows(long nNewTopRow, sal_uInt16 nLinesOnScreen, bool bUpdateCursor);
558 bool SeekCursor(long nRow, bool bAbsolute = false);
559 void RemoveColumns(); // cleaning of own structures
560 void AdjustRows();
561 sal_Int32 AlignSeekCursor();
562 bool SetCurrent(long nNewRow);
564 OUString GetCurrentRowCellText(DbGridColumn* pCol,const DbGridRowRef& _rRow) const;
565 virtual void DeleteSelectedRows();
566 static bool IsValid(const DbGridRowRef& _xRow) { return _xRow.is() && _xRow->IsValid(); }
568 // row which is currently being appended
569 bool IsCurrentAppending() const;
571 // empty row for insertion
572 bool IsInsertionRow(long nRow) const;
574 void SetSeekPos(sal_Int32 nPos) {m_nSeekPos = nPos;}
575 sal_Int32 GetCurrentPos() const {return m_nCurrentPos;}
576 sal_Int32 GetSeekPos() const {return m_nSeekPos;}
577 sal_Int32 GetTotalCount() const {return m_nTotalCount;}
579 const DbGridRowRef& GetEmptyRow() const { return m_xEmptyRow; }
580 const DbGridRowRef& GetSeekRow() const { return m_xSeekRow; }
581 const DbGridRowRef& GetPaintRow() const { return m_xPaintRow; }
583 void ConnectToFields();
584 void DisconnectFromFields();
586 void implAdjustInSolarThread(bool _bRows);
587 // calls AdjustRows or AdjustDataSource, synchron if the caller is running in the solar thread, else asynchron
589 protected:
590 void ImplInitWindow( const InitWindowFacet _eInitWhat );
591 DECL_LINK(OnDelete, void*, void);
593 DECL_LINK(OnAsyncAdjust, void*, void);
594 // if the param is != NULL, AdjustRows will be called, else AdjustDataSource
596 private:
597 using BrowseBox::InsertHandleColumn;
600 #endif // INCLUDED_SVX_GRIDCTRL_HXX
602 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */