Allow using arbitrary windows as wxDataViewCtrl editors in wxGTK
Previously the editor created by wxDataViewRenderer::CreateEditorCtrl() had to be a native GTK+ widget implementing GtkCellEditable interface which prevented using composite windows (e.g. a container for a text control and a button) as editors. Create a helper container wrapping them now and implementing GtkCellEditable now to allow this.
This commit is contained in:
@@ -162,6 +162,7 @@ All (GUI):
|
|||||||
wxGTK:
|
wxGTK:
|
||||||
|
|
||||||
- Support building wxGTK3 under Windows (Kolya Kosenko).
|
- Support building wxGTK3 under Windows (Kolya Kosenko).
|
||||||
|
- Implement support for non-wxTextCtrl custom editors in wxDataViewCtrl.
|
||||||
- Fix vertical cell alignment in wxDataViewCtrl.
|
- Fix vertical cell alignment in wxDataViewCtrl.
|
||||||
- Fix clearing of wxComboBox with wxCB_READONLY (Chuddah).
|
- Fix clearing of wxComboBox with wxCB_READONLY (Chuddah).
|
||||||
- Fix setting "pressed" bitmap for wxToggleButton (Kevin B. McCarty).
|
- Fix setting "pressed" bitmap for wxToggleButton (Kevin B. McCarty).
|
||||||
|
@@ -60,6 +60,10 @@ public:
|
|||||||
// text
|
// text
|
||||||
virtual GtkCellRendererText *GtkGetTextRenderer() const { return NULL; }
|
virtual GtkCellRendererText *GtkGetTextRenderer() const { return NULL; }
|
||||||
|
|
||||||
|
// return the widget actually used by the renderer for editing, this may be
|
||||||
|
// different from the editor control widget for the custom renderers
|
||||||
|
virtual GtkWidget* GtkGetEditorWidget() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Change the mode at GTK level without touching m_mode, this is useful for
|
// Change the mode at GTK level without touching m_mode, this is useful for
|
||||||
// temporarily making the renderer insensitive but does mean that GetMode()
|
// temporarily making the renderer insensitive but does mean that GetMode()
|
||||||
|
@@ -137,6 +137,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual GtkCellRendererText *GtkGetTextRenderer() const wxOVERRIDE;
|
virtual GtkCellRendererText *GtkGetTextRenderer() const wxOVERRIDE;
|
||||||
|
virtual GtkWidget* GtkGetEditorWidget() const wxOVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool Init(wxDataViewCellMode mode, int align);
|
bool Init(wxDataViewCellMode mode, int align);
|
||||||
|
@@ -1143,6 +1143,168 @@ static GtkCellEditable *gtk_wx_cell_renderer_text_start_editing(
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// GTK+ class GtkWxCellEditorBin: needed only to implement GtkCellEditable for
|
||||||
|
// our editor widgets which don't necessarily implement it on their own.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
CELL_EDITOR_BIN_PROP_0,
|
||||||
|
CELL_EDITOR_BIN_PROP_EDITING_CANCELED
|
||||||
|
};
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
#define GTK_TYPE_WX_CELL_EDITOR_BIN (gtk_wx_cell_editor_bin_get_type ())
|
||||||
|
#define GTK_WX_CELL_EDITOR_BIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_WX_CELL_EDITOR_BIN, GtkWxCellEditorBin))
|
||||||
|
#define GTK_IS_WX_CELL_EDITOR_BIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_WX_CELL_EDITOR_BIN))
|
||||||
|
#define GTK_IS_WX_CELL_EDITOR_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_WX_CELL_EDITOR_BIN))
|
||||||
|
|
||||||
|
GType gtk_wx_cell_editor_bin_get_type();
|
||||||
|
|
||||||
|
struct GtkWxCellEditorBin
|
||||||
|
{
|
||||||
|
GtkBin parent;
|
||||||
|
|
||||||
|
// The actual user-created editor.
|
||||||
|
wxWindow* editor;
|
||||||
|
};
|
||||||
|
|
||||||
|
static GtkWidget* gtk_wx_cell_editor_bin_new(wxWindow* editor);
|
||||||
|
static void gtk_wx_cell_editor_bin_init(GTypeInstance* instance, void*);
|
||||||
|
static void gtk_wx_cell_editor_bin_class_init(void* klass, void*);
|
||||||
|
static void gtk_wx_cell_editor_bin_get_property(GObject*, guint, GValue*, GParamSpec*);
|
||||||
|
static void gtk_wx_cell_editor_bin_set_property(GObject*, guint, const GValue*, GParamSpec*);
|
||||||
|
|
||||||
|
static void gtk_wx_cell_editor_bin_cell_editable_init(void* g_iface, void*);
|
||||||
|
static void gtk_wx_cell_editor_bin_cell_editable_start_editing(
|
||||||
|
GtkCellEditable *cell_editable,
|
||||||
|
GdkEvent *event);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
GType
|
||||||
|
gtk_wx_cell_editor_bin_get_type()
|
||||||
|
{
|
||||||
|
static GType cell_editor_bin_type = 0;
|
||||||
|
|
||||||
|
if ( !cell_editor_bin_type )
|
||||||
|
{
|
||||||
|
const GTypeInfo cell_editor_bin_info =
|
||||||
|
{
|
||||||
|
sizeof (GtkBinClass),
|
||||||
|
NULL, /* base_init */
|
||||||
|
NULL, /* base_finalize */
|
||||||
|
gtk_wx_cell_editor_bin_class_init,
|
||||||
|
NULL, /* class_finalize */
|
||||||
|
NULL, /* class_data */
|
||||||
|
sizeof (GtkWxCellEditorBin),
|
||||||
|
0, /* n_preallocs */
|
||||||
|
gtk_wx_cell_editor_bin_init,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
cell_editor_bin_type = g_type_register_static( GTK_TYPE_BIN,
|
||||||
|
"GtkWxCellEditorBin", &cell_editor_bin_info, (GTypeFlags)0 );
|
||||||
|
|
||||||
|
|
||||||
|
static const GInterfaceInfo cell_editable_iface_info =
|
||||||
|
{
|
||||||
|
gtk_wx_cell_editor_bin_cell_editable_init,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
g_type_add_interface_static (cell_editor_bin_type,
|
||||||
|
GTK_TYPE_CELL_EDITABLE,
|
||||||
|
&cell_editable_iface_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cell_editor_bin_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_wx_cell_editor_bin_init(GTypeInstance* instance, void*)
|
||||||
|
{
|
||||||
|
GtkWxCellEditorBin* const bin = GTK_WX_CELL_EDITOR_BIN(instance);
|
||||||
|
bin->editor = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gtk_wx_cell_editor_bin_class_init(void* klass, void*)
|
||||||
|
{
|
||||||
|
GObjectClass* const oclass = G_OBJECT_CLASS(klass);
|
||||||
|
|
||||||
|
oclass->set_property = gtk_wx_cell_editor_bin_set_property;
|
||||||
|
oclass->get_property = gtk_wx_cell_editor_bin_get_property;
|
||||||
|
|
||||||
|
g_object_class_override_property(oclass,
|
||||||
|
CELL_EDITOR_BIN_PROP_EDITING_CANCELED,
|
||||||
|
"editing-canceled");
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to provide these virtual methods as we must support the
|
||||||
|
// editing-canceled property, but they don't seem to be actually ever called,
|
||||||
|
// so it's not clear if we must implement them and how. For now just do
|
||||||
|
// nothing.
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_wx_cell_editor_bin_get_property(GObject*, guint, GValue*, GParamSpec*)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_wx_cell_editor_bin_set_property(GObject*, guint, const GValue*, GParamSpec*)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkWidget*
|
||||||
|
gtk_wx_cell_editor_bin_new(wxWindow* editor)
|
||||||
|
{
|
||||||
|
if ( !editor )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
GtkWxCellEditorBin* const
|
||||||
|
bin = (GtkWxCellEditorBin*)g_object_new (GTK_TYPE_WX_CELL_EDITOR_BIN, NULL);
|
||||||
|
|
||||||
|
bin->editor = editor;
|
||||||
|
gtk_container_add(GTK_CONTAINER(bin), editor->m_widget);
|
||||||
|
|
||||||
|
return GTK_WIDGET(bin);
|
||||||
|
}
|
||||||
|
|
||||||
|
// GtkCellEditable interface implementation for GtkWxCellEditorBin
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_wx_cell_editor_bin_cell_editable_init(void* g_iface, void*)
|
||||||
|
{
|
||||||
|
GtkCellEditableIface* iface = static_cast<GtkCellEditableIface*>(g_iface);
|
||||||
|
iface->start_editing = gtk_wx_cell_editor_bin_cell_editable_start_editing;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_wx_cell_editor_bin_cell_editable_start_editing(GtkCellEditable *cell_editable,
|
||||||
|
GdkEvent *event)
|
||||||
|
{
|
||||||
|
GtkWxCellEditorBin* const bin = (GtkWxCellEditorBin *)cell_editable;
|
||||||
|
|
||||||
|
// If we have an editable widget inside the editor, forward to it.
|
||||||
|
for ( wxWindow* win = bin->editor; win; )
|
||||||
|
{
|
||||||
|
GtkWidget* const widget = win->m_widget;
|
||||||
|
if ( GTK_IS_CELL_EDITABLE(widget) )
|
||||||
|
{
|
||||||
|
gtk_cell_editable_start_editing(GTK_CELL_EDITABLE(widget), event);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( win == bin->editor )
|
||||||
|
win = win->GetChildren().front();
|
||||||
|
else
|
||||||
|
win = win->GetNextSibling();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// define new GTK+ class GtkWxCellRenderer
|
// define new GTK+ class GtkWxCellRenderer
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@@ -1164,6 +1326,9 @@ struct _GtkWxCellRenderer
|
|||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
wxDataViewCustomRenderer *cell;
|
wxDataViewCustomRenderer *cell;
|
||||||
|
|
||||||
|
// Non null only while editing.
|
||||||
|
GtkWidget* editor_bin;
|
||||||
};
|
};
|
||||||
|
|
||||||
static GtkCellRenderer *gtk_wx_cell_renderer_new (void);
|
static GtkCellRenderer *gtk_wx_cell_renderer_new (void);
|
||||||
@@ -1245,6 +1410,7 @@ gtk_wx_cell_renderer_init(GTypeInstance* instance, void*)
|
|||||||
{
|
{
|
||||||
GtkWxCellRenderer* cell = GTK_WX_CELL_RENDERER(instance);
|
GtkWxCellRenderer* cell = GTK_WX_CELL_RENDERER(instance);
|
||||||
cell->cell = NULL;
|
cell->cell = NULL;
|
||||||
|
cell->editor_bin = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1302,10 +1468,13 @@ static GtkCellEditable *gtk_wx_cell_renderer_start_editing(
|
|||||||
wxDataViewItem
|
wxDataViewItem
|
||||||
item(cell->GetOwner()->GetOwner()->GTKPathToItem(wxGtkTreePath(path)));
|
item(cell->GetOwner()->GetOwner()->GTKPathToItem(wxGtkTreePath(path)));
|
||||||
|
|
||||||
if (cell->StartEditing(item, renderrect))
|
if (!cell->StartEditing(item, renderrect))
|
||||||
return GTK_CELL_EDITABLE(cell->GetEditorCtrl()->m_widget);
|
return NULL;
|
||||||
|
|
||||||
return NULL;
|
wxrenderer->editor_bin = gtk_wx_cell_editor_bin_new(cell->GetEditorCtrl());
|
||||||
|
gtk_widget_show(wxrenderer->editor_bin);
|
||||||
|
|
||||||
|
return GTK_CELL_EDITABLE(wxrenderer->editor_bin);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1804,7 +1973,7 @@ bool wxDataViewRenderer::FinishEditing()
|
|||||||
{
|
{
|
||||||
// remove editor widget before editor control is deleted,
|
// remove editor widget before editor control is deleted,
|
||||||
// to prevent several GTK warnings
|
// to prevent several GTK warnings
|
||||||
gtk_cell_editable_remove_widget(GTK_CELL_EDITABLE(editorCtrl->m_widget));
|
gtk_cell_editable_remove_widget(GTK_CELL_EDITABLE(GtkGetEditorWidget()));
|
||||||
// delete editor control now, if it is deferred multiple erroneous
|
// delete editor control now, if it is deferred multiple erroneous
|
||||||
// focus-out events will occur, causing debug warnings
|
// focus-out events will occur, causing debug warnings
|
||||||
delete editorCtrl;
|
delete editorCtrl;
|
||||||
@@ -1826,6 +1995,11 @@ void wxDataViewRenderer::GtkInitHandlers()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GtkWidget* wxDataViewRenderer::GtkGetEditorWidget() const
|
||||||
|
{
|
||||||
|
return GetEditorCtrl()->m_widget;
|
||||||
|
}
|
||||||
|
|
||||||
void wxDataViewRenderer::SetMode( wxDataViewCellMode mode )
|
void wxDataViewRenderer::SetMode( wxDataViewCellMode mode )
|
||||||
{
|
{
|
||||||
m_mode = mode;
|
m_mode = mode;
|
||||||
@@ -2419,6 +2593,11 @@ GtkCellRendererText *wxDataViewCustomRenderer::GtkGetTextRenderer() const
|
|||||||
return m_text_renderer;
|
return m_text_renderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GtkWidget* wxDataViewCustomRenderer::GtkGetEditorWidget() const
|
||||||
|
{
|
||||||
|
return GTK_WX_CELL_RENDERER(m_renderer)->editor_bin;
|
||||||
|
}
|
||||||
|
|
||||||
void wxDataViewCustomRenderer::RenderText( const wxString &text,
|
void wxDataViewCustomRenderer::RenderText( const wxString &text,
|
||||||
int xoffset,
|
int xoffset,
|
||||||
wxRect cell,
|
wxRect cell,
|
||||||
|
Reference in New Issue
Block a user