grid.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 2,252 行 · 第 1/5 页
CPP
2,252 行
wxASSERT_MSG(m_control,
wxT("The wxGridCellEditor must be Created first!"));
CBox()->SetValue(m_startValue);
}
void wxGridCellBoolEditor::StartingClick()
{
CBox()->SetValue(!CBox()->GetValue());
}
bool wxGridCellBoolEditor::IsAcceptedKey(wxKeyEvent& event)
{
if ( wxGridCellEditor::IsAcceptedKey(event) )
{
int keycode = event.GetKeyCode();
switch ( keycode )
{
case WXK_SPACE:
case '+':
case '-':
return true;
}
}
return false;
}
void wxGridCellBoolEditor::StartingKey(wxKeyEvent& event)
{
int keycode = event.GetKeyCode();
switch ( keycode )
{
case WXK_SPACE:
CBox()->SetValue(!CBox()->GetValue());
break;
case '+':
CBox()->SetValue(true);
break;
case '-':
CBox()->SetValue(false);
break;
}
}
// return the value as "1" for true and the empty string for false
wxString wxGridCellBoolEditor::GetValue() const
{
bool bSet = CBox()->GetValue();
return bSet ? _T("1") : wxEmptyString;
}
#endif // wxUSE_CHECKBOX
#if wxUSE_COMBOBOX
// ----------------------------------------------------------------------------
// wxGridCellChoiceEditor
// ----------------------------------------------------------------------------
wxGridCellChoiceEditor::wxGridCellChoiceEditor(const wxArrayString& choices,
bool allowOthers)
: m_choices(choices),
m_allowOthers(allowOthers) { }
wxGridCellChoiceEditor::wxGridCellChoiceEditor(size_t count,
const wxString choices[],
bool allowOthers)
: m_allowOthers(allowOthers)
{
if ( count )
{
m_choices.Alloc(count);
for ( size_t n = 0; n < count; n++ )
{
m_choices.Add(choices[n]);
}
}
}
wxGridCellEditor *wxGridCellChoiceEditor::Clone() const
{
wxGridCellChoiceEditor *editor = new wxGridCellChoiceEditor;
editor->m_allowOthers = m_allowOthers;
editor->m_choices = m_choices;
return editor;
}
void wxGridCellChoiceEditor::Create(wxWindow* parent,
wxWindowID id,
wxEvtHandler* evtHandler)
{
m_control = new wxComboBox(parent, id, wxEmptyString,
wxDefaultPosition, wxDefaultSize,
m_choices,
m_allowOthers ? 0 : wxCB_READONLY);
wxGridCellEditor::Create(parent, id, evtHandler);
}
void wxGridCellChoiceEditor::PaintBackground(const wxRect& rectCell,
wxGridCellAttr * attr)
{
// as we fill the entire client area, don't do anything here to minimize
// flicker
// TODO: It doesn't actually fill the client area since the height of a
// combo always defaults to the standard... Until someone has time to
// figure out the right rectangle to paint, just do it the normal way...
wxGridCellEditor::PaintBackground(rectCell, attr);
}
void wxGridCellChoiceEditor::BeginEdit(int row, int col, wxGrid* grid)
{
wxASSERT_MSG(m_control,
wxT("The wxGridCellEditor must be Created first!"));
wxGridCellEditorEvtHandler* evtHandler = NULL;
if (m_control)
evtHandler = wxDynamicCast(m_control->GetEventHandler(), wxGridCellEditorEvtHandler);
// Don't immediately end if we get a kill focus event within BeginEdit
if (evtHandler)
evtHandler->SetInSetFocus(true);
m_startValue = grid->GetTable()->GetValue(row, col);
if (m_allowOthers)
Combo()->SetValue(m_startValue);
else
{
// find the right position, or default to the first if not found
int pos = Combo()->FindString(m_startValue);
if (pos == wxNOT_FOUND)
pos = 0;
Combo()->SetSelection(pos);
}
Combo()->SetInsertionPointEnd();
Combo()->SetFocus();
if (evtHandler)
{
// When dropping down the menu, a kill focus event
// happens after this point, so we can't reset the flag yet.
#if !defined(__WXGTK20__)
evtHandler->SetInSetFocus(false);
#endif
}
}
bool wxGridCellChoiceEditor::EndEdit(int row, int col,
wxGrid* grid)
{
wxString value = Combo()->GetValue();
if ( value == m_startValue )
return false;
grid->GetTable()->SetValue(row, col, value);
return true;
}
void wxGridCellChoiceEditor::Reset()
{
Combo()->SetValue(m_startValue);
Combo()->SetInsertionPointEnd();
}
void wxGridCellChoiceEditor::SetParameters(const wxString& params)
{
if ( !params )
{
// what can we do?
return;
}
m_choices.Empty();
wxStringTokenizer tk(params, _T(','));
while ( tk.HasMoreTokens() )
{
m_choices.Add(tk.GetNextToken());
}
}
// return the value in the text control
wxString wxGridCellChoiceEditor::GetValue() const
{
return Combo()->GetValue();
}
#endif // wxUSE_COMBOBOX
// ----------------------------------------------------------------------------
// wxGridCellEditorEvtHandler
// ----------------------------------------------------------------------------
void wxGridCellEditorEvtHandler::OnKillFocus(wxFocusEvent& event)
{
// Don't disable the cell if we're just starting to edit it
if (m_inSetFocus)
return;
// accept changes
m_grid->DisableCellEditControl();
event.Skip();
}
void wxGridCellEditorEvtHandler::OnKeyDown(wxKeyEvent& event)
{
switch ( event.GetKeyCode() )
{
case WXK_ESCAPE:
m_editor->Reset();
m_grid->DisableCellEditControl();
break;
case WXK_TAB:
m_grid->GetEventHandler()->ProcessEvent( event );
break;
case WXK_RETURN:
case WXK_NUMPAD_ENTER:
if (!m_grid->GetEventHandler()->ProcessEvent(event))
m_editor->HandleReturn(event);
break;
default:
event.Skip();
}
}
void wxGridCellEditorEvtHandler::OnChar(wxKeyEvent& event)
{
switch ( event.GetKeyCode() )
{
case WXK_ESCAPE:
case WXK_TAB:
case WXK_RETURN:
case WXK_NUMPAD_ENTER:
break;
default:
event.Skip();
}
}
// ----------------------------------------------------------------------------
// wxGridCellWorker is an (almost) empty common base class for
// wxGridCellRenderer and wxGridCellEditor managing ref counting
// ----------------------------------------------------------------------------
void wxGridCellWorker::SetParameters(const wxString& WXUNUSED(params))
{
// nothing to do
}
wxGridCellWorker::~wxGridCellWorker()
{
}
// ============================================================================
// renderer classes
// ============================================================================
// ----------------------------------------------------------------------------
// wxGridCellRenderer
// ----------------------------------------------------------------------------
void wxGridCellRenderer::Draw(wxGrid& grid,
wxGridCellAttr& attr,
wxDC& dc,
const wxRect& rect,
int WXUNUSED(row), int WXUNUSED(col),
bool isSelected)
{
dc.SetBackgroundMode( wxSOLID );
// grey out fields if the grid is disabled
if( grid.IsEnabled() )
{
if ( isSelected )
{
dc.SetBrush( wxBrush(grid.GetSelectionBackground(), wxSOLID) );
}
else
{
dc.SetBrush( wxBrush(attr.GetBackgroundColour(), wxSOLID) );
}
}
else
{
dc.SetBrush(wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE), wxSOLID));
}
dc.SetPen( *wxTRANSPARENT_PEN );
dc.DrawRectangle(rect);
}
// ----------------------------------------------------------------------------
// wxGridCellStringRenderer
// ----------------------------------------------------------------------------
void wxGridCellStringRenderer::SetTextColoursAndFont(wxGrid& grid,
wxGridCellAttr& attr,
wxDC& dc,
bool isSelected)
{
dc.SetBackgroundMode( wxTRANSPARENT );
// TODO some special colours for attr.IsReadOnly() case?
// different coloured text when the grid is disabled
if( grid.IsEnabled() )
{
if ( isSelected )
{
dc.SetTextBackground( grid.GetSelectionBackground() );
dc.SetTextForeground( grid.GetSelectionForeground() );
}
else
{
dc.SetTextBackground( attr.GetBackgroundColour() );
dc.SetTextForeground( attr.GetTextColour() );
}
}
else
{
dc.SetTextBackground(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
dc.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT));
}
dc.SetFont( attr.GetFont() );
}
wxSize wxGridCellStringRenderer::DoGetBestSize(wxGridCellAttr& attr,
wxDC& dc,
const wxString& text)
{
wxCoord x = 0, y = 0, max_x = 0;
dc.SetFont(attr.GetFont());
wxStringTokenizer tk(text, _T('\n'));
while ( tk.HasMoreTokens() )
{
dc.GetTextExtent(tk.GetNextToken(), &x, &y);
max_x = wxMax(max_x, x);
}
y *= 1 + text.Freq(wxT('\n')); // multiply by the number of lines.
return wxSize(max_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,
const wxRect& rectCell,
int row, int col,
bool isSelected)
{
wxRect rect = rectCell;
rect.Inflate(-1);
// erase only this cells background, overflow cells should have been erased
wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
int hAlign, vAlign;
attr.GetAlignment(&hAlign, &vAlign);
int overflowCols = 0;
if (attr.GetOverflow())
{
int cols = grid.GetNumberCols();
int best_width = GetBestSize(grid,attr,dc,row,col).GetWidth();
int cell_rows, cell_cols;
attr.GetSize( &cell_rows, &cell_cols ); // shouldn't get here if <=0
if ((best_width > rectCell.width) && (col < cols) && grid.GetTable())
{
int i, c_cols, c_rows;
for (i = col+cell_cols; i < cols; i++)
{
bool is_empty = true;
for (int j=row; j<row+cell_rows; j++)
{
// check w/ anchor cell for multicell block
grid.GetCellSize(j, i, &c_rows, &c_cols);
if (c_rows > 0) c_rows = 0;
if (!grid.GetTable()->IsEmptyCell(j+c_rows, i))
{
is_empty = false;
break;
}
}
if (is_empty)
rect.width += grid.GetColSize(i);
else
{
i--;
break;
}
if (rect.width >= best_width) break;
}
overflowCols = i - col - cell_cols + 1;
if (overflowCols >= cols) overflowCols = cols - 1;
}
if (overflowCols > 0) // redraw overflow cells w/ proper hilight
{
hAlign = wxALIGN_LEFT; // if oveflowed then it's left aligned
wxRect clip = rect;
clip.x += rectCell.width;
// draw each overflow cell individually
int col_end = col+cell_cols+overflowCols;
if (col_end >= grid.GetNumberCols())
col_end = grid.GetNumberCols() - 1;
for (int i = col+cell_cols; i <= col_end; i++)
{
clip.width = grid.GetColSize(i) - 1;
dc.DestroyClippingRegion();
dc.SetClippingRegion(clip);
SetTextColoursAndFont(grid, attr, dc,
grid.IsInSelection(row,i));
grid.DrawTextRectangle(dc, grid.GetCellValue(row, col),
rect, hAlign, vAlign);
clip.x += grid.GetColSize(i) - 1;
}
rect = rectCell;
rect.Inflate(-1);
rect.width++;
dc.DestroyClippingRegion();
}
}
// now we only have to draw the text
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?