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 #include "precompiled_sfx2.hxx" 23 24 #include "Deck.hxx" 25 #include "DeckDescriptor.hxx" 26 #include "DrawHelper.hxx" 27 #include "DeckTitleBar.hxx" 28 #include "Panel.hxx" 29 #include "Theme.hxx" 30 31 #include <tools/SvBorder.hxx> 32 33 34 namespace sfx2 { namespace sidebar { 35 36 37 namespace { 38 static const sal_Int32 MinimalPanelHeight (25); 39 } 40 41 42 43 Deck::Deck ( 44 const DeckDescriptor& rDeckDescriptor, 45 Window* pParentWindow) 46 : Window(pParentWindow), 47 msId(rDeckDescriptor.msId), 48 mpTitleBar(new DeckTitleBar(rDeckDescriptor.msTitle, this)), 49 maIcon(), 50 msIconURL(rDeckDescriptor.msIconURL), 51 msHighContrastIconURL(rDeckDescriptor.msHighContrastIconURL), 52 mpFiller(NULL) 53 { 54 SetBackground(Wallpaper()); 55 } 56 57 58 59 60 Deck::~Deck (void) 61 { 62 Dispose(); 63 } 64 65 66 67 68 void Deck::Dispose (void) 69 { 70 ::std::vector<Panel*> aPanels; 71 aPanels.swap(maPanels); 72 for (::std::vector<Panel*>::const_iterator 73 iPanel(aPanels.begin()), 74 iEnd(aPanels.end()); 75 iPanel!=iEnd; 76 ++iPanel) 77 { 78 (*iPanel)->Dispose(); 79 } 80 } 81 82 83 84 85 const ::rtl::OUString& Deck::GetId (void) const 86 { 87 return msId; 88 } 89 90 91 92 93 TitleBar* Deck::GetTitleBar (void) const 94 { 95 return mpTitleBar; 96 } 97 98 99 100 101 Rectangle Deck::GetContentArea (void) const 102 { 103 const Size aWindowSize (GetSizePixel()); 104 const SvBorder aPadding (Theme::GetDeckPadding()); 105 const int nBorderSize (Theme::GetBorderSize()); 106 107 return Rectangle( 108 aPadding.Left() + nBorderSize, 109 aPadding.Top() + nBorderSize, 110 aWindowSize.Width() - 1 - aPadding.Right() - nBorderSize, 111 aWindowSize.Height() - 1 - aPadding.Bottom() - nBorderSize); 112 } 113 114 115 116 117 ::rtl::OUString Deck::GetIconURL (const bool bIsHighContrastModeActive) const 118 { 119 if (bIsHighContrastModeActive) 120 return msHighContrastIconURL; 121 else 122 return msIconURL; 123 } 124 125 126 127 128 void Deck::Paint (const Rectangle& rUpdateArea) 129 { 130 const Size aWindowSize (GetSizePixel()); 131 const SvBorder aPadding (Theme::GetDeckPadding()); 132 133 // Paint deck background outside the border. 134 DrawHelper::DrawBorder( 135 *this, 136 Rectangle( 137 0, 138 0, 139 aWindowSize.Width() - 1, 140 aWindowSize.Height() - 1), 141 aPadding, 142 Theme::GetDeckBackground(), 143 Theme::GetDeckBackground()); 144 145 // Paint the border. 146 const int nBorderSize (Theme::GetBorderSize()); 147 DrawHelper::DrawBorder( 148 *this, 149 Rectangle( 150 aPadding.Left(), 151 aPadding.Top(), 152 aWindowSize.Width() - 1 - aPadding.Right(), 153 aWindowSize.Height() - 1 - aPadding.Bottom()), 154 SvBorder(nBorderSize, nBorderSize, nBorderSize, nBorderSize), 155 Theme::GetHorizontalBorderPaint(), 156 Theme::GetVerticalBorderPaint()); 157 } 158 159 160 161 162 void Deck::SetPanels (const ::std::vector<Panel*>& rPanels) 163 { 164 maPanels.resize(rPanels.size()); 165 ::std::copy(rPanels.begin(), rPanels.end(), maPanels.begin()); 166 167 RequestLayout(); 168 } 169 170 171 172 173 void Deck::RequestLayout (void) 174 { 175 switch(maPanels.size()) 176 { 177 case 0: 178 // This basically is an error but there is not much that 179 // we can do about it. 180 OSL_ASSERT(maPanels.size()>0); 181 break; 182 183 case 1: 184 if (maPanels[0]->IsTitleBarOptional()) 185 { 186 // There is only one panel in the deck and its title 187 // bar is optional => do not draw the title bar. 188 LayoutSinglePanel(); 189 } 190 else 191 LayoutMultiplePanels(); 192 break; 193 194 default: 195 LayoutMultiplePanels(); 196 break; 197 } 198 199 Invalidate(); 200 } 201 202 203 204 205 void Deck::LayoutSinglePanel (void) 206 { 207 Rectangle aBox (GetContentArea()); 208 aBox = PlaceDeckTitle(GetTitleBar(), aBox); 209 Panel& rPanel (*maPanels.front()); 210 211 if (rPanel.IsExpanded()) 212 { 213 rPanel.Show(); 214 rPanel.GetTitleBar()->Hide(); 215 rPanel.SetPosSizePixel(aBox.Left(), aBox.Top(), aBox.GetWidth(), aBox.GetHeight()); 216 HideFiller(); 217 } 218 else 219 { 220 rPanel.Hide(); 221 ShowFiller(aBox); 222 } 223 } 224 225 226 227 228 void Deck::LayoutMultiplePanels (void) 229 { 230 Rectangle aBox (GetContentArea()); 231 if (aBox.GetWidth()<=0 || aBox.GetHeight()<=0) 232 return; 233 aBox = PlaceDeckTitle(GetTitleBar(), aBox); 234 const sal_Int32 nWidth (aBox.GetWidth()); 235 const sal_Int32 nPanelTitleBarHeight (Theme::GetPanelTitleBarHeight()); 236 237 // Determine the height that is available for panel content 238 // and count the different layouts. 239 const sal_Int32 nX = aBox.Left(); 240 sal_Int32 nHeight = aBox.GetHeight(); 241 sal_Int32 nFullCount (0); 242 sal_Int32 nVerticalStackCount (0); 243 for (::std::vector<Panel*>::const_iterator 244 iPanel(maPanels.begin()), 245 iEnd(maPanels.end()); 246 iPanel!=iEnd; 247 ++iPanel) 248 { 249 const Panel& rPanel (**iPanel); 250 251 nHeight -= nPanelTitleBarHeight; 252 253 if (rPanel.IsExpanded()) 254 { 255 if (rPanel.GetVerticalStackElement().is()) 256 { 257 ++nVerticalStackCount; 258 nHeight -= rPanel.GetVerticalStackElement()->getHeightForWidth(nWidth); 259 } 260 else 261 { 262 ++nFullCount; 263 } 264 } 265 } 266 267 sal_Int32 nHeightPerPanel (nFullCount<=0 ? 0 : nHeight / nFullCount); 268 // The division might lead to rounding errors. Enlarge the first 269 // panel to compensate for that. 270 sal_Int32 nHeightOfFirstPanel = nFullCount+nVerticalStackCount<=0 271 ? 0 272 : nHeightPerPanel + (nHeight - nHeightPerPanel*(nFullCount+nVerticalStackCount)); 273 if (nHeightPerPanel < MinimalPanelHeight) 274 { 275 // Display a vertical scroll bar. 276 // Force height to the minimal panel height. 277 nHeightPerPanel = MinimalPanelHeight; 278 nHeightOfFirstPanel = nHeightPerPanel; 279 } 280 281 // Assign heights and places. 282 sal_Int32 nY (aBox.Top()); 283 for (::std::vector<Panel*>::const_iterator 284 iPanel(maPanels.begin()), 285 iEnd(maPanels.end()); 286 iPanel!=iEnd; 287 ++iPanel) 288 { 289 Panel& rPanel (**iPanel); 290 291 // Place the title bar. 292 TitleBar* pTitleBar = rPanel.GetTitleBar(); 293 pTitleBar->SetPosSizePixel(nX, nY, nWidth, nPanelTitleBarHeight); 294 pTitleBar->Show(); 295 nY += nPanelTitleBarHeight; 296 297 if (rPanel.IsExpanded()) 298 { 299 rPanel.Show(); 300 301 // Place the panel. 302 sal_Int32 nPanelHeight (0); 303 if (rPanel.GetVerticalStackElement().is()) 304 nPanelHeight = rPanel.GetVerticalStackElement()->getHeightForWidth(nWidth); 305 else 306 if (iPanel==maPanels.begin()) 307 nPanelHeight = nHeightOfFirstPanel; 308 else 309 nPanelHeight = nHeightPerPanel; 310 311 rPanel.SetPosSizePixel(nX, nY, nWidth, nPanelHeight); 312 nY += nPanelHeight; 313 } 314 else 315 rPanel.Hide(); 316 } 317 318 if (nY < aBox.Bottom()) 319 ShowFiller(Rectangle(aBox.Left(), nY, aBox.Right(), aBox.Bottom())); 320 else 321 HideFiller(); 322 } 323 324 325 326 327 Rectangle Deck::PlaceDeckTitle ( 328 TitleBar* pDeckTitleBar, 329 const Rectangle& rAvailableSpace) 330 { 331 if (pDeckTitleBar == NULL) 332 { 333 OSL_ASSERT(pDeckTitleBar!=NULL); 334 return rAvailableSpace; 335 } 336 337 const sal_Int32 nDeckTitleBarHeight (Theme::GetDeckTitleBarHeight()); 338 pDeckTitleBar->SetPosSizePixel( 339 rAvailableSpace.Left(), 340 rAvailableSpace.Top(), 341 rAvailableSpace.GetWidth(), 342 nDeckTitleBarHeight); 343 pDeckTitleBar->Show(); 344 return Rectangle( 345 rAvailableSpace.Left(), 346 rAvailableSpace.Top() + nDeckTitleBarHeight, 347 rAvailableSpace.Right(), 348 rAvailableSpace.Bottom()); 349 } 350 351 352 353 354 void Deck::ShowFiller (const Rectangle& rBox) 355 { 356 if (mpFiller == NULL) 357 { 358 mpFiller = new Window(this); 359 mpFiller->SetBackground(Theme::GetDeckBackground().GetWallpaper()); 360 } 361 mpFiller->SetPosSizePixel(rBox.TopLeft(), rBox.GetSize()); 362 mpFiller->Show(); 363 } 364 365 366 367 368 void Deck::HideFiller (void) 369 { 370 if (mpFiller != NULL) 371 mpFiller->Hide(); 372 } 373 374 375 376 } } // end of namespace sfx2::sidebar 377