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 <config_options.h>
23 #include <memory>
24 #include <svtools/svtdllapi.h>
25 #include <tools/ref.hxx>
26 
27 #include <svtools/brwbox.hxx>
28 #include <svtools/brwhead.hxx>
29 #include <tools/lineend.hxx>
30 #include <vcl/InterimItemWindow.hxx>
31 #include <vcl/weldutils.hxx>
32 #include <o3tl/typed_flags_set.hxx>
33 
34 class BrowserDataWin;
35 
36 // EditBrowseBoxFlags (EBBF)
37 enum class EditBrowseBoxFlags
38 {
39     NONE                       = 0x0000,
40 /** if this bit is _not_ set, the handle column will be invalidated upon
41     changing the row in the browse box.  This is for forcing the row picture to
42     be repainted. If you do not have row pictures or text, you don't need this
43     invalidation, then you would specify this bit to prevent flicker
44 */
45     NO_HANDLE_COLUMN_CONTENT   = 0x0001,
46 /** set this bit to activate the cell on a MouseButtonDown, not a MouseButtonUp event
47  */
48     ACTIVATE_ON_BUTTONDOWN     = 0x0002,
49 /** if this bit is set and EditBrowseBoxFlags::NO_HANDLE_COLUMN_CONTENT is _not_ set, the handle
50     column is drawn with the text contained in column 0 instead of an image
51 */
52     HANDLE_COLUMN_TEXT         = 0x0004,
53 
54 /** If this bit is set, tab traveling is somewhat modified<br/>
55     If the control gets the focus because the user pressed the TAB key, then the
56     first or last cell (depending on whether the traveling was cycling forward or backward)
57     gets activated.
58     @see Window::GetGetFocusFlags
59     @see GETFOCUS_*
60 */
61     SMART_TAB_TRAVEL           = 0x0008,
62 
63 };
64 namespace o3tl
65 {
66     template<> struct typed_flags<EditBrowseBoxFlags> : is_typed_flags<EditBrowseBoxFlags, 0x0f> {};
67 }
68 
69 namespace svt
70 {
71     class SVT_DLLPUBLIC CellController : public SvRefBase
72     {
73         friend class EditBrowseBox;
74         Link<LinkParamNone*, void> maModifyHdl;
75 
76         VclPtr<Control>            pWindow;
77         bool                       bSuspended;     // <true> if the window is hidden and disabled
78 
79     public:
80 
81         CellController(Control* pW);
82         virtual ~CellController() override;
83 
GetWindow() const84         Control& GetWindow() const { return *const_cast< CellController* >( this )->pWindow; }
85 
86         virtual void SaveValue() = 0;
87         virtual bool IsValueChangedFromSaved() const = 0;
88 
89         // commit any current changes. Especially, do any reformatting you need (from input formatting
90         // to output formatting) here
91         virtual void CommitModifications();
92 
93         // suspending the controller is not cumulative!
94                 void        suspend( );
95                 void        resume( );
isSuspended() const96         bool        isSuspended( ) const { return bSuspended; }
97 
98     protected:
99         virtual bool MoveAllowed(const KeyEvent& rEvt) const;
SetModifyHdl(const Link<LinkParamNone *,void> & rLink)100         void SetModifyHdl(const Link<LinkParamNone*,void>& rLink) { maModifyHdl = rLink; }
101         virtual void ActivatingMouseEvent(const BrowserMouseEvent& rEvt, bool bUp);
callModifyHdl()102         virtual void callModifyHdl() { maModifyHdl.Call(nullptr); }
103     };
104 
105     typedef tools::SvRef<CellController> CellControllerRef;
106 
107 
108     //= IEditImplementation
109 
UNLESS_MERGELIBS(SVT_DLLPUBLIC)110     class UNLESS_MERGELIBS(SVT_DLLPUBLIC) IEditImplementation
111     {
112     public:
113         virtual ~IEditImplementation() = 0;
114 
115         virtual Control&            GetControl() = 0;
116 
117         virtual OUString            GetText( LineEnd aSeparator ) const = 0;
118         virtual void                SetText( const OUString& _rStr ) = 0;
119 
120         virtual bool                IsReadOnly() const = 0;
121         virtual void                SetReadOnly( bool bReadOnly ) = 0;
122 
123         virtual sal_Int32           GetMaxTextLen() const = 0;
124         virtual void                SetMaxTextLen( sal_Int32 _nMaxLen ) = 0;
125 
126         virtual Selection           GetSelection() const = 0;
127         virtual void                SetSelection( const Selection& _rSelection ) = 0;
128 
129         virtual void                ReplaceSelected( const OUString& _rStr ) = 0;
130         virtual OUString            GetSelected( LineEnd aSeparator ) const = 0;
131 
132         virtual bool                IsValueChangedFromSaved() const = 0;
133         virtual void                SaveValue() = 0;
134 
135         virtual bool                CanUp() const = 0;
136         virtual bool                CanDown() const = 0;
137 
138         virtual void                Cut() = 0;
139         virtual void                Copy() = 0;
140         virtual void                Paste() = 0;
141 
142         // sets a link to call when the text is changed by the user
143         void SetModifyHdl(const Link<LinkParamNone*,void>& rLink)
144         {
145             m_aModify1Hdl = rLink;
146         }
147 
148         // sets an additional link to call when the text is changed by the user
149         void SetAuxModifyHdl(const Link<LinkParamNone*,void>& rLink)
150         {
151             m_aModify2Hdl = rLink;
152         }
153 
154     private:
155         Link<LinkParamNone*,void> m_aModify1Hdl;
156         Link<LinkParamNone*,void> m_aModify2Hdl;
157 
158     protected:
159         void CallModifyHdls()
160         {
161             m_aModify1Hdl.Call(nullptr);
162             m_aModify2Hdl.Call(nullptr);
163         }
164     };
165 
166     class SVT_DLLPUBLIC ControlBase : public InterimItemWindow
167     {
168     public:
169         ControlBase(BrowserDataWin* pParent, const OUString& rUIXMLDescription, const OString& rID);
170 
171         virtual void SetEditableReadOnly(bool bReadOnly);
172 
173         virtual bool ProcessKey(const KeyEvent& rKEvt);
174 
175         virtual void SetPointFont(const vcl::Font& rFont) = 0;
176 
177         // chain after the FocusInHdl
178         void SetFocusInHdl(const Link<LinkParamNone*,void>& rHdl)
179         {
180             m_aFocusInHdl = rHdl;
181         }
182 
183         // chain after the FocusOutHdl
184         void SetFocusOutHdl(const Link<LinkParamNone*,void>& rHdl)
185         {
186             m_aFocusOutHdl = rHdl;
187         }
188 
189         void SetMousePressHdl(const Link<const MouseEvent&,void>& rHdl)
190         {
191             m_aMousePressHdl = rHdl;
192         }
193 
194         void SetMouseReleaseHdl(const Link<const MouseEvent&,void>& rHdl)
195         {
196             m_aMouseReleaseHdl = rHdl;
197         }
198 
199         void SetMouseMoveHdl(const Link<const MouseEvent&,void>& rHdl)
200         {
201             m_aMouseMoveHdl = rHdl;
202         }
203 
204     protected:
205         DECL_LINK(KeyInputHdl, const KeyEvent&, bool);
206         DECL_LINK(FocusInHdl, weld::Widget&, void);
207         DECL_LINK(FocusOutHdl, weld::Widget&, void);
208         DECL_LINK(MousePressHdl, const MouseEvent&, bool);
209         DECL_LINK(MouseReleaseHdl, const MouseEvent&, bool);
210         DECL_LINK(MouseMoveHdl, const MouseEvent&, bool);
211     private:
212         Link<LinkParamNone*,void> m_aFocusInHdl;
213         Link<LinkParamNone*,void> m_aFocusOutHdl;
214         Link<const MouseEvent&,void> m_aMousePressHdl;
215         Link<const MouseEvent&,void> m_aMouseReleaseHdl;
216         Link<const MouseEvent&,void> m_aMouseMoveHdl;
217     };
218 
219     class SVT_DLLPUBLIC EditControlBase : public ControlBase
220     {
221     public:
222         EditControlBase(BrowserDataWin* pParent);
223 
224         virtual void SetEditableReadOnly(bool bReadOnly) override
225         {
226             m_pEntry->set_editable(!bReadOnly);
227         }
228 
229         virtual void SetPointFont(const vcl::Font& rFont) override
230         {
231             m_pEntry->set_font(rFont);
232         }
233 
234         virtual void dispose() override;
235 
236         weld::Entry& get_widget() { return *m_pEntry; }
237 
238         virtual void connect_changed(const Link<weld::Entry&, void>& rLink) = 0;
239         virtual void connect_focus_out(const Link<weld::Widget&, void>& rLink) = 0;
240 
241     protected:
242         void InitEditControlBase(weld::Entry* pEntry);
243 
244     private:
245         weld::Entry* m_pEntry;
246     };
247 
248     class SVT_DLLPUBLIC EditControl : public EditControlBase
249     {
250     public:
251         EditControl(BrowserDataWin* pParent);
252 
253         virtual void dispose() override;
254 
255         virtual void connect_changed(const Link<weld::Entry&, void>& rLink) override
256         {
257             m_xWidget->connect_changed(rLink);
258         }
259 
260         virtual void connect_focus_out(const Link<weld::Widget&, void>& rLink) override
261         {
262             m_xWidget->connect_focus_out(rLink);
263         }
264 
265     protected:
266         std::unique_ptr<weld::Entry> m_xWidget;
267     };
268 
269     class SVT_DLLPUBLIC EntryImplementation : public IEditImplementation
270     {
271         EditControlBase& m_rEdit;
272         int m_nMaxTextLen;
273 
274         DECL_LINK(ModifyHdl, weld::Entry&, void);
275     public:
276         EntryImplementation(EditControlBase& rEdit)
277             : m_rEdit(rEdit)
278             , m_nMaxTextLen(0)
279         {
280             m_rEdit.connect_changed(LINK(this, EntryImplementation, ModifyHdl));
281         }
282 
283         virtual Control& GetControl() override
284         {
285             return m_rEdit;
286         }
287 
288         virtual OUString GetText( LineEnd /*aSeparator*/ ) const override
289         {
290             // ignore the line end - this base implementation does not support it
291             return m_rEdit.get_widget().get_text();
292         }
293 
294         virtual void SetText( const OUString& _rStr ) override
295         {
296             return m_rEdit.get_widget().set_text(_rStr);
297         }
298 
299         virtual bool IsReadOnly() const override
300         {
301             return !m_rEdit.get_widget().get_editable();
302         }
303 
304         virtual void SetReadOnly( bool bReadOnly ) override
305         {
306             m_rEdit.SetEditableReadOnly(bReadOnly);
307         }
308 
309         virtual sal_Int32 GetMaxTextLen() const override
310         {
311             return m_nMaxTextLen;
312         }
313 
314         virtual void SetMaxTextLen( sal_Int32 nMaxLen ) override
315         {
316             m_nMaxTextLen = nMaxLen;
317             m_rEdit.get_widget().set_max_length(m_nMaxTextLen);
318         }
319 
320         virtual Selection GetSelection() const override
321         {
322             int nStartPos, nEndPos;
323             m_rEdit.get_widget().get_selection_bounds(nStartPos, nEndPos);
324             return Selection(nStartPos, nEndPos);
325         }
326 
327         virtual void SetSelection( const Selection& rSelection ) override
328         {
329             auto nMin = rSelection.Min();
330             auto nMax = rSelection.Max();
331             m_rEdit.get_widget().select_region(nMin < 0 ? 0 : nMin, nMax == SELECTION_MAX ? -1 : nMax);
332         }
333 
334         virtual void ReplaceSelected( const OUString& rStr ) override
335         {
336             m_rEdit.get_widget().replace_selection(rStr);
337         }
338 
339         virtual OUString GetSelected( LineEnd /*aSeparator*/ ) const override
340             // ignore the line end - this base implementation does not support it
341         {
342             int nStartPos, nEndPos;
343             weld::Entry& rEntry = m_rEdit.get_widget();
344             rEntry.get_selection_bounds(nStartPos, nEndPos);
345             return rEntry.get_text().copy(nStartPos, nEndPos - nStartPos);
346         }
347 
348         virtual bool IsValueChangedFromSaved() const override
349         {
350             return m_rEdit.get_widget().get_value_changed_from_saved();
351         }
352 
353         virtual void SaveValue() override
354         {
355             m_rEdit.get_widget().save_value();
356         }
357 
358         virtual bool CanUp() const override
359         {
360             return false;
361         }
362 
363         virtual bool CanDown() const override
364         {
365             return false;
366         }
367 
368         virtual void Cut() override
369         {
370             m_rEdit.get_widget().cut_clipboard();
371         }
372 
373         virtual void Copy() override
374         {
375             m_rEdit.get_widget().copy_clipboard();
376         }
377 
378         virtual void Paste() override
379         {
380             m_rEdit.get_widget().paste_clipboard();
381         }
382     };
383 
384     //= MultiLineTextCell
385 
386     /** a multi line edit which can be used in a cell of an EditBrowseBox
387     */
388     class UNLESS_MERGELIBS(SVT_DLLPUBLIC) MultiLineTextCell final : public ControlBase
389     {
390     public:
391         MultiLineTextCell(BrowserDataWin* pParent);
392 
393         virtual void SetEditableReadOnly(bool bReadOnly) override
394         {
395             m_xWidget->set_editable(!bReadOnly);
396         }
397 
398         virtual void SetPointFont(const vcl::Font& rFont) override
399         {
400             m_xWidget->set_font(rFont);
401         }
402 
403         virtual void GetFocus() override;
404 
405         virtual void dispose() override;
406 
407         void connect_changed(const Link<weld::TextView&, void>& rLink)
408         {
409             m_xWidget->connect_changed(rLink);
410         }
411 
412         weld::TextView& get_widget() { return *m_xWidget; }
413 
414     private:
415         std::unique_ptr<weld::TextView> m_xWidget;
416 
417         virtual bool ProcessKey(const KeyEvent& rKEvt) override;
418     };
419 
420     class SVT_DLLPUBLIC MultiLineEditImplementation : public IEditImplementation
421     {
422         MultiLineTextCell& m_rEdit;
423         int m_nMaxTextLen;
424 
425         DECL_LINK(ModifyHdl, weld::TextView&, void);
426     public:
427         MultiLineEditImplementation(MultiLineTextCell& rEdit)
428             : m_rEdit(rEdit)
429             , m_nMaxTextLen(0)
430         {
431             m_rEdit.connect_changed(LINK(this, MultiLineEditImplementation, ModifyHdl));
432         }
433 
434         virtual Control& GetControl() override
435         {
436             return m_rEdit;
437         }
438 
439         virtual OUString GetText(LineEnd aSeparator) const override;
440 
441         virtual void SetText(const OUString& rStr) override
442         {
443             return m_rEdit.get_widget().set_text(rStr);
444         }
445 
446         virtual bool IsReadOnly() const override
447         {
448             return !m_rEdit.get_widget().get_editable();
449         }
450 
451         virtual void SetReadOnly( bool bReadOnly ) override
452         {
453             m_rEdit.SetEditableReadOnly(bReadOnly);
454         }
455 
456         virtual sal_Int32 GetMaxTextLen() const override
457         {
458             return m_nMaxTextLen;
459         }
460 
461         virtual void SetMaxTextLen( sal_Int32 nMaxLen ) override
462         {
463             m_nMaxTextLen = nMaxLen;
464             m_rEdit.get_widget().set_max_length(m_nMaxTextLen);
465         }
466 
467         virtual Selection GetSelection() const override
468         {
469             int nStartPos, nEndPos;
470             m_rEdit.get_widget().get_selection_bounds(nStartPos, nEndPos);
471             return Selection(nStartPos, nEndPos);
472         }
473 
474         virtual void SetSelection( const Selection& rSelection ) override
475         {
476             auto nMin = rSelection.Min();
477             auto nMax = rSelection.Max();
478             m_rEdit.get_widget().select_region(nMin < 0 ? 0 : nMin, nMax == SELECTION_MAX ? -1 : nMax);
479         }
480 
481         virtual void ReplaceSelected( const OUString& rStr ) override
482         {
483             m_rEdit.get_widget().replace_selection(rStr);
484         }
485 
486         virtual OUString GetSelected( LineEnd aSeparator ) const override;
487 
488         virtual bool IsValueChangedFromSaved() const override
489         {
490             return m_rEdit.get_widget().get_value_changed_from_saved();
491         }
492 
493         virtual void SaveValue() override
494         {
495             m_rEdit.get_widget().save_value();
496         }
497 
498         virtual bool CanUp() const override
499         {
500             return m_rEdit.get_widget().can_move_cursor_with_up();
501         }
502 
503         virtual bool CanDown() const override
504         {
505             return m_rEdit.get_widget().can_move_cursor_with_down();
506         }
507 
508         virtual void Cut() override
509         {
510             m_rEdit.get_widget().cut_clipboard();
511         }
512 
513         virtual void Copy() override
514         {
515             m_rEdit.get_widget().copy_clipboard();
516         }
517 
518         virtual void Paste() override
519         {
520             m_rEdit.get_widget().paste_clipboard();
521         }
522     };
523 
524 
525     //= EditCellController
526     class SVT_DLLPUBLIC EditCellController : public CellController
527     {
528         IEditImplementation*    m_pEditImplementation;
529         bool                    m_bOwnImplementation;   // did we create m_pEditImplementation?
530 
531     public:
532         EditCellController( EditControlBase* _pEdit );
533         EditCellController( IEditImplementation* _pImplementation );
534         virtual ~EditCellController( ) override;
535 
536         const IEditImplementation* GetEditImplementation( ) const { return m_pEditImplementation; }
537               IEditImplementation* GetEditImplementation( )       { return m_pEditImplementation; }
538 
539         virtual bool IsValueChangedFromSaved() const override;
540         virtual void SaveValue() override;
541 
542         void Modify()
543         {
544             ModifyHdl(nullptr);
545         }
546 
547     protected:
548         virtual bool MoveAllowed(const KeyEvent& rEvt) const override;
549     private:
550         DECL_LINK(ModifyHdl, LinkParamNone*, void);
551     };
552 
553     //= CheckBoxControl
554     class SVT_DLLPUBLIC CheckBoxControl final : public ControlBase
555     {
556         std::unique_ptr<weld::CheckButton> m_xBox;
557         weld::TriStateEnabled m_aModeState;
558         Link<weld::CheckButton&,void> m_aToggleLink;
559         Link<LinkParamNone*,void> m_aModify1Hdl;
560         Link<LinkParamNone*,void> m_aModify2Hdl;
561 
562     public:
563         CheckBoxControl(BrowserDataWin* pParent);
564         virtual ~CheckBoxControl() override;
565         virtual void dispose() override;
566 
567         virtual void SetPointFont(const vcl::Font& rFont) override;
568 
569         void SetToggleHdl(const Link<weld::CheckButton&,void>& rHdl) {m_aToggleLink = rHdl;}
570 
571         // sets a link to call when the text is changed by the user
572         void SetModifyHdl(const Link<LinkParamNone*,void>& rHdl)
573         {
574             m_aModify1Hdl = rHdl;
575         }
576 
577         // sets an additional link to call when the text is changed by the user
578         void SetAuxModifyHdl(const Link<LinkParamNone*,void>& rLink)
579         {
580             m_aModify2Hdl = rLink;
581         }
582 
583         void SetState(TriState eState);
584         TriState GetState() const { return m_xBox->get_state(); }
585 
586         void EnableTriState(bool bTriState);
587 
588         weld::CheckButton&   GetBox() {return *m_xBox;};
589 
590         // for pseudo-click when initially clicking in a cell activates
591         // the cell and performs a state change on the button as if
592         // it was clicked on
593         void Clicked();
594 
595     private:
596         DECL_LINK(OnToggle, weld::Toggleable&, void);
597 
598         void CallModifyHdls()
599         {
600             m_aModify1Hdl.Call(nullptr);
601             m_aModify2Hdl.Call(nullptr);
602         }
603     };
604 
605     //= CheckBoxCellController
606     class SVT_DLLPUBLIC CheckBoxCellController final : public CellController
607     {
608     public:
609 
610         CheckBoxCellController(CheckBoxControl* pWin);
611         weld::CheckButton& GetCheckBox() const;
612 
613         virtual bool IsValueChangedFromSaved() const override;
614         virtual void SaveValue() override;
615 
616     private:
617         virtual void ActivatingMouseEvent(const BrowserMouseEvent& rEvt, bool bUp) override;
618         DECL_LINK(ModifyHdl, LinkParamNone*, void);
619     };
620 
621     //= ComboBoxControl
622     class SVT_DLLPUBLIC ComboBoxControl final : public ControlBase
623     {
624     private:
625         std::unique_ptr<weld::ComboBox> m_xWidget;
626         Link<LinkParamNone*,void> m_aModify1Hdl;
627         Link<bool,void> m_aModify2Hdl;
628 
629         friend class ComboBoxCellController;
630 
631     public:
632         ComboBoxControl(BrowserDataWin* pParent);
633 
634         virtual void SetPointFont(const vcl::Font& rFont) override;
635 
636         virtual void SetEditableReadOnly(bool bReadOnly) override
637         {
638             m_xWidget->set_entry_editable(!bReadOnly);
639         }
640 
641         weld::ComboBox& get_widget() { return *m_xWidget; }
642 
643         // sets a link to call when the selection is changed by the user
644         void SetModifyHdl(const Link<LinkParamNone*,void>& rHdl)
645         {
646             m_aModify1Hdl = rHdl;
647         }
648 
649         // sets an additional link to call when the selection is changed by the user
650         // bool arg is true when triggered interactively by the user
651         void SetAuxModifyHdl(const Link<bool,void>& rLink)
652         {
653             m_aModify2Hdl = rLink;
654         }
655 
656         void TriggerAuxModify()
657         {
658             m_aModify2Hdl.Call(false);
659         }
660 
661         virtual void dispose() override;
662 
663     private:
664         DECL_LINK(SelectHdl, weld::ComboBox&, void);
665 
666         void CallModifyHdls()
667         {
668             m_aModify1Hdl.Call(nullptr);
669             m_aModify2Hdl.Call(true);
670         }
671     };
672 
673     //= ComboBoxCellController
674     class SVT_DLLPUBLIC ComboBoxCellController : public CellController
675     {
676     public:
677 
678         ComboBoxCellController(ComboBoxControl* pParent);
679         weld::ComboBox& GetComboBox() const { return static_cast<ComboBoxControl&>(GetWindow()).get_widget(); }
680 
681         virtual bool IsValueChangedFromSaved() const override;
682         virtual void SaveValue() override;
683 
684     protected:
685         virtual bool MoveAllowed(const KeyEvent& rEvt) const override;
686     private:
687         DECL_LINK(ModifyHdl, LinkParamNone*, void);
688     };
689 
690     //= ListBoxControl
691     class SVT_DLLPUBLIC ListBoxControl final : public ControlBase
692     {
693     private:
694         std::unique_ptr<weld::ComboBox> m_xWidget;
695         Link<LinkParamNone*,void> m_aModify1Hdl;
696         Link<bool,void> m_aModify2Hdl;
697 
698         friend class ListBoxCellController;
699 
700     public:
701         ListBoxControl(BrowserDataWin* pParent);
702 
703         virtual void SetPointFont(const vcl::Font& rFont) override;
704 
705         weld::ComboBox& get_widget() { return *m_xWidget; }
706 
707         // sets a link to call when the selection is changed by the user
708         void SetModifyHdl(const Link<LinkParamNone*,void>& rHdl)
709         {
710             m_aModify1Hdl = rHdl;
711         }
712 
713         // sets an additional link to call when the selection is changed,
714         // bool arg is true when triggered interactively by the user
715         void SetAuxModifyHdl(const Link<bool,void>& rLink)
716         {
717             m_aModify2Hdl = rLink;
718         }
719 
720         void TriggerAuxModify()
721         {
722             m_aModify2Hdl.Call(false);
723         }
724 
725         virtual void dispose() override;
726     private:
727         DECL_LINK(SelectHdl, weld::ComboBox&, void);
728 
729         void CallModifyHdls()
730         {
731             m_aModify1Hdl.Call(nullptr);
732             m_aModify2Hdl.Call(true);
733         }
734     };
735 
736     //= ListBoxCellController
737     class SVT_DLLPUBLIC ListBoxCellController : public CellController
738     {
739     public:
740 
741         ListBoxCellController(ListBoxControl* pParent);
742         weld::ComboBox& GetListBox() const { return static_cast<ListBoxControl&>(GetWindow()).get_widget(); }
743 
744         virtual bool IsValueChangedFromSaved() const override;
745         virtual void SaveValue() override;
746 
747     protected:
748         virtual bool MoveAllowed(const KeyEvent& rEvt) const override;
749     private:
750         DECL_LINK(ListBoxSelectHdl, LinkParamNone*, void);
751     };
752 
753     class SVT_DLLPUBLIC FormattedControlBase : public EditControlBase
754     {
755     public:
756         FormattedControlBase(BrowserDataWin* pParent, bool bSpinVariant);
757 
758         virtual void dispose() override;
759 
760         virtual void connect_changed(const Link<weld::Entry&, void>& rLink) override;
761         virtual void connect_focus_out(const Link<weld::Widget&, void>& rLink) override;
762 
763         weld::EntryFormatter& get_formatter();
764 
765     protected:
766         bool m_bSpinVariant;
767         std::unique_ptr<weld::Entry> m_xEntry;
768         std::unique_ptr<weld::FormattedSpinButton> m_xSpinButton;
769         std::unique_ptr<weld::EntryFormatter> m_xEntryFormatter;
770 
771         void InitFormattedControlBase();
772     };
773 
774     class SVT_DLLPUBLIC FormattedControl : public FormattedControlBase
775     {
776     public:
777         FormattedControl(BrowserDataWin* pParent, bool bSpinVariant);
778     };
779 
780     class SVT_DLLPUBLIC DoubleNumericControl : public FormattedControlBase
781     {
782     public:
783         DoubleNumericControl(BrowserDataWin* pParent, bool bSpinVariant);
784     };
785 
786     class SVT_DLLPUBLIC LongCurrencyControl : public FormattedControlBase
787     {
788     public:
789         LongCurrencyControl(BrowserDataWin* pParent, bool bSpinVariant);
790     };
791 
792     class SVT_DLLPUBLIC TimeControl : public FormattedControlBase
793     {
794     public:
795         TimeControl(BrowserDataWin* pParent, bool bSpinVariant);
796     };
797 
798     class SVT_DLLPUBLIC DateControl : public FormattedControlBase
799     {
800     public:
801         DateControl(BrowserDataWin* pParent, bool bDropDown);
802 
803         void SetDate(const Date& rDate);
804 
805         virtual void dispose() override;
806     private:
807         std::unique_ptr<weld::MenuButton> m_xMenuButton;
808         std::unique_ptr<weld::Builder> m_xCalendarBuilder;
809         std::unique_ptr<weld::Widget> m_xTopLevel;
810         std::unique_ptr<weld::Calendar> m_xCalendar;
811         std::unique_ptr<weld::Widget> m_xExtras;
812         std::unique_ptr<weld::Button> m_xTodayBtn;
813         std::unique_ptr<weld::Button> m_xNoneBtn;
814 
815         DECL_LINK(ToggleHdl, weld::Toggleable&, void);
816         DECL_LINK(ActivateHdl, weld::Calendar&, void);
817         DECL_LINK(ImplClickHdl, weld::Button&, void);
818     };
819 
820     class SVT_DLLPUBLIC PatternControl final : public EditControl
821     {
822     public:
823         PatternControl(BrowserDataWin* pParent);
824 
825         weld::PatternFormatter& get_formatter() { return *m_xEntryFormatter; }
826 
827         virtual void connect_changed(const Link<weld::Entry&, void>& rLink) override;
828         virtual void connect_focus_out(const Link<weld::Widget&, void>& rLink) override;
829 
830         virtual void dispose() override;
831     private:
832         std::unique_ptr<weld::PatternFormatter> m_xEntryFormatter;
833     };
834 
835     //= FormattedFieldCellController
836     class SVT_DLLPUBLIC FormattedFieldCellController final : public EditCellController
837     {
838     public:
839         FormattedFieldCellController( FormattedControlBase* _pFormatted );
840 
841         virtual void CommitModifications() override;
842     };
843 
844     //= EditBrowserHeader
845     class SVT_DLLPUBLIC EditBrowserHeader : public BrowserHeader
846     {
847     public:
848         EditBrowserHeader( BrowseBox* pParent, WinBits nWinBits = WB_BUTTONSTYLE )
849             :BrowserHeader(pParent, nWinBits){}
850 
851     protected:
852         virtual void DoubleClick() override;
853     };
854 
855 
856     //= EditBrowseBox
857     class EditBrowseBoxImpl;
858     class SVT_DLLPUBLIC EditBrowseBox: public BrowseBox
859     {
860         friend class EditBrowserHeader;
861 
862         enum BrowseInfo
863         {
864             COLSELECT   =   1,
865             ROWSELECT   =   2,
866             ROWCHANGE   =   4,
867             COLCHANGE   =   8
868         };
869 
870     public:
871         enum RowStatus
872         {
873             CLEAN               =   0,
874             CURRENT             =   1,
875             CURRENTNEW          =   2,
876             MODIFIED            =   3,
877             NEW                 =   4,
878             DELETED             =   5,
879             PRIMARYKEY          =   6,
880             CURRENT_PRIMARYKEY  =   7,
881             FILTER              =   8,
882             HEADERFOOTER        =   9
883         };
884 
885     private:
886         EditBrowseBox(EditBrowseBox const &) = delete;
887         EditBrowseBox& operator=(EditBrowseBox const &) = delete;
888 
889         class BrowserMouseEventPtr
890         {
891             std::unique_ptr<BrowserMouseEvent> pEvent;
892             bool               bDown;
893 
894         public:
895             BrowserMouseEventPtr()
896                 : bDown(false)
897             {
898             }
899 
900             bool Is() const {return pEvent != nullptr;}
901             bool IsDown() const {return bDown;}
902             const BrowserMouseEvent* operator->() const {return pEvent.get();}
903 
904             SVT_DLLPUBLIC void Clear();
905             void Set(const BrowserMouseEvent* pEvt, bool bIsDown);
906         } aMouseEvent;
907 
908         CellControllerRef        aController,
909                                  aOldController;
910 
911         ImplSVEvent * nStartEvent, * nEndEvent, * nCellModifiedEvent;     // event ids
912         VclPtr<vcl::Window> m_pFocusWhileRequest;
913             // In ActivateCell, we grab the focus asynchronously, but if between requesting activation
914             // and the asynchronous event the focus has changed, we won't grab it for ourself.
915 
916         sal_Int32   nPaintRow;  // row being painted
917         sal_Int32   nEditRow;
918         sal_uInt16  nEditCol;
919 
920         bool            bHasFocus : 1;
921         mutable bool    bPaintStatus : 1;   // paint a status (image) in the handle column
922         bool            bActiveBeforeTracking;
923 
924         VclPtr<CheckBoxControl> pCheckBoxPaint;
925 
926         EditBrowseBoxFlags  m_nBrowserFlags;
927         std::unique_ptr< EditBrowseBoxImpl> m_aImpl;
928 
929     protected:
930         VclPtr<BrowserHeader>  pHeader;
931 
932         BrowserMouseEventPtr& getMouseEvent() { return aMouseEvent; }
933 
934     protected:
935         BrowserHeader*  GetHeaderBar() const {return pHeader;}
936 
937         virtual VclPtr<BrowserHeader> CreateHeaderBar(BrowseBox* pParent) override;
938 
939         // if you want to have an own header ...
940         virtual VclPtr<BrowserHeader> imp_CreateHeaderBar(BrowseBox* pParent);
941 
942         virtual void ColumnMoved(sal_uInt16 nId) override;
943         virtual void ColumnResized(sal_uInt16 nColId) override;
944         virtual void Resize() override;
945         virtual void ArrangeControls(sal_uInt16& nX, sal_uInt16 nY);
946         virtual bool SeekRow(sal_Int32 nRow) override;
947 
948         virtual void GetFocus() override;
949         virtual void LoseFocus() override;
950         virtual void KeyInput(const KeyEvent& rEvt) override;
951         virtual void MouseButtonDown(const BrowserMouseEvent& rEvt) override;
952         virtual void MouseButtonUp(const BrowserMouseEvent& rEvt) override;
953         virtual void StateChanged( StateChangedType nType ) override;
954         virtual void DataChanged( const DataChangedEvent& rDCEvt ) override;
955 
956         using BrowseBox::MouseButtonUp;
957         using BrowseBox::MouseButtonDown;
958 
959         virtual bool PreNotify(NotifyEvent& rNEvt ) override;
960         virtual bool EventNotify(NotifyEvent& rNEvt) override;
961 
962         virtual void EndScroll() override;
963 
964         // should be used instead of GetFieldRectPixel, 'cause this method here takes into account the borders
965         tools::Rectangle GetCellRect(sal_Int32 nRow, sal_uInt16 nColId, bool bRelToBrowser = true) const;
966         virtual sal_uInt32 GetTotalCellWidth(sal_Int32 nRow, sal_uInt16 nColId);
967         sal_uInt32 GetAutoColumnWidth(sal_uInt16 nColId);
968 
969         virtual void PaintStatusCell(OutputDevice& rDev, const tools::Rectangle& rRect) const;
970         virtual void PaintCell(OutputDevice& rDev, const tools::Rectangle& rRect, sal_uInt16 nColId) const = 0;
971 
972         virtual RowStatus GetRowStatus(sal_Int32 nRow) const;
973 
974         virtual void    RowHeightChanged() override;
975 
976         // callbacks for the data window
977         virtual void    ImplStartTracking() override;
978         virtual void    ImplEndTracking() override;
979 
980         // when changing a row:
981         // CursorMoving:    cursor is being moved, but GetCurRow() still provides the old row
982         virtual bool CursorMoving(sal_Int32 nNewRow, sal_uInt16 nNewCol);
983 
984         // cursor has been moved
985         virtual void CursorMoved() override;
986 
987         virtual void CellModified();        // called whenever a cell has been modified
988         virtual bool SaveModified();    // called whenever a cell should be left, and it's content should be saved
989                                             // return sal_False prevents leaving the cell
990         virtual bool SaveRow();         // commit the current row
991 
992         virtual bool IsModified() const {return aController.is() && aController->IsValueChangedFromSaved();}
993 
994         virtual CellController* GetController(sal_Int32 nRow, sal_uInt16 nCol);
995         virtual void InitController(CellControllerRef& rController, sal_Int32 nRow, sal_uInt16 nCol);
996         static void ResizeController(CellControllerRef const & rController, const tools::Rectangle&);
997         virtual void DoubleClick(const BrowserMouseEvent&) override;
998 
999         void ActivateCell() { ActivateCell(GetCurRow(), GetCurColumnId()); }
1000 
1001         // retrieve the image for the row status
1002         Image GetImage(RowStatus) const;
1003 
1004         // inserting columns
1005         // if you don't set a width, this will be calculated automatically
1006         // if the id isn't set the smallest unused will do it ...
1007         virtual sal_uInt16 AppendColumn(const OUString& rName, sal_uInt16 nWidth, sal_uInt16 nPos = HEADERBAR_APPEND, sal_uInt16 nId = sal_uInt16(-1));
1008 
1009         // called whenever (Shift)Tab or Enter is pressed. If true is returned, these keys
1010         // result in traveling to the next or to th previous cell
1011         virtual bool IsTabAllowed(bool bForward) const;
1012 
1013         virtual bool IsCursorMoveAllowed(sal_Int32 nNewRow, sal_uInt16 nNewColId) const override;
1014 
1015         void    PaintTristate(const tools::Rectangle& rRect, const TriState& eState, bool _bEnabled=true) const;
1016 
1017         void AsynchGetFocus();
1018             // secure starting of StartEditHdl
1019 
1020     public:
1021         EditBrowseBox(vcl::Window* pParent, EditBrowseBoxFlags nBrowserFlags, WinBits nBits, BrowserMode nMode = BrowserMode::NONE );
1022         virtual ~EditBrowseBox() override;
1023         virtual void dispose() override;
1024 
1025         bool IsEditing() const {return aController.is();}
1026         void InvalidateStatusCell(sal_Int32 nRow) {RowModified(nRow, 0);}
1027         void InvalidateHandleColumn();
1028 
1029         // late construction
1030         virtual void Init();
1031         virtual void RemoveRows();
1032         virtual void Dispatch(sal_uInt16 nId);
1033 
1034         const CellControllerRef& Controller() const { return aController; }
1035         EditBrowseBoxFlags  GetBrowserFlags() const { return m_nBrowserFlags; }
1036         void                SetBrowserFlags(EditBrowseBoxFlags nFlags);
1037 
1038         virtual void ActivateCell(sal_Int32 nRow, sal_uInt16 nCol, bool bSetCellFocus = true);
1039         virtual void DeactivateCell(bool bUpdate = true);
1040         // Children ---------------------------------------------------------------
1041 
1042         /** @return  The count of additional controls of the control area. */
1043         virtual sal_Int32 GetAccessibleControlCount() const override;
1044 
1045         /** Creates the accessible object of an additional control.
1046             @param nIndex
1047                 The 0-based index of the control.
1048             @return
1049                 The XAccessible interface of the specified control. */
1050         virtual css::uno::Reference< css::accessibility::XAccessible >
1051         CreateAccessibleControl( sal_Int32 nIndex ) override;
1052 
1053         /** Sets focus to current cell of the data table. */
1054         virtual void GrabTableFocus() override;
1055 
1056         virtual tools::Rectangle GetFieldCharacterBounds(sal_Int32 _nRow,sal_Int32 _nColumnPos,sal_Int32 nIndex) override;
1057         virtual sal_Int32 GetFieldIndexAtPoint(sal_Int32 _nRow,sal_Int32 _nColumnPos,const Point& _rPoint) override;
1058 
1059         virtual bool ProcessKey(const KeyEvent& rEvt) override;
1060 
1061         virtual void ChildFocusIn() override;
1062         virtual void ChildFocusOut() override;
1063 
1064         css::uno::Reference< css::accessibility::XAccessible > CreateAccessibleCheckBoxCell(sal_Int32 _nRow, sal_uInt16 _nColumnPos,const TriState& eState);
1065         bool ControlHasFocus() const;
1066     protected:
1067         // creates the accessible which wraps the active cell
1068         void    implCreateActiveAccessible( );
1069 
1070     private:
1071         virtual void PaintField(vcl::RenderContext& rDev, const tools::Rectangle& rRect,
1072                                 sal_uInt16 nColumnId ) const override;
1073         using Control::ImplInitSettings;
1074         SVT_DLLPRIVATE void ImplInitSettings( bool bFont, bool bForeground, bool bBackground );
1075         SVT_DLLPRIVATE void DetermineFocus( const GetFocusFlags _nGetFocusFlags = GetFocusFlags::NONE);
1076         inline void EnableAndShow() const;
1077 
1078         SVT_DLLPRIVATE void implActivateCellOnMouseEvent(const BrowserMouseEvent& _rEvt, bool _bUp);
1079 
1080         DECL_DLLPRIVATE_LINK( ModifyHdl, LinkParamNone*, void );
1081         DECL_DLLPRIVATE_LINK( StartEditHdl, void*, void );
1082         DECL_DLLPRIVATE_LINK( EndEditHdl, void*, void );
1083         DECL_DLLPRIVATE_LINK( CellModifiedHdl, void*, void );
1084     };
1085 
1086 
1087 }   // namespace svt
1088 
1089 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1090