1 /* 2 Copyright (c) by Valery Goryachev (Wal) 3 */ 4 5 6 #include "swl.h" 7 8 namespace wal 9 { 10 11 AddWin(Win * w,int r1,int c1,int r2,int c2,int al)12 void Layout::AddWin( Win* w, int r1, int c1, int r2, int c2, int al ) 13 { 14 if ( r2 < 0 ) { r2 = r1; } 15 16 if ( c2 < 0 ) { c2 = c1; } 17 18 if ( r1 > r2 || c1 > c2 ) { return; } 19 20 if ( r1 < 0 || c1 < 0 || r2 >= lines.count() || c2 >= columns.count() ) { return; } 21 22 //if (w->layout) w->layout->DelObj(w); 23 if ( w->upLayout ) { w->upLayout->DelObj( w ); } 24 25 w->upLayout = this; 26 objList.emplace_back( new LItemWin( w, r1, r2, c1, c2, al ) ); 27 } 28 AddWinAndEnable(Win * w,int r1,int c1,int r2,int c2,int al)29 void Layout::AddWinAndEnable( Win* w, int r1, int c1, int r2, int c2, int al ) 30 { 31 if ( !w ) { return; } 32 33 this->AddWin( w, r1, c1, r2, c2, al ); 34 w->Enable(); 35 w->Show(); 36 } 37 AddLayout(Layout * l,int r1,int c1,int r2,int c2,int al)38 void Layout::AddLayout( Layout* l, int r1, int c1, int r2, int c2, int al ) 39 { 40 if ( r2 < 0 ) { r2 = r1; } 41 42 if ( c2 < 0 ) { c2 = c1; } 43 44 if ( r1 > r2 || c1 > c2 ) { return; } 45 46 if ( r1 < 0 || c1 < 0 || r2 >= lines.count() || c2 >= columns.count() ) { return; } 47 48 //??? if (w->layout) w->layout->DelObj(w); 49 objList.emplace_back( new LItemLayout( l, r1, r2, c1, c2, al ) ); 50 } 51 AddRect(crect * rect,int r1,int c1,int r2,int c2)52 void Layout::AddRect( crect* rect, int r1, int c1, int r2, int c2 ) 53 { 54 if ( !rect ) { return; } 55 56 if ( r2 < 0 ) { r2 = r1; } 57 58 if ( c2 < 0 ) { c2 = c1; } 59 60 if ( r1 > r2 || c1 > c2 ) { return; } 61 62 if ( r1 < 0 || c1 < 0 || r2 >= lines.count() || c2 >= columns.count() ) { return; } 63 64 objList.emplace_back( new LItemRect( rect, r1, r2, c1, c2 ) ); 65 } 66 67 Layout(int lineCount,int colCount)68 Layout::Layout( int lineCount, int colCount ) 69 : 70 lines( lineCount ), 71 columns( colCount ), 72 currentRect( 0, 0, 0, 0 ), 73 valid( false ) 74 { 75 // int i; //ошибка была в конструсторе ccollect(int n) 76 // for (i=0; i<lineCount; i++) lines.append(); 77 // for (i=0; i<colCount; i++) columns.append(); 78 } 79 ~Layout()80 Layout::~Layout() {} 81 GetLSize(LSize * pls)82 void Layout::GetLSize( LSize* pls ) 83 { 84 /* !!!?? 85 if (valid) 86 { 87 *pls = size; 88 return; 89 } 90 */ 91 Recalc(); 92 int i; 93 LSize ls; 94 95 for ( i = 0; i < lines.count(); i++ ) 96 { 97 ls.y.Plus( lines[i].range ); 98 } 99 100 for ( i = 0; i < columns.count(); i++ ) 101 { 102 ls.x.Plus( columns[i].range ); 103 } 104 105 size = ls; 106 *pls = ls; 107 } 108 SetPos(crect rect,wal::ccollect<WSS> & wList)109 void Layout::SetPos( crect rect, wal::ccollect<WSS>& wList ) 110 { 111 // if (currentRect == rect) return; 112 currentRect = rect; 113 valid = false; 114 this->Recalc(); 115 116 for ( int i = 0; i < ( int )objList.size(); i++ ) 117 { 118 int j; 119 crect r( rect.left, rect.top, 0, 0 ); 120 121 for ( j = 0; j < objList[i]->r1; j++ ) { r.top += lines[j].size; } 122 123 r.bottom = r.top; 124 125 for ( ; j <= objList[i]->r2; j++ ) { r.bottom += lines[j].size; } 126 127 for ( j = 0; j < objList[i]->c1; j++ ) { r.left += columns[j].size; } 128 129 r.right = r.left; 130 131 for ( ; j <= objList[i]->c2; j++ ) { r.right += columns[j].size; } 132 133 objList[i]->SetPos( r, wList ); 134 } 135 } 136 DelObj(void * p)137 void Layout::DelObj( void* p ) 138 { 139 for ( int i = 0; i < ( int )objList.size(); i++ ) 140 { 141 if ( objList[i]->ObjPtr() == p ) 142 { 143 valid = false; 144 objList.erase( objList.begin() + i ); 145 return; 146 } 147 } 148 } 149 150 LineSet(int nLine,int _min,int _max,int _ideal)151 void Layout::LineSet( int nLine, int _min, int _max, int _ideal ) 152 { 153 if ( nLine < 0 || nLine >= lines.count() ) { return; } 154 155 if ( _min >= 0 ) { lines[nLine].initRange.minimal = _min; } 156 157 if ( _max >= 0 ) { lines[nLine].initRange.maximal = _max; } 158 159 if ( _ideal >= 0 ) { lines[nLine].initRange.ideal = _ideal; } 160 161 lines[nLine].initRange.Check(); 162 } 163 ColSet(int nCol,int _min,int _max,int _ideal)164 void Layout::ColSet( int nCol, int _min, int _max, int _ideal ) 165 { 166 if ( nCol < 0 || nCol >= columns.count() ) { return; } 167 168 if ( _min >= 0 ) { columns[nCol].initRange.minimal = _min; } 169 170 if ( _max >= 0 ) { columns[nCol].initRange.maximal = _max; } 171 172 if ( _ideal >= 0 ) { columns[nCol].initRange.ideal = _ideal; } 173 174 /*lines*/ columns[nCol].initRange.Check(); 175 } 176 SetLineGrowth(int n,bool enable)177 void Layout::SetLineGrowth( int n, bool enable ) 178 { 179 if ( n >= 0 && n < lines.count() ) 180 { 181 lines[n].growth = enable; 182 } 183 } 184 SetColGrowth(int n,bool enable)185 void Layout::SetColGrowth( int n, bool enable ) 186 { 187 if ( n >= 0 && n < columns.count() ) 188 { 189 columns[n].growth = enable; 190 } 191 } 192 SetMinRangeN(SpaceStruct * list,int count,int size)193 static void SetMinRangeN( SpaceStruct* list, int count, int size ) 194 { 195 int i, n, addon, rem, space; 196 197 for ( i = 0; i < count; i++ ) //выставляем по минимуму 198 { 199 size -= list[i].range.minimal; 200 } 201 202 if ( size <= 0 ) { return; } 203 204 n = 0; 205 206 for ( i = 0; i < count; i++ ) 207 if ( list[i].growth ) { n++; } 208 209 if ( n > 0 ) 210 { 211 addon = size / n; 212 rem = size % n; 213 214 for ( i = 0; i < count; i++ ) 215 if ( list[i].growth ) 216 { 217 list[i].range.minimal += addon; 218 size -= addon; 219 220 if ( rem > 0 ) { list[i].range.minimal++; rem--; size--; } 221 } 222 223 return; 224 } 225 226 while ( true ) 227 { 228 n = 0; 229 230 for ( i = 0; i < count; i++ ) 231 if ( list[i].range.minimal < list[i].range.maximal ) { n++; } 232 233 if ( !n ) { break; } 234 235 addon = size / n; 236 237 if ( addon == 0 ) { addon = 1; } 238 239 for ( i = 0; i < count; i++ ) 240 { 241 space = list[i].range.maximal - list[i].range.minimal; 242 243 if ( space <= 0 ) { continue; } 244 245 if ( space > addon ) { space = addon; } 246 247 list[i].range.minimal += space; 248 size -= space; 249 250 if ( size <= 0 ) { return; } 251 } 252 253 if ( size <= 0 ) { return; } 254 } 255 256 addon = size / count; 257 rem = size % count; 258 259 for ( i = 0; i < count; i++ ) 260 { 261 list[i].range.minimal += addon; 262 size -= addon; 263 264 if ( rem > 0 ) { list[i].range.minimal++; rem--; size--; } 265 } 266 } 267 SetIdealRangeN(SpaceStruct * list,int count,int size)268 static void SetIdealRangeN( SpaceStruct* list, int count, int size ) 269 { 270 int i, n, addon, rem, space; 271 272 for ( i = 0; i < count; i++ ) 273 { 274 size -= list[i].range.ideal; 275 } 276 277 if ( size <= 0 ) { return; } 278 279 n = 0; 280 281 for ( i = 0; i < count; i++ ) 282 if ( list[i].growth ) { n++; } 283 284 if ( n > 0 ) 285 { 286 addon = size / n; 287 rem = size % n; 288 289 for ( i = 0; i < count; i++ ) 290 if ( list[i].growth ) 291 { 292 list[i].range.ideal += addon; 293 size -= addon; 294 295 if ( rem > 0 ) { list[i].range.ideal++; rem--; size--; } 296 } 297 298 return; 299 } 300 301 while ( true ) 302 { 303 n = 0; 304 305 for ( i = 0; i < count; i++ ) 306 if ( list[i].range.ideal < list[i].range.maximal ) { n++; } 307 308 if ( !n ) { break; } 309 310 addon = size / n; 311 312 if ( addon == 0 ) { addon = 1; } 313 314 for ( i = 0; i < count; i++ ) 315 { 316 space = list[i].range.maximal - list[i].range.ideal; 317 318 if ( space <= 0 ) { continue; } 319 320 if ( space > addon ) { space = addon; } 321 322 list[i].range.ideal += space; 323 size -= space; 324 325 if ( size <= 0 ) { return; } 326 } 327 328 if ( size <= 0 ) { return; } 329 } 330 331 addon = size / count; 332 rem = size % count; 333 334 for ( i = 0; i < count; i++ ) 335 { 336 list[i].range.ideal += addon; 337 size -= addon; 338 339 if ( rem > 0 ) { list[i].range.ideal++; rem--; size--; } 340 } 341 } 342 343 SetMaxRangeN(SpaceStruct * list,int count,int size)344 static void SetMaxRangeN( SpaceStruct* list, int count, int size ) 345 { 346 int i, n, addon, rem; 347 348 for ( i = 0; i < count; i++ ) 349 { 350 size -= list[i].range.maximal; 351 } 352 353 if ( size <= 0 ) { return; } 354 355 n = 0; 356 357 for ( i = 0; i < count; i++ ) 358 if ( list[i].growth ) { n++; } 359 360 if ( n > 0 ) 361 { 362 addon = size / n; 363 rem = size % n; 364 365 for ( i = 0; i < count; i++ ) 366 if ( list[i].growth ) 367 { 368 list[i].range.maximal += addon; 369 size -= addon; 370 371 if ( rem > 0 ) { list[i].range.maximal++; rem--; size--; } 372 } 373 374 return; 375 } 376 377 addon = size / count; 378 rem = size % count; 379 380 for ( i = 0; i < count; i++ ) 381 { 382 list[i].range.maximal += addon; 383 size -= addon; 384 385 if ( rem > 0 ) { list[i].range.maximal++; rem--; size--; } 386 } 387 } 388 389 390 SetOptimalRange(SpaceStruct * list,int count,int size)391 static void SetOptimalRange( SpaceStruct* list, int count, int size ) 392 { 393 int i, n, addon, rem; 394 395 for ( i = 0; i < count; i++ ) //выставляем по минимуму 396 { 397 size -= ( list[i].size = list[i].range.minimal ); 398 } 399 400 if ( size <= 0 ) { return; } 401 402 n = 0; 403 404 for ( i = 0; i < count; i++ ) 405 if ( list[i].growth ) { n++; } 406 407 if ( n > 0 ) 408 { 409 addon = size / n; 410 rem = size % n; 411 412 for ( i = 0; i < count; i++ ) 413 if ( list[i].growth ) 414 { 415 list[i].size += addon; 416 size -= addon; 417 418 if ( rem > 0 ) { list[i].size++; rem--; size--; } 419 } 420 421 return; 422 } 423 424 while ( true ) 425 { 426 n = 0; 427 428 for ( i = 0; i < count; i++ ) 429 if ( list[i].size < list[i].range.maximal ) { n++; } 430 431 if ( !n ) { break; } 432 433 addon = size / n; 434 435 //int rem = size % n; 436 if ( !addon ) { addon = 1; } 437 438 for ( i = 0; i < count; i++ ) 439 { 440 int space = list[i].range.maximal - list[i].size; 441 442 if ( space <= 0 ) { continue; } 443 444 if ( space > addon ) { space = addon; } 445 446 list[i].size += space; 447 size -= space; 448 449 if ( size <= 0 ) { break; } 450 } 451 452 if ( size <= 0 ) { break; } 453 } 454 455 //ret: 456 // size = 0; 457 // for (i = 0; i<count; i++) size+=list[i].size; 458 // return size; 459 } 460 461 Recalc()462 void Layout::Recalc() 463 { 464 //!? if (valid) return; 465 int i; 466 467 for ( i = 0; i < lines.count(); i++ ) 468 { 469 lines[i].Clear(); 470 } 471 472 for ( i = 0; i < columns.count(); i++ ) 473 { 474 columns[i].Clear(); 475 } 476 477 478 wal::ccollect<LSize> lSize( ( int )objList.size() ); 479 480 for ( i = 0; i < ( int )objList.size(); i++ ) 481 { 482 objList[i]->GetLSize( lSize.ptr() + i ); 483 } 484 485 for ( i = 0; i < ( int )objList.size(); i++ ) 486 { 487 LItem* p = objList[i].ptr(); 488 LSize* ls = lSize.ptr() + i; 489 490 if ( p->r1 == p->r2 ) 491 { 492 int r = p->r1; 493 494 if ( lines[r].range.minimal < ls->y.minimal ) 495 { 496 lines[r].range.minimal = ls->y.minimal; 497 } 498 499 if ( lines[r].range.maximal < ls->y.maximal ) 500 { 501 lines[r].range.maximal = ls->y.maximal; 502 } 503 504 if ( lines[r].range.ideal < ls->y.ideal ) 505 { 506 lines[r].range.ideal = ls->y.ideal; 507 } 508 } 509 510 if ( p->c1 == p->c2 ) 511 { 512 int c = p->c1; 513 514 if ( columns[c].range.minimal < ls->x.minimal ) 515 { 516 columns[c].range.minimal = ls->x.minimal; 517 } 518 519 if ( columns[c].range.maximal < ls->x.maximal ) 520 { 521 columns[c].range.maximal = ls->x.maximal; 522 } 523 524 if ( columns[c].range.ideal < ls->x.ideal ) 525 { 526 columns[c].range.ideal = ls->x.ideal; 527 } 528 } 529 } 530 531 532 for ( i = 0; i < ( int )objList.size(); i++ ) 533 { 534 LItem* p = objList[i].ptr(); 535 LSize* ls = lSize.ptr() + i; 536 537 if ( p->r1 != p->r2 ) 538 { 539 SetMinRangeN( lines.ptr() + p->r1, p->r2 - p->r1 + 1, ls->y.minimal ); 540 SetIdealRangeN( lines.ptr() + p->r1, p->r2 - p->r1 + 1, ls->y.ideal ); 541 SetMaxRangeN( lines.ptr() + p->r1, p->r2 - p->r1 + 1, ls->y.maximal ); 542 } 543 544 if ( p->c1 != p->c2 ) 545 { 546 SetMinRangeN ( columns.ptr() + p->c1, p->c2 - p->c1 + 1, ls->x.minimal ); 547 SetIdealRangeN( columns.ptr() + p->c1, p->c2 - p->c1 + 1, ls->x.ideal ); 548 SetMaxRangeN ( columns.ptr() + p->c1, p->c2 - p->c1 + 1, ls->x.maximal ); 549 550 /*чо за херня тут была 551 SetMinRangeN(columns.ptr()+p->r1, p->r2-p->r1+1,ls->x.minimal); 552 SetIdealRangeN(columns.ptr()+p->r1, p->r2-p->r1+1,ls->x.ideal); 553 SetMaxRangeN(columns.ptr()+p->r1, p->r2-p->r1+1,ls->x.maximal); 554 */ 555 } 556 } 557 558 for ( i = 0; i < lines.count(); i++ ) { lines[i].range.Check(); } 559 560 for ( i = 0; i < columns.count(); i++ ) { columns[i].range.Check(); } 561 562 SetOptimalRange( lines.ptr(), lines.count(), currentRect.Height() ); 563 SetOptimalRange( columns.ptr(), columns.count(), currentRect.Width() ); 564 565 valid = true; 566 } 567 ~LItem()568 LItem::~LItem() {} 569 ~LItemWin()570 LItemWin::~LItemWin() { if ( w ) { w->upLayout = 0; } } ~LItemRect()571 LItemRect::~LItemRect() {} ~LItemLayout()572 LItemLayout::~LItemLayout() {}; 573 GetLSize(LSize * ls)574 void LItemLayout::GetLSize( LSize* ls ) 575 { 576 l->GetLSize( ls ); 577 } 578 SetPos(crect rect,wal::ccollect<WSS> & wList)579 void LItemLayout::SetPos( crect rect, wal::ccollect<WSS>& wList ) 580 { 581 LSize ls; 582 l->GetLSize( &ls ); 583 // if (rect.Width() > ls.x.maximal) rect.right = rect.left + ls.x.maximal; 584 // if (rect.Height() > ls.y.maximal) rect.bottom = rect.top + ls.y.maximal; 585 586 int width = rect.Width(); 587 588 if ( width > ls.x.maximal ) 589 { 590 switch ( align & ( Layout::LEFT + Layout::RIGHT ) ) 591 { 592 case Layout::LEFT: 593 rect.right = rect.left + ls.x.maximal; 594 break; 595 596 case Layout::RIGHT: 597 rect.left = rect.right - ls.x.maximal; 598 break; 599 600 default: 601 { 602 int n = ( width - ls.x.maximal ) / 2; 603 rect.left += n; 604 rect.right += n; 605 } 606 } 607 } 608 609 int height = rect.Height(); 610 611 if ( rect.Height() > ls.y.maximal ) 612 { 613 switch ( align & ( Layout::TOP + Layout::BOTTOM ) ) 614 { 615 case Layout::TOP: 616 rect.bottom = rect.top + ls.y.maximal; 617 break; 618 619 case Layout::RIGHT: 620 rect.top = rect.bottom - ls.y.maximal; 621 break; 622 623 default: 624 { 625 int n = ( height - ls.y.maximal ) / 2; 626 rect.top += n; 627 rect.bottom += n; 628 } 629 } 630 }; 631 632 l->SetPos( rect, wList ); 633 } 634 GetLSize(LSize * ls)635 void LItemWin::GetLSize( LSize* ls ) 636 { 637 if ( w->IsVisible() ) { w->GetLSize( ls ); } 638 else 639 { 640 ls->Set( cpoint( 0, 0 ) ); 641 } 642 } 643 644 SetPos(crect rect,wal::ccollect<WSS> & wList)645 void LItemWin::SetPos( crect rect, wal::ccollect<WSS>& wList ) 646 { 647 LSize ls; 648 649 if ( !w->IsVisible() ) { return; } 650 651 w->GetLSize( &ls ); 652 653 int width = rect.Width(); 654 655 if ( width > ls.x.maximal ) 656 { 657 switch ( align & ( Layout::LEFT + Layout::RIGHT ) ) 658 { 659 case Layout::LEFT: 660 rect.right = rect.left + ls.x.maximal; 661 break; 662 663 case Layout::RIGHT: 664 rect.left = rect.right - ls.x.maximal; 665 break; 666 667 default: 668 { 669 int n = ( width - ls.x.maximal ) / 2; 670 rect.left += n; 671 rect.right = rect.left + ls.x.maximal; 672 } 673 } 674 } 675 676 int height = rect.Height(); 677 678 if ( rect.Height() > ls.y.maximal ) 679 { 680 switch ( align & ( Layout::TOP + Layout::BOTTOM ) ) 681 { 682 case Layout::TOP: 683 rect.bottom = rect.top + ls.y.maximal; 684 break; 685 686 case Layout::RIGHT: 687 rect.top = rect.bottom - ls.y.maximal; 688 break; 689 690 default: 691 { 692 int n = ( height - ls.y.maximal ) / 2; 693 rect.top += n; 694 rect.bottom = rect.top + ls.y.maximal; 695 } 696 } 697 }; 698 699 if ( w->Rect() != rect ) 700 { 701 WSS wss; 702 wss.rect = rect; 703 wss.w = w; 704 wList.append( wss ); 705 } 706 } 707 ObjPtr()708 void* LItemLayout::ObjPtr() { return l; } ObjPtr()709 void* LItemWin::ObjPtr() { return w; } 710 711 GetLSize(LSize * ls)712 void LItemRect::GetLSize( LSize* ls ) 713 { 714 static LSize l( cpoint( 0, 0 ) ); 715 *ls = l; 716 } 717 SetPos(crect _rect,wal::ccollect<WSS> & wList)718 void LItemRect::SetPos( crect _rect, wal::ccollect<WSS>& wList ) 719 { 720 if ( rect ) { *rect = _rect; } 721 } 722 ObjPtr()723 void* LItemRect::ObjPtr() { return rect; } 724 725 726 727 }; //namespace wal 728