]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/dataview.cpp
minor cleanup 2 - reformatting
[wxWidgets.git] / src / gtk / dataview.cpp
CommitLineData
790b137e 1/////////////////////////////////////////////////////////////////////////////
93763ad5 2// Name: src/gtk/dataview.cpp
790b137e
RR
3// Purpose: wxDataViewCtrl GTK+2 implementation
4// Author: Robert Roebling
5// Id: $Id$
6// Copyright: (c) 1998 Robert Roebling
7// Licence: wxWindows licence
8/////////////////////////////////////////////////////////////////////////////
9
10// For compilers that support precompilation, includes "wx.h".
11#include "wx/wxprec.h"
12
790b137e
RR
13#if wxUSE_DATAVIEWCTRL
14
15#include "wx/dataview.h"
4ed7af08
RR
16
17#ifndef wxUSE_GENERICDATAVIEWCTRL
18
790b137e 19#include "wx/stockitem.h"
e152afc3 20#include "wx/dcclient.h"
7ea3a0de
RR
21#include "wx/calctrl.h"
22#include "wx/popupwin.h"
23#include "wx/sizer.h"
3f3af7e7 24#include "wx/log.h"
790b137e
RR
25
26#include "wx/gtk/private.h"
27#include "wx/gtk/win_gtk.h"
28
29#include <gobject/gvaluecollector.h>
1557c77b
RR
30#include <gtk/gtktreemodel.h>
31#include <gtk/gtktreednd.h>
790b137e 32
4d496ecb
RR
33#include <gdk/gdkkeysyms.h>
34
790b137e
RR
35//-----------------------------------------------------------------------------
36// classes
37//-----------------------------------------------------------------------------
38
39class wxDataViewCtrl;
40
790b137e
RR
41//-----------------------------------------------------------------------------
42// data
43//-----------------------------------------------------------------------------
44
45extern bool g_blockEventsOnDrag;
46
47//-----------------------------------------------------------------------------
48// define new GTK+ class wxGtkListStore
49//-----------------------------------------------------------------------------
50
51extern "C" {
52
53#define GTK_TYPE_WX_LIST_STORE (gtk_wx_list_store_get_type ())
54#define GTK_WX_LIST_STORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_WX_LIST_STORE, GtkWxListStore))
55#define GTK_WX_LIST_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_WX_LIST_STORE, GtkWxListStoreClass))
56#define GTK_IS_WX_LIST_STORE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_WX_LIST_STORE))
57#define GTK_IS_WX_LIST_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_WX_LIST_STORE))
58#define GTK_WX_LIST_STORE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_WX_LIST_STORE, GtkWxListStoreClass))
59
60GType gtk_wx_list_store_get_type (void);
61
62typedef struct _GtkWxListStore GtkWxListStore;
63typedef struct _GtkWxListStoreClass GtkWxListStoreClass;
64
65struct _GtkWxListStore
66{
67 GObject parent;
68
69 /*< private >*/
70 gint stamp;
71 wxDataViewListModel *model;
72};
73
74struct _GtkWxListStoreClass
75{
e152afc3 76 GObjectClass list_parent_class;
790b137e
RR
77};
78
e152afc3 79static GtkWxListStore *wxgtk_list_store_new (void);
790b137e 80static void wxgtk_list_store_init (GtkWxListStore *list_store);
1557c77b 81static void wxgtk_list_store_class_init (GtkWxListStoreClass *klass);
790b137e
RR
82static void wxgtk_list_store_tree_model_init (GtkTreeModelIface *iface);
83static void wxgtk_list_store_finalize (GObject *object);
84static GtkTreeModelFlags wxgtk_list_store_get_flags (GtkTreeModel *tree_model);
85static gint wxgtk_list_store_get_n_columns (GtkTreeModel *tree_model);
86static GType wxgtk_list_store_get_column_type (GtkTreeModel *tree_model,
93763ad5 87 gint index);
790b137e 88static gboolean wxgtk_list_store_get_iter (GtkTreeModel *tree_model,
93763ad5
WS
89 GtkTreeIter *iter,
90 GtkTreePath *path);
790b137e 91static GtkTreePath *wxgtk_list_store_get_path (GtkTreeModel *tree_model,
93763ad5 92 GtkTreeIter *iter);
790b137e 93static void wxgtk_list_store_get_value (GtkTreeModel *tree_model,
93763ad5
WS
94 GtkTreeIter *iter,
95 gint column,
96 GValue *value);
790b137e 97static gboolean wxgtk_list_store_iter_next (GtkTreeModel *tree_model,
93763ad5 98 GtkTreeIter *iter);
790b137e 99static gboolean wxgtk_list_store_iter_children (GtkTreeModel *tree_model,
93763ad5
WS
100 GtkTreeIter *iter,
101 GtkTreeIter *parent);
790b137e 102static gboolean wxgtk_list_store_iter_has_child (GtkTreeModel *tree_model,
93763ad5 103 GtkTreeIter *iter);
790b137e 104static gint wxgtk_list_store_iter_n_children (GtkTreeModel *tree_model,
93763ad5 105 GtkTreeIter *iter);
790b137e 106static gboolean wxgtk_list_store_iter_nth_child (GtkTreeModel *tree_model,
93763ad5
WS
107 GtkTreeIter *iter,
108 GtkTreeIter *parent,
109 gint n);
790b137e 110static gboolean wxgtk_list_store_iter_parent (GtkTreeModel *tree_model,
93763ad5
WS
111 GtkTreeIter *iter,
112 GtkTreeIter *child);
790b137e 113
e152afc3 114static GObjectClass *list_parent_class = NULL;
790b137e
RR
115
116GType
111f83c4 117gtk_wx_list_store_get_type (void)
790b137e 118{
93763ad5 119 static GType list_store_type = 0;
790b137e 120
93763ad5 121 if (!list_store_type)
790b137e 122 {
93763ad5
WS
123 static const GTypeInfo list_store_info =
124 {
125 sizeof (GtkWxListStoreClass),
126 NULL, /* base_init */
127 NULL, /* base_finalize */
128 (GClassInitFunc) wxgtk_list_store_class_init,
129 NULL, /* class_finalize */
130 NULL, /* class_data */
131 sizeof (GtkWxListStore),
132 0,
133 (GInstanceInitFunc) wxgtk_list_store_init,
134 };
790b137e
RR
135
136 static const GInterfaceInfo tree_model_info =
137 {
93763ad5
WS
138 (GInterfaceInitFunc) wxgtk_list_store_tree_model_init,
139 NULL,
140 NULL
790b137e
RR
141 };
142
143 list_store_type = g_type_register_static (G_TYPE_OBJECT, "GtkWxListStore",
93763ad5 144 &list_store_info, (GTypeFlags)0 );
790b137e
RR
145
146 g_type_add_interface_static (list_store_type,
93763ad5
WS
147 GTK_TYPE_TREE_MODEL,
148 &tree_model_info);
790b137e
RR
149 }
150
151 return list_store_type;
152}
153
1557c77b 154static GtkWxListStore *
e152afc3 155wxgtk_list_store_new(void)
1557c77b 156{
e152afc3
RR
157 GtkWxListStore *retval = (GtkWxListStore *) g_object_new (GTK_TYPE_WX_LIST_STORE, NULL);
158 return retval;
1557c77b
RR
159}
160
790b137e 161static void
1557c77b 162wxgtk_list_store_class_init (GtkWxListStoreClass *klass)
790b137e 163{
e152afc3
RR
164 list_parent_class = (GObjectClass*) g_type_class_peek_parent (klass);
165 GObjectClass *object_class = (GObjectClass*) klass;
790b137e
RR
166 object_class->finalize = wxgtk_list_store_finalize;
167}
168
169static void
170wxgtk_list_store_tree_model_init (GtkTreeModelIface *iface)
171{
172 iface->get_flags = wxgtk_list_store_get_flags;
173 iface->get_n_columns = wxgtk_list_store_get_n_columns;
174 iface->get_column_type = wxgtk_list_store_get_column_type;
175 iface->get_iter = wxgtk_list_store_get_iter;
176 iface->get_path = wxgtk_list_store_get_path;
177 iface->get_value = wxgtk_list_store_get_value;
178 iface->iter_next = wxgtk_list_store_iter_next;
179 iface->iter_children = wxgtk_list_store_iter_children;
180 iface->iter_has_child = wxgtk_list_store_iter_has_child;
181 iface->iter_n_children = wxgtk_list_store_iter_n_children;
182 iface->iter_nth_child = wxgtk_list_store_iter_nth_child;
183 iface->iter_parent = wxgtk_list_store_iter_parent;
184}
185
186static void
187wxgtk_list_store_init (GtkWxListStore *list_store)
188{
189 list_store->model = NULL;
1557c77b 190 list_store->stamp = g_random_int();
790b137e
RR
191}
192
193static void
194wxgtk_list_store_finalize (GObject *object)
195{
1557c77b 196 /* GtkWxListStore *list_store = GTK_WX_LIST_STORE (object); */
790b137e
RR
197
198 /* we need to sort out, which class deletes what */
111f83c4 199 /* delete list_store->model; */
790b137e
RR
200
201 /* must chain up */
e152afc3 202 (* list_parent_class->finalize) (object);
790b137e 203}
93763ad5 204
790b137e
RR
205} // extern "C"
206
207//-----------------------------------------------------------------------------
208// implement callbacks from wxGtkListStore class by letting
209// them call the methods of wxWidgets' wxDataViewListModel
210//-----------------------------------------------------------------------------
211
212static GtkTreeModelFlags
213wxgtk_list_store_get_flags (GtkTreeModel *tree_model)
214{
1557c77b 215 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), (GtkTreeModelFlags)0 );
790b137e 216
67cbdfc1
RR
217 // GTK+ list store uses a linked list for storing the
218 // items and a pointer to a child is used as the member
219 // field of a GtkTreeIter. This means that the iter is
220 // valid in the GtkListStore as long as the child exists.
221 // We use the index of the row and since the index of a
222 // specific row will change if a row above is deleted,
223 // the iter does not persist
224 return /* GTK_TREE_MODEL_ITERS_PERSIST | */ GTK_TREE_MODEL_LIST_ONLY;
790b137e
RR
225}
226
227static gint
228wxgtk_list_store_get_n_columns (GtkTreeModel *tree_model)
229{
230 GtkWxListStore *list_store = (GtkWxListStore *) tree_model;
231 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), 0);
232
239eaa41 233 return list_store->model->GetNumberOfCols();
790b137e
RR
234}
235
236static GType
237wxgtk_list_store_get_column_type (GtkTreeModel *tree_model,
93763ad5 238 gint index)
790b137e
RR
239{
240 GtkWxListStore *list_store = (GtkWxListStore *) tree_model;
241 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), G_TYPE_INVALID);
242
1557c77b 243 GType gtype = G_TYPE_INVALID;
93763ad5 244
1557c77b 245 wxString wxtype = list_store->model->GetColType( (size_t) index );
93763ad5 246
1557c77b
RR
247 if (wxtype == wxT("string"))
248 gtype = G_TYPE_STRING;
790b137e
RR
249
250 return gtype;
251}
252
253static gboolean
254wxgtk_list_store_get_iter (GtkTreeModel *tree_model,
93763ad5
WS
255 GtkTreeIter *iter,
256 GtkTreePath *path)
790b137e
RR
257{
258 GtkWxListStore *list_store = (GtkWxListStore *) tree_model;
259 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), FALSE);
260 g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE);
261
1557c77b 262 size_t i = (size_t)gtk_tree_path_get_indices (path)[0];
790b137e 263
1557c77b 264 if (i >= list_store->model->GetNumberOfRows())
239eaa41 265 return FALSE;
790b137e 266
239eaa41
RR
267 iter->stamp = list_store->stamp;
268 // user_data is just the index
269 iter->user_data = (gpointer) i;
790b137e
RR
270
271 return TRUE;
272}
273
274static GtkTreePath *
275wxgtk_list_store_get_path (GtkTreeModel *tree_model,
93763ad5 276 GtkTreeIter *iter)
790b137e 277{
790b137e 278 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), NULL);
239eaa41 279 g_return_val_if_fail (iter->stamp == GTK_WX_LIST_STORE (tree_model)->stamp, NULL);
93763ad5 280
239eaa41
RR
281 GtkTreePath *retval = gtk_tree_path_new ();
282 // user_data is just the index
7a9f5d5a 283 int i = (wxUIntPtr) iter->user_data;
239eaa41
RR
284 gtk_tree_path_append_index (retval, i);
285 return retval;
790b137e
RR
286}
287
288static void
289wxgtk_list_store_get_value (GtkTreeModel *tree_model,
93763ad5
WS
290 GtkTreeIter *iter,
291 gint column,
292 GValue *value)
790b137e 293{
1557c77b 294 GtkWxListStore *list_store = (GtkWxListStore *) tree_model;
790b137e 295 g_return_if_fail (GTK_IS_WX_LIST_STORE (tree_model) );
239eaa41 296
1557c77b
RR
297 wxDataViewListModel *model = list_store->model;
298 wxString mtype = model->GetColType( (size_t) column );
299 if (mtype == wxT("string"))
300 {
3f3af7e7 301 wxVariant variant;
1557c77b 302 g_value_init( value, G_TYPE_STRING );
3f3af7e7 303 model->GetValue( variant, (size_t) column, (size_t) iter->user_data );
1557c77b
RR
304 g_value_set_string( value, wxGTK_CONV(variant.GetString()) );
305 }
306 else
307 {
308 }
93763ad5 309
790b137e
RR
310#if 0
311 GtkTreeDataList *list;
312 gint tmp_column = column;
313
314 g_return_if_fail (column < GTK_LIST_STORE (tree_model)->n_columns);
315 g_return_if_fail (GTK_LIST_STORE (tree_model)->stamp == iter->stamp);
316
317 list = G_SLIST (iter->user_data)->data;
318
319 while (tmp_column-- > 0 && list)
320 list = list->next;
321
322 if (list == NULL)
323 g_value_init (value, GTK_LIST_STORE (tree_model)->column_headers[column]);
324 else
325 _gtk_tree_data_list_node_to_value (list,
93763ad5
WS
326 GTK_LIST_STORE (tree_model)->column_headers[column],
327 value);
790b137e
RR
328#endif
329
330}
331
332static gboolean
333wxgtk_list_store_iter_next (GtkTreeModel *tree_model,
93763ad5 334 GtkTreeIter *iter)
790b137e 335{
790b137e 336 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), FALSE);
1557c77b 337 GtkWxListStore *list_store = (GtkWxListStore *) tree_model;
93763ad5 338
67cbdfc1 339 g_return_val_if_fail (list_store->stamp == iter->stamp, FALSE);
790b137e 340
7a9f5d5a 341 int n = (wxUIntPtr) iter->user_data;
93763ad5 342
67cbdfc1
RR
343 if (n == -1)
344 return FALSE;
93763ad5 345
1a367564 346 if (n >= (int) list_store->model->GetNumberOfRows()-1)
67cbdfc1 347 return FALSE;
93763ad5 348
111f83c4 349 iter->user_data = (gpointer) ++n;
790b137e 350
67cbdfc1 351 return TRUE;
790b137e
RR
352}
353
354static gboolean
355wxgtk_list_store_iter_children (GtkTreeModel *tree_model,
93763ad5
WS
356 GtkTreeIter *iter,
357 GtkTreeIter *parent)
790b137e 358{
67cbdfc1 359 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), FALSE);
1557c77b 360 GtkWxListStore *list_store = (GtkWxListStore *) tree_model;
93763ad5 361
67cbdfc1 362 // this is a list, nodes have no children
790b137e
RR
363 if (parent)
364 return FALSE;
365
67cbdfc1
RR
366 iter->stamp = list_store->stamp;
367 iter->user_data = (gpointer) -1;
93763ad5 368
67cbdfc1 369 return TRUE;
790b137e
RR
370}
371
372static gboolean
373wxgtk_list_store_iter_has_child (GtkTreeModel *tree_model,
93763ad5 374 GtkTreeIter *iter)
790b137e
RR
375{
376 return FALSE;
377}
378
379static gint
380wxgtk_list_store_iter_n_children (GtkTreeModel *tree_model,
93763ad5 381 GtkTreeIter *iter)
790b137e
RR
382{
383 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), -1);
1557c77b 384 GtkWxListStore *list_store = (GtkWxListStore *) tree_model;
93763ad5 385
790b137e 386 if (iter == NULL)
1557c77b 387 return (gint) list_store->model->GetNumberOfRows();
790b137e 388
67cbdfc1 389 g_return_val_if_fail (list_store->stamp == iter->stamp, -1);
93763ad5 390
790b137e
RR
391 return 0;
392}
393
394static gboolean
395wxgtk_list_store_iter_nth_child (GtkTreeModel *tree_model,
93763ad5
WS
396 GtkTreeIter *iter,
397 GtkTreeIter *parent,
398 gint n)
790b137e 399{
67cbdfc1 400 g_return_val_if_fail (GTK_IS_WX_LIST_STORE (tree_model), FALSE);
1557c77b 401 GtkWxListStore *list_store = (GtkWxListStore *) tree_model;
93763ad5 402
67cbdfc1
RR
403 if (parent)
404 return FALSE;
790b137e 405
67cbdfc1
RR
406 if (n < 0)
407 return FALSE;
93763ad5 408
1557c77b 409 if (n >= (gint) list_store->model->GetNumberOfRows())
67cbdfc1 410 return FALSE;
790b137e 411
67cbdfc1
RR
412 iter->stamp = list_store->stamp;
413 iter->user_data = (gpointer) n;
93763ad5 414
67cbdfc1 415 return TRUE;
790b137e
RR
416}
417
418static gboolean
419wxgtk_list_store_iter_parent (GtkTreeModel *tree_model,
93763ad5
WS
420 GtkTreeIter *iter,
421 GtkTreeIter *child)
790b137e
RR
422{
423 return FALSE;
424}
425
e152afc3
RR
426//-----------------------------------------------------------------------------
427// define new GTK+ class wxGtkCellRenderer
428//-----------------------------------------------------------------------------
429
430extern "C" {
431
432#define GTK_TYPE_WX_CELL_RENDERER (gtk_wx_cell_renderer_get_type ())
433#define GTK_WX_CELL_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_WX_CELL_RENDERER, GtkWxCellRenderer))
434#define GTK_WX_CELL_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_WX_CELL_RENDERER, GtkWxCellRendererClass))
435#define GTK_IS_WX_CELL_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_WX_CELL_RENDERER))
436#define GTK_IS_WX_CELL_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_WX_CELL_RENDERER))
437#define GTK_WX_CELL_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_WX_CELL_RENDERER, GtkWxCellRendererClass))
438
439GType gtk_wx_cell_renderer_get_type (void);
440
441typedef struct _GtkWxCellRenderer GtkWxCellRenderer;
442typedef struct _GtkWxCellRendererClass GtkWxCellRendererClass;
443
444struct _GtkWxCellRenderer
445{
446 GtkCellRenderer parent;
447
448 /*< private >*/
449 wxDataViewCustomCell *cell;
4d496ecb 450 guint32 last_click;
e152afc3
RR
451};
452
453struct _GtkWxCellRendererClass
454{
455 GtkCellRendererClass cell_parent_class;
e152afc3
RR
456};
457
458
459static GtkCellRenderer *gtk_wx_cell_renderer_new (void);
553f7d8f
RR
460static void gtk_wx_cell_renderer_init (
461 GtkWxCellRenderer *cell );
462static void gtk_wx_cell_renderer_class_init(
463 GtkWxCellRendererClass *klass );
464static void gtk_wx_cell_renderer_finalize (
465 GObject *object );
466static void gtk_wx_cell_renderer_get_size (
467 GtkCellRenderer *cell,
93763ad5
WS
468 GtkWidget *widget,
469 GdkRectangle *rectangle,
470 gint *x_offset,
471 gint *y_offset,
472 gint *width,
473 gint *height );
553f7d8f
RR
474static void gtk_wx_cell_renderer_render (
475 GtkCellRenderer *cell,
93763ad5
WS
476 GdkWindow *window,
477 GtkWidget *widget,
478 GdkRectangle *background_area,
479 GdkRectangle *cell_area,
480 GdkRectangle *expose_area,
481 GtkCellRendererState flags );
553f7d8f
RR
482static gboolean gtk_wx_cell_renderer_activate(
483 GtkCellRenderer *cell,
484 GdkEvent *event,
485 GtkWidget *widget,
486 const gchar *path,
487 GdkRectangle *background_area,
488 GdkRectangle *cell_area,
489 GtkCellRendererState flags );
e152afc3
RR
490
491static GObjectClass *cell_parent_class = NULL;
492
493} // extern "C"
494
93763ad5 495GType
e152afc3
RR
496gtk_wx_cell_renderer_get_type (void)
497{
553f7d8f 498 static GType cell_wx_type = 0;
e152afc3 499
553f7d8f 500 if (!cell_wx_type)
e152afc3 501 {
553f7d8f
RR
502 static const GTypeInfo cell_wx_info =
503 {
504 sizeof (GtkWxCellRendererClass),
93763ad5
WS
505 NULL, /* base_init */
506 NULL, /* base_finalize */
553f7d8f 507 (GClassInitFunc) gtk_wx_cell_renderer_class_init,
93763ad5
WS
508 NULL, /* class_finalize */
509 NULL, /* class_data */
553f7d8f
RR
510 sizeof (GtkWxCellRenderer),
511 0, /* n_preallocs */
512 (GInstanceInitFunc) gtk_wx_cell_renderer_init,
513 };
514
93763ad5 515 cell_wx_type = g_type_register_static( GTK_TYPE_CELL_RENDERER,
553f7d8f 516 "GtkWxCellRenderer", &cell_wx_info, (GTypeFlags)0 );
e152afc3
RR
517 }
518
553f7d8f 519 return cell_wx_type;
e152afc3
RR
520}
521
522static void
523gtk_wx_cell_renderer_init (GtkWxCellRenderer *cell)
524{
525 cell->cell = NULL;
4d496ecb 526 cell->last_click = 0;
e152afc3
RR
527}
528
529static void
530gtk_wx_cell_renderer_class_init (GtkWxCellRendererClass *klass)
531{
532 GObjectClass *object_class = G_OBJECT_CLASS (klass);
533 GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (klass);
534
535 cell_parent_class = (GObjectClass*) g_type_class_peek_parent (klass);
536
537 object_class->finalize = gtk_wx_cell_renderer_finalize;
538
539 cell_class->get_size = gtk_wx_cell_renderer_get_size;
540 cell_class->render = gtk_wx_cell_renderer_render;
553f7d8f 541 cell_class->activate = gtk_wx_cell_renderer_activate;
e152afc3
RR
542}
543
544static void
545gtk_wx_cell_renderer_finalize (GObject *object)
546{
547 /* must chain up */
548 (* G_OBJECT_CLASS (cell_parent_class)->finalize) (object);
549}
550
551GtkCellRenderer*
552gtk_wx_cell_renderer_new (void)
553{
554 return (GtkCellRenderer*) g_object_new (GTK_TYPE_WX_CELL_RENDERER, NULL);
555}
556
557static void
558gtk_wx_cell_renderer_get_size (GtkCellRenderer *renderer,
93763ad5
WS
559 GtkWidget *widget,
560 GdkRectangle *cell_area,
561 gint *x_offset,
562 gint *y_offset,
563 gint *width,
564 gint *height)
e152afc3
RR
565{
566 GtkWxCellRenderer *wxrenderer = (GtkWxCellRenderer *) renderer;
567 wxDataViewCustomCell *cell = wxrenderer->cell;
93763ad5 568
e152afc3
RR
569 wxSize size = cell->GetSize();
570
571 gint calc_width = (gint) renderer->xpad * 2 + size.x;
572 gint calc_height = (gint) renderer->ypad * 2 + size.y;
93763ad5
WS
573
574 if (x_offset)
e152afc3 575 *x_offset = 0;
93763ad5 576 if (y_offset)
e152afc3
RR
577 *y_offset = 0;
578
579 if (cell_area && size.x > 0 && size.y > 0)
580 {
581 if (x_offset)
93763ad5 582 {
e152afc3
RR
583 *x_offset = (gint)((renderer->xalign *
584 (cell_area->width - calc_width - 2 * renderer->xpad)));
585 *x_offset = MAX (*x_offset, 0) + renderer->xpad;
93763ad5 586 }
e152afc3
RR
587 if (y_offset)
588 {
589 *y_offset = (gint)((renderer->yalign *
590 (cell_area->height - calc_height - 2 * renderer->ypad)));
591 *y_offset = MAX (*y_offset, 0) + renderer->ypad;
592 }
593 }
594
595 if (width)
596 *width = calc_width;
93763ad5 597
e152afc3
RR
598 if (height)
599 *height = calc_height;
600}
601
602static void
603gtk_wx_cell_renderer_render (GtkCellRenderer *renderer,
93763ad5
WS
604 GdkWindow *window,
605 GtkWidget *widget,
606 GdkRectangle *background_area,
607 GdkRectangle *cell_area,
608 GdkRectangle *expose_area,
609 GtkCellRendererState flags)
e152afc3
RR
610
611{
612 GtkWxCellRenderer *wxrenderer = (GtkWxCellRenderer *) renderer;
613 wxDataViewCustomCell *cell = wxrenderer->cell;
93763ad5 614
e152afc3
RR
615 GdkRectangle rect;
616 gtk_wx_cell_renderer_get_size (renderer, widget, cell_area,
93763ad5
WS
617 &rect.x,
618 &rect.y,
619 &rect.width,
620 &rect.height);
e152afc3
RR
621
622 rect.x += cell_area->x;
623 rect.y += cell_area->y;
624 rect.width -= renderer->xpad * 2;
625 rect.height -= renderer->ypad * 2;
93763ad5 626
e152afc3
RR
627 GdkRectangle dummy;
628 if (gdk_rectangle_intersect (expose_area, &rect, &dummy))
629 {
630 wxRect renderrect( rect.x, rect.y, rect.width, rect.height );
631 wxWindowDC* dc = (wxWindowDC*) cell->GetDC();
4d496ecb
RR
632 if (dc->m_window == NULL)
633 {
634 dc->m_window = window;
635 dc->SetUpDC();
636 }
93763ad5 637
e152afc3
RR
638 int state = 0;
639 if (flags & GTK_CELL_RENDERER_SELECTED)
640 state |= wxDATAVIEW_CELL_SELECTED;
641 if (flags & GTK_CELL_RENDERER_PRELIT)
642 state |= wxDATAVIEW_CELL_PRELIT;
643 if (flags & GTK_CELL_RENDERER_INSENSITIVE)
644 state |= wxDATAVIEW_CELL_INSENSITIVE;
645 if (flags & GTK_CELL_RENDERER_INSENSITIVE)
646 state |= wxDATAVIEW_CELL_INSENSITIVE;
647 if (flags & GTK_CELL_RENDERER_FOCUSED)
648 state |= wxDATAVIEW_CELL_FOCUSED;
649 cell->Render( renderrect, dc, state );
93763ad5 650 }
e152afc3
RR
651}
652
93763ad5 653static gboolean
553f7d8f
RR
654gtk_wx_cell_renderer_activate(
655 GtkCellRenderer *renderer,
656 GdkEvent *event,
657 GtkWidget *widget,
658 const gchar *path,
659 GdkRectangle *background_area,
660 GdkRectangle *cell_area,
661 GtkCellRendererState flags )
662{
663 GtkWxCellRenderer *wxrenderer = (GtkWxCellRenderer *) renderer;
664 wxDataViewCustomCell *cell = wxrenderer->cell;
93763ad5 665
553f7d8f
RR
666 GdkRectangle rect;
667 gtk_wx_cell_renderer_get_size (renderer, widget, cell_area,
93763ad5
WS
668 &rect.x,
669 &rect.y,
670 &rect.width,
671 &rect.height);
553f7d8f
RR
672
673 rect.x += cell_area->x;
674 rect.y += cell_area->y;
675 rect.width -= renderer->xpad * 2;
676 rect.height -= renderer->ypad * 2;
93763ad5 677
553f7d8f 678 wxRect renderrect( rect.x, rect.y, rect.width, rect.height );
93763ad5 679
4d496ecb 680 wxDataViewListModel *model = cell->GetOwner()->GetOwner()->GetModel();
93763ad5 681
4d496ecb
RR
682 GtkTreePath *treepath = gtk_tree_path_new_from_string( path );
683 size_t model_row = (size_t)gtk_tree_path_get_indices (treepath)[0];
684 gtk_tree_path_free( treepath );
93763ad5 685
4d496ecb 686 size_t model_col = cell->GetOwner()->GetModelColumn();
93763ad5 687
4d496ecb
RR
688 if (event->type == GDK_BUTTON_PRESS)
689 {
690 GdkEventButton *button_event = (GdkEventButton*) event;
93763ad5 691 wxPoint pt( ((int) button_event->x) - renderrect.x,
4d496ecb 692 ((int) button_event->y) - renderrect.y );
93763ad5 693
4d496ecb
RR
694 bool ret = false;
695 if (button_event->button == 1)
696 {
697 if (cell->LeftClick( pt, renderrect, model, model_col, model_row ))
698 ret = true;
7ea3a0de 699 // TODO: query system double-click time
4d496ecb
RR
700 if (button_event->time - wxrenderer->last_click < 400)
701 if (cell->Activate( renderrect, model, model_col, model_row ))
702 ret = true;
703 }
704 if (button_event->button == 3)
705 {
706 if (cell->RightClick( pt, renderrect, model, model_col, model_row ))
707 ret = true;
708 }
93763ad5 709
4d496ecb 710 wxrenderer->last_click = button_event->time;
93763ad5 711
4d496ecb
RR
712 return ret;
713 }
93763ad5 714
4d496ecb 715 return false;
553f7d8f
RR
716}
717
93763ad5 718// ---------------------------------------------------------
6e2e590f 719// wxGtkDataViewListModelNotifier
93763ad5 720// ---------------------------------------------------------
6e2e590f
RR
721
722class wxGtkDataViewListModelNotifier: public wxDataViewListModelNotifier
723{
724public:
725 wxGtkDataViewListModelNotifier( GtkWxListStore* gtk_store, wxDataViewListModel *wx_model );
93763ad5 726
6e2e590f
RR
727 virtual bool RowAppended();
728 virtual bool RowPrepended();
729 virtual bool RowInserted( size_t before );
730 virtual bool RowDeleted( size_t row );
731 virtual bool RowChanged( size_t row );
a7f61f76 732 virtual bool ValueChanged( size_t col, size_t row );
4eccd3a1 733 virtual bool RowsReordered( size_t *new_order );
6e2e590f 734 virtual bool Cleared();
93763ad5 735
6e2e590f
RR
736 GtkWxListStore *m_gtk_store;
737 wxDataViewListModel *m_wx_model;
738};
739
93763ad5 740// ---------------------------------------------------------
6e2e590f 741// wxGtkDataViewListModelNotifier
93763ad5 742// ---------------------------------------------------------
6e2e590f 743
93763ad5 744wxGtkDataViewListModelNotifier::wxGtkDataViewListModelNotifier(
6e2e590f
RR
745 GtkWxListStore* gtk_store, wxDataViewListModel *wx_model )
746{
747 m_gtk_store = gtk_store;
748 m_wx_model = wx_model;
749}
93763ad5 750
6e2e590f
RR
751bool wxGtkDataViewListModelNotifier::RowAppended()
752{
753 size_t pos = m_wx_model->GetNumberOfRows()-1;
93763ad5 754
6e2e590f
RR
755 GtkTreeIter iter;
756 iter.stamp = m_gtk_store->stamp;
757 iter.user_data = (gpointer) pos;
93763ad5 758
6e2e590f
RR
759 GtkTreePath *path = gtk_tree_path_new ();
760 gtk_tree_path_append_index (path, (gint) pos);
761 gtk_tree_model_row_inserted (GTK_TREE_MODEL (m_gtk_store), path, &iter);
762 gtk_tree_path_free (path);
93763ad5 763
6e2e590f
RR
764 return true;
765}
766
767bool wxGtkDataViewListModelNotifier::RowPrepended()
768{
605c2c4a
RR
769 GtkTreeIter iter;
770 iter.stamp = m_gtk_store->stamp;
771 iter.user_data = (gpointer) 0;
93763ad5 772
605c2c4a
RR
773 GtkTreePath *path = gtk_tree_path_new ();
774 gtk_tree_path_append_index (path, (gint) 0);
775 gtk_tree_model_row_inserted (GTK_TREE_MODEL (m_gtk_store), path, &iter);
776 gtk_tree_path_free (path);
93763ad5 777
605c2c4a 778 return true;
6e2e590f
RR
779}
780
781bool wxGtkDataViewListModelNotifier::RowInserted( size_t before )
782{
783 return false;
784}
785
786bool wxGtkDataViewListModelNotifier::RowDeleted( size_t row )
787{
788 return false;
789}
790
791bool wxGtkDataViewListModelNotifier::RowChanged( size_t row )
792{
a7f61f76
RR
793 GtkTreeIter iter;
794 iter.stamp = m_gtk_store->stamp;
795 iter.user_data = (gpointer) row;
796 GtkTreePath *path = gtk_tree_model_get_path (GTK_TREE_MODEL (m_gtk_store), &iter);
797 gtk_tree_model_row_changed (GTK_TREE_MODEL (m_gtk_store), path, &iter);
798 gtk_tree_path_free (path);
799
800 return true;
6e2e590f
RR
801}
802
8f850e28 803bool wxGtkDataViewListModelNotifier::ValueChanged( size_t model_col, size_t model_row )
6e2e590f 804{
4eccd3a1 805 // This adds GTK+'s missing MVC logic for ValueChanged
8f850e28
RR
806 wxNode *node = GetOwner()->m_viewingColumns.GetFirst();
807 while (node)
808 {
809 wxDataViewViewingColumn* viewing_column = (wxDataViewViewingColumn*) node->GetData();
810 if (viewing_column->m_modelColumn == model_col)
811 {
812 GtkTreeView *widget = GTK_TREE_VIEW(viewing_column->m_viewColumn->GetOwner()->m_treeview);
813 GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN(viewing_column->m_viewColumn->GetGtkHandle());
814
815 // Get cell area
816 GtkTreePath *path = gtk_tree_path_new();
817 gtk_tree_path_append_index( path, model_row );
818 GdkRectangle cell_area;
819 gtk_tree_view_get_cell_area( widget, path, column, &cell_area );
93763ad5 820 gtk_tree_path_free( path );
8f850e28
RR
821
822 int ydiff = column->button->allocation.height;
823 // Redraw
93763ad5 824 gtk_widget_queue_draw_area( GTK_WIDGET(widget),
8f850e28
RR
825 cell_area.x, ydiff + cell_area.y, cell_area.width, cell_area.height );
826 }
827
828 node = node->GetNext();
829 }
93763ad5 830
8f850e28 831 return true;
6e2e590f
RR
832}
833
4eccd3a1
RR
834bool wxGtkDataViewListModelNotifier::RowsReordered( size_t *new_order )
835{
836 // Assume sizeof(size_t)= == sizeof(gint)
837
838 GtkTreePath *path = gtk_tree_path_new ();
839 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (m_gtk_store), path, NULL, (gint*)new_order);
840 gtk_tree_path_free (path);
841
842 // This adds GTK+'s missing MVC logic for RowsReordered
843 wxNode *node = GetOwner()->m_viewingColumns.GetFirst();
844 while (node)
845 {
846 wxDataViewViewingColumn* viewing_column = (wxDataViewViewingColumn*) node->GetData();
847 GtkTreeView *widget = GTK_TREE_VIEW(viewing_column->m_viewColumn->GetOwner()->m_treeview);
848 // Doesn't work yet...
93763ad5 849 gtk_widget_queue_draw( GTK_WIDGET(widget) );
4eccd3a1
RR
850
851 node = node->GetNext();
852 }
93763ad5 853
4eccd3a1
RR
854 return true;
855}
856
6e2e590f
RR
857bool wxGtkDataViewListModelNotifier::Cleared()
858{
859 return false;
860}
861
93763ad5 862// ---------------------------------------------------------
6842a71a 863// wxDataViewCell
93763ad5 864// ---------------------------------------------------------
6842a71a
RR
865
866IMPLEMENT_ABSTRACT_CLASS(wxDataViewCell, wxDataViewCellBase)
867
868wxDataViewCell::wxDataViewCell( const wxString &varianttype, wxDataViewCellMode mode ) :
869 wxDataViewCellBase( varianttype, mode )
870{
871 m_renderer = NULL;
872}
873
93763ad5 874// ---------------------------------------------------------
6842a71a 875// wxDataViewTextCell
93763ad5 876// ---------------------------------------------------------
6842a71a 877
a7f61f76 878extern "C" {
93763ad5 879static void wxGtkTextRendererEditedCallback( GtkCellRendererText *renderer,
a7f61f76
RR
880 gchar *arg1, gchar *arg2, gpointer user_data );
881}
882
93763ad5 883static void wxGtkTextRendererEditedCallback( GtkCellRendererText *renderer,
a7f61f76
RR
884 gchar *arg1, gchar *arg2, gpointer user_data )
885{
886 wxDataViewTextCell *cell = (wxDataViewTextCell*) user_data;
93763ad5 887
a7f61f76
RR
888 wxString tmp = wxGTK_CONV_BACK( arg2 );
889 wxVariant value = tmp;
890 if (!cell->Validate( value ))
891 return;
93763ad5 892
a7f61f76 893 wxDataViewListModel *model = cell->GetOwner()->GetOwner()->GetModel();
93763ad5 894
a7f61f76
RR
895 GtkTreePath *path = gtk_tree_path_new_from_string( arg1 );
896 size_t model_row = (size_t)gtk_tree_path_get_indices (path)[0];
897 gtk_tree_path_free( path );
93763ad5 898
a7f61f76 899 size_t model_col = cell->GetOwner()->GetModelColumn();
93763ad5 900
a7f61f76
RR
901 model->SetValue( value, model_col, model_row );
902 model->ValueChanged( model_col, model_row );
903}
904
6842a71a
RR
905IMPLEMENT_ABSTRACT_CLASS(wxDataViewTextCell, wxDataViewCell)
906
907wxDataViewTextCell::wxDataViewTextCell( const wxString &varianttype, wxDataViewCellMode mode ) :
908 wxDataViewCell( varianttype, mode )
909{
910 m_renderer = (void*) gtk_cell_renderer_text_new();
93763ad5 911
a7f61f76
RR
912 if (m_mode & wxDATAVIEW_CELL_EDITABLE)
913 {
914 GValue gvalue = { 0, };
915 g_value_init( &gvalue, G_TYPE_BOOLEAN );
916 g_value_set_boolean( &gvalue, true );
917 g_object_set_property( G_OBJECT(m_renderer), "editable", &gvalue );
918 g_value_unset( &gvalue );
93763ad5 919
a7f61f76
RR
920 g_signal_connect_after( m_renderer, "edited", G_CALLBACK(wxGtkTextRendererEditedCallback), this );
921 }
6842a71a 922}
790b137e 923
7b4fde82
RR
924bool wxDataViewTextCell::SetValue( const wxVariant &value )
925{
926 wxString tmp = value;
93763ad5 927
7b4fde82
RR
928 GValue gvalue = { 0, };
929 g_value_init( &gvalue, G_TYPE_STRING );
930 g_value_set_string( &gvalue, wxGTK_CONV( tmp ) );
931 g_object_set_property( G_OBJECT(m_renderer), "text", &gvalue );
932 g_value_unset( &gvalue );
93763ad5 933
7b4fde82
RR
934 return true;
935}
936
a7f61f76
RR
937bool wxDataViewTextCell::GetValue( wxVariant &value )
938{
939 GValue gvalue = { 0, };
940 g_value_init( &gvalue, G_TYPE_STRING );
941 g_object_get_property( G_OBJECT(m_renderer), "text", &gvalue );
93763ad5 942 wxString tmp = wxGTK_CONV_BACK( g_value_get_string( &gvalue ) );
a7f61f76 943 g_value_unset( &gvalue );
93763ad5 944
a7f61f76
RR
945 value = tmp;
946
947 return true;
948}
949
93763ad5 950// ---------------------------------------------------------
605c2c4a 951// wxDataViewToggleCell
93763ad5 952// ---------------------------------------------------------
fa28826d 953
605c2c4a 954extern "C" {
93763ad5 955static void wxGtkToggleRendererToggledCallback( GtkCellRendererToggle *renderer,
605c2c4a
RR
956 gchar *path, gpointer user_data );
957}
958
93763ad5 959static void wxGtkToggleRendererToggledCallback( GtkCellRendererToggle *renderer,
605c2c4a
RR
960 gchar *path, gpointer user_data )
961{
962 wxDataViewToggleCell *cell = (wxDataViewToggleCell*) user_data;
963
93763ad5 964 // get old value
605c2c4a
RR
965 GValue gvalue = { 0, };
966 g_value_init( &gvalue, G_TYPE_BOOLEAN );
967 g_object_get_property( G_OBJECT(renderer), "active", &gvalue );
93763ad5 968 bool tmp = g_value_get_boolean( &gvalue );
605c2c4a
RR
969 g_value_unset( &gvalue );
970 // invert it
971 tmp = !tmp;
93763ad5 972
605c2c4a
RR
973 wxVariant value = tmp;
974 if (!cell->Validate( value ))
975 return;
93763ad5 976
605c2c4a 977 wxDataViewListModel *model = cell->GetOwner()->GetOwner()->GetModel();
93763ad5 978
605c2c4a
RR
979 GtkTreePath *gtk_path = gtk_tree_path_new_from_string( path );
980 size_t model_row = (size_t)gtk_tree_path_get_indices (gtk_path)[0];
981 gtk_tree_path_free( gtk_path );
93763ad5 982
605c2c4a 983 size_t model_col = cell->GetOwner()->GetModelColumn();
93763ad5 984
605c2c4a
RR
985 model->SetValue( value, model_col, model_row );
986 model->ValueChanged( model_col, model_row );
987}
988
989IMPLEMENT_ABSTRACT_CLASS(wxDataViewToggleCell, wxDataViewCell)
990
93763ad5 991wxDataViewToggleCell::wxDataViewToggleCell( const wxString &varianttype,
605c2c4a
RR
992 wxDataViewCellMode mode ) :
993 wxDataViewCell( varianttype, mode )
994{
995 m_renderer = (void*) gtk_cell_renderer_toggle_new();
93763ad5 996
0fdc2321 997 if (m_mode & wxDATAVIEW_CELL_ACTIVATABLE)
605c2c4a 998 {
553f7d8f
RR
999 g_signal_connect_after( m_renderer, "toggled", G_CALLBACK(wxGtkToggleRendererToggledCallback), this );
1000 }
1001 else
1002 {
1003
605c2c4a
RR
1004 GValue gvalue = { 0, };
1005 g_value_init( &gvalue, G_TYPE_BOOLEAN );
553f7d8f 1006 g_value_set_boolean( &gvalue, false );
605c2c4a
RR
1007 g_object_set_property( G_OBJECT(m_renderer), "activatable", &gvalue );
1008 g_value_unset( &gvalue );
553f7d8f
RR
1009
1010 GValue gvalue2 = { 0, };
1011 g_value_init( &gvalue2, gtk_cell_renderer_mode_get_type() );
1012 g_value_set_enum( &gvalue2, GTK_CELL_RENDERER_MODE_INERT );
1013 g_object_set_property( G_OBJECT(m_renderer), "mode", &gvalue2 );
1014 g_value_unset( &gvalue2 );
1015
605c2c4a
RR
1016 }
1017}
1018
1019bool wxDataViewToggleCell::SetValue( const wxVariant &value )
1020{
1021 bool tmp = value;
93763ad5 1022
605c2c4a
RR
1023 GValue gvalue = { 0, };
1024 g_value_init( &gvalue, G_TYPE_BOOLEAN );
1025 g_value_set_boolean( &gvalue, tmp );
1026 g_object_set_property( G_OBJECT(m_renderer), "active", &gvalue );
1027 g_value_unset( &gvalue );
93763ad5 1028
605c2c4a
RR
1029 return true;
1030}
1031
1032bool wxDataViewToggleCell::GetValue( wxVariant &value )
1033{
1034 GValue gvalue = { 0, };
1035 g_value_init( &gvalue, G_TYPE_BOOLEAN );
1036 g_object_get_property( G_OBJECT(m_renderer), "active", &gvalue );
93763ad5 1037 bool tmp = g_value_get_boolean( &gvalue );
605c2c4a 1038 g_value_unset( &gvalue );
93763ad5 1039
605c2c4a
RR
1040 value = tmp;
1041
1042 return true;
1043}
93763ad5
WS
1044
1045// ---------------------------------------------------------
e152afc3 1046// wxDataViewCustomCell
93763ad5 1047// ---------------------------------------------------------
e152afc3
RR
1048
1049class wxDataViewCtrlDC: public wxWindowDC
1050{
1051public:
1052 wxDataViewCtrlDC( wxDataViewCtrl *window )
1053 {
1a367564 1054 GtkWidget *widget = window->m_treeview;
e152afc3
RR
1055 // Set later
1056 m_window = NULL;
4d496ecb 1057
e152afc3
RR
1058 m_context = window->GtkGetPangoDefaultContext();
1059 m_layout = pango_layout_new( m_context );
1060 m_fontdesc = pango_font_description_copy( widget->style->font_desc );
1061
1062 m_cmap = gtk_widget_get_colormap( widget ? widget : window->m_widget );
1063
4d496ecb
RR
1064 // Set m_window later
1065 // SetUpDC();
1066 // m_owner = window;
e152afc3
RR
1067 }
1068};
1069
93763ad5 1070// ---------------------------------------------------------
e152afc3 1071// wxDataViewCustomCell
93763ad5 1072// ---------------------------------------------------------
e152afc3
RR
1073
1074IMPLEMENT_ABSTRACT_CLASS(wxDataViewCustomCell, wxDataViewCell)
1075
93763ad5 1076wxDataViewCustomCell::wxDataViewCustomCell( const wxString &varianttype,
ad63bf41 1077 wxDataViewCellMode mode, bool no_init ) :
e152afc3
RR
1078 wxDataViewCell( varianttype, mode )
1079{
1080 m_dc = NULL;
93763ad5 1081
ad63bf41
RR
1082 if (no_init)
1083 m_renderer = NULL;
1084 else
1085 Init();
1086}
1087
1088bool wxDataViewCustomCell::Init()
1089{
e152afc3
RR
1090 GtkWxCellRenderer *renderer = (GtkWxCellRenderer *) gtk_wx_cell_renderer_new();
1091 renderer->cell = this;
93763ad5 1092
e152afc3 1093 m_renderer = (void*) renderer;
93763ad5 1094
553f7d8f
RR
1095 if (m_mode & wxDATAVIEW_CELL_ACTIVATABLE)
1096 {
1097 GValue gvalue = { 0, };
1098 g_value_init( &gvalue, gtk_cell_renderer_mode_get_type() );
1099 g_value_set_enum( &gvalue, GTK_CELL_RENDERER_MODE_ACTIVATABLE );
1100 g_object_set_property( G_OBJECT(m_renderer), "mode", &gvalue );
1101 g_value_unset( &gvalue );
1102 }
93763ad5 1103
ad63bf41 1104 return true;
e152afc3
RR
1105}
1106
1107wxDataViewCustomCell::~wxDataViewCustomCell()
1108{
1109 if (m_dc)
1110 delete m_dc;
1111}
1112
1113wxDC *wxDataViewCustomCell::GetDC()
1114{
1115 if (m_dc == NULL)
4d496ecb
RR
1116 {
1117 if (GetOwner() == NULL)
1118 return NULL;
1119 if (GetOwner()->GetOwner() == NULL)
1120 return NULL;
e152afc3 1121 m_dc = new wxDataViewCtrlDC( GetOwner()->GetOwner() );
4d496ecb 1122 }
93763ad5 1123
e152afc3
RR
1124 return m_dc;
1125}
93763ad5
WS
1126
1127// ---------------------------------------------------------
ad63bf41 1128// wxDataViewProgressCell
93763ad5 1129// ---------------------------------------------------------
ad63bf41
RR
1130
1131IMPLEMENT_ABSTRACT_CLASS(wxDataViewProgressCell, wxDataViewCustomCell)
1132
93763ad5 1133wxDataViewProgressCell::wxDataViewProgressCell( const wxString &label,
ad63bf41 1134 const wxString &varianttype, wxDataViewCellMode mode ) :
93763ad5 1135 wxDataViewCustomCell( varianttype, mode, true )
ad63bf41
RR
1136{
1137 m_label = label;
1138 m_value = 0;
93763ad5 1139
ad63bf41
RR
1140#ifdef __WXGTK26__
1141 if (!gtk_check_version(2,6,0))
1142 {
1143 m_renderer = (void*) gtk_cell_renderer_progress_new();
93763ad5 1144
ad63bf41
RR
1145 GValue gvalue = { 0, };
1146 g_value_init( &gvalue, G_TYPE_STRING );
1147 g_value_set_boolean( &gvalue, wxGTK_CONV(m_label) );
1148 g_object_set_property( G_OBJECT(m_renderer), "text", &gvalue );
1149 g_value_unset( &gvalue );
1150 }
1151 else
1152#endif
1153 {
1154 // Use custom cell code
1155 wxDataViewCustomCell::Init();
1156 }
1157}
1158
1159wxDataViewProgressCell::~wxDataViewProgressCell()
1160{
1161}
1162
1163bool wxDataViewProgressCell::SetValue( const wxVariant &value )
1164{
1165#ifdef __WXGTK26__
1166 if (!gtk_check_version(2,6,0))
1167 {
1168 gint tmp = (int) value;
1169 GValue gvalue = { 0, };
1170 g_value_init( &gvalue, G_TYPE_INT );
1171 g_value_set_boolean( &gvalue, tmp );
1172 g_object_set_property( G_OBJECT(m_renderer), "value", &gvalue );
1173 g_value_unset( &gvalue );
1174 }
1175 else
1176#endif
1177 {
1178 m_value = (long) value;
93763ad5 1179
ad63bf41
RR
1180 if (m_value < 0) m_value = 0;
1181 if (m_value > 100) m_value = 100;
1182 }
93763ad5 1183
ad63bf41
RR
1184 return true;
1185}
93763ad5 1186
ad63bf41
RR
1187bool wxDataViewProgressCell::Render( wxRect cell, wxDC *dc, int state )
1188{
1189 double pct = (double)m_value / 100.0;
1190 wxRect bar = cell;
1191 bar.width = (int)(cell.width * pct);
1192 dc->SetPen( *wxTRANSPARENT_PEN );
1193 dc->SetBrush( *wxBLUE_BRUSH );
1194 dc->DrawRectangle( bar );
1195
1196 dc->SetBrush( *wxTRANSPARENT_BRUSH );
1197 dc->SetPen( *wxBLACK_PEN );
1198 dc->DrawRectangle( cell );
93763ad5 1199
ad63bf41
RR
1200 return true;
1201}
1202
1203wxSize wxDataViewProgressCell::GetSize()
1204{
1205 return wxSize(40,12);
1206}
93763ad5
WS
1207
1208// ---------------------------------------------------------
4d496ecb 1209// wxDataViewDateCell
93763ad5 1210// ---------------------------------------------------------
4d496ecb 1211
7ea3a0de
RR
1212class wxDataViewDateCellPopupTransient: public wxPopupTransientWindow
1213{
93763ad5 1214public:
7ea3a0de
RR
1215 wxDataViewDateCellPopupTransient( wxWindow* parent, wxDateTime *value,
1216 wxDataViewListModel *model, size_t col, size_t row ) :
1217 wxPopupTransientWindow( parent, wxBORDER_SIMPLE )
1218 {
1219 m_model = model;
1220 m_col = col;
1221 m_row = row;
1222 m_cal = new wxCalendarCtrl( this, -1, *value );
1223 wxBoxSizer *sizer = new wxBoxSizer( wxHORIZONTAL );
1224 sizer->Add( m_cal, 1, wxGROW );
1225 SetSizer( sizer );
1226 sizer->Fit( this );
1227 }
93763ad5 1228
7ea3a0de
RR
1229 virtual void OnDismiss()
1230 {
1231 }
93763ad5 1232
7ea3a0de 1233 void OnCalendar( wxCalendarEvent &event );
93763ad5 1234
7ea3a0de 1235 wxCalendarCtrl *m_cal;
93763ad5 1236 wxDataViewListModel *m_model;
7ea3a0de
RR
1237 size_t m_col;
1238 size_t m_row;
93763ad5 1239
7ea3a0de
RR
1240private:
1241 DECLARE_EVENT_TABLE()
1242};
1243
1244BEGIN_EVENT_TABLE(wxDataViewDateCellPopupTransient,wxPopupTransientWindow)
1245 EVT_CALENDAR( -1, wxDataViewDateCellPopupTransient::OnCalendar )
1246END_EVENT_TABLE()
1247
1248void wxDataViewDateCellPopupTransient::OnCalendar( wxCalendarEvent &event )
1249{
1250 wxDateTime date = event.GetDate();
1251 wxVariant value = date;
1252 m_model->SetValue( value, m_col, m_row );
1253 m_model->ValueChanged( m_col, m_row );
1254 DismissAndNotify();
1255}
1256
4d496ecb
RR
1257IMPLEMENT_ABSTRACT_CLASS(wxDataViewDateCell, wxDataViewCustomCell)
1258
1259wxDataViewDateCell::wxDataViewDateCell( const wxString &varianttype,
1260 wxDataViewCellMode mode ) :
1261 wxDataViewCustomCell( varianttype, mode )
1262{
1263}
93763ad5 1264
4d496ecb
RR
1265bool wxDataViewDateCell::SetValue( const wxVariant &value )
1266{
1267 m_date = value.GetDateTime();
93763ad5 1268
4d496ecb
RR
1269 return true;
1270}
1271
1272bool wxDataViewDateCell::Render( wxRect cell, wxDC *dc, int state )
1273{
1274 dc->SetFont( GetOwner()->GetOwner()->GetFont() );
1275 wxString tmp = m_date.FormatDate();
1276 dc->DrawText( tmp, cell.x, cell.y );
1277
1278 return true;
1279}
1280
1281wxSize wxDataViewDateCell::GetSize()
1282{
1283 wxDataViewCtrl* view = GetOwner()->GetOwner();
1284 wxString tmp = m_date.FormatDate();
1285 wxCoord x,y,d;
1286 view->GetTextExtent( tmp, &x, &y, &d );
1287 return wxSize(x,y+d);
1288}
1289
1290bool wxDataViewDateCell::Activate( wxRect cell, wxDataViewListModel *model, size_t col, size_t row )
1291{
3f3af7e7
RR
1292 wxVariant variant;
1293 model->GetValue( variant, col, row );
7ea3a0de
RR
1294 wxDateTime value = variant.GetDateTime();
1295
93763ad5 1296 wxDataViewDateCellPopupTransient *popup = new wxDataViewDateCellPopupTransient(
7ea3a0de
RR
1297 GetOwner()->GetOwner()->GetParent(), &value, model, col, row );
1298 wxPoint pos = wxGetMousePosition();
1299 popup->Move( pos );
1300 popup->Layout();
1301 popup->Popup( popup->m_cal );
4d496ecb
RR
1302
1303 return true;
1304}
1305
93763ad5 1306// ---------------------------------------------------------
605c2c4a 1307// wxDataViewColumn
93763ad5 1308// ---------------------------------------------------------
7b4fde82
RR
1309
1310extern "C" {
1311static void wxGtkTreeCellDataFunc( GtkTreeViewColumn *column,
1312 GtkCellRenderer *cell,
1313 GtkTreeModel *model,
1314 GtkTreeIter *iter,
1315 gpointer data );
1316}
1317
1318
1319static void wxGtkTreeCellDataFunc( GtkTreeViewColumn *column,
1320 GtkCellRenderer *renderer,
1321 GtkTreeModel *model,
1322 GtkTreeIter *iter,
1323 gpointer data )
1324{
1325 g_return_if_fail (GTK_IS_WX_LIST_STORE (model));
1326 GtkWxListStore *list_store = (GtkWxListStore *) model;
93763ad5 1327
7b4fde82 1328 wxDataViewCell *cell = (wxDataViewCell*) data;
a7f61f76
RR
1329
1330 size_t model_row = (size_t) iter->user_data;
93763ad5 1331
3f3af7e7
RR
1332 wxVariant value;
1333 list_store->model->GetValue( value, cell->GetOwner()->GetModelColumn(), model_row );
7b4fde82
RR
1334
1335 if (value.GetType() != cell->GetVariantType())
3f3af7e7 1336 wxLogError( wxT("Wrong type\n") );
93763ad5 1337
7b4fde82
RR
1338 cell->SetValue( value );
1339}
1340
fa28826d
RR
1341IMPLEMENT_ABSTRACT_CLASS(wxDataViewColumn, wxDataViewColumnBase)
1342
533544f2
RR
1343wxDataViewColumn::wxDataViewColumn( const wxString &title, wxDataViewCell *cell, size_t model_column,
1344 int fixed_width, wxDataViewColumnSizing sizing, int flags ) :
6842a71a 1345 wxDataViewColumnBase( title, cell, model_column, flags )
fa28826d 1346{
6842a71a 1347 GtkCellRenderer *renderer = (GtkCellRenderer *) cell->GetGtkHandle();
93763ad5 1348
6842a71a 1349 GtkTreeViewColumn *column = gtk_tree_view_column_new();
93763ad5 1350
6842a71a 1351 gtk_tree_view_column_set_title( column, wxGTK_CONV(title) );
533544f2
RR
1352
1353 if (sizing == wxDATAVIEW_COL_WIDTH_FIXED)
1354 gtk_tree_view_column_set_sizing( column, GTK_TREE_VIEW_COLUMN_FIXED );
1355 else if (sizing == wxDATAVIEW_COL_WIDTH_GROW)
1356 gtk_tree_view_column_set_sizing( column, GTK_TREE_VIEW_COLUMN_GROW_ONLY );
1357 else
1358 gtk_tree_view_column_set_sizing( column, GTK_TREE_VIEW_COLUMN_AUTOSIZE );
1359
1360 if (fixed_width > 0)
1361 gtk_tree_view_column_set_fixed_width( column, fixed_width );
1362
6842a71a 1363 gtk_tree_view_column_pack_start( column, renderer, TRUE );
93763ad5
WS
1364
1365 gtk_tree_view_column_set_cell_data_func( column, renderer,
7b4fde82 1366 wxGtkTreeCellDataFunc, (gpointer) cell, NULL );
93763ad5 1367
fa28826d
RR
1368 m_column = (void*) column;
1369}
1370
1371wxDataViewColumn::~wxDataViewColumn()
1372{
1373}
1374
1375void wxDataViewColumn::SetTitle( const wxString &title )
1376{
1377 wxDataViewColumnBase::SetTitle( title );
93763ad5 1378
fa28826d
RR
1379 GtkTreeViewColumn *column = (GtkTreeViewColumn *)m_column;
1380 gtk_tree_view_column_set_title( column, wxGTK_CONV(title) );
1381}
1382
533544f2
RR
1383int wxDataViewColumn::GetWidth()
1384{
1385 return gtk_tree_view_column_get_width( (GtkTreeViewColumn *)m_column );
1386}
1387
1388void wxDataViewColumn::SetFixedWidth( int width )
1389{
1390 gtk_tree_view_column_set_fixed_width( (GtkTreeViewColumn *)m_column, width );
1391}
1392
1393int wxDataViewColumn::GetFixedWidth()
1394{
1395 return gtk_tree_view_column_get_fixed_width( (GtkTreeViewColumn *)m_column );
1396}
1397
790b137e
RR
1398//-----------------------------------------------------------------------------
1399// wxDataViewCtrl
1400//-----------------------------------------------------------------------------
1401
239eaa41
RR
1402IMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl, wxDataViewCtrlBase)
1403
1404wxDataViewCtrl::~wxDataViewCtrl()
1405{
8f850e28
RR
1406 if (m_notifier)
1407 GetModel()->RemoveNotifier( m_notifier );
239eaa41
RR
1408}
1409
1410void wxDataViewCtrl::Init()
1411{
8f850e28 1412 m_notifier = NULL;
239eaa41
RR
1413}
1414
1415bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id,
93763ad5 1416 const wxPoint& pos, const wxSize& size,
239eaa41
RR
1417 long style, const wxValidator& validator )
1418{
1419 Init();
93763ad5
WS
1420
1421 m_needParent = true;
1422 m_acceptsFocus = true;
239eaa41
RR
1423
1424 if (!PreCreation( parent, pos, size ) ||
1425 !CreateBase( parent, id, pos, size, style, validator ))
1426 {
1427 wxFAIL_MSG( wxT("wxDataViewCtrl creation failed") );
93763ad5 1428 return false;
239eaa41 1429 }
1a367564
RR
1430
1431 m_widget = gtk_scrolled_window_new (NULL, NULL);
6493aaca
VZ
1432
1433 GtkScrolledWindowSetBorder(m_widget, style);
1a367564
RR
1434
1435 m_treeview = gtk_tree_view_new();
1436 gtk_container_add (GTK_CONTAINER (m_widget), m_treeview);
93763ad5 1437
1a367564
RR
1438 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (m_widget),
1439 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
1440 gtk_widget_show (m_treeview);
93763ad5 1441
239eaa41
RR
1442 m_parent->DoAddChild( this );
1443
1444 PostCreation(size);
1445
1446 return true;
1447}
1448
6e2e590f 1449bool wxDataViewCtrl::AssociateModel( wxDataViewListModel *model )
239eaa41
RR
1450{
1451 if (!wxDataViewCtrlBase::AssociateModel( model ))
1452 return false;
1453
6e2e590f
RR
1454 GtkWxListStore *gtk_store = wxgtk_list_store_new();
1455 gtk_store->model = model;
1456
8f850e28 1457 m_notifier = new wxGtkDataViewListModelNotifier( gtk_store, model );
6e2e590f 1458
93763ad5 1459 model->AddNotifier( m_notifier );
1557c77b 1460
1a367564
RR
1461 gtk_tree_view_set_model( GTK_TREE_VIEW(m_treeview), GTK_TREE_MODEL(gtk_store) );
1462 g_object_unref( gtk_store );
93763ad5 1463
239eaa41
RR
1464 return true;
1465}
790b137e 1466
fa28826d
RR
1467bool wxDataViewCtrl::AppendColumn( wxDataViewColumn *col )
1468{
1469 if (!wxDataViewCtrlBase::AppendColumn(col))
1470 return false;
93763ad5 1471
fa28826d
RR
1472 GtkTreeViewColumn *column = (GtkTreeViewColumn *)col->GetGtkHandle();
1473
1a367564 1474 gtk_tree_view_append_column( GTK_TREE_VIEW(m_treeview), column );
fa28826d
RR
1475
1476 return true;
1477}
1478
93763ad5 1479#endif
4ed7af08 1480 // !wxUSE_GENERICDATAVIEWCTRL
790b137e 1481
93763ad5 1482#endif
4ed7af08 1483 // wxUSE_DATAVIEWCTRL