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 <svtools/svtdllapi.h> 23 #include <tools/wintypes.hxx> 24 #include <vcl/customweld.hxx> 25 #include <vcl/image.hxx> 26 #include <memory> 27 #include <vector> 28 29 class MouseEvent; 30 class TrackingEvent; 31 class HelpEvent; 32 class KeyEvent; 33 class DataChangedEvent; 34 class ScrollBar; 35 class UserDrawEvent; 36 class VirtualDevice; 37 38 struct ValueSetItem; 39 40 enum class DrawFrameStyle; 41 42 /************************************************************************* 43 44 Description 45 ============ 46 47 class ValueSet 48 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 58 and any other items. 59 60 Cross references 61 62 class ListBox 63 64 -------------------------------------------------------------------------- 65 66 WinBits 67 68 WB_RADIOSEL If set the selection will be drawn like an 69 RadioButton. This does only make sense if the image 70 is at least 8 pixel smaller on each side than the item 71 and also WB_DOUBLEBORDER is set and as color 72 COL_WINDOWWORKSPACE is specified. 73 WB_FLATVALUESET Flat Look (if you set WB_ITEMBORDER or WB_DOUBLEBORDER, 74 then you get extra border space, but the Borders 75 aren't painted), 76 WB_ITEMBORDER Items will be bordered 77 WB_DOUBLEBORDER Items will be bordered twice. Additionally WB_ITEMBORDER 78 has to be set, as otherwise this WinBit wouldn't have any 79 effect. It is needed if there are items with a white 80 background, since otherwise the 3D effect wouldn't be 81 recognizable. 82 WB_NAMEFIELD There is a namefield, where the name of an item will be 83 shown. 84 WB_NONEFIELD There is a NoSelection field which can be selected if 85 0 is passed along with SelectItem. Respectively 86 GetSelectedItemId() returns 0 if this field or nothing 87 is selected. This field shows the text which is specified 88 by SetText() respectively no one, if no text was set. With 89 SetNoSelection() the selection can be disabled. 90 WB_VSCROLL A scrollbar will be always shown. The visible number of 91 lines have to be specified with SetLineCount() if this 92 flag is set. 93 WB_BORDER A border will be drawn around the window. 94 WB_NOPOINTERFOCUS The focus won't be gathered, if the control was pressed by 95 the mouse. 96 WB_TABSTOP It is possible to jump into the ValueSet with the tab key. 97 WB_NOTABSTOP It is not possible to jump into the ValueSet with the 98 tab key. 99 WB_NO_DIRECTSELECT Cursor travelling doesn't call select immediately. To 100 execute the selection <RETURN> has to be pressed. 101 -------------------------------------------------------------------------- 102 103 The number of columns must be either set with SetColCount() or 104 SetItemWidth(). If the number of columns is specified by SetColCount() 105 the width of the items will be calculated by the visible range. 106 If the items should have a static width, it has to be specified 107 with SetItemWidth(). In this case the number of columns will be calculated 108 by the visible range. 109 110 The number of rows is given by the number of items / number of columns. The 111 number of visible rows must either specified by SetLineCount() or 112 SetItemWidth(). If the number of visible rows is specified by SetLineCount(), 113 the height of the items will be calculated from the visible height. If the 114 items should have a fixed height it has to be specified with SetItemHeight(). 115 In this case the number of visible rows is then calculated from the visible 116 height. If the number of visible rows is neither specified by SetLineCount() 117 nor by SetItemHeight() all rows will be shown. The height of the items will 118 be calculated by the visible height. If the number of visible rows is 119 specified by SetLineCount() or SetItemHeight() ValueSet does scroll 120 automatically when more lines are available, as are visible. If scrolling 121 should be also possible with a ScrollBar WB_VSCROLL needs to be set. 122 123 The distance between the items can be increased by SetExtraSpacing(). The 124 distance, which will be shown between two items (both in x and in y), is 125 measured in pixels. 126 127 The exact window size for a specific item size can be calculated by 128 CalcWindowSizePixel(). To do this all relevant data (number of columns/...) 129 have to be specified and if no number of rows was set, all items need to 130 be inserted. If the window was created with WB_BORDER/Border=sal_True the 131 size has to be specified with SetOutputSizePixel(). In other cases different 132 size-methods can be used. With CalcItemSize() the inner and outer size of 133 an item could be calculated (for this the free space defined by 134 SetExtraSpacing() will not be included). 135 136 The background color could be specified by SetColor(), with which the image 137 or UserDraw items will be underlaid. If no color is specified the color 138 of other windows (WindowColor) will be used for the background. 139 140 -------------------------------------------------------------------------- 141 142 At first all items should be inserted and only then Show() should be called 143 since the output area will be precomputed. If this is not done the first 144 Paint will appear a little bit slower. Therefore the Control, if it is loaded 145 from the resource and only supplied with items during runtime, should be 146 loaded with Hide = sal_True and then displayed with Show(). 147 148 In case of a visible Control the creation of the new output area could be 149 activated before Paint by calling Format(). 150 151 -------------------------------------------------------------------------- 152 153 If Drag and Drop will be called from the ValueSet the Command-Handler has to 154 be overridden. From this StartDrag needs to be called. If this method returns 155 sal_True the drag-process could be initiated by ExecuteDrag(), otherwise no 156 processing will take place. This method makes sure that ValueSet stops its 157 processing and as appropriate selects the entry. Therefore the calling of 158 Select-Handler within this function must be expected. 159 160 For dropping QueryDrop() and Drop() need to be overridden and ShowDropPos() 161 and HideDropPos() should be called within these methods. 162 To show the insertion point ShowDropPos() has to be called within the 163 QueryDrop-Handler. ShowDropPos() also scrolls the ValueSet if the passed 164 position is located at the window border. Furthermore ShowDropPos() returns 165 the position, at which the item should be inserted respectively which 166 insertion point was shown. If no insertion point was determined 167 VALUESET_ITEM_NOTFOUND will be returned. If the window was left during dragging 168 or the drag process is terminated HideDropPos() should be called in any case. 169 170 -------------------------------------------------------------------------- 171 172 This class is currently still in the SV-Tools. That's why the ValueSet needs 173 to be loaded as a Control out of the resource and the desired WinBits have 174 to be set (before Show) with SetStyle(). 175 176 *************************************************************************/ 177 178 typedef std::vector<std::unique_ptr<ValueSetItem>> ValueItemList; 179 180 #define WB_ITEMBORDER (WinBits(0x00010000)) 181 #define WB_DOUBLEBORDER (WinBits(0x00020000)) 182 #define WB_NAMEFIELD (WinBits(0x00040000)) 183 #define WB_NONEFIELD (WinBits(0x00080000)) 184 #define WB_FLATVALUESET (WinBits(0x02000000)) 185 #define WB_NO_DIRECTSELECT (WinBits(0x04000000)) 186 #define WB_MENUSTYLEVALUESET (WinBits(0x08000000)) 187 188 #define VALUESET_APPEND (size_t(-1)) 189 #define VALUESET_ITEM_NOTFOUND (size_t(-1)) 190 191 class SVT_DLLPUBLIC ValueSet : public weld::CustomWidgetController 192 { 193 private: 194 ScopedVclPtr<VirtualDevice> maVirDev; 195 css::uno::Reference<css::accessibility::XAccessible> mxAccessible; 196 ValueItemList mItemList; 197 std::unique_ptr<ValueSetItem> mpNoneItem; 198 std::unique_ptr<weld::ScrolledWindow> mxScrolledWindow; 199 tools::Rectangle maNoneItemRect; 200 tools::Rectangle maItemListRect; 201 tools::Long mnItemWidth; 202 tools::Long mnItemHeight; 203 tools::Long mnTextOffset; 204 tools::Long mnVisLines; 205 tools::Long mnLines; 206 tools::Long mnUserItemWidth; 207 tools::Long mnUserItemHeight; 208 sal_uInt16 mnSelItemId; 209 int mnSavedItemId; 210 sal_uInt16 mnHighItemId; 211 sal_uInt16 mnCols; 212 sal_uInt16 mnCurCol; 213 sal_uInt16 mnUserCols; 214 sal_uInt16 mnUserVisLines; 215 sal_uInt16 mnFirstLine; 216 sal_uInt16 mnSpacing; 217 DrawFrameStyle mnFrameStyle; 218 Color maColor; 219 OUString maText; 220 WinBits mnStyle; 221 Link<ValueSet*,void> maDoubleClickHdl; 222 Link<ValueSet*,void> maSelectHdl; 223 224 bool mbFormat : 1; 225 bool mbHighlight : 1; 226 bool mbNoSelection : 1; 227 bool mbDrawSelection : 1; 228 bool mbBlackSel : 1; 229 bool mbDoubleSel : 1; 230 bool mbScroll : 1; 231 bool mbFullMode : 1; 232 bool mbEdgeBlending : 1; 233 bool mbHasVisibleItems : 1; 234 235 friend class ValueItemAcc; 236 friend class ValueSetAcc; 237 238 SVT_DLLPRIVATE void ImplDeleteItems(); 239 SVT_DLLPRIVATE void ImplFormatItem(vcl::RenderContext const & rRenderContext, ValueSetItem* pItem, tools::Rectangle aRect); 240 SVT_DLLPRIVATE void ImplDrawItemText(vcl::RenderContext& rRenderContext, const OUString& rStr); 241 SVT_DLLPRIVATE void ImplDrawSelect(vcl::RenderContext& rRenderContext, sal_uInt16 nItemId, const bool bFocus, const bool bDrawSel); 242 SVT_DLLPRIVATE void ImplDrawSelect(vcl::RenderContext& rRenderContext); 243 SVT_DLLPRIVATE void ImplHighlightItem(sal_uInt16 nItemId, bool bIsSelection = true); 244 SVT_DLLPRIVATE void ImplDraw(vcl::RenderContext& rRenderContext); 245 SVT_DLLPRIVATE size_t ImplGetItem( const Point& rPoint ) const; 246 SVT_DLLPRIVATE ValueSetItem* ImplGetItem( size_t nPos ); 247 SVT_DLLPRIVATE ValueSetItem* ImplGetFirstItem(); 248 SVT_DLLPRIVATE sal_uInt16 ImplGetVisibleItemCount() const; 249 SVT_DLLPRIVATE void ImplInsertItem( std::unique_ptr<ValueSetItem> pItem, const size_t nPos ); 250 SVT_DLLPRIVATE tools::Rectangle ImplGetItemRect( size_t nPos ) const; 251 SVT_DLLPRIVATE void ImplFireAccessibleEvent( short nEventId, const css::uno::Any& rOldValue, const css::uno::Any& rNewValue ); 252 SVT_DLLPRIVATE bool ImplHasAccessibleListeners(); 253 SVT_DLLPRIVATE void ImplTracking(const Point& rPos); 254 SVT_DLLPRIVATE void QueueReformat(); 255 SVT_DLLPRIVATE void SetFirstLine(sal_uInt16 nNewFirstLine); // set mnFirstLine and update scrollbar to match 256 SVT_DLLPRIVATE void RecalcScrollBar(); 257 SVT_DLLPRIVATE bool TurnOffScrollBar(); 258 SVT_DLLPRIVATE void TurnOnScrollBar(); 259 DECL_DLLPRIVATE_LINK(ImplScrollHdl, weld::ScrolledWindow&, void); 260 261 Size GetLargestItemSize(); 262 263 ValueSet (const ValueSet &) = delete; 264 ValueSet & operator= (const ValueSet &) = delete; 265 266 protected: 267 virtual css::uno::Reference<css::accessibility::XAccessible> CreateAccessible() override; GetScrollBar() const268 weld::ScrolledWindow* GetScrollBar() const { return mxScrolledWindow.get(); } 269 270 public: 271 ValueSet(std::unique_ptr<weld::ScrolledWindow> pScrolledWindow); 272 virtual ~ValueSet() override; 273 274 virtual void SetDrawingArea(weld::DrawingArea* pDrawingArea) override; 275 276 virtual bool MouseButtonDown( const MouseEvent& rMEvt ) override; 277 virtual bool MouseButtonUp( const MouseEvent& rMEvt ) override; 278 virtual bool MouseMove( const MouseEvent& rMEvt ) override; 279 virtual bool KeyInput( const KeyEvent& rKEvt ) override; 280 virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override; 281 virtual void GetFocus() override; 282 virtual void LoseFocus() override; 283 virtual void Resize() override; 284 virtual void StyleUpdated() override; 285 virtual void Show() override; 286 virtual void Hide() override; 287 virtual OUString RequestHelp(tools::Rectangle& rHelpRect) override; 288 289 virtual void Select(); 290 virtual void UserDraw( const UserDrawEvent& rUDEvt ); 291 GetText() const292 OUString const & GetText() const { return maText; } SetText(const OUString & rText)293 void SetText(const OUString& rText) { maText = rText; } 294 void SetStyle(WinBits nStyle); GetStyle() const295 WinBits GetStyle() const { return mnStyle; } 296 297 void SetOptimalSize(); 298 299 /// Insert @rImage item. 300 void InsertItem(sal_uInt16 nItemId, const Image& rImage); 301 /// Insert @rImage item with @rStr as either a legend or tooltip depending on @bShowLegend. 302 void InsertItem(sal_uInt16 nItemId, const Image& rImage, 303 const OUString& rStr, size_t nPos = VALUESET_APPEND, bool bShowLegend = false); 304 /// Insert an @rColor item with @rStr tooltip. 305 void InsertItem(sal_uInt16 nItemId, const Color& rColor, 306 const OUString& rStr); 307 /// Insert an User Drawn item. 308 void InsertItem(sal_uInt16 nItemId, size_t nPos = VALUESET_APPEND); 309 /// Insert an User Drawn item with @rStr tooltip. 310 void InsertItem(sal_uInt16 nItemId, const OUString& rStr, size_t nPos); 311 void RemoveItem(sal_uInt16 nItemId); 312 313 void Clear(); 314 315 size_t GetItemCount() const; 316 size_t GetItemPos( sal_uInt16 nItemId ) const; 317 sal_uInt16 GetItemId( size_t nPos ) const; 318 sal_uInt16 GetItemId( const Point& rPos ) const; 319 tools::Rectangle GetItemRect( sal_uInt16 nItemId ) const; 320 void EnableFullItemMode( bool bFullMode ); 321 322 void SetColCount( sal_uInt16 nNewCols = 1 ); GetColCount() const323 sal_uInt16 GetColCount() const 324 { 325 return mnUserCols; 326 } 327 void SetLineCount( sal_uInt16 nNewLines = 0 ); GetLineCount() const328 sal_uInt16 GetLineCount() const 329 { 330 return mnUserVisLines; 331 } 332 void SetItemWidth( tools::Long nItemWidth ); 333 void SetItemHeight( tools::Long nLineHeight ); 334 335 void SelectItem( sal_uInt16 nItemId ); GetSelectedItemId() const336 sal_uInt16 GetSelectedItemId() const 337 { 338 return mnSelItemId; 339 } GetSelectItemPos() const340 size_t GetSelectItemPos() const 341 { 342 return GetItemPos( mnSelItemId ); 343 } IsItemSelected(sal_uInt16 nItemId) const344 bool IsItemSelected( sal_uInt16 nItemId ) const 345 { 346 return !mbNoSelection && (nItemId == mnSelItemId); 347 } 348 void SetNoSelection(); IsNoSelection() const349 bool IsNoSelection() const 350 { 351 return mbNoSelection; 352 } 353 354 void RecalculateItemSizes(); 355 356 void SetItemImage( sal_uInt16 nItemId, const Image& rImage ); 357 Image GetItemImage( sal_uInt16 nItemId ) const; 358 void SetItemColor( sal_uInt16 nItemId, const Color& rColor ); 359 Color GetItemColor( sal_uInt16 nItemId ) const; 360 void SetItemData( sal_uInt16 nItemId, void* pData ); 361 void* GetItemData( sal_uInt16 nItemId ) const; 362 void SetItemText( sal_uInt16 nItemId, const OUString& rStr ); 363 OUString GetItemText( sal_uInt16 nItemId ) const; 364 void SetColor( const Color& rColor ); SetColor()365 void SetColor() 366 { 367 SetColor(COL_TRANSPARENT); 368 } IsColor() const369 bool IsColor() const 370 { 371 return !maColor.IsTransparent(); 372 } 373 374 void SetExtraSpacing( sal_uInt16 nNewSpacing ); 375 376 void Format(vcl::RenderContext const & rRenderContext); 377 void SetFormat(); 378 379 Size CalcWindowSizePixel(const Size& rItemSize, 380 sal_uInt16 nCalcCols = 0, 381 sal_uInt16 nCalcLines = 0) const; 382 Size CalcItemSizePixel(const Size& rSize) const; 383 int GetScrollWidth() const; 384 SetSelectHdl(const Link<ValueSet *,void> & rLink)385 void SetSelectHdl(const Link<ValueSet*,void>& rLink) 386 { 387 maSelectHdl = rLink; 388 } 389 SetDoubleClickHdl(const Link<ValueSet *,void> & rLink)390 void SetDoubleClickHdl(const Link<ValueSet*,void>& rLink) 391 { 392 maDoubleClickHdl = rLink; 393 } 394 GetEdgeBlending() const395 bool GetEdgeBlending() const 396 { 397 return mbEdgeBlending; 398 } 399 void SetEdgeBlending(bool bNew); 400 SaveValue()401 void SaveValue() 402 { 403 mnSavedItemId = IsNoSelection() ? -1 : GetSelectedItemId(); 404 } 405 IsValueChangedFromSaved() const406 bool IsValueChangedFromSaved() const 407 { 408 int nItemId = IsNoSelection() ? -1 : GetSelectedItemId(); 409 return mnSavedItemId != nItemId; 410 } 411 412 virtual FactoryFunction GetUITestFactory() const override; 413 }; 414 415 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 416