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