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 #ifndef INCLUDED_VCL_HEADBAR_HXX 21 #define INCLUDED_VCL_HEADBAR_HXX 22 23 #include <vcl/dllapi.h> 24 #include <tools/link.hxx> 25 #include <vcl/window.hxx> 26 #include <o3tl/typed_flags_set.hxx> 27 #include <memory> 28 29 /************************************************************************* 30 31 Description 32 ============ 33 34 class HeaderBar 35 36 This class serves for displaying a header bar. A header bar can display 37 texts, images or both of them. The items can be changed in size, dragged or 38 clicked at. In many cases, it makes, for example, sense to use this control 39 in combination with a SvTabListBox. 40 41 -------------------------------------------------------------------------- 42 43 WinBits 44 45 WB_BORDER a border is drawn in the top and in the bottom 46 WB_BOTTOMBORDER a border is drawn in the bottom 47 WB_BUTTONSTYLE The items look like buttons, otherwise they are flat. 48 WB_3DLOOK 3D look 49 WB_DRAG items can be dragged 50 WB_STDHEADERBAR WB_BUTTONSTYLE | WB_BOTTOMBORDER 51 52 -------------------------------------------------------------------------- 53 54 ItemBits 55 56 HeaderBarItemBits::LEFT content is displayed in the item left-justified 57 HeaderBarItemBits::CENTER content is displayed in the item centred 58 HeaderBarItemBits::RIGHT content is displayed in the item right-justified 59 HeaderBarItemBits::TOP content is displayed in the item at the upper border 60 HeaderBarItemBits::VCENTER content is displayed in the item vertically centred 61 HeaderBarItemBits::BOTTOM content is displayed in the item at the bottom border 62 HeaderBarItemBits::LEFTIMAGE in case of text and image, the image is displayed left of the text 63 HeaderBarItemBits::RIGHTIMAGE in case of text and image, the image is displayed right of the text 64 HeaderBarItemBits::FIXED item cannot be changed in size 65 HeaderBarItemBits::FIXEDPOS item cannot be moved 66 HeaderBarItemBits::CLICKABLE item is clickable 67 (select handler is only called on MouseButtonUp) 68 HeaderBarItemBits::FLAT item is displayed in a flat way, even if WB_BUTTONSTYLE is set 69 HeaderBarItemBits::DOWNARROW An arrow pointing downwards is displayed behind the text, 70 which should, for example, be shown, when after this item, 71 a corresponding list is sorted in descending order. 72 The status of the arrow can be set/reset with SetItemBits(). 73 HeaderBarItemBits::UPARROW An arrow pointing upwards is displayed behind the text, 74 which should, for example, be shown, when after this item, 75 a corresponding list is sorted in ascending order. 76 The status of the arrow can be set/reset with SetItemBits(). 77 HeaderBarItemBits::USERDRAW For this item, the UserDraw handler is called as well. 78 HeaderBarItemBits::STDSTYLE (HeaderBarItemBits::LEFT | HeaderBarItemBits::LEFTIMAGE | HeaderBarItemBits::CLICKABLE) 79 80 -------------------------------------------------------------------------- 81 82 Handler 83 84 Select() Is called, when the item is clicked. If HeaderBarItemBits::CLICKABLE 85 is set in the item and not HeaderBarItemBits::FLAT, the handler is only 86 called in the MouseButtonUp handler, when the mouse has been 87 released over the item. In this case, the Select handler 88 behaves like it does with a ToolBox button. 89 DoubleClick() This handler is called, when an item is double-clicked. 90 Whether the item or the separator has been clicked, can 91 be determined by IsItemMode(). Normally, when a separator 92 is double-clicked, the optimal column width should be 93 calculated and should be set. 94 StartDrag() This handler is called, when dragging is started resp. 95 an item has been clicked. At the latest in this handler, 96 the size of the size-line should be set with 97 SetDragSize(), if IsItemMode() returns false. 98 Drag() This handler is called, when dragging is taking place. 99 If no size is set with SetDragSize(), this handler can 100 be used to draw the line in the neighbouring window by 101 oneself. The current dragging position can be requested 102 with GetDragPos(). In every case, IsItemMode() 103 should be checked to find out whether a separator is 104 dragged as well. 105 EndDrag() This handler is called, when a dragging process has been 106 stopped. If GetCurItemId() returns 0 in the EndDrag handler, 107 the drag process was aborted. If this is not the case and 108 IsItemMode() returns false, the new size of the dragged 109 item should be requested using GetItemSize() and it 110 should be taken over in the corresponding control. 111 If IsItemMode() returns true, GetCurItemId() 112 returns an Id and IsItemDrag() returns true, this 113 item has been dragged. In this case, the new position 114 should be requested using GetItemPos() and the data 115 in the corresponding control should be adapted. 116 Otherwise, the position to which the item has been dragged 117 could also be requested with GetItemDragPos(). 118 119 Further methods that are important for the handler. 120 121 GetCurItemId() Returns the id of the item, for which the handler has 122 currently been called. Only returns a valid id in the 123 handlers Select(), DoubleClick(), StartDrag(), 124 Drag() and EndDrag(). In the EndDrag handler, 125 this method returns the id of the dragged item or 0, 126 if the drag process has been aborted. 127 GetItemDragPos() Returns the position, at which an item has been moved. 128 HEADERBAR_ITEM_NOTFOUND is returned, if the process 129 has been aborted or no ItemDrag is active. 130 IsItemMode() This method can be used to determine whether the 131 handler has been called for an item or a separator. 132 true - handler was called for the item 133 false - handler was called for the separator 134 IsItemDrag() This method can be used to determine whether an item 135 has been dragged or selected. 136 true - item is dragged 137 false - item is selected 138 SetDragSize() This method is used to set the size of the separating 139 line that is drawn by the control. It should be 140 equivalent to the height of the neighbouring window. 141 The height of the HeaderBar is added automatically. 142 143 -------------------------------------------------------------------------- 144 145 Further methods 146 147 SetOffset() This method sets the offset, from which on the 148 items are shown. This is needed when the 149 corresponding window is scrolled. 150 CalcWindowSizePixel() This method can be used to calculate the height 151 of the window, so that the content of the item 152 can be displayed. 153 154 -------------------------------------------------------------------------- 155 156 Tips and tricks: 157 158 1) ContextMenu 159 If a context sensitive PopupMenu should be shown, the command 160 handler must be overlaid. Using GetItemId() and when passing the 161 mouse position, it can be determined whether the mouse click has been 162 carried out over an item resp. over which item the mouse click has been 163 carried out. 164 165 2) last item 166 If ButtonStyle has been set, it looks better, if an empty item is 167 set at the end which takes up the remaining space. 168 In order to do that, you can insert an item with an empty string and 169 pass HEADERBAR_FULLSIZE as size. For such an item, you should not set 170 HeaderBarItemBits::CLICKABLE, but HeaderBarItemBits::FIXEDPOS. 171 172 *************************************************************************/ 173 174 class ImplHeadItem; 175 176 #define WB_BOTTOMBORDER (WinBits(0x0400)) 177 #define WB_BUTTONSTYLE (WinBits(0x0800)) 178 #define WB_STDHEADERBAR (WB_BUTTONSTYLE | WB_BOTTOMBORDER) 179 180 enum class HeaderBarItemBits 181 { 182 NONE = 0x0000, 183 LEFT = 0x0001, 184 CENTER = 0x0002, 185 RIGHT = 0x0004, 186 LEFTIMAGE = 0x0010, 187 RIGHTIMAGE = 0x0020, 188 CLICKABLE = 0x0400, 189 FLAT = 0x0800, 190 DOWNARROW = 0x1000, 191 UPARROW = 0x2000, 192 STDSTYLE = LEFT | LEFTIMAGE | CLICKABLE, 193 }; 194 195 namespace o3tl 196 { 197 template<> struct typed_flags<HeaderBarItemBits> : is_typed_flags<HeaderBarItemBits, 0x3c37> {}; 198 } 199 200 #define HEADERBAR_APPEND (sal_uInt16(0xFFFF)) 201 #define HEADERBAR_ITEM_NOTFOUND (sal_uInt16(0xFFFF)) 202 #define HEADERBAR_FULLSIZE (tools::Long(1000000000)) 203 204 class VCL_DLLPUBLIC HeaderBar : public vcl::Window 205 { 206 private: 207 std::vector<std::unique_ptr<ImplHeadItem>> mvItemList; 208 tools::Long mnBorderOff1; 209 tools::Long mnBorderOff2; 210 tools::Long mnOffset; 211 tools::Long mnDX; 212 tools::Long mnDY; 213 tools::Long mnDragSize; 214 tools::Long mnStartPos; 215 tools::Long mnDragPos; 216 tools::Long mnMouseOff; 217 sal_uInt16 mnCurItemId; 218 sal_uInt16 mnItemDragPos; 219 bool mbDragable; 220 bool mbDrag; 221 bool mbItemDrag; 222 bool mbOutDrag; 223 bool mbButtonStyle; 224 bool mbItemMode; 225 Link<HeaderBar*,void> maStartDragHdl; 226 Link<HeaderBar*,void> maEndDragHdl; 227 Link<HeaderBar*,void> maSelectHdl; 228 Link<HeaderBar*,void> maCreateAccessibleHdl; 229 230 css::uno::Reference< css::accessibility::XAccessible > 231 mxAccessible; 232 233 using Window::ImplInit; 234 VCL_DLLPRIVATE void ImplInit( WinBits nWinStyle ); 235 VCL_DLLPRIVATE void ImplInitSettings( bool bFont, bool bForeground, bool bBackground ); 236 VCL_DLLPRIVATE tools::Long ImplGetItemPos( sal_uInt16 nPos ) const; 237 VCL_DLLPRIVATE tools::Rectangle ImplGetItemRect( sal_uInt16 nPos ) const; 238 VCL_DLLPRIVATE sal_uInt16 ImplDoHitTest( const Point& rPos, tools::Long& nMouseOff, sal_uInt16& nPos ) const; 239 VCL_DLLPRIVATE void ImplInvertDrag( sal_uInt16 nStartPos, sal_uInt16 nEndPos ); 240 VCL_DLLPRIVATE void ImplDrawItem(vcl::RenderContext& rRenderContext, sal_uInt16 nPos, bool bHigh, 241 const tools::Rectangle& rItemRect, const tools::Rectangle* pRect); 242 VCL_DLLPRIVATE void ImplDrawItem(vcl::RenderContext& rRenderContext, sal_uInt16 nPos, bool bHigh, 243 const tools::Rectangle* pRect); 244 VCL_DLLPRIVATE void ImplUpdate( sal_uInt16 nPos, 245 bool bEnd = false ); 246 VCL_DLLPRIVATE void ImplStartDrag( const Point& rPos, bool bCommand ); 247 VCL_DLLPRIVATE void ImplDrag( const Point& rPos ); 248 VCL_DLLPRIVATE void ImplEndDrag( bool bCancel ); 249 250 virtual void ApplySettings(vcl::RenderContext& rRenderContext) override; 251 252 public: 253 HeaderBar( vcl::Window* pParent, WinBits nWinBits ); 254 virtual ~HeaderBar() override; 255 256 virtual void MouseButtonDown( const MouseEvent& rMEvt ) override; 257 virtual void MouseMove( const MouseEvent& rMEvt ) override; 258 virtual void Tracking( const TrackingEvent& rTEvt ) override; 259 virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override; 260 virtual void Draw( OutputDevice* pDev, const Point& rPos, DrawFlags nFlags ) override; 261 virtual void Resize() override; 262 virtual void Command( const CommandEvent& rCEvt ) override; 263 virtual void RequestHelp( const HelpEvent& rHEvt ) override; 264 virtual void StateChanged( StateChangedType nStateChange ) override; 265 virtual void DataChanged( const DataChangedEvent& rDCEvt ) override; 266 267 virtual Size GetOptimalSize() const override; 268 269 virtual void EndDrag(); 270 virtual void Select(); 271 virtual void DoubleClick(); 272 273 void InsertItem( sal_uInt16 nItemId, const OUString& rText, 274 tools::Long nSize, HeaderBarItemBits nBits = HeaderBarItemBits::STDSTYLE, 275 sal_uInt16 nPos = HEADERBAR_APPEND ); 276 void RemoveItem( sal_uInt16 nItemId ); 277 void MoveItem( sal_uInt16 nItemId, sal_uInt16 nNewPos ); 278 void Clear(); 279 280 void SetOffset( tools::Long nNewOffset ); SetDragSize(tools::Long nNewSize)281 void SetDragSize( tools::Long nNewSize ) { mnDragSize = nNewSize; } 282 283 sal_uInt16 GetItemCount() const; 284 sal_uInt16 GetItemPos( sal_uInt16 nItemId ) const; 285 sal_uInt16 GetItemId( sal_uInt16 nPos ) const; 286 sal_uInt16 GetItemId( const Point& rPos ) const; 287 tools::Rectangle GetItemRect( sal_uInt16 nItemId ) const; GetCurItemId() const288 sal_uInt16 GetCurItemId() const { return mnCurItemId; } IsItemMode() const289 bool IsItemMode() const { return mbItemMode; } 290 291 void SetItemSize( sal_uInt16 nItemId, tools::Long nNewSize ); 292 tools::Long GetItemSize( sal_uInt16 nItemId ) const; 293 void SetItemBits( sal_uInt16 nItemId, HeaderBarItemBits nNewBits ); 294 HeaderBarItemBits GetItemBits( sal_uInt16 nItemId ) const; 295 296 void SetItemText( sal_uInt16 nItemId, const OUString& rText ); 297 OUString GetItemText( sal_uInt16 nItemId ) const; 298 299 OUString GetHelpText( sal_uInt16 nItemId ) const; 300 301 Size CalcWindowSizePixel() const; 302 303 using Window::SetHelpId; 304 SetStartDragHdl(const Link<HeaderBar *,void> & rLink)305 void SetStartDragHdl( const Link<HeaderBar*,void>& rLink ) { maStartDragHdl = rLink; } SetEndDragHdl(const Link<HeaderBar *,void> & rLink)306 void SetEndDragHdl( const Link<HeaderBar*,void>& rLink ) { maEndDragHdl = rLink; } SetSelectHdl(const Link<HeaderBar *,void> & rLink)307 void SetSelectHdl( const Link<HeaderBar*,void>& rLink ) { maSelectHdl = rLink; } SetCreateAccessibleHdl(const Link<HeaderBar *,void> & rLink)308 void SetCreateAccessibleHdl( const Link<HeaderBar*,void>& rLink ) { maCreateAccessibleHdl = rLink; } 309 IsDragable() const310 bool IsDragable() const { return mbDragable; } 311 312 /** Creates and returns the accessible object of the header bar. */ 313 virtual css::uno::Reference< css::accessibility::XAccessible > CreateAccessible() override; 314 void SetAccessible( const css::uno::Reference< css::accessibility::XAccessible >& ); 315 }; 316 317 #endif // INCLUDED_VCL_HEADBAR_HXX 318 319 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 320