1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
22 #include <svtools/svtdllapi.h>
23 #include <vcl/wintypes.hxx>
24 #include <vcl/customweld.hxx>
25 #include <vcl/image.hxx>
33 class DataChangedEvent
;
40 enum class DrawFrameStyle
;
42 /*************************************************************************
49 This class allows the selection of an item. In the process items are
50 drawn side by side. The selection of items can be more clear than in a
51 ListBox shape for example in case of colors or samples.
52 The amount of columns drawn by the control and whether the items
53 should be encircled can be specified. Optional a NoSelection or name
54 field could be shown. By default image and color items are supported.
55 Items could be drawn by oneself if InsertItem() is only called with
56 an ID. To achieve this the UserDraw handler needs to be overridden. The
57 description text could be specified afterwards in case of UserDraw
64 --------------------------------------------------------------------------
68 WB_FLATVALUESET Flat Look (if you set WB_ITEMBORDER or WB_DOUBLEBORDER,
69 then you get extra border space, but the Borders
71 WB_ITEMBORDER Items will be bordered
72 WB_DOUBLEBORDER Items will be bordered twice. Additionally WB_ITEMBORDER
73 has to be set, as otherwise this WinBit wouldn't have any
74 effect. It is needed if there are items with a white
75 background, since otherwise the 3D effect wouldn't be
77 WB_NAMEFIELD There is a namefield, where the name of an item will be
79 WB_NONEFIELD There is a NoSelection field which can be selected if
80 0 is passed along with SelectItem. Respectively
81 GetSelectedItemId() returns 0 if this field or nothing
82 is selected. This field shows the text which is specified
83 by SetText() respectively no one, if no text was set. With
84 SetNoSelection() the selection can be disabled.
85 WB_VSCROLL A scrollbar will be always shown. The visible number of
86 lines have to be specified with SetLineCount() if this
88 WB_BORDER A border will be drawn around the window.
89 WB_TABSTOP It is possible to jump into the ValueSet with the tab key.
90 WB_NOTABSTOP It is not possible to jump into the ValueSet with the
92 WB_NO_DIRECTSELECT Cursor travelling doesn't call select immediately. To
93 execute the selection <RETURN> has to be pressed.
94 --------------------------------------------------------------------------
96 The number of columns must be either set with SetColCount() or
97 SetItemWidth(). If the number of columns is specified by SetColCount()
98 the width of the items will be calculated by the visible range.
99 If the items should have a static width, it has to be specified
100 with SetItemWidth(). In this case the number of columns will be calculated
101 by the visible range.
103 The number of rows is given by the number of items / number of columns. The
104 number of visible rows must either specified by SetLineCount() or
105 SetItemWidth(). If the number of visible rows is specified by SetLineCount(),
106 the height of the items will be calculated from the visible height. If the
107 items should have a fixed height it has to be specified with SetItemHeight().
108 In this case the number of visible rows is then calculated from the visible
109 height. If the number of visible rows is neither specified by SetLineCount()
110 nor by SetItemHeight() all rows will be shown. The height of the items will
111 be calculated by the visible height. If the number of visible rows is
112 specified by SetLineCount() or SetItemHeight() ValueSet does scroll
113 automatically when more lines are available, as are visible. If scrolling
114 should be also possible with a ScrollBar WB_VSCROLL needs to be set.
116 The distance between the items can be increased by SetExtraSpacing(). The
117 distance, which will be shown between two items (both in x and in y), is
120 The exact window size for a specific item size can be calculated by
121 CalcWindowSizePixel(). To do this all relevant data (number of columns/...)
122 have to be specified and if no number of rows was set, all items need to
123 be inserted. If the window was created with WB_BORDER/Border=sal_True the
124 size has to be specified with SetOutputSizePixel(). In other cases different
125 size-methods can be used. With CalcItemSize() the inner and outer size of
126 an item could be calculated (for this the free space defined by
127 SetExtraSpacing() will not be included).
129 The background color could be specified by SetColor(), with which the image
130 or UserDraw items will be underlaid. If no color is specified the color
131 of other windows (WindowColor) will be used for the background.
133 --------------------------------------------------------------------------
135 At first all items should be inserted and only then Show() should be called
136 since the output area will be precomputed. If this is not done the first
137 Paint will appear a little bit slower. Therefore the Control, if it is loaded
138 from the resource and only supplied with items during runtime, should be
139 loaded with Hide = sal_True and then displayed with Show().
141 In case of a visible Control the creation of the new output area could be
142 activated before Paint by calling Format().
144 --------------------------------------------------------------------------
146 If Drag and Drop will be called from the ValueSet the Command-Handler has to
147 be overridden. From this StartDrag needs to be called. If this method returns
148 sal_True the drag-process could be initiated by ExecuteDrag(), otherwise no
149 processing will take place. This method makes sure that ValueSet stops its
150 processing and as appropriate selects the entry. Therefore the calling of
151 Select-Handler within this function must be expected.
153 For dropping QueryDrop() and Drop() need to be overridden and ShowDropPos()
154 and HideDropPos() should be called within these methods.
155 To show the insertion point ShowDropPos() has to be called within the
156 QueryDrop-Handler. ShowDropPos() also scrolls the ValueSet if the passed
157 position is located at the window border. Furthermore ShowDropPos() returns
158 the position, at which the item should be inserted respectively which
159 insertion point was shown. If no insertion point was determined
160 VALUESET_ITEM_NOTFOUND will be returned. If the window was left during dragging
161 or the drag process is terminated HideDropPos() should be called in any case.
163 --------------------------------------------------------------------------
165 This class is currently still in the SV-Tools. That's why the ValueSet needs
166 to be loaded as a Control out of the resource and the desired WinBits have
167 to be set (before Show) with SetStyle().
169 *************************************************************************/
171 typedef std::vector
<std::unique_ptr
<ValueSetItem
>> ValueItemList
;
173 #define WB_ITEMBORDER (WinBits(0x00010000))
174 #define WB_DOUBLEBORDER (WinBits(0x00020000))
175 #define WB_NAMEFIELD (WinBits(0x00040000))
176 #define WB_NONEFIELD (WinBits(0x00080000))
177 #define WB_FLATVALUESET (WinBits(0x02000000))
178 #define WB_NO_DIRECTSELECT (WinBits(0x04000000))
179 #define WB_MENUSTYLEVALUESET (WinBits(0x08000000))
181 #define VALUESET_APPEND (size_t(-1))
182 #define VALUESET_ITEM_NOTFOUND (size_t(-1))
184 class SVT_DLLPUBLIC ValueSet
: public weld::CustomWidgetController
187 ScopedVclPtr
<VirtualDevice
> maVirDev
;
188 css::uno::Reference
<css::accessibility::XAccessible
> mxAccessible
;
189 ValueItemList mItemList
;
190 std::unique_ptr
<ValueSetItem
> mpNoneItem
;
191 std::unique_ptr
<weld::ScrolledWindow
> mxScrolledWindow
;
192 tools::Rectangle maNoneItemRect
;
193 tools::Rectangle maItemListRect
;
194 tools::Long mnItemWidth
;
195 tools::Long mnItemHeight
;
196 tools::Long mnTextOffset
;
197 tools::Long mnVisLines
;
199 tools::Long mnUserItemWidth
;
200 tools::Long mnUserItemHeight
;
201 sal_uInt16 mnSelItemId
;
203 sal_uInt16 mnHighItemId
;
206 sal_uInt16 mnUserCols
;
207 sal_uInt16 mnUserVisLines
;
208 sal_uInt16 mnFirstLine
;
209 sal_uInt16 mnSpacing
;
210 DrawFrameStyle mnFrameStyle
;
214 Link
<ValueSet
*,void> maDoubleClickHdl
;
215 Link
<ValueSet
*,void> maSelectHdl
;
218 bool mbHighlight
: 1;
219 bool mbNoSelection
: 1;
220 bool mbDoubleSel
: 1;
223 bool mbEdgeBlending
: 1;
224 bool mbHasVisibleItems
: 1;
226 friend class ValueItemAcc
;
227 friend class ValueSetAcc
;
229 SVT_DLLPRIVATE
void ImplDeleteItems();
230 SVT_DLLPRIVATE
void ImplFormatItem(vcl::RenderContext
const & rRenderContext
, ValueSetItem
* pItem
, tools::Rectangle aRect
);
231 SVT_DLLPRIVATE
void ImplDrawItemText(vcl::RenderContext
& rRenderContext
, const OUString
& rStr
);
232 // nItemId is the item to draw selected, but if nothing is selected something else may be drawn as selected instead, the item to draw
233 // selected is returned
234 SVT_DLLPRIVATE ValueSetItem
* ImplGetDrawSelectItem(sal_uInt16 nItemId
, const bool bFocus
, tools::Rectangle
& rRect
);
235 SVT_DLLPRIVATE
void ImplDrawSelect(vcl::RenderContext
& rRenderContext
,
236 const tools::Rectangle
& rRect
, const ValueSetItem
* pItem
,
237 const bool bFocus
, const bool bDrawSel
,
238 const bool bSelected
, const bool bHover
);
239 SVT_DLLPRIVATE
void ImplDrawSelect(vcl::RenderContext
& rRenderContext
);
240 SVT_DLLPRIVATE
void ImplHighlightItem(sal_uInt16 nItemId
);
241 SVT_DLLPRIVATE
void ImplDraw(vcl::RenderContext
& rRenderContext
);
242 SVT_DLLPRIVATE
size_t ImplGetItem( const Point
& rPoint
) const;
243 SVT_DLLPRIVATE ValueSetItem
* ImplGetItem( size_t nPos
);
244 SVT_DLLPRIVATE ValueSetItem
* ImplGetFirstItem();
245 SVT_DLLPRIVATE sal_uInt16
ImplGetVisibleItemCount() const;
246 SVT_DLLPRIVATE
void ImplInsertItem( std::unique_ptr
<ValueSetItem
> pItem
, const size_t nPos
);
247 SVT_DLLPRIVATE
tools::Rectangle
ImplGetItemRect( size_t nPos
) const;
248 SVT_DLLPRIVATE
void ImplFireAccessibleEvent( short nEventId
, const css::uno::Any
& rOldValue
, const css::uno::Any
& rNewValue
);
249 SVT_DLLPRIVATE
bool ImplHasAccessibleListeners() const;
250 SVT_DLLPRIVATE
void ImplTracking(bool bLeaveWindow
, const Point
& rPos
);
251 SVT_DLLPRIVATE
void QueueReformat();
252 SVT_DLLPRIVATE
void SetFirstLine(sal_uInt16 nNewFirstLine
); // set mnFirstLine and update scrollbar to match
253 SVT_DLLPRIVATE
void RecalcScrollBar();
254 SVT_DLLPRIVATE
bool TurnOffScrollBar();
255 SVT_DLLPRIVATE
void TurnOnScrollBar();
256 DECL_DLLPRIVATE_LINK(ImplScrollHdl
, weld::ScrolledWindow
&, void);
258 Size
GetLargestItemSize();
260 ValueSet (const ValueSet
&) = delete;
261 ValueSet
& operator= (const ValueSet
&) = delete;
264 virtual css::uno::Reference
<css::accessibility::XAccessible
> CreateAccessible() override
;
265 weld::ScrolledWindow
* GetScrollBar() const { return mxScrolledWindow
.get(); }
268 ValueSet(std::unique_ptr
<weld::ScrolledWindow
> pScrolledWindow
);
269 virtual ~ValueSet() override
;
271 virtual void SetDrawingArea(weld::DrawingArea
* pDrawingArea
) override
;
273 virtual bool MouseButtonDown( const MouseEvent
& rMEvt
) override
;
274 virtual bool MouseButtonUp( const MouseEvent
& rMEvt
) override
;
275 virtual bool MouseMove( const MouseEvent
& rMEvt
) override
;
276 virtual bool KeyInput( const KeyEvent
& rKEvt
) override
;
277 virtual void Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& rRect
) override
;
278 virtual void GetFocus() override
;
279 virtual void LoseFocus() override
;
280 virtual void Resize() override
;
281 virtual void StyleUpdated() override
;
282 virtual void Show() override
;
283 virtual void Hide() override
;
284 virtual OUString
RequestHelp(tools::Rectangle
& rHelpRect
) override
;
286 virtual void Select();
287 virtual void UserDraw( const UserDrawEvent
& rUDEvt
);
289 OUString
const & GetText() const { return maText
; }
290 void SetText(const OUString
& rText
) { maText
= rText
; }
291 void SetStyle(WinBits nStyle
);
292 WinBits
GetStyle() const { return mnStyle
; }
294 void SetOptimalSize();
296 /// Insert @rImage item.
297 void InsertItem(sal_uInt16 nItemId
, const Image
& rImage
);
298 /// Insert @rImage item with @rStr as either a legend or tooltip depending on @bShowLegend.
299 void InsertItem(sal_uInt16 nItemId
, const Image
& rImage
,
300 const OUString
& rStr
, size_t nPos
= VALUESET_APPEND
, bool bShowLegend
= false);
301 /// Insert an @rColor item with @rStr tooltip.
302 void InsertItem(sal_uInt16 nItemId
, const Color
& rColor
,
303 const OUString
& rStr
);
304 /// Insert an User Drawn item.
305 void InsertItem(sal_uInt16 nItemId
, size_t nPos
= VALUESET_APPEND
);
306 /// Insert an User Drawn item with @rStr tooltip.
307 void InsertItem(sal_uInt16 nItemId
, const OUString
& rStr
, size_t nPos
);
308 void RemoveItem(sal_uInt16 nItemId
);
312 size_t GetItemCount() const;
313 size_t GetItemPos( sal_uInt16 nItemId
) const;
314 sal_uInt16
GetItemId( size_t nPos
) const;
315 sal_uInt16
GetItemId( const Point
& rPos
) const;
316 tools::Rectangle
GetItemRect( sal_uInt16 nItemId
) const;
317 void EnableFullItemMode( bool bFullMode
);
319 void SetColCount( sal_uInt16 nNewCols
= 1 );
320 sal_uInt16
GetColCount() const
324 void SetLineCount( sal_uInt16 nNewLines
= 0 );
325 sal_uInt16
GetLineCount() const
327 return mnUserVisLines
;
329 void SetItemWidth( tools::Long nItemWidth
);
330 void SetItemHeight( tools::Long nLineHeight
);
332 void SelectItem( sal_uInt16 nItemId
);
333 sal_uInt16
GetSelectedItemId() const
337 size_t GetSelectItemPos() const
339 return GetItemPos( mnSelItemId
);
341 bool IsItemSelected( sal_uInt16 nItemId
) const
343 return !mbNoSelection
&& (nItemId
== mnSelItemId
);
345 void SetNoSelection();
346 bool IsNoSelection() const
348 return mbNoSelection
;
351 void RecalculateItemSizes();
353 void SetItemImage( sal_uInt16 nItemId
, const Image
& rImage
);
354 Image
GetItemImage( sal_uInt16 nItemId
) const;
355 void SetItemColor( sal_uInt16 nItemId
, const Color
& rColor
);
356 Color
GetItemColor( sal_uInt16 nItemId
) const;
357 void SetItemData( sal_uInt16 nItemId
, void* pData
);
358 void* GetItemData( sal_uInt16 nItemId
) const;
359 void SetItemText( sal_uInt16 nItemId
, const OUString
& rStr
);
360 OUString
GetItemText( sal_uInt16 nItemId
) const;
361 void SetColor( const Color
& rColor
);
364 SetColor(COL_TRANSPARENT
);
368 return !maColor
.IsTransparent();
371 void SetExtraSpacing( sal_uInt16 nNewSpacing
);
373 void Format(vcl::RenderContext
const & rRenderContext
);
376 Size
CalcWindowSizePixel(const Size
& rItemSize
,
377 sal_uInt16 nCalcCols
= 0,
378 sal_uInt16 nCalcLines
= 0) const;
379 Size
CalcItemSizePixel(const Size
& rSize
) const;
380 int GetScrollWidth() const;
382 void SetSelectHdl(const Link
<ValueSet
*,void>& rLink
)
387 void SetDoubleClickHdl(const Link
<ValueSet
*,void>& rLink
)
389 maDoubleClickHdl
= rLink
;
392 bool GetEdgeBlending() const
394 return mbEdgeBlending
;
396 void SetEdgeBlending(bool bNew
);
400 mnSavedItemId
= IsNoSelection() ? -1 : GetSelectedItemId();
403 bool IsValueChangedFromSaved() const
405 int nItemId
= IsNoSelection() ? -1 : GetSelectedItemId();
406 return mnSavedItemId
!= nItemId
;
409 virtual FactoryFunction
GetUITestFactory() const override
;
412 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */