1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxGenericGrid
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "gridg.h"
17 // For compilers that support precompilation, includes "wx/wx.h".
18 #include "wx/wxprec.h"
30 #include "wx/string.h"
31 #include "wx/generic/gridg.h"
32 #include "wx/settings.h"
34 static wxFont
*wxGridEntryFont
= NULL
;
36 #define wxGRID_DRAG_NONE 0
37 #define wxGRID_DRAG_LEFT_RIGHT 1
38 #define wxGRID_DRAG_UP_DOWN 2
40 IMPLEMENT_DYNAMIC_CLASS(wxGenericGrid
, wxPanel
)
42 BEGIN_EVENT_TABLE(wxGenericGrid
, wxPanel
)
43 EVT_SIZE(wxGenericGrid::OnSize
)
44 EVT_PAINT(wxGenericGrid::OnPaint
)
45 EVT_MOUSE_EVENTS(wxGenericGrid::OnMouseEvent
)
46 EVT_TEXT(wxGRID_TEXT_CTRL
, wxGenericGrid::OnText
)
47 EVT_COMMAND_SCROLL(wxGRID_HSCROLL
, wxGenericGrid::OnGridScroll
)
48 EVT_COMMAND_SCROLL(wxGRID_VSCROLL
, wxGenericGrid::OnGridScroll
)
51 wxCursor
*wxGenericGrid::horizontalSashCursor
= NULL
;
52 wxCursor
*wxGenericGrid::verticalSashCursor
= NULL
;
54 wxGenericGrid::wxGenericGrid(void)
59 cellTextColour
= *wxBLACK
;
60 cellBackgroundColour
= *wxWHITE
;
61 labelTextColour
= *wxBLACK
;
62 labelBackgroundColour
= *wxLIGHT_GREY
;
63 labelBackgroundBrush
= NULL
;
67 currentRectVisible
= FALSE
;
69 #if defined(__WIN95__)
70 scrollWidth
= wxSystemSettings::GetSystemMetric(wxSYS_VSCROLL_X
);
74 dragStatus
= wxGRID_DRAG_NONE
;
76 dragStartPosition
= 0;
79 wxGridEntryFont
= NULL
;
80 leftOfSheet
= wxGRID_DEFAULT_SHEET_LEFT
;
81 topOfSheet
= wxGRID_DEFAULT_SHEET_TOP
;
82 cellHeight
= wxGRID_DEFAULT_CELL_HEIGHT
;
87 verticalLabelWidth
= wxGRID_DEFAULT_VERTICAL_LABEL_WIDTH
;
88 horizontalLabelHeight
= wxGRID_DEFAULT_HORIZONAL_LABEL_HEIGHT
;
89 verticalLabelAlignment
= wxCENTRE
;
90 horizontalLabelAlignment
= wxCENTRE
;
91 editControlPosition
.x
= wxGRID_DEFAULT_EDIT_X
;
92 editControlPosition
.y
= wxGRID_DEFAULT_EDIT_Y
;
93 editControlPosition
.width
= wxGRID_DEFAULT_EDIT_WIDTH
;
94 editControlPosition
.height
= wxGRID_DEFAULT_EDIT_HEIGHT
;
103 rowLabelCells
= NULL
;
104 colLabelCells
= NULL
;
108 bool wxGenericGrid::Create(wxWindow
*parent
, const wxWindowID id
, const wxPoint
& pos
, const wxSize
& size
,
109 const long style
, const wxString
& name
)
115 cellTextColour
= *wxBLACK
;
116 cellBackgroundColour
= *wxWHITE
;
117 labelTextColour
= *wxBLACK
;
118 labelBackgroundColour
= *wxLIGHT_GREY
;
119 labelBackgroundBrush
= NULL
;
120 labelTextFont
= wxTheFontList
->FindOrCreateFont(10, wxSWISS
, wxNORMAL
, wxBOLD
);
121 cellTextFont
= wxTheFontList
->FindOrCreateFont(10, wxSWISS
, wxNORMAL
, wxNORMAL
);
123 currentRectVisible
= FALSE
;
125 #if defined(__WIN95__)
126 scrollWidth
= wxSystemSettings::GetSystemMetric(wxSYS_VSCROLL_X
);
130 dragStatus
= wxGRID_DRAG_NONE
;
132 dragStartPosition
= 0;
133 dragLastPosition
= 0;
134 divisionPen
= wxThePenList
->FindOrCreatePen("LIGHT GREY", 1, wxSOLID
);
136 if (!wxGridEntryFont
)
137 wxGridEntryFont
= new wxFont(9, wxSWISS
, wxNORMAL
, wxBOLD
);
139 if (!horizontalSashCursor
)
141 horizontalSashCursor
= new wxCursor(wxCURSOR_SIZEWE
);
142 verticalSashCursor
= new wxCursor(wxCURSOR_SIZENS
);
145 SetLabelBackgroundColour(labelBackgroundColour
);
147 leftOfSheet
= wxGRID_DEFAULT_SHEET_LEFT
;
148 topOfSheet
= wxGRID_DEFAULT_SHEET_TOP
;
149 cellHeight
= wxGRID_DEFAULT_CELL_HEIGHT
;
155 verticalLabelWidth
= wxGRID_DEFAULT_VERTICAL_LABEL_WIDTH
;
156 horizontalLabelHeight
= wxGRID_DEFAULT_HORIZONAL_LABEL_HEIGHT
;
157 verticalLabelAlignment
= wxCENTRE
;
158 horizontalLabelAlignment
= wxCENTRE
;
159 editControlPosition
.x
= wxGRID_DEFAULT_EDIT_X
;
160 editControlPosition
.y
= wxGRID_DEFAULT_EDIT_Y
;
161 editControlPosition
.width
= wxGRID_DEFAULT_EDIT_WIDTH
;
162 editControlPosition
.height
= wxGRID_DEFAULT_EDIT_HEIGHT
;
170 /* Store the rect. coordinates for the current cell */
171 SetCurrentRect(wCursorRow
, wCursorColumn
);
173 bEditCreated
= FALSE
;
178 rowLabelCells
= NULL
;
179 colLabelCells
= NULL
;
182 wxPanel::Create(parent
, id
, pos
, size
, style
, name
);
184 SetButtonFont(*wxGridEntryFont
);
185 SetLabelFont(*wxGridEntryFont
);
187 textItem
= new wxTextCtrl(this, wxGRID_TEXT_CTRL
, "",
188 wxPoint(editControlPosition
.x
, editControlPosition
.y
), wxSize(editControlPosition
.width
, -1),
190 textItem
->Show(TRUE
);
191 // textItem->SetLabel("");
192 textItem
->SetFocus();
193 int controlW
, controlH
;
195 textItem
->GetSize(&controlW
, &controlH
);
196 editControlPosition
.height
= controlH
;
198 topOfSheet
= editControlPosition
.y
+ controlH
+ 2;
202 hScrollBar
= new wxScrollBar(this, wxGRID_HSCROLL
, wxPoint(0, 0), wxSize(20, 100), wxHORIZONTAL
);
203 vScrollBar
= new wxScrollBar(this, wxGRID_VSCROLL
, wxPoint(0, 0), wxSize(100, 20), wxVERTICAL
);
204 // hScrollBar->Show(FALSE);
205 // vScrollBar->Show(FALSE);
206 AllowDoubleClick(TRUE
);
211 wxGenericGrid::~wxGenericGrid(void)
216 void wxGenericGrid::ClearGrid(void)
221 for (i
= 0; i
< totalRows
; i
++)
223 for (j
= 0; j
< totalCols
; j
++)
225 delete gridCells
[i
][j
];
226 delete[] gridCells
[i
];
240 for (i
= 0; i
< totalRows
; i
++)
241 delete rowLabelCells
[i
];
242 delete[] rowLabelCells
;
243 rowLabelCells
= NULL
;
247 for (i
= 0; i
< totalCols
; i
++)
248 delete colLabelCells
[i
];
249 delete[] colLabelCells
;
250 colLabelCells
= NULL
;
254 bool wxGenericGrid::CreateGrid(int nRows
, int nCols
, wxString
**cellValues
, short *widths
,
255 short defaultWidth
, short defaultHeight
)
261 colWidths
= new short[nCols
];
262 rowHeights
= new short[nRows
];
263 for (i
= 0; i
< nCols
; i
++)
265 colWidths
[i
] = widths
[i
];
267 colWidths
[i
] = defaultWidth
;
268 for (i
= 0; i
< nRows
; i
++)
269 rowHeights
[i
] = defaultHeight
;
271 gridCells
= new wxGridCell
**[nRows
];
273 for (i
= 0; i
< nRows
; i
++)
274 gridCells
[i
] = new wxGridCell
*[nCols
];
276 for (i
= 0; i
< nRows
; i
++)
277 for (j
= 0; j
< nCols
; j
++)
280 gridCells
[i
][j
] = OnCreateCell();
281 gridCells
[i
][j
]->SetTextValue(cellValues
[i
][j
]);
284 gridCells
[i
][j
] = NULL
;
286 rowLabelCells
= new wxGridCell
*[nRows
];
287 for (i
= 0; i
< nRows
; i
++)
288 rowLabelCells
[i
] = new wxGridCell(this);
289 colLabelCells
= new wxGridCell
*[nCols
];
290 for (i
= 0; i
< nCols
; i
++)
291 colLabelCells
[i
] = new wxGridCell(this);
293 wCursorRow
= wCursorColumn
= 0;
294 SetCurrentRect(0, 0);
296 // Need to determine various dimensions
300 int objectSizeX
= totalCols
;
302 int viewLengthX
= totalCols
;
303 hScrollBar
->SetViewLength(viewLengthX
);
304 hScrollBar
->SetObjectLength(objectSizeX
);
305 hScrollBar
->SetPageSize(pageSizeX
);
307 int objectSizeY
= totalRows
;
309 int viewLengthY
= totalRows
;
311 vScrollBar
->SetViewLength(viewLengthY
);
312 vScrollBar
->SetObjectLength(objectSizeY
);
313 vScrollBar
->SetPageSize(pageSizeY
);
318 OnChangeSelectionLabel();
323 // Need to determine various dimensions
324 void wxGenericGrid::UpdateDimensions(void)
326 int canvasWidth
, canvasHeight
;
327 GetSize(&canvasWidth
, &canvasHeight
);
331 int controlW
, controlH
;
332 GetTextItem()->GetSize(&controlW
, &controlH
);
333 topOfSheet
= editControlPosition
.y
+ controlH
+ 2;
337 rightOfSheet
= leftOfSheet
+ verticalLabelWidth
;
339 for (i
= scrollPosX
; i
< totalCols
; i
++)
341 if (rightOfSheet
> canvasWidth
)
344 rightOfSheet
+= colWidths
[i
];
346 bottomOfSheet
= topOfSheet
+ horizontalLabelHeight
;
347 for (i
= scrollPosY
; i
< totalRows
; i
++)
349 if (bottomOfSheet
> canvasHeight
)
352 bottomOfSheet
+= rowHeights
[i
];
355 totalGridWidth
= leftOfSheet
+ verticalLabelWidth
;
356 for (i
= 0; i
< totalCols
; i
++)
358 totalGridWidth
+= colWidths
[i
];
360 totalGridHeight
= topOfSheet
+ horizontalLabelHeight
;
361 for (i
= 0; i
< totalRows
; i
++)
363 totalGridHeight
+= rowHeights
[i
];
367 wxGridCell
*wxGenericGrid::GetCell(int row
, int col
)
372 if ((row
>= totalRows
) || (col
>= totalCols
))
375 wxGridCell
*cell
= gridCells
[row
][col
];
378 gridCells
[row
][col
] = OnCreateCell();
379 return gridCells
[row
][col
];
385 void wxGenericGrid::SetGridClippingRegion(wxDC
*dc
)
387 int scrollWidthHoriz
= 0;
388 int scrollWidthVert
= 0;
390 GetClientSize(&cw
, &ch
);
392 if (hScrollBar
&& hScrollBar
->IsShown())
393 scrollWidthHoriz
= scrollWidth
;
394 if (vScrollBar
&& vScrollBar
->IsShown())
395 scrollWidthVert
= scrollWidth
;
397 // Don't paint over the scrollbars
398 dc
->SetClippingRegion(leftOfSheet
, topOfSheet
,
399 cw
- scrollWidthVert
- leftOfSheet
, ch
- scrollWidthHoriz
- topOfSheet
);
402 void wxGenericGrid::OnPaint(wxPaintEvent
& WXUNUSED(event
))
405 static bool inPaint = FALSE;
417 dc
.SetOptimization(FALSE
);
419 SetGridClippingRegion(&dc
);
422 DrawEditableArea(&dc
);
423 DrawColumnLabels(&dc
);
428 /* Hilight present cell */
429 SetCurrentRect(wCursorRow
, wCursorColumn
);
430 if (currentRectVisible
)
433 dc
.DestroyClippingRegion();
434 dc
.SetOptimization(TRUE
);
440 void wxGenericGrid::DrawLabelAreas(wxDC
*dc
)
443 GetClientSize(&cw
, &ch
);
445 dc
->SetPen(*wxTRANSPARENT_PEN
);
446 // dc->SetBrush(*dc->GetBackground());
448 // Should blank out any area which isn't going to be painted over.
449 // dc->DrawRectangle(leftOfSheet, bottomOfSheet, cw - leftOfSheet, ch - bottomOfSheet);
450 // dc->DrawRectangle(rightOfSheet, topOfSheet, cw - rightOfSheet, ch - topOfSheet);
452 // Paint the label areas
453 dc
->SetBrush(*labelBackgroundBrush
);
454 // dc->DrawRectangle(leftOfSheet, topOfSheet, rightOfSheet - leftOfSheet + 1, horizontalLabelHeight + 1);
455 dc
->DrawRectangle(leftOfSheet
, topOfSheet
, cw
-leftOfSheet
, horizontalLabelHeight
+ 1);
456 // dc->DrawRectangle(leftOfSheet, topOfSheet, verticalLabelWidth + 1, bottomOfSheet - topOfSheet + 1);
457 dc
->DrawRectangle(leftOfSheet
, topOfSheet
, verticalLabelWidth
+ 1, ch
-topOfSheet
);
460 void wxGenericGrid::DrawEditableArea(wxDC
*dc
)
463 GetClientSize(&cw
, &ch
);
465 dc
->SetPen(*wxTRANSPARENT_PEN
);
466 dc
->SetBrush(*wxTheBrushList
->FindOrCreateBrush(cellBackgroundColour
, wxSOLID
));
467 // dc->DrawRectangle(leftOfSheet+verticalLabelWidth, topOfSheet+horizontalLabelHeight,
468 // rightOfSheet-(leftOfSheet+verticalLabelWidth) + 1, bottomOfSheet - (topOfSheet+horizontalLabelHeight) + 1);
469 dc
->DrawRectangle(leftOfSheet
+verticalLabelWidth
, topOfSheet
+horizontalLabelHeight
,
470 cw
-(leftOfSheet
+verticalLabelWidth
), ch
- (topOfSheet
+horizontalLabelHeight
));
473 void wxGenericGrid::DrawGridLines(wxDC
*dc
)
476 GetClientSize(&cw
, &ch
);
482 dc
->SetPen(*divisionPen
);
484 int heightCount
= topOfSheet
+ horizontalLabelHeight
;
486 // Draw horizontal grey lines for cells
487 for (i
= scrollPosY
; i
< (totalRows
+1); i
++)
489 if (heightCount
> ch
)
493 dc
->DrawLine(leftOfSheet
, heightCount
,
496 heightCount
+= rowHeights
[i
];
501 if (verticalLabelWidth
> 0)
503 dc
->SetPen(*wxBLACK_PEN
);
505 // Draw horizontal black lines for row labels
506 int heightCount
= topOfSheet
+ horizontalLabelHeight
;
507 for (i
= scrollPosY
; i
< (totalRows
+1); i
++)
509 if (heightCount
> ch
)
513 dc
->DrawLine(leftOfSheet
, heightCount
,
514 verticalLabelWidth
, heightCount
);
516 heightCount
+= rowHeights
[i
];
519 // Draw a black vertical line for row number cells
520 dc
->DrawLine(leftOfSheet
+ verticalLabelWidth
, topOfSheet
,
521 leftOfSheet
+ verticalLabelWidth
, ch
);
522 // First vertical line
523 dc
->DrawLine(leftOfSheet
, topOfSheet
, leftOfSheet
, ch
);
525 dc
->SetPen(*wxWHITE_PEN
);
527 // Draw highlights on row labels
528 heightCount
= topOfSheet
+ horizontalLabelHeight
;
529 for (i
= scrollPosY
; i
< totalRows
; i
++)
531 if (heightCount
> ch
)
535 dc
->DrawLine(leftOfSheet
+1, heightCount
+1,
536 verticalLabelWidth
, heightCount
+1);
537 dc
->DrawLine(leftOfSheet
+1, heightCount
+1,
538 leftOfSheet
+1, heightCount
+ rowHeights
[i
] - 1);
539 heightCount
+= rowHeights
[i
];
542 // Last one - down to the floor.
543 dc
->DrawLine(leftOfSheet
+1, heightCount
+1,
544 verticalLabelWidth
, heightCount
+1);
545 dc
->DrawLine(leftOfSheet
+1, heightCount
+1,
552 dc
->SetPen(*divisionPen
);
554 // Draw vertical grey lines for cells
555 int widthCount
= leftOfSheet
+ verticalLabelWidth
;
556 for (i
= scrollPosX
; i
< totalCols
; i
++)
562 // Skip the first one
565 dc
->DrawLine(widthCount
, topOfSheet
+ horizontalLabelHeight
,
566 widthCount
, bottomOfSheet
);
568 widthCount
+= colWidths
[i
];
572 dc
->DrawLine(widthCount
, topOfSheet
+ horizontalLabelHeight
,
573 widthCount
, bottomOfSheet
);
576 dc
->SetPen(*wxBLACK_PEN
);
578 // Draw two black horizontal lines for column number cells
580 leftOfSheet
, topOfSheet
,
582 dc
->DrawLine(leftOfSheet
, topOfSheet
+ horizontalLabelHeight
,
583 cw
, topOfSheet
+ horizontalLabelHeight
);
585 if (horizontalLabelHeight
> 0)
587 int widthCount
= leftOfSheet
+ verticalLabelWidth
;
589 // Draw black vertical lines for column number cells
590 for (i
= scrollPosX
; i
< totalCols
; i
++)
596 dc
->DrawLine(widthCount
, topOfSheet
,
597 widthCount
, topOfSheet
+ horizontalLabelHeight
);
598 widthCount
+= colWidths
[i
];
603 dc
->DrawLine(widthCount
, topOfSheet
,
604 widthCount
, topOfSheet
+ horizontalLabelHeight
);
607 dc
->SetPen(*wxWHITE_PEN
);
608 widthCount
= leftOfSheet
+ verticalLabelWidth
;
610 for (i
= scrollPosX
; i
< totalCols
; i
++)
616 dc
->DrawLine(widthCount
+1, topOfSheet
+1,
617 widthCount
+colWidths
[i
], topOfSheet
+1);
618 dc
->DrawLine(widthCount
+1, topOfSheet
+1,
619 widthCount
+1, topOfSheet
+horizontalLabelHeight
);
620 widthCount
+= colWidths
[i
];
623 // Last one - to the right side of the canvas.
624 dc
->DrawLine(widthCount
+1, topOfSheet
+1,
626 dc
->DrawLine(widthCount
+1, topOfSheet
+1,
627 widthCount
+1, topOfSheet
+horizontalLabelHeight
);
632 void wxGenericGrid::DrawColumnLabels(wxDC
*dc
)
635 GetClientSize(&cw
, &ch
);
637 if (horizontalLabelHeight
== 0)
643 // Draw letters for columns
644 rect
.y
= topOfSheet
+ 1;
645 rect
.height
= horizontalLabelHeight
- 1;
647 dc
->SetTextBackground(labelBackgroundColour
);
648 dc
->SetBackgroundMode(wxTRANSPARENT
);
649 // dc->SetTextForeground(labelTextColour);
651 int widthCount
= leftOfSheet
+ verticalLabelWidth
;
652 for (i
= scrollPosX
; i
< totalCols
; i
++)
658 rect
.x
= 1 + widthCount
;
659 rect
.width
= colWidths
[i
];
660 DrawColumnLabel(dc
, &rect
, i
);
662 widthCount
+= colWidths
[i
];
667 void wxGenericGrid::DrawColumnLabel(wxDC
*dc
, wxRectangle
*rect
, int col
)
669 wxGridCell
*cell
= GetLabelCell(wxHORIZONTAL
, col
);
678 dc
->SetTextForeground(GetLabelTextColour());
679 dc
->SetFont(*GetLabelTextFont());
680 if ( !cell
->GetTextValue().IsNull() )
681 DrawTextRect(dc
, cell
->GetTextValue(), &rect2
, GetLabelAlignment(wxHORIZONTAL
));
685 void wxGenericGrid::DrawRowLabels(wxDC
*dc
)
688 GetClientSize(&cw
, &ch
);
690 if (verticalLabelWidth
== 0)
696 // Draw numbers for rows
697 rect
.x
= leftOfSheet
;
698 rect
.width
= verticalLabelWidth
;
700 int heightCount
= topOfSheet
+ horizontalLabelHeight
;
702 dc
->SetTextBackground(labelBackgroundColour
);
703 dc
->SetBackgroundMode(wxTRANSPARENT
);
705 for (i
= scrollPosY
; i
< totalRows
; i
++)
707 if (heightCount
> ch
)
711 rect
.y
= 1 + heightCount
;
712 rect
.height
= rowHeights
[i
];
713 DrawRowLabel(dc
, &rect
, i
);
715 heightCount
+= rowHeights
[i
];
720 void wxGenericGrid::DrawRowLabel(wxDC
*dc
, wxRectangle
*rect
, int row
)
722 wxGridCell
*cell
= GetLabelCell(wxVERTICAL
, row
);
731 dc
->SetTextForeground(GetLabelTextColour());
732 dc
->SetFont(*GetLabelTextFont());
733 if ( !cell
->GetTextValue().IsNull() )
734 DrawTextRect(dc
, cell
->GetTextValue(), &rect2
, GetLabelAlignment(wxVERTICAL
));
738 void wxGenericGrid::DrawCells(wxDC
*dc
)
741 GetClientSize(&cw
, &ch
);
745 // Draw value corresponding to each cell
746 for (i
= scrollPosY
; i
< totalRows
; i
++)
748 for (j
= scrollPosX
; j
< totalCols
; j
++)
750 SetCurrentRect(i
, j
, cw
, ch
);
751 if (currentRectVisible
)
753 DrawCellBackground(dc
, &CurrentRect
, i
, j
);
754 DrawCellValue(dc
, &CurrentRect
, i
, j
);
756 if (CurrentRect
.x
> cw
)
759 if (CurrentRect
.y
> ch
)
762 dc
->SetBackgroundMode(wxSOLID
);
763 dc
->SetPen(*wxBLACK_PEN
);
766 void wxGenericGrid::DrawCellBackground(wxDC
*dc
, wxRectangle
*rect
, int row
, int col
)
768 wxGridCell
*cell
= GetCell(row
, col
);
771 dc
->SetBrush(*cell
->GetBackgroundBrush());
772 dc
->SetPen(*wxTRANSPARENT_PEN
);
774 dc
->DrawRectangle(rect
->x
+1, rect
->y
+1, rect
->width
-1, rect
->height
-1);
776 dc
->DrawRectangle(rect
->x
+1, rect
->y
+1, rect
->width
, rect
->height
);
778 dc
->SetPen(*wxBLACK_PEN
);
782 void wxGenericGrid::DrawCellValue(wxDC
*dc
, wxRectangle
*rect
, int row
, int col
)
784 wxGridCell
*cell
= GetCell(row
, col
);
787 wxBitmap
*bitmap
= cell
->GetCellBitmap();
797 DrawBitmapRect(dc
, bitmap
, &rect2
, cell
->GetAlignment());
801 dc
->SetBackgroundMode(wxTRANSPARENT
);
802 dc
->SetTextForeground(cell
->GetTextColour());
803 dc
->SetFont(*cell
->GetFont());
805 if ( !cell
->GetTextValue().IsNull() )
806 DrawTextRect(dc
, cell
->GetTextValue(), &rect2
, cell
->GetAlignment());
811 void wxGenericGrid::AdjustScrollbars(void)
814 GetClientSize(&cw
, &ch
);
816 // To calculate the number of steps for each scrollbar,
817 // we need to see how much will fit onto the canvas
818 // at the present size. So:
819 // 1) Find the *last* row r1 such that when it's at the top of the
820 // window, all the remaining rows are visible.
821 // 2) There should therefore be r1 - 1 steps in the scrollbar.
822 // Similarly with columns.
824 // IGNORE THE ABOVE, it's crap.
825 // We find the view size by seeing how many rows/cols fit on
827 // BUT... this means that the scrollbar should be adjusted every time
828 // it's scrolled, as well as when sized, because with variable size rows/cols,
829 // the number of rows/col visible on the view differs according to what bit
830 // you're looking at. The object length is always the same, but the
831 // view length differs.
833 // Since this may not be known until the end of this function, we should probably call AdjustScrollbars
835 int vertScrollBarWidth
= scrollWidth
;
836 int horizScrollBarHeight
= scrollWidth
;
837 if (vScrollBar
&& !vScrollBar
->IsShown())
838 vertScrollBarWidth
= 0;
839 if (hScrollBar
&& !hScrollBar
->IsShown())
840 horizScrollBarHeight
= 0;
842 int noHorizSteps
= 0;
845 if (totalGridWidth
<= cw
)
852 if (GetLabelSize(wxVERTICAL) > 0)
858 for (i
= scrollPosX
; i
< totalCols
; i
++)
860 widthCount
+= colWidths
[i
];
861 // A partial bit doesn't count, we still have to scroll to see the
863 if (widthCount
+ leftOfSheet
+ verticalLabelWidth
> (cw
-vertScrollBarWidth
))
872 if (totalGridHeight
<= ch
)
879 if (GetLabelSize(wxHORIZONTAL) > 0)
885 for (i
= scrollPosY
; i
< totalRows
; i
++)
887 heightCount
+= rowHeights
[i
];
888 // A partial bit doesn't count, we still have to scroll to see the
890 if (heightCount
+ topOfSheet
+ horizontalLabelHeight
> (ch
-horizScrollBarHeight
))
899 if (totalGridWidth
<= cw
)
902 hScrollBar
->Show(FALSE
);
908 hScrollBar
->Show(TRUE
);
911 if (totalGridHeight
<= ch
)
914 vScrollBar
->Show(FALSE
);
920 vScrollBar
->Show(TRUE
);
923 UpdateDimensions(); // Necessary in case scrollPosX/Y changed
925 vertScrollBarWidth
= scrollWidth
;
926 horizScrollBarHeight
= scrollWidth
;
927 if (vScrollBar
&& !vScrollBar
->IsShown())
928 vertScrollBarWidth
= 0;
929 if (hScrollBar
&& !hScrollBar
->IsShown())
930 horizScrollBarHeight
= 0;
934 int nCols
= GetCols();
936 hScrollBar->SetPageSize(wxMax(noHorizSteps, 1));
937 hScrollBar->SetViewLength(wxMax(noHorizSteps, 1));
938 hScrollBar->SetObjectLength(nCols);
940 hScrollBar
->SetScrollbar(hScrollBar
->GetPosition(), wxMax(noHorizSteps
, 1), nCols
, wxMax(noHorizSteps
, 1));
942 hScrollBar
->SetSize(leftOfSheet
, ch
- scrollWidth
,
943 cw
- vertScrollBarWidth
- leftOfSheet
, scrollWidth
);
948 int nRows
= GetRows();
950 vScrollBar->SetPageSize(wxMax(noVertSteps, 1));
951 vScrollBar->SetViewLength(wxMax(noVertSteps, 1));
952 vScrollBar->SetObjectLength(nRows);
955 vScrollBar
->SetScrollbar(vScrollBar
->GetPosition(), wxMax(noVertSteps
, 1), nRows
, wxMax(noVertSteps
, 1));
956 vScrollBar
->SetSize(cw
- scrollWidth
, topOfSheet
,
957 scrollWidth
, ch
- topOfSheet
- horizScrollBarHeight
);
961 void wxGenericGrid::OnSize(wxSizeEvent
& WXUNUSED(event
) )
963 if (!vScrollBar
|| !hScrollBar
)
969 GetClientSize(&cw
, &ch
);
971 if (GetTextItem() && GetTextItem()->IsShown())
973 GetTextItem()->SetSize(editControlPosition
.x
, editControlPosition
.y
,
974 cw
- editControlPosition
.x
, editControlPosition
.height
);
978 bool wxGenericGrid::CellHitTest(int x
, int y
, int *row
, int *col
)
980 // Find the selected cell and call OnSelectCell
981 if (x
>= (leftOfSheet
+ verticalLabelWidth
) && y
>= (topOfSheet
+ horizontalLabelHeight
) &&
982 x
<= rightOfSheet
&& y
<= bottomOfSheet
)
984 // Calculate the cell number from x and y
985 x
-= (verticalLabelWidth
+ leftOfSheet
);
986 y
-= (topOfSheet
+ horizontalLabelHeight
);
990 // Now we need to do a hit test for which row we're on
991 int currentHeight
= 0;
992 for (i
= scrollPosY
; i
< totalRows
; i
++)
994 if (y
>= currentHeight
&& y
<= (currentHeight
+ rowHeights
[i
]))
999 currentHeight
+= rowHeights
[i
];
1002 // Now we need to do a hit test for which column we're on
1003 int currentWidth
= 0;
1004 for (i
= scrollPosX
; i
< totalCols
; i
++)
1006 if (x
>= currentWidth
&& x
<= (currentWidth
+ colWidths
[i
]))
1011 currentWidth
+= colWidths
[i
];
1018 bool wxGenericGrid::LabelSashHitTest(int x
, int y
, int *orientation
, int *rowOrCol
, int *startPos
)
1023 if (x
>= (leftOfSheet
+ verticalLabelWidth
) && y
>= topOfSheet
&&
1024 x
<= rightOfSheet
&& y
<= (topOfSheet
+ horizontalLabelHeight
))
1026 // We may be on a column label sash.
1027 int currentWidth
= leftOfSheet
+ verticalLabelWidth
;
1028 for (i
= scrollPosX
; i
< totalCols
; i
++)
1030 if (x
>= (currentWidth
+ colWidths
[i
] - tolerance
) && x
<= (currentWidth
+ colWidths
[i
] + tolerance
))
1032 *orientation
= wxHORIZONTAL
;
1034 *startPos
= currentWidth
;
1037 currentWidth
+= colWidths
[i
];
1041 else if (x
>= leftOfSheet
&& y
>= (topOfSheet
+ horizontalLabelHeight
) &&
1042 x
<= (leftOfSheet
+ verticalLabelWidth
) && y
<= bottomOfSheet
)
1044 // We may be on a row label sash.
1045 int currentHeight
= topOfSheet
+ horizontalLabelHeight
;
1046 for (i
= scrollPosY
; i
< totalRows
; i
++)
1048 if (y
>= (currentHeight
+ rowHeights
[i
] - tolerance
) && y
<= (currentHeight
+ rowHeights
[i
] + tolerance
))
1050 *orientation
= wxVERTICAL
;
1052 *startPos
= currentHeight
;
1055 currentHeight
+= rowHeights
[i
];
1062 bool wxGenericGrid::LabelHitTest(int x
, int y
, int *row
, int *col
)
1064 // Find the selected label
1065 if (x
>= leftOfSheet
&& y
>= topOfSheet
&&
1066 x
<= rightOfSheet
&& y
<= bottomOfSheet
)
1068 // Calculate the cell number from x and y
1074 // Now we need to do a hit test for which row we're on
1075 int currentHeight
= horizontalLabelHeight
;
1076 for (i
= scrollPosY
; i
< totalRows
; i
++)
1078 if (y
>= currentHeight
&& y
<= (currentHeight
+ rowHeights
[i
]))
1083 currentHeight
+= rowHeights
[i
];
1085 if (y
>= 0 && y
<= horizontalLabelHeight
)
1090 // Now we need to do a hit test for which column we're on
1091 int currentWidth
= verticalLabelWidth
;
1092 for (i
= scrollPosX
; i
< totalCols
; i
++)
1094 if (x
>= currentWidth
&& x
<= (currentWidth
+ colWidths
[i
]))
1099 currentWidth
+= colWidths
[i
];
1101 if (x
>= 0 && x
<= verticalLabelWidth
)
1106 if ((*col
== -1) || (*row
== -1))
1114 void wxGenericGrid::OnMouseEvent(wxMouseEvent
& ev
)
1118 wxClientDC
dc(this);
1122 if (CellHitTest((int)ev
.GetX(), (int)ev
.GetY(), &row
, &col
))
1124 OnSelectCellImplementation(& dc
, row
, col
);
1125 OnCellLeftClick(row
, col
, (int)ev
.GetX(), (int)ev
.GetY(), ev
.ControlDown(), ev
.ShiftDown());
1127 if (LabelHitTest((int)ev
.GetX(), (int)ev
.GetY(), &row
, &col
))
1129 OnLabelLeftClick(row
, col
, (int)ev
.GetX(), (int)ev
.GetY(), ev
.ControlDown(), ev
.ShiftDown());
1133 else if (ev
.Dragging() && ev
.LeftIsDown())
1137 case wxGRID_DRAG_NONE
:
1140 if (LabelSashHitTest((int)ev
.GetX(), (int)ev
.GetY(), &orientation
, &dragRowOrCol
, &dragStartPosition
))
1142 if (orientation
== wxHORIZONTAL
)
1144 dragStatus
= wxGRID_DRAG_LEFT_RIGHT
;
1145 SetCursor(*horizontalSashCursor
);
1146 dragLastPosition
= (int)ev
.GetX();
1150 dragStatus
= wxGRID_DRAG_UP_DOWN
;
1151 SetCursor(*verticalSashCursor
);
1152 dragLastPosition
= (int)ev
.GetY();
1154 wxClientDC
dc(this);
1156 dc
.SetLogicalFunction(wxINVERT
);
1157 if (orientation
== wxHORIZONTAL
)
1158 dc
.DrawLine((int)ev
.GetX(), topOfSheet
, (int)ev
.GetX(), bottomOfSheet
);
1160 dc
.DrawLine(leftOfSheet
, (int)ev
.GetY(), rightOfSheet
, (int)ev
.GetY());
1167 case wxGRID_DRAG_LEFT_RIGHT
:
1169 wxClientDC
dc(this);
1171 dc
.SetLogicalFunction(wxINVERT
);
1172 dc
.DrawLine(dragLastPosition
, topOfSheet
, dragLastPosition
, bottomOfSheet
);
1174 dc
.DrawLine((int)ev
.GetX(), topOfSheet
, (int)ev
.GetX(), bottomOfSheet
);
1177 dragLastPosition
= (int)ev
.GetX();
1178 SetCursor(*horizontalSashCursor
);
1181 case wxGRID_DRAG_UP_DOWN
:
1183 wxClientDC
dc(this);
1185 dc
.SetLogicalFunction(wxINVERT
);
1186 dc
.DrawLine(leftOfSheet
, dragLastPosition
, rightOfSheet
, dragLastPosition
);
1188 dc
.DrawLine(leftOfSheet
, (int)ev
.GetY(), rightOfSheet
, (int)ev
.GetY());
1191 dragLastPosition
= (int)ev
.GetY();
1192 SetCursor(*verticalSashCursor
);
1197 else if (ev
.Moving())
1199 int rowOrCol
, orientation
, startPos
;
1200 if (LabelSashHitTest((int)ev
.GetX(), (int)ev
.GetY(), &orientation
, &rowOrCol
, &startPos
))
1202 if (orientation
== wxHORIZONTAL
)
1203 SetCursor(*horizontalSashCursor
);
1205 SetCursor(*verticalSashCursor
);
1208 SetCursor(*wxSTANDARD_CURSOR
);
1210 else if (ev
.LeftUp())
1214 case wxGRID_DRAG_LEFT_RIGHT
:
1216 wxClientDC
dc(this);
1218 dc
.SetLogicalFunction(wxINVERT
);
1219 dc
.DrawLine(dragLastPosition
, topOfSheet
, dragLastPosition
, bottomOfSheet
);
1220 dc
.SetLogicalFunction(wxCOPY
);
1224 if (ev
.GetX() > dragStartPosition
)
1226 colWidths
[dragRowOrCol
] = (short)(ev
.GetX() - dragStartPosition
);
1231 SetCursor(*wxSTANDARD_CURSOR
);
1233 GetClientSize(&cw
, &ch
);
1238 case wxGRID_DRAG_UP_DOWN
:
1240 wxClientDC
dc(this);
1242 dc
.SetLogicalFunction(wxINVERT
);
1243 dc
.DrawLine(leftOfSheet
, dragLastPosition
, rightOfSheet
, dragLastPosition
);
1244 dc
.SetLogicalFunction(wxCOPY
);
1248 if (ev
.GetY() > dragStartPosition
)
1250 rowHeights
[dragRowOrCol
] = (short)(ev
.GetY() - dragStartPosition
);
1255 SetCursor(*wxSTANDARD_CURSOR
);
1259 dragStatus
= wxGRID_DRAG_NONE
;
1261 else if (ev
.RightDown())
1264 if (CellHitTest((int)ev
.GetX(), (int)ev
.GetY(), &row
, &col
))
1266 OnCellRightClick(row
, col
, (int)ev
.GetX(), (int)ev
.GetY(), ev
.ControlDown(), ev
.ShiftDown());
1268 if (LabelHitTest((int)ev
.GetX(), (int)ev
.GetY(), &row
, &col
))
1270 OnLabelRightClick(row
, col
, (int)ev
.GetX(), (int)ev
.GetY(), ev
.ControlDown(), ev
.ShiftDown());
1275 void wxGenericGrid::OnSelectCellImplementation(wxDC
*dc
, int row
, int col
)
1277 wCursorColumn
= col
;
1280 OnChangeSelectionLabel();
1282 SetGridClippingRegion(dc
);
1284 // Remove the highlight from the old cell
1285 if (currentRectVisible
)
1288 // Highlight the new cell and copy its content to the edit control
1289 SetCurrentRect(wCursorRow
, wCursorColumn
);
1290 wxGridCell
*cell
= GetCell(wCursorRow
, wCursorColumn
);
1293 if ( cell
->GetTextValue().IsNull() )
1294 textItem
->SetValue("");
1296 textItem
->SetValue(cell
->GetTextValue());
1299 SetGridClippingRegion(dc
);
1301 // Why isn't this needed for Windows??
1302 // Probably because of the SetValue??
1306 dc
->DestroyClippingRegion();
1308 OnSelectCell(row
, col
);
1311 wxGridCell
*wxGenericGrid::OnCreateCell(void)
1313 return new wxGridCell(this);
1316 void wxGenericGrid::OnChangeLabels(void)
1320 for (i
= 0; i
< totalRows
; i
++)
1322 sprintf(buf
, "%d", i
+1);
1323 SetLabelValue(wxVERTICAL
, buf
, i
);
1325 // A...Z,AA...ZZ,AAA...ZZZ, etc.
1326 for (i
= 0; i
< totalCols
; i
++)
1329 int noTimes
= (i
/26 + 1);
1330 int ch
= (i
% 26) + 65;
1332 for (j
= 0; j
< noTimes
; j
++)
1335 sprintf(buf2
, "%c", (char)ch
);
1338 SetLabelValue(wxHORIZONTAL
, buf
, i
);
1342 void wxGenericGrid::OnChangeSelectionLabel(void)
1347 wxString
rowLabel(GetLabelValue(wxVERTICAL
, GetCursorRow()));
1348 wxString
colLabel(GetLabelValue(wxHORIZONTAL
, GetCursorColumn()));
1350 wxString newLabel
= colLabel
+ rowLabel
;
1351 if ((newLabel
.Length() > 0) && (newLabel
.Length() <= 8) && GetTextItem())
1353 // GetTextItem()->SetLabel(newLabel);
1357 void wxGenericGrid::HighlightCell(wxDC
*dc
)
1359 dc
->SetLogicalFunction(wxINVERT
);
1361 dc
->DrawLine(CurrentRect
.x
+ 1, CurrentRect
.y
+ 1, CurrentRect
.x
+ CurrentRect
.width
- 1, CurrentRect
.y
+ 1);
1363 dc
->DrawLine(CurrentRect
.x
+ CurrentRect
.width
- 1, CurrentRect
.y
+ 1,
1364 CurrentRect
.x
+ CurrentRect
.width
- 1, CurrentRect
.y
+CurrentRect
.height
- 1);
1366 dc
->DrawLine(CurrentRect
.x
+ CurrentRect
.width
- 1, CurrentRect
.y
+ CurrentRect
.height
- 1,
1367 CurrentRect
.x
+ 1, CurrentRect
.y
+ CurrentRect
.height
- 1);
1369 dc
->DrawLine(CurrentRect
.x
+ 1, CurrentRect
.y
+ CurrentRect
.height
- 1, CurrentRect
.x
+ 1, CurrentRect
.y
+ 1);
1371 dc
->SetLogicalFunction(wxCOPY
);
1374 void wxGenericGrid::DrawCellText(void)
1376 if (!currentRectVisible
)
1379 wxGridCell
*cell
= GetCell(GetCursorRow(), GetCursorColumn());
1383 static char szEdit
[300];
1385 wxClientDC
dc(this);
1388 SetGridClippingRegion(& dc
);
1390 dc
.SetBackgroundMode(wxTRANSPARENT
);
1391 dc
.SetBrush(*cell
->GetBackgroundBrush());
1393 strcpy(szEdit
, textItem
->GetValue());
1402 DrawTextRect(& dc
, " ", &rect
, wxLEFT
);
1403 DrawTextRect(& dc
, szEdit
, &rect
, cell
->GetAlignment());
1405 dc
.DestroyClippingRegion();
1407 dc
.SetBackgroundMode(wxSOLID
);
1412 void wxGenericGrid::SetCurrentRect(int Row
, int Column
, int canvasW
, int canvasH
)
1414 int currentWidth
= leftOfSheet
+ verticalLabelWidth
;
1416 for (i
= scrollPosX
; i
< Column
; i
++)
1417 currentWidth
+= colWidths
[i
];
1419 int currentHeight
= topOfSheet
+ horizontalLabelHeight
;
1420 for (i
= scrollPosY
; i
< Row
; i
++)
1421 currentHeight
+= rowHeights
[i
];
1423 CurrentRect
.x
= currentWidth
;
1424 CurrentRect
.y
= currentHeight
;
1425 CurrentRect
.width
= colWidths
? (colWidths
[Column
]) : 0;
1426 CurrentRect
.height
= rowHeights
? (rowHeights
[Row
]) : 0;
1428 if (Row
< scrollPosY
|| Column
< scrollPosX
)
1429 currentRectVisible
= FALSE
;
1430 else if ((canvasW
!= -1 && canvasH
!= -1) && (CurrentRect
.x
> canvasW
|| CurrentRect
.y
> canvasH
))
1431 currentRectVisible
= FALSE
;
1432 else currentRectVisible
= TRUE
;
1435 static bool wxRectIntersection(wxRectangle
*rect1
, wxRectangle
*rect2
, wxRectangle
*rect3
)
1437 int x2_1
= rect1
->x
+ rect1
->width
;
1438 int y2_1
= rect1
->y
+ rect1
->height
;
1440 int x2_2
= rect2
->x
+ rect2
->width
;
1441 int y2_2
= rect2
->y
+ rect2
->height
;
1445 // Check for intersection
1446 if ((rect1
->x
> x2_2
) || (rect2
->x
> x2_1
) ||
1447 (rect1
->y
> y2_2
) || (rect2
->y
> y2_1
))
1450 rect3
->x
= rect3
->y
= rect3
->width
= rect3
->height
= 0;
1454 if (rect1
->x
> rect2
->x
)
1455 rect3
->x
= rect1
->x
;
1457 rect3
->x
= rect2
->x
;
1458 if (rect1
->y
> rect2
->y
)
1459 rect3
->y
= rect1
->y
;
1461 rect3
->y
= rect2
->y
;
1472 rect3
->width
= (int)(x2_3
- rect3
->x
);
1473 rect3
->height
= (int)(y2_3
- rect3
->y
);
1477 void wxGenericGrid::DrawTextRect(wxDC
*dc
, const wxString
& text
, wxRectangle
*rect
, int flag
)
1481 // Ultimately, this functionality should be built into wxWindows,
1482 // and optimized for each platform. E.g. on Windows, use DrawText
1483 // passing a clipping rectangle, so that the wxWindows clipping region
1484 // does not have to be used to implement this.
1486 // If we're already clipping, we need to find the intersection
1487 // between current clipping area and text clipping area.
1489 wxRectangle clipRect
;
1490 wxRectangle clipRect2
;
1491 long clipX
, clipY
, clipW
, clipH
;
1492 dc
->GetClippingBox(&clipX
, &clipY
, &clipW
, &clipH
);
1493 clipRect
.x
= (int)clipX
; clipRect
.y
= (int)clipY
;
1494 clipRect
.width
= (int)clipW
; clipRect
.height
= (int)clipH
;
1496 bool alreadyClipping
= TRUE
;
1498 if (clipRect
.x
== 0 && clipRect
.y
== 0 && clipRect
.width
== 0 && clipRect
.height
== 0)
1500 alreadyClipping
= FALSE
;
1501 clipRect2
.x
= rect
->x
; clipRect2
.y
= rect
->y
;
1502 clipRect2
.width
= rect
->width
; clipRect2
.height
= rect
->height
;
1506 // Find intersection.
1507 if (!wxRectIntersection(rect
, &clipRect
, &clipRect2
))
1511 if (alreadyClipping
)
1512 dc
->DestroyClippingRegion();
1514 dc
->SetClippingRegion(clipRect2
.x
, clipRect2
.y
, clipRect2
.width
, clipRect2
.height
);
1515 long textWidth
, textHeight
;
1517 dc
->GetTextExtent(text
, &textWidth
, &textHeight
);
1525 x
= (rect
->x
+ rect
->width
- textWidth
- 1.0);
1526 y
= (rect
->y
+ (rect
->height
- textHeight
)/2.0);
1531 x
= (rect
->x
+ (rect
->width
- textWidth
)/2.0);
1532 y
= (rect
->y
+ (rect
->height
- textHeight
)/2.0);
1538 x
= (rect
->x
+ 1.0);
1539 y
= (rect
->y
+ (rect
->height
- textHeight
)/2.0);
1543 dc
->DrawText(text
, (long)x
, (long)y
);
1545 dc
->DestroyClippingRegion();
1547 // Restore old clipping
1548 if (alreadyClipping
)
1549 dc
->SetClippingRegion(clipRect
.x
, clipRect
.y
, clipRect
.width
, clipRect
.height
);
1554 void wxGenericGrid::DrawBitmapRect(wxDC
*dc
, wxBitmap
*bitmap
, wxRectangle
*rect
, int flag
)
1558 // Ultimately, this functionality should be built into wxWindows,
1559 // and optimized for each platform. E.g. on Windows, use DrawText
1560 // passing a clipping rectangle, so that the wxWindows clipping region
1561 // does not have to be used to implement this.
1563 // If we're already clipping, we need to find the intersection
1564 // between current clipping area and text clipping area.
1566 wxRectangle clipRect
;
1567 wxRectangle clipRect2
;
1568 long clipX
, clipY
, clipW
, clipH
;
1569 dc
->GetClippingBox(&clipX
, &clipY
, &clipW
, &clipH
);
1570 clipRect
.x
= (int)clipX
; clipRect
.y
= (int)clipY
;
1571 clipRect
.width
= (int)clipW
; clipRect
.height
= (int)clipH
;
1573 bool alreadyClipping
= TRUE
;
1575 if (clipRect
.x
== 0 && clipRect
.y
== 0 && clipRect
.width
== 0 && clipRect
.height
== 0)
1577 alreadyClipping
= FALSE
;
1578 clipRect2
.x
= rect
->x
; clipRect2
.y
= rect
->y
;
1579 clipRect2
.width
= rect
->width
; clipRect2
.height
= rect
->height
;
1583 // Find intersection.
1584 if (!wxRectIntersection(rect
, &clipRect
, &clipRect2
))
1588 if (alreadyClipping
)
1589 dc
->DestroyClippingRegion();
1591 dc
->SetClippingRegion(clipRect2
.x
, clipRect2
.y
, clipRect2
.width
, clipRect2
.height
);
1592 float bitmapWidth
, bitmapHeight
;
1594 bitmapWidth
= bitmap
->GetWidth();
1595 bitmapHeight
= bitmap
->GetHeight();
1603 x
= (long)(rect
->x
+ rect
->width
- bitmapWidth
- 1);
1604 y
= (long)(rect
->y
+ (rect
->height
- bitmapHeight
)/2.0);
1609 x
= (long)(rect
->x
+ (rect
->width
- bitmapWidth
)/2.0);
1610 y
= (long)(rect
->y
+ (rect
->height
- bitmapHeight
)/2.0);
1616 x
= (long)(rect
->x
+ 1);
1617 y
= (long)(rect
->y
+ (rect
->height
- bitmapHeight
)/2.0);
1622 dcTemp
.SelectObject(*bitmap
);
1624 dc
->Blit( (long)x
, (long)y
, (long)bitmapWidth
, (long)bitmapHeight
, &dcTemp
, 0, 0);
1625 dcTemp
.SelectObject(wxNullBitmap
);
1627 dc
->DestroyClippingRegion();
1629 // Restore old clipping
1630 if (alreadyClipping
)
1631 dc
->SetClippingRegion(clipRect
.x
, clipRect
.y
, clipRect
.width
, clipRect
.height
);
1636 void wxGenericGrid::OnActivate(bool active
)
1640 // Edit control should always have the focus
1641 if (GetTextItem() && GetEditable())
1643 GetTextItem()->SetFocus();
1644 wxGridCell
*cell
= GetCell(GetCursorRow(), GetCursorColumn());
1646 GetTextItem()->SetValue(cell
->GetTextValue());
1651 void wxGenericGrid::SetCellValue(const wxString
& val
, int row
, int col
)
1653 wxGridCell
*cell
= GetCell(row
, col
);
1656 cell
->SetTextValue(val
);
1658 RefreshCell(row
, col
, TRUE
);
1662 void wxGenericGrid::RefreshCell(int row
, int col
, bool setText
)
1664 // Don't refresh within a pair of batch brackets
1665 if (GetBatchCount() > 0)
1669 GetClientSize(&cw
, &ch
);
1671 SetCurrentRect(row
, col
, cw
, ch
);
1672 if (currentRectVisible
)
1674 wxGridCell
*cell
= GetCell(row
, col
);
1676 bool currentPos
= FALSE
;
1677 if (row
== wCursorRow
&& col
== wCursorColumn
&& GetTextItem() && GetTextItem()->IsShown() && setText
)
1679 GetTextItem()->SetValue(cell
->GetTextValue());
1682 // Gets refreshed anyway in MSW
1687 wxClientDC
dc(this);
1689 DrawCellBackground(& dc
, &CurrentRect
, row
, col
);
1690 DrawCellValue(& dc
, &CurrentRect
, row
, col
);
1696 wxString
& wxGenericGrid::GetCellValue(int row
, int col
)
1698 static wxString
emptyString("");
1700 wxGridCell
*cell
= GetCell(row
, col
);
1702 return cell
->GetTextValue();
1707 void wxGenericGrid::SetColumnWidth(int col
, int width
)
1709 if (col
<= totalCols
)
1710 colWidths
[col
] = width
;
1713 int wxGenericGrid::GetColumnWidth(int col
)
1715 if (col
<= totalCols
)
1716 return colWidths
[col
];
1721 void wxGenericGrid::SetRowHeight(int row
, int height
)
1723 if (row
<= totalRows
)
1724 rowHeights
[row
] = height
;
1727 int wxGenericGrid::GetRowHeight(int row
)
1729 if (row
<= totalRows
)
1730 return rowHeights
[row
];
1735 void wxGenericGrid::SetLabelSize(int orientation
, int sz
)
1737 if (orientation
== wxHORIZONTAL
)
1738 horizontalLabelHeight
= sz
;
1740 verticalLabelWidth
= sz
;
1742 SetCurrentRect(GetCursorRow(), GetCursorColumn());
1745 int wxGenericGrid::GetLabelSize(int orientation
)
1747 if (orientation
== wxHORIZONTAL
)
1748 return horizontalLabelHeight
;
1750 return verticalLabelWidth
;
1753 wxGridCell
*wxGenericGrid::GetLabelCell(int orientation
, int pos
)
1755 if (orientation
== wxHORIZONTAL
)
1757 if (colLabelCells
&& pos
< totalCols
)
1758 return colLabelCells
[pos
];
1764 if (rowLabelCells
&& pos
< totalRows
)
1765 return rowLabelCells
[pos
];
1771 void wxGenericGrid::SetLabelValue(int orientation
, const wxString
& val
, int pos
)
1773 wxGridCell
*cell
= GetLabelCell(orientation
, pos
);
1775 cell
->SetTextValue(val
);
1778 wxString
& wxGenericGrid::GetLabelValue(int orientation
, int pos
)
1780 static wxString emptyString
= "";
1781 wxGridCell
*cell
= GetLabelCell(orientation
, pos
);
1783 return cell
->GetTextValue();
1788 void wxGenericGrid::SetLabelAlignment(int orientation
, int align
)
1790 if (orientation
== wxHORIZONTAL
)
1791 horizontalLabelAlignment
= align
;
1793 verticalLabelAlignment
= align
;
1795 SetCurrentRect(GetCursorRow(), GetCursorColumn());
1798 int wxGenericGrid::GetLabelAlignment(int orientation
)
1800 if (orientation
== wxHORIZONTAL
)
1801 return horizontalLabelAlignment
;
1803 return verticalLabelAlignment
;
1806 void wxGenericGrid::SetLabelTextColour(const wxColour
& colour
)
1808 labelTextColour
= colour
;
1812 void wxGenericGrid::SetLabelBackgroundColour(const wxColour
& colour
)
1814 labelBackgroundColour
= colour
;
1815 labelBackgroundBrush
= wxTheBrushList
->FindOrCreateBrush(labelBackgroundColour
, wxSOLID
);
1818 void wxGenericGrid::SetEditable(bool edit
)
1823 int controlW
, controlH
;
1824 textItem
->GetSize(&controlW
, &controlH
);
1825 editControlPosition
.height
= controlH
;
1827 topOfSheet
= editControlPosition
.x
+ controlH
+ 2;
1830 textItem
->Show(TRUE
);
1832 #if defined(__WINDOWS__) && (wxMINOR_VERSION == 6 && wxRELEASE_NUMBER < 6)
1833 ::ShowWindow(textItem
->GetLabelHWND(), TRUE
);
1835 textItem
->SetFocus();
1843 textItem
->Show(FALSE
);
1845 #if defined(__WINDOWS__) && (wxMINOR_VERSION == 6 && wxRELEASE_NUMBER < 6)
1846 ::ShowWindow(textItem
->GetLabelHWND(), FALSE
);
1851 SetCurrentRect(GetCursorRow(), GetCursorColumn());
1854 GetClientSize(&cw
, &ch
);
1859 int scrollWidth = 16;
1860 GetClientSize(&cw, &ch);
1863 vScrollBar->SetSize(cw - scrollWidth, topOfSheet,
1864 scrollWidth, ch - topOfSheet - scrollWidth);
1868 void wxGenericGrid::SetCellAlignment(int flag
, int row
, int col
)
1870 wxGridCell
*cell
= GetCell(row
, col
);
1872 cell
->SetAlignment(flag
);
1875 int wxGenericGrid::GetCellAlignment(int row
, int col
)
1877 wxGridCell
*cell
= GetCell(row
, col
);
1879 return cell
->GetAlignment();
1881 return cellAlignment
;
1884 void wxGenericGrid::SetCellAlignment(int flag
)
1886 cellAlignment
= flag
;
1888 for (i
= 0; i
< GetRows(); i
++)
1889 for (j
= 0; j
< GetCols(); j
++)
1891 GetCell(i
, j
)->SetAlignment(flag
);
1894 int wxGenericGrid::GetCellAlignment(void)
1896 return cellAlignment
;
1899 void wxGenericGrid::SetCellBackgroundColour(const wxColour
& col
)
1901 cellBackgroundColour
= col
;
1903 for (i
= 0; i
< GetRows(); i
++)
1904 for (j
= 0; j
< GetCols(); j
++)
1906 GetCell(i
, j
)->SetBackgroundColour(col
);
1909 void wxGenericGrid::SetCellBackgroundColour(const wxColour
& val
, int row
, int col
)
1911 wxGridCell
*cell
= GetCell(row
, col
);
1914 cell
->SetBackgroundColour(val
);
1915 RefreshCell(row
, col
);
1919 wxColour
& wxGenericGrid::GetCellBackgroundColour(int row
, int col
)
1921 wxGridCell
*cell
= GetCell(row
, col
);
1923 return cell
->GetBackgroundColour();
1925 return cellBackgroundColour
;
1928 void wxGenericGrid::SetCellTextColour(const wxColour
& val
, int row
, int col
)
1930 wxGridCell
*cell
= GetCell(row
, col
);
1933 cell
->SetTextColour(val
);
1934 RefreshCell(row
, col
);
1938 void wxGenericGrid::SetCellTextFont(wxFont
*fnt
, int row
, int col
)
1940 wxGridCell
*cell
= GetCell(row
, col
);
1944 RefreshCell(row
, col
);
1948 wxFont
*wxGenericGrid::GetCellTextFont(int row
, int col
)
1950 wxGridCell
*cell
= GetCell(row
, col
);
1952 return cell
->GetFont();
1954 return cellTextFont
;
1957 wxColour
& wxGenericGrid::GetCellTextColour(int row
, int col
)
1959 wxGridCell
*cell
= GetCell(row
, col
);
1961 return cell
->GetTextColour();
1963 return cellTextColour
;
1966 void wxGenericGrid::SetCellTextColour(const wxColour
& val
)
1968 cellTextColour
= val
;
1970 for (i
= 0; i
< GetRows(); i
++)
1971 for (j
= 0; j
< GetCols(); j
++)
1973 GetCell(i
, j
)->SetTextColour(val
);
1976 void wxGenericGrid::SetCellTextFont(wxFont
*fnt
)
1980 for (i
= 0; i
< GetRows(); i
++)
1981 for (j
= 0; j
< GetCols(); j
++)
1983 GetCell(i
, j
)->SetFont(fnt
);
1986 void wxGenericGrid::SetCellBitmap(wxBitmap
*bitmap
, int row
, int col
)
1988 wxGridCell
*cell
= GetCell(row
, col
);
1991 cell
->SetCellBitmap(bitmap
);
1992 RefreshCell(row
, col
);
1996 wxBitmap
*wxGenericGrid::GetCellBitmap(int row
, int col
)
1998 wxGridCell
*cell
= GetCell(row
, col
);
2001 return cell
->GetCellBitmap();
2007 bool wxGenericGrid::InsertCols(int pos
, int n
, bool updateLabels
)
2009 if (pos
> totalCols
)
2013 return CreateGrid(1, n
);
2018 for (i
= 0; i
< totalRows
; i
++)
2020 wxGridCell
**cols
= gridCells
[i
];
2021 wxGridCell
**newCols
= new wxGridCell
*[totalCols
+ n
];
2022 for (j
= 0; j
< pos
; j
++)
2023 newCols
[j
] = cols
[j
];
2024 for (j
= pos
; j
< pos
+ n
; j
++)
2025 newCols
[j
] = new wxGridCell(this);
2026 for (j
= pos
+ n
; j
< totalCols
+ n
; j
++)
2027 newCols
[j
] = cols
[j
- n
];
2030 gridCells
[i
] = newCols
;
2034 short *newColWidths
= new short[totalCols
+ n
];
2035 for (j
= 0; j
< pos
; j
++)
2036 newColWidths
[j
] = colWidths
[j
];
2037 for (j
= pos
; j
< pos
+ n
; j
++)
2038 newColWidths
[j
] = wxGRID_DEFAULT_CELL_WIDTH
;
2039 for (j
= pos
+ n
; j
< totalCols
+ n
; j
++)
2040 newColWidths
[j
] = colWidths
[j
- n
];
2042 colWidths
= newColWidths
;
2045 wxGridCell
**newLabels
= new wxGridCell
*[totalCols
+ n
];
2046 for (j
= 0; j
< pos
; j
++)
2047 newLabels
[j
] = colLabelCells
[j
];
2048 for (j
= pos
; j
< pos
+ n
; j
++)
2049 newLabels
[j
] = new wxGridCell(this);
2050 for (j
= pos
+ n
; j
< totalCols
+ n
; j
++)
2051 newLabels
[j
] = colLabelCells
[j
- n
];
2053 delete[] colLabelCells
;
2054 colLabelCells
= newLabels
;
2066 bool wxGenericGrid::InsertRows(int pos
, int n
, bool updateLabels
)
2068 if (pos
> totalRows
)
2072 return CreateGrid(n
, 1);
2077 wxGridCell
***rows
= new wxGridCell
**[totalRows
+ n
];
2080 for (i
= 0; i
< pos
; i
++)
2081 rows
[i
] = gridCells
[i
];
2083 for (i
= pos
; i
< pos
+ n
; i
++)
2085 rows
[i
] = new wxGridCell
*[totalCols
];
2086 for (j
= 0; j
< totalCols
; j
++)
2087 rows
[i
][j
] = new wxGridCell(this);
2090 for (i
= pos
+ n
; i
< totalRows
+ n
; i
++)
2091 rows
[i
] = gridCells
[i
- n
];
2097 short *newRowHeights
= new short[totalRows
+ n
];
2098 for (i
= 0; i
< pos
; i
++)
2099 newRowHeights
[i
] = rowHeights
[i
];
2100 for (i
= pos
; i
< pos
+ n
; i
++)
2101 newRowHeights
[i
] = wxGRID_DEFAULT_CELL_HEIGHT
;
2102 for (i
= pos
+ n
; i
< totalRows
+ n
; i
++)
2103 newRowHeights
[i
] = rowHeights
[i
- n
];
2104 delete[] rowHeights
;
2105 rowHeights
= newRowHeights
;
2108 wxGridCell
**newLabels
= new wxGridCell
*[totalRows
+ n
];
2109 for (i
= 0; i
< pos
; i
++)
2110 newLabels
[i
] = rowLabelCells
[i
];
2111 for (i
= pos
; i
< pos
+ n
; i
++)
2112 newLabels
[i
] = new wxGridCell(this);
2113 for (i
= pos
+ n
; i
< totalRows
+ n
; i
++)
2114 newLabels
[i
] = rowLabelCells
[i
- n
];
2116 delete[] rowLabelCells
;
2117 rowLabelCells
= newLabels
;
2129 bool wxGenericGrid::AppendCols(int n
, bool updateLabels
)
2131 return InsertCols(GetCols(), n
, updateLabels
);
2134 bool wxGenericGrid::AppendRows(int n
, bool updateLabels
)
2136 return InsertRows(GetRows(), n
, updateLabels
);
2139 bool wxGenericGrid::DeleteRows(int pos
, int n
, bool updateLabels
)
2141 if (pos
> totalRows
)
2148 wxGridCell
***rows
= new wxGridCell
**[totalRows
- n
];
2151 for (i
= 0; i
< pos
; i
++)
2152 rows
[i
] = gridCells
[i
];
2154 for (i
= pos
+ n
; i
< totalRows
; i
++)
2155 rows
[i
-n
] = gridCells
[i
];
2161 short *newRowHeights
= new short[totalRows
- n
];
2162 for (i
= 0; i
< pos
; i
++)
2163 newRowHeights
[i
] = rowHeights
[i
];
2164 for (i
= pos
+ n
; i
< totalRows
; i
++)
2165 newRowHeights
[i
-n
] = rowHeights
[i
];
2166 delete[] rowHeights
;
2167 rowHeights
= newRowHeights
;
2170 wxGridCell
**newLabels
= new wxGridCell
*[totalRows
- n
];
2171 for (i
= 0; i
< pos
; i
++)
2172 newLabels
[i
] = rowLabelCells
[i
];
2173 for (i
= pos
+ n
; i
< totalRows
; i
++)
2174 newLabels
[i
-n
] = rowLabelCells
[i
];
2176 delete[] rowLabelCells
;
2177 rowLabelCells
= newLabels
;
2188 bool wxGenericGrid::DeleteCols(int pos
, int n
, bool updateLabels
)
2190 if (pos
+ n
> totalCols
)
2198 for (i
= 0; i
< totalRows
; i
++)
2200 wxGridCell
**cols
= gridCells
[i
];
2201 wxGridCell
**newCols
= new wxGridCell
*[totalCols
- n
];
2202 for (j
= 0; j
< pos
; j
++)
2203 newCols
[j
] = cols
[j
];
2204 for (j
= pos
; j
< pos
+ n
; j
++)
2206 for (j
= pos
+ n
; j
< totalCols
; j
++)
2207 newCols
[j
-n
] = cols
[j
];
2210 gridCells
[i
] = newCols
;
2214 short *newColWidths
= new short[totalCols
- n
];
2215 for (j
= 0; j
< pos
; j
++)
2216 newColWidths
[j
] = colWidths
[j
];
2217 for (j
= pos
+ n
; j
< totalCols
; j
++)
2218 newColWidths
[j
-n
] = colWidths
[j
];
2220 colWidths
= newColWidths
;
2223 wxGridCell
**newLabels
= new wxGridCell
*[totalCols
- n
];
2224 for (j
= 0; j
< pos
; j
++)
2225 newLabels
[j
] = colLabelCells
[j
];
2226 for (j
= pos
+ n
; j
< totalCols
; j
++)
2227 newLabels
[j
-n
] = colLabelCells
[j
];
2229 delete[] colLabelCells
;
2230 colLabelCells
= newLabels
;
2241 void wxGenericGrid::SetGridCursor(int row
, int col
)
2243 if (row
>= totalRows
|| col
>= totalCols
)
2246 if (row
== GetCursorRow() && col
== GetCursorColumn())
2249 wxClientDC
dc(this);
2252 SetGridClippingRegion(& dc
);
2254 if (currentRectVisible
)
2255 HighlightCell(& dc
);
2258 wCursorColumn
= col
;
2259 SetCurrentRect(row
, col
);
2260 if (currentRectVisible
)
2261 HighlightCell(& dc
);
2263 dc
.DestroyClippingRegion();
2271 wxGridCell::wxGridCell(wxGenericGrid
*window
)
2275 backgroundBrush
= NULL
;
2277 textColour
= window
->GetCellTextColour();
2279 textColour
.Set(0,0,0);
2281 backgroundColour
= window
->GetCellBackgroundColour();
2283 backgroundColour
.Set(255,255,255);
2286 font
= window
->GetCellTextFont();
2288 font
= wxTheFontList
->FindOrCreateFont(12, wxSWISS
, wxNORMAL
, wxNORMAL
);
2290 SetBackgroundColour(backgroundColour
);
2293 alignment
= window
->GetCellAlignment();
2298 wxGridCell::~wxGridCell(void)
2302 void wxGridCell::SetBackgroundColour(const wxColour
& colour
)
2304 backgroundColour
= colour
;
2305 backgroundBrush
= wxTheBrushList
->FindOrCreateBrush(backgroundColour
, wxSOLID
);
2308 void wxGenericGrid::OnText(wxCommandEvent
& WXUNUSED(ev
) )
2310 wxGenericGrid
*grid
= this;
2311 wxGridCell
*cell
= grid
->GetCell(grid
->GetCursorRow(), grid
->GetCursorColumn());
2312 if (cell
&& grid
->CurrentCellVisible())
2314 cell
->SetTextValue(grid
->GetTextItem()->GetValue());
2315 wxClientDC
dc(grid
);
2318 grid
->SetGridClippingRegion(& dc
);
2319 grid
->DrawCellBackground(& dc
, &grid
->GetCurrentRect(), grid
->GetCursorRow(), grid
->GetCursorColumn());
2320 grid
->DrawCellValue(& dc
, &grid
->GetCurrentRect(), grid
->GetCursorRow(), grid
->GetCursorColumn());
2321 grid
->HighlightCell(& dc
);
2322 dc
.DestroyClippingRegion();
2325 grid
->OnCellChange(grid
->GetCursorRow(), grid
->GetCursorColumn());
2327 // grid->DrawCellText();
2331 void wxGenericGrid::OnGridScroll(wxScrollEvent
& ev
)
2333 static bool inScroll
= FALSE
;
2339 wxGenericGrid
*win
= this;
2341 bool change
= FALSE
;
2343 if (ev
.GetEventObject() == win
->GetHorizScrollBar())
2345 change
= (ev
.GetPosition() != scrollPosX
);
2346 win
->SetScrollPosX(ev
.GetPosition());
2350 change
= (ev
.GetPosition() != scrollPosY
);
2351 win
->SetScrollPosY(ev
.GetPosition());
2354 win
->UpdateDimensions();
2355 win
->SetCurrentRect(win
->GetCursorRow(), win
->GetCursorColumn());
2357 // Because rows and columns can be arbitrary sizes,
2358 // the scrollbars will need to be adjusted to reflect the
2362 if (change
) win
->Refresh(FALSE
);