Merge miscellaneous wxDataViewCtrl-related bug fixes
Make it possible to define custom renderers using text controls reacting to error presses in at least wxMSW and wxGTK. Closes https://github.com/wxWidgets/wxWidgets/pull/221
This commit is contained in:
@@ -180,6 +180,9 @@ public:
|
||||
// wxDVR_DEFAULT_ALIGNMENT.
|
||||
int GetEffectiveAlignment() const;
|
||||
|
||||
// Send wxEVT_DATAVIEW_ITEM_EDITING_STARTED event.
|
||||
void NotifyEditingStarted(const wxDataViewItem& item);
|
||||
|
||||
protected:
|
||||
// These methods are called from PrepareForItem() and should do whatever is
|
||||
// needed for the current platform to ensure that the item is rendered
|
||||
@@ -199,7 +202,7 @@ protected:
|
||||
wxString m_variantType;
|
||||
wxDataViewColumn *m_owner;
|
||||
wxWeakRef<wxWindow> m_editorCtrl;
|
||||
wxDataViewItem m_item; // for m_editorCtrl
|
||||
wxDataViewItem m_item; // Item being currently edited, if valid.
|
||||
|
||||
// internal utility, may be used anywhere the window associated with the
|
||||
// renderer is required
|
||||
|
@@ -3671,6 +3671,15 @@ protected:
|
||||
virtual bool TryParent(wxEvent& event), return DoTryApp(event); )
|
||||
#endif // WXWIN_COMPATIBILITY_2_8
|
||||
|
||||
// Overriding this method allows filtering the event handlers dynamically
|
||||
// connected to this object. If this method returns false, the handler is
|
||||
// not connected at all. If it returns true, it is connected using the
|
||||
// possibly modified fields of the given entry.
|
||||
virtual bool OnDynamicBind(wxDynamicEventTableEntry& WXUNUSED(entry))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static const wxEventTable sm_eventTable;
|
||||
virtual const wxEventTable *GetEventTable() const;
|
||||
|
@@ -181,7 +181,10 @@ public:
|
||||
void OnSetFocus(wxFocusEvent& event);
|
||||
|
||||
// intercept WM_GETDLGCODE
|
||||
virtual WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam);
|
||||
virtual bool MSWHandleMessage(WXLRESULT *result,
|
||||
WXUINT message,
|
||||
WXWPARAM wParam,
|
||||
WXLPARAM lParam);
|
||||
|
||||
virtual bool MSWShouldPreProcessMessage(WXMSG* pMsg);
|
||||
virtual WXDWORD MSWGetStyle(long style, WXDWORD *exstyle) const;
|
||||
|
@@ -14,6 +14,8 @@
|
||||
|
||||
#include "wx/settings.h" // solely for wxSystemColour
|
||||
|
||||
class WXDLLIMPEXP_FWD_CORE wxButton;
|
||||
|
||||
// if this is set to 1, we use deferred window sizing to reduce flicker when
|
||||
// resizing complicated window hierarchies, but this can in theory result in
|
||||
// different behaviour than the old code so we keep the possibility to use it
|
||||
@@ -534,6 +536,16 @@ public:
|
||||
virtual wxMenu* MSWFindMenuFromHMENU(WXHMENU hMenu);
|
||||
#endif // wxUSE_MENUS && !__WXUNIVERSAL__
|
||||
|
||||
// Return the default button for the TLW containing this window or NULL if
|
||||
// none.
|
||||
static wxButton* MSWGetDefaultButtonFor(wxWindow* win);
|
||||
|
||||
// Simulate a click on the given button if it is non-null, enabled and
|
||||
// shown.
|
||||
//
|
||||
// Return true if the button was clicked, false otherwise.
|
||||
static bool MSWClickButtonIfPossible(wxButton* btn);
|
||||
|
||||
protected:
|
||||
// this allows you to implement standard control borders without
|
||||
// repeating the code in different classes that are not derived from
|
||||
|
@@ -743,6 +743,11 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
// Override wxEvtHandler method to check for a common problem of binding
|
||||
// wxEVT_TEXT_ENTER to a control without wxTE_PROCESS_ENTER style, which is
|
||||
// never going to work.
|
||||
virtual bool OnDynamicBind(wxDynamicEventTableEntry& entry);
|
||||
|
||||
// override streambuf method
|
||||
#if wxHAS_TEXT_WINDOW_STREAM
|
||||
int overflow(int i) wxOVERRIDE;
|
||||
|
@@ -173,10 +173,12 @@ private:
|
||||
class MyCustomRenderer: public wxDataViewCustomRenderer
|
||||
{
|
||||
public:
|
||||
MyCustomRenderer()
|
||||
: wxDataViewCustomRenderer("string",
|
||||
wxDATAVIEW_CELL_ACTIVATABLE,
|
||||
wxALIGN_CENTER)
|
||||
// This renderer can be either activatable or editable, for demonstration
|
||||
// purposes. In real programs, you should select whether the user should be
|
||||
// able to activate or edit the cell and it doesn't make sense to switch
|
||||
// between the two -- but this is just an example, so it doesn't stop us.
|
||||
explicit MyCustomRenderer(wxDataViewCellMode mode)
|
||||
: wxDataViewCustomRenderer("string", mode, wxALIGN_CENTER)
|
||||
{ }
|
||||
|
||||
virtual bool Render( wxRect rect, wxDC *dc, int state ) wxOVERRIDE
|
||||
@@ -223,6 +225,34 @@ public:
|
||||
|
||||
virtual bool GetValue( wxVariant &WXUNUSED(value) ) const wxOVERRIDE { return true; }
|
||||
|
||||
virtual bool HasEditorCtrl() const wxOVERRIDE { return true; }
|
||||
|
||||
virtual wxWindow*
|
||||
CreateEditorCtrl(wxWindow* parent,
|
||||
wxRect labelRect,
|
||||
const wxVariant& value) wxOVERRIDE
|
||||
{
|
||||
wxTextCtrl* text = new wxTextCtrl(parent, wxID_ANY, value,
|
||||
labelRect.GetPosition(),
|
||||
labelRect.GetSize(),
|
||||
wxTE_PROCESS_ENTER);
|
||||
text->SetInsertionPointEnd();
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
virtual bool
|
||||
GetValueFromEditorCtrl(wxWindow* ctrl, wxVariant& value) wxOVERRIDE
|
||||
{
|
||||
wxTextCtrl* text = wxDynamicCast(ctrl, wxTextCtrl);
|
||||
if ( !text )
|
||||
return false;
|
||||
|
||||
value = text->GetValue();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
wxString m_value;
|
||||
};
|
||||
@@ -614,7 +644,7 @@ void MyFrame::BuildDataViewCtrl(wxPanel* parent, unsigned int nPanel, unsigned l
|
||||
|
||||
// column 5 of the view control:
|
||||
|
||||
MyCustomRenderer *cr = new MyCustomRenderer;
|
||||
MyCustomRenderer *cr = new MyCustomRenderer(wxDATAVIEW_CELL_ACTIVATABLE);
|
||||
wxDataViewColumn *column5 =
|
||||
new wxDataViewColumn( "custom", cr, 5, -1, wxALIGN_LEFT,
|
||||
wxDATAVIEW_COL_RESIZABLE );
|
||||
@@ -662,7 +692,7 @@ void MyFrame::BuildDataViewCtrl(wxPanel* parent, unsigned int nPanel, unsigned l
|
||||
|
||||
m_ctrl[1]->AppendColumn(
|
||||
new wxDataViewColumn("custom renderer",
|
||||
new MyCustomRenderer,
|
||||
new MyCustomRenderer(wxDATAVIEW_CELL_EDITABLE),
|
||||
MyListModel::Col_Custom)
|
||||
);
|
||||
}
|
||||
|
@@ -444,7 +444,13 @@ void MyListModel::GetValueByRow( wxVariant &variant,
|
||||
break;
|
||||
|
||||
case Col_Custom:
|
||||
variant = wxString::Format("%d", row % 100);
|
||||
{
|
||||
IntToStringMap::const_iterator it = m_customColValues.find(row);
|
||||
if ( it != m_customColValues.end() )
|
||||
variant = it->second;
|
||||
else
|
||||
variant = wxString::Format("%d", row % 100);
|
||||
}
|
||||
break;
|
||||
|
||||
case Col_Max:
|
||||
@@ -531,10 +537,13 @@ bool MyListModel::SetValueByRow( const wxVariant &variant,
|
||||
|
||||
case Col_Date:
|
||||
case Col_TextWithAttr:
|
||||
case Col_Custom:
|
||||
wxLogError("Cannot edit the column %d", col);
|
||||
break;
|
||||
|
||||
case Col_Custom:
|
||||
m_customColValues[row] = variant.GetString();
|
||||
break;
|
||||
|
||||
case Col_Max:
|
||||
wxFAIL_MSG( "invalid column" );
|
||||
}
|
||||
|
@@ -8,6 +8,10 @@
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "wx/hashmap.h"
|
||||
|
||||
WX_DECLARE_HASH_MAP(unsigned, wxString, wxIntegerHash, wxIntegerEqual,
|
||||
IntToStringMap);
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// MyMusicTreeModelNode: a node inside MyMusicTreeModel
|
||||
@@ -235,6 +239,7 @@ public:
|
||||
private:
|
||||
wxArrayString m_textColValues;
|
||||
wxArrayString m_iconColValues;
|
||||
IntToStringMap m_customColValues;
|
||||
wxIcon m_icon[2];
|
||||
};
|
||||
|
||||
|
@@ -2603,7 +2603,14 @@ void TestDefaultActionDialog::OnCatchListBoxDClick(wxCommandEvent& WXUNUSED(even
|
||||
|
||||
void TestDefaultActionDialog::OnTextEnter(wxCommandEvent& event)
|
||||
{
|
||||
wxLogMessage("Text \"%s\" entered.", event.GetString());
|
||||
const wxString& text = event.GetString();
|
||||
if ( text.empty() )
|
||||
{
|
||||
event.Skip();
|
||||
return;
|
||||
}
|
||||
|
||||
wxLogMessage("Text \"%s\" entered.", text);
|
||||
}
|
||||
|
||||
void MyFrame::OnTestDefaultActionDialog(wxCommandEvent& WXUNUSED(event))
|
||||
|
@@ -681,8 +681,6 @@ bool wxDataViewRendererBase::StartEditing( const wxDataViewItem &item, wxRect la
|
||||
if( !start_event.IsAllowed() )
|
||||
return false;
|
||||
|
||||
m_item = item; // remember for later
|
||||
|
||||
unsigned int col = GetOwner()->GetModelColumn();
|
||||
const wxVariant& value = CheckedGetValue(dv_ctrl->GetModel(), item, col);
|
||||
|
||||
@@ -703,15 +701,23 @@ bool wxDataViewRendererBase::StartEditing( const wxDataViewItem &item, wxRect la
|
||||
m_editorCtrl->SetFocus();
|
||||
#endif
|
||||
|
||||
// Now we should send Editing Started event
|
||||
return true;
|
||||
}
|
||||
|
||||
void wxDataViewRendererBase::NotifyEditingStarted(const wxDataViewItem& item)
|
||||
{
|
||||
// Remember the item being edited for use in FinishEditing() later.
|
||||
m_item = item;
|
||||
|
||||
wxDataViewColumn* const column = GetOwner();
|
||||
wxDataViewCtrl* const dv_ctrl = column->GetOwner();
|
||||
|
||||
wxDataViewEvent event( wxEVT_DATAVIEW_ITEM_EDITING_STARTED, dv_ctrl->GetId() );
|
||||
event.SetDataViewColumn( GetOwner() );
|
||||
event.SetDataViewColumn( column );
|
||||
event.SetModel( dv_ctrl->GetModel() );
|
||||
event.SetItem( item );
|
||||
event.SetEventObject( dv_ctrl );
|
||||
dv_ctrl->GetEventHandler()->ProcessEvent( event );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void wxDataViewRendererBase::DestroyEditControl()
|
||||
@@ -745,9 +751,10 @@ bool wxDataViewRendererBase::FinishEditing()
|
||||
if (!m_editorCtrl)
|
||||
return true;
|
||||
|
||||
// Try to get the value, normally we should succeed but if we fail, don't
|
||||
// return immediately, we still need to destroy the edit control.
|
||||
wxVariant value;
|
||||
if ( !GetValueFromEditorCtrl(m_editorCtrl, value) )
|
||||
return false;
|
||||
const bool gotValue = GetValueFromEditorCtrl(m_editorCtrl, value);
|
||||
|
||||
wxDataViewCtrl* dv_ctrl = GetOwner()->GetOwner();
|
||||
|
||||
@@ -755,6 +762,9 @@ bool wxDataViewRendererBase::FinishEditing()
|
||||
|
||||
dv_ctrl->GetMainWindow()->SetFocus();
|
||||
|
||||
if ( !gotValue )
|
||||
return false;
|
||||
|
||||
bool isValid = Validate(value);
|
||||
unsigned int col = GetOwner()->GetModelColumn();
|
||||
|
||||
@@ -769,13 +779,16 @@ bool wxDataViewRendererBase::FinishEditing()
|
||||
event.SetEventObject( dv_ctrl );
|
||||
dv_ctrl->GetEventHandler()->ProcessEvent( event );
|
||||
|
||||
bool accepted = false;
|
||||
if ( isValid && event.IsAllowed() )
|
||||
{
|
||||
dv_ctrl->GetModel()->ChangeValue(value, m_item, col);
|
||||
return true;
|
||||
accepted = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
m_item = wxDataViewItem();
|
||||
|
||||
return accepted;
|
||||
}
|
||||
|
||||
wxVariant
|
||||
@@ -1044,17 +1057,20 @@ void wxDataViewEditorCtrlEvtHandler::OnChar( wxKeyEvent &event )
|
||||
{
|
||||
switch ( event.m_keyCode )
|
||||
{
|
||||
case WXK_RETURN:
|
||||
m_finished = true;
|
||||
m_owner->FinishEditing();
|
||||
break;
|
||||
|
||||
case WXK_ESCAPE:
|
||||
{
|
||||
m_finished = true;
|
||||
m_owner->CancelEditing();
|
||||
break;
|
||||
}
|
||||
|
||||
case WXK_RETURN:
|
||||
if ( !event.HasAnyModifiers() )
|
||||
{
|
||||
m_finished = true;
|
||||
m_owner->FinishEditing();
|
||||
break;
|
||||
}
|
||||
wxFALLTHROUGH; // Ctrl/Alt/Shift-Enter is not handled specially
|
||||
|
||||
default:
|
||||
event.Skip();
|
||||
}
|
||||
|
@@ -1693,6 +1693,13 @@ void wxEvtHandler::DoBind(int id,
|
||||
wxDynamicEventTableEntry *entry =
|
||||
new wxDynamicEventTableEntry(eventType, id, lastId, func, userData);
|
||||
|
||||
// Check if the derived class allows binding such event handlers.
|
||||
if ( !OnDynamicBind(*entry) )
|
||||
{
|
||||
delete entry;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_dynamicEvents)
|
||||
m_dynamicEvents = new DynamicEvents;
|
||||
|
||||
|
@@ -1194,6 +1194,21 @@ void wxTextCtrlBase::DoUpdateWindowUI(wxUpdateUIEvent& event)
|
||||
}
|
||||
}
|
||||
|
||||
bool wxTextCtrlBase::OnDynamicBind(wxDynamicEventTableEntry& entry)
|
||||
{
|
||||
if ( entry.m_eventType == wxEVT_TEXT_ENTER )
|
||||
{
|
||||
wxCHECK_MSG
|
||||
(
|
||||
HasFlag(wxTE_PROCESS_ENTER),
|
||||
false,
|
||||
wxS("Must have wxTE_PROCESS_ENTER for wxEVT_TEXT_ENTER to work")
|
||||
);
|
||||
}
|
||||
|
||||
return wxControl::OnDynamicBind(entry);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// hit testing
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@@ -120,8 +120,8 @@ wxDataViewColumn* GetExpanderColumnOrFirstOne(wxDataViewCtrl* dataview)
|
||||
wxTextCtrl *CreateEditorTextCtrl(wxWindow *parent, const wxRect& labelRect, const wxString& value)
|
||||
{
|
||||
wxTextCtrl* ctrl = new wxTextCtrl(parent, wxID_ANY, value,
|
||||
wxPoint(labelRect.x,labelRect.y),
|
||||
wxSize(labelRect.width,labelRect.height),
|
||||
labelRect.GetPosition(),
|
||||
labelRect.GetSize(),
|
||||
wxTE_PROCESS_ENTER);
|
||||
|
||||
// Adjust size of wxTextCtrl editor to fit text, even if it means being
|
||||
@@ -2251,6 +2251,8 @@ wxDataViewMainWindow::StartEditing(const wxDataViewItem& item,
|
||||
const wxRect itemRect = GetItemRect(item, col);
|
||||
if ( renderer->StartEditing(item, itemRect) )
|
||||
{
|
||||
renderer->NotifyEditingStarted(item);
|
||||
|
||||
// Save the renderer to be able to finish/cancel editing it later and
|
||||
// save the control to be able to detect if we're still editing it.
|
||||
m_editorRenderer = renderer;
|
||||
@@ -3632,7 +3634,17 @@ void wxDataViewMainWindow::OnCharHook(wxKeyEvent& event)
|
||||
return;
|
||||
|
||||
case WXK_RETURN:
|
||||
// Shift-Enter is not special neither.
|
||||
if ( event.ShiftDown() )
|
||||
break;
|
||||
wxFALLTHROUGH;
|
||||
|
||||
case WXK_TAB:
|
||||
// Ctrl/Alt-Tab or Enter could be used for something else, so
|
||||
// don't handle them here.
|
||||
if ( event.HasModifiers() )
|
||||
break;
|
||||
|
||||
m_editorRenderer->FinishEditing();
|
||||
return;
|
||||
}
|
||||
|
@@ -1749,20 +1749,11 @@ bool wxGtkDataViewModelNotifier::Cleared()
|
||||
// wxDataViewRenderer
|
||||
// ---------------------------------------------------------
|
||||
|
||||
static gpointer s_user_data = NULL;
|
||||
|
||||
static void
|
||||
wxgtk_cell_editable_editing_done( GtkCellEditable *WXUNUSED(editable),
|
||||
wxDataViewRenderer *wxrenderer )
|
||||
{
|
||||
wxDataViewColumn *column = wxrenderer->GetOwner();
|
||||
wxDataViewCtrl *dv = column->GetOwner();
|
||||
wxDataViewEvent event( wxEVT_DATAVIEW_ITEM_EDITING_DONE, dv->GetId() );
|
||||
event.SetDataViewColumn( column );
|
||||
event.SetModel( dv->GetModel() );
|
||||
wxDataViewItem item( s_user_data );
|
||||
event.SetItem( item );
|
||||
dv->HandleWindowEvent( event );
|
||||
wxrenderer->FinishEditing();
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1774,17 +1765,11 @@ wxgtk_renderer_editing_started( GtkCellRenderer *WXUNUSED(cell), GtkCellEditable
|
||||
|
||||
wxDataViewColumn *column = wxrenderer->GetOwner();
|
||||
wxDataViewCtrl *dv = column->GetOwner();
|
||||
wxDataViewEvent event( wxEVT_DATAVIEW_ITEM_EDITING_STARTED, dv->GetId() );
|
||||
event.SetDataViewColumn( column );
|
||||
event.SetModel( dv->GetModel() );
|
||||
wxDataViewItem item(dv->GTKPathToItem(wxGtkTreePath(path)));
|
||||
event.SetItem( item );
|
||||
dv->HandleWindowEvent( event );
|
||||
wxrenderer->NotifyEditingStarted(item);
|
||||
|
||||
if (GTK_IS_CELL_EDITABLE(editable))
|
||||
{
|
||||
s_user_data = item.GetID();
|
||||
|
||||
g_signal_connect (editable, "editing_done",
|
||||
G_CALLBACK (wxgtk_cell_editable_editing_done),
|
||||
(gpointer) wxrenderer );
|
||||
|
@@ -2058,14 +2058,48 @@ void wxTextCtrl::OnKeyDown(wxKeyEvent& event)
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
WXLRESULT wxTextCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
|
||||
bool
|
||||
wxTextCtrl::MSWHandleMessage(WXLRESULT *rc,
|
||||
WXUINT nMsg,
|
||||
WXWPARAM wParam,
|
||||
WXLPARAM lParam)
|
||||
{
|
||||
WXLRESULT lRc = wxTextCtrlBase::MSWWindowProc(nMsg, wParam, lParam);
|
||||
bool processed = wxTextCtrlBase::MSWHandleMessage(rc, nMsg, wParam, lParam);
|
||||
|
||||
// Handle the special case of "Enter" key: the user code needs to specify
|
||||
// wxTE_PROCESS_ENTER style to get it in the first place, but if this flag
|
||||
// is used, then even if the wxEVT_TEXT_ENTER handler skips the event, the
|
||||
// normal action of this key is not performed because IsDialogMessage() is
|
||||
// not called and, also, an annoying beep is generated by EDIT default
|
||||
// WndProc.
|
||||
//
|
||||
// Fix these problems by explicitly performing the default function of this
|
||||
// key (which would be done by MSWProcessMessage() if we didn't have
|
||||
// wxTE_PROCESS_ENTER) and preventing the default WndProc from getting it.
|
||||
if ( nMsg == WM_CHAR &&
|
||||
!processed &&
|
||||
HasFlag(wxTE_PROCESS_ENTER) &&
|
||||
wParam == VK_RETURN &&
|
||||
!wxIsAnyModifierDown() )
|
||||
{
|
||||
MSWClickButtonIfPossible(MSWGetDefaultButtonFor(this));
|
||||
|
||||
processed = true;
|
||||
}
|
||||
|
||||
switch ( nMsg )
|
||||
{
|
||||
case WM_GETDLGCODE:
|
||||
{
|
||||
// Ensure that the result value is initialized even if the base
|
||||
// class didn't handle WM_GETDLGCODE but just update the value
|
||||
// returned by it if it did handle it.
|
||||
if ( !processed )
|
||||
{
|
||||
*rc = MSWDefWindowProc(nMsg, wParam, lParam);
|
||||
processed = true;
|
||||
}
|
||||
|
||||
// we always want the chars and the arrows: the arrows for
|
||||
// navigation and the chars because we want Ctrl-C to work even
|
||||
// in a read only control
|
||||
@@ -2089,7 +2123,7 @@ WXLRESULT wxTextCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPara
|
||||
if ( HasFlag(wxTE_PROCESS_TAB) )
|
||||
lDlgCode |= DLGC_WANTTAB;
|
||||
|
||||
lRc |= lDlgCode;
|
||||
*rc |= lDlgCode;
|
||||
}
|
||||
else // !editable
|
||||
{
|
||||
@@ -2098,11 +2132,17 @@ WXLRESULT wxTextCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPara
|
||||
// including DLGC_WANTMESSAGE). This is strange (how
|
||||
// does it work in the native Win32 apps?) but for now
|
||||
// live with it.
|
||||
lRc = lDlgCode;
|
||||
*rc = lDlgCode;
|
||||
}
|
||||
|
||||
if ( IsMultiLine() )
|
||||
{
|
||||
// The presence of this style, coming from the default EDIT
|
||||
// WndProc, indicates that the control contents should be
|
||||
// selected when it gets focus, but we don't want this to
|
||||
// happen for the multiline controls, so clear it.
|
||||
*rc &= ~DLGC_HASSETSEL;
|
||||
}
|
||||
if (IsMultiLine())
|
||||
// Clear the DLGC_HASSETSEL bit from the return value
|
||||
lRc &= ~DLGC_HASSETSEL;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2122,7 +2162,7 @@ WXLRESULT wxTextCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPara
|
||||
#endif // wxUSE_MENUS
|
||||
}
|
||||
|
||||
return lRc;
|
||||
return processed;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@@ -2316,7 +2316,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg)
|
||||
// currently active button should get enter press even
|
||||
// if there is a default button elsewhere so check if
|
||||
// this window is a button first
|
||||
wxWindow *btn = NULL;
|
||||
wxButton *btn = NULL;
|
||||
if ( lDlgCode & DLGC_DEFPUSHBUTTON )
|
||||
{
|
||||
// let IsDialogMessage() handle this for all
|
||||
@@ -2325,8 +2325,11 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg)
|
||||
long style = ::GetWindowLong(msg->hwnd, GWL_STYLE);
|
||||
if ( (style & BS_OWNERDRAW) == BS_OWNERDRAW )
|
||||
{
|
||||
// emulate the button click
|
||||
btn = wxFindWinFromHandle(msg->hwnd);
|
||||
btn = wxDynamicCast
|
||||
(
|
||||
wxFindWinFromHandle(msg->hwnd),
|
||||
wxButton
|
||||
);
|
||||
}
|
||||
}
|
||||
else // not a button itself, do we have default button?
|
||||
@@ -2367,25 +2370,12 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg)
|
||||
);
|
||||
}
|
||||
}
|
||||
else // bCtrlDown
|
||||
{
|
||||
win = wxGetTopLevelParent(win);
|
||||
}
|
||||
|
||||
wxTopLevelWindow * const
|
||||
tlw = wxDynamicCast(win, wxTopLevelWindow);
|
||||
if ( tlw )
|
||||
{
|
||||
btn = wxDynamicCast(tlw->GetDefaultItem(),
|
||||
wxButton);
|
||||
}
|
||||
btn = MSWGetDefaultButtonFor(win);
|
||||
}
|
||||
|
||||
if ( btn && btn->IsEnabled() && btn->IsShownOnScreen() )
|
||||
{
|
||||
btn->MSWCommand(BN_CLICKED, 0 /* unused */);
|
||||
if ( MSWClickButtonIfPossible(btn) )
|
||||
return true;
|
||||
}
|
||||
|
||||
// This "Return" key press won't be actually used for
|
||||
// navigation so don't generate wxNavigationKeyEvent
|
||||
@@ -2544,6 +2534,36 @@ bool wxWindowMSW::MSWSafeIsDialogMessage(WXMSG* msg)
|
||||
|
||||
#endif // __WXUNIVERSAL__
|
||||
|
||||
/* static */
|
||||
wxButton* wxWindowMSW::MSWGetDefaultButtonFor(wxWindow* win)
|
||||
{
|
||||
#if wxUSE_BUTTON
|
||||
win = wxGetTopLevelParent(win);
|
||||
|
||||
wxTopLevelWindow *const tlw = wxDynamicCast(win, wxTopLevelWindow);
|
||||
if ( tlw )
|
||||
return wxDynamicCast(tlw->GetDefaultItem(), wxButton);
|
||||
#endif // wxUSE_BUTTON
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool wxWindowMSW::MSWClickButtonIfPossible(wxButton* btn)
|
||||
{
|
||||
#if wxUSE_BUTTON
|
||||
if ( btn && btn->IsEnabled() && btn->IsShownOnScreen() )
|
||||
{
|
||||
btn->MSWCommand(BN_CLICKED, 0 /* unused */);
|
||||
return true;
|
||||
}
|
||||
#endif // wxUSE_BUTTON
|
||||
|
||||
wxUnusedVar(btn);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// message params unpackers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
@@ -1886,22 +1886,20 @@ outlineView:(NSOutlineView*)outlineView
|
||||
wxDataViewColumn* const
|
||||
col([static_cast<wxDVCNSTableColumn*>(tableColumn) getColumnPointer]);
|
||||
|
||||
wxDataViewCtrl* const dvc = implementation->GetDataViewCtrl();
|
||||
|
||||
|
||||
// stop editing of a custom item first (if necessary)
|
||||
dvc->FinishCustomItemEditing();
|
||||
|
||||
// now, send the event:
|
||||
wxDataViewEvent
|
||||
event(wxEVT_DATAVIEW_ITEM_EDITING_STARTED,dvc->GetId());
|
||||
|
||||
event.SetEventObject(dvc);
|
||||
event.SetItem(
|
||||
wxDataViewItemFromItem([self itemAtRow:currentlyEditedRow]));
|
||||
event.SetColumn(dvc->GetColumnPosition(col));
|
||||
event.SetDataViewColumn(col);
|
||||
dvc->GetEventHandler()->ProcessEvent(event);
|
||||
wxDataViewRenderer* const renderer = col->GetRenderer();
|
||||
if ( renderer )
|
||||
{
|
||||
renderer->NotifyEditingStarted
|
||||
(
|
||||
wxDataViewItemFromItem([self itemAtRow:currentlyEditedRow])
|
||||
);
|
||||
}
|
||||
//else: we should always have a renderer but don't crash if for some
|
||||
// unfathomable reason we don't have it
|
||||
}
|
||||
|
||||
-(void) textDidEndEditing:(NSNotification*)notification
|
||||
|
Reference in New Issue
Block a user