#if defined(__WXGTK20__)
// for testing
- #define wxUSE_GENERICDATAVIEWCTRL 1
+ // #define wxUSE_GENERICDATAVIEWCTRL 1
#elif defined(__WXMAC__)
#define wxUSE_GENERICDATAVIEWCTRL 1
#else
wxDataViewSortedListModel( wxDataViewListModel *child );
virtual ~wxDataViewSortedListModel();
+ void SetAscending( bool ascending ) { m_ascending = ascending; }
+ bool GetAscending() { return m_ascending; }
+
virtual unsigned int GetNumberOfRows();
virtual unsigned int GetNumberOfCols();
// return type as reported by wxVariant
virtual void Resort();
private:
+ bool m_ascending;
wxDataViewListModel *m_child;
wxDataViewSortedIndexArray m_array;
wxDataViewListModelNotifier *m_notifierOnChild;
+
+ void InitStatics(); // BAD
protected:
DECLARE_DYNAMIC_CLASS_NO_COPY(wxDataViewSortedListModel)
virtual const wxBitmap &GetBitmap();
virtual void SetAlignment( wxAlignment align ) = 0;
+
+ virtual void SetSortable( bool sortable ) = 0;
+ virtual bool GetSortable() = 0;
virtual void SetSortOrder( bool ascending ) = 0;
+ virtual bool IsSortOrderAscending() = 0;
wxDataViewRenderer* GetRenderer() { return m_renderer; }
m_row(-1),
m_model(NULL),
m_value(wxNullVariant),
- m_editCancelled(false)
+ m_editCancelled(false),
+ m_column(NULL)
{ }
wxDataViewEvent(const wxDataViewEvent& event)
m_row(event.m_col),
m_model(event.m_model),
m_value(event.m_value),
- m_editCancelled(event.m_editCancelled)
+ m_editCancelled(event.m_editCancelled),
+ m_column(event.m_column)
{ }
int GetColumn() const { return m_col; }
const wxVariant &GetValue() const { return m_value; }
void SetValue( const wxVariant &value ) { m_value = value; }
+ // for wxEVT_DATAVIEW_COLUMN_HEADER_CLICKED only
+ void SetDataViewColumn( wxDataViewColumn *col ) { m_column = col; }
+ wxDataViewColumn *GetDataViewColumn() { return m_column; }
+
// was label editing canceled? (for wxEVT_COMMAND_DATVIEW_END_LABEL_EDIT only)
bool IsEditCancelled() const { return m_editCancelled; }
void SetEditCanceled(bool editCancelled) { m_editCancelled = editCancelled; }
wxDataViewModel *m_model;
wxVariant m_value;
bool m_editCancelled;
+ wxDataViewColumn *m_column;
private:
DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxDataViewEvent)
BEGIN_DECLARE_EVENT_TYPES()
DECLARE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ROW_SELECTED, -1)
DECLARE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ROW_ACTIVATED, -1)
+ DECLARE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK, -1)
+ DECLARE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK, -1)
END_DECLARE_EVENT_TYPES()
typedef void (wxEvtHandler::*wxDataViewEventFunction)(wxDataViewEvent&);
#define EVT_DATAVIEW_ROW_SELECTED(id, fn) wx__DECLARE_DATAVIEWEVT(ROW_SELECTED, id, fn)
#define EVT_DATAVIEW_ROW_ACTIVATED(id, fn) wx__DECLARE_DATAVIEWEVT(ROW_ACTIVATED, id, fn)
+#define EVT_DATAVIEW_COLUMN_HEADER_CLICK(id, fn) wx__DECLARE_DATAVIEWEVT(COLUMN_HEADER_CLICK, id, fn)
+#define EVT_DATAVIEW_COLUMN_HEADER_RIGHT_CLICKED(id, fn) wx__DECLARE_DATAVIEWEVT(COLUMN_HEADER_RIGHT_CLICK, id, fn)
#if defined(wxUSE_GENERICDATAVIEWCTRL)
virtual void SetBitmap( const wxBitmap &bitmap );
virtual void SetAlignment( wxAlignment align );
+
+ virtual void SetSortable( bool sortable );
+ virtual bool GetSortable();
virtual void SetSortOrder( bool ascending );
+ virtual bool IsSortOrderAscending();
virtual int GetWidth();
virtual void SetBitmap( const wxBitmap &bitmap );
virtual void SetAlignment( wxAlignment align );
+
+ virtual void SetSortable( bool sortable );
+ virtual bool GetSortable();
virtual void SetSortOrder( bool ascending );
+ virtual bool IsSortOrderAscending();
virtual int GetWidth();
private:
// holds the GTK handle
void* m_column;
-
+
+ // delayed connection to mouse events
+ friend class wxDataViewCtrl;
+ void OnInternalIdle();
+ bool m_isConnected;
+
protected:
DECLARE_DYNAMIC_CLASS_NO_COPY(wxDataViewColumn)
};
virtual int GetSelection() const;
virtual int GetSelections(wxArrayInt& aSelections) const;
-
private:
friend class wxDataViewCtrlDC;
+ friend class wxDataViewColumn;
friend class wxGtkDataViewListModelNotifier;
GtkWidget *m_treeview;
wxDataViewListModelNotifier *m_notifier;
+ virtual void OnInternalIdle();
+
private:
DECLARE_DYNAMIC_CLASS(wxDataViewCtrl)
DECLARE_NO_COPY_CLASS(wxDataViewCtrl)
void OnSelectedSorted(wxDataViewEvent &event);
void OnActivatedUnsorted(wxDataViewEvent &event);
+ void OnHeaderClickSorted(wxDataViewEvent &event);
+ void OnHeaderClickUnsorted(wxDataViewEvent &event);
+
private:
wxDataViewCtrl* dataview_left;
wxDataViewCtrl* dataview_right;
wxLog *m_logOld;
wxTextCtrl *m_logWindow;
- MyUnsortedTextModel *m_unsorted_model;
+ MyUnsortedTextModel *m_unsorted_model;
+ wxDataViewSortedListModel *m_sorted_model;
DECLARE_EVENT_TABLE()
};
EVT_DATAVIEW_ROW_SELECTED( ID_SORTED, MySortingFrame::OnSelectedSorted )
EVT_DATAVIEW_ROW_SELECTED( ID_UNSORTED, MySortingFrame::OnSelectedUnsorted )
EVT_DATAVIEW_ROW_ACTIVATED( ID_UNSORTED, MySortingFrame::OnActivatedUnsorted )
+ EVT_DATAVIEW_COLUMN_HEADER_CLICK( ID_SORTED, MySortingFrame::OnHeaderClickSorted )
+ EVT_DATAVIEW_COLUMN_HEADER_CLICK( ID_UNSORTED, MySortingFrame::OnHeaderClickUnsorted )
END_EVENT_TABLE()
MySortingFrame::MySortingFrame(wxFrame *frame, wxChar *title, int x, int y, int w, int h):
// Right wxDataViewCtrl using the sorting model
dataview_right = new wxDataViewCtrl( this, ID_SORTED );
- wxDataViewSortedListModel *sorted_model =
- new wxDataViewSortedListModel( m_unsorted_model );
- dataview_right->AssociateModel( sorted_model );
+ m_sorted_model = new wxDataViewSortedListModel( m_unsorted_model );
+ dataview_right->AssociateModel( m_sorted_model );
text_renderer = new wxDataViewTextRenderer( wxT("string"), wxDATAVIEW_CELL_EDITABLE );
column = new wxDataViewColumn( wxT("editable"), text_renderer, 0, -1, wxDATAVIEW_COL_SORTABLE|wxDATAVIEW_COL_RESIZABLE );
dataview_right->AppendColumn( column );
wxLogMessage( wxT("OnActivated from unsorted list, activated %d"), (int) event.GetRow() );
}
+void MySortingFrame::OnHeaderClickSorted(wxDataViewEvent &event)
+{
+ wxDataViewColumn *col = event.GetDataViewColumn();
+ wxLogMessage( wxT("OnHeaderClick from sorted list, column %s"), col->GetTitle().c_str() );
+
+ if (col->GetTitle() == wxT("editable"))
+ {
+ // this is the sorting column
+ if (col->IsSortOrderAscending())
+ {
+ col->SetSortOrder( false );
+ m_sorted_model->SetAscending( false );
+ m_sorted_model->Resort();
+ }
+ else
+ {
+ col->SetSortOrder( true );
+ m_sorted_model->SetAscending( true );
+ m_sorted_model->Resort();
+ }
+ }
+}
+
+void MySortingFrame::OnHeaderClickUnsorted(wxDataViewEvent &event)
+{
+ wxLogMessage( wxT("OnHeaderClick from unsorted list, column %s"), event.GetDataViewColumn()->GetTitle().c_str() );
+}
+
void MySortingFrame::OnQuit(wxCommandEvent& WXUNUSED(event) )
{
Close(true);
return 0;
}
+int wxCALLBACK wxDataViewListModelSortedDefaultCompareDescending
+ (unsigned int row1, unsigned int row2, unsigned int col, wxDataViewListModel* model )
+{
+ return wxDataViewListModelSortedDefaultCompare( row2, row1, col, model );
+}
+
static wxDataViewListModelCompare s_CmpFunc;
static wxDataViewListModel *s_CmpModel;
-static unsigned int s_CmpCol;
+static unsigned int s_CmpCol;
int LINKAGEMODE wxDataViewIntermediateCmp( unsigned int row1, unsigned int row2 )
{
m_array( wxDataViewIntermediateCmp )
{
m_child = child;
- s_CmpCol = 0;
- s_CmpModel = child;
- s_CmpFunc = wxDataViewListModelSortedDefaultCompare;
+
+ m_ascending = true;
m_notifierOnChild = new wxDataViewSortedListModelNotifier( this );
m_child->AddNotifier( m_notifierOnChild );
m_child->RemoveNotifier( m_notifierOnChild );
}
+// FIXME
+void wxDataViewSortedListModel::InitStatics()
+{
+ s_CmpCol = 0;
+ s_CmpModel = m_child;
+ if (m_ascending)
+ s_CmpFunc = wxDataViewListModelSortedDefaultCompare;
+ else
+ s_CmpFunc = wxDataViewListModelSortedDefaultCompareDescending;
+}
+
void wxDataViewSortedListModel::Resort()
{
+ InitStatics();
+
m_array.Clear();
unsigned int n = m_child->GetNumberOfRows();
unsigned int i;
DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ROW_SELECTED)
DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_ROW_ACTIVATED)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK)
#endif
// TODO
}
+void wxDataViewColumn::SetSortable( bool WXUNUSED(sortable) )
+{
+ // TODO
+}
+
+bool wxDataViewColumn::GetSortable()
+{
+ // TODO
+ return false;
+}
+
void wxDataViewColumn::SetSortOrder( bool WXUNUSED(ascending) )
{
// TODO
}
+bool wxDataViewColumn::IsSortOrderAscending()
+{
+ // TODO
+ return true;
+}
+
+
wxDataViewColumn::~wxDataViewColumn()
{
}
// wxDataViewColumn
// ---------------------------------------------------------
+
+static gboolean
+gtk_dataview_header_button_press_callback( GtkWidget *widget,
+ GdkEventButton *gdk_event,
+ wxDataViewColumn *column )
+{
+ if (gdk_event->type != GDK_BUTTON_PRESS)
+ return TRUE;
+
+ if (gdk_event->button == 1)
+ {
+ wxDataViewCtrl *dv = column->GetOwner();
+ wxDataViewEvent event( wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK, dv->GetId() );
+ event.SetDataViewColumn( column );
+ event.SetModel( dv->GetModel() );
+ dv->GetEventHandler()->ProcessEvent( event );
+ }
+
+ return TRUE;
+}
+
extern "C" {
static void wxGtkTreeCellDataFunc( GtkTreeViewColumn *column,
GtkCellRenderer *cell,
int width, int flags ) :
wxDataViewColumnBase( title, cell, model_column, width, flags )
{
+ m_isConnected = false;
+
GtkCellRenderer *renderer = (GtkCellRenderer *) cell->GetGtkHandle();
GtkTreeViewColumn *column = gtk_tree_view_column_new();
-
- gtk_tree_view_column_set_title( column, wxGTK_CONV(title) );
+ m_column = (void*) column;
+
+ gtk_tree_view_column_set_clickable( column, true );
+
+ SetTitle( title );
if (flags & wxDATAVIEW_COL_RESIZABLE)
gtk_tree_view_column_set_resizable( column, true );
gtk_tree_view_column_set_cell_data_func( column, renderer,
wxGtkTreeCellDataFunc, (gpointer) cell, NULL );
- m_column = (void*) column;
}
wxDataViewColumn::wxDataViewColumn( const wxBitmap &bitmap, wxDataViewRenderer *cell, unsigned int model_column,
int width, int flags ) :
wxDataViewColumnBase( bitmap, cell, model_column, width, flags )
{
+ m_isConnected = false;
+
GtkCellRenderer *renderer = (GtkCellRenderer *) cell->GetGtkHandle();
GtkTreeViewColumn *column = gtk_tree_view_column_new();
{
}
+void wxDataViewColumn::OnInternalIdle()
+{
+ if (m_isConnected)
+ return;
+
+ if (GTK_WIDGET_REALIZED(GetOwner()->m_treeview))
+ {
+ GtkTreeViewColumn *column = (GtkTreeViewColumn *)m_column;
+ if (column->button)
+ {
+ g_signal_connect(column->button, "button_press_event",
+ G_CALLBACK (gtk_dataview_header_button_press_callback), this);
+
+ m_isConnected = true;
+ }
+ }
+}
+
void wxDataViewColumn::SetTitle( const wxString &title )
{
wxDataViewColumnBase::SetTitle( title );
GtkTreeViewColumn *column = (GtkTreeViewColumn *)m_column;
- gtk_tree_view_column_set_title( column, wxGTK_CONV(title) );
+ if (m_isConnected)
+ {
+ // disconnect before column->button gets recreated
+ g_signal_handlers_disconnect_by_func( column->button,
+ (void*) gtk_dataview_header_button_press_callback, this);
+
+ m_isConnected = false;
+ }
+
+ gtk_tree_view_column_set_title( column, wxGTK_CONV(title) );
+
gtk_tree_view_column_set_widget( column, NULL );
}
gtk_tree_view_column_set_alignment( column, xalign );
}
+void wxDataViewColumn::SetSortable( bool sortable )
+{
+ GtkTreeViewColumn *column = (GtkTreeViewColumn *)m_column;
+ gtk_tree_view_column_set_sort_indicator( column, sortable );
+}
+
+bool wxDataViewColumn::GetSortable()
+{
+ GtkTreeViewColumn *column = (GtkTreeViewColumn *)m_column;
+ return gtk_tree_view_column_get_sort_indicator( column );
+}
+
void wxDataViewColumn::SetSortOrder( bool ascending )
{
GtkTreeViewColumn *column = (GtkTreeViewColumn *)m_column;
gtk_tree_view_column_set_sort_order( column, GTK_SORT_DESCENDING );
}
+bool wxDataViewColumn::IsSortOrderAscending()
+{
+ GtkTreeViewColumn *column = (GtkTreeViewColumn *)m_column;
+
+ return (gtk_tree_view_column_get_sort_order( column ) != GTK_SORT_DESCENDING);
+}
+
int wxDataViewColumn::GetWidth()
{
return gtk_tree_view_column_get_width( (GtkTreeViewColumn *)m_column );
return true;
}
+void wxDataViewCtrl::OnInternalIdle()
+{
+ wxWindow::OnInternalIdle();
+
+ unsigned int cols = GetNumberOfColumns();
+ unsigned int i;
+ for (i = 0; i < cols; i++)
+ {
+ wxDataViewColumn *col = GetColumn( i );
+ col->OnInternalIdle();
+ }
+}
+
bool wxDataViewCtrl::AssociateModel( wxDataViewListModel *model )
{
if (!wxDataViewCtrlBase::AssociateModel( model ))