///////////////////////////////////////////////////////////////////////////// // Name: gridg.cpp // Purpose: wxGenericGrid // Author: Julian Smart // Modified by: // Created: 04/01/98 // RCS-ID: $Id$ // Copyright: (c) Julian Smart and Markus Holzem // Licence: wxWindows license ///////////////////////////////////////////////////////////////////////////// #ifdef __GNUG__ #pragma implementation "gridg.h" #pragma interface #endif // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include #include "wx/string.h" #include "wx/generic/gridg.h" #include "wx/settings.h" // Set to zero to use no double-buffering #ifdef __WXMSW__ #define wxUSE_DOUBLE_BUFFERING 1 #else #define wxUSE_DOUBLE_BUFFERING 0 #endif #define wxGRID_DRAG_NONE 0 #define wxGRID_DRAG_LEFT_RIGHT 1 #define wxGRID_DRAG_UP_DOWN 2 IMPLEMENT_DYNAMIC_CLASS(wxGenericGrid, wxPanel) IMPLEMENT_DYNAMIC_CLASS(wxGridEvent, wxEvent) BEGIN_EVENT_TABLE(wxGenericGrid, wxPanel) EVT_SIZE(wxGenericGrid::OnSize) EVT_PAINT(wxGenericGrid::OnPaint) EVT_ERASE_BACKGROUND(wxGenericGrid::OnEraseBackground) EVT_MOUSE_EVENTS(wxGenericGrid::OnMouseEvent) EVT_TEXT(wxGRID_TEXT_CTRL, wxGenericGrid::OnText) EVT_COMMAND_SCROLL(wxGRID_HSCROLL, wxGenericGrid::OnGridScroll) EVT_COMMAND_SCROLL(wxGRID_VSCROLL, wxGenericGrid::OnGridScroll) // default wxGridEvent handlers EVT_GRID_SELECT_CELL(wxGenericGrid::_OnSelectCell) EVT_GRID_CREATE_CELL(wxGenericGrid::_OnCreateCell) EVT_GRID_CHANGE_LABELS(wxGenericGrid::_OnChangeLabels) EVT_GRID_CHANGE_SEL_LABEL(wxGenericGrid::_OnChangeSelectionLabel) EVT_GRID_CELL_CHANGE(wxGenericGrid::_OnCellChange) EVT_GRID_CELL_LCLICK(wxGenericGrid::_OnCellLeftClick) EVT_GRID_CELL_RCLICK(wxGenericGrid::_OnCellRightClick) EVT_GRID_LABEL_LCLICK(wxGenericGrid::_OnLabelLeftClick) EVT_GRID_LABEL_RCLICK(wxGenericGrid::_OnLabelRightClick) END_EVENT_TABLE() wxGenericGrid::wxGenericGrid(void) { m_batchCount = 0; m_hScrollBar = (wxScrollBar *) NULL; m_vScrollBar = (wxScrollBar *) NULL; m_cellTextColour = *wxBLACK; m_cellBackgroundColour = *wxWHITE; m_labelTextColour = *wxBLACK; // m_labelBackgroundColour = *wxLIGHT_GREY; m_labelBackgroundColour = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE ); m_labelBackgroundBrush = wxNullBrush; m_labelTextFont = wxNullFont; m_cellTextFont = wxNullFont; m_textItem = (wxTextCtrl *) NULL; m_currentRectVisible = FALSE; m_editable = TRUE; #if defined(__WIN95__) m_scrollWidth = wxSystemSettings::GetSystemMetric(wxSYS_VSCROLL_X); #else m_scrollWidth = 16; #endif m_dragStatus = wxGRID_DRAG_NONE; m_dragRowOrCol = 0; m_dragStartPosition = 0; m_dragLastPosition = 0; m_divisionPen = wxNullPen; m_leftOfSheet = wxGRID_DEFAULT_SHEET_LEFT; m_topOfSheet = wxGRID_DEFAULT_SHEET_TOP; m_cellHeight = wxGRID_DEFAULT_CELL_HEIGHT; m_totalGridWidth = 0; m_totalGridHeight = 0; m_colWidths = (short *) NULL; m_rowHeights = (short *) NULL; m_verticalLabelWidth = wxGRID_DEFAULT_VERTICAL_LABEL_WIDTH; m_horizontalLabelHeight = wxGRID_DEFAULT_HORIZONAL_LABEL_HEIGHT; m_verticalLabelAlignment = wxCENTRE; m_horizontalLabelAlignment = wxCENTRE; m_editControlPosition.x = wxGRID_DEFAULT_EDIT_X; m_editControlPosition.y = wxGRID_DEFAULT_EDIT_Y; m_editControlPosition.width = wxGRID_DEFAULT_EDIT_WIDTH; m_editControlPosition.height = wxGRID_DEFAULT_EDIT_HEIGHT; m_wCursorRow = 0; m_wCursorColumn = 0; m_scrollPosX = 0; m_scrollPosY = 0; m_editCreated = FALSE; m_totalRows = 0; m_totalCols = 0; m_gridCells = (wxGridCell ***) NULL; m_rowLabelCells = (wxGridCell **) NULL; m_colLabelCells = (wxGridCell **) NULL; m_textItem = (wxTextCtrl *) NULL; } bool wxGenericGrid::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name) { m_batchCount = 0; m_editingPanel = (wxPanel *) NULL; m_hScrollBar = (wxScrollBar *) NULL; m_vScrollBar = (wxScrollBar *) NULL; m_cellTextColour = *wxBLACK; m_cellBackgroundColour = *wxWHITE; m_labelTextColour = *wxBLACK; // m_labelBackgroundColour = *wxLIGHT_GREY; m_labelBackgroundColour = wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE ); m_labelBackgroundBrush = wxNullBrush; m_labelTextFont = * wxTheFontList->FindOrCreateFont(10, wxSWISS, wxNORMAL, wxBOLD); m_cellTextFont = * wxTheFontList->FindOrCreateFont(10, wxSWISS, wxNORMAL, wxNORMAL); m_textItem = (wxTextCtrl *) NULL; m_currentRectVisible = FALSE; m_editable = TRUE; #if defined(__WIN95__) m_scrollWidth = wxSystemSettings::GetSystemMetric(wxSYS_VSCROLL_X); #else m_scrollWidth = 16; #endif m_dragStatus = wxGRID_DRAG_NONE; m_dragRowOrCol = 0; m_dragStartPosition = 0; m_dragLastPosition = 0; m_divisionPen = * wxThePenList->FindOrCreatePen("LIGHT GREY", 1, wxSOLID); m_doubleBufferingBitmap = (wxBitmap *) NULL; if (!m_horizontalSashCursor.Ok()) { m_horizontalSashCursor = wxCursor(wxCURSOR_SIZEWE); m_verticalSashCursor = wxCursor(wxCURSOR_SIZENS); } SetLabelBackgroundColour(m_labelBackgroundColour); m_leftOfSheet = wxGRID_DEFAULT_SHEET_LEFT; m_topOfSheet = wxGRID_DEFAULT_SHEET_TOP; m_cellHeight = wxGRID_DEFAULT_CELL_HEIGHT; m_totalGridWidth = 0; m_totalGridHeight = 0; m_colWidths = (short *) NULL; m_rowHeights = (short *) NULL; m_verticalLabelWidth = wxGRID_DEFAULT_VERTICAL_LABEL_WIDTH; m_horizontalLabelHeight = wxGRID_DEFAULT_HORIZONAL_LABEL_HEIGHT; m_verticalLabelAlignment = wxCENTRE; m_horizontalLabelAlignment = wxCENTRE; m_editControlPosition.x = wxGRID_DEFAULT_EDIT_X; m_editControlPosition.y = wxGRID_DEFAULT_EDIT_Y; m_editControlPosition.width = wxGRID_DEFAULT_EDIT_WIDTH; m_editControlPosition.height = wxGRID_DEFAULT_EDIT_HEIGHT; m_wCursorRow = 0; m_wCursorColumn = 0; m_scrollPosX = 0; m_scrollPosY = 0; /* Store the rect. coordinates for the current cell */ SetCurrentRect(m_wCursorRow, m_wCursorColumn); m_editCreated = FALSE; m_totalRows = 0; m_totalCols = 0; m_gridCells = (wxGridCell ***) NULL; m_rowLabelCells = (wxGridCell **) NULL; m_colLabelCells = (wxGridCell **) NULL; m_textItem = (wxTextCtrl *) NULL; wxPanel::Create(parent, id, pos, size, style, name); m_editingPanel = new wxPanel(this); m_textItem = new wxTextCtrl(m_editingPanel, wxGRID_TEXT_CTRL, "", wxPoint(m_editControlPosition.x, m_editControlPosition.y), wxSize(m_editControlPosition.width, -1), 0); m_textItem->Show(TRUE); m_textItem->SetFocus(); int controlW, controlH; m_textItem->GetSize(&controlW, &controlH); m_editControlPosition.height = controlH; m_topOfSheet = m_editControlPosition.y + controlH + 2; m_editCreated = TRUE; m_hScrollBar = new wxScrollBar(this, wxGRID_HSCROLL, wxPoint(0, 0), wxSize(20, 100), wxHORIZONTAL); m_vScrollBar = new wxScrollBar(this, wxGRID_VSCROLL, wxPoint(0, 0), wxSize(100, 20), wxVERTICAL); return TRUE; } wxGenericGrid::~wxGenericGrid(void) { ClearGrid(); } void wxGenericGrid::ClearGrid(void) { int i,j; if (m_gridCells) { for (i = 0; i < m_totalRows; i++) { for (j = 0; j < m_totalCols; j++) if (m_gridCells[i][j]) delete m_gridCells[i][j]; delete[] m_gridCells[i]; } delete[] m_gridCells; m_gridCells = (wxGridCell ***) NULL; } if (m_colWidths) delete[] m_colWidths; m_colWidths = (short *) NULL; if (m_rowHeights) delete[] m_rowHeights; m_rowHeights = (short *) NULL; if (m_rowLabelCells) { for (i = 0; i < m_totalRows; i++) delete m_rowLabelCells[i]; delete[] m_rowLabelCells; m_rowLabelCells = (wxGridCell **) NULL; } if (m_colLabelCells) { for (i = 0; i < m_totalCols; i++) delete m_colLabelCells[i]; delete[] m_colLabelCells; m_colLabelCells = (wxGridCell **) NULL; } if (m_doubleBufferingBitmap) { delete m_doubleBufferingBitmap; m_doubleBufferingBitmap = (wxBitmap *) NULL; } } bool wxGenericGrid::CreateGrid(int nRows, int nCols, wxString **cellValues, short *widths, short defaultWidth, short defaultHeight) { m_totalRows = nRows; m_totalCols = nCols; int i,j; m_colWidths = new short[nCols]; m_rowHeights = new short[nRows]; for (i = 0; i < nCols; i++) if (widths) m_colWidths[i] = widths[i]; else m_colWidths[i] = defaultWidth; for (i = 0; i < nRows; i++) m_rowHeights[i] = defaultHeight; m_gridCells = new wxGridCell **[nRows]; for (i = 0; i < nRows; i++) m_gridCells[i] = new wxGridCell *[nCols]; for (i = 0; i < nRows; i++) for (j = 0; j < nCols; j++) if (cellValues) { //m_gridCells[i][j] = OnCreateCell(); wxGridEvent g_evt(GetId(), wxEVT_GRID_CREATE_CELL, this, i, j); GetEventHandler()->ProcessEvent(g_evt); m_gridCells[i][j] = g_evt.m_cell; m_gridCells[i][j]->SetTextValue(cellValues[i][j]); } else m_gridCells[i][j] = (wxGridCell *) NULL; m_rowLabelCells = new wxGridCell *[nRows]; for (i = 0; i < nRows; i++) m_rowLabelCells[i] = new wxGridCell(this); m_colLabelCells = new wxGridCell *[nCols]; for (i = 0; i < nCols; i++) m_colLabelCells[i] = new wxGridCell(this); m_wCursorRow = m_wCursorColumn = 0; SetCurrentRect(0, 0); // Need to determine various dimensions UpdateDimensions(); // Number of 'lines' int objectSizeX = m_totalCols; int pageSizeX = 1; int viewLengthX = m_totalCols; /* m_hScrollBar->SetViewLength(viewLengthX); m_hScrollBar->SetObjectLength(objectSizeX); m_hScrollBar->SetPageSize(pageSizeX); */ m_hScrollBar->SetScrollbar(m_hScrollBar->GetThumbPosition(), pageSizeX, objectSizeX, viewLengthX); int objectSizeY = m_totalRows; int pageSizeY = 1; int viewLengthY = m_totalRows; /* m_vScrollBar->SetViewLength(viewLengthY); m_vScrollBar->SetObjectLength(objectSizeY); m_vScrollBar->SetPageSize(pageSizeY); */ m_vScrollBar->SetScrollbar(m_vScrollBar->GetThumbPosition(), pageSizeY, objectSizeY, viewLengthY); AdjustScrollbars(); //OnChangeLabels(); wxGridEvent g_evt(GetId(), wxEVT_GRID_CHANGE_LABELS, this); GetEventHandler()->ProcessEvent(g_evt); //OnChangeSelectionLabel(); wxGridEvent g_evt2(GetId(), wxEVT_GRID_CHANGE_SEL_LABEL, this); GetEventHandler()->ProcessEvent(g_evt2); return TRUE; } // Need to determine various dimensions void wxGenericGrid::UpdateDimensions(void) { int canvasWidth, canvasHeight; GetSize(&canvasWidth, &canvasHeight); if (m_editCreated && m_editable) { int controlW, controlH; GetTextItem()->GetSize(&controlW, &controlH); m_topOfSheet = m_editControlPosition.y + controlH + 2; } else m_topOfSheet = 0; m_rightOfSheet = m_leftOfSheet + m_verticalLabelWidth; int i; for (i = m_scrollPosX; i < m_totalCols; i++) { if (m_rightOfSheet > canvasWidth) break; else m_rightOfSheet += m_colWidths[i]; } m_bottomOfSheet = m_topOfSheet + m_horizontalLabelHeight; for (i = m_scrollPosY; i < m_totalRows; i++) { if (m_bottomOfSheet > canvasHeight) break; else m_bottomOfSheet += m_rowHeights[i]; } m_totalGridWidth = m_leftOfSheet + m_verticalLabelWidth; for (i = 0; i < m_totalCols; i++) { m_totalGridWidth += m_colWidths[i]; } m_totalGridHeight = m_topOfSheet + m_horizontalLabelHeight; for (i = 0; i < m_totalRows; i++) { m_totalGridHeight += m_rowHeights[i]; } } wxGridCell *wxGenericGrid::GetCell(int row, int col) const { if (!m_gridCells) return (wxGridCell *) NULL; if ((row >= m_totalRows) || (col >= m_totalCols)) return (wxGridCell *) NULL; wxGridCell *cell = m_gridCells[row][col]; if (!cell) { // m_gridCells[row][col] = OnCreateCell(); wxGridEvent g_evt(GetId(), wxEVT_GRID_CREATE_CELL, (wxGenericGrid*) this, row, col); GetEventHandler()->ProcessEvent(g_evt); m_gridCells[row][col] = g_evt.m_cell; return m_gridCells[row][col]; } else return cell; } void wxGenericGrid::SetGridClippingRegion(wxDC *dc) { int m_scrollWidthHoriz = 0; int m_scrollWidthVert = 0; int cw, ch; GetClientSize(&cw, &ch); if (m_hScrollBar && m_hScrollBar->IsShown()) m_scrollWidthHoriz = m_scrollWidth; if (m_vScrollBar && m_vScrollBar->IsShown()) m_scrollWidthVert = m_scrollWidth; // Don't paint over the scrollbars dc->SetClippingRegion(m_leftOfSheet, m_topOfSheet, cw - m_scrollWidthVert - m_leftOfSheet, ch - m_scrollWidthHoriz - m_topOfSheet); } void wxGenericGrid::OnPaint(wxPaintEvent& WXUNUSED(event)) { int w, h; GetClientSize(&w, &h); bool useDoubleBuffering = (bool) wxUSE_DOUBLE_BUFFERING; if (useDoubleBuffering) { // Reuse the old bitmap if possible if (!m_doubleBufferingBitmap || (m_doubleBufferingBitmap->GetWidth() < w || m_doubleBufferingBitmap->GetHeight() < h)) { if (m_doubleBufferingBitmap) delete m_doubleBufferingBitmap; m_doubleBufferingBitmap = new wxBitmap(w, h); } if (!m_doubleBufferingBitmap || !m_doubleBufferingBitmap->Ok()) { // If we couldn't create a new bitmap, perhaps because resources were low, // then don't complain, just don't double-buffer if (m_doubleBufferingBitmap) delete m_doubleBufferingBitmap; m_doubleBufferingBitmap = (wxBitmap *) NULL; useDoubleBuffering = FALSE; } } if (useDoubleBuffering) { wxPaintDC paintDC(this); wxMemoryDC dc(& paintDC); dc.SelectObject(* m_doubleBufferingBitmap); PaintGrid(dc); int vertScrollBarWidth = m_scrollWidth; int horizScrollBarHeight = m_scrollWidth; if (m_vScrollBar && !m_vScrollBar->IsShown()) vertScrollBarWidth = 0; if (m_hScrollBar && !m_hScrollBar->IsShown()) horizScrollBarHeight = 0; paintDC.Blit(m_leftOfSheet, m_topOfSheet, w - vertScrollBarWidth - m_leftOfSheet, h - horizScrollBarHeight - m_topOfSheet, &dc, m_leftOfSheet, m_topOfSheet, wxCOPY); dc.SelectObject(wxNullBitmap); } else { wxPaintDC dc(this); PaintGrid(dc); } } void wxGenericGrid::PaintGrid(wxDC& dc) { dc.BeginDrawing(); dc.SetOptimization(FALSE); SetGridClippingRegion(& dc); DrawLabelAreas(& dc); DrawEditableArea(& dc); DrawColumnLabels(& dc); DrawRowLabels(& dc); DrawCells(& dc); DrawGridLines(& dc); /* Hilight present cell */ SetCurrentRect(m_wCursorRow, m_wCursorColumn); if (m_currentRectVisible) HighlightCell(& dc); dc.DestroyClippingRegion(); dc.SetOptimization(TRUE); dc.EndDrawing(); } // Erase (some of) the background. // Currently, a Windows-only optimisation. void wxGenericGrid::OnEraseBackground(wxEraseEvent& WXUNUSED(event) ) { wxClientDC dc(this); dc.BeginDrawing(); dc.SetOptimization(FALSE); int w, h; GetClientSize(& w, & h); dc.SetBrush(*wxLIGHT_GREY_BRUSH); dc.SetPen(*wxLIGHT_GREY_PEN); if (m_hScrollBar && m_hScrollBar->IsShown() && m_vScrollBar && m_vScrollBar->IsShown()) { dc.DrawRectangle(w - m_scrollWidth, h - m_scrollWidth, m_scrollWidth, m_scrollWidth); } dc.SetOptimization(TRUE); dc.EndDrawing(); } void wxGenericGrid::DrawLabelAreas(wxDC *dc) { int cw, ch; GetClientSize(&cw, &ch); dc->SetPen(*wxTRANSPARENT_PEN); // dc->SetBrush(*dc->GetBackground()); // Should blank out any area which isn't going to be painted over. // dc->DrawRectangle(m_leftOfSheet, m_bottomOfSheet, cw - m_leftOfSheet, ch - m_bottomOfSheet); // dc->DrawRectangle(m_rightOfSheet, m_topOfSheet, cw - m_rightOfSheet, ch - m_topOfSheet); // Paint the label areas dc->SetBrush(m_labelBackgroundBrush); // dc->DrawRectangle(m_leftOfSheet, m_topOfSheet, m_rightOfSheet - m_leftOfSheet + 1, m_horizontalLabelHeight + 1); dc->DrawRectangle(m_leftOfSheet, m_topOfSheet, cw-m_leftOfSheet, m_horizontalLabelHeight + 1); // dc->DrawRectangle(m_leftOfSheet, m_topOfSheet, m_verticalLabelWidth + 1, m_bottomOfSheet - m_topOfSheet + 1); dc->DrawRectangle(m_leftOfSheet, m_topOfSheet, m_verticalLabelWidth + 1, ch-m_topOfSheet); } void wxGenericGrid::DrawEditableArea(wxDC *dc) { int cw, ch; GetClientSize(&cw, &ch); dc->SetPen(*wxTRANSPARENT_PEN); dc->SetBrush(*wxTheBrushList->FindOrCreateBrush(m_cellBackgroundColour, wxSOLID)); // dc->DrawRectangle(m_leftOfSheet+m_verticalLabelWidth, m_topOfSheet+m_horizontalLabelHeight, // m_rightOfSheet-(m_leftOfSheet+m_verticalLabelWidth) + 1, m_bottomOfSheet - (m_topOfSheet+m_horizontalLabelHeight) + 1); dc->DrawRectangle(m_leftOfSheet+m_verticalLabelWidth, m_topOfSheet+m_horizontalLabelHeight, cw-(m_leftOfSheet+m_verticalLabelWidth), ch - (m_topOfSheet+m_horizontalLabelHeight)); } void wxGenericGrid::DrawGridLines(wxDC *dc) { int cw, ch; GetClientSize(&cw, &ch); int i; if (m_divisionPen.Ok()) { dc->SetPen(m_divisionPen); int heightCount = m_topOfSheet + m_horizontalLabelHeight; // Draw horizontal grey lines for cells for (i = m_scrollPosY; i < (m_totalRows+1); i++) { if (heightCount > ch) break; else { dc->DrawLine(m_leftOfSheet, heightCount, cw, heightCount); if (i < m_totalRows) heightCount += m_rowHeights[i]; } } } if (m_verticalLabelWidth > 0) { dc->SetPen(*wxBLACK_PEN); // Draw horizontal black lines for row labels int heightCount = m_topOfSheet + m_horizontalLabelHeight; for (i = m_scrollPosY; i < (m_totalRows+1); i++) { if (heightCount > ch) break; else { dc->DrawLine(m_leftOfSheet, heightCount, m_verticalLabelWidth, heightCount); if (i < m_totalRows) heightCount += m_rowHeights[i]; } } // Draw a black vertical line for row number cells dc->DrawLine(m_leftOfSheet + m_verticalLabelWidth, m_topOfSheet, m_leftOfSheet + m_verticalLabelWidth, ch); // First vertical line dc->DrawLine(m_leftOfSheet, m_topOfSheet, m_leftOfSheet, ch); dc->SetPen(*wxWHITE_PEN); // Draw highlights on row labels heightCount = m_topOfSheet + m_horizontalLabelHeight; for (i = m_scrollPosY; i < m_totalRows; i++) { if (heightCount > ch) break; else { dc->DrawLine(m_leftOfSheet+1, heightCount+1, m_verticalLabelWidth, heightCount+1); dc->DrawLine(m_leftOfSheet+1, heightCount+1, m_leftOfSheet+1, heightCount + m_rowHeights[i] - 1); heightCount += m_rowHeights[i]; } } // Last one - down to the floor. dc->DrawLine(m_leftOfSheet+1, heightCount+1, m_verticalLabelWidth, heightCount+1); dc->DrawLine(m_leftOfSheet+1, heightCount+1, m_leftOfSheet+1, ch); } if (m_divisionPen.Ok()) { dc->SetPen(m_divisionPen); // Draw vertical grey lines for cells int widthCount = m_leftOfSheet + m_verticalLabelWidth; for (i = m_scrollPosX; i < m_totalCols; i++) { if (widthCount > cw) break; else { // Skip the first one if (i != m_scrollPosX) { dc->DrawLine(widthCount, m_topOfSheet + m_horizontalLabelHeight, widthCount, m_bottomOfSheet); } widthCount += m_colWidths[i]; } } // Last one dc->DrawLine(widthCount, m_topOfSheet + m_horizontalLabelHeight, widthCount, m_bottomOfSheet); } dc->SetPen(*wxBLACK_PEN); // Draw two black horizontal lines for column number cells dc->DrawLine( m_leftOfSheet, m_topOfSheet, cw, m_topOfSheet); dc->DrawLine(m_leftOfSheet, m_topOfSheet + m_horizontalLabelHeight, cw, m_topOfSheet + m_horizontalLabelHeight); if (m_horizontalLabelHeight > 0) { int widthCount = m_leftOfSheet + m_verticalLabelWidth; // Draw black vertical lines for column number cells for (i = m_scrollPosX; i < m_totalCols; i++) { if (widthCount > cw) break; else { dc->DrawLine(widthCount, m_topOfSheet, widthCount, m_topOfSheet + m_horizontalLabelHeight); widthCount += m_colWidths[i]; } } // Last one dc->DrawLine(widthCount, m_topOfSheet, widthCount, m_topOfSheet + m_horizontalLabelHeight); // Draw highlights dc->SetPen(*wxWHITE_PEN); widthCount = m_leftOfSheet + m_verticalLabelWidth; for (i = m_scrollPosX; i < m_totalCols; i++) { if (widthCount > cw) break; else { dc->DrawLine(widthCount+1, m_topOfSheet+1, widthCount+m_colWidths[i], m_topOfSheet+1); dc->DrawLine(widthCount+1, m_topOfSheet+1, widthCount+1, m_topOfSheet+m_horizontalLabelHeight); widthCount += m_colWidths[i]; } } // Last one - to the right side of the canvas. dc->DrawLine(widthCount+1, m_topOfSheet+1, cw, m_topOfSheet+1); dc->DrawLine(widthCount+1, m_topOfSheet+1, widthCount+1, m_topOfSheet+m_horizontalLabelHeight); } } void wxGenericGrid::DrawColumnLabels(wxDC *dc) { int cw, ch; GetClientSize(&cw, &ch); if (m_horizontalLabelHeight == 0) return; int i; wxRect rect; // Draw letters for columns rect.y = m_topOfSheet + 1; rect.height = m_horizontalLabelHeight - 1; dc->SetTextBackground(m_labelBackgroundColour); dc->SetBackgroundMode(wxTRANSPARENT); // dc->SetTextForeground(m_labelTextColour); int widthCount = m_leftOfSheet + m_verticalLabelWidth; for (i = m_scrollPosX; i < m_totalCols; i++) { if (widthCount > cw) break; else { rect.x = 1 + widthCount; rect.width = m_colWidths[i]; DrawColumnLabel(dc, &rect, i); widthCount += m_colWidths[i]; } } } void wxGenericGrid::DrawColumnLabel(wxDC *dc, wxRect *rect, int col) { wxGridCell *cell = GetLabelCell(wxHORIZONTAL, col); if (cell) { wxRect rect2; rect2 = *rect; rect2.x += 3; rect2.y += 2; rect2.width -= 5; rect2.height -= 4; dc->SetTextForeground(GetLabelTextColour()); dc->SetFont(GetLabelTextFont()); if ( !cell->GetTextValue().IsNull() ) DrawTextRect(dc, cell->GetTextValue(), &rect2, GetLabelAlignment(wxHORIZONTAL)); } } void wxGenericGrid::DrawRowLabels(wxDC *dc) { int cw, ch; GetClientSize(&cw, &ch); if (m_verticalLabelWidth == 0) return; int i; wxRect rect; // Draw numbers for rows rect.x = m_leftOfSheet; rect.width = m_verticalLabelWidth; int heightCount = m_topOfSheet + m_horizontalLabelHeight; dc->SetTextBackground(m_labelBackgroundColour); dc->SetBackgroundMode(wxTRANSPARENT); for (i = m_scrollPosY; i < m_totalRows; i++) { if (heightCount > ch) break; else { rect.y = 1 + heightCount; rect.height = m_rowHeights[i]; DrawRowLabel(dc, &rect, i); heightCount += m_rowHeights[i]; } } } void wxGenericGrid::DrawRowLabel(wxDC *dc, wxRect *rect, int row) { wxGridCell *cell = GetLabelCell(wxVERTICAL, row); if (cell) { wxRect rect2; rect2 = *rect; rect2.x += 3; rect2.y += 2; rect2.width -= 5; rect2.height -= 4; dc->SetTextForeground(GetLabelTextColour()); dc->SetFont(GetLabelTextFont()); if ( !cell->GetTextValue().IsNull() ) DrawTextRect(dc, cell->GetTextValue(), &rect2, GetLabelAlignment(wxVERTICAL)); } } void wxGenericGrid::DrawCells(wxDC *dc) { int cw, ch; GetClientSize(&cw, &ch); int i,j; // Draw value corresponding to each cell for (i = m_scrollPosY; i < m_totalRows; i++) { for (j = m_scrollPosX; j < m_totalCols; j++) { SetCurrentRect(i, j, cw, ch); if (m_currentRectVisible) { DrawCellBackground(dc, &m_currentRect, i, j); DrawCellValue(dc, &m_currentRect, i, j); } if (m_currentRect.x > cw) break; } if (m_currentRect.y > ch) break; } dc->SetBackgroundMode(wxSOLID); dc->SetPen(*wxBLACK_PEN); } void wxGenericGrid::DrawCellBackground(wxDC *dc, wxRect *rect, int row, int col) { wxGridCell *cell = GetCell(row, col); if (cell) { dc->SetBrush(cell->GetBackgroundBrush()); dc->SetPen(*wxTRANSPARENT_PEN); #if 0 // In wxWin 2.0 the dc code is exact. RR. #ifdef __WXMOTIF__ dc->DrawRectangle(rect->x+1, rect->y+1, rect->width-1, rect->height-1); #else dc->DrawRectangle(rect->x+1, rect->y+1, rect->width, rect->height); #endif #endif dc->DrawRectangle(rect->x+1, rect->y+1, rect->width-1, rect->height-1); dc->SetPen(*wxBLACK_PEN); } } void wxGenericGrid::DrawCellValue(wxDC *dc, wxRect *rect, int row, int col) { wxGridCell *cell = GetCell(row, col); if (cell) { wxBitmap *bitmap = cell->GetCellBitmap(); wxRect rect2; rect2 = *rect; rect2.x += 3; rect2.y += 2; rect2.width -= 5; rect2.height -= 4; if (bitmap) { DrawBitmapRect(dc, bitmap, &rect2, cell->GetAlignment()); } else { dc->SetBackgroundMode(wxTRANSPARENT); dc->SetTextForeground(cell->GetTextColour()); dc->SetFont(cell->GetFont()); if ( !cell->GetTextValue().IsNull() ) DrawTextRect(dc, cell->GetTextValue(), &rect2, cell->GetAlignment()); } } } void wxGenericGrid::AdjustScrollbars(void) { int cw, ch; GetClientSize(&cw, &ch); // We find the view size by seeing how many rows/cols fit on // the current view. // BUT... this means that the scrollbar should be adjusted every time // it's scrolled, as well as when sized, because with variable size rows/cols, // the number of rows/col visible on the view differs according to what bit // you're looking at. The object length is always the same, but the // view length differs. // Since this may not be known until the end of this function, we should probably call AdjustScrollbars // twice. int vertScrollBarWidth = m_scrollWidth; int horizScrollBarHeight = m_scrollWidth; if (m_vScrollBar && !m_vScrollBar->IsShown()) vertScrollBarWidth = 0; if (m_hScrollBar && !m_hScrollBar->IsShown()) horizScrollBarHeight = 0; int noHorizSteps = 0; int noVertSteps = 0; if (m_totalGridWidth + vertScrollBarWidth <= cw) noHorizSteps = 0; else { noHorizSteps = 0; int widthCount = 0; int i; int nx = 0; for (i = m_scrollPosX ; i < m_totalCols; i++) { widthCount += m_colWidths[i]; // A partial bit doesn't count, we still have to scroll to see the // rest of it if (widthCount + m_leftOfSheet + m_verticalLabelWidth > (cw-vertScrollBarWidth)) break; else nx ++; } noHorizSteps += nx; } if (m_totalGridHeight + horizScrollBarHeight <= ch) noVertSteps = 0; else { noVertSteps = 0; int heightCount = 0; int i; int ny = 0; for (i = m_scrollPosY ; i < m_totalRows; i++) { heightCount += m_rowHeights[i]; // A partial bit doesn't count, we still have to scroll to see the // rest of it if (heightCount + m_topOfSheet + m_horizontalLabelHeight > (ch-horizScrollBarHeight)) break; else ny ++; } noVertSteps += ny; } if (m_totalGridWidth + vertScrollBarWidth <= cw) { if ( m_hScrollBar ) m_hScrollBar->Show(FALSE); SetScrollPosX(0); } else { if ( m_hScrollBar ) m_hScrollBar->Show(TRUE); } if (m_totalGridHeight + horizScrollBarHeight <= ch) { if ( m_vScrollBar ) m_vScrollBar->Show(FALSE); SetScrollPosY(0); } else { if ( m_vScrollBar ) m_vScrollBar->Show(TRUE); } UpdateDimensions(); // Necessary in case m_scrollPosX/Y changed vertScrollBarWidth = m_scrollWidth; horizScrollBarHeight = m_scrollWidth; if (m_vScrollBar && !m_vScrollBar->IsShown()) vertScrollBarWidth = 0; if (m_hScrollBar && !m_hScrollBar->IsShown()) horizScrollBarHeight = 0; if (m_hScrollBar) { int nCols = GetCols(); m_hScrollBar->SetScrollbar(m_hScrollBar->GetThumbPosition(), wxMax(noHorizSteps, 1), (noHorizSteps == 0) ? 1 : nCols, wxMax(noHorizSteps, 1)); m_hScrollBar->SetSize(m_leftOfSheet, ch - m_scrollWidth -2, cw - vertScrollBarWidth - m_leftOfSheet, m_scrollWidth); } if (m_vScrollBar) { int nRows = GetRows(); m_vScrollBar->SetScrollbar(m_vScrollBar->GetThumbPosition(), wxMax(noVertSteps, 1), (noVertSteps == 0) ? 1 : nRows, wxMax(noVertSteps, 1)); m_vScrollBar->SetSize(cw - m_scrollWidth, m_topOfSheet, m_scrollWidth, ch - m_topOfSheet - horizScrollBarHeight); } } void wxGenericGrid::OnSize(wxSizeEvent& WXUNUSED(event) ) { if (!m_vScrollBar || !m_hScrollBar) return; AdjustScrollbars(); int cw, ch; GetClientSize(&cw, &ch); if (m_editCreated && m_editingPanel && GetTextItem() && GetTextItem()->IsShown()) { m_editingPanel->SetSize(0, 0, cw, m_editControlPosition.height + m_editControlPosition.y + 2); GetTextItem()->SetSize(m_editControlPosition.x, m_editControlPosition.y, cw - m_editControlPosition.x, m_editControlPosition.height); } } bool wxGenericGrid::CellHitTest(int x, int y, int *row, int *col) { // Find the selected cell and call OnSelectCell if (x >= (m_leftOfSheet + m_verticalLabelWidth) && y >= (m_topOfSheet + m_horizontalLabelHeight) && x <= m_rightOfSheet && y <= m_bottomOfSheet) { // Calculate the cell number from x and y x -= (m_verticalLabelWidth + m_leftOfSheet); y -= (m_topOfSheet + m_horizontalLabelHeight); int i; // Now we need to do a hit test for which row we're on int currentHeight = 0; for (i = m_scrollPosY; i < m_totalRows; i++) { if (y >= currentHeight && y <= (currentHeight + m_rowHeights[i])) { *row = i; break; } currentHeight += m_rowHeights[i]; } // Now we need to do a hit test for which column we're on int currentWidth = 0; for (i = m_scrollPosX; i < m_totalCols; i++) { if (x >= currentWidth && x <= (currentWidth + m_colWidths[i])) { *col = i; break; } currentWidth += m_colWidths[i]; } return TRUE; } return FALSE; } bool wxGenericGrid::LabelSashHitTest(int x, int y, int *orientation, int *rowOrCol, int *startPos) { int i; int tolerance = 3; if (x >= (m_leftOfSheet + m_verticalLabelWidth) && y >= m_topOfSheet && x <= m_rightOfSheet && y <= (m_topOfSheet + m_horizontalLabelHeight)) { // We may be on a column label sash. int currentWidth = m_leftOfSheet + m_verticalLabelWidth; for (i = m_scrollPosX; i < m_totalCols; i++) { if (x >= (currentWidth + m_colWidths[i] - tolerance) && x <= (currentWidth + m_colWidths[i] + tolerance)) { *orientation = wxHORIZONTAL; *rowOrCol = i; *startPos = currentWidth; return TRUE; } currentWidth += m_colWidths[i]; } return FALSE; } else if (x >= m_leftOfSheet && y >= (m_topOfSheet + m_horizontalLabelHeight) && x <= (m_leftOfSheet + m_verticalLabelWidth) && y <= m_bottomOfSheet) { // We may be on a row label sash. int currentHeight = m_topOfSheet + m_horizontalLabelHeight; for (i = m_scrollPosY; i < m_totalRows; i++) { if (y >= (currentHeight + m_rowHeights[i] - tolerance) && y <= (currentHeight + m_rowHeights[i] + tolerance)) { *orientation = wxVERTICAL; *rowOrCol = i; *startPos = currentHeight; return TRUE; } currentHeight += m_rowHeights[i]; } return FALSE; } return FALSE; } bool wxGenericGrid::LabelHitTest(int x, int y, int *row, int *col) { // Find the selected label if (x >= m_leftOfSheet && y >= m_topOfSheet && x <= m_rightOfSheet && y <= m_bottomOfSheet) { // Calculate the cell number from x and y x -= m_leftOfSheet; y -= m_topOfSheet; int i; // Now we need to do a hit test for which row we're on int currentHeight = m_horizontalLabelHeight; for (i = m_scrollPosY; i < m_totalRows; i++) { if (y >= currentHeight && y <= (currentHeight + m_rowHeights[i])) { *row = i; break; } currentHeight += m_rowHeights[i]; } if (y >= 0 && y <= m_horizontalLabelHeight) { *row = -1; } // Now we need to do a hit test for which column we're on int currentWidth = m_verticalLabelWidth; for (i = m_scrollPosX; i < m_totalCols; i++) { if (x >= currentWidth && x <= (currentWidth + m_colWidths[i])) { *col = i; break; } currentWidth += m_colWidths[i]; } if (x >= 0 && x <= m_verticalLabelWidth) { *col = -1; } if ((*col == -1) || (*row == -1)) { return TRUE; } } return FALSE; } void wxGenericGrid::OnMouseEvent(wxMouseEvent& ev) { if (ev.LeftDown()) { wxClientDC dc(this); dc.BeginDrawing(); int row, col; if (CellHitTest((int)ev.GetX(), (int)ev.GetY(), &row, &col)) { OnSelectCellImplementation(& dc, row, col); //OnCellLeftClick(row, col, (int)ev.GetX(), (int)ev.GetY(), ev.ControlDown(), ev.ShiftDown()); wxGridEvent g_evt(GetId(), wxEVT_GRID_CELL_LCLICK, this, row, col, (int)ev.GetX(), (int)ev.GetY(), ev.ControlDown(), ev.ShiftDown()); GetEventHandler()->ProcessEvent(g_evt); } if (LabelHitTest((int)ev.GetX(), (int)ev.GetY(), &row, &col)) { //OnLabelLeftClick(row, col, (int)ev.GetX(), (int)ev.GetY(), ev.ControlDown(), ev.ShiftDown()); wxGridEvent g_evt(GetId(), wxEVT_GRID_LABEL_LCLICK, this, row, col, (int)ev.GetX(), (int)ev.GetY(), ev.ControlDown(), ev.ShiftDown()); GetEventHandler()->ProcessEvent(g_evt); } dc.EndDrawing(); } else if (ev.Dragging() && ev.LeftIsDown()) { switch (m_dragStatus) { case wxGRID_DRAG_NONE: { int orientation; if (LabelSashHitTest((int)ev.GetX(), (int)ev.GetY(), &orientation, &m_dragRowOrCol, &m_dragStartPosition)) { if (orientation == wxHORIZONTAL) { m_dragStatus = wxGRID_DRAG_LEFT_RIGHT; SetCursor(m_horizontalSashCursor); m_dragLastPosition = (int)ev.GetX(); } else { m_dragStatus = wxGRID_DRAG_UP_DOWN; SetCursor(m_verticalSashCursor); m_dragLastPosition = (int)ev.GetY(); } wxClientDC dc(this); dc.BeginDrawing(); dc.SetLogicalFunction(wxINVERT); if (orientation == wxHORIZONTAL) dc.DrawLine((int)ev.GetX(), m_topOfSheet, (int)ev.GetX(), m_bottomOfSheet); else dc.DrawLine(m_leftOfSheet, (int)ev.GetY(), m_rightOfSheet, (int)ev.GetY()); dc.EndDrawing(); CaptureMouse(); } break; } case wxGRID_DRAG_LEFT_RIGHT: { wxClientDC dc(this); dc.BeginDrawing(); dc.SetLogicalFunction(wxINVERT); dc.DrawLine(m_dragLastPosition, m_topOfSheet, m_dragLastPosition, m_bottomOfSheet); dc.DrawLine((int)ev.GetX(), m_topOfSheet, (int)ev.GetX(), m_bottomOfSheet); dc.EndDrawing(); m_dragLastPosition = (int)ev.GetX(); SetCursor(m_horizontalSashCursor); break; } case wxGRID_DRAG_UP_DOWN: { wxClientDC dc(this); dc.BeginDrawing(); dc.SetLogicalFunction(wxINVERT); dc.DrawLine(m_leftOfSheet, m_dragLastPosition, m_rightOfSheet, m_dragLastPosition); dc.DrawLine(m_leftOfSheet, (int)ev.GetY(), m_rightOfSheet, (int)ev.GetY()); dc.EndDrawing(); m_dragLastPosition = (int)ev.GetY(); SetCursor(m_verticalSashCursor); break; } } } else if (ev.Moving()) { int rowOrCol, orientation, startPos; if (LabelSashHitTest((int)ev.GetX(), (int)ev.GetY(), &orientation, &rowOrCol, &startPos)) { if (orientation == wxHORIZONTAL) SetCursor(m_horizontalSashCursor); else SetCursor(m_verticalSashCursor); } else SetCursor(*wxSTANDARD_CURSOR); } else if (ev.LeftUp()) { switch (m_dragStatus) { case wxGRID_DRAG_LEFT_RIGHT: { wxClientDC dc(this); dc.BeginDrawing(); dc.SetLogicalFunction(wxINVERT); dc.DrawLine(m_dragLastPosition, m_topOfSheet, m_dragLastPosition, m_bottomOfSheet); dc.SetLogicalFunction(wxCOPY); dc.EndDrawing(); ReleaseMouse(); if (ev.GetX() > m_dragStartPosition) { m_colWidths[m_dragRowOrCol] = (short)(ev.GetX() - m_dragStartPosition); UpdateDimensions(); AdjustScrollbars(); Refresh(); } SetCursor(*wxSTANDARD_CURSOR); int cw, ch; GetClientSize(&cw, &ch); wxSizeEvent evt; OnSize(evt); break; } case wxGRID_DRAG_UP_DOWN: { wxClientDC dc(this); dc.BeginDrawing(); dc.SetLogicalFunction(wxINVERT); dc.DrawLine(m_leftOfSheet, m_dragLastPosition, m_rightOfSheet, m_dragLastPosition); dc.SetLogicalFunction(wxCOPY); dc.EndDrawing(); ReleaseMouse(); if (ev.GetY() > m_dragStartPosition) { m_rowHeights[m_dragRowOrCol] = (short)(ev.GetY() - m_dragStartPosition); UpdateDimensions(); AdjustScrollbars(); Refresh(); } SetCursor(*wxSTANDARD_CURSOR); break; } } m_dragStatus = wxGRID_DRAG_NONE; } else if (ev.RightDown()) { int row, col; if (CellHitTest((int)ev.GetX(), (int)ev.GetY(), &row, &col)) { //OnCellRightClick(row, col, (int)ev.GetX(), (int)ev.GetY(), ev.ControlDown(), ev.ShiftDown()); wxGridEvent g_evt(GetId(), wxEVT_GRID_CELL_RCLICK, this, row, col, (int)ev.GetX(), (int)ev.GetY(), ev.ControlDown(), ev.ShiftDown()); GetEventHandler()->ProcessEvent(g_evt); } if (LabelHitTest((int)ev.GetX(), (int)ev.GetY(), &row, &col)) { //OnLabelRightClick(row, col, (int)ev.GetX(), (int)ev.GetY(), ev.ControlDown(), ev.ShiftDown()); wxGridEvent g_evt(GetId(), wxEVT_GRID_LABEL_RCLICK, this, row, col, (int)ev.GetX(), (int)ev.GetY(), ev.ControlDown(), ev.ShiftDown()); GetEventHandler()->ProcessEvent(g_evt); } } } void wxGenericGrid::OnSelectCellImplementation(wxDC *dc, int row, int col) { m_wCursorColumn = col; m_wCursorRow = row; //OnChangeSelectionLabel(); wxGridEvent g_evt(GetId(), wxEVT_GRID_CHANGE_SEL_LABEL, this); GetEventHandler()->ProcessEvent(g_evt); SetGridClippingRegion(dc); // Remove the highlight from the old cell if (m_currentRectVisible) HighlightCell(dc); // Highlight the new cell and copy its content to the edit control SetCurrentRect(m_wCursorRow, m_wCursorColumn); wxGridCell *cell = GetCell(m_wCursorRow, m_wCursorColumn); if (cell) { if ( cell->GetTextValue().IsNull() ) m_textItem->SetValue(""); else m_textItem->SetValue(cell->GetTextValue()); } SetGridClippingRegion(dc); // 1) Why isn't this needed for Windows?? // Probably because of the SetValue?? JS. // 2) Arrrrrgh. This isn't needed anywhere, // of course. One hour of debugging... RR. #ifndef __WXMSW__ // HighlightCell(dc); #endif dc->DestroyClippingRegion(); //OnSelectCell(row, col); wxGridEvent g_evt2(GetId(), wxEVT_GRID_SELECT_CELL, this, row, col); GetEventHandler()->ProcessEvent(g_evt2); } wxGridCell *wxGenericGrid::OnCreateCell(void) { return new wxGridCell(this); } void wxGenericGrid::OnChangeLabels(void) { char buf[100]; int i; for (i = 0; i < m_totalRows; i++) { sprintf(buf, "%d", i+1); SetLabelValue(wxVERTICAL, buf, i); } // A...Z,AA...ZZ,AAA...ZZZ, etc. for (i = 0; i < m_totalCols; i++) { int j; int noTimes = (i/26 + 1); int ch = (i % 26) + 65; buf[0] = 0; for (j = 0; j < noTimes; j++) { char buf2[20]; sprintf(buf2, "%c", (char)ch); strcat(buf, buf2); } SetLabelValue(wxHORIZONTAL, buf, i); } } void wxGenericGrid::OnChangeSelectionLabel(void) { if (!GetEditable()) return; wxString rowLabel(GetLabelValue(wxVERTICAL, GetCursorRow())); wxString colLabel(GetLabelValue(wxHORIZONTAL, GetCursorColumn())); wxString newLabel = colLabel + rowLabel; if ((newLabel.Length() > 0) && (newLabel.Length() <= 8) && GetTextItem()) { // GetTextItem()->SetLabel(newLabel); } } void wxGenericGrid::HighlightCell(wxDC *dc) { dc->SetLogicalFunction(wxINVERT); // Top dc->DrawLine( m_currentRect.x + 1, m_currentRect.y + 1, m_currentRect.x + m_currentRect.width - 1, m_currentRect.y + 1); // Right dc->DrawLine( m_currentRect.x + m_currentRect.width - 1, m_currentRect.y + 1, m_currentRect.x + m_currentRect.width - 1, m_currentRect.y +m_currentRect.height - 1 ); // Bottom dc->DrawLine( m_currentRect.x + m_currentRect.width - 1, m_currentRect.y + m_currentRect.height - 1, m_currentRect.x + 1, m_currentRect.y + m_currentRect.height - 1); // Left dc->DrawLine( m_currentRect.x + 1, m_currentRect.y + m_currentRect.height - 1, m_currentRect.x + 1, m_currentRect.y + 1); dc->SetLogicalFunction(wxCOPY); } void wxGenericGrid::DrawCellText(void) { if (!m_currentRectVisible) return; wxGridCell *cell = GetCell(GetCursorRow(), GetCursorColumn()); if (!cell) return; static char szEdit[300]; wxClientDC dc(this); dc.BeginDrawing(); SetGridClippingRegion(& dc); dc.SetBackgroundMode(wxTRANSPARENT); dc.SetBrush(cell->GetBackgroundBrush()); strcpy(szEdit, m_textItem->GetValue()); wxRect rect; rect = m_currentRect; rect.x += 3; rect.y += 2; rect.width -= 5; rect.height -= 4; DrawTextRect(& dc, " ", &rect, wxLEFT); DrawTextRect(& dc, szEdit, &rect, cell->GetAlignment()); dc.DestroyClippingRegion(); dc.SetBackgroundMode(wxSOLID); dc.EndDrawing(); } void wxGenericGrid::SetCurrentRect(int Row, int Column, int canvasW, int canvasH) { int currentWidth = m_leftOfSheet + m_verticalLabelWidth; int i; for (i = m_scrollPosX; i < Column; i++) currentWidth += m_colWidths[i]; int currentHeight = m_topOfSheet + m_horizontalLabelHeight; for (i = m_scrollPosY; i < Row; i++) currentHeight += m_rowHeights[i]; m_currentRect.x = currentWidth; m_currentRect.y = currentHeight; m_currentRect.width = m_colWidths ? (m_colWidths[Column]) : 0; m_currentRect.height = m_rowHeights ? (m_rowHeights[Row]) : 0; if (Row < m_scrollPosY || Column < m_scrollPosX) m_currentRectVisible = FALSE; else if ((canvasW != -1 && canvasH != -1) && (m_currentRect.x > canvasW || m_currentRect.y > canvasH)) m_currentRectVisible = FALSE; else m_currentRectVisible = TRUE; } static bool wxRectIntersection(wxRect *rect1, wxRect *rect2, wxRect *rect3) { int x2_1 = rect1->x + rect1->width; int y2_1 = rect1->y + rect1->height; int x2_2 = rect2->x + rect2->width; int y2_2 = rect2->y + rect2->height; int x2_3, y2_3; // Check for intersection if ((rect1->x > x2_2) || (rect2->x > x2_1) || (rect1->y > y2_2) || (rect2->y > y2_1)) { // No intersection rect3->x = rect3->y = rect3->width = rect3->height = 0; return FALSE; } if (rect1->x > rect2->x) rect3->x = rect1->x; else rect3->x = rect2->x; if (rect1->y > rect2->y) rect3->y = rect1->y; else rect3->y = rect2->y; if (x2_1 > x2_2) x2_3 = x2_2; else x2_3 = x2_1; if (y2_1 > y2_2) y2_3 = y2_2; else y2_3 = y2_1; rect3->width = (int)(x2_3 - rect3->x); rect3->height = (int)(y2_3 - rect3->y); return TRUE; } void wxGenericGrid::DrawTextRect(wxDC *dc, const wxString& text, wxRect *rect, int flag) { dc->BeginDrawing(); // Ultimately, this functionality should be built into wxWindows, // and optimized for each platform. E.g. on Windows, use DrawText // passing a clipping rectangle, so that the wxWindows clipping region // does not have to be used to implement this. // If we're already clipping, we need to find the intersection // between current clipping area and text clipping area. wxRect clipRect; wxRect clipRect2; long clipX, clipY, clipW, clipH; dc->GetClippingBox(&clipX, &clipY, &clipW, &clipH); clipRect.x = (int)clipX; clipRect.y = (int)clipY; clipRect.width = (int)clipW; clipRect.height = (int)clipH; bool alreadyClipping = TRUE; if (clipRect.x == 0 && clipRect.y == 0 && clipRect.width == 0 && clipRect.height == 0) { alreadyClipping = FALSE; clipRect2.x = rect->x; clipRect2.y = rect->y; clipRect2.width = rect->width; clipRect2.height = rect->height; } else { // Find intersection. if (!wxRectIntersection(rect, &clipRect, &clipRect2)) return; } if (alreadyClipping) dc->DestroyClippingRegion(); dc->SetClippingRegion(clipRect2.x, clipRect2.y, clipRect2.width, clipRect2.height); long textWidth, textHeight; dc->GetTextExtent(text, &textWidth, &textHeight); // Do alignment float x,y; switch (flag) { case wxRIGHT: { x = (rect->x + rect->width - textWidth - 1.0); y = (rect->y + (rect->height - textHeight)/2.0); break; } case wxCENTRE: { x = (rect->x + (rect->width - textWidth)/2.0); y = (rect->y + (rect->height - textHeight)/2.0); break; } case wxLEFT: default: { x = (rect->x + 1.0); y = (rect->y + (rect->height - textHeight)/2.0); break; } } dc->DrawText(text, (long)x, (long)y ); dc->DestroyClippingRegion(); // Restore old clipping if (alreadyClipping) dc->SetClippingRegion(clipRect.x, clipRect.y, clipRect.width, clipRect.height); dc->EndDrawing(); } void wxGenericGrid::DrawBitmapRect(wxDC *dc, wxBitmap *bitmap, wxRect *rect, int flag) { dc->BeginDrawing(); // Ultimately, this functionality should be built into wxWindows, // and optimized for each platform. E.g. on Windows, use DrawText // passing a clipping rectangle, so that the wxWindows clipping region // does not have to be used to implement this. // If we're already clipping, we need to find the intersection // between current clipping area and text clipping area. wxRect clipRect; wxRect clipRect2; long clipX, clipY, clipW, clipH; dc->GetClippingBox(&clipX, &clipY, &clipW, &clipH); clipRect.x = (int)clipX; clipRect.y = (int)clipY; clipRect.width = (int)clipW; clipRect.height = (int)clipH; bool alreadyClipping = TRUE; if (clipRect.x == 0 && clipRect.y == 0 && clipRect.width == 0 && clipRect.height == 0) { alreadyClipping = FALSE; clipRect2.x = rect->x; clipRect2.y = rect->y; clipRect2.width = rect->width; clipRect2.height = rect->height; } else { // Find intersection. if (!wxRectIntersection(rect, &clipRect, &clipRect2)) return; } if (alreadyClipping) dc->DestroyClippingRegion(); dc->SetClippingRegion(clipRect2.x, clipRect2.y, clipRect2.width, clipRect2.height); float bitmapWidth, bitmapHeight; bitmapWidth = bitmap->GetWidth(); bitmapHeight = bitmap->GetHeight(); // Do alignment long x,y; switch (flag) { case wxRIGHT: { x = (long)(rect->x + rect->width - bitmapWidth - 1); y = (long)(rect->y + (rect->height - bitmapHeight)/2.0); break; } case wxCENTRE: { x = (long)(rect->x + (rect->width - bitmapWidth)/2.0); y = (long)(rect->y + (rect->height - bitmapHeight)/2.0); break; } case wxLEFT: default: { x = (long)(rect->x + 1); y = (long)(rect->y + (rect->height - bitmapHeight)/2.0); break; } } wxMemoryDC dcTemp; dcTemp.SelectObject(*bitmap); dc->Blit( (long)x, (long)y, (long)bitmapWidth, (long)bitmapHeight, &dcTemp, 0, 0); dcTemp.SelectObject(wxNullBitmap); dc->DestroyClippingRegion(); // Restore old clipping if (alreadyClipping) dc->SetClippingRegion(clipRect.x, clipRect.y, clipRect.width, clipRect.height); dc->EndDrawing(); } void wxGenericGrid::OnActivate(bool active) { if (active) { // Edit control should always have the focus if (GetTextItem() && GetEditable()) { GetTextItem()->SetFocus(); wxGridCell *cell = GetCell(GetCursorRow(), GetCursorColumn()); if (cell) GetTextItem()->SetValue(cell->GetTextValue()); } } } void wxGenericGrid::SetCellValue(const wxString& val, int row, int col) { wxGridCell *cell = GetCell(row, col); if (cell) { cell->SetTextValue(val); RefreshCell(row, col, TRUE); } } void wxGenericGrid::RefreshCell(int row, int col, bool setText) { // Don't refresh within a pair of batch brackets if (GetBatchCount() > 0) return; int cw, ch; GetClientSize(&cw, &ch); SetCurrentRect(row, col, cw, ch); if (m_currentRectVisible) { wxGridCell *cell = GetCell(row, col); bool currentPos = FALSE; if (row == m_wCursorRow && col == m_wCursorColumn && GetTextItem() && GetTextItem()->IsShown() && setText) { GetTextItem()->SetValue(cell->GetTextValue()); currentPos = TRUE; } // Gets refreshed anyway in MSW #ifdef __WXMSW__ if (!currentPos) #endif { wxClientDC dc(this); dc.BeginDrawing(); DrawCellBackground(& dc, &m_currentRect, row, col); DrawCellValue(& dc, &m_currentRect, row, col); dc.EndDrawing(); } } } wxString& wxGenericGrid::GetCellValue(int row, int col) const { static wxString emptyString(""); wxGridCell *cell = GetCell(row, col); if (cell) return cell->GetTextValue(); else return emptyString; } void wxGenericGrid::SetColumnWidth(int col, int width) { if (col <= m_totalCols) m_colWidths[col] = width; } int wxGenericGrid::GetColumnWidth(int col) const { if (col <= m_totalCols) return m_colWidths[col]; else return 0; } void wxGenericGrid::SetRowHeight(int row, int height) { if (row <= m_totalRows) m_rowHeights[row] = height; } int wxGenericGrid::GetRowHeight(int row) const { if (row <= m_totalRows) return m_rowHeights[row]; else return 0; } void wxGenericGrid::SetLabelSize(int orientation, int sz) { if (orientation == wxHORIZONTAL) m_horizontalLabelHeight = sz; else m_verticalLabelWidth = sz; UpdateDimensions(); SetCurrentRect(GetCursorRow(), GetCursorColumn()); } int wxGenericGrid::GetLabelSize(int orientation) const { if (orientation == wxHORIZONTAL) return m_horizontalLabelHeight; else return m_verticalLabelWidth; } wxGridCell *wxGenericGrid::GetLabelCell(int orientation, int pos) const { if (orientation == wxHORIZONTAL) { if (m_colLabelCells && pos < m_totalCols) return m_colLabelCells[pos]; else return (wxGridCell *) NULL; } else { if (m_rowLabelCells && pos < m_totalRows) return m_rowLabelCells[pos]; else return (wxGridCell *) NULL; } } void wxGenericGrid::SetLabelValue(int orientation, const wxString& val, int pos) { wxGridCell *cell = GetLabelCell(orientation, pos); if (cell) cell->SetTextValue(val); } wxString& wxGenericGrid::GetLabelValue(int orientation, int pos) const { static wxString emptyString = ""; wxGridCell *cell = GetLabelCell(orientation, pos); if (cell) return cell->GetTextValue(); else return emptyString; } void wxGenericGrid::SetLabelAlignment(int orientation, int align) { if (orientation == wxHORIZONTAL) m_horizontalLabelAlignment = align; else m_verticalLabelAlignment = align; UpdateDimensions(); SetCurrentRect(GetCursorRow(), GetCursorColumn()); } int wxGenericGrid::GetLabelAlignment(int orientation) const { if (orientation == wxHORIZONTAL) return m_horizontalLabelAlignment; else return m_verticalLabelAlignment; } void wxGenericGrid::SetLabelTextColour(const wxColour& colour) { m_labelTextColour = colour; } void wxGenericGrid::SetLabelBackgroundColour(const wxColour& colour) { m_labelBackgroundColour = colour; m_labelBackgroundBrush = * wxTheBrushList->FindOrCreateBrush(m_labelBackgroundColour, wxSOLID); } void wxGenericGrid::SetEditable(bool edit) { m_editable = edit; if (edit) { int controlW, controlH; m_textItem->GetSize(&controlW, &controlH); m_editControlPosition.height = controlH; m_topOfSheet = m_editControlPosition.x + controlH + 2; if (m_textItem) { m_editingPanel->Show(TRUE); m_textItem->Show(TRUE); m_textItem->SetFocus(); } } else { m_topOfSheet = 0; if (m_textItem) { m_textItem->Show(FALSE); m_editingPanel->Show(FALSE); } } UpdateDimensions(); SetCurrentRect(GetCursorRow(), GetCursorColumn()); int cw, ch; GetClientSize(&cw, &ch); wxSizeEvent evt; OnSize(evt); /* int cw, ch; int m_scrollWidth = 16; GetClientSize(&cw, &ch); if (m_vScrollBar) m_vScrollBar->SetSize(cw - m_scrollWidth, m_topOfSheet, m_scrollWidth, ch - m_topOfSheet - m_scrollWidth); */ } void wxGenericGrid::SetCellAlignment(int flag, int row, int col) { wxGridCell *cell = GetCell(row, col); if (cell) cell->SetAlignment(flag); } int wxGenericGrid::GetCellAlignment(int row, int col) const { wxGridCell *cell = GetCell(row, col); if (cell) return cell->GetAlignment(); else return m_cellAlignment; } void wxGenericGrid::SetCellAlignment(int flag) { m_cellAlignment = flag; int i,j; for (i = 0; i < GetRows(); i++) for (j = 0; j < GetCols(); j++) if (GetCell(i, j)) GetCell(i, j)->SetAlignment(flag); } int wxGenericGrid::GetCellAlignment(void) const { return m_cellAlignment; } void wxGenericGrid::SetCellBackgroundColour(const wxColour& col) { m_cellBackgroundColour = col; int i,j; for (i = 0; i < GetRows(); i++) for (j = 0; j < GetCols(); j++) if (GetCell(i, j)) GetCell(i, j)->SetBackgroundColour(col); } void wxGenericGrid::SetCellBackgroundColour(const wxColour& val, int row, int col) { wxGridCell *cell = GetCell(row, col); if (cell) { cell->SetBackgroundColour(val); RefreshCell(row, col); } } wxColour& wxGenericGrid::GetCellBackgroundColour(int row, int col) const { wxGridCell *cell = GetCell(row, col); if (cell) return cell->GetBackgroundColour(); else return (wxColour&) m_cellBackgroundColour; } void wxGenericGrid::SetCellTextColour(const wxColour& val, int row, int col) { wxGridCell *cell = GetCell(row, col); if (cell) { cell->SetTextColour(val); RefreshCell(row, col); } } void wxGenericGrid::SetCellTextFont(const wxFont& fnt, int row, int col) { wxGridCell *cell = GetCell(row, col); if (cell) { cell->SetFont(fnt); RefreshCell(row, col); } } wxFont& wxGenericGrid::GetCellTextFont(int row, int col) const { wxGridCell *cell = GetCell(row, col); if (cell) return (wxFont&) cell->GetFont(); else return (wxFont&) m_cellTextFont; } wxColour& wxGenericGrid::GetCellTextColour(int row, int col) const { wxGridCell *cell = GetCell(row, col); if (cell) return (wxColour&) cell->GetTextColour(); else return (wxColour&) m_cellTextColour; } void wxGenericGrid::SetCellTextColour(const wxColour& val) { m_cellTextColour = val; int i,j; for (i = 0; i < GetRows(); i++) for (j = 0; j < GetCols(); j++) if (GetCell(i, j)) GetCell(i, j)->SetTextColour(val); } void wxGenericGrid::SetCellTextFont(const wxFont& fnt) { m_cellTextFont = fnt; int i,j; for (i = 0; i < GetRows(); i++) for (j = 0; j < GetCols(); j++) if (GetCell(i, j)) GetCell(i, j)->SetFont(fnt); } void wxGenericGrid::SetCellBitmap(wxBitmap *bitmap, int row, int col) { wxGridCell *cell = GetCell(row, col); if (cell) { cell->SetCellBitmap(bitmap); RefreshCell(row, col); } } wxBitmap *wxGenericGrid::GetCellBitmap(int row, int col) const { wxGridCell *cell = GetCell(row, col); if (cell) { return cell->GetCellBitmap(); } else return (wxBitmap *) NULL; } bool wxGenericGrid::InsertCols(int pos, int n, bool updateLabels) { if (pos > m_totalCols) return FALSE; if (!m_gridCells) return CreateGrid(1, n); else { int i, j; // Cells for (i = 0; i < m_totalRows; i++) { wxGridCell **cols = m_gridCells[i]; wxGridCell **newCols = new wxGridCell *[m_totalCols + n]; for (j = 0; j < pos; j++) newCols[j] = cols[j]; for (j = pos; j < pos + n; j++) newCols[j] = new wxGridCell(this); for (j = pos + n; j < m_totalCols + n; j++) newCols[j] = cols[j - n]; delete[] cols; m_gridCells[i] = newCols; } // Column widths short *newColWidths = new short[m_totalCols + n]; for (j = 0; j < pos; j++) newColWidths[j] = m_colWidths[j]; for (j = pos; j < pos + n; j++) newColWidths[j] = wxGRID_DEFAULT_CELL_WIDTH; for (j = pos + n; j < m_totalCols + n; j++) newColWidths[j] = m_colWidths[j - n]; delete[] m_colWidths; m_colWidths = newColWidths; // Column labels wxGridCell **newLabels = new wxGridCell *[m_totalCols + n]; for (j = 0; j < pos; j++) newLabels[j] = m_colLabelCells[j]; for (j = pos; j < pos + n; j++) newLabels[j] = new wxGridCell(this); for (j = pos + n; j < m_totalCols + n; j++) newLabels[j] = m_colLabelCells[j - n]; delete[] m_colLabelCells; m_colLabelCells = newLabels; m_totalCols += n; if (updateLabels) { //OnChangeLabels(); wxGridEvent g_evt(GetId(), wxEVT_GRID_CHANGE_LABELS, this); GetEventHandler()->ProcessEvent(g_evt); } UpdateDimensions(); AdjustScrollbars(); return TRUE; } } bool wxGenericGrid::InsertRows(int pos, int n, bool updateLabels) { if (pos > m_totalRows) return FALSE; if (!m_gridCells) return CreateGrid(n, 1); else { int i, j; wxGridCell ***rows = new wxGridCell **[m_totalRows + n]; // Cells for (i = 0; i < pos; i++) rows[i] = m_gridCells[i]; for (i = pos; i < pos + n; i++) { rows[i] = new wxGridCell *[m_totalCols]; for (j = 0; j < m_totalCols; j++) rows[i][j] = new wxGridCell(this); } for (i = pos + n; i < m_totalRows + n; i++) rows[i] = m_gridCells[i - n]; delete[] m_gridCells; m_gridCells = rows; // Row heights short *newRowHeights = new short[m_totalRows + n]; for (i = 0; i < pos; i++) newRowHeights[i] = m_rowHeights[i]; for (i = pos; i < pos + n; i++) newRowHeights[i] = wxGRID_DEFAULT_CELL_HEIGHT; for (i = pos + n; i < m_totalRows + n; i++) newRowHeights[i] = m_rowHeights[i - n]; delete[] m_rowHeights; m_rowHeights = newRowHeights; // Column labels wxGridCell **newLabels = new wxGridCell *[m_totalRows + n]; for (i = 0; i < pos; i++) newLabels[i] = m_rowLabelCells[i]; for (i = pos; i < pos + n; i++) newLabels[i] = new wxGridCell(this); for (i = pos + n; i < m_totalRows + n; i++) newLabels[i] = m_rowLabelCells[i - n]; delete[] m_rowLabelCells; m_rowLabelCells = newLabels; m_totalRows += n; if (updateLabels) { //OnChangeLabels(); wxGridEvent g_evt(GetId(), wxEVT_GRID_CHANGE_LABELS, this); GetEventHandler()->ProcessEvent(g_evt); } UpdateDimensions(); AdjustScrollbars(); return TRUE; } } bool wxGenericGrid::AppendCols(int n, bool updateLabels) { return InsertCols(GetCols(), n, updateLabels); } bool wxGenericGrid::AppendRows(int n, bool updateLabels) { return InsertRows(GetRows(), n, updateLabels); } bool wxGenericGrid::DeleteRows(int pos, int n, bool updateLabels) { if (pos > m_totalRows) return FALSE; if (!m_gridCells) return FALSE; int i; wxGridCell ***rows = new wxGridCell **[m_totalRows - n]; // Cells for (i = 0; i < pos; i++) rows[i] = m_gridCells[i]; for (i = pos + n; i < m_totalRows; i++) rows[i-n] = m_gridCells[i]; delete[] m_gridCells; m_gridCells = rows; // Row heights short *newRowHeights = new short[m_totalRows - n]; for (i = 0; i < pos; i++) newRowHeights[i] = m_rowHeights[i]; for (i = pos + n; i < m_totalRows; i++) newRowHeights[i-n] = m_rowHeights[i]; delete[] m_rowHeights; m_rowHeights = newRowHeights; // Column labels wxGridCell **newLabels = new wxGridCell *[m_totalRows - n]; for (i = 0; i < pos; i++) newLabels[i] = m_rowLabelCells[i]; for (i = pos + n; i < m_totalRows; i++) newLabels[i-n] = m_rowLabelCells[i]; delete[] m_rowLabelCells; m_rowLabelCells = newLabels; m_totalRows -= n; if (updateLabels){ //OnChangeLabels(); wxGridEvent g_evt(GetId(), wxEVT_GRID_CHANGE_LABELS, this); GetEventHandler()->ProcessEvent(g_evt); } UpdateDimensions(); AdjustScrollbars(); return TRUE; } bool wxGenericGrid::DeleteCols(int pos, int n, bool updateLabels) { if (pos + n > m_totalCols) return FALSE; if (!m_gridCells) return FALSE; int i, j; // Cells for (i = 0; i < m_totalRows; i++) { wxGridCell **cols = m_gridCells[i]; wxGridCell **newCols = new wxGridCell *[m_totalCols - n]; for (j = 0; j < pos; j++) newCols[j] = cols[j]; for (j = pos; j < pos + n; j++) delete cols[j]; for (j = pos + n; j < m_totalCols; j++) newCols[j-n] = cols[j]; delete[] cols; m_gridCells[i] = newCols; } // Column widths short *newColWidths = new short[m_totalCols - n]; for (j = 0; j < pos; j++) newColWidths[j] = m_colWidths[j]; for (j = pos + n; j < m_totalCols; j++) newColWidths[j-n] = m_colWidths[j]; delete[] m_colWidths; m_colWidths = newColWidths; // Column labels wxGridCell **newLabels = new wxGridCell *[m_totalCols - n]; for (j = 0; j < pos; j++) newLabels[j] = m_colLabelCells[j]; for (j = pos + n; j < m_totalCols; j++) newLabels[j-n] = m_colLabelCells[j]; delete[] m_colLabelCells; m_colLabelCells = newLabels; m_totalCols -= n; if (updateLabels) { //OnChangeLabels(); wxGridEvent g_evt(GetId(), wxEVT_GRID_CHANGE_LABELS, this); GetEventHandler()->ProcessEvent(g_evt); } UpdateDimensions(); AdjustScrollbars(); return TRUE; } void wxGenericGrid::SetGridCursor(int row, int col) { if (row >= m_totalRows || col >= m_totalCols) return; if (row == GetCursorRow() && col == GetCursorColumn()) return; wxClientDC dc(this); dc.BeginDrawing(); SetGridClippingRegion(& dc); if (m_currentRectVisible) HighlightCell(& dc); m_wCursorRow = row; m_wCursorColumn = col; int cw, ch; GetClientSize(&cw, &ch); SetCurrentRect(row, col, cw, ch); if (m_currentRectVisible) HighlightCell(& dc); dc.DestroyClippingRegion(); dc.EndDrawing(); } /* * Grid cell */ wxGridCell::wxGridCell(wxGenericGrid *window) { cellBitmap = (wxBitmap *) NULL; font = wxNullFont; backgroundBrush = wxNullBrush; if (window) textColour = window->GetCellTextColour(); else textColour.Set(0,0,0); if (window) backgroundColour = window->GetCellBackgroundColour(); else backgroundColour.Set(255,255,255); if (window) font = window->GetCellTextFont(); else font = * wxTheFontList->FindOrCreateFont(12, wxSWISS, wxNORMAL, wxNORMAL); SetBackgroundColour(backgroundColour); if (window) alignment = window->GetCellAlignment(); else alignment = wxLEFT; } wxGridCell::~wxGridCell(void) { } void wxGridCell::SetBackgroundColour(const wxColour& colour) { backgroundColour = colour; backgroundBrush = * wxTheBrushList->FindOrCreateBrush(backgroundColour, wxSOLID); } void wxGenericGrid::OnText(wxCommandEvent& WXUNUSED(ev) ) { wxGenericGrid *grid = this; wxGridCell *cell = grid->GetCell(grid->GetCursorRow(), grid->GetCursorColumn()); if (cell && grid->CurrentCellVisible()) { cell->SetTextValue(grid->GetTextItem()->GetValue()); wxClientDC dc(grid); dc.BeginDrawing(); grid->SetGridClippingRegion(& dc); grid->DrawCellBackground(& dc, &grid->GetCurrentRect(), grid->GetCursorRow(), grid->GetCursorColumn()); grid->DrawCellValue(& dc, &grid->GetCurrentRect(), grid->GetCursorRow(), grid->GetCursorColumn()); grid->HighlightCell(& dc); dc.DestroyClippingRegion(); dc.EndDrawing(); //grid->OnCellChange(grid->GetCursorRow(), grid->GetCursorColumn()); wxGridEvent g_evt(GetId(), wxEVT_GRID_CELL_CHANGE, grid, grid->GetCursorRow(), grid->GetCursorColumn()); GetEventHandler()->ProcessEvent(g_evt); // grid->DrawCellText(); } } void wxGenericGrid::OnGridScroll(wxScrollEvent& ev) { static bool inScroll = FALSE; if ( inScroll ) return; inScroll = TRUE; wxGenericGrid *win = this; bool change = FALSE; if (ev.GetEventObject() == win->GetHorizScrollBar()) { change = (ev.GetPosition() != m_scrollPosX); win->SetScrollPosX(ev.GetPosition()); } else { change = (ev.GetPosition() != m_scrollPosY); win->SetScrollPosY(ev.GetPosition()); } win->UpdateDimensions(); win->SetCurrentRect(win->GetCursorRow(), win->GetCursorColumn()); // Because rows and columns can be arbitrary sizes, // the scrollbars will need to be adjusted to reflect the // current view. AdjustScrollbars(); if (change) win->Refresh(FALSE); inScroll = FALSE; } //---------------------------------------------------------------------- // Default wxGridEvent handlers // (just redirect to the pre-existing virtual methods) void wxGenericGrid::_OnSelectCell(wxGridEvent& ev) { OnSelectCell(ev.m_row, ev.m_col); } void wxGenericGrid::_OnCreateCell(wxGridEvent& ev) { ev.m_cell = OnCreateCell(); } void wxGenericGrid::_OnChangeLabels(wxGridEvent& WXUNUSED(ev)) { OnChangeLabels(); } void wxGenericGrid::_OnChangeSelectionLabel(wxGridEvent& WXUNUSED(ev)) { OnChangeSelectionLabel(); } void wxGenericGrid::_OnCellChange(wxGridEvent& ev) { OnCellChange(ev.m_row, ev.m_col); } void wxGenericGrid::_OnCellLeftClick(wxGridEvent& ev) { OnCellLeftClick(ev.m_row, ev.m_col, ev.m_x, ev.m_y, ev.m_control, ev.m_shift); } void wxGenericGrid::_OnCellRightClick(wxGridEvent& ev) { OnCellRightClick(ev.m_row, ev.m_col, ev.m_x, ev.m_y, ev.m_control, ev.m_shift); } void wxGenericGrid::_OnLabelLeftClick(wxGridEvent& ev) { OnLabelLeftClick(ev.m_row, ev.m_col, ev.m_x, ev.m_y, ev.m_control, ev.m_shift); } void wxGenericGrid::_OnLabelRightClick(wxGridEvent& ev) { OnLabelRightClick(ev.m_row, ev.m_col, ev.m_x, ev.m_y, ev.m_control, ev.m_shift); }