Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Added menu item icon to show whether updates are available #519

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,6 @@ public boolean canPerformControlAction(ApplicationControlAction a, DocumentWindo
switch (a) {
case ABOUT:
case REGISTER:
case CHECK_UPDATES:
case NEW_FILE:
case NEW_TEMPLATE:
case OPEN_FILE:
Expand All @@ -238,6 +237,10 @@ public boolean canPerformControlAction(ApplicationControlAction a, DocumentWindo
result = true;
break;

case CHECK_UPDATES:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to make this change at all? If the update is not available, the item is disabled, so not clickable. I think the existing behaviour is fine here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. The checks are performed every time you open the menu. Even with disabling the menu item in the FXML file, if we leave this hard coded to a true response, it will re-enable the item when you open the menu.

result = AppSettings.isUpdateAvailable();
break;

case CLOSE_FRONT_WINDOW:
result = windowList.isEmpty() == false;
break;
Expand Down Expand Up @@ -996,11 +999,13 @@ private void checkUpdates(DocumentWindowController source) {
dialog.showAndWait();
});
} else {
SBAlert alert = new SBAlert(Alert.AlertType.INFORMATION, getFrontDocumentWindow().getStage());
alert.setTitle(I18N.getString("check_for_updates.alert.up_to_date.title"));
alert.setHeaderText(I18N.getString("check_for_updates.alert.headertext"));
alert.setContentText(I18N.getString("check_for_updates.alert.up_to_date.message"));
alert.showAndWait();
Platform.runLater(()->{
SBAlert alert = new SBAlert(Alert.AlertType.INFORMATION, getFrontDocumentWindow().getStage());
alert.setTitle(I18N.getString("check_for_updates.alert.up_to_date.title"));
alert.setHeaderText(I18N.getString("check_for_updates.alert.headertext"));
alert.setContentText(I18N.getString("check_for_updates.alert.up_to_date.message"));
alert.showAndWait();
});
}
} catch (NumberFormatException ex) {
Platform.runLater(() -> showVersionNumberFormatError(source));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import com.oracle.javafx.scenebuilder.app.i18n.I18N;
import com.oracle.javafx.scenebuilder.app.preferences.PreferencesController;
import com.oracle.javafx.scenebuilder.app.preferences.PreferencesRecordGlobal;
import com.oracle.javafx.scenebuilder.app.util.AppSettings;
import com.oracle.javafx.scenebuilder.kit.editor.EditorController;
import com.oracle.javafx.scenebuilder.kit.editor.EditorController.ControlAction;
import com.oracle.javafx.scenebuilder.kit.editor.EditorController.EditAction;
Expand All @@ -66,6 +67,7 @@
import java.util.TreeMap;
import java.util.TreeSet;

import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
Expand All @@ -81,6 +83,8 @@
import javafx.scene.control.RadioMenuItem;
import javafx.scene.control.SeparatorMenuItem;
import javafx.scene.effect.Effect;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCharacterCombination;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
Expand Down Expand Up @@ -1171,6 +1175,23 @@ public String getTitle() {
insertMenu.setOnMenuValidation(onCustomPartOfInsertMenuValidationHandler);

windowMenu.setOnMenuValidation(onWindowMenuValidationHandler);

// Modify the Check Updates menu item if there is an update available.
// Icons by Font Awesome (https://fontawesome.com/license/free) under CC BY 4.0 License
AppSettings.getLatestVersion(latestVersion -> {
if (AppSettings.isUpdateAvailable()) {
Image icon = new Image(MenuBarController.class
.getResource("download_icon.png")
.toExternalForm());
ImageView iconView = new ImageView(icon);

Platform.runLater(() -> {
checkUpdatesMenuItem.setGraphic(iconView);
checkUpdatesMenuItem.disableProperty().setValue(false);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense to disable this menu option?

In case the user really wanted to be sure, clicking on it should at least bring a dialog saying that the current version XXX is already up-to-date, which is what we already do now?

image

checkUpdatesMenuItem.setText(I18N.getString("menu.title.check.updates.available"));
});
}
});
}

private void addSwatchGraphic(RadioMenuItem swatchMenuItem) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@
import java.net.URL;
import java.util.Properties;
import java.util.function.Consumer;
import java.util.logging.Level;
import java.util.logging.Logger;

public class AppSettings {
public static final String APP_ICON_16 = SceneBuilderApp.class.getResource("SceneBuilderLogo_16.png").toString();
Expand All @@ -64,9 +66,9 @@ public class AppSettings {

private static String sceneBuilderVersion;
private static String latestVersion;

private static String latestVersionText;
private static String latestVersionAnnouncementURL;
private static boolean isUpdateAvailable = false;

private static final JsonReaderFactory readerFactory = Json.createReaderFactory(null);

Expand All @@ -82,7 +84,7 @@ private static void initSceneBuiderVersion() {
sceneBuilderVersion = sbProps.getProperty("build.version", "UNSET");
}
} catch (IOException ex) {
ex.printStackTrace();
Logger.getLogger(AppSettings.class.getName()).log(Level.SEVERE, "Failed to load \"about.propertties\" resource.", ex);
}
}

Expand Down Expand Up @@ -114,6 +116,10 @@ public static boolean isCurrentVersionLowerThan(String version) {
return false;
}

public static boolean isUpdateAvailable() {
return isUpdateAvailable;
}

public static void getLatestVersion(Consumer<String> consumer) {

if (latestVersion == null) {
Expand All @@ -124,18 +130,25 @@ public static void getLatestVersion(Consumer<String> consumer) {
URL url = null;
try {
url = new URL(LATEST_VERSION_CHECK_URL);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (MalformedURLException ex) {
Logger.getLogger(AppSettings.class.getName()).log(Level.SEVERE, "Failed to parse latest version check URL.", ex);
}

try (InputStream inputStream = url.openStream()) {
prop.load(inputStream);
onlineVersionNumber = prop.getProperty(LATEST_VERSION_NUMBER_PROPERTY);

} catch (IOException ex) {
ex.printStackTrace();
Logger.getLogger(AppSettings.class.getName()).log(Level.SEVERE, "Failed retrieve latest version information.", ex);
}
latestVersion = onlineVersionNumber;

try {
isUpdateAvailable = isCurrentVersionLowerThan(latestVersion);
} catch (NumberFormatException ex) {
Logger.getLogger(AppSettings.class.getName()).log(Level.SEVERE, "Failed to load parse latest version number.", ex);
}

consumer.accept(latestVersion);
}, "GetLatestVersion").start();
} else {
Expand All @@ -159,11 +172,11 @@ private static void updateLatestVersionInfo() {
JsonObject announcementObject = object.getJsonObject("announcement");
latestVersionText = announcementObject.getString("text");
latestVersionAnnouncementURL = announcementObject.getString("url");
} catch (IOException e) {
e.printStackTrace();
} catch (IOException ex) {
Logger.getLogger(AppSettings.class.getName()).log(Level.SEVERE, "Failed to retrieve or decode latest version information.", ex);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (MalformedURLException ex) {
Logger.getLogger(AppSettings.class.getName()).log(Level.SEVERE, "Failed to parse latest version information URL", ex);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,9 @@ menu.title.no.window = No Window
# Help menu items
menu.title.scene.builder.help = Scene Builder Help
menu.title.show.welcome = Show Welcome Page
menu.title.check.updates = Check for Update...
menu.title.check.updates.available = Update available
menu.title.check.updates.ok = No updates available

menu.title.about = About Scene Builder
menu.title.register = Register...
menu.title.help.javafx=JavaFX
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
<?import javafx.scene.control.SeparatorMenuItem?>
<?import javafx.scene.layout.StackPane?>

<?import javafx.scene.image.ImageView?>
<?import javafx.scene.image.Image?>

<StackPane xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1">
<children>
<MenuBar fx:id="menuBar">
Expand Down Expand Up @@ -313,7 +316,15 @@
<MenuItem fx:id="communityContributeMenuItem" mnemonicParsing="false" text="%menu.title.help.scenebuilder.contribute" />
<MenuItem fx:id="sceneBuilderHomeMenuItem" mnemonicParsing="false" text="%menu.title.help.scenebuilder.home" />
<SeparatorMenuItem mnemonicParsing="false" />
<MenuItem fx:id="checkUpdatesMenuItem" mnemonicParsing="true" text="%menu.title.check.updates" />
<MenuItem fx:id="checkUpdatesMenuItem" disable="true" mnemonicParsing="true" text="%menu.title.check.updates.ok">
<graphic>
<ImageView>
<image>
<Image url="@check_icon.png" />
</image>
</ImageView>
</graphic>
</MenuItem>
<MenuItem fx:id="registerMenuItem" mnemonicParsing="false" text="%menu.title.register" />
<MenuItem fx:id="showWelcomeItem" mnemonicParsing="false" text="%menu.title.show.welcome" />
<MenuItem fx:id="aboutMenuItem" mnemonicParsing="false" text="%menu.title.about" />
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.