diff --git a/app/gui/src/main/java/org/mobilitydata/gtfsvalidator/app/gui/GtfsValidatorApp.java b/app/gui/src/main/java/org/mobilitydata/gtfsvalidator/app/gui/GtfsValidatorApp.java index e48ee4cb00..5f30458ea9 100644 --- a/app/gui/src/main/java/org/mobilitydata/gtfsvalidator/app/gui/GtfsValidatorApp.java +++ b/app/gui/src/main/java/org/mobilitydata/gtfsvalidator/app/gui/GtfsValidatorApp.java @@ -23,13 +23,17 @@ import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; +import java.awt.Image; +import java.awt.Toolkit; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.File; import java.net.URI; import java.net.URISyntaxException; +import java.net.URL; import java.nio.file.Path; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.ResourceBundle; import javax.swing.BorderFactory; @@ -134,6 +138,7 @@ public void showNewVersionAvailable() { void constructUI() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + setApplicationIcon(); JPanel panel = new JPanel(); panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS)); @@ -155,6 +160,25 @@ void constructUI() { } } + private void setApplicationIcon() { + Toolkit toolkit = Toolkit.getDefaultToolkit(); + List iconFileNames = + Arrays.asList("icon_16x16.png", "icon_32x32.png", "icon_48x48.png"); + List iconImages = new ArrayList<>(); + for (String iconFileName : iconFileNames) { + URL resource = getClass().getResource(iconFileName); + if (resource != null) { + Image image = toolkit.createImage(resource); + iconImages.add(image); + } else { + logger.atWarning().log("Icon image not found: %s", iconFileName); + } + } + if (!iconImages.isEmpty()) { + setIconImages(iconImages); + } + } + private void constructGtfsInputSection(JPanel parent) { // GTFS Input Section parent.add(createLabelWithFont(bundle.getString("gtfs_input"), BOLD_FONT)); diff --git a/app/gui/src/main/resources/org/mobilitydata/gtfsvalidator/app/gui/icon_16x16.png b/app/gui/src/main/resources/org/mobilitydata/gtfsvalidator/app/gui/icon_16x16.png new file mode 100644 index 0000000000..d343d6d6ce Binary files /dev/null and b/app/gui/src/main/resources/org/mobilitydata/gtfsvalidator/app/gui/icon_16x16.png differ diff --git a/app/gui/src/main/resources/org/mobilitydata/gtfsvalidator/app/gui/icon_32x32.png b/app/gui/src/main/resources/org/mobilitydata/gtfsvalidator/app/gui/icon_32x32.png new file mode 100644 index 0000000000..a4224210e9 Binary files /dev/null and b/app/gui/src/main/resources/org/mobilitydata/gtfsvalidator/app/gui/icon_32x32.png differ diff --git a/app/gui/src/main/resources/org/mobilitydata/gtfsvalidator/app/gui/icon_48x48.png b/app/gui/src/main/resources/org/mobilitydata/gtfsvalidator/app/gui/icon_48x48.png new file mode 100644 index 0000000000..05cad2ac4a Binary files /dev/null and b/app/gui/src/main/resources/org/mobilitydata/gtfsvalidator/app/gui/icon_48x48.png differ diff --git a/app/pkg/build.gradle b/app/pkg/build.gradle index d16eb72152..074d97b815 100644 --- a/app/pkg/build.gradle +++ b/app/pkg/build.gradle @@ -14,6 +14,8 @@ * limitations under the License. */ +import org.gradle.internal.os.OperatingSystem + plugins { id 'java' id "de.jjohannes.extra-java-module-info" version "0.11" @@ -96,9 +98,16 @@ jlink { // Some platforms (e.g. Mac OS) need a pure x.y.z version number. // So strip any -SNAPSHOT suffix if present. appVersion = project.version.toString().replace('-SNAPSHOT', '') - if (org.gradle.internal.os.OperatingSystem.current().windows) { + if (OperatingSystem.current().isWindows()) { installerOptions += ['--win-per-user-install', '--win-dir-chooser', '--win-menu', '--win-shortcut'] - imageOptions += ['--win-console'] + imageOptions = [ + '--icon', "${projectDir}/src/main/icons/Icon.ico", '--win-console' + ] + } + if (OperatingSystem.current().isMacOsX()) { + imageOptions = [ + '--icon', "${projectDir}/src/main/icons/Icon.icns" + ] } } } diff --git a/app/pkg/src/main/icons/Icon.icns b/app/pkg/src/main/icons/Icon.icns new file mode 100644 index 0000000000..2c47ba4346 Binary files /dev/null and b/app/pkg/src/main/icons/Icon.icns differ diff --git a/app/pkg/src/main/icons/Icon.ico b/app/pkg/src/main/icons/Icon.ico new file mode 100644 index 0000000000..d4aba368da Binary files /dev/null and b/app/pkg/src/main/icons/Icon.ico differ diff --git a/app/pkg/src/main/icons/Icon.svg b/app/pkg/src/main/icons/Icon.svg new file mode 100644 index 0000000000..b608130c2c --- /dev/null +++ b/app/pkg/src/main/icons/Icon.svg @@ -0,0 +1,81 @@ + +image/svg+xml + + + + + + + + + + + + + + diff --git a/app/pkg/src/main/icons/README.md b/app/pkg/src/main/icons/README.md new file mode 100644 index 0000000000..b4a0a2d1ee --- /dev/null +++ b/app/pkg/src/main/icons/README.md @@ -0,0 +1,15 @@ +## Updating Application Icons + +The source file for all application icons is `Icon.svg`. This is used to create three +platform-specific application icons: + +* Windows: `Icon.ico` +* Mac OS: `Icon.icns` +* Java In-App + +When updating the source icon, you can run the following three scripts to regenerate the +relevant icon files from the SVG source: + +* `svg2ico.sh` +* `svg2icsn.sh` +* `svg2jframe_icons.sh` \ No newline at end of file diff --git a/app/pkg/src/main/icons/svg2icns.sh b/app/pkg/src/main/icons/svg2icns.sh new file mode 100755 index 0000000000..8ad35978bc --- /dev/null +++ b/app/pkg/src/main/icons/svg2icns.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# +# Helper script for constructing a Mac OS icns icon bundle, +# from an intermediate iconset file bundle. Requires install +# of ImageMagik for `convert` command. + +set -e + +BASEDIR=$(dirname "$0") +SVG=$BASEDIR/Icon.svg +ICONSET_DIR=$BASEDIR/Icon.iconset + +CONFIGS=" +icon_16x16.png,16x16 +icon_16x16@2x.png,32x32 +icon_32x32.png,32x32 +icon_32x32@2x.png,64x64 +icon_128x128.png,128x128 +icon_128x128@2x.png,256x256 +icon_256x256.png,256x256 +icon_256x256@2x.png,512x512 +icon_512x512.png,512x512 +icon_512x512@2x.png,1024x1024 +" + +if [ -e $ICONSET_DIR ]; then + rm -rf "$ICONSET_DIR" +fi +mkdir $ICONSET_DIR + +for CONFIG in $CONFIGS; do + FILENAME=$(echo $CONFIG | cut -d, -f1) + SIZE=$(echo $CONFIG | cut -d, -f2) + echo $FILENAME + convert -density 1200 -background none -resize $SIZE $SVG $ICONSET_DIR/$FILENAME +done + +iconutil -c icns $ICONSET_DIR +rm -rf "$ICONSET_DIR" diff --git a/app/pkg/src/main/icons/svg2ico.sh b/app/pkg/src/main/icons/svg2ico.sh new file mode 100755 index 0000000000..a68fa58649 --- /dev/null +++ b/app/pkg/src/main/icons/svg2ico.sh @@ -0,0 +1,34 @@ +#!/bin/bash +# +# Helper script for constructing a Windows icon bundle. Requires +# install of ImageMagik for `convert` command. + +set -e + +BASEDIR=$(dirname "$0") +SVG=$BASEDIR/Icon.svg +ICO_DIR=$BASEDIR/Icon.ico_dir + +CONFIGS=" +icon_16x16.png,16x16 +icon_32x32.png,32x32 +icon_48x48.png,48x48 +icon_64x64.png,64x64 +icon_128x128.png,128x128 +icon_256x256.png,256x256 +" + +if [ -e $ICO_DIR ]; then + rm -rf "$ICO_DIR" +fi +mkdir $ICO_DIR + +for CONFIG in $CONFIGS; do + FILENAME=$(echo $CONFIG | cut -d, -f1) + SIZE=$(echo $CONFIG | cut -d, -f2) + echo $FILENAME + convert -density 1200 -background none -resize $SIZE $SVG $ICO_DIR/$FILENAME +done + +convert $ICO_DIR/*.png Icon.ico +rm -rf "$ICO_DIR" diff --git a/app/pkg/src/main/icons/svg2jframe_icons.sh b/app/pkg/src/main/icons/svg2jframe_icons.sh new file mode 100755 index 0000000000..f9b9801c29 --- /dev/null +++ b/app/pkg/src/main/icons/svg2jframe_icons.sh @@ -0,0 +1,25 @@ +#!/bin/bash +# +# Helper script for constructing Java in-app icon resources. Requires +# install of ImageMagik for `convert` command. + +set -e + +BASEDIR=$(dirname "$0") +SVG=$BASEDIR/Icon.svg + +PROJECT_ROOT_DIR=$(git rev-parse --show-toplevel) +RESOURCES_DIR=$PROJECT_ROOT_DIR/app/gui/src/main/resources/org/mobilitydata/gtfsvalidator/app/gui + +CONFIGS=" +icon_16x16.png,16x16 +icon_32x32.png,32x32 +icon_48x48.png,48x48 +" + +for CONFIG in $CONFIGS; do + FILENAME=$(echo $CONFIG | cut -d, -f1) + SIZE=$(echo $CONFIG | cut -d, -f2) + echo $FILENAME + convert -density 1200 -background none -resize $SIZE $SVG $RESOURCES_DIR/$FILENAME +done