home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / OWLSRC.PAK / TOOLBOX.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  6.3 KB  |  255 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // Copyright (c) 1992, 1997 by Borland International, All Rights Reserved
  4. //
  5. //$Revision:   10.9  $
  6. //
  7. // Implementation of class TToolBox, a 2-d arrangement of TButtonGadgets.
  8. //----------------------------------------------------------------------------
  9. #include <owl/pch.h>
  10. #if !defined(OWL_TOOLBOX_H)
  11. # include <owl/toolbox.h>
  12. #endif
  13. #if !defined(OWL_BUTTONGA_H)
  14. # include <owl/buttonga.h>
  15. #endif
  16. #if !defined(WINSYS_UIMETRIC_H)
  17. # include <winsys/uimetric.h>
  18. #endif
  19.  
  20. OWL_DIAGINFO;
  21.  
  22. IMPLEMENT_CASTABLE(TToolBox);
  23.  
  24. //
  25. // Construct a 2-d toolbox with a given number of rows, columns, and direction.
  26. //
  27. TToolBox::TToolBox(TWindow*        parent,
  28.                    int             numColumns,
  29.                    int             numRows,
  30.                    TTileDirection  direction,
  31.                    TModule*        module)
  32. :
  33.   TGadgetWindow(parent, direction, new TGadgetWindowFont, module)
  34. {
  35.   NumRows = numRows;
  36.   NumColumns = numColumns;
  37.  
  38.   // Make the gadget borders (if any) overlap the tool box's borders
  39.   //
  40.   Margins.Units = TMargins::BorderUnits;
  41.   Margins.Left = Margins.Right = TSystem::Has3dUI() ? 0 : -TUIMetric::CxBorder;
  42.   Margins.Top = Margins.Bottom = TSystem::Has3dUI() ? 0 : -TUIMetric::CyBorder;
  43.  
  44.   ShrinkWrapWidth = true;
  45. }
  46.  
  47. //
  48. // Always turn off notched corners when gadgets are in this toolbox.
  49. // Only TButtonGadgets or derived gadgets are supported.
  50. //
  51. void
  52. TToolBox::Insert(TGadget& g, TPlacement placement, TGadget* sibling)
  53. {
  54.   TGadgetWindow::Insert(g, placement, sibling);
  55.  
  56.   // Notch the corners if it's a buttonGadget
  57.   //
  58.   TButtonGadget* bg = TYPESAFE_DOWNCAST(&g,TButtonGadget);
  59.   if (bg)
  60.     bg->SetNotchCorners(false);
  61. }
  62.  
  63. //
  64. // Swap the rows & columns count, & let our base class do the rest
  65. //
  66. void
  67. TToolBox::SetDirection(TTileDirection direction)
  68. {
  69.   if (Direction != direction) {
  70.     int t = NumRows;
  71.     NumRows = NumColumns;
  72.     NumColumns = t;
  73.   }
  74.  
  75.   TGadgetWindow::SetDirection(direction);
  76. }
  77.  
  78. //
  79. // Compute the numer of rows & columns, filling in rows OR columns if left
  80. // unspecified using AS_MANY_AS_NEEDED (but not both).
  81. //
  82. void
  83. TToolBox::ComputeNumRowsColumns(int& numRows, int& numColumns)
  84. {
  85.   CHECK(NumRows != AS_MANY_AS_NEEDED || NumColumns != AS_MANY_AS_NEEDED);
  86.   numRows = NumRows == AS_MANY_AS_NEEDED ?
  87.               (NumGadgets + NumColumns - 1) / NumColumns :
  88.               NumRows;
  89.   numColumns = NumColumns == AS_MANY_AS_NEEDED ?
  90.                  (NumGadgets + NumRows - 1) / NumRows :
  91.                  NumColumns;
  92. }
  93.  
  94. //
  95. // Compute the cell size which is determined by the widest and the highest
  96. // gadget
  97. //
  98. void
  99. TToolBox::ComputeCellSize(TSize& cellSize)
  100. {
  101.   cellSize.cx = cellSize.cy = 0;
  102.  
  103.   for (TGadget* g = Gadgets; g; g = g->NextGadget()) {
  104.     TSize  desiredSize(0, 0);
  105.  
  106.     g->GetDesiredSize(desiredSize);
  107.  
  108.     if (desiredSize.cx > cellSize.cx)
  109.       cellSize.cx = desiredSize.cx;
  110.  
  111.     if (desiredSize.cy > cellSize.cy)
  112.       cellSize.cy = desiredSize.cy;
  113.   }
  114. }
  115.  
  116. //
  117. // Calculate how big this toolbox should be.
  118. //
  119. void
  120. TToolBox::GetDesiredSize(TSize& size)
  121. {
  122.   // Get border sizes
  123.   //
  124.   int    cxBorder = TSystem::Has3dUI() ? 0 : (int)TUIMetric::CxBorder;
  125.   int    cyBorder = TSystem::Has3dUI() ? 0 : (int)TUIMetric::CyBorder;
  126.  
  127.   int    left, right, top, bottom;
  128.   GetMargins(Margins, left, right, top, bottom);
  129.   size.cx = left + right;
  130.   size.cy = top + bottom;
  131.  
  132.   // Add in this window's border size if used
  133.   //
  134.   if (Attr.Style & WS_BORDER) {
  135.     size.cx += 2 * TUIMetric::CxBorder;
  136.     size.cy += 2 * TUIMetric::CyBorder;
  137.   }
  138.  
  139.   TSize  cellSize;
  140.   ComputeCellSize(cellSize);
  141.  
  142.   int    numRows, numColumns;
  143.   ComputeNumRowsColumns(numRows, numColumns);
  144.  
  145.   size.cx += numColumns * cellSize.cx;
  146.   size.cy += numRows * cellSize.cy;
  147.  
  148.   // Compensate for the gadgets overlapping if UI style does that
  149.   //
  150.   size.cx -= (numColumns - 1) * cxBorder;
  151.   size.cy -= (numRows - 1) * cyBorder;
  152. }
  153.  
  154. //
  155. // Tile the gadgets in a tight 2-dimensional grid. Horizontal direction results
  156. // in a row-major layout, and vertical direction results in column-major layout
  157. //
  158. TRect
  159. TToolBox::TileGadgets()
  160. {
  161.   TSize     cellSize;
  162.   ComputeCellSize(cellSize);
  163.  
  164.   int       numRows, numColumns;
  165.   ComputeNumRowsColumns(numRows, numColumns);
  166.  
  167.   TRect     innerRect;
  168.   GetInnerRect(innerRect);
  169.  
  170.   TRect     invalidRect;
  171.   invalidRect.SetEmpty();
  172.  
  173.   if (Direction == Horizontal) {
  174.     // Row Major
  175.     //
  176.     int y = innerRect.top;
  177.     TGadget* g = Gadgets;
  178.  
  179.     for (int r = 0; r < numRows; r++) {
  180.       int x = innerRect.left;
  181.  
  182.       for (int c = 0; c < numColumns && g; c++) {
  183.         TRect bounds(TPoint(x, y), cellSize);
  184.         TRect originalBounds(g->GetBounds());
  185.  
  186.         if (bounds != g->GetBounds()) {
  187.           g->SetBounds(bounds);
  188.  
  189.           if (invalidRect.IsNull())
  190.             invalidRect = bounds;
  191.           else
  192.             invalidRect |= bounds;
  193.  
  194.           if (originalBounds.TopLeft() != TPoint(0, 0))
  195.             invalidRect |= originalBounds;
  196.         }
  197.  
  198.         x += cellSize.cx;
  199.         g = g->NextGadget();
  200.       }
  201.  
  202.       y += cellSize.cy;
  203.     }
  204.   }
  205.   else {
  206.     // Column Major
  207.     //
  208.     int x = innerRect.left;
  209.     TGadget* g = Gadgets;
  210.  
  211.     for (int c = 0; c < numColumns; c++) {
  212.       int y = innerRect.top;
  213.  
  214.       for (int r = 0; r < numRows && g; r++) {
  215.         TRect bounds(TPoint(x, y), cellSize);
  216.         TRect originalBounds(g->GetBounds());
  217.  
  218.         if (bounds != originalBounds) {
  219.           g->SetBounds(bounds);
  220.  
  221.           if (invalidRect.IsNull())
  222.             invalidRect = bounds;
  223.           else
  224.             invalidRect |= bounds;
  225.  
  226.           if (originalBounds.TopLeft() != TPoint(0, 0))
  227.             invalidRect |= originalBounds;
  228.         }
  229.  
  230.         y += cellSize.cy;
  231.         g = g->NextGadget();
  232.       }
  233.  
  234.       x += cellSize.cx;
  235.     }
  236.   }
  237.   return invalidRect;
  238. }
  239.  
  240. //
  241. // Perform a layout session. After calling the base LayoutSession, adjust this
  242. // window's size & pos to match desired. Assumes it is used as a client in a
  243. // frame.
  244. //
  245. void
  246. TToolBox::LayoutSession()
  247. {
  248.   TGadgetWindow::LayoutSession();
  249.  
  250.   TSize sz;
  251.   GetDesiredSize(sz);
  252.  
  253.   SetWindowPos(0, 0,0, sz.cx, sz.cy, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER);
  254. }
  255.