1/* 2 * Copyright 2010, Haiku, Inc. 3 * All rights reserved. Distributed under the terms of the MIT License. 4 */ 5 6 7#include <AbstractLayout.h> 8#include <LayoutUtils.h> 9#include <Message.h> 10#include <View.h> 11#include <ViewPrivate.h> 12 13 14namespace { 15 const char* const kSizesField = "BAbstractLayout:sizes"; 16 // kSizesField == {min, max, preferred} 17 const char* const kAlignmentField = "BAbstractLayout:alignment"; 18 const char* const kFrameField = "BAbstractLayout:frame"; 19 const char* const kVisibleField = "BAbstractLayout:visible"; 20 21 enum proxy_type { VIEW_PROXY_TYPE, DATA_PROXY_TYPE }; 22} 23 24 25struct BAbstractLayout::Proxy { 26 27 Proxy(proxy_type type) 28 : 29 type(type) 30 { 31 } 32 33 virtual ~Proxy() 34 { 35 } 36 37 virtual BSize MinSize() const = 0; 38 virtual void SetMinSize(const BSize&) = 0; 39 40 virtual BSize MaxSize() const = 0; 41 virtual void SetMaxSize(const BSize&) = 0; 42 43 virtual BSize PreferredSize() const = 0; 44 virtual void SetPreferredSize(const BSize&) = 0; 45 46 virtual BAlignment Alignment() const = 0; 47 virtual void SetAlignment(const BAlignment&) = 0; 48 49 virtual BRect Frame() const = 0; 50 virtual void SetFrame(const BRect& frame) = 0; 51 52 virtual bool IsVisible(bool ancestorHidden) const = 0; 53 virtual void SetVisible(bool visible) = 0; 54 55 virtual status_t AddDataToArchive(BMessage* archive, 56 bool ancestorHidden) = 0; 57 virtual status_t RestoreDataFromArchive(const BMessage* archive) = 0; 58 59 proxy_type type; 60}; 61 62 63struct BAbstractLayout::DataProxy : Proxy { 64 65 DataProxy() 66 : 67 Proxy(DATA_PROXY_TYPE), 68 minSize(), 69 maxSize(), 70 preferredSize(), 71 alignment(), 72 frame(-1, -1, 0, 0), 73 visible(true) 74 { 75 } 76 77 BSize MinSize() const 78 { 79 return minSize; 80 } 81 82 void SetMinSize(const BSize& min) 83 { 84 minSize = min; 85 } 86 87 BSize MaxSize() const 88 { 89 return maxSize; 90 } 91 92 void SetMaxSize(const BSize& max) 93 { 94 maxSize = max; 95 } 96 97 BSize PreferredSize() const 98 { 99 return preferredSize; 100 } 101 102 void SetPreferredSize(const BSize& preferred) 103 { 104 preferredSize = preferred; 105 } 106 107 BAlignment Alignment() const 108 { 109 return this->alignment; 110 } 111 112 void SetAlignment(const BAlignment& align) 113 { 114 this->alignment = align; 115 } 116 117 BRect Frame() const 118 { 119 return frame; 120 } 121 122 void SetFrame(const BRect& frame) 123 { 124 if (frame == this->frame) 125 return; 126 this->frame = frame; 127 } 128 129 bool IsVisible(bool) const 130 { 131 return visible; 132 } 133 134 void SetVisible(bool visible) 135 { 136 this->visible = visible; 137 } 138 139 status_t AddDataToArchive(BMessage* archive, bool ancestorHidden) 140 { 141 status_t err = archive->AddSize(kSizesField, minSize); 142 if (err == B_OK) 143 err = archive->AddSize(kSizesField, maxSize); 144 if (err == B_OK) 145 err = archive->AddSize(kSizesField, preferredSize); 146 if (err == B_OK) 147 err = archive->AddAlignment(kAlignmentField, alignment); 148 if (err == B_OK) 149 err = archive->AddRect(kFrameField, frame); 150 if (err == B_OK) 151 err = archive->AddBool(kVisibleField, visible); 152 153 return err; 154 } 155 156 status_t RestoreDataFromArchive(const BMessage* archive) 157 { 158 status_t err = archive->FindSize(kSizesField, 0, &minSize); 159 if (err == B_OK) 160 err = archive->FindSize(kSizesField, 1, &maxSize); 161 if (err == B_OK) 162 err = archive->FindSize(kSizesField, 2, &preferredSize); 163 if (err == B_OK) 164 err = archive->FindAlignment(kAlignmentField, &alignment); 165 if (err == B_OK) 166 err = archive->FindRect(kFrameField, &frame); 167 if (err == B_OK) 168 err = archive->FindBool(kVisibleField, &visible); 169 170 return err; 171 } 172 173 BSize minSize; 174 BSize maxSize; 175 BSize preferredSize; 176 BAlignment alignment; 177 BRect frame; 178 bool visible; 179}; 180 181 182struct BAbstractLayout::ViewProxy : Proxy { 183 ViewProxy(BView* target) 184 : 185 Proxy(VIEW_PROXY_TYPE), 186 view(target) 187 { 188 } 189 190 BSize MinSize() const 191 { 192 return view->ExplicitMinSize(); 193 } 194 195 void SetMinSize(const BSize& min) 196 { 197 view->SetExplicitMinSize(min); 198 } 199 200 BSize MaxSize() const 201 { 202 return view->ExplicitMaxSize(); 203 } 204 205 void SetMaxSize(const BSize& min) 206 { 207 view->SetExplicitMaxSize(min); 208 } 209 210 BSize PreferredSize() const 211 { 212 return view->ExplicitPreferredSize(); 213 } 214 215 void SetPreferredSize(const BSize& preferred) 216 { 217 view->SetExplicitPreferredSize(preferred); 218 } 219 220 BAlignment Alignment() const 221 { 222 return view->ExplicitAlignment(); 223 } 224 225 void SetAlignment(const BAlignment& alignment) 226 { 227 view->SetExplicitAlignment(alignment); 228 } 229 230 BRect Frame() const 231 { 232 return view->Frame(); 233 } 234 235 void SetFrame(const BRect& frame) 236 { 237 view->MoveTo(frame.LeftTop()); 238 view->ResizeTo(frame.Width(), frame.Height()); 239 } 240 241 bool IsVisible(bool ancestorsVisible) const 242 { 243 int16 showLevel = BView::Private(view).ShowLevel(); 244 return (showLevel - (ancestorsVisible ? 0 : 1)) <= 0; 245 } 246 247 void SetVisible(bool visible) 248 { 249 // No need to check that we are not re-hiding, that is done 250 // for us. 251 if (visible) 252 view->Show(); 253 else 254 view->Hide(); 255 } 256 257 status_t AddDataToArchive(BMessage* archive, bool ancestorHidden) 258 { 259 return B_OK; 260 } 261 262 status_t RestoreDataFromArchive(const BMessage* archive) 263 { 264 return B_OK; 265 } 266 267 BView* view; 268}; 269 270 271BAbstractLayout::BAbstractLayout() 272 : 273 fExplicitData(new BAbstractLayout::DataProxy()) 274{ 275} 276 277 278BAbstractLayout::BAbstractLayout(BMessage* from) 279 : 280 BLayout(BUnarchiver::PrepareArchive(from)), 281 fExplicitData(new DataProxy()) 282{ 283 BUnarchiver(from).Finish(); 284} 285 286 287BAbstractLayout::~BAbstractLayout() 288{ 289 delete fExplicitData; 290} 291 292 293BSize 294BAbstractLayout::MinSize() 295{ 296 return BLayoutUtils::ComposeSize(fExplicitData->MinSize(), BaseMinSize()); 297} 298 299 300BSize 301BAbstractLayout::MaxSize() 302{ 303 return BLayoutUtils::ComposeSize(fExplicitData->MaxSize(), BaseMaxSize()); 304} 305 306 307BSize 308BAbstractLayout::PreferredSize() 309{ 310 return BLayoutUtils::ComposeSize(fExplicitData->PreferredSize(), 311 BasePreferredSize()); 312} 313 314 315BAlignment 316BAbstractLayout::Alignment() 317{ 318 return BLayoutUtils::ComposeAlignment(fExplicitData->Alignment(), 319 BaseAlignment()); 320} 321 322 323void 324BAbstractLayout::SetExplicitMinSize(BSize size) 325{ 326 fExplicitData->SetMinSize(size); 327} 328 329 330void 331BAbstractLayout::SetExplicitMaxSize(BSize size) 332{ 333 fExplicitData->SetMaxSize(size); 334} 335 336 337void 338BAbstractLayout::SetExplicitPreferredSize(BSize size) 339{ 340 fExplicitData->SetPreferredSize(size); 341} 342 343 344void 345BAbstractLayout::SetExplicitAlignment(BAlignment alignment) 346{ 347 fExplicitData->SetAlignment(alignment); 348} 349 350 351BSize 352BAbstractLayout::BaseMinSize() 353{ 354 return BSize(0, 0); 355} 356 357 358BSize 359BAbstractLayout::BaseMaxSize() 360{ 361 return BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED); 362} 363 364 365BSize 366BAbstractLayout::BasePreferredSize() 367{ 368 return BSize(0, 0); 369} 370 371 372BAlignment 373BAbstractLayout::BaseAlignment() 374{ 375 return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT); 376} 377 378 379BRect 380BAbstractLayout::Frame() 381{ 382 return fExplicitData->Frame(); 383} 384 385 386void 387BAbstractLayout::SetFrame(BRect frame) 388{ 389 if (frame != fExplicitData->Frame()) { 390 fExplicitData->SetFrame(frame); 391 if (!Owner()) 392 Relayout(); 393 } 394} 395 396 397bool 398BAbstractLayout::IsVisible() 399{ 400 return fExplicitData->IsVisible(AncestorsVisible()); 401} 402 403 404void 405BAbstractLayout::SetVisible(bool visible) 406{ 407 if (visible != fExplicitData->IsVisible(AncestorsVisible())) { 408 fExplicitData->SetVisible(visible); 409 if (Layout()) 410 Layout()->InvalidateLayout(false); 411 VisibilityChanged(visible); 412 } 413} 414 415 416status_t 417BAbstractLayout::Archive(BMessage* into, bool deep) const 418{ 419 BArchiver archiver(into); 420 status_t err = BLayout::Archive(into, deep); 421 422 return archiver.Finish(err); 423} 424 425 426status_t 427BAbstractLayout::AllArchived(BMessage* archive) const 428{ 429 return BLayout::AllArchived(archive); 430} 431 432 433status_t 434BAbstractLayout::AllUnarchived(const BMessage* from) 435{ 436 status_t err = fExplicitData->RestoreDataFromArchive(from); 437 if (err != B_OK) 438 return err; 439 440 return BLayout::AllUnarchived(from); 441} 442 443 444status_t 445BAbstractLayout::ItemArchived(BMessage* into, BLayoutItem* item, 446 int32 index) const 447{ 448 return BLayout::ItemArchived(into, item, index); 449} 450 451 452status_t 453BAbstractLayout::ItemUnarchived(const BMessage* from, BLayoutItem* item, 454 int32 index) 455{ 456 return BLayout::ItemUnarchived(from, item, index); 457} 458 459 460bool 461BAbstractLayout::ItemAdded(BLayoutItem* item, int32 atIndex) 462{ 463 return BLayout::ItemAdded(item, atIndex); 464} 465 466 467void 468BAbstractLayout::ItemRemoved(BLayoutItem* item, int32 fromIndex) 469{ 470 BLayout::ItemRemoved(item, fromIndex); 471} 472 473 474void 475BAbstractLayout::LayoutInvalidated(bool children) 476{ 477 BLayout::LayoutInvalidated(children); 478} 479 480 481void 482BAbstractLayout::OwnerChanged(BView* was) 483{ 484 if (was) { 485 static_cast<ViewProxy*>(fExplicitData)->view = Owner(); 486 return; 487 } 488 489 delete fExplicitData; 490 fExplicitData = new ViewProxy(Owner()); 491} 492 493 494void 495BAbstractLayout::AttachedToLayout() 496{ 497 BLayout::AttachedToLayout(); 498} 499 500 501void 502BAbstractLayout::DetachedFromLayout(BLayout* layout) 503{ 504 BLayout::DetachedFromLayout(layout); 505} 506 507 508void 509BAbstractLayout::AncestorVisibilityChanged(bool shown) 510{ 511 if (AncestorsVisible() == shown) 512 return; 513 514 if (BView* owner = Owner()) { 515 if (shown) 516 owner->Show(); 517 else 518 owner->Hide(); 519 } 520 BLayout::AncestorVisibilityChanged(shown); 521} 522 523 524// Binary compatibility stuff 525 526 527status_t 528BAbstractLayout::Perform(perform_code code, void* _data) 529{ 530 return BLayout::Perform(code, _data); 531} 532 533 534void BAbstractLayout::_ReservedAbstractLayout1() {} 535void BAbstractLayout::_ReservedAbstractLayout2() {} 536void BAbstractLayout::_ReservedAbstractLayout3() {} 537void BAbstractLayout::_ReservedAbstractLayout4() {} 538void BAbstractLayout::_ReservedAbstractLayout5() {} 539void BAbstractLayout::_ReservedAbstractLayout6() {} 540void BAbstractLayout::_ReservedAbstractLayout7() {} 541void BAbstractLayout::_ReservedAbstractLayout8() {} 542void BAbstractLayout::_ReservedAbstractLayout9() {} 543void BAbstractLayout::_ReservedAbstractLayout10() {} 544 545