16
16
17
17
18
18
import java .util .*;
19
+ import java .util .function .*;
19
20
20
21
import org .eclipse .swt .*;
21
22
import org .eclipse .swt .events .*;
@@ -100,6 +101,7 @@ public class Table extends Composite {
100
101
int headerHeight ;
101
102
boolean boundsChangedSinceLastDraw , headerVisible , wasScrolled ;
102
103
boolean rowActivated ;
104
+ boolean showImagesForDefaultColumn ;
103
105
AsyncSetDataTask asyncSetDataTask = new AsyncSetDataTask ();
104
106
105
107
private long headerCSSProvider ;
@@ -235,7 +237,7 @@ long cellDataProc (long tree_column, long cell, long tree_model, long iter, long
235
237
ptr [0 ] = 0 ;
236
238
if (isPixbuf ) {
237
239
GTK .gtk_tree_model_get (tree_model , iter , modelIndex + CELL_PIXBUF , ptr , -1 );
238
- OS .g_object_set (cell , OS .gicon , ptr [0 ], 0 );
240
+ OS .g_object_set (cell , OS .pixbuf , ptr [0 ], 0 );
239
241
if (ptr [0 ] != 0 ) OS .g_object_unref (ptr [0 ]);
240
242
} else {
241
243
GTK .gtk_tree_model_get (tree_model , iter , modelIndex + CELL_TEXT , ptr , -1 );
@@ -626,9 +628,10 @@ void createColumn (TableColumn column, int index) {
626
628
if (columnHandle == 0 ) error (SWT .ERROR_NO_HANDLES );
627
629
if (index == 0 && columnCount > 0 ) {
628
630
TableColumn checkColumn = columns [0 ];
629
- createRenderers (checkColumn .handle , checkColumn .modelIndex , false , checkColumn .style );
631
+ createRenderers (checkColumn .handle , checkColumn .modelIndex , false , checkColumn .showImages , checkColumn . style );
630
632
}
631
- createRenderers (columnHandle , modelIndex , index == 0 , column == null ? 0 : column .style );
633
+ createRenderers (columnHandle , modelIndex , index == 0 ,
634
+ column == null ? showImagesForDefaultColumn : column .showImages , column == null ? 0 : column .style );
632
635
if ((style & SWT .VIRTUAL ) == 0 && columnCount == 0 ) {
633
636
GTK .gtk_tree_view_column_set_sizing (columnHandle , GTK .GTK_TREE_VIEW_COLUMN_GROW_ONLY );
634
637
} else {
@@ -720,9 +723,11 @@ void createItem (TableColumn column, int index) {
720
723
GTK .gtk_tree_view_column_set_sizing (column .handle , GTK .GTK_TREE_VIEW_COLUMN_FIXED );
721
724
GTK .gtk_tree_view_column_set_visible (column .handle , false );
722
725
column .modelIndex = FIRST_COLUMN ;
723
- createRenderers (column .handle , column .modelIndex , true , column .style );
726
+ createRenderers (column .handle , column .modelIndex , true , showImagesForDefaultColumn , column .style );
724
727
column .customDraw = firstCustomDraw ;
725
728
firstCustomDraw = false ;
729
+ column .showImages = showImagesForDefaultColumn ;
730
+ showImagesForDefaultColumn = false ;
726
731
} else {
727
732
createColumn (column , index );
728
733
}
@@ -829,7 +834,7 @@ void createItem (TableItem item, int index) {
829
834
items [index ] = item ;
830
835
}
831
836
832
- void createRenderers (long columnHandle , int modelIndex , boolean check , int columnStyle ) {
837
+ void createRenderers (long columnHandle , int modelIndex , boolean check , boolean showImages , int columnStyle ) {
833
838
GTK .gtk_tree_view_column_clear (columnHandle );
834
839
if ((style & SWT .CHECK ) != 0 && check ) {
835
840
GTK .gtk_tree_view_column_pack_start (columnHandle , checkRenderer , false );
@@ -845,13 +850,14 @@ void createRenderers (long columnHandle, int modelIndex, boolean check, int colu
845
850
long pixbufRenderer = ownerDraw ? OS .g_object_new (display .gtk_cell_renderer_pixbuf_get_type (), 0 ) : GTK .gtk_cell_renderer_pixbuf_new ();
846
851
if (pixbufRenderer == 0 ) {
847
852
error (SWT .ERROR_NO_HANDLES );
848
- } else {
849
- // set default size this size is used for calculating the icon and text positions in a table
850
- if (! ownerDraw ) {
851
- // Set render size to 0x0 until we actually add images, fix for
852
- // Bug 457196 (this applies to Tables as well).
853
- GTK . gtk_cell_renderer_set_fixed_size ( pixbufRenderer , 0 , 0 ) ;
853
+ }
854
+ if (! ownerDraw ) {
855
+ int width = ( pixbufSizeSet && showImages ) ? pixbufWidth : 1 ;
856
+ int height = - 1 ;
857
+ if (( style & SWT . VIRTUAL ) != 0 ) {
858
+ height = pixbufSizeSet ? pixbufHeight : 0 ;
854
859
}
860
+ GTK .gtk_cell_renderer_set_fixed_size (pixbufRenderer , width , height );
855
861
}
856
862
long textRenderer = ownerDraw ? OS .g_object_new (display .gtk_cell_renderer_text_get_type (), 0 ) : GTK .gtk_cell_renderer_text_new ();
857
863
if (textRenderer == 0 ) error (SWT .ERROR_NO_HANDLES );
@@ -1058,6 +1064,7 @@ void destroyItem (TableColumn column) {
1058
1064
long columnHandle = column .handle ;
1059
1065
if (columnCount == 1 ) {
1060
1066
firstCustomDraw = column .customDraw ;
1067
+ showImagesForDefaultColumn = column .showImages ;
1061
1068
}
1062
1069
System .arraycopy (columns , index + 1 , columns , index , --columnCount - index );
1063
1070
columns [columnCount ] = null ;
@@ -1107,7 +1114,8 @@ void destroyItem (TableColumn column) {
1107
1114
}
1108
1115
if (index == 0 ) {
1109
1116
TableColumn checkColumn = columns [0 ];
1110
- createRenderers (checkColumn .handle , checkColumn .modelIndex , true , checkColumn .style );
1117
+ createRenderers (checkColumn .handle , checkColumn .modelIndex , true , checkColumn .showImages ,
1118
+ checkColumn .style );
1111
1119
}
1112
1120
}
1113
1121
if (!searchEnabled ()) {
@@ -2575,11 +2583,12 @@ void recreateRenderers () {
2575
2583
OS .g_signal_connect_closure (checkRenderer , OS .toggled , display .getClosure (TOGGLED ), false );
2576
2584
}
2577
2585
if (columnCount == 0 ) {
2578
- createRenderers (GTK .gtk_tree_view_get_column (handle , 0 ), Table .FIRST_COLUMN , true , 0 );
2586
+ createRenderers (GTK .gtk_tree_view_get_column (handle , 0 ), Table .FIRST_COLUMN , true , showImagesForDefaultColumn ,
2587
+ 0 );
2579
2588
} else {
2580
2589
for (int i = 0 ; i < columnCount ; i ++) {
2581
2590
TableColumn column = columns [i ];
2582
- createRenderers (column .handle , column .modelIndex , i == 0 , column .style );
2591
+ createRenderers (column .handle , column .modelIndex , i == 0 , column .showImages , column . style );
2583
2592
}
2584
2593
}
2585
2594
}
@@ -4243,6 +4252,130 @@ void checkSetDataInProcessBeforeRemoval(int start, int end) {
4243
4252
}
4244
4253
}
4245
4254
4255
+ boolean initPixbufSize (Image image ) {
4256
+ if (pixbufSizeSet || image == null ) {
4257
+ return false ;
4258
+ }
4259
+ int iWidth , iHeight ;
4260
+ if (DPIUtil .useCairoAutoScale ()) {
4261
+ iWidth = image .getBounds ().width ;
4262
+ iHeight = image .getBounds ().height ;
4263
+ } else {
4264
+ iWidth = image .getBoundsInPixels ().width ;
4265
+ iHeight = image .getBoundsInPixels ().height ;
4266
+ }
4267
+ if (iWidth <= 0 || iHeight <= 0 ) {
4268
+ return false ;
4269
+ }
4270
+ pixbufSizeSet = true ;
4271
+ pixbufHeight = iHeight ;
4272
+ pixbufWidth = iWidth ;
4273
+ /*
4274
+ * Feature in GTK: a Table with the style SWT.VIRTUAL has fixed-height-mode
4275
+ * enabled. This will limit the size of any cells, including renderers. In order
4276
+ * to prevent images from disappearing/being cropped, we update row heights when
4277
+ * the first image is set. Fix for bug 480261.
4278
+ */
4279
+ if ((style & SWT .VIRTUAL ) != 0 ) {
4280
+ initFixedRowHeight ();
4281
+ }
4282
+ return true ;
4283
+ }
4284
+
4285
+ private void initFixedRowHeight () {
4286
+ long columnList = GTK .gtk_tree_view_get_columns (handle );
4287
+ if (columnList == 0 ) {
4288
+ return ;
4289
+ }
4290
+
4291
+ // set fixed height for all GtkCellRendererPixbufs
4292
+ for (var colItem = columnList ; colItem != 0 ; colItem = OS .g_list_next (colItem )) {
4293
+ long column = OS .g_list_data (colItem );
4294
+ long renderer = getPixbufRenderer (column );
4295
+ if (renderer != 0 ) {
4296
+ GTK .gtk_cell_renderer_set_fixed_size (renderer , 1 , pixbufHeight );
4297
+ }
4298
+ }
4299
+ OS .g_list_free (columnList );
4300
+
4301
+ /*
4302
+ * Change fixed height of existing rows to fit new pixbuf height.
4303
+ *
4304
+ * Wrapped in asyncExec because when this method is invoked from 'checkData()',
4305
+ * the 'row_changed' signal is blocked (but we need it unblocked to invalidate
4306
+ * existing rows).
4307
+ */
4308
+ display .asyncExec ( () -> {
4309
+ if (!isDisposed () && modelHandle != 0 ) {
4310
+ /*
4311
+ * Reset computed 'fixed_height' to '-1'
4312
+ *
4313
+ * Note: current GTK3 (3.24.41) doesn't support setting 'fixed_height_mode' to
4314
+ * 'true' multiple times: each call appends additional "notify::sizing"
4315
+ * callbacks to columns and doesn't remove old ones.
4316
+ *
4317
+ * It's fine to use here, because this method is executed once per tree.
4318
+ */
4319
+ OS .g_object_set (handle , OS .fixed_height_mode , false , 0 );
4320
+ OS .g_object_set (handle , OS .fixed_height_mode , true , 0 );
4321
+
4322
+ // to update height of the existing rows we need to invalidate them in gtk
4323
+ // we do that by invoking 'gtk_tree_view_row_changed' on each of row
4324
+ int [] value = new int [1 ];
4325
+ forEachChildRow (modelHandle , 0 , iter -> {
4326
+ GTK .gtk_tree_model_get (modelHandle , iter , CHECKED_COLUMN , value , -1 );
4327
+ GTK .gtk_list_store_set (modelHandle , iter , CHECKED_COLUMN , value [0 ], -1 );
4328
+ });
4329
+ }
4330
+ });
4331
+ }
4332
+
4333
+ private static void forEachChildRow (long modelHandle , long parentIter , LongConsumer doWithIter ) {
4334
+ long iter = OS .g_malloc (GTK .GtkTreeIter_sizeof ());
4335
+ if (GTK .gtk_tree_model_iter_children (modelHandle , iter , parentIter )) {
4336
+ do {
4337
+ doWithIter .accept (iter );
4338
+ forEachChildRow (modelHandle , iter , doWithIter );
4339
+ } while (GTK .gtk_tree_model_iter_next (modelHandle , iter ));
4340
+ }
4341
+ OS .g_free (iter );
4342
+ }
4343
+
4344
+ boolean isShowingImagesForColumn (int columnIdx ) {
4345
+ if (columnCount == 0 ) {
4346
+ Objects .checkIndex (columnIdx , 1 );
4347
+ return showImagesForDefaultColumn ;
4348
+ } else {
4349
+ Objects .checkIndex (columnIdx , columnCount );
4350
+ return columns [columnIdx ].showImages ;
4351
+ }
4352
+ }
4353
+
4354
+ boolean showImagesForColumn (int columnIdx ) {
4355
+ Objects .checkIndex (columnIdx , Math .max (1 , columnCount ));
4356
+ if (pixbufSizeSet && !isShowingImagesForColumn (columnIdx )) {
4357
+ long col = GTK .gtk_tree_view_get_column (handle , columnIdx );
4358
+ if (col != 0 ) {
4359
+ long pixbufRenderer = getPixbufRenderer (col );
4360
+ if (pixbufRenderer != 0 ) {
4361
+ int height = ((style & SWT .VIRTUAL ) != 0 ) ? pixbufHeight : -1 ;
4362
+ GTK .gtk_cell_renderer_set_fixed_size (pixbufRenderer , pixbufWidth , height );
4363
+ if (columnCount == 0 ) {;
4364
+ showImagesForDefaultColumn = true ;
4365
+ } else {
4366
+ columns [columnIdx ].showImages = true ;
4367
+ }
4368
+ if (!GTK .GTK4 ) {
4369
+ // update column renderers layout to add space for image width
4370
+ GTK3 .gtk_tree_view_column_queue_resize (col );
4371
+ }
4372
+ return true ;
4373
+ }
4374
+ }
4375
+ }
4376
+ return false ;
4377
+ }
4378
+
4246
4379
@ Override
4247
4380
public void dispose () {
4248
4381
super .dispose ();
0 commit comments