diff --git a/CHANGES.md b/CHANGES.md index a829f5ef..5522da3a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,8 @@ # DurianSwt releases ## [Unreleased] +### Fixed +- Mac tables with a checkbox column now size the rest of their columns correctly. ([#14](https://github.com/diffplug/durian-swt/pull/14)) ## [3.4.0] - 2021-07-17 ### Added diff --git a/durian-swt/build.gradle b/durian-swt/build.gradle index 3a250335..d6a70038 100644 --- a/durian-swt/build.gradle +++ b/durian-swt/build.gradle @@ -27,21 +27,23 @@ dependencies { } */ // in java-library mode, durian-swt.os remains as a folder of classes for gradle internally, which the osgi plugin does not like -tasks.jar.dependsOn(':durian-swt.os:jar') +tasks.named('jar').configure { + dependsOn(':durian-swt.os:jar') +} ///////////////////////// // INTERACTIVE TESTING // ///////////////////////// // standard `gradlew test` will autoclose after 500ms +boolean isMac = System.getProperty("os.name").toLowerCase().contains("mac") test { systemProperty 'com.diffplug.test.autoclose.milliseconds', '500' useJUnit { // there are some tests that can't pass without a user, so we'll exclude them excludeCategories 'com.diffplug.common.swt.InteractiveTest$FailsWithoutUser' // SWT tests don't work in gradle on OS X (https://github.com/ReadyTalk/swt-bling/issues/4) - boolean isMac = System.getProperty("os.name").toLowerCase().contains("mac"); if (isMac) { - excludeCategories 'com.diffplug.common.swt.InteractiveTest' + jvmArgs = ['-XstartOnFirstThread'] } } // log all test events @@ -51,9 +53,12 @@ test { } // only run the interactive tests -task interactiveTest(type: Test) { +tasks.register('interactiveTest', Test) { systemProperty 'com.diffplug.test.autoclose.milliseconds', null useJUnit { includeCategories 'com.diffplug.common.swt.InteractiveTest' + if (isMac) { + jvmArgs = ['-XstartOnFirstThread'] + } } } diff --git a/durian-swt/src/main/java/com/diffplug/common/swt/ColumnFormat.java b/durian-swt/src/main/java/com/diffplug/common/swt/ColumnFormat.java index d37de449..5b9ab603 100644 --- a/durian-swt/src/main/java/com/diffplug/common/swt/ColumnFormat.java +++ b/durian-swt/src/main/java/com/diffplug/common/swt/ColumnFormat.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 DiffPlug + * Copyright (C) 2020-2021 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package com.diffplug.common.swt; +import com.diffplug.common.swt.os.OS; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -109,12 +110,43 @@ protected static Table buildTable(Composite parent, int style, boolean linesVisi // create the columns and layout Function buildFunc = builder -> builder.build(control); List columns = columnBuilders.stream().map(buildFunc).collect(Collectors.toList()); - buildLayout(control, new TableColumnLayout(), columns, columnBuilders); + + boolean needsSpecialLayout = SwtMisc.flagIsSet(SWT.CHECK, style) && OS.getNative().isMac(); + TableColumnLayout layout = needsSpecialLayout ? new MacCheckTableColumnLayout() : new TableColumnLayout(); + buildLayout(control, layout, columns, columnBuilders); // return the control return control; } + /** Adds a phantom column for the checkboxes so that the rest of the space is calculated correctly. */ + private static class MacCheckTableColumnLayout extends TableColumnLayout { + private static final int CHECK_COLUMN_WIDTH = 15; + + @Override + protected int getColumnCount(Scrollable tableTree) { + return super.getColumnCount(tableTree) + 1; + } + + @Override + protected void setColumnWidths(Scrollable tableTree, int[] widths) { + TableColumn[] columns = ((Table) tableTree).getColumns(); + for (int i = 0; i < columns.length; i++) { + columns[i].setWidth(widths[i]); + } + } + + @Override + protected ColumnLayoutData getLayoutData(Scrollable tableTree, int columnIndex) { + Table table = (Table) tableTree; + if (columnIndex < table.getColumnCount()) { + return (ColumnLayoutData) table.getColumn(columnIndex).getData(LAYOUT_DATA); + } else { + return new ColumnPixelData(CHECK_COLUMN_WIDTH); + } + } + } + /** Builds a table with the given columns. */ protected static Tree buildTree(Composite parent, int style, boolean linesVisible, boolean headerVisible, List columnBuilders) { SwtMisc.assertClean(parent); diff --git a/durian-swt/src/test/java/com/diffplug/common/swt/jface/ColumnViewerFormatTest.java b/durian-swt/src/test/java/com/diffplug/common/swt/jface/ColumnViewerFormatTest.java new file mode 100644 index 00000000..73d135cb --- /dev/null +++ b/durian-swt/src/test/java/com/diffplug/common/swt/jface/ColumnViewerFormatTest.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2020-2021 DiffPlug + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.diffplug.common.swt.jface; + + +import com.diffplug.common.swt.InteractiveTest; +import com.diffplug.common.swt.Layouts; +import java.util.Arrays; +import org.eclipse.jface.viewers.ArrayContentProvider; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +@Category(InteractiveTest.class) +public class ColumnViewerFormatTest { + @Test + public void testCopy() { + InteractiveTest.testCoat("Column viewer", 10, 10, cmp -> { + Layouts.setFill(cmp); + buildTableWithCheck(new Composite(cmp, SWT.BORDER), true); + buildTableWithCheck(new Composite(cmp, SWT.BORDER), false); + }); + } + + private void buildTableWithCheck(Composite cmp, boolean hasCheck) { + ColumnViewerFormat format = ColumnViewerFormat.builder(); + format.setStyle(SWT.FULL_SELECTION | (hasCheck ? SWT.CHECK : SWT.NONE)); + format.addColumn().setLabelProviderText(s -> s); + TableViewer viewer = format.buildTable(cmp); + viewer.setContentProvider(ArrayContentProvider.getInstance()); + viewer.setInput(Arrays.asList("Onesy twosy threesy foursy", "red orange yellow green blue purple")); + } +} diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 05679dc3..ffed3a25 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index b4f908aa..744e882e 100755 --- a/gradlew +++ b/gradlew @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh # # Copyright 2015 the original author or authors. @@ -172,12 +172,14 @@ if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then esac fi -ARGV=("$@") -eval set -- $DEFAULT_JVM_OPTS +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` -IFS=$' -' read -rd '' -a JAVA_OPTS_ARR <<< "$(echo $JAVA_OPTS | xargs -n1)" -IFS=$' -' read -rd '' -a GRADLE_OPTS_ARR <<< "$(echo $GRADLE_OPTS | xargs -n1)" +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" -exec "$JAVACMD" "$@" "${JAVA_OPTS_ARR[@]}" "${GRADLE_OPTS_ARR[@]}" "-Dorg.gradle.appname=$APP_BASE_NAME" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "${ARGV[@]}" +exec "$JAVACMD" "$@" diff --git a/settings.gradle b/settings.gradle index 7ffc9505..58b221d7 100644 --- a/settings.gradle +++ b/settings.gradle @@ -20,7 +20,7 @@ plugins { id 'org.jdrupes.mdoclet' apply false } blowdryerSetup { - github 'diffplug/blowdryer-diffplug', 'tag', '5.0.4' + github 'diffplug/blowdryer-diffplug', 'tag', '5.0.6' //devLocal '../blowdryer-diffplug' }