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 14 namespace { 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 25 struct 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 63 struct 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 182 struct 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 271 BAbstractLayout::BAbstractLayout() 272 : 273 fExplicitData(new BAbstractLayout::DataProxy()) 274 { 275 } 276 277 278 BAbstractLayout::BAbstractLayout(BMessage* from) 279 : 280 BLayout(BUnarchiver::PrepareArchive(from)), 281 fExplicitData(new DataProxy()) 282 { 283 BUnarchiver(from).Finish(); 284 } 285 286 287 BAbstractLayout::~BAbstractLayout() 288 { 289 delete fExplicitData; 290 } 291 292 293 BSize 294 BAbstractLayout::MinSize() 295 { 296 return BLayoutUtils::ComposeSize(fExplicitData->MinSize(), BaseMinSize()); 297 } 298 299 300 BSize 301 BAbstractLayout::MaxSize() 302 { 303 return BLayoutUtils::ComposeSize(fExplicitData->MaxSize(), BaseMaxSize()); 304 } 305 306 307 BSize 308 BAbstractLayout::PreferredSize() 309 { 310 return BLayoutUtils::ComposeSize(fExplicitData->PreferredSize(), 311 BasePreferredSize()); 312 } 313 314 315 BAlignment 316 BAbstractLayout::Alignment() 317 { 318 return BLayoutUtils::ComposeAlignment(fExplicitData->Alignment(), 319 BaseAlignment()); 320 } 321 322 323 void 324 BAbstractLayout::SetExplicitMinSize(BSize size) 325 { 326 fExplicitData->SetMinSize(size); 327 } 328 329 330 void 331 BAbstractLayout::SetExplicitMaxSize(BSize size) 332 { 333 fExplicitData->SetMaxSize(size); 334 } 335 336 337 void 338 BAbstractLayout::SetExplicitPreferredSize(BSize size) 339 { 340 fExplicitData->SetPreferredSize(size); 341 } 342 343 344 void 345 BAbstractLayout::SetExplicitAlignment(BAlignment alignment) 346 { 347 fExplicitData->SetAlignment(alignment); 348 } 349 350 351 BSize 352 BAbstractLayout::BaseMinSize() 353 { 354 return BSize(0, 0); 355 } 356 357 358 BSize 359 BAbstractLayout::BaseMaxSize() 360 { 361 return BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED); 362 } 363 364 365 BSize 366 BAbstractLayout::BasePreferredSize() 367 { 368 return BSize(0, 0); 369 } 370 371 372 BAlignment 373 BAbstractLayout::BaseAlignment() 374 { 375 return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT); 376 } 377 378 379 BRect 380 BAbstractLayout::Frame() 381 { 382 return fExplicitData->Frame(); 383 } 384 385 386 void 387 BAbstractLayout::SetFrame(BRect frame) 388 { 389 if (frame != fExplicitData->Frame()) { 390 fExplicitData->SetFrame(frame); 391 if (!Owner()) 392 Relayout(); 393 } 394 } 395 396 397 bool 398 BAbstractLayout::IsVisible() 399 { 400 return fExplicitData->IsVisible(AncestorsVisible()); 401 } 402 403 404 void 405 BAbstractLayout::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 416 status_t 417 BAbstractLayout::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 426 status_t 427 BAbstractLayout::AllArchived(BMessage* archive) const 428 { 429 return BLayout::AllArchived(archive); 430 } 431 432 433 status_t 434 BAbstractLayout::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 444 status_t 445 BAbstractLayout::ItemArchived(BMessage* into, BLayoutItem* item, 446 int32 index) const 447 { 448 return BLayout::ItemArchived(into, item, index); 449 } 450 451 452 status_t 453 BAbstractLayout::ItemUnarchived(const BMessage* from, BLayoutItem* item, 454 int32 index) 455 { 456 return BLayout::ItemUnarchived(from, item, index); 457 } 458 459 460 bool 461 BAbstractLayout::ItemAdded(BLayoutItem* item, int32 atIndex) 462 { 463 return BLayout::ItemAdded(item, atIndex); 464 } 465 466 467 void 468 BAbstractLayout::ItemRemoved(BLayoutItem* item, int32 fromIndex) 469 { 470 BLayout::ItemRemoved(item, fromIndex); 471 } 472 473 474 void 475 BAbstractLayout::LayoutInvalidated(bool children) 476 { 477 BLayout::LayoutInvalidated(children); 478 } 479 480 481 void 482 BAbstractLayout::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 494 void 495 BAbstractLayout::AttachedToLayout() 496 { 497 BLayout::AttachedToLayout(); 498 } 499 500 501 void 502 BAbstractLayout::DetachedFromLayout(BLayout* layout) 503 { 504 BLayout::DetachedFromLayout(layout); 505 } 506 507 508 void 509 BAbstractLayout::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 527 status_t 528 BAbstractLayout::Perform(perform_code code, void* _data) 529 { 530 return BLayout::Perform(code, _data); 531 } 532 533 534 void BAbstractLayout::_ReservedAbstractLayout1() {} 535 void BAbstractLayout::_ReservedAbstractLayout2() {} 536 void BAbstractLayout::_ReservedAbstractLayout3() {} 537 void BAbstractLayout::_ReservedAbstractLayout4() {} 538 void BAbstractLayout::_ReservedAbstractLayout5() {} 539 void BAbstractLayout::_ReservedAbstractLayout6() {} 540 void BAbstractLayout::_ReservedAbstractLayout7() {} 541 void BAbstractLayout::_ReservedAbstractLayout8() {} 542 void BAbstractLayout::_ReservedAbstractLayout9() {} 543 void BAbstractLayout::_ReservedAbstractLayout10() {} 544 545