X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/816be743e86d10387376fa87ddb2fc684eb1efd3..2912e35f1774b140b44cb9f9568aa5ab8122cd02:/src/generic/grid.cpp diff --git a/src/generic/grid.cpp b/src/generic/grid.cpp index d728ad8407..dd06aeda0b 100644 --- a/src/generic/grid.cpp +++ b/src/generic/grid.cpp @@ -41,6 +41,7 @@ #include "wx/log.h" #include "wx/textctrl.h" #include "wx/checkbox.h" + #include "wx/combobox.h" #include "wx/valtext.h" #endif @@ -858,6 +859,84 @@ void wxGridCellBoolEditor::StartingClick() CBox()->SetValue(!CBox()->GetValue()); } +// ---------------------------------------------------------------------------- +// wxGridCellChoiceEditor +// ---------------------------------------------------------------------------- + +wxGridCellChoiceEditor::wxGridCellChoiceEditor(size_t count, + const wxChar* choices[], + bool allowOthers) + : m_allowOthers(allowOthers) +{ + m_choices.Alloc(count); + for ( size_t n = 0; n < count; n++ ) + { + m_choices.Add(choices[n]); + } +} + +void wxGridCellChoiceEditor::Create(wxWindow* parent, + wxWindowID id, + wxEvtHandler* evtHandler) +{ + size_t count = m_choices.GetCount(); + wxString *choices = new wxString[count]; + for ( size_t n = 0; n < count; n++ ) + { + choices[n] = m_choices[n]; + } + + m_control = new wxComboBox(parent, id, wxEmptyString, + wxDefaultPosition, wxDefaultSize, + count, choices, + m_allowOthers ? 0 : wxCB_READONLY); + + delete [] choices; + + wxGridCellEditor::Create(parent, id, evtHandler); +} + +void wxGridCellChoiceEditor::PaintBackground(const wxRect& WXUNUSED(rectCell), + wxGridCellAttr * WXUNUSED(attr)) +{ + // as we fill the entire client area, don't do anything here to minimize + // flicker +} + +void wxGridCellChoiceEditor::BeginEdit(int row, int col, wxGrid* grid) +{ + wxASSERT_MSG(m_control, + wxT("The wxGridCellEditor must be Created first!")); + + m_startValue = grid->GetTable()->GetValue(row, col); + + Combo()->SetValue(m_startValue); + Combo()->SetInsertionPointEnd(); + Combo()->SetFocus(); +} + +bool wxGridCellChoiceEditor::EndEdit(int row, int col, + bool saveValue, + wxGrid* grid) +{ + wxString value = Combo()->GetValue(); + bool changed = value != m_startValue; + + if ( changed ) + grid->GetTable()->SetValue(row, col, value); + + m_startValue = wxEmptyString; + Combo()->SetValue(m_startValue); + + return changed; +} + +void wxGridCellChoiceEditor::Reset() +{ + Combo()->SetValue(m_startValue); + Combo()->SetInsertionPointEnd(); +} + // ---------------------------------------------------------------------------- // wxGridCellEditorEvtHandler // ---------------------------------------------------------------------------- @@ -961,6 +1040,25 @@ void wxGridCellStringRenderer::SetTextColoursAndFont(wxGrid& grid, dc.SetFont( attr.GetFont() ); } +wxSize wxGridCellStringRenderer::DoGetBestSize(wxGridCellAttr& attr, + wxDC& dc, + const wxString& text) +{ + wxCoord x, y; + dc.SetFont(attr.GetFont()); + dc.GetTextExtent(text, &x, &y); + + return wxSize(x, y); +} + +wxSize wxGridCellStringRenderer::GetBestSize(wxGrid& grid, + wxGridCellAttr& attr, + wxDC& dc, + int row, int col) +{ + return DoGetBestSize(attr, dc, grid.GetCellValue(row, col)); +} + void wxGridCellStringRenderer::Draw(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc, @@ -983,6 +1081,23 @@ void wxGridCellStringRenderer::Draw(wxGrid& grid, rect, hAlign, vAlign); } +// ---------------------------------------------------------------------------- +// wxGridCellNumberRenderer +// ---------------------------------------------------------------------------- + +wxString wxGridCellNumberRenderer::GetString(wxGrid& grid, int row, int col) +{ + wxGridTableBase *table = grid.GetTable(); + wxString text; + if ( table->CanGetValueAs(row, col, wxGRID_VALUE_NUMBER) ) + { + text.Printf(_T("%ld"), table->GetValueAsLong(row, col)); + } + //else: leave the string empty or put 0 into it? + + return text; +} + void wxGridCellNumberRenderer::Draw(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc, @@ -1002,15 +1117,15 @@ void wxGridCellNumberRenderer::Draw(wxGrid& grid, wxRect rect = rectCell; rect.Inflate(-1); - wxGridTableBase *table = grid.GetTable(); - wxString text; - if ( table->CanGetValueAs(row, col, wxGRID_VALUE_NUMBER) ) - { - text.Printf(_T("%ld"), table->GetValueAsLong(row, col)); - } - //else: leave the string empty or put 0 into it? + grid.DrawTextRectangle(dc, GetString(grid, row, col), rect, hAlign, vAlign); +} - grid.DrawTextRectangle(dc, text, rect, hAlign, vAlign); +wxSize wxGridCellNumberRenderer::GetBestSize(wxGrid& grid, + wxGridCellAttr& attr, + wxDC& dc, + int row, int col) +{ + return DoGetBestSize(attr, dc, GetString(grid, row, col)); } // ---------------------------------------------------------------------------- @@ -1023,6 +1138,24 @@ wxGridCellFloatRenderer::wxGridCellFloatRenderer(int width, int precision) SetPrecision(precision); } +wxString wxGridCellFloatRenderer::GetString(wxGrid& grid, int row, int col) +{ + wxGridTableBase *table = grid.GetTable(); + wxString text; + if ( table->CanGetValueAs(row, col, wxGRID_VALUE_FLOAT) ) + { + if ( !m_format ) + { + m_format.Printf(_T("%%%d.%d%%f"), m_width, m_precision); + } + + text.Printf(m_format, table->GetValueAsDouble(row, col)); + } + //else: leave the string empty or put 0 into it? + + return text; +} + void wxGridCellFloatRenderer::Draw(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc, @@ -1042,66 +1175,76 @@ void wxGridCellFloatRenderer::Draw(wxGrid& grid, wxRect rect = rectCell; rect.Inflate(-1); - wxGridTableBase *table = grid.GetTable(); - wxString text; - if ( table->CanGetValueAs(row, col, wxGRID_VALUE_FLOAT) ) - { - if ( !m_format ) - { - m_format.Printf(_T("%%%d.%d%%f"), m_width, m_precision); - } - - text.Printf(m_format, table->GetValueAsDouble(row, col)); - } - //else: leave the string empty or put 0 into it? + grid.DrawTextRectangle(dc, GetString(grid, row, col), rect, hAlign, vAlign); +} - grid.DrawTextRectangle(dc, text, rect, hAlign, vAlign); +wxSize wxGridCellFloatRenderer::GetBestSize(wxGrid& grid, + wxGridCellAttr& attr, + wxDC& dc, + int row, int col) +{ + return DoGetBestSize(attr, dc, GetString(grid, row, col)); } // ---------------------------------------------------------------------------- // wxGridCellBoolRenderer // ---------------------------------------------------------------------------- -void wxGridCellBoolRenderer::Draw(wxGrid& grid, - wxGridCellAttr& attr, - wxDC& dc, - const wxRect& rect, - int row, int col, - bool isSelected) -{ - wxGridCellRenderer::Draw(grid, attr, dc, rect, row, col, isSelected); +wxSize wxGridCellBoolRenderer::ms_sizeCheckMark; - // between checkmark and box - static const wxCoord margin = 4; +// between checkmark and box +static const wxCoord wxGRID_CHECKMARK_MARGIN = 4; - // get checkbox size - static wxCoord s_checkSize = 0; - if ( s_checkSize == 0 ) +wxSize wxGridCellBoolRenderer::GetBestSize(wxGrid& grid, + wxGridCellAttr& WXUNUSED(attr), + wxDC& WXUNUSED(dc), + int WXUNUSED(row), + int WXUNUSED(col)) +{ + // compute it only once (no locks for MT safeness in GUI thread...) + if ( !ms_sizeCheckMark.x ) { - // compute it only once (no locks for MT safeness in GUI thread...) + // get checkbox size + wxCoord checkSize = 0; wxCheckBox *checkbox = new wxCheckBox(&grid, -1, wxEmptyString); wxSize size = checkbox->GetBestSize(); - s_checkSize = size.y + margin; + checkSize = size.y + wxGRID_CHECKMARK_MARGIN; - // FIXME wxGTK::wxCheckBox::GetBestSize() is really weird... + // FIXME wxGTK::wxCheckBox::GetBestSize() gives "wrong" result #ifdef __WXGTK__ - s_checkSize -= size.y / 2; + checkSize -= size.y / 2; #endif delete checkbox; + + ms_sizeCheckMark.x = ms_sizeCheckMark.y = checkSize; } + return ms_sizeCheckMark; +} + +void wxGridCellBoolRenderer::Draw(wxGrid& grid, + wxGridCellAttr& attr, + wxDC& dc, + const wxRect& rect, + int row, int col, + bool isSelected) +{ + wxGridCellRenderer::Draw(grid, attr, dc, rect, row, col, isSelected); + // draw a check mark in the centre (ignoring alignment - TODO) + wxSize size = GetBestSize(grid, attr, dc, row, col); wxRect rectMark; - rectMark.x = rect.x + rect.width/2 - s_checkSize/2; - rectMark.y = rect.y + rect.height/2 - s_checkSize/2; - rectMark.width = rectMark.height = s_checkSize; + rectMark.x = rect.x + rect.width/2 - size.x/2; + rectMark.y = rect.y + rect.height/2 - size.y/2; + rectMark.width = size.x; + rectMark.height = size.y; dc.SetBrush(*wxTRANSPARENT_BRUSH); dc.SetPen(wxPen(attr.GetTextColour(), 1, wxSOLID)); dc.DrawRectangle(rectMark); - rectMark.Inflate(-margin); + rectMark.Inflate(-wxGRID_CHECKMARK_MARGIN); bool value; if (grid.GetTable()->CanGetValueAs(row, col, wxT("bool"))) @@ -5299,7 +5442,7 @@ int wxGrid::YToRow( int y ) return i; } - return m_numRows; //-1; + return -1; } @@ -5313,7 +5456,7 @@ int wxGrid::XToCol( int x ) return i; } - return m_numCols; //-1; + return -1; } @@ -6599,6 +6742,62 @@ int wxGrid::GetColMinimalWidth(int col) const return obj ? (int)obj : WXGRID_MIN_COL_WIDTH; } +void wxGrid::AutoSizeColumn( int col, bool setAsMin ) +{ + wxClientDC dc(m_gridWin); + + wxCoord width, widthMax = 0; + for ( int row = 0; row < m_numRows; row++ ) + { + wxGridCellAttr* attr = GetCellAttr(row, col); + wxGridCellRenderer* renderer = attr->GetRenderer(GetDefaultRendererForCell(row,col)); + if ( renderer ) + { + width = renderer->GetBestSize(*this, *attr, dc, row, col).x; + if ( width > widthMax ) + { + widthMax = width; + } + } + + attr->DecRef(); + } + + // now also compare with the column label width + dc.SetFont( GetLabelFont() ); + dc.GetTextExtent( GetColLabelValue(col), &width, NULL ); + if ( width > widthMax ) + { + widthMax = width; + } + + if ( !widthMax ) + { + // empty column - give default width (notice that if widthMax is less + // than default width but != 0, it's ok) + widthMax = m_defaultColWidth; + } + else + { + // leave some space around text + widthMax += 10; + } + + SetColSize(col, widthMax); + if ( setAsMin ) + { + SetColMinimalWidth(col, widthMax); + } +} + +void wxGrid::AutoSizeColumns( bool setAsMin ) +{ + for ( int col = 0; col < m_numCols; col++ ) + { + AutoSizeColumn(col, setAsMin); + } +} + // // ------ cell value accessor functions //