1 #---------------------------------------------------------------------- 
   2 # Name:        wxPython.lib.rcsizer 
   3 # Purpose:     RowColSizer: 
   5 # Author:      Robin Dunn, adapted from code by Niki Spahiev 
   9 # Copyright:   (c) 2002 by Total Control Software 
  10 # Licence:     wxWindows license 
  11 #---------------------------------------------------------------------- 
  14 A pure-Python wxSizer that lays out items in a grid similar to 
  15 wxFlexGridSizer but item position is not implicit but explicitly 
  16 specified by row and col, and row/col spanning is supported. 
  18 Adapted from code by Niki Spahiev. 
  20 If anyone is interested, it would be nice to have this ported to C++. 
  25 from wxPython
.wx 
import * 
  28 #---------------------------------------------------------------------- 
  30 class RowColSizer(wxPySizer
): 
  32     # default sizes for cells with no item 
  37         wxPySizer
.__init
__(self
) 
  38         self
.growableRows 
= [] 
  39         self
.growableCols 
= [] 
  42     def AddGrowableRow(self
, idx
): 
  43         self
.growableRows
.append(idx
) 
  45     def AddGrowableCol(self
, idx
): 
  46         self
.growableCols
.append(idx
) 
  50     #-------------------------------------------------- 
  51     def Add(self
, item
, option
=0, flag
=0, border
=0, 
  52             row
=-1, col
=-1,       # row, col and spanning can be specified individually... 
  54             pos
=None, size
=None,  # or as tuples (row,col) and (rowspan,colspan) 
  60             rowspan
, colspan 
= size
 
  62         assert row 
!= -1, "Row must be specified" 
  63         assert col 
!= -1, "Column must be specified" 
  65         # Do I really want to do this?  Probably not... 
  66         #if rowspan > 1 or colspan > 1: 
  67         #    flag = flag | wxEXPAND 
  69         wxPySizer
.Add(self
, item
, option
, flag
, border
, 
  70                       userData
=(row
, col
, row
+rowspan
, col
+colspan
)) 
  75     def AddSpacer(self
, width
, height
, option
=0, flag
=0, border
=0, 
  83             rowspan
, colspan 
= size
 
  85         assert row 
!= -1, "Row must be specified" 
  86         assert col 
!= -1, "Column must be specified" 
  88         wxPySizer
.AddSpacer(self
, width
, height
, option
, flag
, border
, 
  89                             userData
=(row
, col
, row
+rowspan
, col
+colspan
)) 
  91     #-------------------------------------------------- 
  92     def _add( self
, size
, dim 
): 
  93         r
, c
, r2
, c2 
= dim   
# unpack coords and spanning 
  95         # are the widths and heights lists long enough? 
  96         if r2 
> len(self
.rowHeights
): 
  97             x 
= [self
.row_h
] * (r2
-len(self
.rowHeights
)) 
  98             self
.rowHeights
.extend( x 
) 
  99         if c2 
> len(self
.colWidths
): 
 100             x 
= [self
.col_w
] * (c2
-len(self
.colWidths
)) 
 101             self
.colWidths
.extend( x 
) 
 103         # set the widths and heights lists for this item 
 105         for i 
in range(r
, r2
): 
 106             self
.rowHeights
[i
] = max( self
.rowHeights
[i
], size
.height 
/ scale 
) 
 108         for i 
in range(c
, c2
): 
 109             self
.colWidths
[i
] = max( self
.colWidths
[i
], size
.width 
/ scale 
) 
 112     #-------------------------------------------------- 
 114         items 
= self
.GetChildren() 
 116             return wxSize(10, 10) 
 122             self
._add
( item
.CalcMin(), item
.GetUserData() ) 
 124         size 
= wxSize( reduce( operator
.add
, self
.colWidths
), 
 125                        reduce( operator
.add
, self
.rowHeights
) ) 
 129     #-------------------------------------------------- 
 130     def RecalcSizes( self 
): 
 131         # save current dimensions, etc. 
 132         curWidth  
= self
.GetSize().width
 
 133         curHeight 
= self
.GetSize().height
 
 134         px 
= self
.GetPosition().x
 
 135         py 
= self
.GetPosition().y
 
 136         minWidth  
= self
.CalcMin().width
 
 137         minHeight 
= self
.CalcMin().height
 
 139         # Check for growables 
 140         if self
.growableRows 
and curHeight 
> minHeight
: 
 141             delta 
= (curHeight 
- minHeight
) / len(self
.growableRows
) 
 142             extra 
= (curHeight 
- minHeight
) % len(self
.growableRows
) 
 143             for idx 
in self
.growableRows
: 
 144                 self
.rowHeights
[idx
] += delta
 
 145             self
.rowHeights
[self
.growableRows
[0]] += extra
 
 147         if self
.growableCols 
and curWidth 
> minWidth
: 
 148             delta 
= (curWidth 
- minWidth
) / len(self
.growableCols
) 
 149             extra 
= (curWidth 
- minWidth
) % len(self
.growableCols
) 
 150             for idx 
in self
.growableCols
: 
 151                 self
.colWidths
[idx
] += delta
 
 152             self
.colWidths
[self
.growableCols
[0]] += extra
 
 154         rpos 
= [0] * len(self
.rowHeights
) 
 155         cpos 
= [0] * len(self
.colWidths
) 
 157         for i 
in range(len(self
.rowHeights
)): 
 158             height 
= self
.rowHeights
[i
] 
 162         for i 
in range(len(self
.colWidths
)): 
 163             width 
= self
.colWidths
[i
] 
 167         # iterate children and set dimensions... 
 168         for item 
in self
.GetChildren(): 
 169             r
, c
, r2
, c2 
= item
.GetUserData() 
 170             width 
= reduce( operator
.add
, self
.colWidths
[c
:c2
] ) 
 171             height 
= reduce( operator
.add
, self
.rowHeights
[r
:r2
] ) 
 172             self
.SetItemBounds( item
, cpos
[c
], rpos
[r
], width
, height 
) 
 175     #-------------------------------------------------- 
 176     def SetItemBounds(self
, item
, x
, y
, w
, h
): 
 177         # calculate the item's actual size and position within 
 181         flag 
= item
.GetFlag() 
 183         if flag 
& wxEXPAND 
or flag 
& wxSHAPED
: 
 186             if flag 
& wxALIGN_CENTER_HORIZONTAL
: 
 187                 ipt
.x 
= x 
+ (w 
- isz
.width
) / 2 
 188             elif flag 
& wxALIGN_RIGHT
: 
 189                 ipt
.x 
= x 
+ (w 
- isz
.width
) 
 191             if flag 
& wxALIGN_CENTER_VERTICAL
: 
 192                 ipt
.y 
= y 
+ (h 
- isz
.height
) / 2 
 193             elif flag 
& wxALIGN_BOTTOM
: 
 194                 ipt
.y 
= y 
+ (h 
- isz
.height
) 
 196         item
.SetDimension(ipt
, isz
) 
 199 #---------------------------------------------------------------------- 
 200 #----------------------------------------------------------------------