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 (long(1000000000)) 203 204 #define HEADERBAR_TEXTOFF 2 205 206 207 class VCL_DLLPUBLIC HeaderBar : public vcl::Window 208 { 209 private: 210 std::vector<std::unique_ptr<ImplHeadItem>> mvItemList; 211 long mnBorderOff1; 212 long mnBorderOff2; 213 long mnOffset; 214 long mnDX; 215 long mnDY; 216 long mnDragSize; 217 long mnStartPos; 218 long mnDragPos; 219 long mnMouseOff; 220 sal_uInt16 mnCurItemId; 221 sal_uInt16 mnItemDragPos; 222 bool mbDragable; 223 bool mbDrag; 224 bool mbItemDrag; 225 bool mbOutDrag; 226 bool mbButtonStyle; 227 bool mbItemMode; 228 Link<HeaderBar*,void> maStartDragHdl; 229 Link<HeaderBar*,void> maDragHdl; 230 Link<HeaderBar*,void> maEndDragHdl; 231 Link<HeaderBar*,void> maSelectHdl; 232 Link<HeaderBar*,void> maCreateAccessibleHdl; 233 234 css::uno::Reference< css::accessibility::XAccessible > 235 mxAccessible; 236 237 using Window::ImplInit; 238 VCL_DLLPRIVATE void ImplInit( WinBits nWinStyle ); 239 VCL_DLLPRIVATE void ImplInitSettings( bool bFont, bool bForeground, bool bBackground ); 240 VCL_DLLPRIVATE long ImplGetItemPos( sal_uInt16 nPos ) const; 241 VCL_DLLPRIVATE tools::Rectangle ImplGetItemRect( sal_uInt16 nPos ) const; 242 using Window::ImplHitTest; 243 VCL_DLLPRIVATE sal_uInt16 ImplHitTest( const Point& rPos, long& nMouseOff, sal_uInt16& nPos ) const; 244 VCL_DLLPRIVATE void ImplInvertDrag( sal_uInt16 nStartPos, sal_uInt16 nEndPos ); 245 VCL_DLLPRIVATE void ImplDrawItem(vcl::RenderContext& rRenderContext, sal_uInt16 nPos, bool bHigh, 246 const tools::Rectangle& rItemRect, const tools::Rectangle* pRect); 247 VCL_DLLPRIVATE void ImplDrawItem(vcl::RenderContext& rRenderContext, sal_uInt16 nPos, bool bHigh, 248 const tools::Rectangle* pRect); 249 VCL_DLLPRIVATE void ImplUpdate( sal_uInt16 nPos, 250 bool bEnd = false ); 251 VCL_DLLPRIVATE void ImplStartDrag( const Point& rPos, bool bCommand ); 252 VCL_DLLPRIVATE void ImplDrag( const Point& rPos ); 253 VCL_DLLPRIVATE void ImplEndDrag( bool bCancel ); 254 255 virtual void ApplySettings(vcl::RenderContext& rRenderContext) override; 256 257 public: 258 HeaderBar( vcl::Window* pParent, WinBits nWinBits ); 259 virtual ~HeaderBar() override; 260 261 virtual void MouseButtonDown( const MouseEvent& rMEvt ) override; 262 virtual void MouseMove( const MouseEvent& rMEvt ) override; 263 virtual void Tracking( const TrackingEvent& rTEvt ) override; 264 virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override; 265 virtual void Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, DrawFlags nFlags ) override; 266 virtual void Resize() override; 267 virtual void Command( const CommandEvent& rCEvt ) override; 268 virtual void RequestHelp( const HelpEvent& rHEvt ) override; 269 virtual void StateChanged( StateChangedType nStateChange ) override; 270 virtual void DataChanged( const DataChangedEvent& rDCEvt ) override; 271 272 virtual Size GetOptimalSize() const override; 273 274 virtual void EndDrag(); 275 virtual void Select(); 276 virtual void DoubleClick(); 277 278 void InsertItem( sal_uInt16 nItemId, const OUString& rText, 279 long nSize, HeaderBarItemBits nBits = HeaderBarItemBits::STDSTYLE, 280 sal_uInt16 nPos = HEADERBAR_APPEND ); 281 void RemoveItem( sal_uInt16 nItemId ); 282 void MoveItem( sal_uInt16 nItemId, sal_uInt16 nNewPos ); 283 void Clear(); 284 285 void SetOffset( long nNewOffset ); SetDragSize(long nNewSize)286 void SetDragSize( long nNewSize ) { mnDragSize = nNewSize; } 287 288 sal_uInt16 GetItemCount() const; 289 sal_uInt16 GetItemPos( sal_uInt16 nItemId ) const; 290 sal_uInt16 GetItemId( sal_uInt16 nPos ) const; 291 sal_uInt16 GetItemId( const Point& rPos ) const; 292 tools::Rectangle GetItemRect( sal_uInt16 nItemId ) const; GetCurItemId() const293 sal_uInt16 GetCurItemId() const { return mnCurItemId; } IsItemMode() const294 bool IsItemMode() const { return mbItemMode; } 295 296 void SetItemSize( sal_uInt16 nItemId, long nNewSize ); 297 long GetItemSize( sal_uInt16 nItemId ) const; 298 void SetItemBits( sal_uInt16 nItemId, HeaderBarItemBits nNewBits ); 299 HeaderBarItemBits GetItemBits( sal_uInt16 nItemId ) const; 300 301 void SetItemText( sal_uInt16 nItemId, const OUString& rText ); 302 OUString GetItemText( sal_uInt16 nItemId ) const; 303 304 OUString GetHelpText( sal_uInt16 nItemId ) const; 305 306 Size CalcWindowSizePixel() const; 307 308 using Window::SetHelpId; 309 SetStartDragHdl(const Link<HeaderBar *,void> & rLink)310 void SetStartDragHdl( const Link<HeaderBar*,void>& rLink ) { maStartDragHdl = rLink; } SetEndDragHdl(const Link<HeaderBar *,void> & rLink)311 void SetEndDragHdl( const Link<HeaderBar*,void>& rLink ) { maEndDragHdl = rLink; } SetSelectHdl(const Link<HeaderBar *,void> & rLink)312 void SetSelectHdl( const Link<HeaderBar*,void>& rLink ) { maSelectHdl = rLink; } SetCreateAccessibleHdl(const Link<HeaderBar *,void> & rLink)313 void SetCreateAccessibleHdl( const Link<HeaderBar*,void>& rLink ) { maCreateAccessibleHdl = rLink; } 314 IsDragable() const315 bool IsDragable() const { return mbDragable; } 316 317 /** Creates and returns the accessible object of the header bar. */ 318 virtual css::uno::Reference< css::accessibility::XAccessible > CreateAccessible() override; 319 void SetAccessible( const css::uno::Reference< css::accessibility::XAccessible >& ); 320 }; 321 322 #endif // INCLUDED_VCL_HEADBAR_HXX 323 324 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 325