Skip to content

Commit 064e80f

Browse files
committed
Fix for image display problems in Tree and Table eclipse-platform#1739
Fixes image display problems (cropping, not showing) for Tree and Table (both normal and virtual variants). Also fixes eclipse-platform#678 Fixes eclipse-platform#678 Fixes eclipse-platform#1739
1 parent 7d718fe commit 064e80f

File tree

10 files changed

+424
-135
lines changed

10 files changed

+424
-135
lines changed

bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/gtk3.c

+10
Original file line numberDiff line numberDiff line change
@@ -2048,6 +2048,16 @@ JNIEXPORT void JNICALL GTK3_NATIVE(gtk_1tree_1view_1column_1cell_1get_1size)
20482048
}
20492049
#endif
20502050

2051+
#ifndef NO_gtk_1tree_1view_1column_1queue_1resize
2052+
JNIEXPORT void JNICALL GTK3_NATIVE(gtk_1tree_1view_1column_1queue_1resize)
2053+
(JNIEnv *env, jclass that, jlong arg0)
2054+
{
2055+
GTK3_NATIVE_ENTER(env, that, gtk_1tree_1view_1column_1queue_1resize_FUNC);
2056+
gtk_tree_view_column_queue_resize((GtkTreeViewColumn *)arg0);
2057+
GTK3_NATIVE_EXIT(env, that, gtk_1tree_1view_1column_1queue_1resize_FUNC);
2058+
}
2059+
#endif
2060+
20512061
#ifndef NO_gtk_1tree_1view_1get_1bin_1window
20522062
JNIEXPORT jlong JNICALL GTK3_NATIVE(gtk_1tree_1view_1get_1bin_1window)
20532063
(JNIEnv *env, jclass that, jlong arg0)

bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/gtk3_stats.h

+1
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ typedef enum {
191191
gtk_1toolbar_1set_1show_1arrow_FUNC,
192192
gtk_1toolbar_1set_1style_FUNC,
193193
gtk_1tree_1view_1column_1cell_1get_1size_FUNC,
194+
gtk_1tree_1view_1column_1queue_1resize_FUNC,
194195
gtk_1tree_1view_1get_1bin_1window_FUNC,
195196
gtk_1viewport_1set_1shadow_1type_FUNC,
196197
gtk_1widget_1add_1accelerator_FUNC,

bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk3/GTK3.java

+4
Original file line numberDiff line numberDiff line change
@@ -1002,6 +1002,10 @@ public class GTK3 {
10021002
* @param height cast=(gint *)
10031003
*/
10041004
public static final native void gtk_tree_view_column_cell_get_size(long tree_column, GdkRectangle cell_area, int[] x_offset, int[] y_offset, int[] width, int[] height);
1005+
/**
1006+
* @param tree_column cast=(GtkTreeViewColumn *)
1007+
*/
1008+
public static final native void gtk_tree_view_column_queue_resize(long tree_column);
10051009

10061010
/* GdkWindow */
10071011
/**

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

+149-14
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
package org.eclipse.swt.widgets;
1616

1717

18+
import java.util.*;
19+
import java.util.function.*;
20+
1821
import org.eclipse.swt.*;
1922
import org.eclipse.swt.events.*;
2023
import 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
42444379
public void dispose() {
42454380
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)