|
20 | 20 |
|
21 | 21 | import com.sun.javafx.PlatformUtil; |
22 | 22 | import com.sun.javafx.scene.control.skin.LabeledText; |
| 23 | +import de.codecentric.centerdevice.MenuToolkit; |
23 | 24 | import javafx.application.Platform; |
24 | 25 | import javafx.beans.value.ObservableValue; |
25 | 26 | import javafx.collections.FXCollections; |
26 | 27 | import javafx.collections.ObservableList; |
27 | 28 | import javafx.event.ActionEvent; |
| 29 | +import javafx.event.EventHandler; |
28 | 30 | import javafx.fxml.FXML; |
29 | 31 | import javafx.scene.control.*; |
30 | 32 | import javafx.scene.effect.DropShadow; |
|
33 | 35 | import javafx.scene.layout.VBox; |
34 | 36 | import javafx.scene.paint.Color; |
35 | 37 | import javafx.stage.DirectoryChooser; |
| 38 | +import javafx.stage.WindowEvent; |
36 | 39 | import org.json.JSONArray; |
37 | 40 |
|
38 | 41 | import java.awt.Desktop; |
|
54 | 57 | import java.util.zip.ZipInputStream; |
55 | 58 |
|
56 | 59 | import static blobsaver.Main.appPrefs; |
| 60 | +import static blobsaver.Main.primaryStage; |
57 | 61 | import static blobsaver.Shared.githubIssue; |
58 | 62 | import static blobsaver.Shared.newReportableError; |
59 | 63 | import static blobsaver.Shared.newUnreportableError; |
|
64 | 68 | public class Controller { |
65 | 69 |
|
66 | 70 |
|
| 71 | + @FXML private MenuBar menuBar; |
| 72 | + |
67 | 73 | @FXML private ChoiceBox deviceTypeChoiceBox; |
68 | 74 | @FXML private ChoiceBox deviceModelChoiceBox; |
69 | 75 |
|
@@ -261,6 +267,17 @@ public void initialize() { |
261 | 267 | path = path.replaceAll("%20", " "); |
262 | 268 | pathField.setText(path); |
263 | 269 |
|
| 270 | + if (PlatformUtil.isMac()) { |
| 271 | + EventHandler<WindowEvent> onShowing = new EventHandler<WindowEvent>() { |
| 272 | + @Override |
| 273 | + public void handle(WindowEvent event) { |
| 274 | + log("using macos menu bar"); |
| 275 | + useMacOSMenuBar(); |
| 276 | + primaryStage.removeEventHandler(event.getEventType(), this); |
| 277 | + } |
| 278 | + }; |
| 279 | + primaryStage.setOnShowing(onShowing); |
| 280 | + } |
264 | 281 | } |
265 | 282 |
|
266 | 283 | public void checkForUpdatesHandler() { |
@@ -768,61 +785,132 @@ public void aboutMenuHandler() { |
768 | 785 | "This program is licensed under GNU GPL v3.0-only"); |
769 | 786 | resizeAlertButtons(alert); |
770 | 787 | alert.showAndWait(); |
771 | | - if (githubRepo.equals(alert.getResult())) { |
772 | | - try { |
773 | | - Desktop.getDesktop().browse(new URI("https://github.com/airsquared/blobsaver")); |
774 | | - } catch (IOException | URISyntaxException e) { |
775 | | - e.printStackTrace(); |
776 | | - } |
777 | | - } else if (viewLicense.equals(alert.getResult())) { |
778 | | - try { |
779 | | - InputStream input; |
780 | | - if (PlatformUtil.isWindows()) { |
781 | | - input = Main.class.getResourceAsStream("gpl-3.0_windows.txt"); |
782 | | - } else { |
783 | | - input = Main.class.getResourceAsStream("gpl-3.0.txt"); |
| 788 | + switch (alert.getResult().getText()) { |
| 789 | + case "Github Repo": |
| 790 | + try { |
| 791 | + Desktop.getDesktop().browse(new URI("https://github.com/airsquared/blobsaver")); |
| 792 | + } catch (IOException | URISyntaxException e) { |
| 793 | + e.printStackTrace(); |
784 | 794 | } |
785 | | - File licenseFile = File.createTempFile("gpl-3.0_", ".txt"); |
786 | | - OutputStream out = new FileOutputStream(licenseFile); |
787 | | - int read; |
788 | | - byte[] bytes = new byte[1024]; |
| 795 | + break; |
| 796 | + case "View License": |
| 797 | + try { |
| 798 | + InputStream input; |
| 799 | + if (PlatformUtil.isWindows()) { |
| 800 | + input = Main.class.getResourceAsStream("gpl-3.0_windows.txt"); |
| 801 | + } else { |
| 802 | + input = Main.class.getResourceAsStream("gpl-3.0.txt"); |
| 803 | + } |
| 804 | + File licenseFile = File.createTempFile("gpl-3.0_", ".txt"); |
| 805 | + OutputStream out = new FileOutputStream(licenseFile); |
| 806 | + int read; |
| 807 | + byte[] bytes = new byte[1024]; |
789 | 808 |
|
790 | | - while ((read = input.read(bytes)) != -1) { |
791 | | - out.write(bytes, 0, read); |
792 | | - } |
793 | | - out.close(); |
794 | | - licenseFile.deleteOnExit(); |
795 | | - licenseFile.setReadOnly(); |
796 | | - java.awt.Desktop.getDesktop().edit(licenseFile); |
797 | | - } catch (IOException e) { |
798 | | - e.printStackTrace(); |
799 | | - } |
800 | | - } else if (librariesUsed.equals(alert.getResult())) { |
801 | | - try { |
802 | | - InputStream input; |
803 | | - if (PlatformUtil.isWindows()) { |
804 | | - input = getClass().getResourceAsStream("libraries_used_windows.txt"); |
805 | | - } else { |
806 | | - input = getClass().getResourceAsStream("libraries_used.txt"); |
| 809 | + while ((read = input.read(bytes)) != -1) { |
| 810 | + out.write(bytes, 0, read); |
| 811 | + } |
| 812 | + out.close(); |
| 813 | + licenseFile.deleteOnExit(); |
| 814 | + licenseFile.setReadOnly(); |
| 815 | + java.awt.Desktop.getDesktop().edit(licenseFile); |
| 816 | + } catch (IOException e) { |
| 817 | + e.printStackTrace(); |
807 | 818 | } |
808 | | - File libsUsedFile = File.createTempFile("blobsaver-libraries_used_", ".txt"); |
809 | | - OutputStream out = new FileOutputStream(libsUsedFile); |
810 | | - int read; |
811 | | - byte[] bytes = new byte[1024]; |
| 819 | + break; |
| 820 | + case "Libraries Used": |
| 821 | + try { |
| 822 | + InputStream input; |
| 823 | + if (PlatformUtil.isWindows()) { |
| 824 | + input = Main.class.getResourceAsStream("libraries_used_windows.txt"); |
| 825 | + } else { |
| 826 | + input = Main.class.getResourceAsStream("libraries_used.txt"); |
| 827 | + } |
| 828 | + File libsUsedFile = File.createTempFile("blobsaver-libraries_used_", ".txt"); |
| 829 | + OutputStream out = new FileOutputStream(libsUsedFile); |
| 830 | + int read; |
| 831 | + byte[] bytes = new byte[1024]; |
812 | 832 |
|
813 | | - while ((read = input.read(bytes)) != -1) { |
814 | | - out.write(bytes, 0, read); |
| 833 | + while ((read = input.read(bytes)) != -1) { |
| 834 | + out.write(bytes, 0, read); |
| 835 | + } |
| 836 | + out.close(); |
| 837 | + libsUsedFile.deleteOnExit(); |
| 838 | + libsUsedFile.setReadOnly(); |
| 839 | + java.awt.Desktop.getDesktop().edit(libsUsedFile); |
| 840 | + } catch (IOException e) { |
| 841 | + e.printStackTrace(); |
815 | 842 | } |
816 | | - out.close(); |
817 | | - libsUsedFile.deleteOnExit(); |
818 | | - libsUsedFile.setReadOnly(); |
819 | | - java.awt.Desktop.getDesktop().edit(libsUsedFile); |
820 | | - } catch (IOException e) { |
821 | | - e.printStackTrace(); |
822 | | - } |
| 843 | + break; |
823 | 844 | } |
824 | 845 | } |
825 | 846 |
|
| 847 | + private void useMacOSMenuBar() { |
| 848 | + |
| 849 | + ((VBox) menuBar.getParent()).setMinHeight(560.0); |
| 850 | + ((VBox) menuBar.getParent()).setPrefHeight(560.0); |
| 851 | + presetVBox.setMinHeight(560.0); |
| 852 | + presetVBox.setPrefHeight(560.0); |
| 853 | + |
| 854 | + menuBar.setUseSystemMenuBar(true); |
| 855 | + MenuBar macOSMenuBar = new MenuBar(); |
| 856 | + MenuToolkit tk = MenuToolkit.toolkit(); |
| 857 | + |
| 858 | + Menu applicationMenu = tk.createDefaultApplicationMenu("blobsaver"); |
| 859 | + |
| 860 | + MenuItem aboutMenuItem = new MenuItem("About blobsaver"); |
| 861 | + aboutMenuItem.setOnAction(event2 -> aboutMenuHandler()); |
| 862 | + applicationMenu.getItems().set(0, aboutMenuItem); |
| 863 | + |
| 864 | + MenuItem checkForUpdatesMenuItem = new MenuItem("Check for Updates..."); |
| 865 | + checkForUpdatesMenuItem.setOnAction(event1 -> checkForUpdatesHandler()); |
| 866 | + applicationMenu.getItems().add(1, new SeparatorMenuItem()); |
| 867 | + applicationMenu.getItems().add(2, checkForUpdatesMenuItem); |
| 868 | + |
| 869 | + MenuItem clearAllDataMenuItem = new MenuItem("Clear all data..."); |
| 870 | + clearAllDataMenuItem.setOnAction(event1 -> resetAppHandler()); |
| 871 | + applicationMenu.getItems().add(3, new SeparatorMenuItem()); |
| 872 | + applicationMenu.getItems().add(4, clearAllDataMenuItem); |
| 873 | + |
| 874 | + macOSMenuBar.getMenus().add(0, applicationMenu); |
| 875 | + |
| 876 | + |
| 877 | + Menu windowMenu = new Menu("Window"); |
| 878 | + |
| 879 | + windowMenu.getItems().add(new SeparatorMenuItem()); |
| 880 | + windowMenu.getItems().add(tk.createMinimizeMenuItem()); |
| 881 | + windowMenu.getItems().add(tk.createCycleWindowsItem()); |
| 882 | + |
| 883 | + MenuItem debugLogMenuItem = new MenuItem("Open/Close Debug log"); |
| 884 | + debugLogMenuItem.setOnAction(event -> { |
| 885 | + debugLogHandler(); |
| 886 | + tk.setMenuBar(DebugWindow.getDebugStage(), macOSMenuBar); |
| 887 | + }); |
| 888 | + windowMenu.getItems().add(new SeparatorMenuItem()); |
| 889 | + windowMenu.getItems().add(debugLogMenuItem); |
| 890 | + |
| 891 | + windowMenu.getItems().add(new SeparatorMenuItem()); |
| 892 | + windowMenu.getItems().add(tk.createBringAllToFrontItem()); |
| 893 | + windowMenu.getItems().add(new SeparatorMenuItem()); |
| 894 | + tk.autoAddWindowMenuItems(windowMenu); |
| 895 | + |
| 896 | + macOSMenuBar.getMenus().add(windowMenu); |
| 897 | + |
| 898 | + |
| 899 | + Menu helpMenu = menuBar.getMenus().get(1); |
| 900 | + |
| 901 | + helpMenu.getItems().add(1, new SeparatorMenuItem()); |
| 902 | + helpMenu.getItems().add(4, new SeparatorMenuItem()); |
| 903 | + |
| 904 | + MenuItem checkForValidBlobsMenuItem = new MenuItem("Check for Valid Blobs..."); |
| 905 | + checkForValidBlobsMenuItem.setOnAction(event -> checkBlobs()); |
| 906 | + helpMenu.getItems().set(5, checkForValidBlobsMenuItem); |
| 907 | + |
| 908 | + macOSMenuBar.getMenus().add(helpMenu); |
| 909 | + |
| 910 | + |
| 911 | + tk.setMenuBar(primaryStage, macOSMenuBar); |
| 912 | + } |
| 913 | + |
826 | 914 | public void backgroundSettingsHandler() { |
827 | 915 | choosingRunInBackground = !choosingRunInBackground; |
828 | 916 | if (choosingRunInBackground) { |
|
0 commit comments