Skip to content

Commit 2edcaa6

Browse files
committed
Fix for image display problems in Tree and Table #1739
Fixes image display problems (cropping, not showing) for Tree and Table (both normal and virtual variants). Fixes #1739
1 parent 26f9a6f commit 2edcaa6

File tree

6 files changed

+308
-134
lines changed

6 files changed

+308
-134
lines changed

bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Table.java

+147-14
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717

1818
import java.util.*;
19+
import java.util.function.*;
1920

2021
import org.eclipse.swt.*;
2122
import org.eclipse.swt.events.*;
@@ -100,6 +101,7 @@ public class Table extends Composite {
100101
int headerHeight;
101102
boolean boundsChangedSinceLastDraw, headerVisible, wasScrolled;
102103
boolean rowActivated;
104+
boolean showImagesForDefaultColumn;
103105
AsyncSetDataTask asyncSetDataTask = new AsyncSetDataTask();
104106

105107
private long headerCSSProvider;
@@ -235,7 +237,7 @@ long cellDataProc (long tree_column, long cell, long tree_model, long iter, long
235237
ptr [0] = 0;
236238
if (isPixbuf) {
237239
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);
239241
if (ptr [0] != 0) OS.g_object_unref (ptr [0]);
240242
} else {
241243
GTK.gtk_tree_model_get (tree_model, iter, modelIndex + CELL_TEXT, ptr, -1);
@@ -626,9 +628,10 @@ void createColumn (TableColumn column, int index) {
626628
if (columnHandle == 0) error (SWT.ERROR_NO_HANDLES);
627629
if (index == 0 && columnCount > 0) {
628630
TableColumn checkColumn = columns [0];
629-
createRenderers (checkColumn.handle, checkColumn.modelIndex, false, checkColumn.style);
631+
createRenderers (checkColumn.handle, checkColumn.modelIndex, false, checkColumn.showImages, checkColumn.style);
630632
}
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);
632635
if ((style & SWT.VIRTUAL) == 0 && columnCount == 0) {
633636
GTK.gtk_tree_view_column_set_sizing (columnHandle, GTK.GTK_TREE_VIEW_COLUMN_GROW_ONLY);
634637
} else {
@@ -720,9 +723,11 @@ void createItem (TableColumn column, int index) {
720723
GTK.gtk_tree_view_column_set_sizing (column.handle, GTK.GTK_TREE_VIEW_COLUMN_FIXED);
721724
GTK.gtk_tree_view_column_set_visible (column.handle, false);
722725
column.modelIndex = FIRST_COLUMN;
723-
createRenderers (column.handle, column.modelIndex, true, column.style);
726+
createRenderers (column.handle, column.modelIndex, true, showImagesForDefaultColumn, column.style);
724727
column.customDraw = firstCustomDraw;
725728
firstCustomDraw = false;
729+
column.showImages = showImagesForDefaultColumn;
730+
showImagesForDefaultColumn = false;
726731
} else {
727732
createColumn (column, index);
728733
}
@@ -829,7 +834,7 @@ void createItem (TableItem item, int index) {
829834
items [index] = item;
830835
}
831836

832-
void createRenderers (long columnHandle, int modelIndex, boolean check, int columnStyle) {
837+
void createRenderers (long columnHandle, int modelIndex, boolean check, boolean showImages, int columnStyle) {
833838
GTK.gtk_tree_view_column_clear (columnHandle);
834839
if ((style & SWT.CHECK) != 0 && check) {
835840
GTK.gtk_tree_view_column_pack_start (columnHandle, checkRenderer, false);
@@ -845,13 +850,14 @@ void createRenderers (long columnHandle, int modelIndex, boolean check, int colu
845850
long pixbufRenderer = ownerDraw ? OS.g_object_new (display.gtk_cell_renderer_pixbuf_get_type (), 0) : GTK.gtk_cell_renderer_pixbuf_new ();
846851
if (pixbufRenderer == 0) {
847852
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;
854859
}
860+
GTK.gtk_cell_renderer_set_fixed_size(pixbufRenderer, width, height);
855861
}
856862
long textRenderer = ownerDraw ? OS.g_object_new (display.gtk_cell_renderer_text_get_type (), 0) : GTK.gtk_cell_renderer_text_new ();
857863
if (textRenderer == 0) error (SWT.ERROR_NO_HANDLES);
@@ -1058,6 +1064,7 @@ void destroyItem (TableColumn column) {
10581064
long columnHandle = column.handle;
10591065
if (columnCount == 1) {
10601066
firstCustomDraw = column.customDraw;
1067+
showImagesForDefaultColumn = column.showImages;
10611068
}
10621069
System.arraycopy (columns, index + 1, columns, index, --columnCount - index);
10631070
columns [columnCount] = null;
@@ -1107,7 +1114,8 @@ void destroyItem (TableColumn column) {
11071114
}
11081115
if (index == 0) {
11091116
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);
11111119
}
11121120
}
11131121
if (!searchEnabled ()) {
@@ -2575,11 +2583,12 @@ void recreateRenderers () {
25752583
OS.g_signal_connect_closure (checkRenderer, OS.toggled, display.getClosure (TOGGLED), false);
25762584
}
25772585
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);
25792588
} else {
25802589
for (int i = 0; i < columnCount; i++) {
25812590
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);
25832592
}
25842593
}
25852594
}
@@ -4243,6 +4252,130 @@ void checkSetDataInProcessBeforeRemoval(int start, int end) {
42434252
}
42444253
}
42454254

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+
42464379
@Override
42474380
public void dispose() {
42484381
super.dispose();

bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TableColumn.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public class TableColumn extends Item {
4545
long labelHandle, imageHandle, buttonHandle;
4646
Table parent;
4747
int modelIndex, lastButton, lastTime, lastX, lastWidth;
48-
boolean customDraw, useFixedWidth;
48+
boolean customDraw, showImages, useFixedWidth;
4949
String toolTipText;
5050

5151
/**
@@ -606,7 +606,7 @@ public void setAlignment (int alignment) {
606606
if (index == -1 || index == 0) return;
607607
style &= ~(SWT.LEFT | SWT.RIGHT | SWT.CENTER);
608608
style |= alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER);
609-
parent.createRenderers (handle, modelIndex, index == 0, style);
609+
parent.createRenderers (handle, modelIndex, index == 0, showImages, style);
610610
}
611611

612612
void setFontDescription (long font) {

bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/TableItem.java

+5-33
Original file line numberDiff line numberDiff line change
@@ -1201,40 +1201,12 @@ public void setImage(int index, Image image) {
12011201
}
12021202
surface = imageList.getSurface(imageIndex);
12031203
pixbuf = ImageList.createPixbuf(surface);
1204-
}
12051204

1206-
long parentHandle = parent.handle;
1207-
long column = GTK.gtk_tree_view_get_column (parentHandle, index);
1208-
long pixbufRenderer = parent.getPixbufRenderer (column);
1209-
int [] currentWidth = new int [1];
1210-
int [] currentHeight= new int [1];
1211-
GTK.gtk_cell_renderer_get_fixed_size (pixbufRenderer, currentWidth, currentHeight);
1212-
if (!parent.pixbufSizeSet) {
1213-
if (image != null) {
1214-
int iWidth, iHeight;
1215-
if (DPIUtil.useCairoAutoScale()) {
1216-
iWidth = image.getBounds ().width;
1217-
iHeight = image.getBounds ().height;
1218-
} else {
1219-
iWidth = image.getBoundsInPixels ().width;
1220-
iHeight = image.getBoundsInPixels ().height;
1221-
}
1222-
if (iWidth > currentWidth [0] || iHeight > currentHeight [0]) {
1223-
GTK.gtk_cell_renderer_set_fixed_size (pixbufRenderer, iWidth, iHeight);
1224-
parent.pixbufHeight = iHeight;
1225-
parent.pixbufWidth = iWidth;
1226-
parent.pixbufSizeSet = true;
1227-
}
1205+
if (!parent.pixbufSizeSet) {
1206+
parent.initPixbufSize (image);
12281207
}
1229-
} else {
1230-
/*
1231-
* We check to see if the cached value is greater than the size of the pixbufRenderer.
1232-
* If it is, then we change the size of the pixbufRenderer accordingly.
1233-
* Bug 489025: There is a corner case where the below is triggered when current(Width|Height) is -1,
1234-
* which results in icons being set to 0. Fix is to compare only positive sizes.
1235-
*/
1236-
if (parent.pixbufWidth > Math.max(currentWidth [0], 0) || parent.pixbufHeight > Math.max(currentHeight [0], 0)) {
1237-
GTK.gtk_cell_renderer_set_fixed_size (pixbufRenderer, parent.pixbufWidth, parent.pixbufHeight);
1208+
if (parent.pixbufSizeSet && !parent.isShowingImagesForColumn (index)) {
1209+
parent.showImagesForColumn (index);
12381210
}
12391211
}
12401212
int modelIndex = parent.columnCount == 0 ? Table.FIRST_COLUMN : parent.columns [index].modelIndex;
@@ -1254,7 +1226,7 @@ public void setImage(int index, Image image) {
12541226
* width and see if it's larger than the maximum of the previous widths.
12551227
*/
12561228
if (parent.columnCount == 0) {
1257-
column = GTK.gtk_tree_view_get_column (parent.handle, index);
1229+
long column = GTK.gtk_tree_view_get_column (parent.handle, index);
12581230
parent.maxWidth = Math.max(parent.maxWidth, parent.calculateWidth(column, this.handle));
12591231
}
12601232
}

0 commit comments

Comments
 (0)