Add support for "activatable" editors to wxGrid
This is useful for editors which don't really need to show any control as they can change their value directly and will be used to reimplement wxGridCellBoolEditor in the upcoming commits.
This commit is contained in:
parent
73532c4d95
commit
3cc3236f10
@ -233,6 +233,130 @@ public:
|
||||
// Smart pointer to wxGridCellRenderer, calling DecRef() on it automatically.
|
||||
typedef wxObjectDataPtr<wxGridCellRenderer> wxGridCellRendererPtr;
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Helper classes used by wxGridCellEditor::TryActivate() and DoActivate().
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// This class represents a source of cell activation, which may be either a
|
||||
// user event (mouse or keyboard) or the program itself.
|
||||
//
|
||||
// Note that objects of this class are supposed to be ephemeral and so store
|
||||
// pointers to the events specified when creating them, which are supposed to
|
||||
// have life-time greater than that of the objects of this class.
|
||||
class wxGridActivationSource
|
||||
{
|
||||
public:
|
||||
enum Origin
|
||||
{
|
||||
Program,
|
||||
Key,
|
||||
Mouse
|
||||
};
|
||||
|
||||
// Factory functions, only used by the library itself.
|
||||
static wxGridActivationSource FromProgram()
|
||||
{
|
||||
return wxGridActivationSource(Program, NULL);
|
||||
}
|
||||
|
||||
static wxGridActivationSource From(const wxKeyEvent& event)
|
||||
{
|
||||
return wxGridActivationSource(Key, &event);
|
||||
}
|
||||
|
||||
static wxGridActivationSource From(const wxMouseEvent& event)
|
||||
{
|
||||
return wxGridActivationSource(Mouse, &event);
|
||||
}
|
||||
|
||||
// Accessors allowing to retrieve information about the source.
|
||||
|
||||
// Can be called for any object.
|
||||
Origin GetOrigin() const { return m_origin; }
|
||||
|
||||
// Can be called for objects with Key origin only.
|
||||
const wxKeyEvent& GetKeyEvent() const
|
||||
{
|
||||
wxASSERT( m_origin == Key );
|
||||
|
||||
return *static_cast<const wxKeyEvent*>(m_event);
|
||||
}
|
||||
|
||||
// Can be called for objects with Mouse origin only.
|
||||
const wxMouseEvent& GetMouseEvent() const
|
||||
{
|
||||
wxASSERT( m_origin == Mouse );
|
||||
|
||||
return *static_cast<const wxMouseEvent*>(m_event);
|
||||
}
|
||||
|
||||
private:
|
||||
wxGridActivationSource(Origin origin, const wxEvent* event)
|
||||
: m_origin(origin),
|
||||
m_event(event)
|
||||
{
|
||||
}
|
||||
|
||||
const Origin m_origin;
|
||||
const wxEvent* const m_event;
|
||||
};
|
||||
|
||||
// This class represents the result of TryActivate(), which may be either
|
||||
// absence of any action (if activating wouldn't change the value anyhow),
|
||||
// attempt to change the value to the specified one or just start normal
|
||||
// editing, which is the default for the editors not supporting activation.
|
||||
class wxGridActivationResult
|
||||
{
|
||||
public:
|
||||
enum Action
|
||||
{
|
||||
Ignore,
|
||||
Change,
|
||||
ShowEditor
|
||||
};
|
||||
|
||||
// Factory functions, only used by the library itself.
|
||||
static wxGridActivationResult DoNothing()
|
||||
{
|
||||
return wxGridActivationResult(Ignore);
|
||||
}
|
||||
|
||||
static wxGridActivationResult DoChange(const wxString& newval)
|
||||
{
|
||||
return wxGridActivationResult(Change, newval);
|
||||
}
|
||||
|
||||
static wxGridActivationResult DoEdit()
|
||||
{
|
||||
return wxGridActivationResult(ShowEditor);
|
||||
}
|
||||
|
||||
// Accessors allowing to retrieve information about the result.
|
||||
|
||||
// Can be called for any object.
|
||||
Action GetAction() const { return m_action; }
|
||||
|
||||
// Can be called for objects with Change action type only.
|
||||
const wxString& GetNewValue() const
|
||||
{
|
||||
wxASSERT( m_action == Change );
|
||||
|
||||
return m_newval;
|
||||
}
|
||||
|
||||
private:
|
||||
explicit
|
||||
wxGridActivationResult(Action action, const wxString& newval = wxString())
|
||||
: m_action(action),
|
||||
m_newval(newval)
|
||||
{
|
||||
}
|
||||
|
||||
const Action m_action;
|
||||
const wxString m_newval;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxGridCellEditor: This class is responsible for providing and manipulating
|
||||
// the in-place edit controls for the grid. Instances of wxGridCellEditor
|
||||
@ -335,6 +459,32 @@ public:
|
||||
wxControl* GetControl() { return wxDynamicCast(m_control, wxControl); }
|
||||
void SetControl(wxControl* control) { m_control = control; }
|
||||
|
||||
|
||||
// Support for "activatable" editors: those change the value of the cell
|
||||
// immediately, instead of creating an editor control and waiting for user
|
||||
// input.
|
||||
//
|
||||
// See wxGridCellBoolEditor for an example of such editor.
|
||||
|
||||
// Override this function to return "Change" activation result from it to
|
||||
// show that the editor supports activation. DoActivate() will be called if
|
||||
// the cell changing event is not vetoed.
|
||||
virtual
|
||||
wxGridActivationResult
|
||||
TryActivate(int WXUNUSED(row), int WXUNUSED(col),
|
||||
wxGrid* WXUNUSED(grid),
|
||||
const wxGridActivationSource& WXUNUSED(actSource))
|
||||
{
|
||||
return wxGridActivationResult::DoEdit();
|
||||
}
|
||||
|
||||
virtual
|
||||
void
|
||||
DoActivate(int WXUNUSED(row), int WXUNUSED(col), wxGrid* WXUNUSED(grid))
|
||||
{
|
||||
wxFAIL_MSG( "Must be overridden if TryActivate() is overridden" );
|
||||
}
|
||||
|
||||
protected:
|
||||
// the dtor is private because only DecRef() can delete us
|
||||
virtual ~wxGridCellEditor();
|
||||
@ -2908,13 +3058,17 @@ private:
|
||||
}
|
||||
|
||||
// Show/hide the cell editor for the current cell unconditionally.
|
||||
void DoShowCellEditControl();
|
||||
|
||||
// Return false if the editor was activated instead of being shown and also
|
||||
// sets m_cellEditCtrlEnabled to true when it returns true as a side effect.
|
||||
bool DoShowCellEditControl(const wxGridActivationSource& actSource);
|
||||
void DoHideCellEditControl();
|
||||
|
||||
// Unconditionally try showing the editor for the current cell.
|
||||
//
|
||||
// Returns false if the user code vetoed wxEVT_GRID_EDITOR_SHOWN.
|
||||
bool DoEnableCellEditControl();
|
||||
// Returns false if the user code vetoed wxEVT_GRID_EDITOR_SHOWN or if the
|
||||
// editor was simply activated and won't be permanently shown.
|
||||
bool DoEnableCellEditControl(const wxGridActivationSource& actSource);
|
||||
|
||||
// Unconditionally disable (accepting the changes) the editor.
|
||||
void DoDisableCellEditControl();
|
||||
|
@ -447,6 +447,97 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Represents a source of cell activation, which may be either a user event
|
||||
(mouse or keyboard) or the program itself.
|
||||
|
||||
An object of this class is passed to wxGridCellEditor::TryActivate() by the
|
||||
library and the code overriding this method may use its GetOrigin() method
|
||||
to determine how exactly the cell is being activated.
|
||||
|
||||
@since 3.1.4
|
||||
*/
|
||||
class wxGridActivationSource
|
||||
{
|
||||
public:
|
||||
/// Result of GetOrigin().
|
||||
enum Origin
|
||||
{
|
||||
/// Activated due to an explicit wxGrid::EnableCellEditControl() call.
|
||||
Program,
|
||||
|
||||
/// Activated due to the user pressing a key, see GetKeyEvent().
|
||||
Key,
|
||||
|
||||
/// Activated due to the user clicking on a cell, see GetMouseEvent().
|
||||
Mouse
|
||||
};
|
||||
|
||||
/// Get the origin of the activation.
|
||||
Origin GetOrigin() const;
|
||||
|
||||
/**
|
||||
Get the key event corresponding to the key press activating the cell.
|
||||
|
||||
This method can be called for objects with Key origin only, use
|
||||
GetOrigin() to check for this first.
|
||||
*/
|
||||
const wxKeyEvent& GetKeyEvent() const;
|
||||
|
||||
/**
|
||||
Get the mouse event corresponding to the click activating the cell.
|
||||
|
||||
This method can be called for objects with Mouse origin only, use
|
||||
GetOrigin() to check for this first.
|
||||
*/
|
||||
const wxMouseEvent& GetMouseEvent() const;
|
||||
};
|
||||
|
||||
/**
|
||||
Represents the result of wxGridCellEditor::TryActivate().
|
||||
|
||||
Editors overriding wxGridCellEditor::TryActivate() must use one of
|
||||
DoNothing(), DoChange() or DoEdit() methods to return an object of this
|
||||
type corresponding to the desired action.
|
||||
|
||||
@since 3.1.4
|
||||
*/
|
||||
class wxGridActivationResult
|
||||
{
|
||||
public:
|
||||
/**
|
||||
Indicate that nothing should be done and the cell shouldn't be edited
|
||||
at all.
|
||||
|
||||
Note that this is different from DoEdit() and may be useful when the
|
||||
value of the cell wouldn't change if it were activated anyhow, e.g.
|
||||
because the key or mouse event carried by wxGridActivationSource would
|
||||
leave the cell value unchanged.
|
||||
*/
|
||||
static wxGridActivationResult DoNothing();
|
||||
|
||||
/**
|
||||
Indicate that activating the cell is possible and would change its
|
||||
value to the given one.
|
||||
|
||||
This is the method to call for activatable editors, using it will
|
||||
result in changing the value of the cell to @a newval without showing
|
||||
the editor control at all.
|
||||
|
||||
Note that the change may still be vetoed by wxEVT_GRID_CELL_CHANGING
|
||||
handler.
|
||||
*/
|
||||
static wxGridActivationResult DoChange(const wxString& newval);
|
||||
|
||||
/**
|
||||
Indicate that the editor control should be shown and the cell should be
|
||||
edited normally.
|
||||
|
||||
This is the default return value of wxGridCellEditor::TryActivate().
|
||||
*/
|
||||
static wxGridActivationResult DoEdit();
|
||||
};
|
||||
|
||||
/**
|
||||
@class wxGridCellEditor
|
||||
|
||||
@ -456,6 +547,12 @@ public:
|
||||
the cell attributes for individual cells, rows, columns, or even for the
|
||||
entire grid.
|
||||
|
||||
Normally wxGridCellEditor shows some UI control allowing the user to edit
|
||||
the cell, but starting with wxWidgets 3.1.4 it's also possible to define
|
||||
"activatable" cell editors, that change the value of the cell directly when
|
||||
it's activated (typically by pressing Space key or clicking on it), see
|
||||
TryActivate() method.
|
||||
|
||||
@library{wxcore}
|
||||
@category{grid}
|
||||
|
||||
@ -627,6 +724,41 @@ public:
|
||||
void SetControl(wxControl* control);
|
||||
|
||||
|
||||
/**
|
||||
Function allowing to create an "activatable" editor.
|
||||
|
||||
As explained in this class description, activatable editors don't show
|
||||
any edit control but change the cell value directly, when it is
|
||||
activated (by any way described by wxGridActivationSource).
|
||||
|
||||
To create such editor, this method must be overridden to return
|
||||
wxGridActivationResult::DoChange() passing it the new value of the
|
||||
cell. If the change is not vetoed by wxEVT_GRID_CELL_CHANGING handler,
|
||||
DoActivate() will be called to actually change the value, so it must be
|
||||
overridden as well if TryActivate() is overridden.
|
||||
|
||||
By default, wxGridActivationResult::DoEdit() is returned, meaning that
|
||||
this is a normal editor, using an edit control for changing the cell
|
||||
value.
|
||||
|
||||
@since 3.1.4
|
||||
*/
|
||||
virtual wxGridActivationResult
|
||||
TryActivate(int row, int col, wxGrid* grid,
|
||||
const wxGridActivationSource& actSource);
|
||||
|
||||
/**
|
||||
Function which must be overridden for "activatable" editors.
|
||||
|
||||
If TryActivate() is overridden to return "change" action, this function
|
||||
will be called to actually apply this change. Note that it is not
|
||||
passed the value to apply, as it is assumed that the editor class
|
||||
stores this value as a member variable anyhow.
|
||||
|
||||
@since 3.1.4
|
||||
*/
|
||||
virtual void DoActivate(int row, int col, wxGrid* grid);
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
|
@ -4664,7 +4664,7 @@ wxGrid::DoGridCellLeftUp(wxMouseEvent& event,
|
||||
{
|
||||
ClearSelection();
|
||||
|
||||
if ( DoEnableCellEditControl() )
|
||||
if ( DoEnableCellEditControl(wxGridActivationSource::From(event)) )
|
||||
GetCurrentCellEditorPtr()->StartingClick();
|
||||
|
||||
m_waitForSlowClick = false;
|
||||
@ -5969,7 +5969,8 @@ void wxGrid::OnChar( wxKeyEvent& event )
|
||||
// ensure cell is visble
|
||||
MakeCellVisible(m_currentCellCoords);
|
||||
|
||||
if ( DoEnableCellEditControl() && !specialEditKey )
|
||||
if ( DoEnableCellEditControl(wxGridActivationSource::From(event))
|
||||
&& !specialEditKey )
|
||||
editor->StartingKey(event);
|
||||
}
|
||||
else
|
||||
@ -7149,7 +7150,7 @@ void wxGrid::EnableCellEditControl( bool enable )
|
||||
// this should be checked by the caller!
|
||||
wxCHECK_RET( CanEnableCellControl(), wxT("can't enable editing for this cell!") );
|
||||
|
||||
DoEnableCellEditControl();
|
||||
DoEnableCellEditControl(wxGridActivationSource::FromProgram());
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -7158,14 +7159,20 @@ void wxGrid::EnableCellEditControl( bool enable )
|
||||
}
|
||||
}
|
||||
|
||||
bool wxGrid::DoEnableCellEditControl()
|
||||
bool wxGrid::DoEnableCellEditControl(const wxGridActivationSource& actSource)
|
||||
{
|
||||
if ( SendEvent(wxEVT_GRID_EDITOR_SHOWN) == -1 )
|
||||
return false;
|
||||
|
||||
m_cellEditCtrlEnabled = true;
|
||||
if ( !DoShowCellEditControl(actSource) )
|
||||
{
|
||||
// We have to send the HIDDEN event matching the SHOWN one above as the
|
||||
// user code may reasonably expect always getting them in pairs, so do
|
||||
// it even if the editor hadn't really been shown at all.
|
||||
SendEvent(wxEVT_GRID_EDITOR_HIDDEN);
|
||||
|
||||
DoShowCellEditControl();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -7217,16 +7224,57 @@ void wxGrid::ShowCellEditControl()
|
||||
return;
|
||||
}
|
||||
|
||||
DoShowCellEditControl();
|
||||
DoShowCellEditControl(wxGridActivationSource::FromProgram());
|
||||
}
|
||||
}
|
||||
|
||||
void wxGrid::DoShowCellEditControl()
|
||||
bool wxGrid::DoShowCellEditControl(const wxGridActivationSource& actSource)
|
||||
{
|
||||
wxRect rect = CellToRect( m_currentCellCoords );
|
||||
int row = m_currentCellCoords.GetRow();
|
||||
int col = m_currentCellCoords.GetCol();
|
||||
|
||||
wxGridCellAttrPtr attr = GetCellAttrPtr(row, col);
|
||||
wxGridCellEditorPtr editor = attr->GetEditorPtr(this, row, col);
|
||||
|
||||
const wxGridActivationResult&
|
||||
res = editor->TryActivate(row, col, this, actSource);
|
||||
switch ( res.GetAction() )
|
||||
{
|
||||
case wxGridActivationResult::Change:
|
||||
// This is somewhat similar to what DoSaveEditControlValue() does.
|
||||
// but we don't allow vetoing CHANGED event here as this code is
|
||||
// new and shouldn't have to support this obsolete usage.
|
||||
if ( SendEvent(wxEVT_GRID_CELL_CHANGING, res.GetNewValue()) != -1 )
|
||||
{
|
||||
const wxString& oldval = GetCellValue(m_currentCellCoords);
|
||||
|
||||
editor->DoActivate(row, col, this);
|
||||
|
||||
// Show the new cell value.
|
||||
RefreshBlock(m_currentCellCoords, m_currentCellCoords);
|
||||
|
||||
if ( SendEvent(wxEVT_GRID_CELL_CHANGED, oldval) == -1 )
|
||||
{
|
||||
wxFAIL_MSG( "Vetoing wxEVT_GRID_CELL_CHANGED is ignored" );
|
||||
}
|
||||
}
|
||||
wxFALLTHROUGH;
|
||||
|
||||
case wxGridActivationResult::Ignore:
|
||||
// In any case, don't start editing normally.
|
||||
return false;
|
||||
|
||||
case wxGridActivationResult::ShowEditor:
|
||||
// Continue normally.
|
||||
break;
|
||||
}
|
||||
|
||||
// It's not enabled just yet, but will be soon, and we need to set it
|
||||
// before generating any events in case their user-defined handlers decide
|
||||
// to call EnableCellEditControl() to avoid reentrancy problems.
|
||||
m_cellEditCtrlEnabled = true;
|
||||
|
||||
wxGridWindow *gridWindow = CellToGridWindow(row, col);
|
||||
|
||||
// if this is part of a multicell, find owner (topleft)
|
||||
@ -7251,8 +7299,6 @@ void wxGrid::DoShowCellEditControl()
|
||||
rect.Deflate(1, 1);
|
||||
#endif
|
||||
|
||||
wxGridCellAttrPtr attr = GetCellAttrPtr(row, col);
|
||||
wxGridCellEditorPtr editor = attr->GetEditorPtr(this, row, col);
|
||||
if ( !editor->IsCreated() )
|
||||
{
|
||||
editor->Create(gridWindow, wxID_ANY,
|
||||
@ -7348,6 +7394,8 @@ void wxGrid::DoShowCellEditControl()
|
||||
|
||||
editor->BeginEdit(row, col, this);
|
||||
editor->SetCellAttr(NULL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void wxGrid::HideCellEditControl()
|
||||
|
Loading…
Reference in New Issue
Block a user