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 #if !defined(VCL_DLLIMPLEMENTATION) && !defined(TOOLKIT_DLLIMPLEMENTATION) && !defined(VCL_INTERNALS)
23 #error "don't use this in new code"
24 #endif
25 
26 #include <vcl/dllapi.h>
27 #include <vcl/image.hxx>
28 #include <vcl/ctrl.hxx>
29 #include <vcl/vclenum.hxx>
30 #include <memory>
31 #include <vector>
32 
33 namespace com::sun::star::frame { struct FeatureStateEvent; }
34 template <class T> class VclPtr;
35 
36 class Color;
37 class ImplCommonButtonData;
38 enum class DrawButtonFlags;
39 
40 class VCL_DLLPUBLIC Button : public Control
41 {
42 private:
43     std::unique_ptr<ImplCommonButtonData> mpButtonData;
44     Link<Button*,void> maClickHdl;
45 
46     /// Command URL (like .uno:Save) in case the button should handle it.
47     OUString maCommand;
48 
49                                     Button (const Button &) = delete;
50                                     Button & operator= (const Button &) = delete;
51 public:
52     SAL_DLLPRIVATE DrawTextFlags    ImplGetTextStyle( WinBits nWinStyle, DrawFlags nDrawFlags );
53     SAL_DLLPRIVATE void             ImplDrawAlignedImage(OutputDevice* pDev, Point& rPos, Size& rSize,
54                                               sal_Int32 nImageSep,
55                                               DrawTextFlags nTextStyle, tools::Rectangle *pSymbolRect=nullptr, bool bAddImageSep = false );
56     SAL_DLLPRIVATE void             ImplSetFocusRect( const tools::Rectangle &rFocusRect );
57     SAL_DLLPRIVATE const tools::Rectangle& ImplGetFocusRect() const;
58     SAL_DLLPRIVATE void             ImplSetSymbolAlign( SymbolAlign eAlign );
59     /// The x-coordinate of the vertical separator line, use in MenuButton subclass only.
60     SAL_DLLPRIVATE tools::Long             ImplGetSeparatorX() const;
61     SAL_DLLPRIVATE void             ImplSetSeparatorX( tools::Long nX );
62 
63 protected:
64     explicit            Button( WindowType nType );
65 
66     // for drawing RadioButton or CheckButton that has Text and/or Image
67     SAL_DLLPRIVATE void ImplDrawRadioCheck(OutputDevice* pDev, WinBits nWinStyle, DrawFlags nDrawFlags,
68                                            const Point& rPos, const Size& rSize,
69                                            const Size& rImageSize, tools::Rectangle& rStateRect,
70                                            tools::Rectangle& rMouseRect);
71     SAL_DLLPRIVATE tools::Long ImplGetImageToTextDistance() const;
72 
73 public:
74     virtual            ~Button() override;
75     virtual void        dispose() override;
76 
77     virtual void        Click();
78 
SetClickHdl(const Link<Button *,void> & rLink)79     void                SetClickHdl( const Link<Button*,void>& rLink ) { maClickHdl = rLink; }
GetClickHdl() const80     const Link<Button*,void>& GetClickHdl() const { return maClickHdl; }
81 
82     /// Setup handler for UNO commands so that commands like .uno:Something are handled automagically by this button.
83     void                SetCommandHandler(const OUString& aCommand);
GetCommand() const84     OUString const &    GetCommand() const { return maCommand; }
85 
86     void                SetModeImage( const Image& rImage );
87     Image const &       GetModeImage( ) const;
88     bool                HasImage() const;
89     void                SetImageAlign( ImageAlign eAlign );
90     ImageAlign          GetImageAlign() const;
91     DrawButtonFlags     GetButtonState() const;
92     DrawButtonFlags&    GetButtonState();
93 
94     /// Set an image to use as the complete render view of a custom button,
95     /// instead of the usual contents of a button
96     void                SetCustomButtonImage( const Image& rImage );
97     Image const &       GetCustomButtonImage() const;
98 
99     bool                IsSmallSymbol() const;
100     void                SetSmallSymbol();
101     virtual bool        set_property(const OString &rKey, const OUString &rValue) override;
102 
103     /// Sets the button state according to the FeatureStateEvent emitted by a Uno state change.
104     virtual void        statusChanged(const css::frame::FeatureStateEvent& rEvent);
105 
106     virtual FactoryFunction GetUITestFactory() const override;
107 
108     virtual void DumpAsPropertyTree(tools::JsonWriter&) override;
109 
110 protected:
111 
112     /// Handler for click, in case we want the button to handle uno commands (.uno:Something).
113     DECL_STATIC_LINK(Button, dispatchCommandHandler, Button*, void);
114 };
115 
116 enum class PushButtonDropdownStyle
117 {
118     NONE            = 0x0000,
119     MenuButton      = 0x0002, //visual down arrow
120     SplitMenuButton = 0x0003, //visual down arrow and separator line
121 };
122 
123 class VCL_DLLPUBLIC PushButton : public Button
124 {
125 public:
126     SAL_DLLPRIVATE void            ImplSetDefButton( bool bSet );
127     SAL_DLLPRIVATE void            ImplDrawPushButtonFrame(vcl::RenderContext& rRenderContext, tools::Rectangle& rRect, DrawButtonFlags nStyle);
128     SAL_DLLPRIVATE static bool     ImplHitTestPushButton(vcl::Window const * pDev, const Point& rPos);
129     SAL_DLLPRIVATE bool            ImplIsDefButton() const;
130 
131     explicit        PushButton( vcl::Window* pParent, WinBits nStyle = 0 );
132 
133     virtual void    MouseButtonDown( const MouseEvent& rMEvt ) override;
134     virtual void    Tracking( const TrackingEvent& rTEvt ) override;
135     virtual void    KeyInput( const KeyEvent& rKEvt ) override;
136     virtual void    KeyUp( const KeyEvent& rKEvt ) override;
137     virtual void    Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect ) override;
138     virtual void    Draw( OutputDevice* pDev, const Point& rPos, DrawFlags nFlags ) override;
139     virtual void    Resize() override;
140     virtual void    GetFocus() override;
141     virtual void    LoseFocus() override;
142     virtual void    StateChanged( StateChangedType nType ) override;
143     virtual void    DataChanged( const DataChangedEvent& rDCEvt ) override;
144     virtual bool    PreNotify( NotifyEvent& rNEvt ) override;
145 
146     void            Toggle();
147 
148     void            SetSymbol( SymbolType eSymbol );
GetSymbol() const149     SymbolType      GetSymbol() const { return meSymbol; }
150     void            SetSymbolAlign( SymbolAlign eAlign );
151 
152     void            SetDropDown( PushButtonDropdownStyle nStyle );
153 
154     void            SetState( TriState eState );
GetState() const155     TriState        GetState() const { return meState; }
156     virtual void    statusChanged(const css::frame::FeatureStateEvent& rEvent) override;
157 
158     void            Check( bool bCheck = true );
159     bool            IsChecked() const;
160 
161     void            SetPressed( bool bPressed );
IsPressed() const162     bool            IsPressed() const { return mbPressed; }
163 
164     void            EndSelection();
165 
166     Size            CalcMinimumSize() const;
167     virtual Size    GetOptimalSize() const override;
168 
169     virtual bool    set_property(const OString &rKey, const OUString &rValue) override;
170     virtual void    ShowFocus(const tools::Rectangle& rRect) override;
171 
setAction(bool bIsAction)172     void setAction(bool bIsAction)
173     {
174         mbIsAction = bIsAction;
175     }
176 
isAction() const177     bool isAction() const
178     {
179         return mbIsAction;
180     }
181 
182 protected:
183     PushButtonDropdownStyle mnDDStyle;
184     bool            mbIsActive;
185 
186     SAL_DLLPRIVATE void            ImplInitPushButtonData();
187     SAL_DLLPRIVATE static WinBits  ImplInitStyle( const vcl::Window* pPrevWindow, WinBits nStyle );
188     SAL_DLLPRIVATE void            ImplInitSettings( bool bBackground );
189     SAL_DLLPRIVATE void            ImplDrawPushButtonContent(OutputDevice* pDev, DrawFlags nDrawFlags,
190                                                              const tools::Rectangle& rRect, bool bMenuBtnSep,
191                                                              DrawButtonFlags nButtonFlags);
192     SAL_DLLPRIVATE void            ImplDrawPushButton(vcl::RenderContext& rRenderContext);
193     using Button::ImplGetTextStyle;
194     SAL_DLLPRIVATE DrawTextFlags   ImplGetTextStyle( DrawFlags nDrawFlags ) const;
IsSymbol() const195     SAL_DLLPRIVATE bool            IsSymbol() const { return ( (meSymbol != SymbolType::DONTKNOW) && (meSymbol != SymbolType::IMAGE) ); }
196 
197                                    PushButton( const PushButton & ) = delete;
198                                    PushButton& operator=( const PushButton & )
199                                        = delete;
200 
201     SAL_DLLPRIVATE void            ImplInit( vcl::Window* pParent, WinBits nStyle );
202 
203     using Control::ImplInitSettings;
204     using Window::ImplInit;
205 
206     explicit        PushButton( WindowType nType );
207 
208     virtual void    FillLayoutData() const override;
209     virtual const vcl::Font&
210                     GetCanonicalFont( const StyleSettings& _rStyle ) const override;
211     virtual const Color&
212                     GetCanonicalTextColor( const StyleSettings& _rStyle ) const override;
213 
214 private:
215     SymbolType      meSymbol;
216     TriState        meState;
217     bool            mbPressed;
218     bool            mbIsAction;
219 };
220 
Check(bool bCheck)221 inline void PushButton::Check( bool bCheck )
222 {
223     SetState( bCheck ? TRISTATE_TRUE : TRISTATE_FALSE );
224 }
225 
IsChecked() const226 inline bool PushButton::IsChecked() const
227 {
228     return (GetState() == TRISTATE_TRUE);
229 }
230 
231 class VCL_DLLPUBLIC OKButton final : public PushButton
232 {
233 private:
234     using PushButton::ImplInit;
235 
236     SAL_DLLPRIVATE void            ImplInit( vcl::Window* pParent, WinBits nStyle );
237 
238                                    OKButton (const OKButton &) = delete;
239                                    OKButton & operator= (const OKButton &) = delete;
240 
241 public:
242     explicit        OKButton( vcl::Window* pParent, WinBits nStyle = WB_DEFBUTTON );
243 
244     virtual void    Click() override;
245 };
246 
247 class VCL_DLLPUBLIC CancelButton : public PushButton
248 {
249 protected:
250     using PushButton::ImplInit;
251 private:
252     SAL_DLLPRIVATE void ImplInit( vcl::Window* pParent, WinBits nStyle );
253 
254                         CancelButton (const CancelButton &) = delete;
255                         CancelButton & operator= (const CancelButton &) = delete;
256 
257 public:
258     explicit        CancelButton( vcl::Window* pParent, WinBits nStyle = 0 );
259 
260     virtual void    Click() override;
261 };
262 
263 class CloseButton final : public CancelButton
264 {
265 public:
266     explicit CloseButton(vcl::Window* pParent);
267 };
268 
269 class VCL_DLLPUBLIC HelpButton final : public PushButton
270 {
271 private:
272     using PushButton::ImplInit;
273     SAL_DLLPRIVATE void ImplInit( vcl::Window* pParent, WinBits nStyle );
274 
275                         HelpButton( const HelpButton & ) = delete;
276                         HelpButton & operator= ( const HelpButton & ) = delete;
277 
278     virtual void    StateChanged( StateChangedType nStateChange ) override;
279 
280 public:
281     explicit        HelpButton( vcl::Window* pParent, WinBits nStyle = 0 );
282 
283     virtual void    Click() override;
284 };
285 
286 class VCL_DLLPUBLIC CheckBox : public Button
287 {
288 private:
289     tools::Rectangle       maStateRect;
290     tools::Rectangle       maMouseRect;
291     TriState        meState;
292     bool            mbTriState;
293     Link<CheckBox&,void> maToggleHdl;
294     SAL_DLLPRIVATE void         ImplInitCheckBoxData();
295     SAL_DLLPRIVATE static WinBits ImplInitStyle( const vcl::Window* pPrevWindow, WinBits nStyle );
296     SAL_DLLPRIVATE void         ImplInitSettings( bool bBackground );
297     SAL_DLLPRIVATE void         ImplDraw( OutputDevice* pDev, DrawFlags nDrawFlags,
298                                     const Point& rPos, const Size& rSize,
299                                     const Size& rImageSize, tools::Rectangle& rStateRect,
300                                     tools::Rectangle& rMouseRect );
301     SAL_DLLPRIVATE void         ImplDrawCheckBox(vcl::RenderContext& rRenderContext );
302     SAL_DLLPRIVATE Size         ImplGetCheckImageSize() const;
303 
304                                 CheckBox(const CheckBox &) = delete;
305                                 CheckBox& operator= (const CheckBox &) = delete;
306 
307 protected:
308     using Control::ImplInitSettings;
309     using Window::ImplInit;
310     SAL_DLLPRIVATE void         ImplInit( vcl::Window* pParent, WinBits nStyle );
311     virtual void                FillLayoutData() const override;
312     virtual const vcl::Font&    GetCanonicalFont( const StyleSettings& _rStyle ) const override;
313     virtual const Color&        GetCanonicalTextColor( const StyleSettings& _rStyle ) const override;
314     void                        ImplAdjustNWFSizes() override;
315 
316     virtual void ImplDrawCheckBoxState(vcl::RenderContext& rRenderContext);
GetStateRect() const317     SAL_DLLPRIVATE const tools::Rectangle& GetStateRect() const { return maStateRect; }
GetMouseRect() const318     SAL_DLLPRIVATE const tools::Rectangle& GetMouseRect() const { return maMouseRect; }
319 
320 public:
321     SAL_DLLPRIVATE void         ImplCheck();
322 public:
323     explicit        CheckBox( vcl::Window* pParent, WinBits nStyle = 0 );
324 
325     virtual void    MouseButtonDown( const MouseEvent& rMEvt ) override;
326     virtual void    Tracking( const TrackingEvent& rTEvt ) override;
327     virtual void    KeyInput( const KeyEvent& rKEvt ) override;
328     virtual void    KeyUp( const KeyEvent& rKEvt ) override;
329     virtual void    Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect ) override;
330     virtual void    Draw( OutputDevice* pDev, const Point& rPos, DrawFlags nFlags ) override;
331     virtual void    Resize() override;
332     virtual void    GetFocus() override;
333     virtual void    LoseFocus() override;
334     virtual void    StateChanged( StateChangedType nType ) override;
335     virtual void    DataChanged( const DataChangedEvent& rDCEvt ) override;
336     virtual bool    PreNotify( NotifyEvent& rNEvt ) override;
337 
338     void            Toggle();
339 
340     void            SetState( TriState eState );
GetState() const341     TriState        GetState() const { return meState; }
342 
Check(bool bCheck=true)343     void            Check( bool bCheck = true )
344     {
345         SetState( bCheck ? TRISTATE_TRUE : TRISTATE_FALSE );
346     }
347 
IsChecked() const348     bool            IsChecked() const
349     {
350         return (GetState() == TRISTATE_TRUE);
351     }
352 
353     void            EnableTriState( bool bTriState = true );
IsTriStateEnabled() const354     bool            IsTriStateEnabled() const { return mbTriState; }
355 
356     static Image    GetCheckImage( const AllSettings& rSettings, DrawButtonFlags nFlags );
357 
358     Size            CalcMinimumSize( tools::Long nMaxWidth = 0 ) const;
359     virtual Size    GetOptimalSize() const override;
360 
SetToggleHdl(const Link<CheckBox &,void> & rLink)361     void            SetToggleHdl( const Link<CheckBox&,void>& rLink ) { maToggleHdl = rLink; }
362 
363     virtual bool set_property(const OString &rKey, const OUString &rValue) override;
364     virtual void ShowFocus(const tools::Rectangle& rRect) override;
365 
366     /// Button has additional stuff that we need to dump too.
367     void DumpAsPropertyTree(tools::JsonWriter&) override;
368 
369     virtual FactoryFunction GetUITestFactory() const override;
370 };
371 
372 class VCL_DLLPUBLIC RadioButton : public Button
373 {
374 private:
375     friend class VclBuilder;
376 
377     std::shared_ptr< std::vector< VclPtr< RadioButton > > > m_xGroup;
378     tools::Rectangle       maStateRect;
379     tools::Rectangle       maMouseRect;
380     Image           maImage;
381     bool            mbChecked;
382     bool            mbRadioCheck;
383     bool            mbStateChanged;
384     bool            mbUsesExplicitGroup;
385     Link<RadioButton&,void> maToggleHdl;
386     SAL_DLLPRIVATE void     ImplInitRadioButtonData();
387     SAL_DLLPRIVATE WinBits  ImplInitStyle( const vcl::Window* pPrevWindow, WinBits nStyle );
388     SAL_DLLPRIVATE void     ImplInitSettings( bool bBackground );
389     SAL_DLLPRIVATE void     ImplDrawRadioButtonState(vcl::RenderContext& rRenderContext);
390     SAL_DLLPRIVATE void     ImplDraw( OutputDevice* pDev, DrawFlags nDrawFlags,
391                               const Point& rPos, const Size& rSize,
392                               const Size& rImageSize, tools::Rectangle& rStateRect,
393                               tools::Rectangle& rMouseRect );
394     SAL_DLLPRIVATE void     ImplDrawRadioButton(vcl::RenderContext& rRenderContext );
395     SAL_DLLPRIVATE void     ImplUncheckAllOther();
396     SAL_DLLPRIVATE Size     ImplGetRadioImageSize() const;
397 
398                             RadioButton(const RadioButton &) = delete;
399                             RadioButton& operator= (const RadioButton &) = delete;
400 
401 protected:
402     using Control::ImplInitSettings;
403     using Window::ImplInit;
404     SAL_DLLPRIVATE void     ImplInit( vcl::Window* pParent, WinBits nStyle );
405 
406 public:
407     SAL_DLLPRIVATE void     ImplCallClick( bool bGrabFocus = false, GetFocusFlags nFocusFlags = GetFocusFlags::NONE );
408 
409 protected:
410     virtual void    FillLayoutData() const override;
411     virtual const vcl::Font&
412                     GetCanonicalFont( const StyleSettings& _rStyle ) const override;
413     virtual const Color&
414                     GetCanonicalTextColor( const StyleSettings& _rStyle ) const override;
415     void            ImplAdjustNWFSizes() override;
416 
417 public:
418     /*
419      bUsesExplicitGroup of true means that group() is used to set what radiobuttons are part of a group
420      while false means that contiguous radiobuttons are considered part of a group where WB_GROUP designates
421      the start of the group and all contiguous radiobuttons without WB_GROUP set form the rest of the group.
422 
423      true is fairly straightforward, false leads to trick situations and is the legacy case
424     */
425     explicit        RadioButton(vcl::Window* pParent, bool bUsesExplicitGroup, WinBits nWinStyle);
426     virtual         ~RadioButton() override;
427     virtual void    dispose() override;
428 
429     virtual void    MouseButtonDown( const MouseEvent& rMEvt ) override;
430     virtual void    Tracking( const TrackingEvent& rTEvt ) override;
431     virtual void    KeyInput( const KeyEvent& rKEvt ) override;
432     virtual void    KeyUp( const KeyEvent& rKEvt ) override;
433     virtual void    Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect ) override;
434     virtual void    Draw( OutputDevice* pDev, const Point& rPos, DrawFlags nFlags ) override;
435     virtual void    Resize() override;
436     virtual void    GetFocus() override;
437     virtual void    LoseFocus() override;
438     virtual void    StateChanged( StateChangedType nType ) override;
439     virtual void    DataChanged( const DataChangedEvent& rDCEvt ) override;
440     virtual bool    PreNotify( NotifyEvent& rNEvt ) override;
441 
442     void            Toggle();
443 
IsStateChanged() const444     bool            IsStateChanged() const { return mbStateChanged; }
445 
EnableRadioCheck(bool bRadioCheck)446     void            EnableRadioCheck( bool bRadioCheck ) { mbRadioCheck = bRadioCheck; }
IsRadioCheckEnabled() const447     bool            IsRadioCheckEnabled() const { return mbRadioCheck; }
448 
449     void            SetModeRadioImage( const Image& rImage );
450 
451     void            SetState( bool bCheck );
452     void            Check( bool bCheck = true );
IsChecked() const453     bool            IsChecked() const { return mbChecked; }
454 
455     static Image    GetRadioImage( const AllSettings& rSettings, DrawButtonFlags nFlags );
456 
457     Size            CalcMinimumSize( tools::Long nMaxWidth = 0 ) const;
458     virtual Size    GetOptimalSize() const override;
459 
SetToggleHdl(const Link<RadioButton &,void> & rLink)460     void            SetToggleHdl( const Link<RadioButton&,void>& rLink ) { maToggleHdl = rLink; }
461 
462     /** GetRadioButtonGroup returns a list of pointers to <code>RadioButton</code>s in the same group.
463 
464     The pointers in the returned list are valid at the time call returns. However rescheduling
465     or giving up the SolarMutex may mean events get executed that lead to the pointers getting
466     invalid.
467 
468     @param bIncludeThis
469     defines whether <code>this</code> is contained in the returned list
470 
471     @return
472     on return contains the <code>RadioButton</code>s
473     in the same group as this <code>RadioButton</code>.
474     */
475     std::vector<VclPtr<RadioButton> > GetRadioButtonGroup(bool bIncludeThis = true) const;
476 
477     virtual bool set_property(const OString &rKey, const OUString &rValue) override;
478 
479     /*
480      * Group this RadioButton with another
481      */
482     void group(RadioButton &rOther);
483     virtual void ShowFocus(const tools::Rectangle& rRect) override;
484 
485     /// Button has additional stuff that we need to dump too.
486     void DumpAsPropertyTree(tools::JsonWriter&) override;
487 
488     virtual FactoryFunction GetUITestFactory() const override;
489 };
490 
491 class VCL_DLLPUBLIC ImageButton final : public PushButton
492 {
493 private:
494     using PushButton::ImplInitStyle;
495 
496     SAL_DLLPRIVATE void     ImplInitStyle();
497 
498                             ImageButton( const ImageButton & ) = delete;
499                             ImageButton & operator= ( const ImageButton & ) = delete;
500 
501 public:
502                  ImageButton( vcl::Window* pParent, WinBits nStyle = 0 );
503 };
504 
505 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
506