1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 #ifndef _VCL_ARRANGE_HXX 25 #define _VCL_ARRANGE_HXX 26 27 #include "vcl/window.hxx" 28 29 #include <vector> 30 #include <map> 31 #include <boost/shared_ptr.hpp> 32 33 namespace vcl 34 { 35 /* some helper classes for simple window layouting 36 guidelines: 37 - a WindowArranger is not a Window 38 - a WindowArranger hierarchy manages exactly one level of child windows inside a common parent 39 this is to keep the vcl Window hierarchy flat, as some code like accelerators depend on such behavior 40 - a WindowArranger never becomes owner of a Window, windows need to be destroyed separately 41 - a WindowArranger however always is owner of its child WindowArrangers, that is the 42 WindowArranger hierarchy will keep track of its objects and delete them 43 - a managed element of a WindowArranger can either be a Window (a leaf in the hierarchy) 44 or a child WindowArranger (a node in the hierarchy), but never both 45 */ 46 47 class VCL_DLLPUBLIC WindowArranger 48 { 49 protected: 50 struct Element 51 { 52 Window* m_pElement; 53 boost::shared_ptr<WindowArranger> m_pChild; 54 sal_Int32 m_nExpandPriority; 55 Size m_aMinSize; 56 bool m_bHidden; 57 long m_nLeftBorder; 58 long m_nTopBorder; 59 long m_nRightBorder; 60 long m_nBottomBorder; 61 Elementvcl::WindowArranger::Element62 Element() 63 : m_pElement( NULL ) 64 , m_pChild() 65 , m_nExpandPriority( 0 ) 66 , m_bHidden( false ) 67 , m_nLeftBorder( 0 ) 68 , m_nTopBorder( 0 ) 69 , m_nRightBorder( 0 ) 70 , m_nBottomBorder( 0 ) 71 {} 72 Elementvcl::WindowArranger::Element73 Element( Window* i_pWin, 74 boost::shared_ptr<WindowArranger> const & i_pChild = boost::shared_ptr<WindowArranger>(), 75 sal_Int32 i_nExpandPriority = 0, 76 const Size& i_rMinSize = Size() 77 ) 78 : m_pElement( i_pWin ) 79 , m_pChild( i_pChild ) 80 , m_nExpandPriority( i_nExpandPriority ) 81 , m_aMinSize( i_rMinSize ) 82 , m_bHidden( false ) 83 , m_nLeftBorder( 0 ) 84 , m_nTopBorder( 0 ) 85 , m_nRightBorder( 0 ) 86 , m_nBottomBorder( 0 ) 87 {} 88 deleteChildvcl::WindowArranger::Element89 void deleteChild() { m_pChild.reset(); } 90 91 sal_Int32 getExpandPriority() const; 92 Size getOptimalSize( WindowSizeType ) const; 93 bool isVisible() const; 94 void setPosSize( const Point&, const Size& ); 95 }; 96 97 Window* m_pParentWindow; 98 WindowArranger* m_pParentArranger; 99 Rectangle m_aManagedArea; 100 long m_nOuterBorder; 101 102 rtl::OUString m_aIdentifier; 103 104 virtual Element* getElement( size_t i_nIndex ) = 0; getConstElement(size_t i_nIndex) const105 const Element* getConstElement( size_t i_nIndex ) const 106 { return const_cast<WindowArranger*>(this)->getElement( i_nIndex ); } 107 108 109 public: 110 static long getDefaultBorder(); 111 getBorderValue(long nBorder)112 static long getBorderValue( long nBorder ) 113 { return nBorder >= 0 ? nBorder : -nBorder * getDefaultBorder(); } 114 WindowArranger(WindowArranger * i_pParent=NULL)115 WindowArranger( WindowArranger* i_pParent = NULL ) 116 : m_pParentWindow( i_pParent ? i_pParent->m_pParentWindow : NULL ) 117 , m_pParentArranger( i_pParent ) 118 , m_nOuterBorder( 0 ) 119 {} 120 virtual ~WindowArranger(); 121 122 // ask what would be the optimal size 123 virtual Size getOptimalSize( WindowSizeType ) const = 0; 124 // call Resize to trigger layouting inside the managed area 125 // without function while parent window is unset 126 virtual void resize() = 0; 127 // avoid this if possible, using the constructor instead 128 // there can be only one parent window and all managed windows MUST 129 // be direct children of that window 130 // violating that condition will result in undefined behavior 131 virtual void setParentWindow( Window* ); 132 133 virtual void setParent( WindowArranger* ); 134 135 virtual size_t countElements() const = 0; getChild(size_t i_nIndex) const136 boost::shared_ptr<WindowArranger> getChild( size_t i_nIndex ) const 137 { 138 const Element* pEle = getConstElement( i_nIndex ); 139 return pEle ? pEle->m_pChild : boost::shared_ptr<WindowArranger>(); 140 } getWindow(size_t i_nIndex) const141 Window* getWindow( size_t i_nIndex ) const 142 { 143 const Element* pEle = getConstElement( i_nIndex ); 144 return pEle ? pEle->m_pElement : NULL; 145 } 146 147 virtual bool isVisible() const; // true if any element is visible 148 149 virtual com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue > getProperties() const; 150 virtual void setProperties( const com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >& ); 151 getExpandPriority(size_t i_nIndex) const152 sal_Int32 getExpandPriority( size_t i_nIndex ) const 153 { 154 const Element* pEle = getConstElement( i_nIndex ); 155 return pEle ? pEle->getExpandPriority() : 0; 156 } 157 getMinimumSize(size_t i_nIndex) const158 Size getMinimumSize( size_t i_nIndex ) const 159 { 160 const Element* pEle = getConstElement( i_nIndex ); 161 return pEle ? pEle->m_aMinSize : Size(); 162 } 163 setMinimumSize(size_t i_nIndex,const Size & i_rMinSize)164 bool setMinimumSize( size_t i_nIndex, const Size& i_rMinSize ) 165 { 166 Element* pEle = getElement( i_nIndex ); 167 if( pEle ) 168 pEle->m_aMinSize = i_rMinSize; 169 return pEle != NULL; 170 } 171 setBorders(size_t i_nIndex,long i_nLeft,long i_nTop,long i_nRight,long i_nBottom)172 void setBorders( size_t i_nIndex, long i_nLeft, long i_nTop, long i_nRight, long i_nBottom ) 173 { 174 Element* pEle = getElement( i_nIndex ); 175 if( pEle ) 176 { 177 pEle->m_nLeftBorder = i_nLeft; 178 pEle->m_nRightBorder = i_nRight; 179 pEle->m_nTopBorder = i_nTop; 180 pEle->m_nBottomBorder = i_nBottom; 181 } 182 } 183 getBorders(size_t i_nIndex,long * i_pLeft=NULL,long * i_pTop=NULL,long * i_pRight=NULL,long * i_pBottom=NULL) const184 void getBorders( size_t i_nIndex, long* i_pLeft = NULL, long* i_pTop = NULL, long* i_pRight = NULL, long* i_pBottom = NULL ) const 185 { 186 const Element* pEle = getConstElement( i_nIndex ); 187 if( pEle ) 188 { 189 if( i_pLeft ) *i_pLeft = pEle->m_nLeftBorder; 190 if( i_pTop ) *i_pTop = pEle->m_nTopBorder; 191 if( i_pRight ) *i_pRight = pEle->m_nRightBorder; 192 if( i_pBottom ) *i_pBottom = pEle->m_nBottomBorder; 193 } 194 } 195 196 197 void show( bool i_bShow = true, bool i_bImmediateUpdate = true ); 198 setManagedArea(const Rectangle & i_rArea)199 void setManagedArea( const Rectangle& i_rArea ) 200 { 201 m_aManagedArea = i_rArea; 202 resize(); 203 } getManagedArea() const204 const Rectangle& getManagedArea() const { return m_aManagedArea; } 205 setOuterBorder(long i_nBorder)206 void setOuterBorder( long i_nBorder ) 207 { 208 m_nOuterBorder = i_nBorder; 209 resize(); 210 } 211 getIdentifier() const212 const rtl::OUString getIdentifier() const 213 { return m_aIdentifier; } 214 setIdentifier(const rtl::OUString & i_rId)215 void setIdentifier( const rtl::OUString& i_rId ) 216 { m_aIdentifier = i_rId; } 217 }; 218 219 class VCL_DLLPUBLIC RowOrColumn : public WindowArranger 220 { 221 long m_nBorderWidth; 222 bool m_bColumn; 223 224 std::vector< WindowArranger::Element > m_aElements; 225 226 void distributeRowWidth( std::vector< Size >& io_rSizes, long i_nUsedWidth, long i_nExtraWidth ); 227 void distributeColumnHeight( std::vector< Size >& io_rSizes, long i_nUsedHeight, long i_nExtraHeight ); 228 protected: getElement(size_t i_nIndex)229 virtual Element* getElement( size_t i_nIndex ) 230 { return i_nIndex < m_aElements.size() ? &m_aElements[ i_nIndex ] : 0; } 231 232 public: RowOrColumn(WindowArranger * i_pParent=NULL,bool bColumn=true,long i_nBorderWidth=-1)233 RowOrColumn( WindowArranger* i_pParent = NULL, 234 bool bColumn = true, long i_nBorderWidth = -1 ) 235 : WindowArranger( i_pParent ) 236 , m_nBorderWidth( i_nBorderWidth ) 237 , m_bColumn( bColumn ) 238 {} 239 240 virtual ~RowOrColumn(); 241 242 virtual Size getOptimalSize( WindowSizeType ) const; 243 virtual void resize(); countElements() const244 virtual size_t countElements() const { return m_aElements.size(); } 245 246 // add a managed window at the given index 247 // an index smaller than zero means add the window at the end 248 size_t addWindow( Window*, sal_Int32 i_nExpandPrio = 0, const Size& i_rMinSize = Size(), size_t i_nIndex = ~0 ); 249 void remove( Window* ); 250 251 size_t addChild( boost::shared_ptr<WindowArranger> const &, sal_Int32 i_nExpandPrio = 0, size_t i_nIndex = ~0 ); 252 // convenience: use for addChild( new WindowArranger( ... ) ) constructs addChild(WindowArranger * i_pNewChild,sal_Int32 i_nExpandPrio=0,size_t i_nIndex=~0)253 size_t addChild( WindowArranger* i_pNewChild, sal_Int32 i_nExpandPrio = 0, size_t i_nIndex = ~0 ) 254 { return addChild( boost::shared_ptr<WindowArranger>( i_pNewChild ), i_nExpandPrio, i_nIndex ); } 255 void remove( boost::shared_ptr<WindowArranger> const & ); 256 getBorderWidth() const257 long getBorderWidth() const { return m_nBorderWidth; } 258 }; 259 260 class VCL_DLLPUBLIC LabeledElement : public WindowArranger 261 { 262 WindowArranger::Element m_aLabel; 263 WindowArranger::Element m_aElement; 264 long m_nDistance; 265 long m_nLabelColumnWidth; 266 int m_nLabelStyle; 267 protected: getElement(size_t i_nIndex)268 virtual Element* getElement( size_t i_nIndex ) 269 { 270 if( i_nIndex == 0 ) 271 return &m_aLabel; 272 else if( i_nIndex == 1 ) 273 return &m_aElement; 274 return 0; 275 } 276 277 public: LabeledElement(WindowArranger * i_pParent=NULL,int i_nLabelStyle=0,long i_nDistance=-1)278 LabeledElement( WindowArranger* i_pParent = NULL, int i_nLabelStyle = 0, long i_nDistance = -1 ) 279 : WindowArranger( i_pParent ) 280 , m_nDistance( i_nDistance ) 281 , m_nLabelColumnWidth( 0 ) 282 , m_nLabelStyle( i_nLabelStyle ) 283 {} 284 285 virtual ~LabeledElement(); 286 287 virtual Size getOptimalSize( WindowSizeType ) const; 288 virtual void resize(); countElements() const289 virtual size_t countElements() const { return 2; } 290 291 void setLabel( Window* ); 292 void setLabel( boost::shared_ptr<WindowArranger> const & ); 293 void setElement( Window* ); 294 void setElement( boost::shared_ptr<WindowArranger> const & ); setLabelColumnWidth(long i_nWidth)295 void setLabelColumnWidth( long i_nWidth ) 296 { m_nLabelColumnWidth = i_nWidth; } 297 getLabelSize(WindowSizeType i_eType) const298 Size getLabelSize( WindowSizeType i_eType ) const 299 { return m_aLabel.getOptimalSize( i_eType ); } getElementSize(WindowSizeType i_eType) const300 Size getElementSize( WindowSizeType i_eType ) const 301 { return m_aElement.getOptimalSize( i_eType ); } 302 }; 303 304 class VCL_DLLPUBLIC LabelColumn : public RowOrColumn 305 { 306 long getLabelWidth() const; 307 public: LabelColumn(WindowArranger * i_pParent=NULL,long i_nBorderWidth=-1)308 LabelColumn( WindowArranger* i_pParent = NULL, long i_nBorderWidth = -1 ) 309 : RowOrColumn( i_pParent, true, i_nBorderWidth ) 310 {} 311 virtual ~LabelColumn(); 312 313 virtual Size getOptimalSize( WindowSizeType ) const; 314 virtual void resize(); 315 316 // returns the index of the added label 317 size_t addRow( Window* i_pLabel, boost::shared_ptr<WindowArranger> const& i_rElement, long i_nIndent = 0 ); 318 size_t addRow( Window* i_pLabel, Window* i_pElement, long i_nIndent = 0, const Size& i_rElementMinSize = Size() ); 319 }; 320 321 class VCL_DLLPUBLIC Indenter : public WindowArranger 322 { 323 long m_nIndent; 324 WindowArranger::Element m_aElement; 325 326 protected: getElement(size_t i_nIndex)327 virtual Element* getElement( size_t i_nIndex ) 328 { return i_nIndex == 0 ? &m_aElement : NULL; } 329 330 public: Indenter(WindowArranger * i_pParent=NULL,long i_nIndent=3* getDefaultBorder ())331 Indenter( WindowArranger* i_pParent = NULL, long i_nIndent = 3*getDefaultBorder() ) 332 : WindowArranger( i_pParent ) 333 , m_nIndent( i_nIndent ) 334 {} 335 336 virtual ~Indenter(); 337 338 virtual Size getOptimalSize( WindowSizeType ) const; 339 virtual void resize(); countElements() const340 virtual size_t countElements() const { return (m_aElement.m_pElement != 0 || m_aElement.m_pChild != 0) ? 1 : 0; } 341 setIndent(long i_nIndent)342 void setIndent( long i_nIndent ) 343 { 344 m_nIndent = i_nIndent; 345 resize(); 346 } 347 348 void setWindow( Window*, sal_Int32 i_nExpandPrio = 0 ); 349 void setChild( boost::shared_ptr<WindowArranger> const &, sal_Int32 i_nExpandPrio = 0 ); 350 // convenience: use for setChild( new WindowArranger( ... ) ) constructs setChild(WindowArranger * i_pChild,sal_Int32 i_nExpandPrio=0)351 void setChild( WindowArranger* i_pChild, sal_Int32 i_nExpandPrio = 0 ) 352 { setChild( boost::shared_ptr<WindowArranger>( i_pChild ), i_nExpandPrio ); } 353 }; 354 355 class VCL_DLLPUBLIC Spacer : public WindowArranger 356 { 357 WindowArranger::Element m_aElement; 358 Size m_aSize; 359 360 protected: getElement(size_t i_nIndex)361 virtual Element* getElement( size_t i_nIndex ) 362 { return i_nIndex == 0 ? &m_aElement : NULL; } 363 364 public: Spacer(WindowArranger * i_pParent=NULL,sal_Int32 i_nPrio=20,const Size & i_rSize=Size (0,0))365 Spacer( WindowArranger* i_pParent = NULL, sal_Int32 i_nPrio = 20, const Size& i_rSize = Size( 0, 0 ) ) 366 : WindowArranger( i_pParent ) 367 , m_aElement( NULL, boost::shared_ptr<WindowArranger>(), i_nPrio ) 368 , m_aSize( i_rSize ) 369 {} 370 ~Spacer()371 virtual ~Spacer() {} 372 getOptimalSize(WindowSizeType) const373 virtual Size getOptimalSize( WindowSizeType ) const 374 { return m_aSize; } resize()375 virtual void resize() {} setParentWindow(Window *)376 virtual void setParentWindow( Window* ) {} countElements() const377 virtual size_t countElements() const { return 1; } isVisible() const378 virtual bool isVisible() const { return true; } 379 }; 380 381 class VCL_DLLPUBLIC MatrixArranger : public WindowArranger 382 { 383 long m_nBorderX; 384 long m_nBorderY; 385 386 struct MatrixElement : public WindowArranger::Element 387 { 388 sal_uInt32 m_nX; 389 sal_uInt32 m_nY; 390 MatrixElementvcl::MatrixArranger::MatrixElement391 MatrixElement() 392 : WindowArranger::Element() 393 , m_nX( 0 ) 394 , m_nY( 0 ) 395 {} 396 MatrixElementvcl::MatrixArranger::MatrixElement397 MatrixElement( Window* i_pWin, 398 sal_uInt32 i_nX, sal_uInt32 i_nY, 399 boost::shared_ptr<WindowArranger> const & i_pChild = boost::shared_ptr<WindowArranger>(), 400 sal_Int32 i_nExpandPriority = 0, 401 const Size& i_rMinSize = Size() 402 ) 403 : WindowArranger::Element( i_pWin, i_pChild, i_nExpandPriority, i_rMinSize ) 404 , m_nX( i_nX ) 405 , m_nY( i_nY ) 406 { 407 } 408 }; 409 410 std::vector< MatrixElement > m_aElements; 411 std::map< sal_uInt64, size_t > m_aMatrixMap; // maps (x | (y << 32)) to index in m_aElements 412 getMap(sal_uInt32 i_nX,sal_uInt32 i_nY)413 sal_uInt64 getMap( sal_uInt32 i_nX, sal_uInt32 i_nY ) 414 { return static_cast< sal_uInt64 >(i_nX) | (static_cast< sal_uInt64>(i_nY) << 32 ); } 415 416 static void distributeExtraSize( std::vector<long>& io_rSizes, const std::vector<sal_Int32>& i_rPrios, long i_nExtraWidth ); 417 418 Size getOptimalSize( WindowSizeType, 419 std::vector<long>& o_rColumnWidths, std::vector<long>& o_rRowHeights, 420 std::vector<sal_Int32>& o_rColumnPrio, std::vector<sal_Int32>& o_rRowPrio 421 ) const; 422 protected: getElement(size_t i_nIndex)423 virtual Element* getElement( size_t i_nIndex ) 424 { return i_nIndex < m_aElements.size() ? &m_aElements[ i_nIndex ] : 0; } 425 426 public: MatrixArranger(WindowArranger * i_pParent=NULL,long i_nBorderX=-1,long i_nBorderY=-1)427 MatrixArranger( WindowArranger* i_pParent = NULL, 428 long i_nBorderX = -1, 429 long i_nBorderY = -1 ) 430 : WindowArranger( i_pParent ) 431 , m_nBorderX( i_nBorderX ) 432 , m_nBorderY( i_nBorderY ) 433 {} 434 435 virtual ~MatrixArranger(); 436 437 virtual Size getOptimalSize( WindowSizeType ) const; 438 virtual void resize(); countElements() const439 virtual size_t countElements() const { return m_aElements.size(); } 440 441 // add a managed window at the given matrix position 442 size_t addWindow( Window*, sal_uInt32 i_nX, sal_uInt32 i_nY, sal_Int32 i_nExpandPrio = 0, const Size& i_rMinSize = Size() ); 443 void remove( Window* ); 444 445 size_t addChild( boost::shared_ptr<WindowArranger> const &, sal_uInt32 i_nX, sal_uInt32 i_nY, sal_Int32 i_nExpandPrio = 0 ); 446 // convenience: use for addChild( new WindowArranger( ... ) ) constructs addChild(WindowArranger * i_pNewChild,sal_uInt32 i_nX,sal_uInt32 i_nY,sal_Int32 i_nExpandPrio=0)447 size_t addChild( WindowArranger* i_pNewChild, sal_uInt32 i_nX, sal_uInt32 i_nY, sal_Int32 i_nExpandPrio = 0 ) 448 { return addChild( boost::shared_ptr<WindowArranger>( i_pNewChild ), i_nX, i_nY, i_nExpandPrio ); } 449 void remove( boost::shared_ptr<WindowArranger> const & ); 450 }; 451 452 } 453 454 #endif 455 456