1515package org .eclipse .swt .widgets ;
1616
1717
18+ import java .util .*;
19+ import java .util .function .*;
20+
1821import org .eclipse .swt .*;
1922import org .eclipse .swt .events .*;
2023import org .eclipse .swt .graphics .*;
@@ -98,6 +101,7 @@ public class Table extends Composite {
98101 int headerHeight ;
99102 boolean boundsChangedSinceLastDraw , headerVisible , wasScrolled ;
100103 boolean rowActivated ;
104+ boolean showImagesForDefaultColumn ;
101105
102106 private long headerCSSProvider ;
103107
@@ -232,7 +236,7 @@ long cellDataProc (long tree_column, long cell, long tree_model, long iter, long
232236 ptr [0 ] = 0 ;
233237 if (isPixbuf ) {
234238 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 );
236240 if (ptr [0 ] != 0 ) OS .g_object_unref (ptr [0 ]);
237241 } else {
238242 GTK .gtk_tree_model_get (tree_model , iter , modelIndex + CELL_TEXT , ptr , -1 );
@@ -623,9 +627,10 @@ void createColumn (TableColumn column, int index) {
623627 if (columnHandle == 0 ) error (SWT .ERROR_NO_HANDLES );
624628 if (index == 0 && columnCount > 0 ) {
625629 TableColumn checkColumn = columns [0 ];
626- createRenderers (checkColumn .handle , checkColumn .modelIndex , false , checkColumn .style );
630+ createRenderers (checkColumn .handle , checkColumn .modelIndex , false , checkColumn .showImages , checkColumn . style );
627631 }
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 );
629634 if ((style & SWT .VIRTUAL ) == 0 && columnCount == 0 ) {
630635 GTK .gtk_tree_view_column_set_sizing (columnHandle , GTK .GTK_TREE_VIEW_COLUMN_GROW_ONLY );
631636 } else {
@@ -717,9 +722,11 @@ void createItem (TableColumn column, int index) {
717722 GTK .gtk_tree_view_column_set_sizing (column .handle , GTK .GTK_TREE_VIEW_COLUMN_FIXED );
718723 GTK .gtk_tree_view_column_set_visible (column .handle , false );
719724 column .modelIndex = FIRST_COLUMN ;
720- createRenderers (column .handle , column .modelIndex , true , column .style );
725+ createRenderers (column .handle , column .modelIndex , true , showImagesForDefaultColumn , column .style );
721726 column .customDraw = firstCustomDraw ;
722727 firstCustomDraw = false ;
728+ column .showImages = showImagesForDefaultColumn ;
729+ showImagesForDefaultColumn = false ;
723730 } else {
724731 createColumn (column , index );
725732 }
@@ -826,7 +833,7 @@ void createItem (TableItem item, int index) {
826833 items [index ] = item ;
827834}
828835
829- void createRenderers (long columnHandle , int modelIndex , boolean check , int columnStyle ) {
836+ void createRenderers (long columnHandle , int modelIndex , boolean check , boolean showImages , int columnStyle ) {
830837 GTK .gtk_tree_view_column_clear (columnHandle );
831838 if ((style & SWT .CHECK ) != 0 && check ) {
832839 GTK .gtk_tree_view_column_pack_start (columnHandle , checkRenderer , false );
@@ -842,13 +849,14 @@ void createRenderers (long columnHandle, int modelIndex, boolean check, int colu
842849 long pixbufRenderer = ownerDraw ? OS .g_object_new (display .gtk_cell_renderer_pixbuf_get_type (), 0 ) : GTK .gtk_cell_renderer_pixbuf_new ();
843850 if (pixbufRenderer == 0 ) {
844851 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 ;
851858 }
859+ GTK .gtk_cell_renderer_set_fixed_size (pixbufRenderer , width , height );
852860 }
853861 long textRenderer = ownerDraw ? OS .g_object_new (display .gtk_cell_renderer_text_get_type (), 0 ) : GTK .gtk_cell_renderer_text_new ();
854862 if (textRenderer == 0 ) error (SWT .ERROR_NO_HANDLES );
@@ -1055,6 +1063,7 @@ void destroyItem (TableColumn column) {
10551063 long columnHandle = column .handle ;
10561064 if (columnCount == 1 ) {
10571065 firstCustomDraw = column .customDraw ;
1066+ showImagesForDefaultColumn = column .showImages ;
10581067 }
10591068 System .arraycopy (columns , index + 1 , columns , index , --columnCount - index );
10601069 columns [columnCount ] = null ;
@@ -1104,7 +1113,8 @@ void destroyItem (TableColumn column) {
11041113 }
11051114 if (index == 0 ) {
11061115 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 );
11081118 }
11091119 }
11101120 if (!searchEnabled ()) {
@@ -2572,11 +2582,12 @@ void recreateRenderers () {
25722582 OS .g_signal_connect_closure (checkRenderer , OS .toggled , display .getClosure (TOGGLED ), false );
25732583 }
25742584 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 );
25762587 } else {
25772588 for (int i = 0 ; i < columnCount ; i ++) {
25782589 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 );
25802591 }
25812592 }
25822593}
@@ -4240,6 +4251,130 @@ void checkSetDataInProcessBeforeRemoval(int start, int end) {
42404251 }
42414252}
42424253
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+
42434378@ Override
42444379public void dispose () {
42454380 super .dispose ();
0 commit comments