PageRenderTime 402ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/CS/migrated/branches/R0_16/libs/csws/csgrid.cpp

#
C++ | 706 lines | 560 code | 71 blank | 75 comment | 123 complexity | bf52d48d1594efacebb4b1858c1723c1 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, LGPL-2.0
  1. /*
  2. Crystal Space Windowing System : grid class
  3. Copyright (C) 2000 by Norman Kramer <normank@lycosmail.com>
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public
  6. License as published by the Free Software Foundation; either
  7. version 2 of the License, or (at your option) any later version.
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Library General Public License for more details.
  12. You should have received a copy of the GNU Library General Public
  13. License along with this library; if not, write to the Free
  14. Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. */
  16. #include "cssysdef.h"
  17. #include "csws/csapp.h"
  18. #include "csws/cswindow.h"
  19. #include "csws/csgrid.h"
  20. /*******************************************************************************************************
  21. * csRegionTree2D
  22. *******************************************************************************************************/
  23. /**
  24. * Tiles this rect into the tree and creates new children if needed.
  25. */
  26. void csRegionTree2D::Insert (csRect &area, csSome data)
  27. {
  28. if (children[0]){
  29. int i=0;
  30. while (i<5 && children[i]){
  31. csRect common( area );
  32. common.Intersect (children[i]->region);
  33. if (!common.IsEmpty () ) children[i]->Insert (common, data);
  34. i++;
  35. }
  36. }else{
  37. // leaf
  38. if (region.Intersects (area)){
  39. // maybe this regions equals the area, then we simply replace the data and are done
  40. if (region.Equal (area.xmin, area.ymin, area.xmax, area.ymax)){
  41. this->data = data;
  42. }else{
  43. int i=0;
  44. // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  45. // DO NOT CHANGE THE SEQUENCE OF THE FOLLOWING, IT ENSURES FindRegion RETURNS AREAS ORDERED LEFT TO RIGHT
  46. // FOR SINGLE ROW REGIONS (likewise TOP TO DOWN)
  47. // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  48. // does an upper stripe exist ?
  49. if (region.ymin < area.ymin){
  50. csRect rc( region ); rc.ymax = area.ymin;
  51. children[i++] = new csRegionTree2D (rc, this->data);
  52. }
  53. // does a left stripe exist ?
  54. if (region.xmin < area.xmin){
  55. csRect rc( region.xmin, area.ymin, area.xmin, area.ymax );
  56. children[i++] = new csRegionTree2D (rc, this->data);
  57. }
  58. // the region which fully covers area
  59. children[i++] = new csRegionTree2D (area, data);
  60. // does a right stripe exist ?
  61. if (region.xmax > area.xmax){
  62. csRect rc( area.xmax, area.ymin, region.xmax, area.ymax );
  63. children[i++] = new csRegionTree2D (rc, this->data);
  64. }
  65. // does a lower stripe exist ?
  66. if (region.ymax > area.ymax){
  67. csRect rc( region ); rc.ymin = area.ymax;
  68. children[i++] = new csRegionTree2D (rc, this->data);
  69. }
  70. // now this leaf became a simple node
  71. }
  72. }
  73. }
  74. }
  75. /**
  76. * Returns a list of leaves that do all contain parts of area.
  77. */
  78. void csRegionTree2D::FindRegion (const csRect &area, csVector &vLeafList)
  79. {
  80. if (children[0]){
  81. int i=0;
  82. while (i<5 && children[i]) children[i++]->FindRegion (area, vLeafList);
  83. }else{
  84. if (region.Intersects (area)) vLeafList.Push (this);
  85. }
  86. }
  87. /**
  88. * Traverse the tree and call user supplied function for every node.
  89. */
  90. void csRegionTree2D::Traverse (RegionTreeFunc userFunc, csSome databag)
  91. {
  92. if (userFunc (this, databag)){
  93. int i=0;
  94. while (i<5 && children[i]) children[i++]->Traverse (userFunc, databag);
  95. }
  96. }
  97. /*******************************************************************************************************
  98. * csSparseGrid::csGridRow
  99. *******************************************************************************************************/
  100. csSparseGrid::csGridRow::csGridRow (int theCol)
  101. {
  102. col = theCol;
  103. }
  104. csSparseGrid::csGridRow::~csGridRow ()
  105. {
  106. DeleteAll ();
  107. }
  108. void csSparseGrid::csGridRow::SetAt (int col, csSome data)
  109. {
  110. int key = FindSortedKey ((csConstSome)col);
  111. if (key==-1) key=InsertSorted (new GridRowEntry (col, data));
  112. else Get (key)->data=data;
  113. }
  114. csSparseGrid::GridRowEntry* csSparseGrid::csGridRow::Get (int index)
  115. {
  116. return (csSparseGrid::GridRowEntry*)csVector::Get (index);
  117. }
  118. int csSparseGrid::csGridRow::Compare (csSome Item1, csSome Item2, int Mode) const{
  119. (void)Mode;
  120. csSparseGrid::GridRowEntry *e1 = (csSparseGrid::GridRowEntry*)Item1, *e2 = (csSparseGrid::GridRowEntry*)Item2;
  121. return (e1->col<e2->col ? -1 : e1->col>e2->col ? 1 : 0);
  122. }
  123. int csSparseGrid::csGridRow::CompareKey (csSome Item1, csConstSome Key, int Mode) const{
  124. (void)Mode;
  125. csSparseGrid::GridRowEntry *e1 = (csSparseGrid::GridRowEntry*)Item1;
  126. return (e1->col<(int)Key ? -1 : e1->col>(int)Key ? 1 : 0);
  127. }
  128. bool csSparseGrid::csGridRow::FreeItem (csSome Item)
  129. {
  130. delete (csSparseGrid::GridRowEntry*)Item;
  131. return true;
  132. }
  133. /*******************************************************************************************************
  134. * csGridCell
  135. *******************************************************************************************************/
  136. void csGridCell::DrawLine (int x1, int y1, int x2, int y2, csCellBorder& border)
  137. {
  138. if (border.style == GCBS_LINE)
  139. Box ( MIN(x1,x2), y1, MAX(x1,x2), y2, CSPAL_GRIDCELL_BORDER_FG);
  140. else if (border.style != GCBS_NONE){
  141. int maxX, maxY, i = 0, nSegs, xcompo, ycompo;
  142. static const int linepattern[][13] = {
  143. { 2, 4, 0, 2, 0 }, // DASH
  144. { 4, 4, 0, 2, 0, 2, 0, 2, 0 }, // DASHPOINT
  145. { 6, 4, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0 }, // DASHPOINTPOINT
  146. { 6, 4, 0, 2, 0, 4, 0, 2, 0, 2, 0, 2, 0 } // DASHDASHPOINT
  147. };
  148. if (x1<=x2) {xcompo=0; ycompo=1;}
  149. else {xcompo=1; ycompo=0;}
  150. maxX = MAX(x1,x2); maxY=MAX(y1,y2);
  151. x1 = MIN(x1,x2); x2 = MAX(x1,x2);
  152. nSegs = linepattern[ (int)border.style ][0]; // linesegments in linepattern
  153. while (x1<maxX && y1<maxY){
  154. i = i%nSegs;
  155. x2 = x1 + linepattern[ (int)border.style ][1+2*i+xcompo];
  156. y2 = y1 + linepattern[ (int)border.style ][1+2*i+ycompo];
  157. Box (x1, y1, MIN(x2,maxX), MIN(y2,maxY), (i&1 ? CSPAL_GRIDCELL_BORDER_BG : CSPAL_GRIDCELL_BORDER_FG));
  158. // printf("%d,%d -> %d,%d = %d\n", x1, y1, x2, y2,(i&1 ? 0 : 1));
  159. x1 = x2; y1=y2;
  160. i++;
  161. }
  162. }
  163. }
  164. void csGridCell::Draw ()
  165. {
  166. int lx=0, rx=0, ty=0, by=0; // offsets if borders are drawn;
  167. if (upper.style != GCBS_NONE){
  168. ty = upper.thick;
  169. DrawLine (0, 0, bound.Width () - (right.style == GCBS_NONE ? 0 : right.thick), upper.thick, upper);
  170. }
  171. if (right.style != GCBS_NONE){
  172. rx = right.thick;
  173. DrawLine (bound.Width (), 0, bound.Width () - right.thick,
  174. bound.Height () - (lower.style == GCBS_NONE ? 0 : lower.thick), right);
  175. }
  176. if (lower.style != GCBS_NONE){
  177. by = lower.thick;
  178. DrawLine (0 + (left.style == GCBS_NONE ? 0 : left.thick), bound.Height () - lower.thick,
  179. bound.Width (), bound.Height (), lower);
  180. }
  181. if (left.style != GCBS_NONE){
  182. lx = left.thick;
  183. DrawLine (left.thick, upper.style == GCBS_NONE ? 0 : upper.thick, 0,
  184. bound.Height (), left);
  185. }
  186. // fill the canvas with bgcolor
  187. bound.xmin+=lx;
  188. bound.ymin+=ty;
  189. bound.xmax-=rx;
  190. bound.ymax-=by;
  191. Box (0, 0, bound.Width (), bound.Height (), CSPAL_GRIDCELL_BACKGROUND);
  192. if (data){
  193. int tx = (bound.Width () - TextWidth (((csString*)data)->GetData())) /2;
  194. int ty = (bound.Height () - TextHeight ()) /2;
  195. Text (tx, ty, CSPAL_GRIDCELL_DATA_FG, CSPAL_GRIDCELL_DATA_BG, ((csString*)data)->GetData() );
  196. }
  197. bound.xmin-=lx;
  198. bound.ymin-=ty;
  199. bound.xmax+=rx;
  200. bound.ymax+=by;
  201. }
  202. /*******************************************************************************************************
  203. * csGridView
  204. *******************************************************************************************************/
  205. csGridView::csGridView (csGrid *pParent, const csRect& region, int iStyle) : csComponent (pParent)
  206. {
  207. pGrid = pParent;
  208. area.Set (region);
  209. ViewStyle = iStyle;
  210. if (ViewStyle & CSGVS_HSCROLL)
  211. hscroll = new csScrollBar (this, cssfsThinRect);
  212. else
  213. hscroll = NULL;
  214. if (ViewStyle & CSGVS_VSCROLL)
  215. vscroll = new csScrollBar (this, cssfsThinRect);
  216. else
  217. vscroll = NULL;
  218. SetPalette (CSPAL_GRIDVIEW);
  219. col = area.xmin;
  220. row = area.ymin;
  221. }
  222. csGridView::csGridView (const csGridView& view, int iStyle /*=0*/) : csComponent (view.pGrid)
  223. {
  224. pGrid = view.pGrid;
  225. area.Set (view.area);
  226. ViewStyle = (iStyle ? iStyle : view.ViewStyle);
  227. if (ViewStyle & CSGVS_HSCROLL)
  228. hscroll = new csScrollBar (this, cssfsThinRect);
  229. else
  230. hscroll = NULL;
  231. if (ViewStyle & CSGVS_VSCROLL)
  232. vscroll = new csScrollBar (this, cssfsThinRect);
  233. else
  234. vscroll = NULL;
  235. SetPalette (view.palette, view.palettesize);
  236. row = view.row;
  237. col = view.col;
  238. }
  239. bool csGridView::SetRect (int xmin, int ymin, int xmax, int ymax)
  240. {
  241. if (csComponent::SetRect (xmin, ymin, xmax, ymax)){
  242. if (hscroll)
  243. hscroll->SetRect (0, bound.Height () - CSSB_DEFAULTSIZE,
  244. bound.Width () - (vscroll ? CSSB_DEFAULTSIZE-1 : 0), bound.Height () );
  245. if (vscroll)
  246. vscroll->SetRect (bound.Width () - CSSB_DEFAULTSIZE, 0,
  247. bound.Width (), bound.Height () - (hscroll ? CSSB_DEFAULTSIZE-1 : 0) );
  248. fPlaceItems = true;
  249. return true;
  250. }
  251. return false;
  252. }
  253. void csGridView::PlaceItems ()
  254. {
  255. fPlaceItems = false;
  256. // count the number of cells visible in the first row (exact would be the minimum of cells in a row in the visible area)
  257. csVector vRegionList;
  258. csRect rc;
  259. int i=0, w1=0, w2=0;
  260. int nRowCells=0, nColCells=0;
  261. csRegionTree2D *r;
  262. if (hscroll){
  263. rc.Set (col, row, area.xmax, row+1);
  264. pGrid->regions->FindRegion (rc, vRegionList);
  265. while (i < vRegionList.Length() && w1 < bound.Width ()){
  266. r = (csRegionTree2D*)vRegionList.Get (i);
  267. w2 = (r->region.Width() - MAX(col-r->region.xmin,0)) * ((csGridCell*)r->data)->bound.Width (); // #Cells * CellLength
  268. if (w1+w2 < bound.Width ()){
  269. nRowCells += (r->region.Width() - MAX(col-r->region.xmin,0));
  270. w1+=w2;
  271. }else{
  272. nRowCells += (bound.Width () - w1)/((csGridCell*)r->data)->bound.Width ();
  273. w1=bound.Width ();
  274. }
  275. i++;
  276. }
  277. hsbstatus.value = col - area.xmin;
  278. hsbstatus.maxvalue = area.Width ();
  279. hsbstatus.size = 10;
  280. hsbstatus.maxsize = area.Width ();
  281. hsbstatus.step = 1;
  282. hsbstatus.pagestep = MAX( nRowCells, 1);
  283. hscroll->SendCommand (cscmdScrollBarSet, &hsbstatus);
  284. }
  285. if (vscroll){
  286. // count numbers of cells in first column (exact would be the minimum of cells in a column in the visible area)
  287. rc.Set (col, row, col+1, area.ymax);
  288. i=0, w1=0, w2=0;
  289. vRegionList.SetLength (0);
  290. pGrid->regions->FindRegion (rc, vRegionList);
  291. while (i < vRegionList.Length() && w1 < bound.Height ()){
  292. r = (csRegionTree2D*)vRegionList.Get (i);
  293. // #Cells * CellHeight
  294. w2 = (r->region.Height()-MAX(row-r->region.ymin, 0)) * ((csGridCell*)r->data)->bound.Height ();
  295. if (w1+w2 < bound.Height ()){
  296. nColCells += (r->region.Height()-MAX(row-r->region.ymin, 0));
  297. w1+=w2;
  298. }else{
  299. nColCells += (bound.Height () - w1)/((csGridCell*)r->data)->bound.Height ();
  300. w1=bound.Height ();
  301. }
  302. i++;
  303. }
  304. vsbstatus.value = row - area.ymin;
  305. vsbstatus.maxvalue = area.Height ();
  306. vsbstatus.size = 10;
  307. vsbstatus.maxsize = area.Height ();
  308. vsbstatus.step = 1;
  309. vsbstatus.pagestep = MAX( nColCells, 1);
  310. vscroll->SendCommand (cscmdScrollBarSet, &vsbstatus);
  311. }
  312. }
  313. static bool DrawCellComponents (csComponent *child, void *param){
  314. (void)param;
  315. child->Draw ();
  316. return false;
  317. }
  318. void csGridView::Draw()
  319. {
  320. if (fPlaceItems)
  321. PlaceItems ();
  322. int y=0, x, n;
  323. int c,actRow=row;
  324. csRect rc;
  325. csRegionTree2D *r;
  326. csVector vRegions;
  327. csGridCell *cell = NULL;
  328. while (y < bound.Height () && actRow < area.ymax){
  329. rc.Set (col, actRow, area.xmax, actRow+1);
  330. vRegions.SetLength (0);
  331. pGrid->regions->FindRegion (rc, vRegions);
  332. if (vRegions.Length () == 0) break; // no more rows to draw
  333. x=0; n=0; c=col;
  334. while (x < bound.Width () && n < vRegions.Length () && c < area.xmax){
  335. r = (csRegionTree2D*)vRegions.Get (n++);
  336. cell = (csGridCell*)r->data;
  337. Insert (cell); cell->Show (false); // show but don't focus
  338. for (; c < r->region.xmax && x < bound.Width () && c < area.xmax; c++){
  339. cell->SetPos (x, y);
  340. cell->row = actRow;
  341. cell->col = c;
  342. cell->data = pGrid->grid->GetAt (actRow, c);
  343. cell->Draw ();
  344. cell->ForEach (DrawCellComponents, NULL, true);
  345. x += cell->bound.Width ();
  346. }
  347. Delete (cell);
  348. }
  349. y += cell->bound.Height ();
  350. actRow++;
  351. }
  352. // fill the remainingspace with backcolor
  353. Box (0, y, bound.Width (), bound.Height (), CSPAL_GRIDVIEW_BACKGROUND);
  354. csComponent::Draw ();
  355. }
  356. bool csGridView::HandleEvent (csEvent& Event)
  357. {
  358. switch (Event.Type){
  359. case csevCommand:
  360. switch (Event.Command.Code){
  361. case cscmdScrollBarValueChanged:
  362. {
  363. csScrollBar *bar = (csScrollBar*)Event.Command.Info;
  364. csScrollBarStatus sbs;
  365. if (!bar || bar->SendCommand (cscmdScrollBarGetStatus, &sbs))
  366. return true;
  367. if (sbs.maxvalue <= 0)
  368. return true;
  369. if (bar == hscroll){
  370. hsbstatus = sbs;
  371. if (col-area.xmin != sbs.value){
  372. col = area.xmin + sbs.value;
  373. PlaceItems ();
  374. Invalidate (true);
  375. }
  376. }else
  377. if (bar == vscroll){
  378. vsbstatus = sbs;
  379. if (row-area.ymin != sbs.value){
  380. row = area.ymin + sbs.value;
  381. PlaceItems ();
  382. Invalidate (true);
  383. }
  384. }
  385. return true;
  386. }
  387. break;
  388. };
  389. break;
  390. }
  391. return csComponent::HandleEvent (Event);
  392. }
  393. void csGridView::FixSize (int &newW, int &newH)
  394. {
  395. if (hscroll && newH < hscroll->bound.Height () ) newH = hscroll->bound.Height ();
  396. if (vscroll && newW < vscroll->bound.Width () ) newW = vscroll->bound.Width ();
  397. }
  398. void csGridView::SuggestSize (int &w, int &h)
  399. {
  400. w=h=0;
  401. if (hscroll) { h += CSSB_DEFAULTSIZE; }
  402. if (vscroll) { w += CSSB_DEFAULTSIZE; }
  403. }
  404. csGridView* csGridView::CreateCopy (int iStyle)
  405. {
  406. return new csGridView (*this, iStyle);
  407. }
  408. csGridView* csGridView::SplitX (int x, int iStyle /*=0*/)
  409. {
  410. csGridView *sp=NULL;
  411. if (x>0 && x<bound.Width ()){
  412. sp = CreateCopy (iStyle);
  413. if (sp){
  414. sp->areafactor = (float)x / (float)bound.Width ();
  415. pGrid->vViews.Push (sp);
  416. sp->SetRect (bound.xmin, bound.ymin, bound.xmin + x, bound.ymax);
  417. SetRect (bound.xmin + x, bound.ymin, bound.xmax, bound.ymax);
  418. pGrid->viewlayout->Insert (sp->bound, sp);
  419. }
  420. }
  421. return sp;
  422. }
  423. csGridView* csGridView::SplitY (int y, int iStyle /*=0*/)
  424. {
  425. csGridView *sp=NULL;
  426. if (y>0 && y<bound.Height ()){
  427. sp = CreateCopy (iStyle);
  428. if (sp){
  429. sp->areafactor = (float)y / (float)bound.Height ();
  430. pGrid->vViews.Push (sp);
  431. sp->SetRect (bound.xmin, bound.ymin, bound.xmax, bound.ymin+y);
  432. SetRect (bound.xmin, bound.ymin+y, bound.xmax, bound.ymax);
  433. pGrid->viewlayout->Insert (sp->bound, sp);
  434. }
  435. }
  436. return sp;
  437. }
  438. /*******************************************************************************************************
  439. * csGrid
  440. *******************************************************************************************************/
  441. csGrid::csGrid (csComponent *pParent, int nRows, int nCols, int iStyle) : csComponent (pParent)
  442. {
  443. csRect rc (0, 0, nCols, nRows);
  444. csGridCell *gc = new csGridCell;
  445. gc->SetRect (0, 0, 50, 30);
  446. init (pParent, rc, iStyle, gc);
  447. }
  448. csGrid::csGrid (csComponent *pParent, int nRows, int nCols, int iStyle, csGridCell *gridpattern) : csComponent (pParent)
  449. {
  450. csRect rc (0, 0, nCols, nRows);
  451. init (pParent, rc, iStyle, gridpattern);
  452. }
  453. void csGrid::init (csComponent *pParent, csRect &rc, int iStyle, csGridCell *gc)
  454. {
  455. grid = new csSparseGrid;
  456. SetPalette (CSPAL_GRIDVIEW);
  457. SetState (CSS_SELECTABLE, true);
  458. vRegionStyles.Push (gc);
  459. vViews.Push (new csGridView (this, rc, (iStyle & ~(CSGS_HSPLIT|CSGS_VSPLIT))));
  460. regions = new csRegionTree2D (rc, vRegionStyles.Get (0) );
  461. // rc below is a dummy and will be recalculated when SetRect is called
  462. viewlayout = new csRegionTree2D (rc, vViews.Get (0) );
  463. sliderX=sliderY=NULL;
  464. if (iStyle & CSGS_HSPLIT)
  465. sliderX = new csSlider (this);
  466. if (iStyle & CSGS_VSPLIT)
  467. sliderY = new csSlider (this);
  468. if (pParent)
  469. pParent->SendCommand (cscmdWindowSetClient, (void*)this);
  470. }
  471. csGrid::~csGrid ()
  472. {
  473. int i;
  474. for (i=0; i < grid->rows.Length (); i++){
  475. csSparseGrid::csGridRow *r = (csSparseGrid::csGridRow*)grid->rows.Get(i)->data;
  476. for(int j=0; j<r->Length (); j++){
  477. csString *str = (csString*)r->Get (j)->data;
  478. if (str) delete str;
  479. }
  480. delete r;
  481. }
  482. delete grid;
  483. delete regions;
  484. for (i=0; i<vRegionStyles.Length (); i++) delete (csGridCell*)vRegionStyles.Get (i);
  485. // for (i=0; i<vViews.Length (); i++) delete (csGridView*)vViews.Get (i);
  486. }
  487. void csGrid::Draw ()
  488. {
  489. Box (0, 0, bound.Width (), bound.Height (), CSPAL_GRIDVIEW_BACKGROUND);
  490. csComponent::Draw (); // views are children, so they are drawn here
  491. }
  492. bool csGrid::HandleEvent (csEvent &Event)
  493. {
  494. switch (Event.Type){
  495. case csevCommand:
  496. switch (Event.Command.Code){
  497. case cscmdSliderPosSet:
  498. {
  499. csSlider *sl = (csSlider*)Event.Command.Info;
  500. // find the view containing the mouse pointer
  501. int x,y, x1, y1;
  502. sl->GetLastMousePos (x, y);
  503. sl->LocalToGlobal (x, y);
  504. x1=x; y1=y;
  505. GlobalToLocal (x,y);
  506. csRect rc (x, y, x+1, y+1);
  507. csVector vSpl;
  508. viewlayout->FindRegion (rc, vSpl);
  509. if (vSpl.Length () == 1){
  510. csGridView *spl = (csGridView*)((csRegionTree2D*)vSpl.Get (0))->data;
  511. spl->GlobalToLocal (x1, y1);
  512. if (sl == sliderX){
  513. spl->SplitX (x1);
  514. // place the slider to its original locations
  515. }else{
  516. spl->SplitY (y1);
  517. }
  518. PlaceItems ();
  519. }else
  520. return false;
  521. return true;
  522. }
  523. break;
  524. }
  525. break;
  526. }
  527. return csComponent::HandleEvent (Event);
  528. }
  529. /**
  530. * Resize views proportional to the new size of csGrid.
  531. * @@@ TODO: TAKE MINIMUM SIZE INTO ACCOUNT
  532. */
  533. static bool ResizeViews (csSome node, csSome /*databag*/)
  534. {
  535. csRegionTree2D *t = (csRegionTree2D*)node;
  536. if (t->children[0] == NULL){
  537. // leaf - we find the new size in the region variable
  538. ((csGridView*)t->data)->SetRect (t->region.xmin, t->region.ymin, t->region.xmax, t->region.ymax );
  539. return false;
  540. }else{
  541. csGridView *sp1 = (csGridView*)t->children[0]->data;
  542. int newWidthSp1 = (int)(t->region.Width () * sp1->areafactor);
  543. int newHeightSp1 = (int)(t->region.Height () * sp1->areafactor);
  544. if (t->children[0]->region.xmin != t->children[1]->region.xmin){
  545. // views were divided along the x axis
  546. t->children[0]->region.Set (t->region.xmin, t->region.ymin, t->region.xmin + newWidthSp1, t->region.ymax);
  547. t->children[1]->region.Set (t->region.xmin + newWidthSp1, t->region.ymin, t->region.xmax, t->region.ymax);
  548. }else{
  549. // views were divided along the y axis
  550. t->children[0]->region.Set (t->region.xmin, t->region.ymin, t->region.xmax, t->region.ymin + newHeightSp1);
  551. t->children[1]->region.Set (t->region.xmin, t->region.ymin + newHeightSp1, t->region.xmax, t->region.ymax);
  552. }
  553. }
  554. return true;
  555. }
  556. /**
  557. * Calculate the minimal area neeed to display all views.
  558. */
  559. void csGrid::CalcMinimalSize (csRegionTree2D *node, int &w, int &h)
  560. {
  561. if (node->children[0] == NULL){
  562. // leaf
  563. ((csGridView*)node->data)->SuggestSize (w, h);
  564. }else{
  565. int w1, w2, h1, h2;
  566. csGridView *sp1 = (csGridView*)(node->children[0]->data);
  567. csGridView *sp2 = (csGridView*)(node->children[1]->data);
  568. CalcMinimalSize (node->children[0], w1, h1);
  569. CalcMinimalSize (node->children[1], w2, h2);
  570. if (sp1->bound.xmin != sp2->bound.xmin){
  571. w = w1 + w2;
  572. h = MAX (h1, h2);
  573. }else{
  574. w = MAX (w1, w2);
  575. h = h1 + h2;
  576. }
  577. }
  578. }
  579. bool csGrid::SetRect (int xmin, int ymin, int xmax, int ymax)
  580. {
  581. if (csComponent::SetRect (xmin, ymin, xmax, ymax)){
  582. viewlayout->region.Set (0, 0, bound.Width ()- (sliderX?4:0), bound.Height ()-(sliderY?4:0));
  583. viewlayout->Traverse (ResizeViews);
  584. PlaceItems ();
  585. return true;
  586. }
  587. return false;
  588. }
  589. void csGrid::FixSize (int &newW, int &newH)
  590. {
  591. int w, h;
  592. SuggestSize (w, h);
  593. if (newW < w) newW = w;
  594. if (newH < h) newH = h;
  595. }
  596. void csGrid::SuggestSize (int &w, int &h)
  597. {
  598. CalcMinimalSize (viewlayout, w, h);
  599. w += (sliderX ? sliderX->bound.Width () : 0);
  600. h += (sliderY ? sliderY->bound.Height () : 0);
  601. }
  602. void csGrid::PlaceItems ()
  603. {
  604. if (sliderX)
  605. sliderX->SetRect (bound.Width()-3, 0, bound.Width (), bound.Height ());
  606. if (sliderY)
  607. sliderY->SetRect (0, bound.Height () - 3, bound.Width (), bound.Height ());
  608. }
  609. void csGrid::SetStringAt (int row, int col, const char *data)
  610. {
  611. csString *str = (csString*)grid->GetAt (row, col);
  612. if (str || data){
  613. if (!str){
  614. str = new csString (data);
  615. grid->SetAt (row, col, str);
  616. }else if (!data) {
  617. delete str;
  618. grid->SetAt (row, col, NULL);
  619. }else{
  620. str->Truncate (0).Append (data);
  621. }
  622. }
  623. }
  624. void csGrid::CreateRegion (csRect& rc, csGridCell *cell)
  625. {
  626. regions->Insert (rc, cell);
  627. if (!cell->IsUsed ()){
  628. cell->SetUsed ();
  629. vRegionStyles.Push (cell);
  630. }
  631. Invalidate (true);
  632. }