From 6dc2b36d1439a89ed393f5cc710955369477273a Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Tue, 1 Aug 2017 13:51:48 +0800 Subject: [PATCH] HMCLKotlin project --- .nb-gradle-properties | 36 - .travis.yml | 14 - HMCL/HMCL.keystore | Bin 2284 -> 0 bytes HMCL/HMCLauncher.exe | Bin 40960 -> 0 bytes HMCL/build.gradle | 197 +-- HMCL/icon.ico | Bin 4286 -> 0 bytes HMCL/src/main/icon.icns | Bin 158805 -> 0 bytes .../main/java/org/jackhuang/hmcl/Main.java | 251 --- .../api/event/config/ProfileChangedEvent.java | 37 - .../api/event/config/ProfileLoadingEvent.java | 35 - .../org/jackhuang/hmcl/setting/Config.java | 342 ---- .../org/jackhuang/hmcl/setting/Profile.java | 183 -- .../org/jackhuang/hmcl/setting/Settings.java | 172 -- .../hmcl/setting/VersionSetting.java | 341 ---- .../org/jackhuang/hmcl/ui/DraggableFrame.java | 73 - .../jackhuang/hmcl/ui/GameDownloadPanel.form | 85 - .../jackhuang/hmcl/ui/GameDownloadPanel.java | 172 -- .../jackhuang/hmcl/ui/GameSettingsPanel.form | 1017 ----------- .../jackhuang/hmcl/ui/GameSettingsPanel.java | 1532 ----------------- .../java/org/jackhuang/hmcl/ui/HeaderTab.java | 108 -- .../org/jackhuang/hmcl/ui/InstallerPanel.form | 85 - .../org/jackhuang/hmcl/ui/InstallerPanel.java | 210 --- .../jackhuang/hmcl/ui/JLineWrapTextPane.java | 101 -- .../hmcl/ui/LauncherSettingsPanel.form | 582 ------- .../hmcl/ui/LauncherSettingsPanel.java | 655 ------- .../jackhuang/hmcl/ui/LaunchingUIDaemon.java | 257 --- .../java/org/jackhuang/hmcl/ui/LogWindow.form | 245 --- .../java/org/jackhuang/hmcl/ui/LogWindow.java | 425 ----- .../hmcl/ui/LogWindowOutputStream.java | 83 - .../java/org/jackhuang/hmcl/ui/MainFrame.java | 506 ------ .../org/jackhuang/hmcl/ui/MainPagePanel.form | 304 ---- .../org/jackhuang/hmcl/ui/MainPagePanel.java | 553 ------ .../jackhuang/hmcl/ui/NewProfileWindow.form | 124 -- .../jackhuang/hmcl/ui/NewProfileWindow.java | 164 -- .../org/jackhuang/hmcl/ui/NewTabPane.java | 59 - .../org/jackhuang/hmcl/ui/RepaintPage.java | 58 - .../ui/modpack/ModpackDescriptionPanel.form | 75 - .../ui/modpack/ModpackDescriptionPanel.java | 129 -- .../ui/modpack/ModpackFileSelectionPanel.form | 41 - .../ui/modpack/ModpackFileSelectionPanel.java | 141 -- .../modpack/ModpackInitializationPanel.form | 145 -- .../modpack/ModpackInitializationPanel.java | 230 --- .../hmcl/ui/modpack/ModpackWizard.java | 193 --- .../jackhuang/hmcl/util/CrashReporter.java | 151 -- .../jackhuang/hmcl/util/DefaultPlugin.java | 78 - .../jackhuang/hmcl/util/FileNameFilter.java | 45 - .../jackhuang/hmcl/util/HMCLAssetService.java | 47 - .../jackhuang/hmcl/util/HMCLGameLauncher.java | 112 -- .../jackhuang/hmcl/util/HMCLGameProvider.java | 58 - .../hmcl/util/HMCLMinecraftLoader.java | 51 - .../hmcl/util/HMCLMinecraftService.java | 187 -- .../hmcl/util/LauncherVisibility.java | 44 - .../org/jackhuang/hmcl/util/Log4jHandler.java | 150 -- .../hmcl/util/MinecraftCrashAdvicer.java | 58 - .../hmcl/util/upgrade/AppDataUpgrader.java | 258 --- .../hmcl/util/upgrade/IUpgrader.java | 50 - .../hmcl/util/upgrade/NewFileUpgrader.java | 65 - .../org/jackhuang/hmcl/background.jpg | Bin 83434 -> 0 bytes .../resources/org/jackhuang/hmcl/close.png | Bin 382 -> 0 bytes .../resources/org/jackhuang/hmcl/icon-new.png | Bin 28154 -> 0 bytes .../resources/org/jackhuang/hmcl/icon.png | Bin 5362 -> 0 bytes .../resources/org/jackhuang/hmcl/log4j.xml | 25 - .../resources/org/jackhuang/hmcl/minimize.png | Bin 232 -> 0 bytes HMCLAPI/build.gradle | 29 - .../java/org/jackhuang/hmcl/api/HMCLApi.java | 34 - .../java/org/jackhuang/hmcl/api/HMCLog.java | 50 - .../java/org/jackhuang/hmcl/api/ILogger.java | 35 - .../java/org/jackhuang/hmcl/api/IPlugin.java | 46 - .../java/org/jackhuang/hmcl/api/IProcess.java | 42 - .../org/jackhuang/hmcl/api/PluginManager.java | 94 - .../org/jackhuang/hmcl/api/VersionNumber.java | 116 -- .../java/org/jackhuang/hmcl/api/Wrapper.java | 39 - .../api/auth/AuthenticationException.java | 41 - .../hmcl/api/auth/IAuthenticator.java | 75 - .../jackhuang/hmcl/api/auth/LoginInfo.java | 32 - .../hmcl/api/auth/UserProfileProvider.java | 118 -- .../jackhuang/hmcl/api/event/EventBus.java | 48 - .../hmcl/api/event/EventHandler.java | 79 - .../hmcl/api/event/OutOfDateEvent.java | 39 - .../hmcl/api/event/PropertyChangedEvent.java | 49 - .../hmcl/api/event/ResultedEvent.java | 44 - .../hmcl/api/event/ResultedSimpleEvent.java | 41 - .../jackhuang/hmcl/api/event/SimpleEvent.java | 41 - .../config/AuthenticatorChangedEvent.java | 37 - .../config/DownloadTypeChangedEvent.java | 36 - .../api/event/config/ThemeChangedEvent.java | 37 - .../hmcl/api/event/launch/LaunchEvent.java | 37 - .../event/launch/LaunchSucceededEvent.java | 37 - .../hmcl/api/event/launch/LaunchingState.java | 32 - .../launch/LaunchingStateChangedEvent.java | 36 - .../launch/ProcessingLaunchOptionsEvent.java | 41 - .../launch/ProcessingLoginResultEvent.java | 41 - .../event/process/JVMLaunchFailedEvent.java | 37 - .../JavaProcessExitedAbnormallyEvent.java | 37 - .../process/JavaProcessStartingEvent.java | 37 - .../process/JavaProcessStoppedEvent.java | 37 - .../event/version/LoadedOneVersionEvent.java | 36 - .../event/version/RefreshedVersionsEvent.java | 36 - .../version/RefreshingVersionsEvent.java | 36 - .../jackhuang/hmcl/api/func/BiFunction.java | 27 - .../jackhuang/hmcl/api/func/CallbackIO.java | 29 - .../org/jackhuang/hmcl/api/func/Consumer.java | 29 - .../org/jackhuang/hmcl/api/func/Function.java | 27 - .../jackhuang/hmcl/api/func/NonFunction.java | 27 - .../jackhuang/hmcl/api/func/Predicate.java | 27 - .../hmcl/api/game/DecompressLibraryJob.java | 52 - .../org/jackhuang/hmcl/api/game/Extract.java | 55 - .../jackhuang/hmcl/api/game/GameDirType.java | 28 - .../hmcl/api/game/IMinecraftLibrary.java | 45 - .../hmcl/api/game/LaunchOptions.java | 212 --- .../jackhuang/hmcl/api/ui/AddTabCallback.java | 35 - .../java/org/jackhuang/hmcl/api/ui/Theme.java | 50 - .../org/jackhuang/hmcl/api/ui/TopTabPage.java | 41 - HMCLCore/build.gradle | 34 - .../jackhuang/hmcl/core/GameException.java | 41 - .../java/org/jackhuang/hmcl/core/MCUtils.java | 81 - .../hmcl/core/RuntimeGameException.java | 40 - .../hmcl/core/asset/AssetsIndex.java | 55 - .../hmcl/core/asset/AssetsMojangLoader.java | 103 -- .../hmcl/core/asset/AssetsObject.java | 72 - .../hmcl/core/asset/IAssetsHandler.java | 142 -- .../core/asset/MinecraftAssetService.java | 249 --- .../hmcl/core/auth/AbstractAuthenticator.java | 105 -- .../hmcl/core/auth/OfflineAuthenticator.java | 112 -- .../core/auth/YggdrasilAuthenticator.java | 146 -- .../auth/yggdrasil/AuthenticationRequest.java | 77 - .../hmcl/core/auth/yggdrasil/GameProfile.java | 99 -- .../hmcl/core/auth/yggdrasil/Property.java | 28 - .../hmcl/core/auth/yggdrasil/PropertyMap.java | 116 -- .../core/auth/yggdrasil/RefreshRequest.java | 64 - .../hmcl/core/auth/yggdrasil/Response.java | 40 - .../core/auth/yggdrasil/UUIDTypeAdapter.java | 45 - .../hmcl/core/auth/yggdrasil/User.java | 44 - .../hmcl/core/auth/yggdrasil/UserType.java | 55 - .../core/auth/yggdrasil/ValidateRequest.java | 33 - .../yggdrasil/YggdrasilAuthentication.java | 274 --- .../download/BMCLAPIDownloadProvider.java | 85 - .../core/download/CurseDownloadProvider.java | 31 - .../core/download/DownloadLibraryJob.java | 53 - .../hmcl/core/download/DownloadType.java | 68 - .../hmcl/core/download/IDownloadProvider.java | 69 - .../download/MinecraftDownloadService.java | 163 -- .../MinecraftRemoteLatestVersion.java | 34 - .../core/download/MinecraftRemoteVersion.java | 44 - .../download/MinecraftRemoteVersions.java | 88 - .../core/download/MojangDownloadProvider.java | 89 - .../hmcl/core/install/InstallProfile.java | 34 - .../hmcl/core/install/InstallerType.java | 36 - .../core/install/InstallerVersionList.java | 136 -- .../InstallerVersionNewerComparator.java | 36 - .../install/MinecraftInstallerService.java | 88 - .../core/install/forge/ForgeInstaller.java | 99 -- .../hmcl/core/install/forge/Install.java | 122 -- .../install/forge/MinecraftForgeVersion.java | 79 - .../forge/MinecraftForgeVersionList.java | 119 -- .../forge/MinecraftForgeVersionRoot.java | 47 - .../install/liteloader/LiteLoaderBranch.java | 35 - .../liteloader/LiteLoaderInstaller.java | 102 -- .../LiteLoaderInstallerVersion.java | 58 - .../liteloader/LiteLoaderMCVersions.java | 36 - .../install/liteloader/LiteLoaderRepo.java | 35 - .../install/liteloader/LiteLoaderVersion.java | 44 - .../liteloader/LiteLoaderVersionList.java | 118 -- .../liteloader/LiteLoaderVersionsMeta.java | 61 - .../liteloader/LiteLoaderVersionsRoot.java | 33 - .../install/optifine/OptiFineInstaller.java | 108 -- .../install/optifine/OptiFineVersion.java | 68 - .../bmcl/OptiFineBMCLVersionList.java | 104 -- .../vanilla/OptiFineDownloadFormatter.java | 58 - .../optifine/vanilla/OptiFineVersionList.java | 138 -- .../core/launch/AbstractMinecraftLoader.java | 205 --- .../hmcl/core/launch/DefaultGameLauncher.java | 75 - .../hmcl/core/launch/GameLauncher.java | 223 --- .../hmcl/core/launch/IAssetProvider.java | 30 - .../hmcl/core/launch/LibraryDownloadTask.java | 43 - .../hmcl/core/launch/MinecraftLoader.java | 138 -- .../hmcl/core/mod/MinecraftModService.java | 114 -- .../jackhuang/hmcl/core/mod/ModAdviser.java | 34 - .../org/jackhuang/hmcl/core/mod/ModInfo.java | 186 -- .../hmcl/core/mod/ModpackManager.java | 273 --- .../core/service/IMinecraftAssetService.java | 62 - .../core/service/IMinecraftBasicService.java | 32 - .../service/IMinecraftDownloadService.java | 50 - .../service/IMinecraftInstallerService.java | 42 - .../hmcl/core/service/IMinecraftLoader.java | 33 - .../core/service/IMinecraftModService.java | 41 - .../hmcl/core/service/IMinecraftProvider.java | 164 -- .../hmcl/core/service/IMinecraftService.java | 60 - .../jackhuang/hmcl/core/service/IProfile.java | 43 - .../version/AbstractMinecraftLibrary.java | 69 - .../core/version/AssetIndexDownloadInfo.java | 46 - .../hmcl/core/version/GameDownloadInfo.java | 86 - .../core/version/LibrariesDownloadInfo.java | 33 - .../core/version/LibraryDownloadInfo.java | 46 - .../hmcl/core/version/LoggingInfo.java | 41 - .../core/version/MinecraftClassicVersion.java | 74 - .../hmcl/core/version/MinecraftLibrary.java | 142 -- .../core/version/MinecraftOldLibrary.java | 57 - .../hmcl/core/version/MinecraftVersion.java | 227 --- .../core/version/MinecraftVersionManager.java | 311 ---- .../jackhuang/hmcl/core/version/Natives.java | 43 - .../hmcl/core/version/OSRestriction.java | 54 - .../jackhuang/hmcl/core/version/Rules.java | 40 - .../hmcl/util/AbstractSwingWorker.java | 79 - .../org/jackhuang/hmcl/util/ArrayUtils.java | 107 -- .../main/java/org/jackhuang/hmcl/util/C.java | 48 - .../jackhuang/hmcl/util/CollectionUtils.java | 52 - .../hmcl/util/DoubleOutputStream.java | 90 - .../jackhuang/hmcl/util/IUpdateChecker.java | 62 - .../org/jackhuang/hmcl/util/MathUtils.java | 60 - .../hmcl/util/MinecraftVersionRequest.java | 181 -- .../java/org/jackhuang/hmcl/util/Pair.java | 78 - .../org/jackhuang/hmcl/util/StrUtils.java | 186 -- .../jackhuang/hmcl/util/UpdateChecker.java | 106 -- .../java/org/jackhuang/hmcl/util/Utils.java | 62 - .../jackhuang/hmcl/util/code/Charsets.java | 55 - .../jackhuang/hmcl/util/code/DigestUtils.java | 251 --- .../org/jackhuang/hmcl/util/code/Hex.java | 128 -- .../hmcl/util/lang/Localization.java | 76 - .../hmcl/util/lang/SupportedLocales.java | 73 - .../hmcl/util/log/AppenderControl.java | 68 - .../hmcl/util/log/Configuration.java | 40 - .../org/jackhuang/hmcl/util/log/Level.java | 129 -- .../org/jackhuang/hmcl/util/log/LogEvent.java | 33 - .../hmcl/util/log/LoggingException.java | 30 - .../util/log/appender/AbstractAppender.java | 57 - .../util/log/appender/ConsoleAppender.java | 90 - .../hmcl/util/log/appender/IAppender.java | 38 - .../log/appender/OutputStreamAppender.java | 63 - .../util/log/layout/AbstractStringLayout.java | 33 - .../hmcl/util/log/layout/DefaultLayout.java | 37 - .../hmcl/util/log/layout/ILayout.java | 34 - .../hmcl/util/log/logger/AbstractLogger.java | 396 ----- .../hmcl/util/log/logger/ILogger.java | 129 -- .../hmcl/util/log/logger/Logger.java | 165 -- .../log/message/AbstractMessageFactory.java | 36 - .../hmcl/util/log/message/IMessage.java | 35 - .../util/log/message/IMessageFactory.java | 31 - .../hmcl/util/log/message/ObjectMessage.java | 73 - .../log/message/ParameterizedMessage.java | 356 ---- .../message/ParameterizedMessageFactory.java | 30 - .../hmcl/util/log/message/SimpleMessage.java | 79 - .../log/message/StringFormattedMessage.java | 100 -- .../hmcl/util/net/FileDownloadTask.java | 249 --- .../jackhuang/hmcl/util/net/HTTPGetTask.java | 111 -- .../org/jackhuang/hmcl/util/net/NetUtils.java | 122 -- .../org/jackhuang/hmcl/util/net/WebFrame.java | 53 - .../org/jackhuang/hmcl/util/net/WebPage.java | 53 - .../hmcl/util/sys/CompressingUtils.java | 163 -- .../jackhuang/hmcl/util/sys/FileUtils.java | 376 ---- .../org/jackhuang/hmcl/util/sys/IOUtils.java | 285 --- .../org/jackhuang/hmcl/util/sys/Java.java | 178 -- .../jackhuang/hmcl/util/sys/JavaProcess.java | 95 - .../jackhuang/hmcl/util/sys/JdkVersion.java | 158 -- .../java/org/jackhuang/hmcl/util/sys/OS.java | 94 - .../org/jackhuang/hmcl/util/sys/Platform.java | 56 - .../jackhuang/hmcl/util/sys/PrintlnEvent.java | 45 - .../hmcl/util/sys/ProcessMonitor.java | 139 -- .../hmcl/util/sys/ProcessThread.java | 92 - .../hmcl/util/sys/ReflectionHelper.java | 66 - .../hmcl/util/sys/WaitForThread.java | 47 - .../jackhuang/hmcl/util/sys/ZipEngine.java | 139 -- .../hmcl/util/task/DeleteFileTask.java | 45 - .../hmcl/util/task/DoingDoneListener.java | 48 - .../jackhuang/hmcl/util/task/DoubleTask.java | 71 - .../hmcl/util/task/NoShownTaskException.java | 30 - .../hmcl/util/task/ParallelTask.java | 56 - .../util/task/ProgressProviderListener.java | 31 - .../org/jackhuang/hmcl/util/task/Task.java | 137 -- .../jackhuang/hmcl/util/task/TaskInfo.java | 35 - .../jackhuang/hmcl/util/task/TaskList.java | 185 -- .../hmcl/util/task/TaskRunnable.java | 42 - .../jackhuang/hmcl/util/task/TaskWindow.form | 93 - .../jackhuang/hmcl/util/task/TaskWindow.java | 329 ---- .../jackhuang/hmcl/util/task/TaskWorker.java | 68 - .../hmcl/util/task/comm/PreviousResult.java | 29 - .../task/comm/PreviousResultRegistrar.java | 36 - .../hmcl/util/ui/AbstractFilter.java | 56 - .../jackhuang/hmcl/util/ui/BasicColors.java | 64 - .../hmcl/util/ui/DropShadowBorder.java | 94 - .../hmcl/util/ui/FastBlurFilter.java | 139 -- .../jackhuang/hmcl/util/ui/GaussionPanel.java | 107 -- .../jackhuang/hmcl/util/ui/GraphicsUtils.java | 265 --- .../org/jackhuang/hmcl/util/ui/IRepaint.java | 48 - .../jackhuang/hmcl/util/ui/JFontComboBox.java | 71 - .../hmcl/util/ui/JSystemFileChooser.java | 57 - .../jackhuang/hmcl/util/ui/MessageBox.java | 153 -- .../hmcl/util/ui/MyRepaintManager.java | 48 - .../java/org/jackhuang/hmcl/util/ui/Page.java | 163 -- .../hmcl/util/ui/StackBlurFilter.java | 149 -- .../jackhuang/hmcl/util/ui/SwingUtils.java | 403 ----- .../jackhuang/hmcl/util/ui/TintablePanel.java | 93 - .../jackhuang/hmcl/util/ui/WideComboBox.java | 65 - .../checktree/CheckBoxTreeCellRenderer.java | 99 -- .../util/ui/checktree/CheckBoxTreeLabel.java | 80 - .../util/ui/checktree/CheckBoxTreeNode.java | 114 -- .../CheckBoxTreeNodeSelectionListener.java | 45 - .../util/ui/wizard/api/WizardDisplayer.java | 167 -- .../ui/wizard/api/WizardResultReceiver.java | 45 - .../api/displayer/InstructionsPanel.java | 37 - .../api/displayer/NavButtonManager.java | 631 ------- .../ui/wizard/api/displayer/NavProgress.java | 147 -- .../api/displayer/WizardDisplayerImpl.java | 572 ------ .../wizard/modules/InstructionsPanelImpl.java | 429 ----- .../hmcl/util/ui/wizard/modules/MergeMap.java | 281 --- .../util/ui/wizard/spi/AbstractWizard.java | 41 - .../util/ui/wizard/spi/BranchingWizard.java | 317 ---- .../ui/wizard/spi/DeferredWizardResult.java | 127 -- .../util/ui/wizard/spi/GenericListener.java | 380 ---- .../ui/wizard/spi/ResultProgressHandle.java | 89 - .../hmcl/util/ui/wizard/spi/SimpleWizard.java | 211 --- .../util/ui/wizard/spi/SimpleWizardInfo.java | 315 ---- .../hmcl/util/ui/wizard/spi/Summary.java | 137 -- .../hmcl/util/ui/wizard/spi/Util.java | 158 -- .../hmcl/util/ui/wizard/spi/Wizard.java | 360 ---- .../ui/wizard/spi/WizardBranchController.java | 175 -- .../util/ui/wizard/spi/WizardController.java | 120 -- .../spi/WizardControllerImplementation.java | 70 - .../util/ui/wizard/spi/WizardException.java | 52 - .../ui/wizard/spi/WizardImplementation.java | 246 --- .../util/ui/wizard/spi/WizardObserver.java | 40 - .../hmcl/util/ui/wizard/spi/WizardPage.java | 1122 ------------ .../hmcl/util/ui/wizard/spi/WizardPanel.java | 97 -- .../ui/wizard/spi/WizardPanelNavResult.java | 70 - .../ui/wizard/spi/WizardPanelProvider.java | 312 ---- .../org/jackhuang/hmcl/lang/I18N.lang | 440 ----- .../org/jackhuang/hmcl/lang/I18N.properties | 440 ----- .../org/jackhuang/hmcl/lang/I18N_ru.lang | 440 ----- .../jackhuang/hmcl/lang/I18N_ru.properties | 441 ----- .../org/jackhuang/hmcl/lang/I18N_vi.lang | 438 ----- .../jackhuang/hmcl/lang/I18N_vi.properties | 438 ----- .../org/jackhuang/hmcl/lang/I18N_zh.lang | 440 ----- .../jackhuang/hmcl/lang/I18N_zh.properties | 440 ----- .../org/jackhuang/hmcl/lang/I18N_zh_CN.lang | 440 ----- .../jackhuang/hmcl/lang/I18N_zh_CN.properties | 440 ----- .../resources/org/jackhuang/hmcl/wizard.jpg | Bin 6041 -> 0 bytes HMCLaF/build.gradle | 33 - .../hmcl/laf/BeautyEyeLNFHelper.java | 391 ----- .../hmcl/laf/BeautyEyeLookAndFeel.java | 109 -- .../java/org/jackhuang/hmcl/laf/LAFTheme.java | 102 -- .../jackhuang/hmcl/laf/button/BEButtonUI.java | 363 ---- .../hmcl/laf/button/BEToggleButtonUI.java | 125 -- .../hmcl/laf/button/CustomButton.java | 32 - .../hmcl/laf/button/CustomButtonUI.java | 140 -- .../org/jackhuang/hmcl/laf/button/__UI__.java | 63 - .../hmcl/laf/combox/BEComboBoxRenderer.java | 118 -- .../hmcl/laf/combox/BEComboBoxUI.java | 406 ----- .../org/jackhuang/hmcl/laf/combox/__UI__.java | 54 - .../hmcl/laf/filechooser/BEFileChooserUI.java | 149 -- .../hmcl/laf/filechooser/__UI__.java | 54 - .../laf/internalframe/BEDesktopIconUI.java | 121 -- .../BEInternalFrameTitlePane.java | 631 ------- .../laf/internalframe/BEInternalFrameUI.java | 225 --- .../hmcl/laf/internalframe/__UI__.java | 55 - .../org/jackhuang/hmcl/laf/list/BEListUI.java | 61 - .../laf/list/MyDefaultListCellRenderer.java | 114 -- .../org/jackhuang/hmcl/laf/list/__UI__.java | 79 - .../hmcl/laf/menu/BECheckBoxMenuItemUI.java | 112 -- .../jackhuang/hmcl/laf/menu/BEMenuBarUI.java | 41 - .../jackhuang/hmcl/laf/menu/BEMenuItemUI.java | 71 - .../org/jackhuang/hmcl/laf/menu/BEMenuUI.java | 306 ---- .../hmcl/laf/menu/BEPopupMenuSeparatorUI.java | 122 -- .../hmcl/laf/menu/BEPopupMenuUI.java | 39 - .../laf/menu/BERadioButtonMenuItemUI.java | 105 -- .../org/jackhuang/hmcl/laf/menu/__UI__.java | 105 -- .../laf/popup/TranslucentPopupFactory.java | 389 ----- .../org/jackhuang/hmcl/laf/popup/__UI__.java | 23 - .../hmcl/laf/progress/BEProgressBarUI.java | 281 --- .../jackhuang/hmcl/laf/progress/__UI__.java | 32 - .../hmcl/laf/radio$cb_btn/BECheckBoxUI.java | 44 - .../laf/radio$cb_btn/BERadioButtonUI.java | 45 - .../hmcl/laf/radio$cb_btn/__UI__.java | 83 - .../hmcl/laf/resources/beautyeye.java | 31 - .../hmcl/laf/resources/beautyeye_zh_CN.java | 31 - .../hmcl/laf/scroll/BEScrollBarUI.java | 181 -- .../hmcl/laf/scroll/BEScrollPaneUI.java | 38 - .../hmcl/laf/scroll/ScrollPaneBorder.java | 29 - .../org/jackhuang/hmcl/laf/scroll/__UI__.java | 46 - .../hmcl/laf/separator/BEPanelUI.java | 46 - .../hmcl/laf/separator/BESeparatorUI.java | 75 - .../jackhuang/hmcl/laf/separator/__UI__.java | 68 - .../jackhuang/hmcl/laf/slider/BESliderUI.java | 158 -- .../org/jackhuang/hmcl/laf/slider/__UI__.java | 30 - .../hmcl/laf/spinner/BESpinnerUI.java | 138 -- .../jackhuang/hmcl/laf/spinner/__UI__.java | 31 - .../hmcl/laf/split/BESplitPaneDivider.java | 293 ---- .../hmcl/laf/split/BESplitPaneUI.java | 39 - .../laf/split/SplitPaneDividerBorder.java | 123 -- .../org/jackhuang/hmcl/laf/split/__UI__.java | 36 - .../hmcl/laf/tab/BETabbedPaneUI.java | 288 ---- .../org/jackhuang/hmcl/laf/tab/__UI__.java | 51 - .../hmcl/laf/table/BETableHeaderUI.java | 479 ------ .../jackhuang/hmcl/laf/table/BETableUI.java | 57 - .../laf/table/FocusCellHighlightBorder.java | 61 - .../hmcl/laf/table/TableScrollBorder.java | 29 - .../org/jackhuang/hmcl/laf/table/__UI__.java | 102 -- .../hmcl/laf/textcoms/BEEditorPaneUI.java | 67 - .../laf/textcoms/BEFormattedTextFieldUI.java | 96 -- .../hmcl/laf/textcoms/BEPasswordFieldUI.java | 94 - .../hmcl/laf/textcoms/BETextAreaUI.java | 65 - .../hmcl/laf/textcoms/BETextFieldUI.java | 104 -- .../hmcl/laf/textcoms/BETextPaneUI.java | 67 - .../hmcl/laf/textcoms/FocusListenerImpl.java | 249 --- .../jackhuang/hmcl/laf/textcoms/__UI__.java | 136 -- .../hmcl/laf/titlepane/BERootPaneUI.java | 1232 ------------- .../hmcl/laf/titlepane/BETitlePane.java | 1259 -------------- .../jackhuang/hmcl/laf/titlepane/__UI__.java | 80 - .../laf/toolbar/BEToolBarSeparatorUI.java | 115 -- .../hmcl/laf/toolbar/BEToolBarUI.java | 362 ---- .../jackhuang/hmcl/laf/toolbar/__UI__.java | 49 - .../org/jackhuang/hmcl/laf/tree/BETreeUI.java | 234 --- .../org/jackhuang/hmcl/laf/tree/__UI__.java | 53 - .../hmcl/laf/utils/AnimationController.java | 386 ----- .../org/jackhuang/hmcl/laf/utils/BEUtils.java | 448 ----- .../hmcl/laf/utils/Icon9Factory.java | 173 -- .../jackhuang/hmcl/laf/utils/IconFactory.java | 150 -- .../jackhuang/hmcl/laf/utils/LogHelper.java | 56 - .../hmcl/laf/utils/MySwingUtilities2.java | 178 -- .../hmcl/laf/utils/NinePatchHelper.java | 72 - .../jackhuang/hmcl/laf/utils/RawCache.java | 64 - .../org/jackhuang/hmcl/laf/utils/Skin.java | 31 - .../jackhuang/hmcl/laf/utils/TMSchema.java | 457 ----- .../java/org/jackhuang/hmcl/laf/utils/UI.java | 66 - .../jackhuang/hmcl/laf/utils/WinUtils.java | 147 -- .../laf/utils/WindowTranslucencyHelper.java | 54 - .../hmcl/laf/widget/ImageBgPanel.java | 98 -- .../hmcl/laf/widget/N9ComponentFactory.java | 137 -- .../laf/widget/border/BEDashedBorder.java | 76 - .../widget/border/BEDashedRoundRecBorder.java | 134 -- .../hmcl/laf/widget/border/BERoundBorder.java | 185 -- .../laf/widget/border/BEShadowBorder.java | 46 - .../laf/widget/border/BEShadowBorder3.java | 45 - .../laf/widget/border/NinePatchBorder.java | 68 - .../laf/widget/border/PlainGrayBorder.java | 48 - .../hmcl/laf/widget/border/package.html | 7 - .../jb2011/ninepatch4j/GraphicsUtilities.java | 73 - .../org/jb2011/ninepatch4j/NinePatch.java | 122 -- .../jb2011/ninepatch4j/NinePatchChunk.java | 358 ---- .../imgs/RadioButtonMenuItemCheckIcon2.png | Bin 812 -> 0 bytes .../imgs/RadioButtonMenuItemCheckIcon2_1.png | Bin 812 -> 0 bytes .../RadioButtonMenuItemCheckIcon_none.png | Bin 679 -> 0 bytes .../RadioButtonMenuItemCheckIcon_none_1.png | Bin 679 -> 0 bytes .../org/jackhuang/hmcl/laf/utils/imgs/a.png | Bin 2833 -> 0 bytes .../jackhuang/hmcl/laf/utils/imgs/asc2.png | Bin 2848 -> 0 bytes .../org/jackhuang/hmcl/laf/utils/imgs/b.png | Bin 2829 -> 0 bytes .../laf/utils/imgs/checkbox_menuitem_none.png | Bin 350 -> 0 bytes .../utils/imgs/checkbox_menuitem_none_1.png | Bin 350 -> 0 bytes .../checkbox_menuitem_selected_normal.png | Bin 519 -> 0 bytes .../checkbox_menuitem_selected_normal_1.png | Bin 519 -> 0 bytes .../hmcl/laf/utils/imgs/checkbox_off.png | Bin 205 -> 0 bytes .../laf/utils/imgs/checkbox_off_disabled.png | Bin 211 -> 0 bytes .../hmcl/laf/utils/imgs/checkbox_off_over.png | Bin 211 -> 0 bytes .../laf/utils/imgs/checkbox_off_pressed.png | Bin 211 -> 0 bytes .../hmcl/laf/utils/imgs/checkbox_on.png | Bin 521 -> 0 bytes .../laf/utils/imgs/checkbox_on_disabled.png | Bin 518 -> 0 bytes .../hmcl/laf/utils/imgs/checkbox_on_over.png | Bin 525 -> 0 bytes .../laf/utils/imgs/checkbox_on_pressed.png | Bin 526 -> 0 bytes .../laf/utils/imgs/default_frame_icon.png | Bin 569 -> 0 bytes .../jackhuang/hmcl/laf/utils/imgs/desc2.png | Bin 2826 -> 0 bytes .../jackhuang/hmcl/laf/utils/imgs/error.png | Bin 3155 -> 0 bytes .../laf/utils/imgs/frame_close_normal.png | Bin 3128 -> 0 bytes .../hmcl/laf/utils/imgs/frame_close_over.png | Bin 343 -> 0 bytes .../laf/utils/imgs/frame_close_pressed.png | Bin 3202 -> 0 bytes .../hmcl/laf/utils/imgs/frame_close_rover.png | Bin 3221 -> 0 bytes .../hmcl/laf/utils/imgs/frame_max_normal.png | Bin 3179 -> 0 bytes .../hmcl/laf/utils/imgs/frame_max_pressed.png | Bin 3212 -> 0 bytes .../hmcl/laf/utils/imgs/frame_max_rover.png | Bin 3252 -> 0 bytes .../laf/utils/imgs/frame_maximize_over.png | Bin 229 -> 0 bytes .../hmcl/laf/utils/imgs/frame_maxwin.png | Bin 3283 -> 0 bytes .../laf/utils/imgs/frame_maxwin_pressed.png | Bin 3231 -> 0 bytes .../laf/utils/imgs/frame_maxwin_rover.png | Bin 3275 -> 0 bytes .../hmcl/laf/utils/imgs/frame_min_normal.png | Bin 3108 -> 0 bytes .../hmcl/laf/utils/imgs/frame_min_pressed.png | Bin 3119 -> 0 bytes .../hmcl/laf/utils/imgs/frame_min_rover.png | Bin 3130 -> 0 bytes .../laf/utils/imgs/frame_minimize_over.png | Bin 235 -> 0 bytes .../laf/utils/imgs/frame_setup_normal.png | Bin 272 -> 0 bytes .../laf/utils/imgs/frame_windowize_over.png | Bin 1058 -> 0 bytes .../jackhuang/hmcl/laf/utils/imgs/head_bg.png | Bin 969 -> 0 bytes .../hmcl/laf/utils/imgs/head_inactive.png | Bin 2836 -> 0 bytes .../jackhuang/hmcl/laf/utils/imgs/ifi1.png | Bin 3043 -> 0 bytes .../jackhuang/hmcl/laf/utils/imgs/info.png | Bin 1994 -> 0 bytes .../jackhuang/hmcl/laf/utils/imgs/leaf1.png | Bin 326 -> 0 bytes .../hmcl/laf/utils/imgs/np/arrow.9.png | Bin 248 -> 0 bytes .../laf/utils/imgs/np/arrow_pressed.9.png | Bin 246 -> 0 bytes .../hmcl/laf/utils/imgs/np/arrow_rover.9.png | Bin 253 -> 0 bytes .../utils/imgs/np/btn_general_default.9.png | Bin 2940 -> 0 bytes .../utils/imgs/np/btn_general_pressed.9.png | Bin 258 -> 0 bytes .../laf/utils/imgs/np/btn_general_rover.9.png | Bin 241 -> 0 bytes .../utils/imgs/np/btn_special_default.9.png | Bin 263 -> 0 bytes .../utils/imgs/np/btn_special_disabled.9.png | Bin 217 -> 0 bytes .../laf/utils/imgs/np/combo_disabled.9.png | Bin 347 -> 0 bytes .../hmcl/laf/utils/imgs/np/combo_normal.9.png | Bin 349 -> 0 bytes .../hmcl/laf/utils/imgs/np/combo_over.9.png | Bin 346 -> 0 bytes .../laf/utils/imgs/np/combo_pressed.9.png | Bin 350 -> 0 bytes .../utils/imgs/np/frame_shadow_border4.9.png | Bin 5157 -> 0 bytes .../laf/utils/imgs/np/hint_bg_lightblue.9.png | Bin 272 -> 0 bytes .../imgs/np/hint_bg_lightblue_gray.9.png | Bin 2968 -> 0 bytes .../imgs/np/list_cell_selected_bg2.9.png | Bin 301 -> 0 bytes .../hmcl/laf/utils/imgs/np/menu_bg.9.png | Bin 301 -> 0 bytes .../laf/utils/imgs/np/orange_baloon1.9.png | Bin 422 -> 0 bytes .../hmcl/laf/utils/imgs/np/plain_gray1.9.png | Bin 166 -> 0 bytes .../laf/utils/imgs/np/progress_bar_bg.9.png | Bin 509 -> 0 bytes .../laf/utils/imgs/np/progress_bar_bg_v.9.png | Bin 538 -> 0 bytes .../utils/imgs/np/progress_bar_grean_v.9.png | Bin 2982 -> 0 bytes .../utils/imgs/np/progress_bar_green.9.png | Bin 3038 -> 0 bytes .../laf/utils/imgs/np/query_item_bg_2.9.png | Bin 4076 -> 0 bytes .../laf/utils/imgs/np/scroll_pane_bg1.9.png | Bin 247 -> 0 bytes .../hmcl/laf/utils/imgs/np/shadow1.9.png | Bin 3086 -> 0 bytes .../hmcl/laf/utils/imgs/np/shadow2.9.png | Bin 3984 -> 0 bytes .../laf/utils/imgs/np/shadow_bg_popup.9.png | Bin 348 -> 0 bytes .../utils/imgs/np/shadow_bg_tooltip2.9.png | Bin 1219 -> 0 bytes .../laf/utils/imgs/np/slider_track2.9.png | Bin 238 -> 0 bytes .../utils/imgs/np/slider_track2_dark.9.png | Bin 240 -> 0 bytes .../imgs/np/slider_track2_forgroud.9.png | Bin 273 -> 0 bytes .../np/slider_track2_forgroud_disable.9.png | Bin 3003 -> 0 bytes .../imgs/np/slider_track2_forgroud_v.9.png | Bin 349 -> 0 bytes .../np/slider_track2_forgroud_v_disable.9.png | Bin 2947 -> 0 bytes .../laf/utils/imgs/np/slider_track2_v.9.png | Bin 303 -> 0 bytes .../utils/imgs/np/slider_track2_v_dark.9.png | Bin 313 -> 0 bytes .../hmcl/laf/utils/imgs/np/spinner1_bg.9.png | Bin 295 -> 0 bytes .../utils/imgs/np/spinner1_btn_down_bg.9.png | Bin 322 -> 0 bytes .../np/spinner1_btn_down_pressed_bg.9.png | Bin 366 -> 0 bytes .../utils/imgs/np/spinner1_btn_up_bg.9.png | Bin 309 -> 0 bytes .../imgs/np/spinner1_btn_up_pressed_bg.9.png | Bin 315 -> 0 bytes .../utils/imgs/np/spinner1_disable_bg.9.png | Bin 3260 -> 0 bytes .../laf/utils/imgs/np/split_touch_bg1.9.png | Bin 257 -> 0 bytes .../laf/utils/imgs/np/table_header_bg1.9.png | Bin 178 -> 0 bytes .../imgs/np/table_header_separator1.9.png | Bin 2869 -> 0 bytes .../utils/imgs/np/table_scrollborder1.9.png | Bin 319 -> 0 bytes .../hmcl/laf/utils/imgs/np/tips_bg.9.png | Bin 1434 -> 0 bytes .../utils/imgs/np/toggle_button_rover.9.png | Bin 3658 -> 0 bytes .../imgs/np/toggle_button_selected.9.png | Bin 738 -> 0 bytes .../hmcl/laf/utils/imgs/np/toolbar_bg1.9.png | Bin 181 -> 0 bytes .../laf/utils/imgs/np/toolbar_bg1_EAST.9.png | Bin 259 -> 0 bytes .../laf/utils/imgs/np/toolbar_bg1_SOUTH.9.png | Bin 2898 -> 0 bytes .../laf/utils/imgs/np/toolbar_bg1_WEST.9.png | Bin 260 -> 0 bytes .../hmcl/laf/utils/imgs/question.png | Bin 3393 -> 0 bytes .../hmcl/laf/utils/imgs/radio_btn.png | Bin 772 -> 0 bytes .../utils/imgs/radio_btn_disabled_normal.png | Bin 738 -> 0 bytes .../imgs/radio_btn_disabled_selected.png | Bin 843 -> 0 bytes .../hmcl/laf/utils/imgs/radio_btn_over.png | Bin 785 -> 0 bytes .../hmcl/laf/utils/imgs/radio_btn_pressed.png | Bin 796 -> 0 bytes .../laf/utils/imgs/radio_btn_selected.png | Bin 883 -> 0 bytes .../utils/imgs/radio_btn_selected_over.png | Bin 893 -> 0 bytes .../utils/imgs/radio_btn_selected_pressed.png | Bin 937 -> 0 bytes .../hmcl/laf/utils/imgs/slider_tick1.png | Bin 3235 -> 0 bytes .../hmcl/laf/utils/imgs/slider_tick1_dark.png | Bin 3241 -> 0 bytes .../laf/utils/imgs/slider_tick1_notrangle.png | Bin 3366 -> 0 bytes .../imgs/slider_tick1_notrangle_dark.png | Bin 3363 -> 0 bytes .../utils/imgs/slider_tick1_notrangle_v.png | Bin 3179 -> 0 bytes .../imgs/slider_tick1_notrangle_v_dark.png | Bin 3189 -> 0 bytes .../hmcl/laf/utils/imgs/slider_tick1_v.png | Bin 3132 -> 0 bytes .../laf/utils/imgs/slider_tick1_v_dark.png | Bin 3140 -> 0 bytes .../laf/utils/imgs/treeDefaultClosed1.png | Bin 397 -> 0 bytes .../hmcl/laf/utils/imgs/treeDefaultOpen1.png | Bin 506 -> 0 bytes .../jackhuang/hmcl/laf/utils/imgs/warn.png | Bin 3110 -> 0 bytes LICENSE | 674 -------- README.md | 56 - build.gradle | 61 +- common.gradle | 50 - gradle/wrapper/gradle-wrapper.jar | Bin 52271 -> 54788 bytes gradle/wrapper/gradle-wrapper.properties | 4 +- gradlew | 74 +- gradlew.bat | 18 +- license-header.txt | 17 - settings.gradle | 39 +- 566 files changed, 97 insertions(+), 58905 deletions(-) delete mode 100755 .nb-gradle-properties delete mode 100644 .travis.yml delete mode 100644 HMCL/HMCL.keystore delete mode 100755 HMCL/HMCLauncher.exe delete mode 100755 HMCL/icon.ico delete mode 100755 HMCL/src/main/icon.icns delete mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/Main.java delete mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/api/event/config/ProfileChangedEvent.java delete mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/api/event/config/ProfileLoadingEvent.java delete mode 100755 HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java delete mode 100755 HMCL/src/main/java/org/jackhuang/hmcl/setting/Profile.java delete mode 100755 HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java delete mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java delete mode 100755 HMCL/src/main/java/org/jackhuang/hmcl/ui/DraggableFrame.java delete mode 100755 HMCL/src/main/java/org/jackhuang/hmcl/ui/GameDownloadPanel.form delete mode 100755 HMCL/src/main/java/org/jackhuang/hmcl/ui/GameDownloadPanel.java delete mode 100755 HMCL/src/main/java/org/jackhuang/hmcl/ui/GameSettingsPanel.form delete mode 100755 HMCL/src/main/java/org/jackhuang/hmcl/ui/GameSettingsPanel.java delete mode 100755 HMCL/src/main/java/org/jackhuang/hmcl/ui/HeaderTab.java delete mode 100755 HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerPanel.form delete mode 100755 HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerPanel.java delete mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/JLineWrapTextPane.java delete mode 100755 HMCL/src/main/java/org/jackhuang/hmcl/ui/LauncherSettingsPanel.form delete mode 100755 HMCL/src/main/java/org/jackhuang/hmcl/ui/LauncherSettingsPanel.java delete mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/LaunchingUIDaemon.java delete mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.form delete mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.java delete mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindowOutputStream.java delete mode 100755 HMCL/src/main/java/org/jackhuang/hmcl/ui/MainFrame.java delete mode 100755 HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPagePanel.form delete mode 100755 HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPagePanel.java delete mode 100755 HMCL/src/main/java/org/jackhuang/hmcl/ui/NewProfileWindow.form delete mode 100755 HMCL/src/main/java/org/jackhuang/hmcl/ui/NewProfileWindow.java delete mode 100755 HMCL/src/main/java/org/jackhuang/hmcl/ui/NewTabPane.java delete mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/RepaintPage.java delete mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/modpack/ModpackDescriptionPanel.form delete mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/modpack/ModpackDescriptionPanel.java delete mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/modpack/ModpackFileSelectionPanel.form delete mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/modpack/ModpackFileSelectionPanel.java delete mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/modpack/ModpackInitializationPanel.form delete mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/modpack/ModpackInitializationPanel.java delete mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/ui/modpack/ModpackWizard.java delete mode 100755 HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java delete mode 100755 HMCL/src/main/java/org/jackhuang/hmcl/util/DefaultPlugin.java delete mode 100755 HMCL/src/main/java/org/jackhuang/hmcl/util/FileNameFilter.java delete mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/util/HMCLAssetService.java delete mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/util/HMCLGameLauncher.java delete mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/util/HMCLGameProvider.java delete mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/util/HMCLMinecraftLoader.java delete mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/util/HMCLMinecraftService.java delete mode 100755 HMCL/src/main/java/org/jackhuang/hmcl/util/LauncherVisibility.java delete mode 100644 HMCL/src/main/java/org/jackhuang/hmcl/util/Log4jHandler.java delete mode 100755 HMCL/src/main/java/org/jackhuang/hmcl/util/MinecraftCrashAdvicer.java delete mode 100755 HMCL/src/main/java/org/jackhuang/hmcl/util/upgrade/AppDataUpgrader.java delete mode 100755 HMCL/src/main/java/org/jackhuang/hmcl/util/upgrade/IUpgrader.java delete mode 100755 HMCL/src/main/java/org/jackhuang/hmcl/util/upgrade/NewFileUpgrader.java delete mode 100644 HMCL/src/main/resources/org/jackhuang/hmcl/background.jpg delete mode 100755 HMCL/src/main/resources/org/jackhuang/hmcl/close.png delete mode 100644 HMCL/src/main/resources/org/jackhuang/hmcl/icon-new.png delete mode 100755 HMCL/src/main/resources/org/jackhuang/hmcl/icon.png delete mode 100644 HMCL/src/main/resources/org/jackhuang/hmcl/log4j.xml delete mode 100755 HMCL/src/main/resources/org/jackhuang/hmcl/minimize.png delete mode 100644 HMCLAPI/build.gradle delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/HMCLApi.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/HMCLog.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/ILogger.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/IPlugin.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/IProcess.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/PluginManager.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/VersionNumber.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/Wrapper.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/auth/AuthenticationException.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/auth/IAuthenticator.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/auth/LoginInfo.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/auth/UserProfileProvider.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/EventBus.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/EventHandler.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/OutOfDateEvent.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/PropertyChangedEvent.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/ResultedEvent.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/ResultedSimpleEvent.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/SimpleEvent.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/config/AuthenticatorChangedEvent.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/config/DownloadTypeChangedEvent.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/config/ThemeChangedEvent.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/launch/LaunchEvent.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/launch/LaunchSucceededEvent.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/launch/LaunchingState.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/launch/LaunchingStateChangedEvent.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/launch/ProcessingLaunchOptionsEvent.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/launch/ProcessingLoginResultEvent.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/process/JVMLaunchFailedEvent.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/process/JavaProcessExitedAbnormallyEvent.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/process/JavaProcessStartingEvent.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/process/JavaProcessStoppedEvent.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/version/LoadedOneVersionEvent.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/version/RefreshedVersionsEvent.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/version/RefreshingVersionsEvent.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/func/BiFunction.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/func/CallbackIO.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/func/Consumer.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/func/Function.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/func/NonFunction.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/func/Predicate.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/game/DecompressLibraryJob.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/game/Extract.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/game/GameDirType.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/game/IMinecraftLibrary.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/game/LaunchOptions.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/ui/AddTabCallback.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/ui/Theme.java delete mode 100644 HMCLAPI/src/main/java/org/jackhuang/hmcl/api/ui/TopTabPage.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/GameException.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/MCUtils.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/RuntimeGameException.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/asset/AssetsIndex.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/asset/AssetsMojangLoader.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/asset/AssetsObject.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/asset/IAssetsHandler.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/asset/MinecraftAssetService.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/AbstractAuthenticator.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/OfflineAuthenticator.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/YggdrasilAuthenticator.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/AuthenticationRequest.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/GameProfile.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/Property.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/PropertyMap.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/RefreshRequest.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/Response.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/UUIDTypeAdapter.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/User.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/UserType.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/ValidateRequest.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/YggdrasilAuthentication.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/BMCLAPIDownloadProvider.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/CurseDownloadProvider.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/DownloadLibraryJob.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/DownloadType.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/IDownloadProvider.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/MinecraftDownloadService.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/MinecraftRemoteLatestVersion.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/MinecraftRemoteVersion.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/MinecraftRemoteVersions.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/MojangDownloadProvider.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/InstallProfile.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/InstallerType.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/InstallerVersionList.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/InstallerVersionNewerComparator.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/MinecraftInstallerService.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/forge/ForgeInstaller.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/forge/Install.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/forge/MinecraftForgeVersion.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/forge/MinecraftForgeVersionList.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/forge/MinecraftForgeVersionRoot.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderBranch.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderInstaller.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderInstallerVersion.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderMCVersions.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderRepo.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderVersion.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderVersionList.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderVersionsMeta.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderVersionsRoot.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/optifine/OptiFineInstaller.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/optifine/OptiFineVersion.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/optifine/bmcl/OptiFineBMCLVersionList.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/optifine/vanilla/OptiFineDownloadFormatter.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/optifine/vanilla/OptiFineVersionList.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/launch/AbstractMinecraftLoader.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/launch/DefaultGameLauncher.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/launch/GameLauncher.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/launch/IAssetProvider.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/launch/LibraryDownloadTask.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/launch/MinecraftLoader.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/mod/MinecraftModService.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/mod/ModAdviser.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/mod/ModInfo.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/mod/ModpackManager.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IMinecraftAssetService.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IMinecraftBasicService.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IMinecraftDownloadService.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IMinecraftInstallerService.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IMinecraftLoader.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IMinecraftModService.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IMinecraftProvider.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IMinecraftService.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IProfile.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/AbstractMinecraftLibrary.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/AssetIndexDownloadInfo.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/GameDownloadInfo.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/LibrariesDownloadInfo.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/LibraryDownloadInfo.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/LoggingInfo.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/MinecraftClassicVersion.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/MinecraftLibrary.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/MinecraftOldLibrary.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/MinecraftVersion.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/MinecraftVersionManager.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/Natives.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/OSRestriction.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/Rules.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/AbstractSwingWorker.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ArrayUtils.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/C.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/CollectionUtils.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/DoubleOutputStream.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/IUpdateChecker.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/MathUtils.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/MinecraftVersionRequest.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/Pair.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/StrUtils.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/UpdateChecker.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/Utils.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/code/Charsets.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/code/DigestUtils.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/code/Hex.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/lang/Localization.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/lang/SupportedLocales.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/AppenderControl.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/Configuration.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/Level.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/LogEvent.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/LoggingException.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/appender/AbstractAppender.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/appender/ConsoleAppender.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/appender/IAppender.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/appender/OutputStreamAppender.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/layout/AbstractStringLayout.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/layout/DefaultLayout.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/layout/ILayout.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/logger/AbstractLogger.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/logger/ILogger.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/logger/Logger.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/message/AbstractMessageFactory.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/message/IMessage.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/message/IMessageFactory.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/message/ObjectMessage.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/message/ParameterizedMessage.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/message/ParameterizedMessageFactory.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/message/SimpleMessage.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/message/StringFormattedMessage.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/net/FileDownloadTask.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/net/HTTPGetTask.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/net/NetUtils.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/net/WebFrame.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/net/WebPage.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/CompressingUtils.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/FileUtils.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/IOUtils.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/Java.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/JavaProcess.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/JdkVersion.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/OS.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/Platform.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/PrintlnEvent.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/ProcessMonitor.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/ProcessThread.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/ReflectionHelper.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/WaitForThread.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/ZipEngine.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/DeleteFileTask.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/DoingDoneListener.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/DoubleTask.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/NoShownTaskException.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/ParallelTask.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/ProgressProviderListener.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/Task.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/TaskInfo.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/TaskList.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/TaskRunnable.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/TaskWindow.form delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/TaskWindow.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/TaskWorker.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/comm/PreviousResult.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/comm/PreviousResultRegistrar.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/AbstractFilter.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/BasicColors.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/DropShadowBorder.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/FastBlurFilter.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/GaussionPanel.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/GraphicsUtils.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/IRepaint.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/JFontComboBox.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/JSystemFileChooser.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/MessageBox.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/MyRepaintManager.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/Page.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/StackBlurFilter.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/SwingUtils.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/TintablePanel.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/WideComboBox.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/checktree/CheckBoxTreeCellRenderer.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/checktree/CheckBoxTreeLabel.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/checktree/CheckBoxTreeNode.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/checktree/CheckBoxTreeNodeSelectionListener.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/api/WizardDisplayer.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/api/WizardResultReceiver.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/api/displayer/InstructionsPanel.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/api/displayer/NavButtonManager.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/api/displayer/NavProgress.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/api/displayer/WizardDisplayerImpl.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/modules/InstructionsPanelImpl.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/modules/MergeMap.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/AbstractWizard.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/BranchingWizard.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/DeferredWizardResult.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/GenericListener.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/ResultProgressHandle.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/SimpleWizard.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/SimpleWizardInfo.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/Summary.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/Util.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/Wizard.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardBranchController.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardController.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardControllerImplementation.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardException.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardImplementation.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardObserver.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardPage.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardPanel.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardPanelNavResult.java delete mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardPanelProvider.java delete mode 100644 HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N.lang delete mode 100644 HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N.properties delete mode 100644 HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_ru.lang delete mode 100644 HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_ru.properties delete mode 100644 HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_vi.lang delete mode 100644 HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_vi.properties delete mode 100644 HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_zh.lang delete mode 100644 HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_zh.properties delete mode 100644 HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_zh_CN.lang delete mode 100644 HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_zh_CN.properties delete mode 100644 HMCLCore/src/main/resources/org/jackhuang/hmcl/wizard.jpg delete mode 100755 HMCLaF/build.gradle delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/BeautyEyeLNFHelper.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/BeautyEyeLookAndFeel.java delete mode 100755 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/LAFTheme.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/button/BEButtonUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/button/BEToggleButtonUI.java delete mode 100755 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/button/CustomButton.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/button/CustomButtonUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/button/__UI__.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/combox/BEComboBoxRenderer.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/combox/BEComboBoxUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/combox/__UI__.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/filechooser/BEFileChooserUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/filechooser/__UI__.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/internalframe/BEDesktopIconUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/internalframe/BEInternalFrameTitlePane.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/internalframe/BEInternalFrameUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/internalframe/__UI__.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/list/BEListUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/list/MyDefaultListCellRenderer.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/list/__UI__.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/menu/BECheckBoxMenuItemUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/menu/BEMenuBarUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/menu/BEMenuItemUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/menu/BEMenuUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/menu/BEPopupMenuSeparatorUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/menu/BEPopupMenuUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/menu/BERadioButtonMenuItemUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/menu/__UI__.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/popup/TranslucentPopupFactory.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/popup/__UI__.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/progress/BEProgressBarUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/progress/__UI__.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/radio$cb_btn/BECheckBoxUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/radio$cb_btn/BERadioButtonUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/radio$cb_btn/__UI__.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/resources/beautyeye.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/resources/beautyeye_zh_CN.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/scroll/BEScrollBarUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/scroll/BEScrollPaneUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/scroll/ScrollPaneBorder.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/scroll/__UI__.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/separator/BEPanelUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/separator/BESeparatorUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/separator/__UI__.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/slider/BESliderUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/slider/__UI__.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/spinner/BESpinnerUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/spinner/__UI__.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/split/BESplitPaneDivider.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/split/BESplitPaneUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/split/SplitPaneDividerBorder.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/split/__UI__.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/tab/BETabbedPaneUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/tab/__UI__.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/table/BETableHeaderUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/table/BETableUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/table/FocusCellHighlightBorder.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/table/TableScrollBorder.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/table/__UI__.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/textcoms/BEEditorPaneUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/textcoms/BEFormattedTextFieldUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/textcoms/BEPasswordFieldUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/textcoms/BETextAreaUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/textcoms/BETextFieldUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/textcoms/BETextPaneUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/textcoms/FocusListenerImpl.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/textcoms/__UI__.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/titlepane/BERootPaneUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/titlepane/BETitlePane.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/titlepane/__UI__.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/toolbar/BEToolBarSeparatorUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/toolbar/BEToolBarUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/toolbar/__UI__.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/tree/BETreeUI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/tree/__UI__.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/AnimationController.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/BEUtils.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/Icon9Factory.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/IconFactory.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/LogHelper.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/MySwingUtilities2.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/NinePatchHelper.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/RawCache.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/Skin.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/TMSchema.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/UI.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/WinUtils.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/WindowTranslucencyHelper.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/ImageBgPanel.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/N9ComponentFactory.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/border/BEDashedBorder.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/border/BEDashedRoundRecBorder.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/border/BERoundBorder.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/border/BEShadowBorder.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/border/BEShadowBorder3.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/border/NinePatchBorder.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/border/PlainGrayBorder.java delete mode 100644 HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/border/package.html delete mode 100644 HMCLaF/src/main/java/org/jb2011/ninepatch4j/GraphicsUtilities.java delete mode 100644 HMCLaF/src/main/java/org/jb2011/ninepatch4j/NinePatch.java delete mode 100644 HMCLaF/src/main/java/org/jb2011/ninepatch4j/NinePatchChunk.java delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/RadioButtonMenuItemCheckIcon2.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/RadioButtonMenuItemCheckIcon2_1.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/RadioButtonMenuItemCheckIcon_none.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/RadioButtonMenuItemCheckIcon_none_1.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/a.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/asc2.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/b.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/checkbox_menuitem_none.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/checkbox_menuitem_none_1.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/checkbox_menuitem_selected_normal.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/checkbox_menuitem_selected_normal_1.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/checkbox_off.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/checkbox_off_disabled.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/checkbox_off_over.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/checkbox_off_pressed.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/checkbox_on.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/checkbox_on_disabled.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/checkbox_on_over.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/checkbox_on_pressed.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/default_frame_icon.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/desc2.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/error.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/frame_close_normal.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/frame_close_over.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/frame_close_pressed.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/frame_close_rover.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/frame_max_normal.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/frame_max_pressed.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/frame_max_rover.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/frame_maximize_over.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/frame_maxwin.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/frame_maxwin_pressed.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/frame_maxwin_rover.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/frame_min_normal.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/frame_min_pressed.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/frame_min_rover.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/frame_minimize_over.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/frame_setup_normal.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/frame_windowize_over.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/head_bg.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/head_inactive.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/ifi1.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/info.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/leaf1.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/arrow.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/arrow_pressed.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/arrow_rover.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/btn_general_default.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/btn_general_pressed.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/btn_general_rover.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/btn_special_default.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/btn_special_disabled.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/combo_disabled.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/combo_normal.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/combo_over.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/combo_pressed.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/frame_shadow_border4.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/hint_bg_lightblue.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/hint_bg_lightblue_gray.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/list_cell_selected_bg2.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/menu_bg.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/orange_baloon1.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/plain_gray1.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/progress_bar_bg.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/progress_bar_bg_v.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/progress_bar_grean_v.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/progress_bar_green.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/query_item_bg_2.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/scroll_pane_bg1.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/shadow1.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/shadow2.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/shadow_bg_popup.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/shadow_bg_tooltip2.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/slider_track2.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/slider_track2_dark.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/slider_track2_forgroud.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/slider_track2_forgroud_disable.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/slider_track2_forgroud_v.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/slider_track2_forgroud_v_disable.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/slider_track2_v.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/slider_track2_v_dark.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/spinner1_bg.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/spinner1_btn_down_bg.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/spinner1_btn_down_pressed_bg.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/spinner1_btn_up_bg.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/spinner1_btn_up_pressed_bg.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/spinner1_disable_bg.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/split_touch_bg1.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/table_header_bg1.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/table_header_separator1.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/table_scrollborder1.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/tips_bg.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/toggle_button_rover.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/toggle_button_selected.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/toolbar_bg1.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/toolbar_bg1_EAST.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/toolbar_bg1_SOUTH.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/toolbar_bg1_WEST.9.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/question.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/radio_btn.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/radio_btn_disabled_normal.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/radio_btn_disabled_selected.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/radio_btn_over.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/radio_btn_pressed.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/radio_btn_selected.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/radio_btn_selected_over.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/radio_btn_selected_pressed.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/slider_tick1.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/slider_tick1_dark.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/slider_tick1_notrangle.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/slider_tick1_notrangle_dark.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/slider_tick1_notrangle_v.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/slider_tick1_notrangle_v_dark.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/slider_tick1_v.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/slider_tick1_v_dark.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/treeDefaultClosed1.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/treeDefaultOpen1.png delete mode 100644 HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/warn.png delete mode 100755 LICENSE delete mode 100755 README.md delete mode 100755 common.gradle delete mode 100755 license-header.txt diff --git a/.nb-gradle-properties b/.nb-gradle-properties deleted file mode 100755 index aa17ec6af..000000000 --- a/.nb-gradle-properties +++ /dev/null @@ -1,36 +0,0 @@ - - - - j2se - 1.8 - 1.8 - - - launch4j - no - - launch4j - - - - - - createApp - no - - createApp - - - - - - - j2se - 1.8 - - - GNU General Public License - - huangyuhui - - diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 8b9ae134a..000000000 --- a/.travis.yml +++ /dev/null @@ -1,14 +0,0 @@ -language: java -jdk: -- oraclejdk8 -branches: - only: - - master -before_install: -- chmod +x gradlew -script: "bash ./gradlew clean build --stacktrace" -before_cache: -- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock -cache: - directories: - - "$HOME/.gradle/caches/" \ No newline at end of file diff --git a/HMCL/HMCL.keystore b/HMCL/HMCL.keystore deleted file mode 100644 index ea91d8309b26af5720b3b9e7d72da1d231a9a66d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2284 zcmd5-=Tp-O6HcQ;r~*oF0s-+CzyOK@(xoWvC?XOkq+`6 zh>05MO^S3xiY20ffB~hv=-kcR%=-_#ANIqu&+g97vpc){Yx`>;5D0Q;;9myAUc&?& z0=FQ0cMJ%`1_H>iT>#F`t;P<9fe{cvFqjPlBf~xr+HO=P*%E@dE?w3Nx^y6C93dAl zB}%O3rCR~lyH%%n_BbuW6_(P0;3oZ2MowATc@t`sHQsL1va90vR|~>UaZftAF3Sgx zH=a2sD&Ag*{D|t$7HM-HD^B4WMsT>2?pM8YyTwsO>fSlMU0466%c8(~z0m^mCa7Xo zdEJJ+^EZ*<@G=K+(};-Rf$3%RYOM{Ms3tok5Qfw0EjBKRAhWhx zLPI-JTLG_E zd1dqNM5H}8F_cs0I#yeSTKV9QNiW2H3M35pJ1=J`7c~`-7afij8pRF3x?ec#O2z!{ zEoLVhwfH@acJWd#=GFF)f3%KP7@vmxi$cq}E$SA(@1SAq36phG8Fa<*N6|V+Fb~BpJB)@=~ zTelec{C%3?XG3lTr^)g137yAcn5m~$;p;26bDCdv5H8LymxYs(pinLJ9F)Z~sNzcaS8*Ykq2>zM5up9BR0lm?!=CBuVH zD&q~@<5?bMOW$qez*D*=w_Xm~>)H45a2ijJ{CIkh7ANW}2Z)Ax3@lO1N+RjfSEc9O z>UO4LBS#c2Fj+y1O0^n!brGJ!)BUYOwXoW@p2B+sU)Wjo$IZNG;U-6c0EueJzMK}a z+8lC!MCNh<@kD!|w2q4**9E+n&+9jorBP>jgBn8wwL`4gj#~M-L4dIl+fwOF9%6G= zgUi>lyHcuQDv^jX+&Y+~&~tgl$!aElPI8d#z0%BCGV9h$$4OhefKtWH_jZN?63wP_ zJT-{gJBE8n=54)oUl7o!QToHx`J$sv&2&WLsD$ly49}e6n-1DhqOp?gQ6KkcXHzbx z*|R+K7lWZ2U)k#_68&p}bssG6`Z0G)rSQ9xeHd~!D``>5ompwLb<+MWuWHw7>uQht zVl7VhVpr0Ukm+~uR!WrO;{&^|Hm^=FPw9d13T*~pRtVBLpuW!lFp9j}`i#1#@ z?as`@m&S9VqG_CZ9SUB#4itFgE7i!E-QkwH!87B+927Rxv;j|E;J$OLxKe;l>KbFz z*HJvWaP8$a`CcTmT%4EY)0_N|H$%I>RFYyXTGD73svNi}635g}BEEl3D}SqFUTrWl z9C$1I{Y^(_vEWU{C!^UIsn==zV2Vi;Kd}TfG{a2Z+^UcBx~cg`dflARx9Pk_ndH8Z zcdjm};ufUd^Ms5)?B}E?&&~rSw)0)Cb1k&6Jvymh-drGbqs~|Vn&fFK zK|2e9fa)1mVbvR%tI7}2KvMtlHzIY|n&VEI>R$41Y^3j-h)4xSL+`mH+!Js&a zz_5K|5j*_OG+{NYvcI%Hg6L+S5)k*zn!ezS$)%I5QKeq+nLA&sAyy+KDkGAivjZ(H zCvKZBQ(DYfp-yVN?E)(g)P>XW7xpux8^+KHBBRm9i$#{LR%4_0y=}tdhr^8`>(w(t zEq88?%iXYJY?FsqPfDPW>s99^_Y`^%v=lth+yRsJ+e>7cWG_#CE%ZzzqJtFkcXD%9 zYWb?yXXxV1@~sXvGQ Qiu9DKtSpsjVq#1AFIyA)5C8xG diff --git a/HMCL/HMCLauncher.exe b/HMCL/HMCLauncher.exe deleted file mode 100755 index bfe3e45c372a77df5776155b7fd27da1795f4085..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40960 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 RLOU7_GyDu|;Q#L$_+LuntoQ%` diff --git a/HMCL/build.gradle b/HMCL/build.gradle index 6df667323..0246ca2c7 100755 --- a/HMCL/build.gradle +++ b/HMCL/build.gradle @@ -1,197 +1,4 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -import java.util.jar.JarFile -import java.util.jar.Pack200 -import java.util.zip.GZIPOutputStream -import java.security.MessageDigest -import java.util.jar.JarOutputStream -import java.util.zip.ZipEntry -import java.util.zip.ZipFile - -plugins { - id "edu.sc.seis.macAppBundle" version "2.1.6" - id "me.tatarka.retrolambda" version "3.5.0" - id 'edu.sc.seis.launch4j' version '2.3.0' - //id "org.jetbrains.kotlin.jvm" version "1.1.2-2" -} - -if (!hasProperty('mainClass')) { - ext.mainClass = 'org.jackhuang.hmcl.Main' -} - -def buildnumber = System.getenv("TRAVIS_BUILD_NUMBER") -if (buildnumber == null) -buildnumber = System.getenv("BUILD_NUMBER") -if (buildnumber == null) -buildnumber = "33" - -def versionroot = System.getenv("VERSION_ROOT") -if (versionroot == null) -versionroot = "2.7.8" - -String mavenGroupId = 'HMCL' -String mavenVersion = versionroot + '.' + buildnumber -String bundleName = "Hello Minecraft! Launcher" - -group = mavenGroupId -version = mavenVersion - -String mavenArtifactId = name - -task generateSources(type: Sync) { - from 'src/main/java' - into "$buildDir/generated-src" - filter(org.apache.tools.ant.filters.ReplaceTokens, tokens: [ - 'HELLO_MINECRAFT_LAUNCHER_VERSION_FOR_GRADLE_REPLACING': mavenVersion - ]) -} -compileJava.setSource "$buildDir/generated-src" -compileJava.dependsOn generateSources - -configurations { - coreCompile.extendsFrom compile - coreRuntime.extendsFrom runtime -} - -configure(install.repositories.mavenInstaller) { - pom.project { - groupId = mavenGroupId - artifactId = mavenArtifactId - version = mavenVersion - } -} - dependencies { - compile project(":HMCLaF") - compile project(":HMCLAPI") compile project(":HMCLCore") -} - -retrolambda { - javaVersion = JavaVersion.VERSION_1_7 -} - -jar { - from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } } - - manifest { - attributes 'Created-By' : 'Copyright(c) 2013-2017 huangyuhui.', - 'Main-Class' : mainClass - } - - doLast { - new File("build/signed").mkdirs() - ant.signjar(signedjar: archivePath, jar: archivePath, - keystore: "HMCL.keystore", storepass: "123456", - alias: "HMCL") - - def messageDigest = MessageDigest.getInstance("SHA1") - archivePath.eachByte 1024 * 1024, { byte[] buf, int bytesRead -> - messageDigest.update(buf, 0, bytesRead); - } - def sha1Hex = new BigInteger(1, messageDigest.digest()).toString(16).padLeft(40, '0') - def fileEx = new File(project.buildDir, "libs/" + archivePath.getName() + ".sha1") - if (!fileEx.exists()) fileEx.createNewFile() - fileEx.append sha1Hex - } -} - -launch4j { - supportUrl = 'http://www.mcbbs.net/thread-142335-1-1.html' - jreMinVersion = '1.7.0' - - mainClassName = mainClass - icon = new File(project.buildDir, '../icon.ico').absolutePath - version = mavenVersion - downloadUrl = 'http://java.com/download' - copyright = "Copyright(c) 2013-2017 huangyuhui." - - jar = new File(project.buildDir, 'libs/' + mavenGroupId + '-' + mavenVersion + '.jar').absolutePath - outfile = mavenGroupId + '-' + mavenVersion + '.exe' - messagesJreVersionError = 'This application requires a Java Runtime Environment installation, or the runtime is corrupted.\n\u6ca1\u6709\u627e\u5230\u004a\u0061\u0076\u0061\u8fd0\u884c\u65f6\uff0c\u8bf7\u4e0d\u8981\u4f7f\u7528\u7eff\u8272\u004a\u0061\u0076\u0061\uff0c\u8bf7\u4f7f\u7528\u5b89\u88c5\u7248\u7684\u004a\u0061\u0076\u0061\uff0c\u70b9\u51fb\u786e\u5b9a\u8fdb\u5165\u004a\u0061\u0076\u0061\u5b89\u88c5\u9875\u9762\u3002' -} - -processResources { - from(sourceSets.main.resources.srcDirs) { - exclude 'icon.icns' - } -} - -task makeExecutable(dependsOn: jar) doLast { - ext { - jar.classifier = '' - makeExecutableinjar = jar.archivePath - jar.classifier = '' - makeExecutableoutjar = jar.archivePath - jar.classifier = '' - } - def loc = new File(project.buildDir, "libs/" + makeExecutableoutjar.getName().substring(0, makeExecutableoutjar.getName().length()-4)+".exe") - def fos = new FileOutputStream(loc) - def is = new FileInputStream(new File(project.buildDir, '../HMCLauncher.exe')) - int read - def bytes = new byte[8192] - while((read = is.read(bytes)) != -1) - fos.write(bytes, 0, read); - is.close() - is = new FileInputStream(makeExecutableinjar) - while((read = is.read(bytes)) != -1) - fos.write(bytes, 0, read); - is.close() - fos.close() - -} - -task makePackGZ(dependsOn: jar) doLast { - ext { - jar.classifier = '' - makeExecutableinjar = jar.archivePath - jar.classifier = '' - makeExecutableoutjar = jar.archivePath - jar.classifier = '' - } - def loc = new File(project.buildDir, "libs/" + makeExecutableoutjar.getName().substring(0, makeExecutableoutjar.getName().length()-4)+".pack.gz") - def os = new GZIPOutputStream(new FileOutputStream(loc)) - Pack200.newPacker().pack new JarFile(makeExecutableinjar), os - os.close() - - def messageDigest = MessageDigest.getInstance("SHA1") - loc.eachByte 1024 * 1024, { byte[] buf, int bytesRead -> - messageDigest.update(buf, 0, bytesRead); - } - def sha1Hex = new BigInteger(1, messageDigest.digest()).toString(16).padLeft(40, '0') - def fileEx = new File(project.buildDir, "libs/" + makeExecutableoutjar.getName().substring(0, makeExecutableoutjar.getName().length()-4)+".pack.gz.sha1") - if (!fileEx.exists()) fileEx.createNewFile() - fileEx.append sha1Hex -} - -task macAppCompressed(type: Zip, dependsOn: createApp) doLast { - archiveName "HMCL-$mavenVersion-MacOSApp.zip" - include '**' - destinationDir file("$buildDir/libs/") - from "$buildDir/macApp" -} - -macAppBundle { - mainClassName = mainClass - icon = "src/main/icon.icns" - javaProperties.put("apple.laf.useScreenMenuBar", "true") -} - -build.dependsOn makeExecutable -build.dependsOn makePackGZ -build.dependsOn macAppCompressed \ No newline at end of file + compile rootProject.files("lib/JFoenix.jar") +} \ No newline at end of file diff --git a/HMCL/icon.ico b/HMCL/icon.ico deleted file mode 100755 index fe7ac703b65263266b6fe864bc89bae4c49bb646..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4286 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�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
MZJ~#!I_ys4`PaAliz) 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 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.Authenticator; -import java.net.PasswordAuthentication; -import java.security.GeneralSecurityException; -import java.security.cert.X509Certificate; -import java.util.Locale; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLContext; -import javax.net.ssl.X509TrustManager; -import javax.swing.ImageIcon; -import javax.swing.JOptionPane; -import javax.swing.RepaintManager; -import org.jackhuang.hmcl.api.HMCLApi; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.api.ILogger; -import org.jackhuang.hmcl.api.PluginManager; -import org.jackhuang.hmcl.api.VersionNumber; -import org.jackhuang.hmcl.core.MCUtils; -import org.jackhuang.hmcl.setting.Settings; -import org.jackhuang.hmcl.ui.LogWindow; -import org.jackhuang.hmcl.ui.MainFrame; -import org.jackhuang.hmcl.util.CrashReporter; -import org.jackhuang.hmcl.util.DefaultPlugin; -import org.jackhuang.hmcl.util.MathUtils; -import org.jackhuang.hmcl.util.ui.MessageBox; -import org.jackhuang.hmcl.util.StrUtils; -import org.jackhuang.hmcl.util.lang.SupportedLocales; -import org.jackhuang.hmcl.util.log.Configuration; -import org.jackhuang.hmcl.util.log.appender.ConsoleAppender; -import org.jackhuang.hmcl.util.log.layout.DefaultLayout; -import org.jackhuang.hmcl.util.ui.MyRepaintManager; -import org.jackhuang.hmcl.util.upgrade.IUpgrader; -import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper; - -/** - * - * @author huangyuhui - */ -public final class Main { - - private static final X509TrustManager XTM = new X509TrustManager() { - @Override - public void checkClientTrusted(X509Certificate[] chain, String authType) { - } - - @Override - public void checkServerTrusted(X509Certificate[] chain, String authType) { - } - - @Override - public X509Certificate[] getAcceptedIssuers() { - return new X509Certificate[0]; - } - }; - private static final HostnameVerifier HNV = (hostname, session) -> true; - - public static final String LAUNCHER_NAME = "Hello Minecraft! Launcher"; - public static final String LAUNCHER_VERSION = "@HELLO_MINECRAFT_LAUNCHER_VERSION_FOR_GRADLE_REPLACING@"; - public static final int MINIMUM_LAUNCHER_VERSION = 16; - - /** - * Make the main window title. - * - * @return the MainWindow title. - */ - public static String makeTitle() { - return LAUNCHER_NAME + ' ' + LAUNCHER_VERSION; - } - - public static String shortTitle() { - return "HMCL" + ' ' + LAUNCHER_VERSION; - } - - public static final Logger LOGGER = Logger.getLogger(Main.class.getName()); - - public static void main(String[] args) throws IOException { - { - try { - File file = new File("hmcl.log").getAbsoluteFile(); - if (!file.exists() && !file.createNewFile()) - LOGGER.log(Level.WARNING, "Failed to create log file {0}", file); - Configuration.DEFAULT.appenders.add(new ConsoleAppender("File", new DefaultLayout(), true, new FileOutputStream(file), true)); - } catch (IOException ex) { - LOGGER.log(Level.SEVERE, "Failed to add log appender File because an error occurred while creating or opening hmcl.log", ex); - } - - org.jackhuang.hmcl.util.log.logger.Logger logger = new org.jackhuang.hmcl.util.log.logger.Logger("HMCL"); - HMCLog.LOGGER = new ILogger() { - @Override - public void log(String msg) { - logger.info(msg); - } - - @Override - public void warn(String msg) { - logger.warn(msg); - } - - @Override - public void warn(String msg, Throwable t) { - logger.warn(msg, t); - } - - @Override - public void err(String msg) { - logger.error(msg); - } - - @Override - public void err(String msg, Throwable t) { - logger.error(msg, t); - } - }; - - HMCLApi.HMCL_VERSION = VersionNumber.check(LAUNCHER_VERSION); - - PluginManager.getPlugin(DefaultPlugin.class); - for (String s : args) - if (s.startsWith("--plugin=")) { - String c = s.substring("--plugin=".length()); - try { - PluginManager.getPlugin(Class.forName(c)); - } catch (ClassNotFoundException ex) { - HMCLog.warn("Class: " + c + " not found, please add your plugin jar to class path.", ex); - } - } else if (s.startsWith("--help")) { - System.out.println("HMCL command line help"); - System.out.println("--noupdate: this arg will prevent HMCL from initializing the newest app version in %appdata%/.hmcl"); - System.out.println("--plugin=: this arg will allow a new plugin to be loaded, please keep your jar in system class path and this class extends IPlugin."); - return; - } - PluginManager.loadPlugins(); - - IUpgrader.NOW_UPGRADER.parseArguments(HMCLApi.HMCL_VERSION, args); - - System.setProperty("awt.useSystemAAFontSettings", "on"); - System.setProperty("swing.aatext", "true"); - System.setProperty("sun.java2d.noddraw", "true"); - System.setProperty("sun.java2d.dpiaware", "false"); - System.setProperty("https.protocols", "SSLv3,TLSv1"); - - try { - SSLContext c = SSLContext.getInstance("SSL"); - c.init(null, new X509TrustManager[] { XTM }, new java.security.SecureRandom()); - HttpsURLConnection.setDefaultSSLSocketFactory(c.getSocketFactory()); - } catch (GeneralSecurityException ignore) { - } - HttpsURLConnection.setDefaultHostnameVerifier(HNV); - - Thread.setDefaultUncaughtExceptionHandler(new CrashReporter(true)); - - HMCLog.log("*** " + Main.makeTitle() + " ***"); - - String s = Settings.getInstance().getLocalization(); - for (SupportedLocales sl : SupportedLocales.values()) - if (sl.name().equals(s)) { - SupportedLocales.setNowLocale(sl); - Locale.setDefault(sl.self); - JOptionPane.setDefaultLocale(sl.self); - } - - if (System.getProperty("java.vm.name").contains("Open")) // OpenJDK - MessageBox.showLocalized("ui.message.open_jdk"); - - try { - BeautyEyeLNFHelper.launchBeautyEyeLNF(); - RepaintManager.setCurrentManager(new MyRepaintManager()); - } catch (Exception ex) { - HMCLog.warn("Failed to set look and feel...", ex); - } - - LogWindow.INSTANCE.clean(); - - Settings.UPDATE_CHECKER.upgrade.register(IUpgrader.NOW_UPGRADER); - Settings.UPDATE_CHECKER.process(false).reg(t -> Main.invokeUpdate()).execute(); - - if (StrUtils.isNotBlank(Settings.getInstance().getProxyHost()) && StrUtils.isNotBlank(Settings.getInstance().getProxyPort()) && MathUtils.canParseInt(Settings.getInstance().getProxyPort())) { - HMCLog.log("Initializing customized proxy"); - System.setProperty("http.proxyHost", Settings.getInstance().getProxyHost()); - System.setProperty("http.proxyPort", Settings.getInstance().getProxyPort()); - if (StrUtils.isNotBlank(Settings.getInstance().getProxyUserName()) && StrUtils.isNotBlank(Settings.getInstance().getProxyPassword())) - Authenticator.setDefault(new Authenticator() { - @Override - protected PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(Settings.getInstance().getProxyUserName(), Settings.getInstance().getProxyPassword().toCharArray()); - } - }); - } - - try { - unpackDefaultLog4jConfiguration(); - } catch(IOException e) { - HMCLog.err("Failed to unpack log4j.xml, log window will not work well.", e); - } - - MainFrame.showMainFrame(); - } - } - - public static void invokeUpdate() { - MainFrame.INSTANCE.invokeUpdate(); - } - - public static final File LOG4J_FILE = new File(MCUtils.getWorkingDirectory("hmcl"), "log4j.xml"); - - public static void unpackDefaultLog4jConfiguration() throws IOException { - LOG4J_FILE.getParentFile().mkdirs(); - if (LOG4J_FILE.exists()) return; - LOG4J_FILE.createNewFile(); - try (InputStream is = Main.class.getResourceAsStream("/org/jackhuang/hmcl/log4j.xml"); - FileOutputStream fos = new FileOutputStream(LOG4J_FILE)) { - int b; - while ((b = is.read()) != -1) - fos.write(b); - } - } - - public static ImageIcon getIcon(String path) { - try { - return new ImageIcon(Main.class.getResource("/org/jackhuang/hmcl/" + path)); - } catch (Exception e) { - HMCLog.err("Failed to load icon", e); - return null; - } - } -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/api/event/config/ProfileChangedEvent.java b/HMCL/src/main/java/org/jackhuang/hmcl/api/event/config/ProfileChangedEvent.java deleted file mode 100644 index 25eec8ef0..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/api/event/config/ProfileChangedEvent.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.event.config; - -import org.jackhuang.hmcl.api.event.SimpleEvent; -import org.jackhuang.hmcl.setting.Profile; - -/** - * This event gets fired when the selected profile changed. - *
- * This event is fired on the {@link org.jackhuang.hmcl.api.HMCLApi#EVENT_BUS} - * @param source {@link org.jackhuang.hmcl.setting.Settings} - * @param Profile the new profile. - * @author huangyuhui - */ -public class ProfileChangedEvent extends SimpleEvent { - - public ProfileChangedEvent(Object source, Profile value) { - super(source, value); - } - -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/api/event/config/ProfileLoadingEvent.java b/HMCL/src/main/java/org/jackhuang/hmcl/api/event/config/ProfileLoadingEvent.java deleted file mode 100644 index 9754d30a2..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/api/event/config/ProfileLoadingEvent.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.event.config; - -import java.util.EventObject; - -/** - * This event gets fired when loading profiles. - *
- * This event is fired on the {@link org.jackhuang.hmcl.api.HMCLApi#EVENT_BUS} - * @param source {@link org.jackhuang.hmcl.setting.Settings} - * @author huangyuhui - */ -public class ProfileLoadingEvent extends EventObject { - - public ProfileLoadingEvent(Object source) { - super(source); - } - -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java deleted file mode 100755 index e63f1de67..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java +++ /dev/null @@ -1,342 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.setting; - -import org.jackhuang.hmcl.core.download.DownloadType; -import com.google.gson.annotations.SerializedName; -import java.awt.Font; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; -import java.util.UUID; -import org.jackhuang.hmcl.core.auth.AbstractAuthenticator; -import org.jackhuang.hmcl.laf.LAFTheme; -import org.jackhuang.hmcl.api.HMCLApi; -import org.jackhuang.hmcl.api.event.config.AuthenticatorChangedEvent; -import org.jackhuang.hmcl.api.event.config.DownloadTypeChangedEvent; -import org.jackhuang.hmcl.api.event.config.ThemeChangedEvent; -import org.jackhuang.hmcl.core.MCUtils; -import org.jackhuang.hmcl.util.sys.JdkVersion; -import org.jackhuang.hmcl.util.sys.OS; -import org.jackhuang.hmcl.api.auth.IAuthenticator; -import org.jackhuang.hmcl.api.ui.Theme; - -/** - * - * @author huangyuhui - */ -public final class Config implements Cloneable { - - @SerializedName("last") - private String last; - @SerializedName("bgpath") - private String bgpath; - @SerializedName("commonpath") - private String commonpath; - @SerializedName("clientToken") - private final String clientToken; - @SerializedName("proxyHost") - private String proxyHost; - @SerializedName("proxyPort") - private String proxyPort; - @SerializedName("proxyUserName") - private String proxyUserName; - @SerializedName("proxyPassword") - private String proxyPassword; - @SerializedName("enableShadow") - private boolean enableShadow; - @SerializedName("enableBlur") - private boolean enableBlur; - @SerializedName("enableAnimation") - private boolean enableAnimation; - @SerializedName("decorated") - private boolean decorated; - @SerializedName("theme") - private String theme; - @SerializedName("java") - private List java; - @SerializedName("localization") - private String localization; - @SerializedName("logintype") - private int logintype; - @SerializedName("downloadtype") - private int downloadtype; - @SerializedName("configurations") - private TreeMap configurations; - @SerializedName("auth") - private Map auth; - @SerializedName("fontFamily") - private String fontFamily; - @SerializedName("fontSize") - private int fontSize; - @SerializedName("logLines") - private int logLines; - - public Config() { - clientToken = UUID.randomUUID().toString(); - logintype = downloadtype = 0; - logLines = 100; - enableAnimation = enableBlur = true; - if (OS.os() == OS.WINDOWS) - enableShadow = true; - theme = LAFTheme.BLUE.id; - decorated = OS.os() == OS.LINUX; - auth = new HashMap<>(); - Font font = Font.decode("Consolas"); - if (font == null) - font = Font.decode("Monospace"); - if (font != null) - fontFamily = font.getFamily(); - fontSize = 12; - commonpath = MCUtils.getLocation().getPath(); - } - - public List getJava() { - return java == null ? java = new ArrayList<>() : java; - } - - public Theme getTheme() { - if (!Theme.THEMES.containsKey(theme)) - theme = LAFTheme.BLUE.id; - return Theme.THEMES.get(theme); - } - - public void setTheme(String theme) { - this.theme = theme; - HMCLApi.EVENT_BUS.fireChannel(new ThemeChangedEvent(this, getTheme())); - Settings.save(); - } - - public boolean isDecorated() { - return decorated; - } - - public void setDecorated(boolean decorated) { - this.decorated = decorated; - } - - public boolean isEnableShadow() { - return enableShadow && OS.os() == OS.WINDOWS; - } - - public void setEnableShadow(boolean enableShadow) { - this.enableShadow = enableShadow; - Settings.save(); - } - - public boolean isEnableAnimation() { - return enableAnimation; - } - - public void setEnableAnimation(boolean enableAnimation) { - this.enableAnimation = enableAnimation; - Settings.save(); - } - - public boolean isEnableBlur() { - return enableBlur; - } - - public void setEnableBlur(boolean enableBlur) { - this.enableBlur = enableBlur; - Settings.save(); - } - - /** - * Last selected profile name. - */ - public String getLast() { - if (last == null) - last = Settings.DEFAULT_PROFILE; - return last; - } - - public void setLast(String last) { - this.last = last; - Settings.onProfileChanged(); - Settings.save(); - } - - public String getBgpath() { - return bgpath; - } - - public void setBgpath(String bgpath) { - this.bgpath = bgpath; - Settings.save(); - } - - public String getCommonpath() { - return commonpath; - } - - public void setCommonpath(String commonpath) { - this.commonpath = commonpath; - Settings.save(); - } - - public String getClientToken() { - return clientToken; - } - - public IAuthenticator getAuthenticator() { - return AbstractAuthenticator.LOGINS.get(getLoginType()); - } - - public int getLoginType() { - if (logintype < 0 || logintype >= AbstractAuthenticator.LOGINS.size()) - logintype = 0; - return logintype; - } - - public void setLoginType(int logintype) { - if (logintype < 0 || logintype >= AbstractAuthenticator.LOGINS.size()) - return; - this.logintype = logintype; - HMCLApi.EVENT_BUS.fireChannel(new AuthenticatorChangedEvent(this, AbstractAuthenticator.LOGINS.get(logintype))); - Settings.save(); - } - - public int getDownloadType() { - return downloadtype; - } - - public void setDownloadType(int downloadtype) { - this.downloadtype = downloadtype; - HMCLApi.EVENT_BUS.fireChannel(new DownloadTypeChangedEvent(this, getDownloadSource().name())); - Settings.save(); - } - - public TreeMap getConfigurations() { - if (configurations == null) - configurations = new TreeMap<>(); - if (configurations.isEmpty()) { - Profile profile = new Profile(); - configurations.put(profile.getName(), profile); - } - return configurations; - } - - public Map getAuthenticatorConfig(String authId) { - return auth.get(authId); - } - - public void setAuthenticatorConfig(String authId, Map map) { - auth.put(authId, map); - Settings.save(); - } - - public DownloadType getDownloadSource() { - if (downloadtype >= DownloadType.values().length || downloadtype < 0) { - downloadtype = 0; - Settings.save(); - } - return DownloadType.values()[downloadtype]; - } - - public String getProxyHost() { - return proxyHost == null ? "" : proxyHost; - } - - public void setProxyHost(String proxyHost) { - this.proxyHost = proxyHost; - Settings.save(); - } - - public String getProxyPort() { - return proxyPort == null ? "" : proxyPort; - } - - public void setProxyPort(String proxyPort) { - this.proxyPort = proxyPort; - Settings.save(); - } - - public String getProxyUserName() { - return proxyUserName == null ? "" : proxyUserName; - } - - public void setProxyUserName(String proxyUserName) { - this.proxyUserName = proxyUserName; - Settings.save(); - } - - public String getProxyPassword() { - return proxyPassword == null ? "" : proxyPassword; - } - - public void setProxyPassword(String proxyPassword) { - this.proxyPassword = proxyPassword; - Settings.save(); - } - - public int getFontSize() { - return fontSize; - } - - public void setFontSize(int fontSize) { - this.fontSize = fontSize; - Settings.save(); - } - - public Font getConsoleFont() { - return Font.decode(fontFamily + "-" + fontSize); - } - - public String getFontFamily() { - return Font.decode(fontFamily).getFamily(); - } - - public void setFontFamily(String fontFamily) { - this.fontFamily = Font.decode(fontFamily).getFamily(); // avoid invalid font family - Settings.save(); - } - - public String getLocalization() { - return localization; - } - - public void setLocalization(String localization) { - this.localization = localization; - Settings.save(); - } - - public int getLogLines() { - if (logLines == 100 || logLines == 1000 || logLines == 5000) - return logLines; - else - return logLines = 100; - } - - public void setLogLines(int logLines) { - this.logLines = logLines; - Settings.save(); - } - - @Override - public Object clone() { - try { - return super.clone(); - } catch (CloneNotSupportedException e) { - throw new Error(e); - } - } - -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Profile.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Profile.java deleted file mode 100755 index 0c50e2215..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Profile.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.setting; - -import org.jackhuang.hmcl.core.service.IProfile; -import com.google.gson.annotations.SerializedName; -import org.jackhuang.hmcl.util.HMCLGameLauncher; -import org.jackhuang.hmcl.util.HMCLMinecraftService; -import java.io.File; -import org.jackhuang.hmcl.core.MCUtils; -import org.jackhuang.hmcl.core.version.MinecraftVersion; -import org.jackhuang.hmcl.util.StrUtils; -import org.jackhuang.hmcl.api.event.EventHandler; -import org.jackhuang.hmcl.api.event.PropertyChangedEvent; - -/** - * - * @author huangyuhui - */ -public final class Profile implements IProfile { - - @SerializedName("selectedMinecraftVersion") - private String selectedVersion = ""; - @SerializedName("gameDir") - private String gameDir; - @SerializedName("noCommon") - private boolean noCommon; - @SerializedName("global") - private VersionSetting global; - - private transient String name; - private transient HMCLMinecraftService service = new HMCLMinecraftService(this); - private transient HMCLGameLauncher launcher = new HMCLGameLauncher(this); - public transient final EventHandler> propertyChanged = new EventHandler<>(); - - public Profile() { - this("Default"); - } - - public Profile(String name) { - this(name, ".minecraft"); - } - - public Profile(String name, String gameDir) { - this.name = name; - this.gameDir = gameDir; - this.global = new VersionSetting(); - } - - public Profile(String name, Profile v) { - this(); - if (v == null) - return; - this.name = name; - gameDir = v.gameDir; - } - - @Override - public HMCLMinecraftService service() { - return service; - } - - public HMCLGameLauncher launcher() { - return launcher; - } - - public VersionSetting getSelectedVersionSetting() { - return getVersionSetting(getSelectedVersion()); - } - - public VersionSetting getVersionSetting(String id) { - VersionSetting vs = service().getVersionSetting(id); - if (vs == null || vs.isUsesGlobal()) { - global.isGlobal = true; - global.id = id; - return global; - } else - return vs; - } - - public boolean isVersionSettingGlobe(String id) { - VersionSetting vs = service().getVersionSetting(id); - return vs == null || vs.isUsesGlobal(); - } - - public void makeVersionSettingSpecial(String id) { - VersionSetting vs = service().getVersionSetting(id); - if (vs == null) { - service().createVersionSetting(id); - vs = service().getVersionSetting(id); - if (vs == null) - return; - vs.setUsesGlobal(false); - } else - vs.setUsesGlobal(false); - propertyChanged.fire(new PropertyChangedEvent<>(this, "selectedVersion", selectedVersion, selectedVersion)); - } - - public void makeVersionSettingGlobal(String id) { - HMCLMinecraftService s = (HMCLMinecraftService) service(); - VersionSetting vs = s.getVersionSetting(id); - if (vs == null) - return; - vs.setUsesGlobal(true); - propertyChanged.fire(new PropertyChangedEvent<>(this, "selectedVersion", selectedVersion, selectedVersion)); - } - - @Override - public String getSelectedVersion() { - String v = selectedVersion; - if (StrUtils.isBlank(v) || service().version().getVersionById(v) == null || service().version().getVersionById(v).hidden) { - MinecraftVersion mv = service().version().getOneVersion(t -> !t.hidden); - if (mv != null) - v = mv.id; - if (StrUtils.isNotBlank(v)) - setSelectedVersion(v); - } - return StrUtils.isBlank(v) ? null : v; - } - - @Override - public void setSelectedVersion(String newVersion) { - PropertyChangedEvent event = new PropertyChangedEvent<>(this, "selectedVersion", this.selectedVersion, newVersion); - this.selectedVersion = newVersion; - propertyChanged.fire(event); - } - - @Override - public File getGameDir() { - if (StrUtils.isBlank(gameDir)) - gameDir = MCUtils.getInitGameDir().getPath(); - return new File(gameDir.replace('\\', '/')); - } - - @Override - public void setGameDir(File gameDir) { - PropertyChangedEvent event = new PropertyChangedEvent<>(this, "gameDir", this.gameDir, gameDir); - this.gameDir = gameDir.getPath(); - service().version().refreshVersions(); - propertyChanged.fire(event); - } - - public boolean isNoCommon() { - return noCommon; - } - - public void setNoCommon(boolean noCommon) { - PropertyChangedEvent event = new PropertyChangedEvent(this, "noCommon", this.noCommon, noCommon); - this.noCommon = noCommon; - propertyChanged.fire(event); - } - - @Override - public String getName() { - return name; - } - - void setName(String name) { - PropertyChangedEvent event = new PropertyChangedEvent<>(this, "name", this.name, name); - this.name = name; - propertyChanged.fire(event); - } - - @Override - public void onSelected() { - service().version().refreshVersions(); - } -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java deleted file mode 100755 index 2d0d6000c..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.setting; - -import com.google.gson.JsonSyntaxException; -import java.io.File; -import java.io.IOException; -import java.util.Collection; -import java.util.Map; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.core.MCUtils; -import org.jackhuang.hmcl.core.download.DownloadType; -import org.jackhuang.hmcl.util.CollectionUtils; -import org.jackhuang.hmcl.api.HMCLApi; -import org.jackhuang.hmcl.api.event.config.ProfileChangedEvent; -import org.jackhuang.hmcl.api.event.config.ProfileLoadingEvent; -import org.jackhuang.hmcl.laf.utils.AnimationController; -import org.jackhuang.hmcl.util.sys.FileUtils; -import org.jackhuang.hmcl.util.ui.MessageBox; -import org.jackhuang.hmcl.util.UpdateChecker; -import org.jackhuang.hmcl.util.sys.IOUtils; - -/** - * - * @author huangyuhui - */ -public final class Settings { - - public static final String DEFAULT_PROFILE = "Default"; - public static final String HOME_PROFILE = "Home"; - - public static final File SETTINGS_FILE = new File("hmcl.json").getAbsoluteFile(); - - private static final Config SETTINGS; - public static final UpdateChecker UPDATE_CHECKER = new UpdateChecker(HMCLApi.HMCL_VERSION, "hmcl"); - - public static Config getInstance() { - return SETTINGS; - } - - static { - SETTINGS = initSettings(); - DownloadType.setSuggestedDownloadType(SETTINGS.getDownloadSource().name()); - AnimationController.ENABLE_ANIMATION = SETTINGS.isEnableAnimation(); - if (!getProfiles().containsKey(DEFAULT_PROFILE)) - getProfiles().put(DEFAULT_PROFILE, new Profile(DEFAULT_PROFILE)); - - for (Map.Entry entry : getProfiles().entrySet()) { - Profile e = entry.getValue(); - e.setName(entry.getKey()); - e.propertyChanged.register(Settings::save); - } - } - - private static Config initSettings() { - Config c = new Config(); - if (SETTINGS_FILE.exists()) - try { - String str = FileUtils.read(SETTINGS_FILE, IOUtils.DEFAULT_CHARSET); - if (str == null || str.trim().equals("")) - HMCLog.log("Settings file is empty, use the default settings."); - else { - Config d = C.GSON.fromJson(str, Config.class); - if (d != null) - c = d; - } - HMCLog.log("Initialized settings."); - } catch (IOException | JsonSyntaxException e) { - HMCLog.warn("Something happened wrongly when load settings.", e); - } - else { - HMCLog.log("No settings file here, may be first loading."); - if (!c.getConfigurations().containsKey(HOME_PROFILE)) - c.getConfigurations().put(HOME_PROFILE, new Profile(HOME_PROFILE, MCUtils.getLocation().getPath())); - } - return c; - } - - public static void save() { - try { - FileUtils.write(SETTINGS_FILE, C.GSON.toJson(SETTINGS), IOUtils.DEFAULT_CHARSET); - } catch (IOException ex) { - HMCLog.err("Failed to save config", ex); - } - } - - public static Profile getLastProfile() { - if (!hasProfile(getInstance().getLast())) - getInstance().setLast(DEFAULT_PROFILE); - return getProfile(getInstance().getLast()); - } - - public static Profile getProfile(String name) { - if (name == null) - name = DEFAULT_PROFILE; - Profile p = getProfiles().get(name); - if (p == null) - if (getProfiles().containsKey(DEFAULT_PROFILE)) - p = getProfiles().get(DEFAULT_PROFILE); - else - getProfiles().put(DEFAULT_PROFILE, p = new Profile()); - return p; - } - - public static boolean hasProfile(String name) { - if (name == null) - name = DEFAULT_PROFILE; - return getProfiles().containsKey(name); - } - - public static Map getProfiles() { - return SETTINGS.getConfigurations(); - } - - public static Collection getProfilesFiltered() { - return CollectionUtils.filter(getProfiles().values(), t -> t != null && t.getName() != null); - } - - public static boolean putProfile(Profile ver) { - if (ver == null || ver.getName() == null || getProfiles().containsKey(ver.getName())) - return false; - getProfiles().put(ver.getName(), ver); - return true; - } - - public static boolean delProfile(Profile ver) { - return delProfile(ver.getName()); - } - - public static boolean delProfile(String ver) { - if (DEFAULT_PROFILE.equals(ver)) { - MessageBox.show(C.i18n("settings.cannot_remove_default_config")); - return false; - } - boolean notify = false; - if (getLastProfile().getName().equals(ver)) - notify = true; - boolean flag = getProfiles().remove(ver) != null; - if (notify && flag) - onProfileChanged(); - return flag; - } - - static void onProfileChanged() { - Profile p = getLastProfile(); - if (p == null) - throw new Error("No profiles here, it should not happen"); - HMCLApi.EVENT_BUS.fireChannel(new ProfileChangedEvent(SETTINGS, p)); - p.onSelected(); - } - - public static void onProfileLoading() { - HMCLApi.EVENT_BUS.fireChannel(new ProfileLoadingEvent(SETTINGS)); - onProfileChanged(); - } -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java deleted file mode 100644 index 8e6e668d3..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.setting; - -import com.google.gson.annotations.SerializedName; -import java.io.File; -import org.jackhuang.hmcl.Main; -import org.jackhuang.hmcl.util.LauncherVisibility; -import org.jackhuang.hmcl.api.game.LaunchOptions; -import org.jackhuang.hmcl.api.game.GameDirType; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.api.event.EventHandler; -import org.jackhuang.hmcl.api.event.PropertyChangedEvent; -import org.jackhuang.hmcl.util.StrUtils; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.util.sys.Java; -import org.jackhuang.hmcl.util.sys.OS; - -/** - * - * @author huangyuhui - */ -public class VersionSetting { - - public transient String id; - public transient boolean isGlobal = false; - - @SerializedName("usesGlobal") - private boolean usesGlobal; - @SerializedName("javaArgs") - private String javaArgs; - @SerializedName("minecraftArgs") - private String minecraftArgs; - @SerializedName("maxMemory") - private String maxMemory; - @SerializedName("permSize") - private String permSize; - @SerializedName("width") - private String width; - @SerializedName("height") - private String height; - @SerializedName("javaDir") - private String javaDir; - @SerializedName("precalledCommand") - private String precalledCommand; - @SerializedName("serverIp") - private String serverIp; - @SerializedName("java") - private String java; - @SerializedName("wrapper") - private String wrapper; - @SerializedName("fullscreen") - private boolean fullscreen; - @SerializedName("noJVMArgs") - private boolean noJVMArgs; - @SerializedName("notCheckGame") - private boolean notCheckGame; - - /** - * 0 - Close the launcher when the game starts.
- * 1 - Hide the launcher when the game starts.
- * 2 - Keep the launcher open.
- */ - @SerializedName("launcherVisibility") - private int launcherVisibility; - - /** - * 0 - .minecraft
- * 1 - .minecraft/versions/<version>/
- */ - @SerializedName("gameDirType") - private int gameDirType; - - public transient final EventHandler propertyChanged = new EventHandler<>(); - - public VersionSetting() { - fullscreen = usesGlobal = false; - launcherVisibility = 1; - gameDirType = 0; - javaDir = java = minecraftArgs = serverIp = precalledCommand = wrapper = ""; - } - - public String getJavaDir() { - Java j = getJava(); - if (j.getHome() == null) - return javaDir; - else - return j.getJava(); - } - - public String getSettingsJavaDir() { - return javaDir; - } - - public File getJavaDirFile() { - return new File(getJavaDir()); - } - - public void setJavaDir(String javaDir) { - PropertyChangedEvent event = new PropertyChangedEvent(this, "javaDir", this.javaDir, javaDir); - this.javaDir = javaDir; - propertyChanged.fire(event); - } - - public Java getJava() { - return Java.JAVA.get(getJavaIndexInAllJavas()); - } - - public int getJavaIndexInAllJavas() { - if (StrUtils.isBlank(java) && StrUtils.isNotBlank(javaDir)) - java = "Custom"; - int idx = Java.JAVA.indexOf(new Java(java, null)); - if (idx == -1) { - java = Java.suggestedJava().getName(); - idx = 0; - } - return idx; - } - - public void setJava(Java java) { - PropertyChangedEvent event = new PropertyChangedEvent(this, "java", this.java, java); - if (java == null) - this.java = Java.JAVA.get(0).getName(); - else { - int idx = Java.JAVA.indexOf(java); - if (idx == -1) - return; - this.java = java.getName(); - } - propertyChanged.fire(event); - } - - public String getJavaArgs() { - if (StrUtils.isBlank(javaArgs)) - return ""; - return javaArgs; - } - - public void setJavaArgs(String javaArgs) { - PropertyChangedEvent event = new PropertyChangedEvent(this, "javaArgs", this.javaArgs, javaArgs); - this.javaArgs = javaArgs; - propertyChanged.fire(event); - } - - public String getMaxMemory() { - if (StrUtils.isBlank(maxMemory)) - return String.valueOf(OS.getSuggestedMemorySize()); - return maxMemory; - } - - public void setMaxMemory(String maxMemory) { - PropertyChangedEvent event = new PropertyChangedEvent(this, "maxMemory", this.maxMemory, maxMemory); - this.maxMemory = maxMemory; - propertyChanged.fire(event); - } - - public String getWidth() { - if (StrUtils.isBlank(width)) - return "854"; - return width; - } - - public void setWidth(String width) { - PropertyChangedEvent event = new PropertyChangedEvent(this, "width", this.width, width); - this.width = width; - propertyChanged.fire(event); - } - - public String getHeight() { - if (StrUtils.isBlank(height)) - return "480"; - return height; - } - - public void setHeight(String height) { - PropertyChangedEvent event = new PropertyChangedEvent(this, "height", this.height, height); - this.height = height; - propertyChanged.fire(event); - } - - public boolean isFullscreen() { - return fullscreen; - } - - public void setFullscreen(boolean fullscreen) { - PropertyChangedEvent event = new PropertyChangedEvent(this, "fullscreen", this.fullscreen, fullscreen); - this.fullscreen = fullscreen; - propertyChanged.fire(event); - } - - public LauncherVisibility getLauncherVisibility() { - return LauncherVisibility.values()[launcherVisibility]; - } - - public void setLauncherVisibility(LauncherVisibility launcherVisibility) { - PropertyChangedEvent event = new PropertyChangedEvent(this, "launcherVisibility", this.launcherVisibility, launcherVisibility); - this.launcherVisibility = launcherVisibility.ordinal(); - propertyChanged.fire(event); - } - - public GameDirType getGameDirType() { - if (gameDirType < 0 || gameDirType > 1) - setGameDirType(GameDirType.ROOT_FOLDER); - return GameDirType.values()[gameDirType]; - } - - public void setGameDirType(GameDirType gameDirType) { - PropertyChangedEvent event = new PropertyChangedEvent(this, "gameDirType", this.gameDirType, gameDirType); - this.gameDirType = gameDirType.ordinal(); - propertyChanged.fire(event); - } - - public String getPermSize() { - return permSize; - } - - public void setPermSize(String permSize) { - PropertyChangedEvent event = new PropertyChangedEvent(this, "permSize", this.permSize, permSize); - this.permSize = permSize; - propertyChanged.fire(event); - } - - public boolean isNoJVMArgs() { - return noJVMArgs; - } - - public void setNoJVMArgs(boolean noJVMArgs) { - PropertyChangedEvent event = new PropertyChangedEvent(this, "noJVMArgs", this.noJVMArgs, noJVMArgs); - this.noJVMArgs = noJVMArgs; - propertyChanged.fire(event); - } - - public String getMinecraftArgs() { - return minecraftArgs; - } - - public void setMinecraftArgs(String minecraftArgs) { - PropertyChangedEvent event = new PropertyChangedEvent(this, "minecraftArgs", this.minecraftArgs, minecraftArgs); - this.minecraftArgs = minecraftArgs; - propertyChanged.fire(event); - } - - public String getPrecalledCommand() { - return precalledCommand; - } - - public void setPrecalledCommand(String precalledCommand) { - PropertyChangedEvent event = new PropertyChangedEvent(this, "precalledCommand", this.precalledCommand, precalledCommand); - this.precalledCommand = precalledCommand; - propertyChanged.fire(event); - } - - public String getWrapper() { - return wrapper; - } - - public void setWrapper(String wrapper) { - PropertyChangedEvent event = new PropertyChangedEvent(this, "wrapper", this.wrapper, wrapper); - this.wrapper = wrapper; - propertyChanged.fire(event); - } - - public String getServerIp() { - return serverIp; - } - - public void setServerIp(String serverIp) { - PropertyChangedEvent event = new PropertyChangedEvent(this, "serverIp", this.serverIp, serverIp); - this.serverIp = serverIp; - propertyChanged.fire(event); - } - - public boolean isNotCheckGame() { - return notCheckGame; - } - - public void setNotCheckGame(boolean notCheckGame) { - PropertyChangedEvent event = new PropertyChangedEvent(this, "notCheckGame", this.notCheckGame, notCheckGame); - this.notCheckGame = notCheckGame; - propertyChanged.fire(event); - } - - public boolean isUsesGlobal() { - return usesGlobal; - } - - public void setUsesGlobal(boolean usesGlobal) { - PropertyChangedEvent event = new PropertyChangedEvent(this, "usesGlobal", this.usesGlobal, usesGlobal); - this.usesGlobal = usesGlobal; - propertyChanged.fire(event); - } - - public LaunchOptions createLaunchOptions(File gameDir) { - LaunchOptions x = new LaunchOptions(); - x.setFullscreen(isFullscreen()); - x.setWrapper(getWrapper()); - x.setGameDir(gameDir); - x.setHeight(getHeight()); - x.setJavaArgs(getJavaArgs()); - x.setLaunchVersion(id); - x.setMaxMemory(getMaxMemory()); - x.setMinecraftArgs(getMinecraftArgs()); - x.setName(Main.shortTitle()); - x.setType(Main.shortTitle()); - x.setVersionName(Main.shortTitle()); - x.setNoJVMArgs(isNoJVMArgs()); - x.setNotCheckGame(isNotCheckGame()); - x.setPermSize(getPermSize()); - x.setPrecalledCommand(getPrecalledCommand()); - x.setProxyHost(Settings.getInstance().getProxyHost()); - x.setProxyPort(Settings.getInstance().getProxyPort()); - x.setProxyUser(Settings.getInstance().getProxyUserName()); - x.setProxyPass(Settings.getInstance().getProxyPassword()); - x.setServerIp(getServerIp()); - x.setWidth(getWidth()); - - String str = getJavaDir(); - if (!getJavaDirFile().exists()) { - HMCLog.err(C.i18n("launch.wrong_javadir")); - setJava(null); - str = getJavaDir(); - } - x.setJavaDir(str); - return x; - } -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/DraggableFrame.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/DraggableFrame.java deleted file mode 100755 index 0081d48ab..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/DraggableFrame.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.ui; - -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.awt.event.MouseMotionListener; -import javax.swing.JFrame; - -/** - * - * @author huangyuhui - */ -public class DraggableFrame extends JFrame - implements MouseListener, MouseMotionListener { - - private int dragGripX; - private int dragGripY; - - public DraggableFrame() { - addMouseListener(this); - addMouseMotionListener(this); - } - - @Override - public void mouseClicked(MouseEvent e) { - } - - @Override - public void mousePressed(MouseEvent e) { - if (e.getButton() == 1 && isUndecorated()) { - this.dragGripX = e.getX(); - this.dragGripY = e.getY(); - } - } - - @Override - public void mouseReleased(MouseEvent e) { - } - - @Override - public void mouseEntered(MouseEvent e) { - } - - @Override - public void mouseExited(MouseEvent e) { - } - - @Override - public void mouseDragged(MouseEvent e) { - if ((e.getModifiersEx() & 0x400) != 0 && isUndecorated()) - setLocation(e.getXOnScreen() - this.dragGripX, e.getYOnScreen() - this.dragGripY); - } - - @Override - public void mouseMoved(MouseEvent e) { - } -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameDownloadPanel.form b/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameDownloadPanel.form deleted file mode 100755 index 5de046455..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameDownloadPanel.form +++ /dev/null @@ -1,85 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameDownloadPanel.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameDownloadPanel.java deleted file mode 100755 index 50a60c4e9..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameDownloadPanel.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.ui; - -import org.jackhuang.hmcl.util.ui.Page; -import javax.swing.table.DefaultTableModel; -import org.jackhuang.hmcl.api.ui.TopTabPage; -import org.jackhuang.hmcl.core.download.MinecraftRemoteVersions; -import org.jackhuang.hmcl.setting.Settings; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.util.ui.MessageBox; -import org.jackhuang.hmcl.util.StrUtils; -import org.jackhuang.hmcl.util.task.ProgressProviderListener; -import org.jackhuang.hmcl.util.task.Task; -import org.jackhuang.hmcl.util.task.TaskWindow; -import org.jackhuang.hmcl.util.ui.SwingUtils; - -/** - * - * @author huangyuhui - */ -public class GameDownloadPanel extends Page implements ProgressProviderListener { - - GameSettingsPanel gsp; - - /** - * Creates new form GameDownloadPanel - */ - public GameDownloadPanel(GameSettingsPanel gsp) { - initComponents(); - this.gsp = gsp; - } - - /** - * This method is called from within the constructor to initialize the form. - * WARNING: Do NOT modify this code. The content of this method is always - * regenerated by the Form Editor. - */ - @SuppressWarnings("unchecked") - // //GEN-BEGIN:initComponents - private void initComponents() { - - btnDownload = new javax.swing.JButton(); - jScrollPane2 = new javax.swing.JScrollPane(); - lstDownloads = new javax.swing.JTable(); - btnRefreshGameDownloads = new javax.swing.JButton(); - - btnDownload.setText(C.i18n("ui.button.download")); // NOI18N - btnDownload.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnDownloadActionPerformed(evt); - } - }); - - lstDownloads.setModel(SwingUtils.makeDefaultTableModel(new String[]{C.i18n("install.version"), C.i18n("install.release_time"), C.i18n("install.time"), C.i18n("install.type")},new Class[]{String.class, String.class, String.class, String.class}, new boolean[]{false, false, false, false})); - lstDownloads.setToolTipText(""); - lstDownloads.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); - jScrollPane2.setViewportView(lstDownloads); - - btnRefreshGameDownloads.setText(C.i18n("ui.button.refresh")); // NOI18N - btnRefreshGameDownloads.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnRefreshGameDownloadsActionPerformed(evt); - } - }); - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); - this.setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 350, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(btnDownload, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(btnRefreshGameDownloads, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(btnRefreshGameDownloads) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(btnDownload)) - .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE) - ); - }// //GEN-END:initComponents - - private void btnDownloadActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDownloadActionPerformed - downloadMinecraft(); - gsp.refreshVersions(); - }//GEN-LAST:event_btnDownloadActionPerformed - - private void btnRefreshGameDownloadsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRefreshGameDownloadsActionPerformed - refreshDownloads(); - }//GEN-LAST:event_btnRefreshGameDownloadsActionPerformed - - public void refreshDownloads() { - if (loading) - return; - loading = true; - DefaultTableModel model = SwingUtils.clearDefaultTable(lstDownloads); - model.addRow(new Object[] { C.i18n("message.loading"), "", "" }); - MinecraftRemoteVersions.refreshRomoteVersions(Settings.getLastProfile().service().getDownloadType()) - .reg((ver) -> model.addRow(new Object[] { ver.id, ver.releaseTime, ver.time, - StrUtils.equalsOne(ver.type, "old_beta", "old_alpha", "release", "snapshot") ? C.i18n("versions." + ver.type) : ver.type })) - .regDone(SwingUtils.invokeLater(() -> { - loading = false; - lstDownloads.requestFocus(); - if (model.getRowCount() > 0) - model.removeRow(0); - })).setProgressProviderListener(this).runAsync(); - } - - boolean loading = false; - - @Override - public void setProgress(Task task, int prog, int max) { - DefaultTableModel model = (DefaultTableModel) lstDownloads.getModel(); - if (model.getRowCount() > 0) - model.setValueAt(C.i18n("message.loading") + " " + (prog < 0 ? "???" : Integer.toString(prog * 100 / max) + "%"), 0, 0); - } - - @Override - public void setStatus(Task task, String sta) { - } - - @Override - public void onProgressProviderDone(Task task) { - } - - void downloadMinecraft() { - if (lstDownloads.getSelectedRow() < 0) { - MessageBox.show(C.i18n("gamedownload.not_refreshed")); - return; - } - String id = (String) lstDownloads.getModel().getValueAt(lstDownloads.getSelectedRow(), 0); - TaskWindow.factory().execute(Settings.getLastProfile().service().download().downloadMinecraft(id)); - } - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JButton btnDownload; - private javax.swing.JButton btnRefreshGameDownloads; - private javax.swing.JScrollPane jScrollPane2; - private javax.swing.JTable lstDownloads; - // End of variables declaration//GEN-END:variables - - boolean refreshedDownloads = false; - - @Override - public void onSelect(TopTabPage page) { - super.onSelect(page); - if (!refreshedDownloads) { - refreshedDownloads = true; - refreshDownloads(); - } - } -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameSettingsPanel.form b/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameSettingsPanel.form deleted file mode 100755 index bc0810059..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameSettingsPanel.form +++ /dev/null @@ -1,1017 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameSettingsPanel.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameSettingsPanel.java deleted file mode 100755 index da582062d..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameSettingsPanel.java +++ /dev/null @@ -1,1532 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.ui; - -import org.jackhuang.hmcl.util.ui.Page; -import java.awt.datatransfer.DataFlavor; -import java.awt.datatransfer.Transferable; -import java.awt.datatransfer.UnsupportedFlavorException; -import java.awt.dnd.DnDConstants; -import java.awt.dnd.DropTarget; -import java.awt.dnd.DropTargetDragEvent; -import java.awt.dnd.DropTargetDropEvent; -import java.awt.dnd.DropTargetEvent; -import java.awt.dnd.DropTargetListener; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.ItemEvent; -import java.awt.event.KeyEvent; -import java.io.File; -import java.io.IOException; -import java.util.List; -import javax.swing.DefaultComboBoxModel; -import javax.swing.JMenuItem; -import javax.swing.JPopupMenu; -import javax.swing.SwingUtilities; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import javax.swing.event.TableModelEvent; -import javax.swing.table.DefaultTableModel; -import org.jackhuang.hmcl.api.HMCLApi; -import org.jackhuang.hmcl.api.event.config.ProfileChangedEvent; -import org.jackhuang.hmcl.api.event.config.ProfileLoadingEvent; -import org.jackhuang.hmcl.api.event.version.RefreshedVersionsEvent; -import org.jackhuang.hmcl.core.GameException; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.util.LauncherVisibility; -import org.jackhuang.hmcl.setting.Profile; -import org.jackhuang.hmcl.setting.Settings; -import org.jackhuang.hmcl.util.FileNameFilter; -import org.jackhuang.hmcl.core.mod.ModInfo; -import org.jackhuang.hmcl.core.install.InstallerType; -import org.jackhuang.hmcl.api.game.GameDirType; -import org.jackhuang.hmcl.core.version.MinecraftVersion; -import org.jackhuang.hmcl.setting.VersionSetting; -import org.jackhuang.hmcl.util.ui.MessageBox; -import org.jackhuang.hmcl.util.AbstractSwingWorker; -import org.jackhuang.hmcl.util.MinecraftVersionRequest; -import org.jackhuang.hmcl.util.sys.OS; -import org.jackhuang.hmcl.util.StrUtils; -import org.jackhuang.hmcl.api.func.Consumer; -import org.jackhuang.hmcl.util.sys.FileUtils; -import org.jackhuang.hmcl.util.ui.SwingUtils; -import org.jackhuang.hmcl.util.sys.Java; -import org.jackhuang.hmcl.util.task.TaskWindow; -import org.jackhuang.hmcl.util.ui.JSystemFileChooser; - -/** - * - * @author huangyuhui - */ -public final class GameSettingsPanel extends RepaintPage implements DropTargetListener { - - boolean isLoading = false; - boolean showedNoVersion = false; - public MinecraftVersionRequest minecraftVersion; - String mcVersion; - - final InstallerPanel installerPanels[] = new InstallerPanel[InstallerType.values().length]; - - public GameSettingsPanel() { - HMCLApi.EVENT_BUS.channel(RefreshedVersionsEvent.class).register(t -> { - if (Settings.getLastProfile().service().version() == t.getSource() && Settings.getLastProfile().service().version().getVersions().isEmpty()) - if (!showedNoVersion && Settings.getLastProfile().service().checkingModpack) { - showedNoVersion = true; - SwingUtilities.invokeLater(() -> { - if (MessageBox.show(C.i18n("mainwindow.no_version"), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION) { - MainFrame.INSTANCE.selectTab("game"); - showGameDownloads(); - } - }); - } - }); - - setRepainter(this); - } - - void initGui() { - initComponents(); - - animationEnabled = Settings.getInstance().isEnableAnimation(); - - dropTarget = new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, this); - - for (int i = 0; i < InstallerType.values().length; i++) - installerPanels[i] = new InstallerPanel(this, InstallerType.values()[i]); - pnlGameDownloads = new GameDownloadPanel(this).setAnimationEnabled(Settings.getInstance().isEnableAnimation()); - - initExplorationMenu(); - initManagementMenu(); - initExternalModsTable(); - initTabs(); - - isLoading = true; - for (Java j : Java.JAVA) - cboJava.addItem(j.getLocalizedName()); - isLoading = false; - - HMCLApi.EVENT_BUS.channel(ProfileLoadingEvent.class).register(onLoadingProfiles); - HMCLApi.EVENT_BUS.channel(ProfileChangedEvent.class).register(onSelectedProfilesChanged); - HMCLApi.EVENT_BUS.channel(RefreshedVersionsEvent.class).register(onRefreshedVersions); - } - - void initExplorationMenu() { - ppmExplore = new JPopupMenu(); - class ImplementedActionListener implements ActionListener { - - String a; - - ImplementedActionListener(String s) { - a = s; - } - - @Override - public void actionPerformed(ActionEvent e) { - Settings.getLastProfile().service().version().open(mcVersion, a); - } - } - JMenuItem itm; - itm = new JMenuItem(C.i18n("folder.game")); - itm.addActionListener(new ImplementedActionListener(null)); - ppmExplore.add(itm); - itm = new JMenuItem(C.i18n("folder.mod")); - itm.addActionListener(new ImplementedActionListener("mods")); - ppmExplore.add(itm); - itm = new JMenuItem(C.i18n("folder.coremod")); - itm.addActionListener(new ImplementedActionListener("coremods")); - ppmExplore.add(itm); - itm = new JMenuItem(C.i18n("folder.config")); - itm.addActionListener(new ImplementedActionListener("config")); - ppmExplore.add(itm); - itm = new JMenuItem(C.i18n("folder.resourcepacks")); - itm.addActionListener(new ImplementedActionListener("resourcepacks")); - ppmExplore.add(itm); - itm = new JMenuItem(C.i18n("folder.screenshots")); - itm.addActionListener(new ImplementedActionListener("screenshots")); - ppmExplore.add(itm); - } - - void initManagementMenu() { - ppmManage = new JPopupMenu(); - JMenuItem itm = new JMenuItem(C.i18n("versions.manage.rename")); - itm.addActionListener((e) -> { - if (mcVersion != null) { - String newName = MessageBox.showInputDialog(C.i18n("versions.manage.rename.message"), mcVersion); - if (newName != null) - if (Settings.getLastProfile().service().version().renameVersion(mcVersion, newName)) - refreshVersions(); - else - MessageBox.showLocalized("wizard.failed"); - } - }); - ppmManage.add(itm); - itm = new JMenuItem(C.i18n("versions.manage.remove")); - itm.addActionListener((e) -> { - if (mcVersion != null && MessageBox.show(C.i18n("versions.manage.remove.confirm") + mcVersion, MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION) - if (Settings.getLastProfile().service().version().removeVersionFromDisk(mcVersion)) - refreshVersions(); - }); - ppmManage.add(itm); - itm = new JMenuItem(C.i18n("versions.manage.redownload_json")); - itm.addActionListener((e) -> { - if (mcVersion != null) - TaskWindow.factory().execute(Settings.getLastProfile().service().download().downloadMinecraftVersionJson(mcVersion)); - }); - ppmManage.add(itm); - itm = new JMenuItem(C.i18n("versions.manage.redownload_assets_index")); - itm.addActionListener((e) -> { - if (mcVersion != null) - try { - Settings.getLastProfile().service().asset().refreshAssetsIndex(mcVersion); - } catch (GameException ex) { - HMCLog.err("Failed to download assets", ex); - MessageBox.showLocalized("assets.failed_download"); - } - }); - ppmManage.add(itm); - itm = new JMenuItem(C.i18n("versions.mamage.remove_libraries")); - itm.addActionListener((e) -> { - if (mcVersion != null) - FileUtils.deleteDirectoryQuietly(new File(Settings.getLastProfile().service().baseDirectory(), "libraries")); - }); - ppmManage.add(itm); - } - - void initExternalModsTable() { - if (lstExternalMods.getColumnModel().getColumnCount() > 0) { - lstExternalMods.getColumnModel().getColumn(0).setMinWidth(17); - lstExternalMods.getColumnModel().getColumn(0).setPreferredWidth(17); - lstExternalMods.getColumnModel().getColumn(0).setMaxWidth(17); - } - lstExternalMods.getSelectionModel().addListSelectionListener(e -> { - int row = lstExternalMods.getSelectedRow(); - List mods = Settings.getLastProfile().service().mod().getMods(Settings.getLastProfile().getSelectedVersion()); - if (mods != null && 0 <= row && row < mods.size()) { - ModInfo m = mods.get(row); - boolean hasLink = m.url != null; - String text = "" + (hasLink ? "
" : "") + m.getName() + (hasLink ? "" : ""); - text += " by " + m.getAuthor(); - String description = "No mod description found"; - if (m.description != null) { - description = ""; - for (String desc : m.description.split("\n")) - description += SwingUtils.getParsedJPanelText(lblModInfo, desc) + "
"; - } - text += "
" + description; - lblModInfo.setText(text); - lblModInfo.setCursor(new java.awt.Cursor(hasLink ? java.awt.Cursor.HAND_CURSOR : java.awt.Cursor.DEFAULT_CURSOR)); - } - }); - ((DefaultTableModel) lstExternalMods.getModel()).addTableModelListener(e -> { - if (e.getType() == TableModelEvent.UPDATE && e.getColumn() == 0) { - int row = lstExternalMods.getSelectedRow(); - List mods = Settings.getLastProfile().service().mod().getMods(Settings.getLastProfile().getSelectedVersion()); - if (mods != null && mods.size() > row && row >= 0) - mods.get(row).reverseModState(); - } - }); - } - - void initTabs() { - tabVersionEdit.addChangeListener(new ChangeListener() { - boolean b = false; - - @Override - public void stateChanged(ChangeEvent e) { - if (tabVersionEdit.getSelectedComponent() == pnlAutoInstall && !b) { - b = true; - installerPanels[0].refreshVersions(); - } - } - }); - - ((NewTabPane) tabVersionEdit).initializing = true; - tabVersionEdit.addTab(C.i18n("settings.tabs.game_download"), pnlGameDownloads); - ((NewTabPane) tabVersionEdit).initializing = false; - - ((NewTabPane) tabInstallers).initializing = true; - for (int i = 0; i < InstallerType.values().length; i++) - tabInstallers.addTab(InstallerType.values()[i].getLocalizedName(), installerPanels[i]); - ((NewTabPane) tabInstallers).initializing = false; - } - - /** - * This method is called from within the constructor to initialize the form. - * WARNING: Do NOT modify this code. The content of this method is always - * regenerated by the Form Editor. - */ - @SuppressWarnings("unchecked") - // //GEN-BEGIN:initComponents - private void initComponents() { - - tabVersionEdit = new NewTabPane(); - ((NewTabPane)tabVersionEdit).initializing = true; - pnlSettings = new Page().setAnimationEnabled(Settings.getInstance().isEnableAnimation()); - lblGameDir = new javax.swing.JLabel(); - txtGameDir = new javax.swing.JTextField(); - lblDimension = new javax.swing.JLabel(); - txtWidth = new javax.swing.JTextField(); - txtHeight = new javax.swing.JTextField(); - lblDimensionX = new javax.swing.JLabel(); - chkFullscreen = new javax.swing.JCheckBox(); - txtJavaDir = new javax.swing.JTextField(); - lblJavaDir = new javax.swing.JLabel(); - lblMaxMemory = new javax.swing.JLabel(); - txtMaxMemory = new javax.swing.JTextField(); - lblMaxMemorySize = new javax.swing.JLabel(); - btnDownloadAllAssets = new javax.swing.JButton(); - cboLauncherVisibility = new javax.swing.JComboBox(); - lblLauncherVisibility = new javax.swing.JLabel(); - lblRunDirectory = new javax.swing.JLabel(); - cboRunDirectory = new javax.swing.JComboBox(); - btnChoosingJavaDir = new javax.swing.JButton(); - cboJava = new javax.swing.JComboBox(); - btnChoosingGameDir = new javax.swing.JButton(); - btnCleanGame = new javax.swing.JButton(); - lblUsesGlobal = new javax.swing.JLabel(); - pnlAdvancedSettings = new Page().setAnimationEnabled(Settings.getInstance().isEnableAnimation()); - lblJavaArgs = new javax.swing.JLabel(); - txtJavaArgs = new javax.swing.JTextField(); - txtMinecraftArgs = new javax.swing.JTextField(); - lblMinecraftArgs = new javax.swing.JLabel(); - lblPermSize = new javax.swing.JLabel(); - txtPermSize = new javax.swing.JTextField(); - chkNoJVMArgs = new javax.swing.JCheckBox(); - lblPrecalledCommand = new javax.swing.JLabel(); - txtPrecalledCommand = new javax.swing.JTextField(); - lblServerIP = new javax.swing.JLabel(); - txtServerIP = new javax.swing.JTextField(); - lblPrecalledCommand1 = new javax.swing.JLabel(); - txtWrapperLauncher = new javax.swing.JTextField(); - chkDontCheckGame = new javax.swing.JCheckBox(); - chkNoCommon = new javax.swing.JCheckBox(); - pnlModManagement = new Page().setAnimationEnabled(Settings.getInstance().isEnableAnimation()); - pnlModManagementContent = new Page().setAnimationEnabled(Settings.getInstance().isEnableAnimation()); - jScrollPane1 = new javax.swing.JScrollPane(); - lstExternalMods = new javax.swing.JTable(); - btnAddMod = new javax.swing.JButton(); - btnRemoveMod = new javax.swing.JButton(); - lblModInfo = new javax.swing.JLabel(); - pnlAutoInstall = new Page().setAnimationEnabled(Settings.getInstance().isEnableAnimation()); - tabInstallers = new NewTabPane(); - pnlTop = new javax.swing.JPanel(); - pnlSelection = new javax.swing.JPanel(); - lblProfile = new javax.swing.JLabel(); - cboProfiles = new javax.swing.JComboBox(); - cboVersions = new javax.swing.JComboBox(); - lblVersions = new javax.swing.JLabel(); - pnlManagement = new javax.swing.JPanel(); - btnModify = new javax.swing.JButton(); - btnRefreshVersions = new javax.swing.JButton(); - txtMinecraftVersion = new javax.swing.JTextField(); - btnNewProfile = new javax.swing.JButton(); - btnRemoveProfile = new javax.swing.JButton(); - btnExplore = new javax.swing.JButton(); - btnTestGame = new javax.swing.JButton(); - btnShowLog = new javax.swing.JButton(); - btnMakeLaunchScript = new javax.swing.JButton(); - btnIncludeMinecraft = new javax.swing.JButton(); - - setBackground(new java.awt.Color(255, 255, 255)); - setOpaque(false); - - tabVersionEdit.setName("tabVersionEdit"); // NOI18N - - lblGameDir.setText(C.i18n("settings.game_directory")); // NOI18N - - txtGameDir.addFocusListener(new java.awt.event.FocusAdapter() { - public void focusLost(java.awt.event.FocusEvent evt) { - txtGameDirFocusLost(evt); - } - }); - - lblDimension.setText(C.i18n("settings.dimension")); // NOI18N - - txtWidth.setToolTipText(""); - txtWidth.addFocusListener(new java.awt.event.FocusAdapter() { - public void focusLost(java.awt.event.FocusEvent evt) { - txtWidthFocusLost(evt); - } - }); - - txtHeight.addFocusListener(new java.awt.event.FocusAdapter() { - public void focusLost(java.awt.event.FocusEvent evt) { - txtHeightFocusLost(evt); - } - }); - - lblDimensionX.setText("x"); - - chkFullscreen.setText(C.i18n("settings.fullscreen")); // NOI18N - chkFullscreen.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - chkFullscreenItemStateChanged(evt); - } - }); - - txtJavaDir.addFocusListener(new java.awt.event.FocusAdapter() { - public void focusLost(java.awt.event.FocusEvent evt) { - txtJavaDirFocusLost(evt); - } - }); - - lblJavaDir.setText(C.i18n("settings.java_dir")); // NOI18N - - lblMaxMemory.setText(C.i18n("settings.max_memory")); // NOI18N - - txtMaxMemory.addFocusListener(new java.awt.event.FocusAdapter() { - public void focusLost(java.awt.event.FocusEvent evt) { - txtMaxMemoryFocusLost(evt); - } - }); - - lblMaxMemorySize.setText(C.i18n("settings.physical_memory") + ": " + OS.getTotalPhysicalMemory() / 1024 / 1024 + "MB"); - - btnDownloadAllAssets.setText(C.i18n("assets.download_all")); // NOI18N - btnDownloadAllAssets.setToolTipText(""); - btnDownloadAllAssets.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnDownloadAllAssetsActionPerformed(evt); - } - }); - - cboLauncherVisibility.setModel(new javax.swing.DefaultComboBoxModel(new String[] { C.i18n("advancedsettings.launcher_visibility.close"), C.i18n("advancedsettings.launcher_visibility.hide"), C.i18n("advancedsettings.launcher_visibility.keep"),C.i18n("advancedsettings.launcher_visibility.hide_reopen") })); - cboLauncherVisibility.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - cboLauncherVisibilityItemStateChanged(evt); - } - }); - - lblLauncherVisibility.setText(C.i18n("advancedsettings.launcher_visible")); // NOI18N - - lblRunDirectory.setText(C.i18n("settings.run_directory")); // NOI18N - - cboRunDirectory.setModel(new javax.swing.DefaultComboBoxModel(new String[] { C.i18n("advancedsettings.game_dir.default"), C.i18n("advancedsettings.game_dir.independent") })); - cboRunDirectory.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - cboRunDirectoryItemStateChanged(evt); - } - }); - - btnChoosingJavaDir.setText(C.i18n("ui.button.explore")); // NOI18N - btnChoosingJavaDir.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnChoosingJavaDirActionPerformed(evt); - } - }); - - cboJava.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - cboJavaItemStateChanged(evt); - } - }); - - btnChoosingGameDir.setText(C.i18n("ui.button.explore")); // NOI18N - btnChoosingGameDir.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnChoosingGameDirActionPerformed(evt); - } - }); - - btnCleanGame.setText(C.i18n("setupwindow.clean")); // NOI18N - btnCleanGame.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnCleanGameActionPerformed(evt); - } - }); - - lblUsesGlobal.setText(C.i18n("settings.type.none")); // NOI18N - lblUsesGlobal.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR)); - lblUsesGlobal.addMouseListener(new java.awt.event.MouseAdapter() { - public void mouseClicked(java.awt.event.MouseEvent evt) { - lblUsesGlobalMouseClicked(evt); - } - }); - - javax.swing.GroupLayout pnlSettingsLayout = new javax.swing.GroupLayout(pnlSettings); - pnlSettings.setLayout(pnlSettingsLayout); - pnlSettingsLayout.setHorizontalGroup( - pnlSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnlSettingsLayout.createSequentialGroup() - .addGroup(pnlSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(lblJavaDir) - .addComponent(lblMaxMemory) - .addComponent(lblGameDir) - .addComponent(lblRunDirectory) - .addComponent(lblLauncherVisibility) - .addComponent(lblDimension)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(pnlSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(cboLauncherVisibility, javax.swing.GroupLayout.Alignment.TRAILING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(pnlSettingsLayout.createSequentialGroup() - .addComponent(txtWidth, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(lblDimensionX) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(txtHeight, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 182, Short.MAX_VALUE) - .addComponent(chkFullscreen)) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnlSettingsLayout.createSequentialGroup() - .addComponent(txtMaxMemory) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(lblMaxMemorySize)) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnlSettingsLayout.createSequentialGroup() - .addComponent(txtGameDir) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnChoosingGameDir)) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnlSettingsLayout.createSequentialGroup() - .addComponent(cboJava, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(txtJavaDir) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnChoosingJavaDir)) - .addComponent(cboRunDirectory, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) - .addGroup(pnlSettingsLayout.createSequentialGroup() - .addComponent(btnDownloadAllAssets) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(btnCleanGame)) - .addGroup(pnlSettingsLayout.createSequentialGroup() - .addComponent(lblUsesGlobal) - .addGap(0, 0, Short.MAX_VALUE)) - ); - pnlSettingsLayout.setVerticalGroup( - pnlSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnlSettingsLayout.createSequentialGroup() - .addComponent(lblUsesGlobal) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(pnlSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(txtGameDir, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblGameDir) - .addComponent(btnChoosingGameDir, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(pnlSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(txtJavaDir, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblJavaDir) - .addComponent(btnChoosingJavaDir, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(cboJava, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(pnlSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(lblMaxMemorySize) - .addComponent(txtMaxMemory, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblMaxMemory)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(pnlSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(cboLauncherVisibility, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblLauncherVisibility)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(pnlSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(cboRunDirectory, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblRunDirectory)) - .addGap(4, 4, 4) - .addGroup(pnlSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(txtHeight, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(chkFullscreen, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblDimensionX, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblDimension) - .addComponent(txtWidth, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 51, Short.MAX_VALUE) - .addGroup(pnlSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(btnDownloadAllAssets) - .addComponent(btnCleanGame)) - .addContainerGap()) - ); - - tabVersionEdit.addTab(C.i18n("settings"), pnlSettings); // NOI18N - - lblJavaArgs.setText(C.i18n("advancedsettings.jvm_args")); // NOI18N - - txtJavaArgs.setToolTipText(C.i18n("advancedsettings.java_args_default")); // NOI18N - txtJavaArgs.addFocusListener(new java.awt.event.FocusAdapter() { - public void focusLost(java.awt.event.FocusEvent evt) { - txtJavaArgsFocusLost(evt); - } - }); - - txtMinecraftArgs.addFocusListener(new java.awt.event.FocusAdapter() { - public void focusLost(java.awt.event.FocusEvent evt) { - txtMinecraftArgsFocusLost(evt); - } - }); - - lblMinecraftArgs.setText(C.i18n("advancedsettings.Minecraft_arguments")); // NOI18N - - lblPermSize.setText(C.i18n("advancedsettings.java_permanent_generation_space")); // NOI18N - - txtPermSize.addFocusListener(new java.awt.event.FocusAdapter() { - public void focusLost(java.awt.event.FocusEvent evt) { - txtPermSizeFocusLost(evt); - } - }); - - chkNoJVMArgs.setText(C.i18n("advancedsettings.no_jvm_args")); // NOI18N - chkNoJVMArgs.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - chkNoJVMArgsItemStateChanged(evt); - } - }); - - lblPrecalledCommand.setText(C.i18n("advancedsettings.precall_command")); // NOI18N - - txtPrecalledCommand.addFocusListener(new java.awt.event.FocusAdapter() { - public void focusLost(java.awt.event.FocusEvent evt) { - txtPrecalledCommandFocusLost(evt); - } - }); - - lblServerIP.setText(C.i18n("advancedsettings.server_ip")); // NOI18N - - txtServerIP.addFocusListener(new java.awt.event.FocusAdapter() { - public void focusLost(java.awt.event.FocusEvent evt) { - txtServerIPFocusLost(evt); - } - }); - - lblPrecalledCommand1.setText(C.i18n("advancedsettings.wrapper_launcher")); // NOI18N - - txtWrapperLauncher.addFocusListener(new java.awt.event.FocusAdapter() { - public void focusLost(java.awt.event.FocusEvent evt) { - txtWrapperLauncherFocusLost(evt); - } - }); - - chkDontCheckGame.setText(C.i18n("advancedsettings.dont_check_game_completeness")); // NOI18N - chkDontCheckGame.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - chkDontCheckGameItemStateChanged(evt); - } - }); - - chkNoCommon.setText(C.i18n("advancedsettings.no_common")); // NOI18N - chkNoCommon.setToolTipText(C.i18n("launcher.commpath_tooltip")); // NOI18N - chkNoCommon.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - chkNoCommonItemStateChanged(evt); - } - }); - - javax.swing.GroupLayout pnlAdvancedSettingsLayout = new javax.swing.GroupLayout(pnlAdvancedSettings); - pnlAdvancedSettings.setLayout(pnlAdvancedSettingsLayout); - pnlAdvancedSettingsLayout.setHorizontalGroup( - pnlAdvancedSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(txtPrecalledCommand) - .addComponent(txtServerIP) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnlAdvancedSettingsLayout.createSequentialGroup() - .addGroup(pnlAdvancedSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(lblMinecraftArgs) - .addComponent(lblPermSize) - .addComponent(lblJavaArgs)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(pnlAdvancedSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(txtJavaArgs, javax.swing.GroupLayout.DEFAULT_SIZE, 457, Short.MAX_VALUE) - .addComponent(txtMinecraftArgs) - .addComponent(txtPermSize, javax.swing.GroupLayout.Alignment.TRAILING))) - .addGroup(pnlAdvancedSettingsLayout.createSequentialGroup() - .addGroup(pnlAdvancedSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(txtWrapperLauncher) - .addGroup(pnlAdvancedSettingsLayout.createSequentialGroup() - .addContainerGap() - .addComponent(chkNoJVMArgs) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(chkNoCommon) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 190, Short.MAX_VALUE) - .addComponent(chkDontCheckGame)) - .addGroup(pnlAdvancedSettingsLayout.createSequentialGroup() - .addGroup(pnlAdvancedSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(lblPrecalledCommand1) - .addComponent(lblPrecalledCommand) - .addComponent(lblServerIP)) - .addGap(0, 0, Short.MAX_VALUE))) - .addContainerGap()) - ); - pnlAdvancedSettingsLayout.setVerticalGroup( - pnlAdvancedSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnlAdvancedSettingsLayout.createSequentialGroup() - .addGap(0, 0, 0) - .addGroup(pnlAdvancedSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(txtJavaArgs, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblJavaArgs)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(pnlAdvancedSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(txtMinecraftArgs, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblMinecraftArgs)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(pnlAdvancedSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(txtPermSize, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblPermSize)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(lblPrecalledCommand1) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(txtWrapperLauncher, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(lblPrecalledCommand) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(txtPrecalledCommand, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(lblServerIP) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(txtServerIP, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(pnlAdvancedSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(chkNoJVMArgs) - .addComponent(chkDontCheckGame) - .addComponent(chkNoCommon)) - .addContainerGap()) - ); - - tabVersionEdit.addTab(C.i18n("advancedsettings"), pnlAdvancedSettings); // NOI18N - - lstExternalMods.setModel(SwingUtils.makeDefaultTableModel(new String[]{"", "Mod", C.i18n("ui.label.version")}, new Class[]{Boolean.class,String.class,String.class}, new boolean[]{true,false,false})); - lstExternalMods.setColumnSelectionAllowed(true); - lstExternalMods.getTableHeader().setReorderingAllowed(false); - lstExternalMods.addKeyListener(new java.awt.event.KeyAdapter() { - public void keyPressed(java.awt.event.KeyEvent evt) { - lstExternalModsKeyPressed(evt); - } - }); - jScrollPane1.setViewportView(lstExternalMods); - lstExternalMods.getColumnModel().getSelectionModel().setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); - - btnAddMod.setText(C.i18n("mods.add")); // NOI18N - btnAddMod.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnAddModActionPerformed(evt); - } - }); - - btnRemoveMod.setText(C.i18n("mods.remove")); // NOI18N - btnRemoveMod.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnRemoveModActionPerformed(evt); - } - }); - - lblModInfo.setText(C.i18n("mods.default_information")); // NOI18N - lblModInfo.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR)); - lblModInfo.addMouseListener(new java.awt.event.MouseAdapter() { - public void mouseClicked(java.awt.event.MouseEvent evt) { - lblModInfoMouseClicked(evt); - } - }); - - javax.swing.GroupLayout pnlModManagementContentLayout = new javax.swing.GroupLayout(pnlModManagementContent); - pnlModManagementContent.setLayout(pnlModManagementContentLayout); - pnlModManagementContentLayout.setHorizontalGroup( - pnlModManagementContentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnlModManagementContentLayout.createSequentialGroup() - .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 644, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(pnlModManagementContentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(btnRemoveMod, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(btnAddMod, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnlModManagementContentLayout.createSequentialGroup() - .addComponent(lblModInfo, javax.swing.GroupLayout.DEFAULT_SIZE, 751, Short.MAX_VALUE) - .addContainerGap()) - ); - pnlModManagementContentLayout.setVerticalGroup( - pnlModManagementContentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnlModManagementContentLayout.createSequentialGroup() - .addGroup(pnlModManagementContentLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnlModManagementContentLayout.createSequentialGroup() - .addComponent(btnAddMod) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnRemoveMod) - .addGap(0, 0, Short.MAX_VALUE)) - .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 271, Short.MAX_VALUE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(lblModInfo)) - ); - - javax.swing.GroupLayout pnlModManagementLayout = new javax.swing.GroupLayout(pnlModManagement); - pnlModManagement.setLayout(pnlModManagementLayout); - pnlModManagementLayout.setHorizontalGroup( - pnlModManagementLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(pnlModManagementContent, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - ); - pnlModManagementLayout.setVerticalGroup( - pnlModManagementLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(pnlModManagementContent, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - ); - - tabVersionEdit.addTab(C.i18n("mods"), pnlModManagement); // NOI18N - - javax.swing.GroupLayout pnlAutoInstallLayout = new javax.swing.GroupLayout(pnlAutoInstall); - pnlAutoInstall.setLayout(pnlAutoInstallLayout); - pnlAutoInstallLayout.setHorizontalGroup( - pnlAutoInstallLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(tabInstallers) - ); - pnlAutoInstallLayout.setVerticalGroup( - pnlAutoInstallLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(tabInstallers) - ); - - tabVersionEdit.addTab(C.i18n("settings.tabs.installers"), pnlAutoInstall); // NOI18N - - lblProfile.setText(C.i18n("ui.label.profile")); // NOI18N - - cboProfiles.setMinimumSize(new java.awt.Dimension(32, 23)); - cboProfiles.setPreferredSize(new java.awt.Dimension(32, 23)); - cboProfiles.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - cboProfilesItemStateChanged(evt); - } - }); - - cboVersions.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - cboVersionsItemStateChanged(evt); - } - }); - - lblVersions.setText(C.i18n("ui.label.version")); // NOI18N - - javax.swing.GroupLayout pnlSelectionLayout = new javax.swing.GroupLayout(pnlSelection); - pnlSelection.setLayout(pnlSelectionLayout); - pnlSelectionLayout.setHorizontalGroup( - pnlSelectionLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnlSelectionLayout.createSequentialGroup() - .addContainerGap() - .addGroup(pnlSelectionLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(lblVersions) - .addComponent(lblProfile)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(pnlSelectionLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(cboProfiles, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(cboVersions, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) - ); - pnlSelectionLayout.setVerticalGroup( - pnlSelectionLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnlSelectionLayout.createSequentialGroup() - .addContainerGap() - .addGroup(pnlSelectionLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(cboProfiles, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblProfile)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(pnlSelectionLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(cboVersions, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblVersions)) - .addContainerGap(11, Short.MAX_VALUE)) - ); - - btnModify.setText(C.i18n("settings.manage")); // NOI18N - btnModify.addMouseListener(new java.awt.event.MouseAdapter() { - public void mouseClicked(java.awt.event.MouseEvent evt) { - btnModifyMouseClicked(evt); - } - }); - - btnRefreshVersions.setText(C.i18n("ui.button.refresh")); // NOI18N - btnRefreshVersions.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnRefreshVersionsActionPerformed(evt); - } - }); - - txtMinecraftVersion.setEditable(false); - - btnNewProfile.setText(C.i18n("setupwindow.new")); // NOI18N - btnNewProfile.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnNewProfileActionPerformed(evt); - } - }); - - btnRemoveProfile.setText(C.i18n("ui.button.delete")); // NOI18N - btnRemoveProfile.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnRemoveProfileActionPerformed(evt); - } - }); - - btnExplore.setText(C.i18n("settings.explore")); // NOI18N - btnExplore.setToolTipText(""); - btnExplore.addMouseListener(new java.awt.event.MouseAdapter() { - public void mouseClicked(java.awt.event.MouseEvent evt) { - btnExploreMouseClicked(evt); - } - }); - - javax.swing.GroupLayout pnlManagementLayout = new javax.swing.GroupLayout(pnlManagement); - pnlManagement.setLayout(pnlManagementLayout); - pnlManagementLayout.setHorizontalGroup( - pnlManagementLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnlManagementLayout.createSequentialGroup() - .addGap(0, 0, 0) - .addGroup(pnlManagementLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(btnNewProfile, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(txtMinecraftVersion)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(pnlManagementLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(btnRemoveProfile, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(btnRefreshVersions, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(pnlManagementLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(btnModify, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(btnExplore, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - ); - pnlManagementLayout.setVerticalGroup( - pnlManagementLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnlManagementLayout.createSequentialGroup() - .addContainerGap() - .addGroup(pnlManagementLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(btnNewProfile, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(btnRemoveProfile, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(btnExplore, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(pnlManagementLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(txtMinecraftVersion, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(btnRefreshVersions, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(btnModify, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - ); - - javax.swing.GroupLayout pnlTopLayout = new javax.swing.GroupLayout(pnlTop); - pnlTop.setLayout(pnlTopLayout); - pnlTopLayout.setHorizontalGroup( - pnlTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnlTopLayout.createSequentialGroup() - .addComponent(pnlSelection, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pnlManagement, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - ); - pnlTopLayout.setVerticalGroup( - pnlTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnlTopLayout.createSequentialGroup() - .addGroup(pnlTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(pnlSelection, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(pnlManagement, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addGap(0, 0, Short.MAX_VALUE)) - ); - - btnTestGame.setText(C.i18n("settings.test_game")); // NOI18N - btnTestGame.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnTestGameActionPerformed(evt); - } - }); - - btnShowLog.setText(C.i18n("mainwindow.show_log")); // NOI18N - btnShowLog.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnShowLogActionPerformed(evt); - } - }); - - btnMakeLaunchScript.setText(C.i18n("mainwindow.make_launch_script")); // NOI18N - btnMakeLaunchScript.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnMakeLaunchScriptActionPerformed(evt); - } - }); - - btnIncludeMinecraft.setText(C.i18n("setupwindow.include_minecraft")); // NOI18N - btnIncludeMinecraft.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnIncludeMinecraftActionPerformed(evt); - } - }); - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); - this.setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(pnlTop, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(tabVersionEdit, javax.swing.GroupLayout.Alignment.TRAILING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addGap(0, 0, Short.MAX_VALUE) - .addComponent(btnMakeLaunchScript) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnShowLog) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnTestGame))) - .addContainerGap()) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addComponent(btnIncludeMinecraft) - .addContainerGap(677, Short.MAX_VALUE))) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(pnlTop, javax.swing.GroupLayout.PREFERRED_SIZE, 70, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(tabVersionEdit) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(btnTestGame) - .addComponent(btnShowLog) - .addComponent(btnMakeLaunchScript)) - .addContainerGap()) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addContainerGap(403, Short.MAX_VALUE) - .addComponent(btnIncludeMinecraft) - .addContainerGap())) - ); - - ((NewTabPane)tabVersionEdit).initializing = false; - }// //GEN-END:initComponents - - private void btnIncludeMinecraftActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnIncludeMinecraftActionPerformed - JSystemFileChooser fc = new JSystemFileChooser(new File("").getAbsoluteFile()); - fc.setFileSelectionMode(JSystemFileChooser.DIRECTORIES_ONLY); - if (fc.showOpenDialog(this) == JSystemFileChooser.APPROVE_OPTION) { - File newGameDir = fc.getSelectedFile(); - String name = MessageBox.showInputDialog(C.i18n("setupwindow.give_a_name")); - if (StrUtils.isBlank(name)) { - MessageBox.show(C.i18n("setupwindow.no_empty_name")); - return; - } - Profile newProfile = new Profile(name); - newProfile.setGameDir(newGameDir); - Settings.putProfile(newProfile); - MessageBox.show(C.i18n("setupwindow.find_in_configurations")); - loadProfiles(); - } - }//GEN-LAST:event_btnIncludeMinecraftActionPerformed - - private void btnMakeLaunchScriptActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnMakeLaunchScriptActionPerformed - MainFrame.INSTANCE.daemon.makeLaunchScript(Settings.getLastProfile()); - }//GEN-LAST:event_btnMakeLaunchScriptActionPerformed - - private void btnShowLogActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnShowLogActionPerformed - LogWindow.INSTANCE.setVisible(true); - }//GEN-LAST:event_btnShowLogActionPerformed - - private void btnTestGameActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnTestGameActionPerformed - LogWindow.INSTANCE.setVisible(true); - MainFrame.INSTANCE.daemon.testGame(Settings.getLastProfile()); - }//GEN-LAST:event_btnTestGameActionPerformed - - private void btnExploreMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_btnExploreMouseClicked - ppmExplore.show(evt.getComponent(), evt.getPoint().x, evt.getPoint().y); - }//GEN-LAST:event_btnExploreMouseClicked - - private void btnRemoveProfileActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRemoveProfileActionPerformed - if (MessageBox.show(C.i18n("ui.message.sure_remove", Settings.getLastProfile().getName()), MessageBox.YES_NO_OPTION) == MessageBox.NO_OPTION) - return; - Settings.delProfile(Settings.getLastProfile()); - }//GEN-LAST:event_btnRemoveProfileActionPerformed - - private void btnNewProfileActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnNewProfileActionPerformed - new NewProfileWindow(null).setVisible(true); - loadProfiles(); - }//GEN-LAST:event_btnNewProfileActionPerformed - - private void btnRefreshVersionsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRefreshVersionsActionPerformed - refreshVersions(); - }//GEN-LAST:event_btnRefreshVersionsActionPerformed - - private void btnModifyMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_btnModifyMouseClicked - ppmManage.show(evt.getComponent(), evt.getPoint().x, evt.getPoint().y); - }//GEN-LAST:event_btnModifyMouseClicked - - private void cboVersionsItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboVersionsItemStateChanged - if (isLoading || evt.getStateChange() != ItemEvent.SELECTED || cboVersions.getSelectedIndex() < 0 || StrUtils.isBlank((String) cboVersions.getSelectedItem())) - return; - Settings.getLastProfile().setSelectedVersion((String) cboVersions.getSelectedItem()); - }//GEN-LAST:event_cboVersionsItemStateChanged - - // - private void cboProfilesItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboProfilesItemStateChanged - if (!isLoading) - Settings.getInstance().setLast((String) cboProfiles.getSelectedItem()); - }//GEN-LAST:event_cboProfilesItemStateChanged - - private void lblModInfoMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_lblModInfoMouseClicked - int idx = lstExternalMods.getSelectedRow(); - if (idx > 0 && idx < Settings.getLastProfile().service().mod().getMods(Settings.getLastProfile().getSelectedVersion()).size()) - SwingUtils.openLink(Settings.getLastProfile().service().mod().getMods(Settings.getLastProfile().getSelectedVersion()).get(idx).url); - }//GEN-LAST:event_lblModInfoMouseClicked - - private void btnRemoveModActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRemoveModActionPerformed - Settings.getLastProfile().service().mod().removeMod(Settings.getLastProfile().getSelectedVersion(), SwingUtils.getValueBySelectedRow(lstExternalMods, lstExternalMods.getSelectedRows(), 1)); - reloadMods(); - }//GEN-LAST:event_btnRemoveModActionPerformed - - private void btnAddModActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAddModActionPerformed - JSystemFileChooser fc = new JSystemFileChooser(); - fc.setFileSelectionMode(JSystemFileChooser.FILES_ONLY); - fc.setDialogTitle(C.i18n("mods.choose_mod")); - fc.setMultiSelectionEnabled(true); - if (fc.showOpenDialog(this) != JSystemFileChooser.APPROVE_OPTION) - return; - boolean flag = true; - for (File f : fc.getSelectedFiles()) - flag &= Settings.getLastProfile().service().mod().addMod(Settings.getLastProfile().getSelectedVersion(), f); - reloadMods(); - if (!flag) - MessageBox.show(C.i18n("mods.failed")); - }//GEN-LAST:event_btnAddModActionPerformed - - private void lstExternalModsKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_lstExternalModsKeyPressed - if (evt.getKeyCode() == KeyEvent.VK_DELETE) - btnRemoveModActionPerformed(null); - }//GEN-LAST:event_lstExternalModsKeyPressed - - private void chkDontCheckGameItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_chkDontCheckGameItemStateChanged - if (!isLoading) - Settings.getLastProfile().getSelectedVersionSetting().setNotCheckGame(chkDontCheckGame.isSelected()); - }//GEN-LAST:event_chkDontCheckGameItemStateChanged - - private void txtWrapperLauncherFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtWrapperLauncherFocusLost - Settings.getLastProfile().getSelectedVersionSetting().setWrapper(txtWrapperLauncher.getText()); - }//GEN-LAST:event_txtWrapperLauncherFocusLost - - private void txtServerIPFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtServerIPFocusLost - Settings.getLastProfile().getSelectedVersionSetting().setServerIp(txtServerIP.getText()); - }//GEN-LAST:event_txtServerIPFocusLost - - private void txtPrecalledCommandFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtPrecalledCommandFocusLost - Settings.getLastProfile().getSelectedVersionSetting().setPrecalledCommand(txtPrecalledCommand.getText()); - }//GEN-LAST:event_txtPrecalledCommandFocusLost - - private void chkNoJVMArgsItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_chkNoJVMArgsItemStateChanged - if (!isLoading) - Settings.getLastProfile().getSelectedVersionSetting().setNoJVMArgs(chkNoJVMArgs.isSelected()); - }//GEN-LAST:event_chkNoJVMArgsItemStateChanged - - private void txtPermSizeFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtPermSizeFocusLost - Settings.getLastProfile().getSelectedVersionSetting().setPermSize(txtPermSize.getText()); - }//GEN-LAST:event_txtPermSizeFocusLost - - private void txtMinecraftArgsFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtMinecraftArgsFocusLost - Settings.getLastProfile().getSelectedVersionSetting().setMinecraftArgs(txtMinecraftArgs.getText()); - }//GEN-LAST:event_txtMinecraftArgsFocusLost - - private void txtJavaArgsFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtJavaArgsFocusLost - Settings.getLastProfile().getSelectedVersionSetting().setJavaArgs(txtJavaArgs.getText()); - }//GEN-LAST:event_txtJavaArgsFocusLost - - private void btnCleanGameActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCleanGameActionPerformed - Settings.getLastProfile().service().version().cleanFolder(); - }//GEN-LAST:event_btnCleanGameActionPerformed - - private void btnChoosingGameDirActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnChoosingGameDirActionPerformed - JSystemFileChooser fc = new JSystemFileChooser(); - fc.setFileSelectionMode(JSystemFileChooser.DIRECTORIES_ONLY); - fc.setDialogTitle(C.i18n("settings.choose_gamedir")); - fc.setMultiSelectionEnabled(false); - if (fc.showOpenDialog(this) != JSystemFileChooser.APPROVE_OPTION || fc.getSelectedFile() == null) - return; - try { - String path = fc.getSelectedFile().getCanonicalPath(); - txtGameDir.setText(path); - Settings.getLastProfile().setGameDir(fc.getSelectedFile()); - } catch (IOException e) { - HMCLog.warn("Failed to set game dir.", e); - MessageBox.show(C.i18n("ui.label.failed_set") + e.getMessage()); - } - }//GEN-LAST:event_btnChoosingGameDirActionPerformed - - private void cboJavaItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboJavaItemStateChanged - if (evt.getStateChange() != ItemEvent.SELECTED || cboJava.getSelectedIndex() < 0 || StrUtils.isBlank((String) cboJava.getSelectedItem())) - return; - int idx = cboJava.getSelectedIndex(); - if (idx != -1) { - Java j = Java.JAVA.get(idx); - txtJavaDir.setText(j.getHome() == null ? Settings.getLastProfile().getSelectedVersionSetting().getSettingsJavaDir() : j.getJava()); - txtJavaDir.setEditable(idx == 1); - if (!isLoading) - Settings.getLastProfile().getSelectedVersionSetting().setJava(j); - } - }//GEN-LAST:event_cboJavaItemStateChanged - - private void btnChoosingJavaDirActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnChoosingJavaDirActionPerformed - if (cboJava.getSelectedIndex() != 1) - return; - JSystemFileChooser fc = new JSystemFileChooser(); - fc.setFileSelectionMode(JSystemFileChooser.FILES_ONLY); - fc.setDialogTitle(C.i18n("settings.choose_javapath")); - fc.setMultiSelectionEnabled(false); - fc.setFileFilter(new FileNameFilter("javaw.exe")); - fc.addChoosableFileFilter(new FileNameFilter("java.exe")); - fc.addChoosableFileFilter(new FileNameFilter("java")); - if (fc.showOpenDialog(this) != JSystemFileChooser.APPROVE_OPTION || fc.getSelectedFile() == null) - return; - try { - String path = fc.getSelectedFile().getCanonicalPath(); - txtJavaDir.setText(path); - Settings.getLastProfile().getSelectedVersionSetting().setJavaDir(txtJavaDir.getText()); - } catch (IOException e) { - HMCLog.warn("Failed to set java path.", e); - MessageBox.show(C.i18n("ui.label.failed_set") + e.getMessage()); - } - }//GEN-LAST:event_btnChoosingJavaDirActionPerformed - - private void cboRunDirectoryItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboRunDirectoryItemStateChanged - if (!isLoading && cboRunDirectory.getSelectedIndex() >= 0) - Settings.getLastProfile().getSelectedVersionSetting().setGameDirType(GameDirType.values()[cboRunDirectory.getSelectedIndex()]); - }//GEN-LAST:event_cboRunDirectoryItemStateChanged - - private void cboLauncherVisibilityItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboLauncherVisibilityItemStateChanged - if (!isLoading && cboLauncherVisibility.getSelectedIndex() >= 0) - Settings.getLastProfile().getSelectedVersionSetting().setLauncherVisibility(LauncherVisibility.values()[cboLauncherVisibility.getSelectedIndex()]); - }//GEN-LAST:event_cboLauncherVisibilityItemStateChanged - - private void btnDownloadAllAssetsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnDownloadAllAssetsActionPerformed - if (mcVersion != null) - try { - TaskWindow.factory().execute(Settings.getLastProfile().service().asset().downloadAssets(mcVersion)); - } catch (GameException ex) { - HMCLog.err("Failed to download assets", ex); - MessageBox.showLocalized("assets.failed_download"); - } - }//GEN-LAST:event_btnDownloadAllAssetsActionPerformed - - private void txtMaxMemoryFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtMaxMemoryFocusLost - Settings.getLastProfile().getSelectedVersionSetting().setMaxMemory(txtMaxMemory.getText()); - }//GEN-LAST:event_txtMaxMemoryFocusLost - - private void txtJavaDirFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtJavaDirFocusLost - Settings.getLastProfile().getSelectedVersionSetting().setJavaDir(txtJavaDir.getText()); - }//GEN-LAST:event_txtJavaDirFocusLost - - private void chkFullscreenItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_chkFullscreenItemStateChanged - if (!isLoading) - Settings.getLastProfile().getSelectedVersionSetting().setFullscreen(chkFullscreen.isSelected()); - }//GEN-LAST:event_chkFullscreenItemStateChanged - - private void txtHeightFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtHeightFocusLost - Settings.getLastProfile().getSelectedVersionSetting().setHeight(txtHeight.getText()); - }//GEN-LAST:event_txtHeightFocusLost - - private void txtWidthFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtWidthFocusLost - Settings.getLastProfile().getSelectedVersionSetting().setWidth(txtWidth.getText()); - }//GEN-LAST:event_txtWidthFocusLost - - private void txtGameDirFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtGameDirFocusLost - Settings.getLastProfile().setGameDir(new File(txtGameDir.getText())); - loadVersions(); - }//GEN-LAST:event_txtGameDirFocusLost - - private void lblUsesGlobalMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_lblUsesGlobalMouseClicked - if (mcVersion == null) - return; - Profile profile = Settings.getLastProfile(); - if (profile.isVersionSettingGlobe(mcVersion)) - profile.makeVersionSettingSpecial(mcVersion); - else - profile.makeVersionSettingGlobal(mcVersion); - }//GEN-LAST:event_lblUsesGlobalMouseClicked - - private void chkNoCommonItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_chkNoCommonItemStateChanged - if (!isLoading) - Settings.getLastProfile().setNoCommon(chkNoCommon.isSelected()); - }//GEN-LAST:event_chkNoCommonItemStateChanged - - // - // - void prepareVersionSetting(Profile profile, VersionSetting vs) { - if (vs == null) - return; - isLoading = true; - txtWidth.setText(vs.getWidth()); - txtHeight.setText(vs.getHeight()); - txtMaxMemory.setText(vs.getMaxMemory()); - txtPermSize.setText(vs.getPermSize()); - txtJavaArgs.setText(vs.getJavaArgs()); - txtMinecraftArgs.setText(vs.getMinecraftArgs()); - txtPrecalledCommand.setText(vs.getPrecalledCommand()); - txtServerIP.setText(vs.getServerIp()); - chkNoJVMArgs.setSelected(vs.isNoJVMArgs()); - chkDontCheckGame.setSelected(vs.isNotCheckGame()); - chkNoCommon.setSelected(profile.isNoCommon()); - chkFullscreen.setSelected(vs.isFullscreen()); - cboLauncherVisibility.setSelectedIndex(vs.getLauncherVisibility().ordinal()); - cboRunDirectory.setSelectedIndex(vs.getGameDirType().ordinal()); - cboJava.setSelectedIndex(vs.getJavaIndexInAllJavas()); - isLoading = false; - } - - /** - * Anaylze the jar of selected minecraft version of current getProfile() to - * get the version. - */ - void loadMinecraftVersion(String id) { - txtMinecraftVersion.setText(""); - if (id == null) - return; - minecraftVersion = MinecraftVersionRequest.minecraftVersion(Settings.getLastProfile().service().version().getMinecraftJar(id)); - txtMinecraftVersion.setText(MinecraftVersionRequest.getResponse(minecraftVersion)); - } - - // - // - String getMinecraftVersionFormatted() { - return minecraftVersion == null ? "" : (StrUtils.formatVersion(minecraftVersion.version) == null) ? mcVersion : minecraftVersion.version; - } - - @Override - public void dragEnter(DropTargetDragEvent dtde) { - } - - @Override - public void dragOver(DropTargetDragEvent dtde) { - } - - @Override - public void dropActionChanged(DropTargetDragEvent dtde) { - } - - @Override - public void dragExit(DropTargetEvent dte) { - } - - @Override - public void drop(DropTargetDropEvent dtde) { - DataFlavor[] f = dtde.getCurrentDataFlavors(); - if (f[0].match(DataFlavor.javaFileListFlavor)) - try { - dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE); - Transferable tr = dtde.getTransferable(); - List files = (List) tr.getTransferData(DataFlavor.javaFileListFlavor); - for (File file : files) - Settings.getLastProfile().service().mod().addMod(Settings.getLastProfile().getSelectedVersion(), file); - reloadMods(); - } catch (UnsupportedFlavorException | IOException ex) { - HMCLog.warn("Failed to drop file.", ex); - } - } - - void refreshVersions() { - Settings.getLastProfile().service().version().refreshVersions(); - } - - // - // - private boolean reloadingMods = false; - private final Object modLock = new Object(); - - private void reloadMods() { - synchronized (modLock) { - if (reloadingMods) - return; - reloadingMods = true; - DefaultTableModel model = SwingUtils.clearDefaultTable(lstExternalMods); - new OverridableSwingWorkerImpl().reg(t -> { - synchronized (modLock) { - for (ModInfo x : t) - model.addRow(new Object[] { x.isActive(), x, x.version }); - reloadingMods = false; - } - }).execute(); - } - } - - private static class OverridableSwingWorkerImpl extends AbstractSwingWorker> { - - @Override - protected void work() throws Exception { - publish(Settings.getLastProfile().service().mod().recacheMods(Settings.getLastProfile().getSelectedVersion())); - } - } - - // - void save() { - VersionSetting vs = Settings.getLastProfile().getSelectedVersionSetting(); - if (txtServerIP.hasFocus()) - vs.setServerIp(txtServerIP.getText()); - if (txtPrecalledCommand.hasFocus()) - vs.setPrecalledCommand(txtPrecalledCommand.getText()); - if (txtPermSize.hasFocus()) - vs.setPermSize(txtPermSize.getText()); - if (txtMinecraftArgs.hasFocus()) - vs.setMinecraftArgs(txtMinecraftArgs.getText()); - if (txtJavaArgs.hasFocus()) - vs.setJavaArgs(txtJavaArgs.getText()); - if (txtJavaDir.hasFocus()) - vs.setJavaDir(txtJavaDir.getText()); - if (txtHeight.hasFocus()) - vs.setHeight(txtHeight.getText()); - if (txtWidth.hasFocus()) - vs.setWidth(txtWidth.getText()); - if (txtMaxMemory.hasFocus()) - vs.setMaxMemory(txtMaxMemory.getText()); - } - - @Override - public void onCreate() { - initGui(); - - super.onCreate(); - Settings.onProfileLoading(); - } - - @Override - public void onLeave() { - super.onLeave(); - save(); - } - - public void showGameDownloads() { - tabVersionEdit.setSelectedComponent(pnlGameDownloads); - } - - // - JPopupMenu ppmManage, ppmExplore; - - DropTarget dropTarget; - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JButton btnAddMod; - private javax.swing.JButton btnChoosingGameDir; - private javax.swing.JButton btnChoosingJavaDir; - private javax.swing.JButton btnCleanGame; - private javax.swing.JButton btnDownloadAllAssets; - private javax.swing.JButton btnExplore; - private javax.swing.JButton btnIncludeMinecraft; - private javax.swing.JButton btnMakeLaunchScript; - private javax.swing.JButton btnModify; - private javax.swing.JButton btnNewProfile; - private javax.swing.JButton btnRefreshVersions; - private javax.swing.JButton btnRemoveMod; - private javax.swing.JButton btnRemoveProfile; - private javax.swing.JButton btnShowLog; - private javax.swing.JButton btnTestGame; - private javax.swing.JComboBox cboJava; - private javax.swing.JComboBox cboLauncherVisibility; - private javax.swing.JComboBox cboProfiles; - private javax.swing.JComboBox cboRunDirectory; - private javax.swing.JComboBox cboVersions; - private javax.swing.JCheckBox chkDontCheckGame; - private javax.swing.JCheckBox chkFullscreen; - private javax.swing.JCheckBox chkNoCommon; - private javax.swing.JCheckBox chkNoJVMArgs; - private javax.swing.JScrollPane jScrollPane1; - private javax.swing.JLabel lblDimension; - private javax.swing.JLabel lblDimensionX; - private javax.swing.JLabel lblGameDir; - private javax.swing.JLabel lblJavaArgs; - private javax.swing.JLabel lblJavaDir; - private javax.swing.JLabel lblLauncherVisibility; - private javax.swing.JLabel lblMaxMemory; - private javax.swing.JLabel lblMaxMemorySize; - private javax.swing.JLabel lblMinecraftArgs; - private javax.swing.JLabel lblModInfo; - private javax.swing.JLabel lblPermSize; - private javax.swing.JLabel lblPrecalledCommand; - private javax.swing.JLabel lblPrecalledCommand1; - private javax.swing.JLabel lblProfile; - private javax.swing.JLabel lblRunDirectory; - private javax.swing.JLabel lblServerIP; - private javax.swing.JLabel lblUsesGlobal; - private javax.swing.JLabel lblVersions; - private javax.swing.JTable lstExternalMods; - private javax.swing.JPanel pnlAdvancedSettings; - private javax.swing.JPanel pnlAutoInstall; - private javax.swing.JPanel pnlManagement; - private javax.swing.JPanel pnlModManagement; - private javax.swing.JPanel pnlModManagementContent; - private javax.swing.JPanel pnlSelection; - private javax.swing.JPanel pnlSettings; - private javax.swing.JPanel pnlTop; - private javax.swing.JTabbedPane tabInstallers; - private javax.swing.JTabbedPane tabVersionEdit; - private javax.swing.JTextField txtGameDir; - private javax.swing.JTextField txtHeight; - private javax.swing.JTextField txtJavaArgs; - private javax.swing.JTextField txtJavaDir; - private javax.swing.JTextField txtMaxMemory; - private javax.swing.JTextField txtMinecraftArgs; - private javax.swing.JTextField txtMinecraftVersion; - private javax.swing.JTextField txtPermSize; - private javax.swing.JTextField txtPrecalledCommand; - private javax.swing.JTextField txtServerIP; - private javax.swing.JTextField txtWidth; - private javax.swing.JTextField txtWrapperLauncher; - // End of variables declaration//GEN-END:variables - - private javax.swing.JPanel pnlGameDownloads; -// - - // - final Runnable onLoadingProfiles = this::loadProfiles; - - private void loadProfiles() { - isLoading = true; - DefaultComboBoxModel model = new DefaultComboBoxModel<>(); - for (Profile s : Settings.getProfilesFiltered()) - model.addElement(s.getName()); - cboProfiles.setModel(model); - isLoading = false; - } - - final Consumer onRefreshedVersions = t -> { - if (Settings.getLastProfile().service().version() == t.getSource()) - loadVersions(); - }; - - void loadVersions() { - DefaultComboBoxModel model = new DefaultComboBoxModel<>(); - for (MinecraftVersion each : Settings.getLastProfile().service().version().getVersions()) { - if (each.hidden) - continue; - model.addElement(each.id); - } - cboVersions.setModel(model); - if (Settings.getLastProfile().getSelectedVersion() != null) - versionChanged(Settings.getLastProfile().getSelectedVersion()); - } - - public void versionChanged(String version) { - isLoading = true; - DefaultComboBoxModel model = (DefaultComboBoxModel) cboVersions.getModel(); - for (int i = 0; i < model.getSize(); ++i) - if (model.getElementAt(i).equals(version)) { - model.setSelectedItem(version); - break; - } - cboVersions.setToolTipText(version); - - this.mcVersion = version; - reloadMods(); - prepareVersionSetting(Settings.getLastProfile(), Settings.getLastProfile().getVersionSetting(version)); - loadMinecraftVersion(version); - - lblUsesGlobal.setText(C.i18n(Settings.getLastProfile().isVersionSettingGlobe(version) ? "settings.type.global" : "settings.type.special")); - for (InstallerPanel p : installerPanels) - p.loadVersions(); - isLoading = false; - } - - final Consumer onSelectedProfilesChanged = event -> { - Profile t = event.getValue(); - t.propertyChanged.register(e -> { - if ("selectedVersion".equals(e.getPropertyName())) - versionChanged(e.getNewValue()); - }); - - txtGameDir.setText(t.getGameDir().getPath()); - - isLoading = true; - DefaultComboBoxModel model = (DefaultComboBoxModel) cboProfiles.getModel(); - for (int i = 0; i < model.getSize(); ++i) - if (model.getElementAt(i).equals(t.getName())) { - model.setSelectedItem(t.getName()); - break; - } - isLoading = false; - }; - // -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/HeaderTab.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/HeaderTab.java deleted file mode 100755 index 826eff9f5..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/HeaderTab.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.ui; - -import java.awt.EventQueue; -import java.awt.event.ActionListener; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import javax.swing.BorderFactory; -import javax.swing.DefaultButtonModel; -import javax.swing.JLabel; - -/** - * - * @author huangyuhui - */ -public class HeaderTab extends JLabel - implements MouseListener { - - private boolean isActive; - private final DefaultButtonModel model; - - public HeaderTab(String text) { - super(text); - - this.model = new DefaultButtonModel(); - setIsActive(false); - - setBorder(BorderFactory.createEmptyBorder(6, 18, 7, 18)); - addMouseListener(this); - } - - public boolean isActive() { - return this.isActive; - } - - public final void setIsActive(boolean isActive) { - this.isActive = isActive; - setOpaque(isActive); - - EventQueue.invokeLater(HeaderTab.this::repaint); - } - - public void addActionListener(ActionListener listener) { - this.model.addActionListener(listener); - } - - public String getActionCommand() { - return this.model.getActionCommand(); - } - - public ActionListener[] getActionListeners() { - return this.model.getActionListeners(); - } - - public void setActionCommand(String command) { - this.model.setActionCommand(command); - } - - @Override - public void mouseClicked(MouseEvent e) { - } - - @Override - public void mousePressed(MouseEvent e) { - if (!isEnabled()) - return; - this.model.setPressed(true); - this.model.setArmed(true); - } - - @Override - public void mouseReleased(MouseEvent e) { - if (!isEnabled()) - return; - this.model.setPressed(false); - this.model.setArmed(false); - } - - @Override - public void mouseEntered(MouseEvent e) { - if (!isEnabled()) - return; - this.model.setRollover(true); - } - - @Override - public void mouseExited(MouseEvent e) { - if (!isEnabled()) - return; - this.model.setRollover(false); - } -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerPanel.form b/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerPanel.form deleted file mode 100755 index fdaca141c..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerPanel.form +++ /dev/null @@ -1,85 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerPanel.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerPanel.java deleted file mode 100755 index c26a3c7be..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/InstallerPanel.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.ui; - -import org.jackhuang.hmcl.util.ui.Page; -import java.util.List; -import javax.swing.SwingUtilities; -import javax.swing.table.DefaultTableModel; -import org.jackhuang.hmcl.api.ui.TopTabPage; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.setting.Settings; -import org.jackhuang.hmcl.core.install.InstallerType; -import org.jackhuang.hmcl.core.install.InstallerVersionList; -import org.jackhuang.hmcl.util.task.TaskRunnable; -import org.jackhuang.hmcl.util.task.TaskWindow; -import org.jackhuang.hmcl.util.ui.MessageBox; -import org.jackhuang.hmcl.util.StrUtils; -import org.jackhuang.hmcl.util.task.ProgressProviderListener; -import org.jackhuang.hmcl.util.task.Task; -import org.jackhuang.hmcl.util.ui.SwingUtils; - -/** - * - * @author huangyuhui - */ -public class InstallerPanel extends Page implements ProgressProviderListener { - - GameSettingsPanel gsp; - - /** - * Creates new form InstallerPanel - * - * @param gsp To get the minecraft version - * @param installerType load which installer - */ - public InstallerPanel(GameSettingsPanel gsp, InstallerType installerType) { - initComponents(); - - animationEnabled = Settings.getInstance().isEnableAnimation(); - - setOpaque(false); - this.gsp = gsp; - id = installerType; - list = Settings.getInstance().getDownloadSource().getProvider().getInstallerByType(id); - } - - /** - * This method is called from within the constructor to initialize the form. - * WARNING: Do NOT modify this code. The content of this method is always - * regenerated by the Form Editor. - */ - @SuppressWarnings("unchecked") - // //GEN-BEGIN:initComponents - private void initComponents() { - - btnInstall = new javax.swing.JButton(); - jScrollPane12 = new javax.swing.JScrollPane(); - lstInstallers = new javax.swing.JTable(); - btnRefresh = new javax.swing.JButton(); - - btnInstall.setText(C.i18n("ui.button.install")); // NOI18N - btnInstall.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnInstallActionPerformed(evt); - } - }); - - lstInstallers.setModel(SwingUtils.makeDefaultTableModel(new String[]{C.i18n("install.version"), C.i18n("install.mcversion")}, - new Class[]{String.class, String.class}, new boolean[]{false, false})); - lstInstallers.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); - jScrollPane12.setViewportView(lstInstallers); - - btnRefresh.setText(C.i18n("ui.button.refresh")); // NOI18N - btnRefresh.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnRefreshActionPerformed(evt); - } - }); - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); - this.setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(jScrollPane12, javax.swing.GroupLayout.DEFAULT_SIZE, 292, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(btnRefresh, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(btnInstall, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane12, javax.swing.GroupLayout.DEFAULT_SIZE, 147, Short.MAX_VALUE) - .addGroup(layout.createSequentialGroup() - .addComponent(btnInstall) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnRefresh) - .addGap(0, 0, Short.MAX_VALUE)) - ); - }// //GEN-END:initComponents - - private void btnInstallActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnInstallActionPerformed - downloadSelectedRow(); - }//GEN-LAST:event_btnInstallActionPerformed - - private void btnRefreshActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRefreshActionPerformed - refreshVersions(); - }//GEN-LAST:event_btnRefreshActionPerformed - - transient List versions; - InstallerVersionList list; - InstallerType id; - - void refreshVersions() { - if (loading) - return; - Task t = list.refresh(new String[] { gsp.getMinecraftVersionFormatted() }); - if (t != null) { - loading = true; - DefaultTableModel model = SwingUtils.clearDefaultTable(lstInstallers); - model.addRow(new Object[] { C.i18n("message.loading"), "", "" }); - t.with(new TaskRunnable(this::loadVersions)).setProgressProviderListener(this).runAsync(); - } - } - - boolean loading = false; - - @Override - public void setProgress(Task task, int prog, int max) { - DefaultTableModel model = (DefaultTableModel) lstInstallers.getModel(); - if (model.getRowCount() > 0) - model.setValueAt(C.i18n("message.loading") + " " + (prog < 0 ? "???" : Integer.toString(prog * 100 / max) + "%"), 0, 0); - } - - @Override - public void setStatus(Task task, String sta) { - } - - @Override - public void onProgressProviderDone(Task task) { - loading = false; - DefaultTableModel model = (DefaultTableModel) lstInstallers.getModel(); - if (model.getRowCount() > 0) - model.removeRow(0); - } - - public synchronized InstallerVersionList.InstallerVersion getVersion(int idx) { - return versions.get(idx); - } - - synchronized void downloadSelectedRow() { - int idx = lstInstallers.getSelectedRow(); - if (versions == null || idx < 0 || idx >= versions.size()) { - MessageBox.show(C.i18n("install.not_refreshed")); - return; - } - TaskWindow.factory() - .append(Settings.getLastProfile().service().install().download(Settings.getLastProfile().getSelectedVersion(), getVersion(idx), id)) - .append(new TaskRunnable(() -> gsp.refreshVersions())) - .execute(); - } - - public void loadVersions() { - SwingUtilities.invokeLater(() -> { - synchronized (InstallerPanel.this) { - DefaultTableModel model = (DefaultTableModel) lstInstallers.getModel(); - String mcver = StrUtils.formatVersion(gsp.getMinecraftVersionFormatted()); - versions = list.getVersions(mcver); - SwingUtils.clearDefaultTable(lstInstallers); - if (versions != null) - for (InstallerVersionList.InstallerVersion v : versions) - if (v != null) - model.addRow(new Object[] { v.selfVersion == null ? "null" : v.selfVersion, v.mcVersion == null ? "null" : v.mcVersion }); - } - }); - } - - boolean refreshed = false; - - @Override - public void onSelect(TopTabPage page) { - super.onSelect(page); - if (!refreshed) { - refreshVersions(); - refreshed = true; - } - } - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JButton btnInstall; - private javax.swing.JButton btnRefresh; - private javax.swing.JScrollPane jScrollPane12; - private javax.swing.JTable lstInstallers; - // End of variables declaration//GEN-END:variables -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/JLineWrapTextPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/JLineWrapTextPane.java deleted file mode 100644 index 3223aede7..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/JLineWrapTextPane.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.ui; - -import javax.swing.JTextPane; -import javax.swing.text.AbstractDocument; -import javax.swing.text.BoxView; -import javax.swing.text.ComponentView; -import javax.swing.text.Element; -import javax.swing.text.IconView; -import javax.swing.text.LabelView; -import javax.swing.text.ParagraphView; -import javax.swing.text.StyleConstants; -import javax.swing.text.StyledEditorKit; -import javax.swing.text.View; -import javax.swing.text.ViewFactory; - -/** - * - * @author huang - */ -public class JLineWrapTextPane extends JTextPane { - - // 内部类 - // 以下内部类全都用于实现自动强制折行 - - private class WarpEditorKit extends StyledEditorKit { - - private ViewFactory defaultFactory = new WarpColumnFactory(); - - @Override - public ViewFactory getViewFactory() { - return defaultFactory; - } - } - - private class WarpColumnFactory implements ViewFactory { - - public View create(Element elem) { - String kind = elem.getName(); - if (kind != null) { - if (kind.equals(AbstractDocument.ContentElementName)) { - return new WarpLabelView(elem); - } else if (kind.equals(AbstractDocument.ParagraphElementName)) { - return new ParagraphView(elem); - } else if (kind.equals(AbstractDocument.SectionElementName)) { - return new BoxView(elem, View.Y_AXIS); - } else if (kind.equals(StyleConstants.ComponentElementName)) { - return new ComponentView(elem); - } else if (kind.equals(StyleConstants.IconElementName)) { - return new IconView(elem); - } - } - - // default to text display - return new LabelView(elem); - } - } - - private class WarpLabelView extends LabelView { - - public WarpLabelView(Element elem) { - super(elem); - } - - @Override - public float getMinimumSpan(int axis) { - switch (axis) { - case View.X_AXIS: - return 0; - case View.Y_AXIS: - return super.getMinimumSpan(axis); - default: - throw new IllegalArgumentException("Invalid axis: " + axis); - } - } - } - - // 本类 - - // 构造函数 - public JLineWrapTextPane() { - super(); - this.setEditorKit(new WarpEditorKit()); - } -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LauncherSettingsPanel.form b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LauncherSettingsPanel.form deleted file mode 100755 index ca54d8164..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LauncherSettingsPanel.form +++ /dev/null @@ -1,582 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LauncherSettingsPanel.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LauncherSettingsPanel.java deleted file mode 100755 index bf483192f..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LauncherSettingsPanel.java +++ /dev/null @@ -1,655 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.ui; - -import java.io.IOException; -import javax.swing.DefaultComboBoxModel; -import javax.swing.filechooser.FileNameExtensionFilter; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.api.ui.Theme; -import org.jackhuang.hmcl.setting.Settings; -import org.jackhuang.hmcl.core.download.DownloadType; -import org.jackhuang.hmcl.util.MathUtils; -import org.jackhuang.hmcl.util.sys.IOUtils; -import org.jackhuang.hmcl.util.ui.MessageBox; -import org.jackhuang.hmcl.util.lang.SupportedLocales; -import org.jackhuang.hmcl.util.ui.JFontComboBox; -import org.jackhuang.hmcl.util.ui.JSystemFileChooser; -import org.jackhuang.hmcl.util.ui.Page; -import org.jackhuang.hmcl.util.ui.SwingUtils; - -/** - * - * @author huangyuhui - */ -public class LauncherSettingsPanel extends RepaintPage { - - public LauncherSettingsPanel() { - setRepainter(this); - } - - void initGui() { - initComponents(); - - animationEnabled = Settings.getInstance().isEnableAnimation(); - - DefaultComboBoxModel d = new DefaultComboBoxModel<>(); - for (DownloadType type : DownloadType.values()) - d.addElement(type.getName()); - cboDownloadSource.setModel(d); - - d = new DefaultComboBoxModel<>(); - int id = 0; - for (SupportedLocales type : SupportedLocales.values()) { - d.addElement(type.showString()); - if (type.name().equals(Settings.getInstance().getLocalization())) - id = type.ordinal(); - } - cboLang.setModel(d); - cboLang.setSelectedIndex(id); - - DefaultComboBoxModel g = new DefaultComboBoxModel<>(); - for (Theme t : Theme.THEMES.values()) - g.addElement(t); - cboTheme.setModel(g); - - txtBackgroundPath.setText(Settings.getInstance().getBgpath()); - txtCommonPath.setText(Settings.getInstance().getCommonpath()); - txtProxyHost.setText(Settings.getInstance().getProxyHost()); - txtProxyPort.setText(Settings.getInstance().getProxyPort()); - txtProxyUsername.setText(Settings.getInstance().getProxyUserName()); - txtProxyPassword.setText(Settings.getInstance().getProxyPassword()); - spinnerFontSize.setValue(Settings.getInstance().getFontSize()); - cboFontFamily.setSelectedItem(Settings.getInstance().getFontFamily()); - cboDownloadSource.setSelectedIndex(Settings.getInstance().getDownloadType()); - cboTheme.setSelectedItem(Settings.getInstance().getTheme()); - chkEnableShadow.setSelected(Settings.getInstance().isEnableShadow()); - chkEnableBlur.setSelected(Settings.getInstance().isEnableBlur()); - chkEnableAnimation.setSelected(Settings.getInstance().isEnableAnimation()); - chkDecorated.setSelected(Settings.getInstance().isDecorated()); - } - - @Override - public void onCreate() { - initGui(); - super.onCreate(); - } - - /** - * This method is called from within the constructor to initialize the form. - * WARNING: Do NOT modify this code. The content of this method is always - * regenerated by the Form Editor. - */ - @SuppressWarnings("unchecked") - // //GEN-BEGIN:initComponents - private void initComponents() { - - lblModpack = new javax.swing.JLabel(); - lblRestart = new javax.swing.JLabel(); - tabLauncherSettings = new NewTabPane(); - pnlGeneral = new Page().setAnimationEnabled(Settings.getInstance().isEnableAnimation()); - lblProxy = new javax.swing.JLabel(); - lblProxyHost = new javax.swing.JLabel(); - txtProxyHost = new javax.swing.JTextField(); - lblProxyPort = new javax.swing.JLabel(); - txtProxyPort = new javax.swing.JTextField(); - lblProxyUserName = new javax.swing.JLabel(); - txtProxyUsername = new javax.swing.JTextField(); - lblProxyPassword = new javax.swing.JLabel(); - txtProxyPassword = new javax.swing.JTextField(); - cboDownloadSource = new javax.swing.JComboBox(); - lblDownloadSource = new javax.swing.JLabel(); - lblCommonPath = new javax.swing.JLabel(); - txtCommonPath = new javax.swing.JTextField(); - btnSetCommonPath = new javax.swing.JButton(); - btnCheckUpdate = new javax.swing.JButton(); - btnMCBBS = new javax.swing.JButton(); - cboLang = new javax.swing.JComboBox(); - lblLang = new javax.swing.JLabel(); - pnlUI = new Page().setAnimationEnabled(Settings.getInstance().isEnableAnimation()); - lblTheme = new javax.swing.JLabel(); - cboTheme = new javax.swing.JComboBox(); - lblBackground = new javax.swing.JLabel(); - txtBackgroundPath = new javax.swing.JTextField(); - chkEnableShadow = new javax.swing.JCheckBox(); - chkEnableBlur = new javax.swing.JCheckBox(); - chkEnableAnimation = new javax.swing.JCheckBox(); - chkDecorated = new javax.swing.JCheckBox(); - btnSelBackgroundPath = new javax.swing.JButton(); - cboFontFamily = new JFontComboBox(); - lblFont = new javax.swing.JLabel(); - spinnerFontSize = new javax.swing.JSpinner(); - lblExample = new javax.swing.JLabel(); - pnlAbout = new Page().setAnimationEnabled(Settings.getInstance().isEnableAnimation()); - lblAbout = new javax.swing.JLabel(); - - lblModpack.setText(C.i18n("launcher.modpack")); // NOI18N - lblModpack.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR)); - lblModpack.addMouseListener(new java.awt.event.MouseAdapter() { - public void mouseClicked(java.awt.event.MouseEvent evt) { - lblModpackMouseClicked(evt); - } - }); - - lblRestart.setText(C.i18n("launcher.restart")); // NOI18N - - lblProxy.setText(C.i18n("launcher.proxy")); // NOI18N - - lblProxyHost.setText(C.i18n("proxy.host")); // NOI18N - - txtProxyHost.addFocusListener(new java.awt.event.FocusAdapter() { - public void focusLost(java.awt.event.FocusEvent evt) { - txtProxyHostFocusLost(evt); - } - }); - - lblProxyPort.setText(C.i18n("proxy.port")); // NOI18N - - txtProxyPort.addFocusListener(new java.awt.event.FocusAdapter() { - public void focusLost(java.awt.event.FocusEvent evt) { - txtProxyPortFocusLost(evt); - } - }); - - lblProxyUserName.setText(C.i18n("proxy.username")); // NOI18N - - txtProxyUsername.addFocusListener(new java.awt.event.FocusAdapter() { - public void focusLost(java.awt.event.FocusEvent evt) { - txtProxyUsernameFocusLost(evt); - } - }); - - lblProxyPassword.setText(C.i18n("proxy.password")); // NOI18N - - txtProxyPassword.addFocusListener(new java.awt.event.FocusAdapter() { - public void focusLost(java.awt.event.FocusEvent evt) { - txtProxyPasswordFocusLost(evt); - } - }); - - cboDownloadSource.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - cboDownloadSourceItemStateChanged(evt); - } - }); - - lblDownloadSource.setText(C.i18n("launcher.download_source")); // NOI18N - - lblCommonPath.setText(C.i18n("launcher.common_location")); // NOI18N - - txtCommonPath.setToolTipText(C.i18n("launcher.commpath_tooltip")); // NOI18N - txtCommonPath.addFocusListener(new java.awt.event.FocusAdapter() { - public void focusLost(java.awt.event.FocusEvent evt) { - txtCommonPathFocusLost(evt); - } - }); - - btnSetCommonPath.setText(C.i18n("ui.button.explore")); // NOI18N - btnSetCommonPath.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnSetCommonPathActionPerformed(evt); - } - }); - - btnCheckUpdate.setText(C.i18n("launcher.update_launcher")); // NOI18N - btnCheckUpdate.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnCheckUpdateActionPerformed(evt); - } - }); - - btnMCBBS.setText("MCBBS"); - btnMCBBS.setToolTipText(""); - btnMCBBS.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnMCBBSActionPerformed(evt); - } - }); - - cboLang.setModel(new DefaultComboBoxModel(new String[]{C.i18n("color.blue"),C.i18n("color.green"),C.i18n("color.purple"),C.i18n("color.dark_blue"),C.i18n("color.orange"),C.i18n("color.red")})); - cboLang.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - cboLangItemStateChanged(evt); - } - }); - - lblLang.setText(C.i18n("launcher.lang")); // NOI18N - - javax.swing.GroupLayout pnlGeneralLayout = new javax.swing.GroupLayout(pnlGeneral); - pnlGeneral.setLayout(pnlGeneralLayout); - pnlGeneralLayout.setHorizontalGroup( - pnlGeneralLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnlGeneralLayout.createSequentialGroup() - .addContainerGap() - .addGroup(pnlGeneralLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnlGeneralLayout.createSequentialGroup() - .addComponent(btnCheckUpdate) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnMCBBS) - .addGap(0, 418, Short.MAX_VALUE)) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnlGeneralLayout.createSequentialGroup() - .addComponent(lblProxy) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(lblProxyHost) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(txtProxyHost, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(lblProxyPort) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(txtProxyPort, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(lblProxyUserName) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(txtProxyUsername, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(lblProxyPassword) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(txtProxyPassword, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGroup(pnlGeneralLayout.createSequentialGroup() - .addGroup(pnlGeneralLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(lblDownloadSource) - .addComponent(lblCommonPath) - .addComponent(lblLang)) - .addGap(28, 28, 28) - .addGroup(pnlGeneralLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(cboLang, javax.swing.GroupLayout.Alignment.TRAILING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(pnlGeneralLayout.createSequentialGroup() - .addComponent(txtCommonPath) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnSetCommonPath)) - .addComponent(cboDownloadSource, javax.swing.GroupLayout.Alignment.TRAILING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))) - .addContainerGap()) - ); - pnlGeneralLayout.setVerticalGroup( - pnlGeneralLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnlGeneralLayout.createSequentialGroup() - .addContainerGap() - .addGroup(pnlGeneralLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(lblCommonPath) - .addComponent(txtCommonPath, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(btnSetCommonPath, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(pnlGeneralLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(lblDownloadSource) - .addComponent(cboDownloadSource, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(pnlGeneralLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(cboLang, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblLang)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(pnlGeneralLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(txtProxyHost, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblProxy) - .addComponent(lblProxyHost) - .addComponent(txtProxyPort, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblProxyPort) - .addComponent(txtProxyUsername, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblProxyUserName) - .addComponent(txtProxyPassword, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblProxyPassword)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 69, Short.MAX_VALUE) - .addGroup(pnlGeneralLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(btnCheckUpdate, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(btnMCBBS, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addContainerGap()) - ); - - tabLauncherSettings.addTab(C.i18n("launcher.tab.general"), pnlGeneral); // NOI18N - - lblTheme.setText(C.i18n("launcher.theme")); // NOI18N - - cboTheme.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - cboThemeItemStateChanged(evt); - } - }); - - lblBackground.setText(C.i18n("launcher.background_location")); // NOI18N - lblBackground.setToolTipText(""); - - txtBackgroundPath.setToolTipText(C.i18n("launcher.background_tooltip")); // NOI18N - txtBackgroundPath.addFocusListener(new java.awt.event.FocusAdapter() { - public void focusLost(java.awt.event.FocusEvent evt) { - txtBackgroundPathFocusLost(evt); - } - }); - - chkEnableShadow.setText(C.i18n("launcher.enable_shadow")); // NOI18N - chkEnableShadow.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - chkEnableShadowItemStateChanged(evt); - } - }); - - chkEnableBlur.setText(C.i18n("launcher.enable_blur")); // NOI18N - chkEnableBlur.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - chkEnableBlurItemStateChanged(evt); - } - }); - - chkEnableAnimation.setText(C.i18n("launcher.enable_animation")); // NOI18N - chkEnableAnimation.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - chkEnableAnimationItemStateChanged(evt); - } - }); - - chkDecorated.setText(C.i18n("launcher.decorated")); // NOI18N - chkDecorated.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - chkDecoratedItemStateChanged(evt); - } - }); - - btnSelBackgroundPath.setText(C.i18n("ui.button.explore")); // NOI18N - btnSelBackgroundPath.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnSelBackgroundPathActionPerformed(evt); - } - }); - - cboFontFamily.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - cboFontFamilyItemStateChanged(evt); - } - }); - - lblFont.setText(C.i18n("launcher.log_font")); // NOI18N - - spinnerFontSize.addChangeListener(new javax.swing.event.ChangeListener() { - public void stateChanged(javax.swing.event.ChangeEvent evt) { - spinnerFontSizeStateChanged(evt); - } - }); - - lblExample.setText("19:10:10 [Client Thread/INFO]: Example"); - - javax.swing.GroupLayout pnlUILayout = new javax.swing.GroupLayout(pnlUI); - pnlUI.setLayout(pnlUILayout); - pnlUILayout.setHorizontalGroup( - pnlUILayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnlUILayout.createSequentialGroup() - .addContainerGap() - .addGroup(pnlUILayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnlUILayout.createSequentialGroup() - .addGroup(pnlUILayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(chkDecorated) - .addGroup(pnlUILayout.createSequentialGroup() - .addComponent(chkEnableShadow) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(chkEnableBlur) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(chkEnableAnimation))) - .addGap(0, 15, Short.MAX_VALUE)) - .addGroup(pnlUILayout.createSequentialGroup() - .addGroup(pnlUILayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(lblBackground) - .addComponent(lblFont) - .addComponent(lblTheme)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(pnlUILayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(cboTheme, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(pnlUILayout.createSequentialGroup() - .addGroup(pnlUILayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(txtBackgroundPath) - .addComponent(cboFontFamily, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(pnlUILayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(btnSelBackgroundPath, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(spinnerFontSize))) - .addGroup(pnlUILayout.createSequentialGroup() - .addComponent(lblExample) - .addGap(0, 0, Short.MAX_VALUE))))) - .addContainerGap()) - ); - pnlUILayout.setVerticalGroup( - pnlUILayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnlUILayout.createSequentialGroup() - .addContainerGap() - .addGroup(pnlUILayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(lblBackground) - .addComponent(txtBackgroundPath, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(btnSelBackgroundPath, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(pnlUILayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(cboFontFamily, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblFont) - .addComponent(spinnerFontSize, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(lblExample) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(pnlUILayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(cboTheme, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblTheme)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 63, Short.MAX_VALUE) - .addGroup(pnlUILayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(chkEnableShadow) - .addComponent(chkEnableBlur) - .addComponent(chkEnableAnimation)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(chkDecorated) - .addContainerGap()) - ); - - tabLauncherSettings.addTab(C.i18n("launcher.tab.ui"), pnlUI); // NOI18N - - lblAbout.setText(C.i18n("launcher.about")); // NOI18N - lblAbout.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR)); - - javax.swing.GroupLayout pnlAboutLayout = new javax.swing.GroupLayout(pnlAbout); - pnlAbout.setLayout(pnlAboutLayout); - pnlAboutLayout.setHorizontalGroup( - pnlAboutLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnlAboutLayout.createSequentialGroup() - .addContainerGap() - .addComponent(lblAbout, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(104, Short.MAX_VALUE)) - ); - pnlAboutLayout.setVerticalGroup( - pnlAboutLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnlAboutLayout.createSequentialGroup() - .addContainerGap() - .addComponent(lblAbout, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - ); - - tabLauncherSettings.addTab(C.i18n("launcher.tab.about"), pnlAbout); // NOI18N - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); - this.setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addGap(10, 10, 10) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(lblModpack, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblRestart)) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addComponent(tabLauncherSettings) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(tabLauncherSettings) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(lblModpack, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(lblRestart) - .addContainerGap()) - ); - - tabLauncherSettings.getAccessibleContext().setAccessibleName(""); - }// //GEN-END:initComponents - - private void cboDownloadSourceItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboDownloadSourceItemStateChanged - Settings.getInstance().setDownloadType(cboDownloadSource.getSelectedIndex()); - }//GEN-LAST:event_cboDownloadSourceItemStateChanged - - private void btnSelBackgroundPathActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSelBackgroundPathActionPerformed - JSystemFileChooser fc = new JSystemFileChooser(); - fc.setFileSelectionMode(JSystemFileChooser.FILES_ONLY); - fc.setDialogTitle(C.i18n("launcher.choose_bgpath")); - fc.setMultiSelectionEnabled(false); - fc.setFileFilter(new FileNameExtensionFilter("*.png", "png")); - fc.addChoosableFileFilter(new FileNameExtensionFilter("*.jpg", "jpg")); - if (fc.showOpenDialog(this) != JSystemFileChooser.APPROVE_OPTION || fc.getSelectedFile() == null) - return; - try { - String path = fc.getSelectedFile().getCanonicalPath(); - path = IOUtils.removeLastSeparator(path); - txtBackgroundPath.setText(path); - Settings.getInstance().setBgpath(path); - MainFrame.INSTANCE.loadBackground(); - } catch (IOException e) { - HMCLog.warn("Failed to set background path.", e); - MessageBox.show(C.i18n("ui.label.failed_set") + e.getMessage()); - } - }//GEN-LAST:event_btnSelBackgroundPathActionPerformed - - private void txtBackgroundPathFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtBackgroundPathFocusLost - Settings.getInstance().setBgpath(txtBackgroundPath.getText()); - MainFrame.INSTANCE.loadBackground(); - }//GEN-LAST:event_txtBackgroundPathFocusLost - - private void btnCheckUpdateActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCheckUpdateActionPerformed - Settings.UPDATE_CHECKER.process(true); - Settings.UPDATE_CHECKER.checkOutdate(); - }//GEN-LAST:event_btnCheckUpdateActionPerformed - - private void cboThemeItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboThemeItemStateChanged - Settings.getInstance().setTheme(((Theme) cboTheme.getSelectedItem()).id); - }//GEN-LAST:event_cboThemeItemStateChanged - - private void lblModpackMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_lblModpackMouseClicked - SwingUtils.openLink("http://huangyuhui.duapp.com/link.php?type=modpack"); - }//GEN-LAST:event_lblModpackMouseClicked - - private void cboLangItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboLangItemStateChanged - Settings.getInstance().setLocalization(SupportedLocales.values()[cboLang.getSelectedIndex()].name()); - }//GEN-LAST:event_cboLangItemStateChanged - - private void chkEnableShadowItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_chkEnableShadowItemStateChanged - Settings.getInstance().setEnableShadow(chkEnableShadow.isSelected()); - }//GEN-LAST:event_chkEnableShadowItemStateChanged - - private void chkDecoratedItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_chkDecoratedItemStateChanged - Settings.getInstance().setDecorated(chkDecorated.isSelected()); - }//GEN-LAST:event_chkDecoratedItemStateChanged - - private void txtProxyHostFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtProxyHostFocusLost - Settings.getInstance().setProxyHost(txtProxyHost.getText()); - }//GEN-LAST:event_txtProxyHostFocusLost - - private void txtProxyPortFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtProxyPortFocusLost - Settings.getInstance().setProxyPort(txtProxyPort.getText()); - }//GEN-LAST:event_txtProxyPortFocusLost - - private void txtProxyUsernameFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtProxyUsernameFocusLost - Settings.getInstance().setProxyUserName(txtProxyUsername.getText()); - }//GEN-LAST:event_txtProxyUsernameFocusLost - - private void txtProxyPasswordFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtProxyPasswordFocusLost - Settings.getInstance().setProxyPassword(txtProxyPassword.getText()); - }//GEN-LAST:event_txtProxyPasswordFocusLost - - private void btnMCBBSActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnMCBBSActionPerformed - SwingUtils.openLink(C.URL_PUBLISH); - }//GEN-LAST:event_btnMCBBSActionPerformed - - private void chkEnableBlurItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_chkEnableBlurItemStateChanged - Settings.getInstance().setEnableBlur(chkEnableBlur.isSelected()); - }//GEN-LAST:event_chkEnableBlurItemStateChanged - - private void chkEnableAnimationItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_chkEnableAnimationItemStateChanged - Settings.getInstance().setEnableAnimation(chkEnableAnimation.isSelected()); - }//GEN-LAST:event_chkEnableAnimationItemStateChanged - - private void btnSetCommonPathActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSetCommonPathActionPerformed - JSystemFileChooser fc = new JSystemFileChooser(); - fc.setFileSelectionMode(JSystemFileChooser.DIRECTORIES_ONLY); - fc.setDialogTitle(C.i18n("launcher.choose_commonpath")); - fc.setMultiSelectionEnabled(false); - if (fc.showOpenDialog(this) != JSystemFileChooser.APPROVE_OPTION || fc.getSelectedFile() == null) - return; - try { - String path = fc.getSelectedFile().getCanonicalPath(); - txtCommonPath.setText(path); - Settings.getInstance().setCommonpath(path); - } catch (IOException e) { - HMCLog.warn("Failed to set common path.", e); - MessageBox.show(C.i18n("ui.label.failed_set") + e.getMessage()); - } - }//GEN-LAST:event_btnSetCommonPathActionPerformed - - private void txtCommonPathFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtCommonPathFocusLost - Settings.getInstance().setCommonpath(txtCommonPath.getText()); - }//GEN-LAST:event_txtCommonPathFocusLost - - private void cboFontFamilyItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboFontFamilyItemStateChanged - Settings.getInstance().setFontFamily(evt.getItem().toString()); - lblExample.setFont(Settings.getInstance().getConsoleFont()); - }//GEN-LAST:event_cboFontFamilyItemStateChanged - - private void spinnerFontSizeStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spinnerFontSizeStateChanged - Settings.getInstance().setFontSize(MathUtils.parseInt(spinnerFontSize.getValue().toString(), 12)); - lblExample.setFont(Settings.getInstance().getConsoleFont()); - }//GEN-LAST:event_spinnerFontSizeStateChanged - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JButton btnCheckUpdate; - private javax.swing.JButton btnMCBBS; - private javax.swing.JButton btnSelBackgroundPath; - private javax.swing.JButton btnSetCommonPath; - private javax.swing.JComboBox cboDownloadSource; - private javax.swing.JComboBox cboFontFamily; - private javax.swing.JComboBox cboLang; - private javax.swing.JComboBox cboTheme; - private javax.swing.JCheckBox chkDecorated; - private javax.swing.JCheckBox chkEnableAnimation; - private javax.swing.JCheckBox chkEnableBlur; - private javax.swing.JCheckBox chkEnableShadow; - private javax.swing.JLabel lblAbout; - private javax.swing.JLabel lblBackground; - private javax.swing.JLabel lblCommonPath; - private javax.swing.JLabel lblDownloadSource; - private javax.swing.JLabel lblExample; - private javax.swing.JLabel lblFont; - private javax.swing.JLabel lblLang; - private javax.swing.JLabel lblModpack; - private javax.swing.JLabel lblProxy; - private javax.swing.JLabel lblProxyHost; - private javax.swing.JLabel lblProxyPassword; - private javax.swing.JLabel lblProxyPort; - private javax.swing.JLabel lblProxyUserName; - private javax.swing.JLabel lblRestart; - private javax.swing.JLabel lblTheme; - private javax.swing.JPanel pnlAbout; - private javax.swing.JPanel pnlGeneral; - private javax.swing.JPanel pnlUI; - private javax.swing.JSpinner spinnerFontSize; - private javax.swing.JTabbedPane tabLauncherSettings; - private javax.swing.JTextField txtBackgroundPath; - private javax.swing.JTextField txtCommonPath; - private javax.swing.JTextField txtProxyHost; - private javax.swing.JTextField txtProxyPassword; - private javax.swing.JTextField txtProxyPort; - private javax.swing.JTextField txtProxyUsername; - // End of variables declaration//GEN-END:variables -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LaunchingUIDaemon.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LaunchingUIDaemon.java deleted file mode 100644 index eea6425df..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LaunchingUIDaemon.java +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.ui; - -import java.io.File; -import java.io.IOException; -import java.io.PipedOutputStream; -import javax.swing.SwingUtilities; -import org.jackhuang.hmcl.api.HMCLApi; -import org.jackhuang.hmcl.api.event.process.JVMLaunchFailedEvent; -import org.jackhuang.hmcl.api.event.process.JavaProcessExitedAbnormallyEvent; -import org.jackhuang.hmcl.api.event.process.JavaProcessStoppedEvent; -import org.jackhuang.hmcl.api.event.launch.LaunchEvent; -import org.jackhuang.hmcl.api.event.launch.LaunchSucceededEvent; -import org.jackhuang.hmcl.api.event.launch.LaunchingStateChangedEvent; -import org.jackhuang.hmcl.util.LauncherVisibility; -import org.jackhuang.hmcl.core.launch.GameLauncher; -import org.jackhuang.hmcl.setting.Profile; -import org.jackhuang.hmcl.setting.Settings; -import org.jackhuang.hmcl.util.HMCLGameLauncher; -import org.jackhuang.hmcl.util.MinecraftCrashAdvicer; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.util.ui.MessageBox; -import org.jackhuang.hmcl.api.func.Consumer; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.api.event.launch.LaunchingState; -import org.jackhuang.hmcl.util.DefaultPlugin; -import org.jackhuang.hmcl.util.Log4jHandler; -import org.jackhuang.hmcl.util.StrUtils; -import org.jackhuang.hmcl.util.sys.FileUtils; -import org.jackhuang.hmcl.util.sys.PrintlnEvent; -import org.jackhuang.hmcl.util.sys.ProcessMonitor; -import org.xml.sax.XMLReader; - -/** - * - * @author huangyuhui - */ -public class LaunchingUIDaemon { - - XMLReader reader; - - public LaunchingUIDaemon() { - HMCLApi.EVENT_BUS.channel(LaunchingStateChangedEvent.class).register(LAUNCHING_STATE_CHANGED); - HMCLApi.EVENT_BUS.channel(LaunchEvent.class).register(p -> { - GameLauncher obj = (GameLauncher) p.getSource(); - HMCLGameLauncher.GameLauncherTag tag = (HMCLGameLauncher.GameLauncherTag) obj.getTag(); - if (tag.launcherVisibility == LauncherVisibility.CLOSE && !LogWindow.INSTANCE.isVisible()) { - HMCLog.log("Without the option of keeping the launcher visible, this application will exit and will NOT catch game logs, but you can turn on \"Debug Mode\"."); - System.exit(0); - } else if (tag.launcherVisibility == LauncherVisibility.KEEP) - MainFrame.INSTANCE.closeMessage(); - else { - if (LogWindow.INSTANCE.isVisible()) - LogWindow.INSTANCE.setExit(() -> true); - HMCLApi.EVENT_BUS.fireChannel(new LaunchingStateChangedEvent(obj, LaunchingState.WaitingForGameLaunching)); - } - // We promise that JavaProcessMonitor.tag is LauncherVisibility - // See events below. - ProcessMonitor monitor = new ProcessMonitor(p.getValue()); - PipedOutputStream os = new PipedOutputStream(); - monitor.setTag(obj); - try { - Log4jHandler handler = new Log4jHandler(monitor, os); - handler.addForbiddenToken(obj.getLoginResult().getAccessToken(), ""); - handler.addForbiddenToken(obj.getLoginResult().getSession(), ""); - handler.addForbiddenToken(obj.getLoginResult().getUserId(), ""); - handler.addForbiddenToken("Setting user: " + obj.getLoginResult().getUserName(), ""); - handler.start(); - } catch(Exception e) { - HMCLog.err("", e); - } - monitor.registerPrintlnEvent(new PrintlnProcessor(obj, os)); - monitor.start(); - }); - HMCLApi.EVENT_BUS.channel(LaunchSucceededEvent.class).register(p -> { - int state = ((HMCLGameLauncher.GameLauncherTag) ((GameLauncher) p.getSource()).getTag()).state; - if (state == 1) - LAUNCH_FINISHER.accept(p); - else if (state == 2) - LAUNCH_SCRIPT_FINISHER.accept(p); - }); - HMCLApi.EVENT_BUS.channel(JavaProcessStoppedEvent.class).register(event -> { - GameLauncher launcher = ((GameLauncher) ((ProcessMonitor) event.getSource()).getTag()); - HMCLApi.EVENT_BUS.fireChannel(new LaunchingStateChangedEvent(launcher, LaunchingState.Done)); - checkExit(unpackProcessMonitor(event.getSource())); - }); - HMCLApi.EVENT_BUS.channel(JavaProcessExitedAbnormallyEvent.class).register(event -> { - ProcessMonitor monitor = (ProcessMonitor) event.getSource(); - int exitCode = event.getValue().getExitCode(); - HMCLog.err("The game exited abnormally, exit code: " + exitCode); - monitor.waitForCommandLineCompletion(); - String[] logs = event.getValue().getStdOutLines().toArray(new String[0]); - String errorText = null; - for (String s : logs) { - int pos = s.lastIndexOf("#@!@#"); - if (pos >= 0 && pos < s.length() - "#@!@#".length() - 1) { - errorText = s.substring(pos + "#@!@#".length()).trim(); - break; - } - } - String msg = C.i18n("launch.exited_abnormally") + " exit code: " + exitCode; - if (errorText != null) - msg += ", advice: " + MinecraftCrashAdvicer.getAdvice(FileUtils.readQuietly(new File(errorText))); - HMCLog.err(msg); - SwingUtilities.invokeLater(() -> LogWindow.INSTANCE.setVisible(true)); - noExitThisTime = true; - }); - HMCLApi.EVENT_BUS.channel(JVMLaunchFailedEvent.class).register(event -> { - int exitCode = event.getValue().getExitCode(); - HMCLog.err("Cannot create jvm, exit code: " + exitCode); - SwingUtilities.invokeLater(() -> LogWindow.INSTANCE.setVisible(true)); - noExitThisTime = true; - }); - } - - static LauncherVisibility unpackProcessMonitor(Object obj) { - GameLauncher launcher = ((GameLauncher) ((ProcessMonitor) obj).getTag()); - HMCLGameLauncher.GameLauncherTag tag = (HMCLGameLauncher.GameLauncherTag) launcher.getTag(); - return tag.launcherVisibility; - } - - boolean noExitThisTime = false; - - void runGame(Profile profile) { - MainFrame.INSTANCE.showMessage(C.i18n("ui.message.launching")); - profile.launcher().genLaunchCode(value -> { - DefaultPlugin.INSTANCE.saveAuthenticatorConfig(); - ((HMCLGameLauncher.GameLauncherTag) value.getTag()).state = 1; - }, MainFrame.INSTANCE::failed, Settings.getInstance().getAuthenticator().getPassword()); - } - - void testGame(Profile profile) { - MainFrame.INSTANCE.showMessage(C.i18n("ui.message.launching")); - profile.launcher().genLaunchCode(value -> { - DefaultPlugin.INSTANCE.saveAuthenticatorConfig(); - ((HMCLGameLauncher.GameLauncherTag) value.getTag()).state = 1; - ((HMCLGameLauncher.GameLauncherTag) value.getTag()).launcherVisibility = LauncherVisibility.KEEP; - }, MainFrame.INSTANCE::failed, Settings.getInstance().getAuthenticator().getPassword()); - } - - void makeLaunchScript(Profile profile) { - MainFrame.INSTANCE.showMessage(C.i18n("ui.message.launching")); - profile.launcher().genLaunchCode(value -> { - DefaultPlugin.INSTANCE.saveAuthenticatorConfig(); - ((HMCLGameLauncher.GameLauncherTag) value.getTag()).state = 2; - }, MainFrame.INSTANCE::failed, Settings.getInstance().getAuthenticator().getPassword()); - } - - class PrintlnProcessor implements Consumer { - - GameLauncher launcher; - PipedOutputStream os; - - public PrintlnProcessor(GameLauncher launcher, PipedOutputStream os) { - this.launcher = launcher; - this.os = os; - } - - @Override - public void accept(PrintlnEvent t) { - if (!t.isError()) - try { - os.write((t.getLine() + C.LINE_SEPARATOR).replace("log4j:Event", "log4j_Event").replace("log4j:Message", "log4j_Message").getBytes()); - os.flush(); - } catch(IOException e) { - HMCLog.err("", e); - } - else System.err.println(t.getLine()); - HMCLGameLauncher.GameLauncherTag tag = (HMCLGameLauncher.GameLauncherTag) launcher.getTag(); - LauncherVisibility l = tag.launcherVisibility; - if (t.getLine().contains("LWJGL Version: ") && l != LauncherVisibility.KEEP) - if (l != LauncherVisibility.HIDE_AND_REOPEN) - MainFrame.INSTANCE.dispose(); - else { // If current state is 'hide and reopen', closes the main window and reset the state to normal. - MainFrame.INSTANCE.setVisible(false); - HMCLApi.EVENT_BUS.fireChannel(new LaunchingStateChangedEvent(launcher, LaunchingState.Done)); - } - } - - } - - private static final Consumer LAUNCHING_STATE_CHANGED = t -> { - String message = null; - switch (t.getValue()) { - case LoggingIn: - message = "launch.state.logging_in"; - break; - case GeneratingLaunchingCodes: - message = "launch.state.generating_launching_codes"; - break; - case DownloadingLibraries: - message = "launch.state.downloading_libraries"; - break; - case DecompressingNatives: - message = "launch.state.decompressing_natives"; - break; - case WaitingForGameLaunching: - message = "launch.state.waiting_launching"; - break; - case Done: - MainFrame.INSTANCE.closeMessage(); - return; - } - MainFrame.INSTANCE.showMessage(C.i18n(message)); - }; - - private static final Consumer LAUNCH_FINISHER = event -> { - try { - ((GameLauncher) event.getSource()).launch(event.getValue()); - } catch (IOException e) { - MainFrame.INSTANCE.failed(C.i18n("launch.failed_creating_process") + "\n" + e.getMessage()); - HMCLog.err("Failed to launch when creating a new process.", e); - } - }; - - private void checkExit(LauncherVisibility v) { - if (v == LauncherVisibility.HIDE_AND_REOPEN) { - HMCLog.log("Launcher will not exit now."); - MainFrame.INSTANCE.setVisible(true); - } else if (v != LauncherVisibility.KEEP && !LogWindow.INSTANCE.isVisible() && !noExitThisTime) { - HMCLog.log("Launcher will exit now."); - System.exit(0); - } else { - HMCLog.log("Launcher will not exit now."); - noExitThisTime = false; - } - } - - private static final Consumer LAUNCH_SCRIPT_FINISHER = event -> { - try { - String s = MessageBox.showInputDialog(C.i18n("mainwindow.enter_script_name")); - if (StrUtils.isNotBlank(s)) - MessageBox.show(C.i18n("mainwindow.make_launch_succeed") + " " + ((GameLauncher) event.getSource()).makeLauncher(s, event.getValue()).getAbsolutePath()); - } catch (IOException ex) { - MessageBox.show(C.i18n("mainwindow.make_launch_script_failed")); - HMCLog.err("Failed to create script file.", ex); - } - MainFrame.INSTANCE.closeMessage(); - }; - -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.form b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.form deleted file mode 100644 index e79c27e5c..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.form +++ /dev/null @@ -1,245 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.java deleted file mode 100644 index 430807187..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindow.java +++ /dev/null @@ -1,425 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.ui; - -import java.io.PrintStream; -import java.util.Deque; -import java.util.LinkedList; -import javax.swing.SwingUtilities; -import javax.swing.text.BadLocationException; -import javax.swing.text.Document; -import javax.swing.text.SimpleAttributeSet; -import javax.swing.text.StyleConstants; -import javax.swing.text.StyledDocument; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.util.log.Level; -import org.jackhuang.hmcl.api.func.NonFunction; -import org.jackhuang.hmcl.setting.Settings; -import org.jackhuang.hmcl.util.DoubleOutputStream; -import org.jackhuang.hmcl.util.Utils; -import org.jackhuang.hmcl.util.sys.ProcessMonitor; -import org.jackhuang.hmcl.util.ui.SwingUtils; - -/** - * - * @author huangyuhui - */ -public class LogWindow extends javax.swing.JFrame { - - public static LogWindowOutputStream outputStream; - - NonFunction listener; - - /** - * Creates new form LogWindow - */ - public LogWindow() { - initComponents(); - - DoubleOutputStream out = new DoubleOutputStream(outputStream = new LogWindowOutputStream(this, Level.INFO), System.out); - System.setOut(new PrintStream(out)); - DoubleOutputStream err = new DoubleOutputStream(new LogWindowOutputStream(this, Level.ERROR), System.err); - System.setErr(new PrintStream(err)); - - SwingUtilities.invokeLater(() -> { - setLocationRelativeTo(null); - //txtLog.setEditable(false); - txtLog.setFont(Settings.getInstance().getConsoleFont()); - cboShowLines.setSelectedItem(String.valueOf(Settings.getInstance().getLogLines())); - }); - } - - public static final LogWindow INSTANCE = new LogWindow(); - - /** - * This method is called from within the constructor to initialize the form. - * WARNING: Do NOT modify this code. The content of this method is always - * regenerated by the Form Editor. - */ - @SuppressWarnings("unchecked") - // //GEN-BEGIN:initComponents - private void initComponents() { - - btnClear = new javax.swing.JButton(); - btnClose = new javax.swing.JButton(); - btnCopy = new javax.swing.JButton(); - lblCrash = new javax.swing.JLabel(); - btnContact = new javax.swing.JButton(); - btnTerminateGame = new javax.swing.JButton(); - pnlLog = new javax.swing.JScrollPane(); - txtLog = new JLineWrapTextPane(); - lblShowLines = new javax.swing.JLabel(); - cboShowLines = new javax.swing.JComboBox<>(); - btnDebug = new javax.swing.JToggleButton(); - btnInfo = new javax.swing.JToggleButton(); - btnWarn = new javax.swing.JToggleButton(); - btnError = new javax.swing.JButton(); - btnFatal = new javax.swing.JButton(); - txtSearch = new javax.swing.JTextField(); - lblSearch = new javax.swing.JLabel(); - - setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); - setTitle(C.i18n("logwindow.title")); // NOI18N - addWindowListener(new java.awt.event.WindowAdapter() { - public void windowClosing(java.awt.event.WindowEvent evt) { - formWindowClosing(evt); - } - }); - - btnClear.setText(C.i18n("ui.button.clear")); // NOI18N - btnClear.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnClearActionPerformed(evt); - } - }); - - btnClose.setText(C.i18n("ui.button.close")); // NOI18N - btnClose.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnCloseActionPerformed(evt); - } - }); - - btnCopy.setText(C.i18n("ui.button.copy")); // NOI18N - btnCopy.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnCopyActionPerformed(evt); - } - }); - - lblCrash.setText(C.i18n("ui.label.crashing")); // NOI18N - - btnContact.setText(C.i18n("logwindow.contact")); // NOI18N - btnContact.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnContactActionPerformed(evt); - } - }); - - btnTerminateGame.setText(C.i18n("logwindow.terminate_game")); // NOI18N - btnTerminateGame.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnTerminateGameActionPerformed(evt); - } - }); - - txtLog.setEditable(false); - pnlLog.setViewportView(txtLog); - - lblShowLines.setText(C.i18n("logwindow.show_lines")); // NOI18N - lblShowLines.setToolTipText(""); - - cboShowLines.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "100", "1000", "5000" })); - cboShowLines.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - cboShowLinesItemStateChanged(evt); - } - }); - - btnDebug.setText("0 debug"); - - btnInfo.setText("0 info"); - - btnWarn.setText("0 warn"); - - btnError.setText("0 error"); - - btnFatal.setText("0 fatal"); - - txtSearch.setToolTipText(""); - txtSearch.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - txtSearchActionPerformed(evt); - } - }); - - lblSearch.setText(C.i18n("logwindow.search")); // NOI18N - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); - getContentPane().setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addComponent(btnContact) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 144, Short.MAX_VALUE) - .addComponent(btnTerminateGame) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnCopy) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnClear) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnClose)) - .addComponent(lblCrash, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(layout.createSequentialGroup() - .addComponent(lblShowLines) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(cboShowLines, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(lblSearch) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(txtSearch) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnFatal) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnError) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnWarn) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnInfo) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnDebug)) - .addComponent(pnlLog)) - .addContainerGap()) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(lblShowLines) - .addComponent(cboShowLines, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(btnDebug) - .addComponent(btnInfo) - .addComponent(btnWarn) - .addComponent(btnError) - .addComponent(btnFatal) - .addComponent(txtSearch, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblSearch)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(lblCrash) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pnlLog, javax.swing.GroupLayout.DEFAULT_SIZE, 281, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(btnClear) - .addComponent(btnClose) - .addComponent(btnCopy) - .addComponent(btnContact) - .addComponent(btnTerminateGame)) - .addContainerGap()) - ); - - pack(); - }// //GEN-END:initComponents - - private void btnCloseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCloseActionPerformed - if (listener != null && listener.apply()) - terminateGames(); - SwingUtils.exitIfNoWindow(this, true); - }//GEN-LAST:event_btnCloseActionPerformed - - private void btnClearActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnClearActionPerformed - clean(); - }//GEN-LAST:event_btnClearActionPerformed - - private void btnCopyActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCopyActionPerformed - Utils.setClipborad(this.txtLog.getText()); - }//GEN-LAST:event_btnCopyActionPerformed - - private void btnContactActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnContactActionPerformed - SwingUtils.openLink(C.URL_CONTACT); - }//GEN-LAST:event_btnContactActionPerformed - - private void btnTerminateGameActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnTerminateGameActionPerformed - terminateGames(); - }//GEN-LAST:event_btnTerminateGameActionPerformed - - private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing - if (listener != null && listener.apply()) - terminateGames(); - SwingUtils.exitIfNoWindow(this); - }//GEN-LAST:event_formWindowClosing - - private void cboShowLinesItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboShowLinesItemStateChanged - Settings.getInstance().setLogLines(Integer.parseInt(cboShowLines.getSelectedItem().toString())); - }//GEN-LAST:event_cboShowLinesItemStateChanged - - private void txtSearchActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtSearchActionPerformed - if (evt.getSource() != txtSearch || txtSearch.getText().isEmpty()) - return; - try { - if (!s.equals(txtSearch.getText())) - pos = 0; - StyledDocument d = txtLog.getStyledDocument(); - s = txtSearch.getText(); - String content = d.getText(0, d.getLength()); - int x = content.indexOf(s, pos); - if (x == -1) { - pos = 0; - x = content.indexOf(s, pos); - } - if (x == -1) - return; - int len = s.length(); - pos = x + len; - SimpleAttributeSet set = new SimpleAttributeSet(d.getLogicalStyle(x).copyAttributes()); - StyleConstants.setBackground(set, txtLog.getSelectionColor()); - StyleConstants.setForeground(set, txtLog.getSelectedTextColor()); - d.setCharacterAttributes(x, len, set, true); - set = new SimpleAttributeSet(d.getLogicalStyle(lastX).copyAttributes()); - StyleConstants.setBackground(set, txtLog.getBackground()); - StyleConstants.setForeground(set, txtLog.getForeground()); - d.setCharacterAttributes(lastX, lastLen, set, true); - txtLog.select(x, pos); - lastX = x; - lastLen = len; - } catch (BadLocationException e) { - } - }//GEN-LAST:event_txtSearchActionPerformed - - String s = ""; - int pos = 0, lastX = 0, lastLen = 0; - - void terminateGames() { - ProcessMonitor.stopAll(); - } - - int removedLength = 0; - Deque offsets = new LinkedList<>(); - int fatals = 0, errors = 0, warns = 0, infos = 0, debugs = 0; - - public void log(final String status, final Level c) { - if (!isVisible()) - return; - SwingUtilities.invokeLater(() -> { - Document d = txtLog.getStyledDocument(); - try { // prevent too much memory used. - if (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory() > 1l * 1024 * 1024 * 256) { - d.remove(0, d.getLength()); - offsets.clear(); - removedLength = 0; - } - } catch (Exception ex) { - HMCLog.err("Failed to clear the text component", ex); - } - String newStatus = status.replace("\t", " "); - SimpleAttributeSet sas = new SimpleAttributeSet(); - StyleConstants.setForeground(sas, c.COLOR); - try { - offsets.add(d.getLength() + removedLength); - d.insertString(d.getLength(), newStatus, sas); - } catch (Exception ex) { - HMCLog.err("Failed to insert \"" + newStatus + "\" to " + d.getLength(), ex); - } - - switch (c) { - case FATAL: - btnFatal.setText(++fatals + " fatals"); - break; - case ERROR: - btnError.setText(++errors + " errors"); - break; - case WARN: - btnWarn.setText(++warns + " warns"); - break; - case INFO: - btnInfo.setText(++infos + " infos"); - break; - case DEBUG: - btnDebug.setText(++debugs + " debugs"); - break; - } - - int maxLines = Integer.parseInt(cboShowLines.getSelectedItem().toString()); - while (offsets.size() > maxLines) { - int start = offsets.pollFirst(); - int end = offsets.peekFirst(); - try { - d.remove(start - removedLength, end - start); // start - removedLength must become 0 - removedLength = end; - } catch (Exception ignore) { - } - } - }); - } - - public void setExit(NonFunction exit) { - this.listener = exit; - } - - public void clean() { - txtLog.setText(""); - } - - @Override - public void setVisible(boolean b) { - txtLog.setFont(Settings.getInstance().getConsoleFont()); - lblCrash.setVisible(false); - btnContact.setVisible(false); - super.setVisible(b); - } - - public void showAsCrashWindow(boolean out_date) { - txtLog.setFont(Settings.getInstance().getConsoleFont()); - if (out_date) { - lblCrash.setVisible(false); - btnContact.setVisible(false); - lblCrash.setText(C.i18n("ui.label.crashing_out_dated")); - } else { - lblCrash.setVisible(true); - btnContact.setVisible(true); - lblCrash.setText(C.i18n("ui.label.crashing")); - } - - super.setVisible(true); - } - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JButton btnClear; - private javax.swing.JButton btnClose; - private javax.swing.JButton btnContact; - private javax.swing.JButton btnCopy; - private javax.swing.JToggleButton btnDebug; - private javax.swing.JButton btnError; - private javax.swing.JButton btnFatal; - private javax.swing.JToggleButton btnInfo; - private javax.swing.JButton btnTerminateGame; - private javax.swing.JToggleButton btnWarn; - private javax.swing.JComboBox cboShowLines; - private javax.swing.JLabel lblCrash; - private javax.swing.JLabel lblSearch; - private javax.swing.JLabel lblShowLines; - private javax.swing.JScrollPane pnlLog; - private javax.swing.JTextPane txtLog; - private javax.swing.JTextField txtSearch; - // End of variables declaration//GEN-END:variables -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindowOutputStream.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindowOutputStream.java deleted file mode 100644 index a52503347..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/LogWindowOutputStream.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.ui; - -import java.io.OutputStream; -import java.util.Objects; -import javax.swing.SwingUtilities; -import org.jackhuang.hmcl.util.log.Level; - -/** - * - * @author huangyuhui - */ -public class LogWindowOutputStream extends OutputStream { - - private final LogWindow txt; - private final Level sas; - - public LogWindowOutputStream(LogWindow logWindow, Level l) { - txt = Objects.requireNonNull(logWindow); - sas = Objects.requireNonNull(l); - } - - @Override - public final void write(byte[] arr) { - write(arr, 0, arr.length); - } - - @Override - public final void write(byte[] arr, int off, int len) { - append(new String(arr, off, len)); - } - - final Object obj = new Object(); - Level lastLevel = null; - - private void append(final String str) { - synchronized(this) { - if (manual) return; - } - SwingUtilities.invokeLater(() -> { - Level level = Level.guessLevel(str); - if (level == null) level = lastLevel; - else lastLevel = level; - txt.log(str, Level.mergeLevel(sas, level)); - }); - } - - @Override - public final void write(int i) { - append(new String(new byte[] { (byte) i })); - } - - boolean manual = false; - - public void log(String s, Level l) { - synchronized(this) { - manual = true; - System.out.print(s); - manual = false; - } - if (l == null) append(s); - else - SwingUtilities.invokeLater(() -> { - txt.log(s, l); - }); - } -} \ No newline at end of file diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainFrame.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainFrame.java deleted file mode 100755 index bc44bd2ce..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainFrame.java +++ /dev/null @@ -1,506 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.ui; - -import org.jackhuang.hmcl.util.ui.GaussionPanel; -import org.jackhuang.hmcl.util.ui.IRepaint; -import java.awt.BorderLayout; -import java.awt.CardLayout; -import java.awt.Color; -import java.awt.Cursor; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.GridLayout; -import java.awt.Rectangle; -import java.awt.Transparency; -import java.awt.Window; -import java.awt.event.ActionListener; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.awt.event.WindowEvent; -import java.awt.event.WindowListener; -import java.awt.image.BufferedImage; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import javax.swing.BorderFactory; -import javax.swing.Box; -import javax.swing.BoxLayout; -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.SwingUtilities; -import javax.swing.UIManager; -import org.jackhuang.hmcl.api.HMCLApi; -import org.jackhuang.hmcl.Main; -import org.jackhuang.hmcl.api.PluginManager; -import org.jackhuang.hmcl.api.event.config.ThemeChangedEvent; -import org.jackhuang.hmcl.setting.Settings; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.util.ui.MessageBox; -import org.jackhuang.hmcl.util.StrUtils; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.util.ui.BasicColors; -import org.jackhuang.hmcl.util.ui.DropShadowBorder; -import org.jackhuang.hmcl.util.ui.GraphicsUtils; -import org.jackhuang.hmcl.util.ui.SwingUtils; -import org.jackhuang.hmcl.util.ui.TintablePanel; -import org.jackhuang.hmcl.api.auth.IAuthenticator; -import org.jackhuang.hmcl.api.ui.Theme; -import org.jackhuang.hmcl.api.ui.TopTabPage; - - -/** - * - * @author huangyuhui - */ -public final class MainFrame extends DraggableFrame implements IRepaint { - - public static final MainFrame INSTANCE = new MainFrame(); - - TintablePanel centralPanel; - JPanel header, infoSwap, realPanel; - CardLayout infoLayout; - JLabel windowTitle; - GaussionPanel backgroundLabel; - DropShadowBorder border; - boolean enableShadow; - String defaultTitle; - - private int tempW, tempH; - - void setContentSize(int w, int h) { - setSize(w, h); - tempW = w; - tempH = h; - } - - MainFrame() { - setUndecorated(!Settings.getInstance().isDecorated()); - defaultTitle = isUndecorated() ? Main.makeTitle() : ""; - enableShadow = Settings.getInstance().isEnableShadow() && isUndecorated(); - if (enableShadow) - setContentSize(834, 542); - else - setContentSize(802, 511); - setDefaultCloseOperation(EXIT_ON_CLOSE); - setTitle(Main.makeTitle()); - initComponents(); - loadBackground(); - - setLocationRelativeTo(null); - if (MainFrame.this.isUndecorated()) - setResizable(false); - - this.addWindowListener(new WindowListener() { - @Override - public void windowOpened(WindowEvent e) { - } - - @Override - public void windowClosing(WindowEvent e) { - closing(); - } - - @Override - public void windowClosed(WindowEvent e) { - } - - @Override - public void windowIconified(WindowEvent e) { - } - - @Override - public void windowDeiconified(WindowEvent e) { - } - - @Override - public void windowActivated(WindowEvent e) { - if (!MainFrame.this.isUndecorated()) { - int w = tempW + getWidth() - getContentPane().getWidth(), h = tempH + getHeight() - getContentPane().getHeight(); - setSize(w, h); - setResizable(false); - setLocationRelativeTo(null); - } - } - - @Override - public void windowDeactivated(WindowEvent e) { - } - }); - - if (enableShadow) - try { - setBackground(new Color(0, 0, 0, 0)); - getRootPane().setBorder(border = new DropShadowBorder(borderColor, 4)); - } catch (Throwable ex) { - HMCLog.err("Failed to set window transparent.", ex); - Settings.getInstance().setEnableShadow(false); - setSize(802, 511); - } - ((JPanel) getContentPane()).setOpaque(true); - - HMCLApi.EVENT_BUS.channel(ThemeChangedEvent.class).register(x -> reloadColor(x.getValue())); - - SwingUtilities.invokeLater(() -> selectTab("main")); - } - - private void initComponents() { - setLayout(null); - - realPanel = new JPanel(); - realPanel.setLayout(null); - - header = new JPanel(); - header.setBounds(0, 0, 800, 30); - realPanel.add(header); - header.setOpaque(true); - header.setLayout(new BoxLayout(header, BoxLayout.LINE_AXIS)); - header.setBorder(BorderFactory.createEmptyBorder(0, 2, 0, 5)); - header.setBackground(borderColor); - header.setForeground(BasicColors.COLOR_WHITE_TEXT); - - ImageIcon headerIcon = Main.getIcon("icon.png"); - this.setIconImage(headerIcon.getImage()); - headerIcon = SwingUtils.scaleImage(headerIcon, 16, 16); - JLabel headerLabel = new JLabel(headerIcon); - headerLabel.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 0)); - header.add(headerLabel); - - header.add(Box.createRigidArea(new Dimension(8, 0))); - - PluginManager.fireAddTab(this, this::initializeTab); - - header.add(Box.createHorizontalGlue()); - - JPanel rightHeaderPanel = new JPanel(); - rightHeaderPanel.setOpaque(false); - rightHeaderPanel.setLayout(new BoxLayout(rightHeaderPanel, BoxLayout.PAGE_AXIS)); - rightHeaderPanel.setBorder(BorderFactory.createEmptyBorder(2, 0, 2, 0)); - - JPanel windowGadgetPanel = new JPanel(); - windowGadgetPanel.setOpaque(false); - windowGadgetPanel.setLayout(new BoxLayout(windowGadgetPanel, BoxLayout.LINE_AXIS)); - windowGadgetPanel.setAlignmentX(1.0F); - - if (!Settings.getInstance().isDecorated()) { - ImageIcon minimizeIcon = Main.getIcon("minimize.png"); - JButton minimizeButton = new JButton(minimizeIcon); - minimizeButton.setBorder(BorderFactory.createEmptyBorder()); - minimizeButton.setContentAreaFilled(false); - minimizeButton.setCursor(new Cursor(12)); - minimizeButton.setFocusable(false); - minimizeButton.addActionListener((e) -> MainFrame.this.minimizeWindow()); - windowGadgetPanel.add(minimizeButton); - - ImageIcon closeIcon = Main.getIcon("close.png"); - JButton closeButton = new JButton(closeIcon); - closeButton.setBorder(BorderFactory.createEmptyBorder()); - closeButton.setContentAreaFilled(false); - closeButton.addActionListener((e) -> MainFrame.this.closeWindow()); - closeButton.setCursor(new Cursor(12)); - closeButton.setFocusable(false); - windowGadgetPanel.add(closeButton); - } - rightHeaderPanel.add(windowGadgetPanel); - - windowTitle = new JLabel(defaultTitle); - windowTitle.setForeground(BasicColors.COLOR_WHITE_TEXT); - header.add(windowTitle); - header.add(Box.createHorizontalGlue()); - header.add(rightHeaderPanel); - - this.centralPanel = new TintablePanel(); - this.centralPanel.setTintColor(BasicColors.COLOR_CENTRAL_BACK); - realPanel.add(this.centralPanel); - JPanel truePanel = new JPanel(); - truePanel.setLayout(new BorderLayout()); - - this.infoSwap = new JPanel(); - this.infoLayout = new CardLayout(); - this.infoSwap.setLayout(infoLayout); - this.infoSwap.setOpaque(false); - - tabWrapper = new JPanel[tabHeader.size()]; - for (int i = 0; i < tabHeader.size(); i++) { - tabWrapper[i] = new JPanel(); - tabWrapper[i].setLayout(new GridLayout()); - infoSwap.add(tabWrapper[i], tabHeader.get(i).getActionCommand()); - } - - truePanel.add(this.infoSwap, "Center"); - centralPanel.setLayout(null); - centralPanel.add(truePanel); - truePanel.setBounds(0, 0, 800, 480); - centralPanel.setBounds(0, 30, 800, 480); - - realPanel.setBounds(1, 0, 800, 511); - add(realPanel); - - reloadColor(Settings.getInstance().getTheme()); - } - - private transient final ActionListener tabListener = e -> MainFrame.this.selectTab(e.getActionCommand()); - - private void initializeTab(TopTabPage inst, String cmd, String title) { - HeaderTab tab = new HeaderTab(title); - tab.setActionCommand(cmd); - tab.setForeground(BasicColors.COLOR_WHITE_TEXT); - tab.setBackground(borderColorDarker); - tab.setLayout(null); - tab.addActionListener(tabListener); - header.add(tab); - tabHeader.add(tab); - tabContent.add(inst); - } - - private final List tabHeader = new ArrayList<>(); - private JPanel tabWrapper[]; - private final List tabContent = new ArrayList<>(); - - public void selectTab(String tabName) { - int chosen = -1; - TopTabPage onCreate = null, onSelect = null, lastPage = null; - for (int i = 0; i < tabHeader.size(); i++) - if (tabName.equalsIgnoreCase(tabHeader.get(i).getActionCommand())) { - if (!tabContent.get(i).isCreated()) { - onCreate = tabContent.get(i); - onCreate.setId(i); - tabWrapper[i].add(tabContent.get(i)); - } else if (tabContent.get(i).isSelected()) - continue; - chosen = i; - break; - } - if (chosen != -1) { - for (int i = 0; i < tabHeader.size(); i++) - if (i != chosen && tabContent.get(i) != null && tabContent.get(i).isSelected()) { - lastPage = tabContent.get(i); - lastPage.onLeave(); - } - for (int i = 0; i < tabHeader.size(); i++) - if (i == chosen) { - for (int j = 0; j < tabHeader.size(); j++) - if (j != i) - tabHeader.get(j).setIsActive(false); - tabHeader.get(i).setIsActive(true); - onSelect = tabContent.get(i); - } - - this.infoLayout.show(this.infoSwap, tabName); - if (onCreate != null) - onCreate.onCreate(); - if (onSelect != null) - onSelect.onSelect(lastPage); - } - } - - protected void closing() { - for (int i = 0; i < tabHeader.size(); i++) - if (tabContent.get(i) != null && tabContent.get(i).isSelected()) - tabContent.get(i).onLeave(); - } - - protected void closeWindow() { - closing(); - System.exit(0); - } - - protected void minimizeWindow() { - setState(1); - } - - ImageIcon background; - - public void loadBackground() { - background = SwingUtils.searchBackgroundImage(Main.getIcon(Settings.getInstance().getTheme().settings.get("Customized.MainFrame.background_image")), Settings.getInstance().getBgpath(), 800, 480); - if (background != null) { - if (backgroundLabel == null) { - backgroundLabel = new GaussionPanel(); - backgroundLabel.setDrawBackgroundLayer(true); - backgroundLabel.addAeroObject(backgroundLabel); - backgroundLabel.setBounds(0, 0, 800, 480); - centralPanel.add(backgroundLabel, -1); - } - backgroundLabel.setBackgroundImage(background.getImage()); - } else - HMCLog.warn("No background image here! The background will be empty!"); - } - - public JPanel getTitleBar() { - return header; - } - - boolean isShowedMessage = false; - - public void closeMessage() { - if (isShowedMessage) { - isShowedMessage = false; - reloadColor(Settings.getInstance().getTheme()); - windowTitle.setText(defaultTitle); - windowTitle.setForeground(Settings.UPDATE_CHECKER.isOutOfDate() ? Color.red : Color.white); - } - } - - public void showMessage(String message) { - isShowedMessage = true; - borderColor = BasicColors.COLOR_RED; - borderColorDarker = BasicColors.COLOR_RED_DARKER; - header.setBackground(borderColor); - for (HeaderTab tab : tabHeader) - tab.setBackground(borderColorDarker); - if (border != null) - border.setColor(borderColor); - repaint(); - windowTitle.setText(message); - windowTitle.setForeground(Color.white); - } - - public static void showMainFrame() { - IAuthenticator l = Settings.getInstance().getAuthenticator(); - if (StrUtils.isBlank(l.getUserName())) - SwingUtilities.invokeLater(() -> MainFrame.INSTANCE.showMessage(C.i18n("ui.message.first_load"))); - if (l.hasPassword() && !l.isLoggedIn()) - SwingUtilities.invokeLater(() -> MainFrame.INSTANCE.showMessage(C.i18n("ui.message.enter_password"))); - INSTANCE.setVisible(true); - } - - Color borderColor; - Color borderColorDarker; - - private void initBorderColor() { - borderColor = UIManager.getColor("Customized.MainFrame.background"); - borderColorDarker = UIManager.getColor("Customized.MainFrame.selected_background"); - } - - public void reloadColor(Theme t) { - if (isShowedMessage) - return; - for (Map.Entry entry : t.settings.entrySet()) { - if (entry.getValue().startsWith("#")) - UIManager.put(entry.getKey(), GraphicsUtils.getWebColor(entry.getValue())); - } - - initBorderColor(); - if (border != null) - border.setColor(borderColor); - header.setBackground(borderColor); - for (HeaderTab tab : tabHeader) - tab.setBackground(borderColorDarker); - repaint(); - } - - private void paintImpl(Graphics g) { - int off = enableShadow ? 16 : 0, yoff = getInsets().top + off, xoff = getInsets().left + off; - int width = 800; - int height = header.getHeight() + 480 - 1; - super.paint(g); - g.setColor(borderColor); - g.drawLine(xoff, yoff, xoff, height + yoff + 1); - g.drawLine(xoff + width + 1, yoff, xoff + width + 1, height + yoff + 1); - g.drawLine(xoff, height + yoff + 1, xoff + width + 1, height + yoff + 1); - } - - @Override - public void paint(Graphics g) { - if (!enableShadow) - paintImpl(g); - else { - int off = enableShadow ? 16 : 0; - int width = this.getWidth(); - int height = this.getHeight(); - int contentWidth = width - off - off; - int contentHeight = height - off - off; - BufferedImage contentImage = new BufferedImage(contentWidth, - contentHeight, Transparency.OPAQUE); - Graphics2D contentG2d = contentImage.createGraphics(); - contentG2d.translate(-off, -off); - paintImpl(g); - paintImpl(contentG2d); - contentG2d.dispose(); - g.drawImage(contentImage, off, off, this); - } - } - - public void invokeUpdate() { - defaultTitle = Main.makeTitle() + C.i18n("update.found"); - windowTitle.addMouseListener(MouseListenerImpl.INSTANCE); - if (!isShowedMessage) { - windowTitle.setText(defaultTitle); - windowTitle.setForeground(Color.red); - } - } - - @Override - public JComponent getRepaintComponent() { - return null; - } - - @Override - public Window getRepaintWindow() { - return this; - } - - @Override - public Collection getRepaintRects() { - int off = MainFrame.INSTANCE.enableShadow ? 16 : 0, yoff = MainFrame.INSTANCE.getInsets().top + off, xoff = MainFrame.INSTANCE.getInsets().left + off; - int width = 800, height = MainFrame.INSTANCE.header.getHeight() + 480 - 1; - return Arrays.asList(new Rectangle(xoff, yoff, xoff, height + yoff + 1), - new Rectangle(xoff + width + 1, yoff, xoff + width + 1, height + yoff + 1), - new Rectangle(xoff, height + yoff + 1, xoff + width + 1, height + yoff + 1)); - } - - private static class MouseListenerImpl implements MouseListener { - - public static final MouseListenerImpl INSTANCE = new MouseListenerImpl(); - - @Override - public void mouseClicked(MouseEvent e) { - Settings.UPDATE_CHECKER.checkOutdate(); - } - - @Override - public void mousePressed(MouseEvent e) { - } - - @Override - public void mouseReleased(MouseEvent e) { - } - - @Override - public void mouseEntered(MouseEvent e) { - } - - @Override - public void mouseExited(MouseEvent e) { - } - } - - public void failed(String s) { - if (s != null) - MessageBox.show(s); - closeMessage(); - } - - transient LaunchingUIDaemon daemon = new LaunchingUIDaemon(); -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPagePanel.form b/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPagePanel.form deleted file mode 100755 index d929e9a74..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPagePanel.form +++ /dev/null @@ -1,304 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPagePanel.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPagePanel.java deleted file mode 100755 index 364f66b43..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/MainPagePanel.java +++ /dev/null @@ -1,553 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.ui; - -import org.jackhuang.hmcl.util.ui.Page; -import org.jackhuang.hmcl.util.ui.WideComboBox; -import org.jackhuang.hmcl.util.ui.GaussionPanel; -import java.awt.CardLayout; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.event.ItemEvent; -import java.awt.event.KeyEvent; -import javax.swing.DefaultComboBoxModel; -import javax.swing.SwingUtilities; -import javax.swing.filechooser.FileNameExtensionFilter; -import org.jackhuang.hmcl.api.HMCLApi; -import org.jackhuang.hmcl.api.event.config.AuthenticatorChangedEvent; -import org.jackhuang.hmcl.api.event.config.ProfileChangedEvent; -import org.jackhuang.hmcl.api.event.config.ProfileLoadingEvent; -import org.jackhuang.hmcl.api.event.launch.LaunchSucceededEvent; -import org.jackhuang.hmcl.api.event.launch.LaunchingState; -import org.jackhuang.hmcl.api.event.launch.LaunchingStateChangedEvent; -import org.jackhuang.hmcl.api.event.version.RefreshedVersionsEvent; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.core.auth.AbstractAuthenticator; -import org.jackhuang.hmcl.setting.Profile; -import org.jackhuang.hmcl.util.StrUtils; -import org.jackhuang.hmcl.core.version.MinecraftVersion; -import org.jackhuang.hmcl.setting.Settings; -import org.jackhuang.hmcl.core.mod.ModpackManager; -import org.jackhuang.hmcl.ui.modpack.ModpackWizard; -import org.jackhuang.hmcl.laf.button.CustomButton; -import org.jackhuang.hmcl.api.func.Consumer; -import org.jackhuang.hmcl.util.sys.FileUtils; -import org.jackhuang.hmcl.util.task.TaskWindow; -import org.jackhuang.hmcl.util.ui.GraphicsUtils; -import org.jackhuang.hmcl.util.ui.JSystemFileChooser; -import org.jackhuang.hmcl.util.ui.SwingUtils; -import org.jackhuang.hmcl.util.ui.wizard.api.WizardDisplayer; -import org.jackhuang.hmcl.api.auth.IAuthenticator; -import org.jackhuang.hmcl.laf.button.CustomButtonUI; -import org.jackhuang.hmcl.util.ui.MessageBox; - -/** - * - * @author huangyuhui - */ -public class MainPagePanel extends Page { - - public MainPagePanel() { - } - - void initGui() { - initComponents(); - - animationEnabled = Settings.getInstance().isEnableAnimation(); - - pnlButtons = new javax.swing.JPanel(); - pnlButtons.setLayout(null); - - int w = 150, h = 50; - btnRun = new CustomButton(); - btnRun.setBounds(0, 0, w, h); - Font font = btnRun.getFont(); - Font newFont = new Font(font.getName(), font.getStyle(), 15); - pnlButtons.add(btnRun); - - btnRun.setText(C.i18n("ui.button.run")); - btnRun.setFont(newFont); - btnRun.addActionListener(e -> MainFrame.INSTANCE.daemon.runGame(Settings.getLastProfile())); - btnRun.setUI(new CustomButtonUI()); - - pnlRoot.add(pnlButtons); - pnlButtons.setBounds(0, 0, w, h); - - this.setSize(new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT)); - this.pnlButtons.setLocation(DEFAULT_WIDTH - pnlButtons.getWidth() - 25, DEFAULT_HEIGHT - pnlButtons.getHeight() - 25); - pnlMore.setBounds(0, 0, pnlMore.getWidth(), DEFAULT_HEIGHT); - pnlMore.setBackground(GraphicsUtils.getWebColorWithAlpha("FFFFFF7F")); - pnlMore.setOpaque(true); - - if (Settings.getInstance().isEnableBlur()) - ((GaussionPanel) pnlRoot).addAeroObject(pnlMore); - ((GaussionPanel) pnlRoot).setBackgroundImage(MainFrame.INSTANCE.background.getImage()); - - ((RepaintPage) pnlMore).setRepainter(pnlRoot); - - HMCLApi.EVENT_BUS.channel(AuthenticatorChangedEvent.class).register(onAuthChanged); - HMCLApi.EVENT_BUS.channel(ProfileLoadingEvent.class).register(onLoadingProfiles); - HMCLApi.EVENT_BUS.channel(ProfileChangedEvent.class).register(onSelectedProfilesChanged); - HMCLApi.EVENT_BUS.channel(RefreshedVersionsEvent.class).register(onRefreshedVersions); - HMCLApi.EVENT_BUS.channel(LaunchingStateChangedEvent.class).register(launchingStateChanged); - HMCLApi.EVENT_BUS.channel(LaunchSucceededEvent.class).register(this::prepareAuths); - - prepareAuths(); - } - - /** - * This method is called from within the constructor to initialize the form. - * WARNING: Do NOT modify this code. The content of this method is always - * regenerated by the Form Editor. - */ - @SuppressWarnings("unchecked") - // //GEN-BEGIN:initComponents - private void initComponents() { - - pnlRoot = new GaussionPanel(); - pnlMore = new org.jackhuang.hmcl.ui.RepaintPage(); - txtPlayerName = new javax.swing.JTextField(); - lblLogin = new javax.swing.JLabel(); - cboLoginMode = new javax.swing.JComboBox(); - lblUserName = new javax.swing.JLabel(); - lblProfile = new javax.swing.JLabel(); - cboProfiles = new javax.swing.JComboBox(); - lblVersion = new javax.swing.JLabel(); - cboVersions = new WideComboBox(); - pnlPassword = new javax.swing.JPanel(); - pnlLogIn = new javax.swing.JPanel(); - lblPassword = new javax.swing.JLabel(); - txtPassword = new javax.swing.JPasswordField(); - pnlLogOut = new javax.swing.JPanel(); - btnLogout = new javax.swing.JButton(); - btnImportModpack = new javax.swing.JButton(); - btnExportModpack = new javax.swing.JButton(); - - setLayout(null); - - pnlRoot.setLayout(null); - - pnlMore.setBackground(new java.awt.Color(204, 204, 204)); - pnlMore.setOpaque(false); - - txtPlayerName.addFocusListener(new java.awt.event.FocusAdapter() { - public void focusGained(java.awt.event.FocusEvent evt) { - txtPlayerNameFocusGained(evt); - } - public void focusLost(java.awt.event.FocusEvent evt) { - txtPlayerNameFocusLost(evt); - } - }); - txtPlayerName.addKeyListener(new java.awt.event.KeyAdapter() { - public void keyPressed(java.awt.event.KeyEvent evt) { - txtPlayerNameKeyPressed(evt); - } - }); - - lblLogin.setText(C.i18n("login.type")); // NOI18N - - cboLoginMode.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - cboLoginModeItemStateChanged(evt); - } - }); - - lblUserName.setText(C.i18n("login.username")); // NOI18N - - lblProfile.setText(C.i18n("ui.label.profile")); // NOI18N - - cboProfiles.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - cboProfilesItemStateChanged(evt); - } - }); - - lblVersion.setText(C.i18n("ui.label.version")); // NOI18N - lblVersion.setToolTipText(C.i18n("ui.label.version")); // NOI18N - - cboVersions.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - cboVersionsItemStateChanged(evt); - } - }); - - pnlPassword.setLayout(new java.awt.CardLayout()); - - lblPassword.setText(C.i18n("ui.label.password")); // NOI18N - - txtPassword.addCaretListener(new javax.swing.event.CaretListener() { - public void caretUpdate(javax.swing.event.CaretEvent evt) { - txtPasswordCaretUpdate(evt); - } - }); - txtPassword.addFocusListener(new java.awt.event.FocusAdapter() { - public void focusGained(java.awt.event.FocusEvent evt) { - txtPasswordFocusGained(evt); - } - }); - txtPassword.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - txtPasswordActionPerformed(evt); - } - }); - txtPassword.addKeyListener(new java.awt.event.KeyAdapter() { - public void keyPressed(java.awt.event.KeyEvent evt) { - txtPasswordKeyPressed(evt); - } - }); - - javax.swing.GroupLayout pnlLogInLayout = new javax.swing.GroupLayout(pnlLogIn); - pnlLogIn.setLayout(pnlLogInLayout); - pnlLogInLayout.setHorizontalGroup( - pnlLogInLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnlLogInLayout.createSequentialGroup() - .addComponent(lblPassword) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(txtPassword)) - ); - pnlLogInLayout.setVerticalGroup( - pnlLogInLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnlLogInLayout.createSequentialGroup() - .addGap(0, 0, Short.MAX_VALUE) - .addGroup(pnlLogInLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(lblPassword, javax.swing.GroupLayout.PREFERRED_SIZE, 22, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(txtPassword, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE))) - ); - - pnlPassword.add(pnlLogIn, "card2"); - - btnLogout.setText(C.i18n("ui.button.logout")); // NOI18N - btnLogout.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnLogoutActionPerformed(evt); - } - }); - - javax.swing.GroupLayout pnlLogOutLayout = new javax.swing.GroupLayout(pnlLogOut); - pnlLogOut.setLayout(pnlLogOutLayout); - pnlLogOutLayout.setHorizontalGroup( - pnlLogOutLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(btnLogout, javax.swing.GroupLayout.DEFAULT_SIZE, 170, Short.MAX_VALUE) - ); - pnlLogOutLayout.setVerticalGroup( - pnlLogOutLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(btnLogout, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - ); - - pnlPassword.add(pnlLogOut, "card3"); - - btnImportModpack.setText(C.i18n("modpack.task.install")); // NOI18N - btnImportModpack.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnImportModpackActionPerformed(evt); - } - }); - - btnExportModpack.setText(C.i18n("modpack.task.save")); // NOI18N - btnExportModpack.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnExportModpackActionPerformed(evt); - } - }); - - javax.swing.GroupLayout pnlMoreLayout = new javax.swing.GroupLayout(pnlMore); - pnlMore.setLayout(pnlMoreLayout); - pnlMoreLayout.setHorizontalGroup( - pnlMoreLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnlMoreLayout.createSequentialGroup() - .addContainerGap() - .addGroup(pnlMoreLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(pnlPassword, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(pnlMoreLayout.createSequentialGroup() - .addGroup(pnlMoreLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(lblProfile, javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(lblVersion, javax.swing.GroupLayout.Alignment.TRAILING)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(pnlMoreLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(cboProfiles, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(cboVersions, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) - .addGroup(pnlMoreLayout.createSequentialGroup() - .addGroup(pnlMoreLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(lblUserName) - .addComponent(lblLogin)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(pnlMoreLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(cboLoginMode, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(txtPlayerName))) - .addComponent(btnExportModpack, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(btnImportModpack, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addContainerGap()) - ); - pnlMoreLayout.setVerticalGroup( - pnlMoreLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnlMoreLayout.createSequentialGroup() - .addContainerGap() - .addGroup(pnlMoreLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(lblProfile) - .addComponent(cboProfiles, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(pnlMoreLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(cboVersions, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblVersion)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(pnlMoreLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(lblLogin) - .addComponent(cboLoginMode, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(pnlMoreLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(lblUserName) - .addComponent(txtPlayerName, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(pnlPassword, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 254, Short.MAX_VALUE) - .addComponent(btnImportModpack) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnExportModpack) - .addContainerGap()) - ); - - pnlRoot.add(pnlMore); - pnlMore.setBounds(0, 0, 190, 480); - - add(pnlRoot); - pnlRoot.setBounds(0, 0, 800, 480); - }// //GEN-END:initComponents - - private void txtPlayerNameFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtPlayerNameFocusGained - MainFrame.INSTANCE.closeMessage(); - }//GEN-LAST:event_txtPlayerNameFocusGained - - private void txtPlayerNameFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtPlayerNameFocusLost - IAuthenticator l = Settings.getInstance().getAuthenticator(); - l.setUserName(txtPlayerName.getText()); - }//GEN-LAST:event_txtPlayerNameFocusLost - - private void cboLoginModeItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboLoginModeItemStateChanged - if (evt.getStateChange() != ItemEvent.SELECTED) - return; - if (preparingAuth) - return; - Settings.getInstance().setLoginType(cboLoginMode.getSelectedIndex()); - }//GEN-LAST:event_cboLoginModeItemStateChanged - - private void cboProfilesItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboProfilesItemStateChanged - if (!isLoading && cboProfiles.getSelectedIndex() != -1 && !StrUtils.isBlank((String) cboProfiles.getSelectedItem())) - Settings.getInstance().setLast((String) cboProfiles.getSelectedItem()); - }//GEN-LAST:event_cboProfilesItemStateChanged - - private void cboVersionsItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboVersionsItemStateChanged - if (isLoading || evt.getStateChange() != ItemEvent.SELECTED || cboVersions.getSelectedIndex() < 0 || StrUtils.isBlank((String) cboVersions.getSelectedItem())) - return; - String mcv = (String) cboVersions.getSelectedItem(); - Settings.getLastProfile().setSelectedVersion(mcv); - }//GEN-LAST:event_cboVersionsItemStateChanged - - private void txtPasswordFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txtPasswordFocusGained - MainFrame.INSTANCE.closeMessage(); - }//GEN-LAST:event_txtPasswordFocusGained - - private void txtPasswordActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtPasswordActionPerformed - MainFrame.INSTANCE.daemon.runGame(Settings.getLastProfile()); - }//GEN-LAST:event_txtPasswordActionPerformed - - private void btnLogoutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnLogoutActionPerformed - if (preparingAuth) - return; - - IAuthenticator l = Settings.getInstance().getAuthenticator(); - CardLayout cl = (CardLayout) pnlPassword.getLayout(); - if (l.isLoggedIn()) - l.logOut(); - cl.first(pnlPassword); - SwingUtilities.invokeLater(this::repaint); - }//GEN-LAST:event_btnLogoutActionPerformed - - private void txtPlayerNameKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_txtPlayerNameKeyPressed - if (evt.getKeyCode() == KeyEvent.VK_ENTER) { - IAuthenticator l = Settings.getInstance().getAuthenticator(); - l.setUserName(txtPlayerName.getText()); - if (!l.hasPassword()) - MainFrame.INSTANCE.daemon.runGame(Settings.getLastProfile()); - else if (!l.isLoggedIn()) - txtPassword.requestFocus(); - } - }//GEN-LAST:event_txtPlayerNameKeyPressed - - private void txtPasswordKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_txtPasswordKeyPressed - if (evt.getKeyCode() == KeyEvent.VK_ENTER) - MainFrame.INSTANCE.daemon.runGame(Settings.getLastProfile()); - }//GEN-LAST:event_txtPasswordKeyPressed - - private void btnImportModpackActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnImportModpackActionPerformed - JSystemFileChooser fc = new JSystemFileChooser(); - fc.setFileSelectionMode(JSystemFileChooser.FILES_ONLY); - fc.setDialogTitle(C.i18n("modpack.choose")); - fc.setMultiSelectionEnabled(false); - fc.setFileFilter(new FileNameExtensionFilter(C.i18n("modpack"), "zip")); - fc.showOpenDialog(this); - if (fc.getSelectedFile() == null) - return; - String suggestedModpackId = MessageBox.showInputDialog(C.i18n("modpack.enter_name"), FileUtils.getBaseName(fc.getSelectedFile().getName())); - if (StrUtils.isBlank(suggestedModpackId)) - return; - TaskWindow.factory().append(ModpackManager.install(MainFrame.INSTANCE, fc.getSelectedFile(), Settings.getLastProfile().service(), suggestedModpackId)).execute(); - Settings.getLastProfile().service().version().refreshVersions(); - }//GEN-LAST:event_btnImportModpackActionPerformed - - private void btnExportModpackActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnExportModpackActionPerformed - if (Settings.getLastProfile().service().version().getVersionCount() <= 0) - return; - WizardDisplayer.showWizard(new ModpackWizard(Settings.getLastProfile()).createWizard()); - }//GEN-LAST:event_btnExportModpackActionPerformed - - private void txtPasswordCaretUpdate(javax.swing.event.CaretEvent evt) {//GEN-FIRST:event_txtPasswordCaretUpdate - Settings.getInstance().getAuthenticator().setPassword(txtPassword.getText()); - }//GEN-LAST:event_txtPasswordCaretUpdate - - // - private void prepareAuths() { - preparingAuth = true; - cboLoginMode.removeAllItems(); - for (IAuthenticator str : AbstractAuthenticator.LOGINS) - cboLoginMode.addItem(str.getName()); - preparingAuth = false; - int loginType = Settings.getInstance().getLoginType(); - if (0 <= loginType && loginType < cboLoginMode.getItemCount()) { - cboLoginMode.setSelectedIndex(loginType); - Settings.getInstance().setLoginType(loginType); - } - } - // - - // - boolean preparingAuth = true; - private boolean isLoading = false; - private javax.swing.JPanel pnlButtons; - private CustomButton btnRun; - private static final int DEFAULT_WIDTH = 800, DEFAULT_HEIGHT = 480; - // - - @Override - public void onCreate() { - initGui(); - super.onCreate(); - Settings.onProfileLoading(); - } - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JButton btnExportModpack; - private javax.swing.JButton btnImportModpack; - private javax.swing.JButton btnLogout; - private javax.swing.JComboBox cboLoginMode; - private javax.swing.JComboBox cboProfiles; - private javax.swing.JComboBox cboVersions; - private javax.swing.JLabel lblLogin; - private javax.swing.JLabel lblPassword; - private javax.swing.JLabel lblProfile; - private javax.swing.JLabel lblUserName; - private javax.swing.JLabel lblVersion; - private javax.swing.JPanel pnlLogIn; - private javax.swing.JPanel pnlLogOut; - private javax.swing.JPanel pnlMore; - private javax.swing.JPanel pnlPassword; - private javax.swing.JPanel pnlRoot; - private javax.swing.JPasswordField txtPassword; - private javax.swing.JTextField txtPlayerName; - // End of variables declaration//GEN-END:variables - - final Consumer onAuthChanged = (x) -> { - if (x.getValue().hasPassword()) { - pnlPassword.setVisible(true); - lblUserName.setText(C.i18n("login.account")); - } else { - pnlPassword.setVisible(false); - lblUserName.setText(C.i18n("login.username")); - } - - CardLayout cl = (CardLayout) pnlPassword.getLayout(); - if (x.getValue().isLoggedIn()) - cl.last(pnlPassword); - else - cl.first(pnlPassword); - String username = x.getValue().getUserName(); - if (username == null) - username = ""; - txtPlayerName.setText(username); - }; - - final Runnable onLoadingProfiles = () -> { - isLoading = true; - DefaultComboBoxModel model = new DefaultComboBoxModel<>(); - for (Profile s : Settings.getProfilesFiltered()) - model.addElement(s.getName()); - cboProfiles.setModel(model); - isLoading = false; - }; - - final Consumer onRefreshedVersions = t -> { - if (Settings.getLastProfile().service().version() == t.getSource()) - loadVersions(); - }; - - boolean showedNoVersion = false; - - void loadVersions() { - isLoading = true; - cboVersions.removeAllItems(); - String selVersion = Settings.getLastProfile().getSelectedVersion(); - if (!Settings.getLastProfile().service().version().getVersions().isEmpty()) { - for (MinecraftVersion mcVersion : Settings.getLastProfile().service().version().getVersions()) { - if (mcVersion.hidden) - continue; - cboVersions.addItem(mcVersion.id); - } - versionChanged(selVersion); - } - isLoading = false; - } - - final Consumer launchingStateChanged = t -> SwingUtilities.invokeLater(() -> SwingUtils.setEnabled(MainFrame.INSTANCE.getRootPane(), t.getValue() == LaunchingState.Done)); - - void versionChanged(String selectedVersion) { - isLoading = true; - DefaultComboBoxModel model = (DefaultComboBoxModel) cboVersions.getModel(); - for (int i = 0; i < model.getSize(); ++i) - if (model.getElementAt(i).equals(selectedVersion)) { - model.setSelectedItem(selectedVersion); - break; - } - isLoading = false; - } - - final Consumer onSelectedProfilesChanged = event -> { - Profile t = event.getValue(); - t.propertyChanged.register(e -> { - if ("selectedVersion".equals(e.getPropertyName())) - versionChanged(e.getNewValue()); - }); - - isLoading = true; - DefaultComboBoxModel model = (DefaultComboBoxModel) cboProfiles.getModel(); - for (int i = 0; i < model.getSize(); ++i) - if (model.getElementAt(i).equals(t.getName())) { - model.setSelectedItem(t.getName()); - break; - } - isLoading = false; - }; -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/NewProfileWindow.form b/HMCL/src/main/java/org/jackhuang/hmcl/ui/NewProfileWindow.form deleted file mode 100755 index 15e5411aa..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/NewProfileWindow.form +++ /dev/null @@ -1,124 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/NewProfileWindow.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/NewProfileWindow.java deleted file mode 100755 index 8ba792a1c..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/NewProfileWindow.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.ui; - -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.setting.Profile; -import org.jackhuang.hmcl.setting.Settings; -import org.jackhuang.hmcl.util.StrUtils; - -/** - * - * @author huangyuhui - */ -public final class NewProfileWindow extends javax.swing.JDialog { - - public NewProfileWindow(java.awt.Frame parent) { - super(parent, true); - initComponents(); - - setLocationRelativeTo(null); - - for (Profile s : Settings.getProfilesFiltered()) - cboProfiles.addItem(s.getName()); - } - - /** - * This method is called from within the constructor to initialize the form. - * WARNING: Do NOT modify this code. The content of this method is always - * regenerated by the Form Editor. - */ - @SuppressWarnings("unchecked") - // //GEN-BEGIN:initComponents - private void initComponents() { - - jLabel1 = new javax.swing.JLabel(); - txtNewProfileName = new javax.swing.JTextField(); - jLabel2 = new javax.swing.JLabel(); - cboProfiles = new javax.swing.JComboBox(); - btnCancel = new javax.swing.JButton(); - btnOK = new javax.swing.JButton(); - - setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); - setTitle(C.i18n("ui.newProfileWindow.title")); // NOI18N - - jLabel1.setText(C.i18n("ui.label.newProfileWindow.new_profile_name")); // NOI18N - - txtNewProfileName.addKeyListener(new java.awt.event.KeyAdapter() { - public void keyTyped(java.awt.event.KeyEvent evt) { - txtNewProfileNameKeyTyped(evt); - } - }); - - jLabel2.setText(C.i18n("ui.label.newProfileWindow.copy_from")); // NOI18N - - btnCancel.setText(C.i18n("button.cancel")); // NOI18N - btnCancel.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnCancelActionPerformed(evt); - } - }); - - btnOK.setText(C.i18n("ui.button.ok")); // NOI18N - btnOK.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnOKActionPerformed(evt); - } - }); - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); - getContentPane().setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(jLabel1) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(txtNewProfileName)) - .addGroup(layout.createSequentialGroup() - .addComponent(jLabel2) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(cboProfiles, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addGap(0, 262, Short.MAX_VALUE) - .addComponent(btnOK) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnCancel))) - .addContainerGap()) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(jLabel1) - .addComponent(txtNewProfileName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(jLabel2) - .addComponent(cboProfiles, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(btnCancel) - .addComponent(btnOK)) - .addContainerGap()) - ); - - pack(); - }// //GEN-END:initComponents - - private void txtNewProfileNameKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_txtNewProfileNameKeyTyped - switch (evt.getKeyCode()) { - case 13: - act(); - break; - case 27: - this.dispose(); - break; - default: - break; - } - }//GEN-LAST:event_txtNewProfileNameKeyTyped - - private void btnOKActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnOKActionPerformed - act(); - }//GEN-LAST:event_btnOKActionPerformed - - void act() { - if (!StrUtils.isBlank(txtNewProfileName.getText())) { - Profile newProfile = new Profile(txtNewProfileName.getText(), Settings.getProfile(cboProfiles.getSelectedItem().toString())); - Settings.putProfile(newProfile); - } - this.dispose(); - } - - private void btnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCancelActionPerformed - this.dispose(); - }//GEN-LAST:event_btnCancelActionPerformed - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JButton btnCancel; - private javax.swing.JButton btnOK; - private javax.swing.JComboBox cboProfiles; - private javax.swing.JLabel jLabel1; - private javax.swing.JLabel jLabel2; - private javax.swing.JTextField txtNewProfileName; - // End of variables declaration//GEN-END:variables -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/NewTabPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/NewTabPane.java deleted file mode 100755 index 8f21f7231..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/NewTabPane.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.ui; - -import javax.swing.JTabbedPane; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import org.jackhuang.hmcl.api.ui.TopTabPage; - -/** - * - * @author huangyuhui - */ -public class NewTabPane extends JTabbedPane implements ChangeListener { - - public NewTabPane() { - super(); - addChangeListener(this); - } - - public boolean initializing; - - @Override - public void stateChanged(ChangeEvent e) { - if (initializing) - return; - for (int i = 0; i < getComponentCount(); ++i) - if (getComponent(i) instanceof TopTabPage) { - TopTabPage comp = (TopTabPage) getComponent(i); - comp.setId(i); - if (getSelectedIndex() != i) - ((TopTabPage) getComponent(i)).onLeave(); - } - if (getSelectedComponent() instanceof TopTabPage) { - if (page == null && getComponentCount() > 0 && getComponent(0) instanceof TopTabPage) - page = (TopTabPage) getComponent(0); - ((TopTabPage) getSelectedComponent()).onSelect(page); - page = (TopTabPage) getSelectedComponent(); - } - } - - TopTabPage page = null; - -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/RepaintPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/RepaintPage.java deleted file mode 100644 index 96ea56974..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/RepaintPage.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.ui; - -import org.jackhuang.hmcl.util.ui.Page; -import org.jackhuang.hmcl.util.ui.IRepaint; -import java.awt.Rectangle; -import java.awt.Window; -import java.util.Arrays; -import java.util.Collection; -import javax.swing.JComponent; - -/** - * - * @author huang - */ -public class RepaintPage extends Page implements IRepaint { - - public RepaintPage() { - super(); - } - - JComponent repainter; - - @Override - public JComponent getRepaintComponent() { - return repainter; - } - - public void setRepainter(JComponent repainter) { - this.repainter = repainter; - } - - @Override - public Collection getRepaintRects() { - return Arrays.asList(this.getBounds()); - } - - @Override - public Window getRepaintWindow() { - return null; - } -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/modpack/ModpackDescriptionPanel.form b/HMCL/src/main/java/org/jackhuang/hmcl/ui/modpack/ModpackDescriptionPanel.form deleted file mode 100644 index 6351c990b..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/modpack/ModpackDescriptionPanel.form +++ /dev/null @@ -1,75 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/modpack/ModpackDescriptionPanel.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/modpack/ModpackDescriptionPanel.java deleted file mode 100644 index 55be5a2bc..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/modpack/ModpackDescriptionPanel.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.ui.modpack; - -import java.awt.Dimension; -import java.awt.HeadlessException; -import java.io.IOException; -import java.util.Map; -import javax.swing.JOptionPane; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.util.ui.MessageBox; -import org.jackhuang.hmcl.util.StrUtils; -import org.jackhuang.hmcl.util.net.WebPage; -import org.jackhuang.hmcl.util.ui.wizard.spi.WizardController; -import org.markdown4j.Markdown4jProcessor; - -/** - * - * @author huangyuhui - */ -public class ModpackDescriptionPanel extends javax.swing.JPanel { - - public static final String KEY_MODPACK_DESCRITION = "modpackDescription"; - - private final transient WizardController controller; - private final Map wizardData; - - /** - * Creates new form ModpackDescriptionPanel - */ - public ModpackDescriptionPanel(WizardController controller, Map wizardData) { - initComponents(); - - this.controller = controller; - this.wizardData = wizardData; - } - - /** - * This method is called from within the constructor to - * initialize the form. - * WARNING: Do NOT modify this code. The content of this method is - * always regenerated by the Form Editor. - */ - @SuppressWarnings("unchecked") - // //GEN-BEGIN:initComponents - private void initComponents() { - - jScrollPane1 = new javax.swing.JScrollPane(); - txtDescription = new javax.swing.JTextPane(); - jButton1 = new javax.swing.JButton(); - lblTitle = new javax.swing.JLabel(); - - txtDescription.addCaretListener(new javax.swing.event.CaretListener() { - public void caretUpdate(javax.swing.event.CaretEvent evt) { - txtDescriptionCaretUpdate(evt); - } - }); - jScrollPane1.setViewportView(txtDescription); - - jButton1.setText(C.i18n("ui.button.preview")); // NOI18N - jButton1.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - jButton1ActionPerformed(evt); - } - }); - - lblTitle.setText(C.i18n("modpack.desc")); // NOI18N - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); - this.setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane1) - .addGroup(layout.createSequentialGroup() - .addGap(0, 0, Short.MAX_VALUE) - .addComponent(jButton1)) - .addGroup(layout.createSequentialGroup() - .addComponent(lblTitle) - .addGap(0, 0, Short.MAX_VALUE)) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(lblTitle) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 250, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jButton1)) - ); - }// //GEN-END:initComponents - - private void txtDescriptionCaretUpdate(javax.swing.event.CaretEvent evt) {//GEN-FIRST:event_txtDescriptionCaretUpdate - wizardData.put(KEY_MODPACK_DESCRITION, txtDescription.getText()); - }//GEN-LAST:event_txtDescriptionCaretUpdate - - private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed - try { - Object msgs[] = new Object[2]; - msgs[0] = C.i18n("ui.button.preview"); - msgs[1] = new WebPage(new Markdown4jProcessor().process(txtDescription.getText())); - ((WebPage) msgs[1]).setPreferredSize(new Dimension(800, 350)); - JOptionPane.showOptionDialog(null, msgs, (String) msgs[0], JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null); - } catch (HeadlessException | IOException e) { - MessageBox.show(StrUtils.getStackTrace(e), C.i18n("message.error"), MessageBox.WARNING_MESSAGE); - } - }//GEN-LAST:event_jButton1ActionPerformed - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JButton jButton1; - private javax.swing.JScrollPane jScrollPane1; - private javax.swing.JLabel lblTitle; - private javax.swing.JTextPane txtDescription; - // End of variables declaration//GEN-END:variables -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/modpack/ModpackFileSelectionPanel.form b/HMCL/src/main/java/org/jackhuang/hmcl/ui/modpack/ModpackFileSelectionPanel.form deleted file mode 100644 index 11e0196b7..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/modpack/ModpackFileSelectionPanel.form +++ /dev/null @@ -1,41 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/modpack/ModpackFileSelectionPanel.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/modpack/ModpackFileSelectionPanel.java deleted file mode 100644 index 28c74a845..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/modpack/ModpackFileSelectionPanel.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.ui.modpack; - -import java.io.File; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import javax.swing.tree.DefaultTreeModel; -import org.jackhuang.hmcl.core.mod.ModAdviser; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.util.Pair; -import org.jackhuang.hmcl.util.sys.FileUtils; -import org.jackhuang.hmcl.util.ui.checktree.CheckBoxTreeCellRenderer; -import org.jackhuang.hmcl.util.ui.checktree.CheckBoxTreeNode; -import org.jackhuang.hmcl.util.ui.checktree.CheckBoxTreeNodeSelectionListener; -import org.jackhuang.hmcl.util.ui.wizard.spi.WizardController; - -/** - * - * @author huangyuhui - */ -public class ModpackFileSelectionPanel extends javax.swing.JPanel { - - private transient final WizardController controller; - private final Map wizardData; - private transient final ModAdviser blackList; - private final Set bannedFiles = new HashSet<>(); - - /** - * Creates new form ModpackFileSelectionPanel - * - * @param blackList Return 0: non blocked, 1: non shown, 2: suggested, - * checked - */ - public ModpackFileSelectionPanel(WizardController controller, Map wizardData, File gameDir, ModAdviser blackList) { - initComponents(); - - this.controller = controller; - this.wizardData = wizardData; - this.blackList = blackList; - - CheckBoxTreeNode root = create(gameDir, "minecraft"); - - jTree1.setModel(new DefaultTreeModel(root)); - jTree1.setCellRenderer(new CheckBoxTreeCellRenderer()); - jTree1.addMouseListener(new CheckBoxTreeNodeSelectionListener()); - - wizardData.put("blackList", root); - } - - private static final HashMap TRANSLATION = new HashMap() { - { - put("minecraft/servers.dat", C.i18n("modpack.files.servers_dat")); - put("minecraft/saves", C.i18n("modpack.files.saves")); - put("minecraft/mods", C.i18n("modpack.files.mods")); - put("minecraft/config", C.i18n("modpack.files.config")); - put("minecraft/liteconfig", C.i18n("modpack.files.liteconfig")); - put("minecraft/resourcepacks", C.i18n("modpack.files.resourcepacks")); - put("minecraft/options.txt", C.i18n("modpack.files.options_txt")); - put("minecraft/optionsshaders.txt", C.i18n("modpack.files.optionsshaders_txt")); - put("minecraft/mods/VoxelMods", C.i18n("modpack.files.mods.voxelmods")); - put("minecraft/dumps", C.i18n("modpack.files.dumps")); - put("minecraft/blueprints", C.i18n("modpack.files.blueprints")); - put("minecraft/scripts", C.i18n("modpack.files.scripts")); - } - }; - - CheckBoxTreeNode create(File file, String basePath) { - ModAdviser.ModSuggestion state = ModAdviser.ModSuggestion.NORMAL; - if (basePath.length() > "minecraft/".length()) - if ((state = blackList.advise(basePath.substring("minecraft/".length()) + (file.isDirectory() ? "/" : ""), file.isDirectory())) == ModAdviser.ModSuggestion.HIDDEN) - return null; - CheckBoxTreeNode node = new CheckBoxTreeNode(TRANSLATION.containsKey(basePath) ? new Pair<>(FileUtils.getName(basePath), TRANSLATION.get(basePath)) : FileUtils.getName(basePath)); - if (state == ModAdviser.ModSuggestion.SUGGESTED) - node.setSelected(true); - - if (file.isDirectory()) { - File[] f = file.listFiles(); - for (File subFile : f) { - CheckBoxTreeNode subNode = create(subFile, basePath + "/" + subFile.getName()); - if (subNode != null) { - subNode.setSelected(subNode.isSelected() | node.isSelected()); - node.add(subNode); - } - } - if (!node.children().hasMoreElements()) - return null; - } - - return node; - } - - /** - * This method is called from within the constructor to - * initialize the form. - * WARNING: Do NOT modify this code. The content of this method is - * always regenerated by the Form Editor. - */ - @SuppressWarnings("unchecked") - // //GEN-BEGIN:initComponents - private void initComponents() { - - jScrollPane1 = new javax.swing.JScrollPane(); - jTree1 = new javax.swing.JTree(); - - jScrollPane1.setViewportView(jTree1); - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); - this.setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE) - ); - }// //GEN-END:initComponents - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JScrollPane jScrollPane1; - private javax.swing.JTree jTree1; - // End of variables declaration//GEN-END:variables -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/modpack/ModpackInitializationPanel.form b/HMCL/src/main/java/org/jackhuang/hmcl/ui/modpack/ModpackInitializationPanel.form deleted file mode 100644 index 2c95beec6..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/modpack/ModpackInitializationPanel.form +++ /dev/null @@ -1,145 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/modpack/ModpackInitializationPanel.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/modpack/ModpackInitializationPanel.java deleted file mode 100644 index fbb6a1eb5..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/modpack/ModpackInitializationPanel.java +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.ui.modpack; - -import java.util.Map; -import java.util.Vector; -import java.util.regex.Pattern; -import javax.swing.DefaultComboBoxModel; -import javax.swing.filechooser.FileNameExtensionFilter; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.util.ui.JSystemFileChooser; -import org.jackhuang.hmcl.util.ui.wizard.spi.WizardController; - -/** - * - * @author huangyuhui - */ -public class ModpackInitializationPanel extends javax.swing.JPanel { - - public static final String KEY_GAME_VERSION = "gameVersion"; - public static final String KEY_MODPACK_LOCATION = "modpackLocation"; - public static final String KEY_MODPACK_NAME = "modpackName"; - public static final String KEY_INCLUDING_LAUNCHER = "launcher"; - - private final transient WizardController controller; - private final Map wizardData; - - /** - * Creates new form ModpackInitializationPanel - */ - public ModpackInitializationPanel(WizardController controller, Map wizardData, Vector versions, String selVersion) { - initComponents(); - - this.controller = controller; - this.wizardData = wizardData; - wizardData.put(KEY_GAME_VERSION, versions); - wizardData.put("selVersion", selVersion); - wizardData.put(KEY_INCLUDING_LAUNCHER, false); - - configureComboContents(); - checkProblem(); - } - - private void configureComboContents() { - Vector versions = (Vector) wizardData.get(KEY_GAME_VERSION); - cboGameVersion.setModel(new DefaultComboBoxModel<>(versions)); - wizardData.put(KEY_GAME_VERSION, wizardData.get("selVersion")); - } - - /** - * This method is called from within the constructor to - * initialize the form. - * WARNING: Do NOT modify this code. The content of this method is - * always regenerated by the Form Editor. - */ - @SuppressWarnings("unchecked") - // //GEN-BEGIN:initComponents - private void initComponents() { - - lblModpackLocation = new javax.swing.JLabel(); - txtModpackLocation = new javax.swing.JTextField(); - cboModpackLocation = new javax.swing.JButton(); - lblGameVersion = new javax.swing.JLabel(); - cboGameVersion = new javax.swing.JComboBox<>(); - jLabel1 = new javax.swing.JLabel(); - jLabel2 = new javax.swing.JLabel(); - txtModpackName = new javax.swing.JTextField(); - chkIncludeLauncher = new javax.swing.JCheckBox(); - - lblModpackLocation.setText(C.i18n("modpack.wizard.step.initialization.save")); // NOI18N - - txtModpackLocation.addCaretListener(new javax.swing.event.CaretListener() { - public void caretUpdate(javax.swing.event.CaretEvent evt) { - txtModpackLocationCaretUpdate(evt); - } - }); - - cboModpackLocation.setText("..."); - cboModpackLocation.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - cboModpackLocationActionPerformed(evt); - } - }); - - lblGameVersion.setText(C.i18n("modpack.wizard.step.initialization.exported_version")); // NOI18N - - cboGameVersion.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - cboGameVersionItemStateChanged(evt); - } - }); - - jLabel1.setText(C.i18n("modpack.wizard.step.initialization.warning")); // NOI18N - - jLabel2.setText(C.i18n("modpack.name")); // NOI18N - - txtModpackName.setToolTipText(""); - txtModpackName.addCaretListener(new javax.swing.event.CaretListener() { - public void caretUpdate(javax.swing.event.CaretEvent evt) { - txtModpackNameCaretUpdate(evt); - } - }); - - chkIncludeLauncher.setText(C.i18n("modpack.wizard.step.initialization.include_launcher")); // NOI18N - chkIncludeLauncher.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - chkIncludeLauncherItemStateChanged(evt); - } - }); - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); - this.setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(txtModpackName) - .addGroup(layout.createSequentialGroup() - .addComponent(lblModpackLocation) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 353, Short.MAX_VALUE) - .addComponent(cboModpackLocation)) - .addComponent(txtModpackLocation) - .addComponent(cboGameVersion, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(lblGameVersion) - .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(jLabel2) - .addComponent(chkIncludeLauncher)) - .addGap(0, 0, Short.MAX_VALUE))) - .addContainerGap()) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 19, Short.MAX_VALUE) - .addComponent(jLabel2) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(txtModpackName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(lblModpackLocation) - .addComponent(cboModpackLocation)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(txtModpackLocation, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(lblGameVersion) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(cboGameVersion, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(chkIncludeLauncher) - .addContainerGap()) - ); - }// //GEN-END:initComponents - - private void cboModpackLocationActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cboModpackLocationActionPerformed - JSystemFileChooser fc = new JSystemFileChooser(); - fc.setFileSelectionMode(JSystemFileChooser.FILES_ONLY); - fc.setDialogTitle(C.i18n("modpack.wizard.step.initialization.save")); - fc.setMultiSelectionEnabled(false); - fc.setFileFilter(new FileNameExtensionFilter(C.i18n("modpack") + "(*.zip)", "zip")); - fc.showSaveDialog(this); - if (fc.getSelectedFile() != null) { - String path = fc.getSelectedFile().getAbsolutePath(); - if (!path.endsWith(".zip")) - path += ".zip"; - txtModpackLocation.setText(path); - } - }//GEN-LAST:event_cboModpackLocationActionPerformed - - private void txtModpackLocationCaretUpdate(javax.swing.event.CaretEvent evt) {//GEN-FIRST:event_txtModpackLocationCaretUpdate - wizardData.put(KEY_MODPACK_LOCATION, txtModpackLocation.getText()); - - checkProblem(); - }//GEN-LAST:event_txtModpackLocationCaretUpdate - - private void cboGameVersionItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cboGameVersionItemStateChanged - wizardData.put(KEY_GAME_VERSION, cboGameVersion.getSelectedItem()); - }//GEN-LAST:event_cboGameVersionItemStateChanged - - private void txtModpackNameCaretUpdate(javax.swing.event.CaretEvent evt) {//GEN-FIRST:event_txtModpackNameCaretUpdate - wizardData.put(KEY_MODPACK_NAME, txtModpackName.getText()); - - checkProblem(); - }//GEN-LAST:event_txtModpackNameCaretUpdate - - private void chkIncludeLauncherItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_chkIncludeLauncherItemStateChanged - wizardData.put(KEY_INCLUDING_LAUNCHER, chkIncludeLauncher.isSelected()); - }//GEN-LAST:event_chkIncludeLauncherItemStateChanged - - static final Pattern PATTERN = Pattern.compile("[-a-zA-Z0-9_\\.\\(\\)\\[\\]\\{\\}\\<\\>\"\'\u4E00-\u9FA5]+$"); - - void checkProblem() { - controller.setProblem(null); - if (txtModpackLocation.getText().trim().isEmpty()) - controller.setProblem(C.i18n("modpack.not_a_valid_location")); - if (!PATTERN.matcher(txtModpackName.getText()).matches()) - controller.setProblem(C.i18n("modpack.not_a_valid_name")); - } - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JComboBox cboGameVersion; - private javax.swing.JButton cboModpackLocation; - private javax.swing.JCheckBox chkIncludeLauncher; - private javax.swing.JLabel jLabel1; - private javax.swing.JLabel jLabel2; - private javax.swing.JLabel lblGameVersion; - private javax.swing.JLabel lblModpackLocation; - private javax.swing.JTextField txtModpackLocation; - private javax.swing.JTextField txtModpackName; - // End of variables declaration//GEN-END:variables -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/modpack/ModpackWizard.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/modpack/ModpackWizard.java deleted file mode 100644 index e74aec2d5..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/modpack/ModpackWizard.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.ui.modpack; - -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Vector; -import javax.swing.JComponent; -import org.jackhuang.hmcl.core.GameException; -import org.jackhuang.hmcl.core.mod.ModpackManager; -import org.jackhuang.hmcl.core.version.MinecraftVersion; -import org.jackhuang.hmcl.setting.Config; -import org.jackhuang.hmcl.setting.Profile; -import org.jackhuang.hmcl.setting.Settings; -import org.jackhuang.hmcl.util.HMCLMinecraftService; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.util.Pair; -import org.jackhuang.hmcl.util.StrUtils; -import org.jackhuang.hmcl.util.Utils; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.util.sys.IOUtils; -import org.jackhuang.hmcl.util.sys.ZipEngine; -import org.jackhuang.hmcl.util.net.WebPage; -import org.jackhuang.hmcl.util.ui.checktree.CheckBoxTreeNode; -import org.jackhuang.hmcl.util.ui.wizard.spi.DeferredWizardResult; -import org.jackhuang.hmcl.util.ui.wizard.spi.ResultProgressHandle; -import org.jackhuang.hmcl.util.ui.wizard.spi.Summary; -import org.jackhuang.hmcl.util.ui.wizard.spi.WizardBranchController; -import org.jackhuang.hmcl.util.ui.wizard.spi.WizardController; -import org.jackhuang.hmcl.util.ui.wizard.spi.WizardException; -import org.jackhuang.hmcl.util.ui.wizard.spi.WizardPanelProvider; - -/** - * - * @author huangyuhui - */ -public class ModpackWizard extends WizardBranchController { - - static void process(CheckBoxTreeNode node, String basePath, List list) { - if (node == null) - return; - if (node.isSelected()) { - if (basePath.length() > "minecraft/".length()) - list.add(basePath.substring("minecraft/".length())); - return; - } - Enumeration e = node.children(); - for (; e.hasMoreElements();) { - CheckBoxTreeNode n = e.nextElement(); - String s; - if (n.getUserObject() instanceof Pair) - s = ((Pair) n.getUserObject()).key; - else - s = n.getUserObject().toString(); - process(n, basePath + "/" + s, list); - } - } - - public ModpackWizard(Profile profile) { - super(new WizardPanelProvider(C.i18n("modpack.wizard"), new String[] { C.i18n("modpack.wizard.step.1"), C.i18n("modpack.wizard.step.2"), C.i18n("modpack.wizard.step.3") }, new String[] { C.i18n("modpack.wizard.step.1.title"), C.i18n("modpack.wizard.step.2.title"), C.i18n("modpack.wizard.step.3.title") }) { - - @Override - protected Object finish(Map settings) throws WizardException { - return new DeferredWizardResult(false) { - @Override - public void start(Map settings, ResultProgressHandle progress) { - progress.setBusy("Processing modpack"); - ArrayList blackList = new ArrayList<>(ModpackManager.MODPACK_BLACK_LIST); - CheckBoxTreeNode root = (CheckBoxTreeNode) settings.get("blackList"); - process(root, "minecraft", blackList); - HashMap map = new HashMap(); - map.put("name", (String) settings.get(ModpackInitializationPanel.KEY_MODPACK_NAME)); - - if (settings.containsKey(ModpackDescriptionPanel.KEY_MODPACK_DESCRITION)) - try { - map.put("description", new org.markdown4j.Markdown4jProcessor().process((String) settings.get(ModpackDescriptionPanel.KEY_MODPACK_DESCRITION))); - } catch (IOException ex) { - progress.failed(C.i18n("modpack.export_error") + ": " + StrUtils.getStackTrace(ex), true); - } - try { - String gameVersion = (String) settings.get(ModpackInitializationPanel.KEY_GAME_VERSION); - String strLocation = (String) settings.get(ModpackInitializationPanel.KEY_MODPACK_LOCATION); - if (!strLocation.endsWith(".zip")) - strLocation += ".zip"; - File loc = new File(strLocation); - File modpack = loc; - if ((Boolean) settings.get(ModpackInitializationPanel.KEY_INCLUDING_LAUNCHER)) - modpack = new File(loc.getAbsolutePath() + ".temp"); - ModpackManager.export(modpack, profile.service().version(), gameVersion, blackList, map, - t -> t.putTextFile(C.GSON.toJson(((HMCLMinecraftService) profile.service()).getVersionSetting(gameVersion)), "minecraft/hmclversion.cfg")); - String summary = "" + C.i18n("modpack.export_finished") + ": " + loc.getAbsolutePath(); - boolean including = false; - if ((Boolean) settings.get(ModpackInitializationPanel.KEY_INCLUDING_LAUNCHER)) { - boolean flag = true; - try (ZipEngine engine = new ZipEngine(loc)) { - Config s = new Config(); - if (!IOUtils.isAbsolutePath(Settings.getInstance().getBgpath())) - s.setBgpath(Settings.getInstance().getBgpath()); - s.setDownloadType(Settings.getInstance().getDownloadType()); - engine.putTextFile(C.GSON.toJson(s), "hmcl.json"); - engine.putFile(modpack, "modpack.zip"); - File bg = new File("bg").getAbsoluteFile(); - if (bg.isDirectory()) - engine.putDirectory(bg); - bg = new File("background.png").getAbsoluteFile(); - if (bg.isFile()) - engine.putFile(bg, "background.png"); - bg = new File("background.jpg").getAbsoluteFile(); - if (bg.isFile()) - engine.putFile(bg, "background.jpg"); - for (URL u : Utils.getURL()) - try { - File f = new File(u.toURI()); - if (f.getName().endsWith(".exe") || f.getName().endsWith(".jar")) - engine.putFile(f, f.getName()); - } catch (IOException | URISyntaxException e) { - HMCLog.err("Failed to add launcher files.", e); - flag = false; - break; - } - } - if (flag) { - including = true; - if (!modpack.delete()) - HMCLog.warn("Failed to delete modpack.zip.temp, maybe the file is in using."); - } - } - summary += "
" + C.i18n(including ? "modpack.included_launcher" : "modpack.not_included_launcher") + ""; - progress.finished(new Summary(new WebPage(summary), null)); - } catch (IOException | GameException ex) { - HMCLog.err("Failed to export modpack", ex); - progress.failed(C.i18n("modpack.export_error") + ": " + StrUtils.getStackTrace(ex), true); - } - } - }; - } - - @Override - - protected JComponent createPanel(WizardController controller, String id, Map settings) { - switch (indexOfStep(id)) { - case 0: - Vector s = new Vector<>(profile.service().version().getVersionCount()); - for (MinecraftVersion v : profile.service().version().getVersions()) - if (!v.hidden) - s.add(v.id); - - controller.setForwardNavigationMode(WizardController.MODE_CAN_CONTINUE); - - return new ModpackInitializationPanel(controller, settings, s, profile.getSelectedVersion()); - case 1: - controller.setForwardNavigationMode(WizardController.MODE_CAN_CONTINUE_OR_FINISH); - - return new ModpackFileSelectionPanel(controller, settings, profile.service().baseDirectory(), ModpackManager.MODPACK_PREDICATE); - case 2: - controller.setForwardNavigationMode(WizardController.MODE_CAN_FINISH); - - return new ModpackDescriptionPanel(controller, settings); - default: - throw new IllegalArgumentException(id); - } - } - }); - } - - @Override - protected WizardPanelProvider getPanelProviderForStep(String step, Map settings) { - return null; - } - -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java deleted file mode 100755 index 969a4bb80..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/CrashReporter.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util; - -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.util.StrUtils; -import org.jackhuang.hmcl.util.ui.MessageBox; -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.swing.SwingUtilities; -import org.jackhuang.hmcl.api.HMCLog; -import static org.jackhuang.hmcl.Main.LAUNCHER_VERSION; -import org.jackhuang.hmcl.setting.Settings; -import org.jackhuang.hmcl.util.net.NetUtils; -import org.jackhuang.hmcl.util.sys.OS; -import org.jackhuang.hmcl.ui.LogWindow; - -/** - * - * @author huangyuhui - */ -public class CrashReporter implements Thread.UncaughtExceptionHandler { - - private static final Logger LOGGER = Logger.getLogger(CrashReporter.class.getName()); - - private static final HashMap SOURCE = new HashMap() { - { - put("MessageBox", ""); - put("AWTError", ""); - put("JFileChooser", "Has your operating system been installed completely or is a ghost system?"); - put("JSystemFileChooser", "Has your operating system been installed completely or is a ghost system?"); - put("Jce", "Has your operating system been installed completely or is a ghost system?"); - put("couldn't create component peer", "Fucking computer!"); - put("sun.awt.shell.Win32ShellFolder2", "crash.user_fault"); - put("UnsatisfiedLinkError", "crash.user_fault"); - put("java.awt.HeadlessException", "crash.headless"); - put("java.lang.NoClassDefFoundError", "crash.NoClassDefFound"); - put("java.lang.VerifyError", "crash.NoClassDefFound"); - put("java.lang.NoSuchMethodError", "crash.NoClassDefFound"); - put("java.lang.IncompatibleClassChangeError", "crash.NoClassDefFound"); - put("java.lang.ClassFormatError", "crash.NoClassDefFound"); - put("java.lang.OutOfMemoryError", "FUCKING MEMORY LIMIT!"); - put("Trampoline", "ui.message.update_java"); - put("NoSuchAlgorithmException", "Has your operating system been installed completely or is a ghost system?"); - } - }; - - boolean enableLogger = false; - - public CrashReporter(boolean enableLogger) { - this.enableLogger = enableLogger; - } - - public boolean checkThrowable(Throwable e) { - String s = StrUtils.getStackTrace(e); - for (HashMap.Entry entry : SOURCE.entrySet()) - if (s.contains(entry.getKey())) { - if (StrUtils.isNotBlank(entry.getValue())) { - String info = C.i18n(entry.getKey()); - LOGGER.severe(info); - try { - showMessage(info); - } catch (Throwable t) { - LOGGER.log(Level.SEVERE, "Failed to show message", t); - } - } - return false; - } - return true; - } - - @Override - public void uncaughtException(Thread t, Throwable e) { - String s = StrUtils.getStackTrace(e); - if (!s.contains("org.jackhuang")) - return; - try { - String text = "\n---- Hello Minecraft! Crash Report ----\n"; - text += " Version: " + LAUNCHER_VERSION + "\n"; - text += " Time: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "\n"; - text += " Thread: " + t.toString() + "\n"; - text += "\n Content: \n "; - text += s + "\n\n"; - text += "-- System Details --\n"; - text += " Operating System: " + OS.getSystemVersion() + "\n"; - text += " Java Version: " + System.getProperty("java.version") + ", " + System.getProperty("java.vendor") + "\n"; - text += " Java VM Version: " + System.getProperty("java.vm.name") + " (" + System.getProperty("java.vm.info") + "), " + System.getProperty("java.vm.vendor") + "\n"; - if (enableLogger) - HMCLog.err(text); - else - System.out.println(text); - - if (checkThrowable(e) && !System.getProperty("java.vm.name").contains("OpenJDK")) { - SwingUtilities.invokeLater(() -> LogWindow.INSTANCE.showAsCrashWindow(Settings.UPDATE_CHECKER.isOutOfDate())); - if (!Settings.UPDATE_CHECKER.isOutOfDate()) - reportToServer(text, s); - } - } catch (Throwable ex) { - LOGGER.log(Level.SEVERE, "Failed to caught exception", ex); - LOGGER.log(Level.SEVERE, "There is the original exception", e); - } - } - - void showMessage(String s) { - try { - MessageBox.show(s, "ERROR", MessageBox.ERROR_MESSAGE); - } catch (Throwable e) { - LOGGER.log(Level.SEVERE, "ERROR", e); - } - } - - private static final HashSet THROWABLE_SET = new HashSet<>(); - - void reportToServer(final String text, String stacktrace) { - if (THROWABLE_SET.contains(stacktrace) || stacktrace.contains("Font") || stacktrace.contains("InternalError")) - return; - THROWABLE_SET.add(stacktrace); - Thread t = new Thread(() -> { - HashMap map = new HashMap<>(); - map.put("CrashReport", text); - try { - NetUtils.post(NetUtils.constantURL("http://huangyuhui.duapp.com/crash.php"), map); - } catch (IOException ex) { - LOGGER.log(Level.SEVERE, "Failed to post HMCL server.", ex); - } - }); - t.setDaemon(true); - t.start(); - } - -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/DefaultPlugin.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/DefaultPlugin.java deleted file mode 100755 index 9127e3633..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/DefaultPlugin.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util; - -import java.util.ArrayList; -import javax.swing.JFrame; -import org.jackhuang.hmcl.api.ui.AddTabCallback; -import org.jackhuang.hmcl.api.IPlugin; -import org.jackhuang.hmcl.core.auth.OfflineAuthenticator; -import org.jackhuang.hmcl.core.auth.YggdrasilAuthenticator; -import org.jackhuang.hmcl.setting.Settings; -import org.jackhuang.hmcl.ui.GameSettingsPanel; -import org.jackhuang.hmcl.ui.LauncherSettingsPanel; -import org.jackhuang.hmcl.ui.MainPagePanel; -import org.jackhuang.hmcl.api.auth.IAuthenticator; -import org.jackhuang.hmcl.api.func.Consumer; -import org.jackhuang.hmcl.api.ui.Theme; -import org.jackhuang.hmcl.laf.LAFTheme; - -/** - * - * @author huangyuhui - */ -public class DefaultPlugin implements IPlugin { - public static DefaultPlugin INSTANCE; - - public DefaultPlugin() { - INSTANCE = this; - for (Theme t : LAFTheme.THEMES) - Theme.THEMES.put(t.getId(), t); - } - - ArrayList auths = new ArrayList<>(); - - @Override - public void onRegisterAuthenticators(Consumer apply) { - String clientToken = Settings.getInstance().getClientToken(); - auths.add(new OfflineAuthenticator(clientToken)); - auths.add(new YggdrasilAuthenticator(clientToken)); - - try { - Runtime.getRuntime().addShutdownHook(new Thread(this::saveAuthenticatorConfig)); - } catch (IllegalStateException ignore) { // Shutdown in progress - } - for (IAuthenticator i : auths) { - i.onLoadSettings(Settings.getInstance().getAuthenticatorConfig(i.id())); - apply.accept(i); - } - } - - public void saveAuthenticatorConfig() { - for (IAuthenticator i : auths) - Settings.getInstance().setAuthenticatorConfig(i.id(), i.onSaveSettings()); - } - - @Override - public void onAddTab(JFrame frame, AddTabCallback callback) { - callback.addTab(new MainPagePanel(), "main", C.i18n("launcher.title.main")); - callback.addTab(new GameSettingsPanel(), "game", C.i18n("launcher.title.game")); - callback.addTab(new LauncherSettingsPanel(), "launcher", C.i18n("launcher.title.launcher")); - } - -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/FileNameFilter.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/FileNameFilter.java deleted file mode 100755 index c8166bf92..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/FileNameFilter.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util; - -import java.io.File; -import javax.swing.filechooser.FileFilter; -import org.jackhuang.hmcl.util.sys.FileUtils; - -/** - * - * @author huangyuhui - */ -public class FileNameFilter extends FileFilter { - - String acceptedName; - - public FileNameFilter(String acceptedName) { - this.acceptedName = acceptedName; - } - - @Override - public boolean accept(File f) { - return f.isDirectory() || f.getName().equals(acceptedName) && !FileUtils.getExtension(f.getName()).equals("lnk"); - } - - @Override - public String getDescription() { - return acceptedName; - } -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/HMCLAssetService.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/HMCLAssetService.java deleted file mode 100644 index 08245ae5c..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/HMCLAssetService.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util; - -import java.io.File; -import org.jackhuang.hmcl.core.asset.MinecraftAssetService; -import org.jackhuang.hmcl.core.service.IMinecraftService; -import org.jackhuang.hmcl.setting.Settings; - -/** - * - * @author huang - */ -public class HMCLAssetService extends MinecraftAssetService { - - public HMCLAssetService(IMinecraftService service) { - super(service); - } - - private boolean useSelf(String assetId) { - return new File(service.baseDirectory(), "assets/indexes/" + assetId + ".json").exists() || ((HMCLMinecraftService) service).getProfile().isNoCommon(); - } - - @Override - public File getAssets(String assetId) { - if (useSelf(assetId)) - return new File(service.baseDirectory(), "assets"); - else - return new File(Settings.getInstance().getCommonpath(), "assets"); - } - -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/HMCLGameLauncher.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/HMCLGameLauncher.java deleted file mode 100644 index c076b5e71..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/HMCLGameLauncher.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util; - -import org.jackhuang.hmcl.core.GameException; -import org.jackhuang.hmcl.api.auth.AuthenticationException; -import org.jackhuang.hmcl.core.auth.AbstractAuthenticator; -import org.jackhuang.hmcl.api.auth.LoginInfo; -import org.jackhuang.hmcl.core.launch.DefaultGameLauncher; -import org.jackhuang.hmcl.core.launch.GameLauncher; -import org.jackhuang.hmcl.api.game.LaunchOptions; -import org.jackhuang.hmcl.setting.Profile; -import org.jackhuang.hmcl.setting.Settings; -import org.jackhuang.hmcl.api.HMCLApi; -import org.jackhuang.hmcl.api.event.launch.LaunchSucceededEvent; -import org.jackhuang.hmcl.api.event.launch.LaunchingState; -import org.jackhuang.hmcl.api.event.launch.LaunchingStateChangedEvent; -import org.jackhuang.hmcl.api.event.launch.ProcessingLaunchOptionsEvent; -import org.jackhuang.hmcl.core.RuntimeGameException; -import org.jackhuang.hmcl.api.func.Consumer; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.api.Wrapper; -import org.jackhuang.hmcl.util.sys.JavaProcess; -import org.jackhuang.hmcl.api.auth.IAuthenticator; - -/** - * - * @author huangyuhui - */ -public class HMCLGameLauncher { - - Profile profile; - boolean isLaunching = false; - - public HMCLGameLauncher(Profile p) { - this.profile = p; - - HMCLApi.EVENT_BUS.channel(LaunchSucceededEvent.class).register(() -> setLaunching(false)); - } - - void setLaunching(boolean isLaunching) { - if (isLaunching != this.isLaunching) - HMCLApi.EVENT_BUS.fireChannel(new LaunchingStateChangedEvent(this, isLaunching ? LaunchingState.Starting : LaunchingState.Done)); - this.isLaunching = isLaunching; - } - - public void genLaunchCode(final Consumer listener, final Consumer failed, String passwordIfNeeded) { - if (isLaunching || profile == null) - return; - setLaunching(true); - HMCLog.log("Start generating launching command..."); - if (!profile.getGameDir().exists()) { - failed.accept(C.i18n("minecraft.wrong_path")); - setLaunching(false); - return; - } - - if (profile.getSelectedVersion() == null) { - failed.accept(C.i18n("minecraft.no_selected_version")); - setLaunching(false); - return; - } - - final IAuthenticator l = AbstractAuthenticator.LOGINS.get(Settings.getInstance().getLoginType()); - final LoginInfo li = new LoginInfo(l.getUserName(), l.isLoggedIn() || !l.hasPassword() ? null : passwordIfNeeded); - Thread t = new Thread() { - @Override - public void run() { - Thread.currentThread().setName("Game Launcher"); - try { - Wrapper options = new Wrapper<>(profile.getSelectedVersionSetting().createLaunchOptions(profile.getGameDir())); - HMCLApi.EVENT_BUS.fireChannel(new ProcessingLaunchOptionsEvent(this, options)); - DefaultGameLauncher gl = new DefaultGameLauncher(options.getValue(), profile.service(), li, l); - GameLauncherTag tag = new GameLauncherTag(); - tag.launcherVisibility = profile.getSelectedVersionSetting().getLauncherVisibility(); - gl.setTag(tag); - listener.accept(gl); - gl.makeLaunchCommand(); - } catch (GameException | RuntimeGameException e) { - failed.accept(C.i18n("launch.failed") + ", " + e.getMessage()); - setLaunching(false); - } catch (AuthenticationException e) { - failed.accept(C.i18n("login.failed") + ", " + e.getMessage()); - setLaunching(false); - } - } - }; - t.setDaemon(true); - t.start(); - } - - public static class GameLauncherTag { - public LauncherVisibility launcherVisibility; - public JavaProcess process; - public int state; // 0 - unknown; 1 - launch; 2 - make launch script. - } -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/HMCLGameProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/HMCLGameProvider.java deleted file mode 100644 index b94e72668..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/HMCLGameProvider.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util; - -import java.io.File; -import org.jackhuang.hmcl.api.game.GameDirType; -import org.jackhuang.hmcl.api.game.IMinecraftLibrary; -import org.jackhuang.hmcl.core.version.MinecraftVersion; -import org.jackhuang.hmcl.core.version.MinecraftVersionManager; -import org.jackhuang.hmcl.setting.Settings; -import org.jackhuang.hmcl.setting.VersionSetting; - -/** - * - * @author huangyuhui - */ -public class HMCLGameProvider extends MinecraftVersionManager { - - public HMCLGameProvider(HMCLMinecraftService p) { - super(p); - } - - @Override - public File getLibraryFile(MinecraftVersion version, IMinecraftLibrary lib) { - VersionSetting vs = service.getProfile().getVersionSetting(version.id); - File self = super.getLibraryFile(version, lib); - if (self.exists() || (vs != null && service.getProfile().isNoCommon())) - return self; - else - return lib.getFilePath(new File(Settings.getInstance().getCommonpath())); - } - - @Override - public File getRunDirectory(String id) { - VersionSetting vs = service.getProfile().getVersionSetting(id); - if (vs == null) - return super.getRunDirectory(id); - else - return vs.getGameDirType() == GameDirType.VERSION_FOLDER - ? service.version().versionRoot(id) - : super.getRunDirectory(id); - } -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/HMCLMinecraftLoader.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/HMCLMinecraftLoader.java deleted file mode 100644 index 8cbf61049..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/HMCLMinecraftLoader.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util; - -import java.util.List; -import org.jackhuang.hmcl.Main; -import org.jackhuang.hmcl.api.auth.UserProfileProvider; -import org.jackhuang.hmcl.api.game.LaunchOptions; -import org.jackhuang.hmcl.core.GameException; -import org.jackhuang.hmcl.core.launch.MinecraftLoader; -import org.jackhuang.hmcl.core.service.IMinecraftService; - -/** - * - * @author huang - */ -public class HMCLMinecraftLoader extends MinecraftLoader { - - public HMCLMinecraftLoader(LaunchOptions p, IMinecraftService provider, UserProfileProvider lr) throws GameException { - super(p, provider, lr); - } - - @Override - protected void appendJVMArgs(List list) { - super.appendJVMArgs(list); - - list.add("-Dminecraft.launcher.version=" + Main.LAUNCHER_VERSION); - list.add("-Dminecraft.launcher.brand=" + Main.LAUNCHER_NAME); - - boolean flag = false; - for (String s : list) if (s.contains("-Dlog4j.configurationFile=")) flag = true; - if (!flag) { - list.add("-Dlog4j.configurationFile=" + Main.LOG4J_FILE.getAbsolutePath()); - } - } -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/HMCLMinecraftService.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/HMCLMinecraftService.java deleted file mode 100644 index fe726a85f..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/HMCLMinecraftService.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util; - -import org.jackhuang.hmcl.core.service.IMinecraftService; -import org.jackhuang.hmcl.core.service.IMinecraftLoader; -import org.jackhuang.hmcl.core.service.IMinecraftModService; -import com.google.gson.JsonSyntaxException; -import java.io.File; -import java.util.HashMap; -import java.util.Map; -import javax.swing.SwingUtilities; -import org.jackhuang.hmcl.api.HMCLApi; -import org.jackhuang.hmcl.api.event.version.LoadedOneVersionEvent; -import org.jackhuang.hmcl.api.event.version.RefreshedVersionsEvent; -import org.jackhuang.hmcl.api.event.version.RefreshingVersionsEvent; -import org.jackhuang.hmcl.core.GameException; -import org.jackhuang.hmcl.core.install.MinecraftInstallerService; -import org.jackhuang.hmcl.api.auth.UserProfileProvider; -import org.jackhuang.hmcl.core.download.MinecraftDownloadService; -import org.jackhuang.hmcl.api.game.LaunchOptions; -import org.jackhuang.hmcl.core.launch.MinecraftLoader; -import org.jackhuang.hmcl.core.mod.MinecraftModService; -import org.jackhuang.hmcl.core.mod.ModpackManager; -import org.jackhuang.hmcl.setting.Profile; -import org.jackhuang.hmcl.setting.VersionSetting; -import org.jackhuang.hmcl.ui.MainFrame; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.util.sys.FileUtils; -import org.jackhuang.hmcl.util.task.TaskWindow; - -/** - * - * @author huangyuhui - */ -public class HMCLMinecraftService extends IMinecraftService { - - private Profile p; - final Map versionSettings = new HashMap<>(); - - public HMCLMinecraftService(Profile p) { - this.p = p; - this.provider = new HMCLGameProvider(this); - provider.initializeMinecraft(); - HMCLApi.EVENT_BUS.channel(RefreshingVersionsEvent.class).register(versionSettings::clear); - HMCLApi.EVENT_BUS.channel(RefreshedVersionsEvent.class).registerFirst(() -> { - if (!checkingModpack) { - checkingModpack = true; - if (version().getVersionCount() == 0) { - File modpack = new File("modpack.zip").getAbsoluteFile(); - if (modpack.exists()) - SwingUtilities.invokeLater(() -> { - if (TaskWindow.factory().execute(ModpackManager.install(MainFrame.INSTANCE, modpack, this, null))) - version().refreshVersions(); - checkedModpack = true; - }); - } - } - }); - HMCLApi.EVENT_BUS.channel(LoadedOneVersionEvent.class).register(e -> loadVersionSetting(e.getValue())); - this.mms = new MinecraftModService(this); - this.mds = new MinecraftDownloadService(this); - this.mas = new HMCLAssetService(this); - this.mis = new MinecraftInstallerService(this); - } - - public boolean checkedModpack = false, checkingModpack = false; - - private void loadVersionSetting(String id) { - if (provider.getVersionById(id) == null) - return; - VersionSetting vs = null; - File f = new File(provider.versionRoot(id), "hmclversion.cfg"); - if (f.exists()) { - String s = FileUtils.readQuietly(f); - if (s != null) - try { - vs = C.GSON.fromJson(s, VersionSetting.class); - } catch (JsonSyntaxException ex) { - HMCLog.warn("Failed to load version setting: " + id, ex); - vs = null; - } - } - if (vs == null) - return; - initVersionSetting(id, vs); - } - - public void createVersionSetting(String id) { - if (provider.getVersionById(id) == null || versionSettings.containsKey(id)) - return; - initVersionSetting(id, new VersionSetting()); - } - - private void initVersionSetting(String id, VersionSetting vs) { - vs.id = id; - vs.propertyChanged.register(event -> saveVersionSetting(((VersionSetting) event.getSource()).id)); - versionSettings.put(id, vs); - } - - /** - * Get the version setting for version id. - * - * @param id version id - * - * @return may return null if the id not exists - */ - public VersionSetting getVersionSetting(String id) { - if (!versionSettings.containsKey(id)) - loadVersionSetting(id); - return versionSettings.get(id); - } - - public void saveVersionSetting(String id) { - if (!versionSettings.containsKey(id)) - return; - File f = new File(provider.versionRoot(id), "hmclversion.cfg"); - FileUtils.writeQuietly(f, C.GSON.toJson(versionSettings.get(id))); - } - - @Override - public File baseDirectory() { - return p.getGameDir(); - } - - protected HMCLGameProvider provider; - - @Override - public HMCLGameProvider version() { - return provider; - } - - protected MinecraftModService mms; - - @Override - public IMinecraftModService mod() { - return mms; - } - - protected MinecraftDownloadService mds; - - @Override - public MinecraftDownloadService download() { - return mds; - } - - final HMCLAssetService mas; - - @Override - public HMCLAssetService asset() { - return mas; - } - - protected MinecraftInstallerService mis; - - @Override - public MinecraftInstallerService install() { - return mis; - } - - @Override - public IMinecraftLoader launch(LaunchOptions options, UserProfileProvider p) throws GameException { - MinecraftLoader l = new HMCLMinecraftLoader(options, this, p); - l.setAssetProvider(mas.ASSET_PROVIDER_IMPL); - return l; - } - - public Profile getProfile() { - return p; - } - -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/LauncherVisibility.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/LauncherVisibility.java deleted file mode 100755 index 0ca1cfea9..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/LauncherVisibility.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util; - -/** - * - * @author huangyuhui - */ -public enum LauncherVisibility { - - /** - * Close the launcher anyway when the game process created even if failed to - * launch game. - */ - CLOSE, - /** - * Hide the launcher when the game process created, if failed to launch - * game, will show the log window. - */ - HIDE, - /** - * Keep the launcher visible even if the game launched successfully. - */ - KEEP, - /** - * Hide the launcher and reopen it when game closes. - */ - HIDE_AND_REOPEN -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/Log4jHandler.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/Log4jHandler.java deleted file mode 100644 index e113c26de..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/Log4jHandler.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util; - -import java.io.IOException; -import java.io.PipedInputStream; -import java.io.PipedOutputStream; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.LinkedList; -import java.util.List; -import javax.xml.parsers.ParserConfigurationException; -import org.jackhuang.hmcl.api.HMCLApi; -import org.jackhuang.hmcl.api.event.process.JavaProcessStoppedEvent; -import org.jackhuang.hmcl.api.func.Consumer; -import org.jackhuang.hmcl.ui.LogWindow; -import org.jackhuang.hmcl.util.log.Level; -import org.jackhuang.hmcl.util.sys.ProcessMonitor; -import org.xml.sax.Attributes; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; -import org.xml.sax.XMLReader; -import org.xml.sax.helpers.DefaultHandler; -import org.xml.sax.helpers.XMLReaderFactory; - -/** - * - * @author huang - */ -public class Log4jHandler extends Thread implements Consumer { - - XMLReader reader; - ProcessMonitor monitor; - PipedInputStream inputStream; - PipedOutputStream outputStream; - List> forbiddenTokens = new LinkedList<>(); - - public Log4jHandler(ProcessMonitor monitor, PipedOutputStream outputStream) throws ParserConfigurationException, IOException, SAXException { - reader = XMLReaderFactory.createXMLReader(); - inputStream = new PipedInputStream(outputStream); - this.outputStream = outputStream; - this.monitor = monitor; - - HMCLApi.EVENT_BUS.channel(JavaProcessStoppedEvent.class).register((Consumer) this); - } - - public void addForbiddenToken(String token, String replacement) { - forbiddenTokens.add(new Pair<>(token, replacement)); - } - - @Override - public void run() { - try { - outputStream.write("".getBytes()); - outputStream.flush(); - reader.setContentHandler(new Log4jHandlerImpl()); - reader.parse(new InputSource(inputStream)); - } catch (SAXException | IOException e) { - - } - } - - @Override - public void accept(JavaProcessStoppedEvent t) { - if (t.getSource() == monitor) { - try { - outputStream.write("".getBytes()); - outputStream.close(); - } catch (IOException ignore) { // won't happen - throw new Error(ignore); - } - } - } - - class Log4jHandlerImpl extends DefaultHandler { - private final SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss"); - - String date = "", thread = "", logger = ""; - StringBuilder message = null; - Level l = null; - boolean readingMessage = false; - - @Override - public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { - switch (localName) { - case "log4j_Event": - message = new StringBuilder(); - Date d = new Date(Long.valueOf(attributes.getValue("timestamp"))); - date = df.format(d); - try { - l = Level.valueOf(attributes.getValue("level")); - } catch(IllegalArgumentException e) { - l = Level.INFO; - } - thread = attributes.getValue("thread"); - logger = attributes.getValue("logger"); - if ("STDERR".equals(logger)) - l = Level.ERROR; - break; - case "log4j_Message": - readingMessage = true; - break; - } - } - - @Override - public void endElement(String uri, String localName, String qName) throws SAXException { - switch (localName) { - case "log4j_Event": - println("[" + date + "] [" + thread + "/" + l.name() + "] [" + logger + "] " + message.toString(), l); - break; - case "log4j_Message": - readingMessage = false; - break; - } - } - - @Override - public void characters(char[] ch, int start, int length) throws SAXException { - String line = new String(ch, start, length); - if (line.trim().isEmpty()) return; - if (readingMessage) - message.append(line).append(C.LINE_SEPARATOR); - else - println(line, Level.guessLevel(line)); - } - - public void println(String message, Level l) { - for (Pair entry : forbiddenTokens) - message = message.replace(entry.key, entry.value); - if (LogWindow.outputStream != null) - LogWindow.outputStream.log(message, l); - } - } -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/MinecraftCrashAdvicer.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/MinecraftCrashAdvicer.java deleted file mode 100755 index ed84f0f11..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/MinecraftCrashAdvicer.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util; - -import org.jackhuang.hmcl.util.lang.SupportedLocales; - -/** - * Give the advice to solve the Minecraft crashing. - * - * @author huangyuhui - */ -public final class MinecraftCrashAdvicer { - - public static String getAdvice(String trace) { - return getAdvice(trace, false); - } - - public static String getAdvice(String trace, boolean selfCrash) { - if (trace == null) - return C.i18n("crash.advice.no"); - trace = trace.toLowerCase(SupportedLocales.getNowLocale().self); - if (trace.contains("pixel format not accelerated")) - return C.i18n("crash.advice.LWJGLException"); - else if (trace.contains("unsupportedclassversionrrror")) - return C.i18n("crash.advice.UnsupportedClassVersionError"); - else if (trace.contains("concurrentmodificationexception")) - return C.i18n("crash.advice.ConcurrentModificationException"); - else if (trace.contains("securityexception")) - return C.i18n("crash.advice.SecurityException"); - else if (trace.contains("nosuchfieldexception") || trace.contains("nosuchmethodexception") || trace.contains("nosuchfielderror") || trace.contains("nosuchmethoderror")) - return C.i18n("crash.advice.NoSuchFieldError"); - else if (trace.contains("outofmemory") || trace.contains("out of memory")) - return C.i18n("crash.advice.OutOfMemoryError"); - else if (trace.contains("noclassdeffounderror") || trace.contains("classnotfoundexception")) - return C.i18n("crash.advice.ClassNotFoundException"); - else if (trace.contains("no lwjgl in java.library.path")) - return C.i18n("crash.advice.no_lwjgl"); - else if (trace.contains("opengl") || trace.contains("openal")) - return C.i18n("crash.advice.OpenGL"); - return C.i18n(selfCrash ? "crash.advice.no" : "crash.advice.otherwise"); - } - -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/upgrade/AppDataUpgrader.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/upgrade/AppDataUpgrader.java deleted file mode 100755 index 9d7d777ef..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/upgrade/AppDataUpgrader.java +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.upgrade; - -import com.google.gson.JsonSyntaxException; -import java.io.File; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.net.URLClassLoader; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.jar.JarFile; -import java.util.jar.JarOutputStream; -import java.util.jar.Pack200; -import java.util.logging.Level; -import java.util.zip.GZIPInputStream; -import org.jackhuang.hmcl.Main; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.api.event.SimpleEvent; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.core.MCUtils; -import org.jackhuang.hmcl.util.task.Task; -import org.jackhuang.hmcl.util.task.TaskWindow; -import org.jackhuang.hmcl.util.net.FileDownloadTask; -import org.jackhuang.hmcl.util.ArrayUtils; -import org.jackhuang.hmcl.util.ui.MessageBox; -import org.jackhuang.hmcl.util.UpdateChecker; -import org.jackhuang.hmcl.util.Utils; -import org.jackhuang.hmcl.api.VersionNumber; -import org.jackhuang.hmcl.util.StrUtils; -import org.jackhuang.hmcl.util.sys.FileUtils; -import org.jackhuang.hmcl.util.sys.IOUtils; -import org.jackhuang.hmcl.util.sys.OS; - -/** - * - * @author huangyuhui - */ -public class AppDataUpgrader extends IUpgrader { - - private boolean launchNewerVersion(String[] args, File jar) throws IOException, PrivilegedActionException { - try (JarFile jarFile = new JarFile(jar)) { - String mainClass = jarFile.getManifest().getMainAttributes().getValue("Main-Class"); - if (mainClass != null) { - ArrayList al = new ArrayList<>(Arrays.asList(args)); - al.add("--noupdate"); - AccessController.doPrivileged((PrivilegedExceptionAction) () -> { - new URLClassLoader(new URL[] { jar.toURI().toURL() }, - URLClassLoader.getSystemClassLoader().getParent()).loadClass(mainClass) - .getMethod("main", String[].class).invoke(null, new Object[] { al.toArray(new String[0]) }); - return null; - }); - return true; - } - } - return false; - } - - @Override - public void parseArguments(VersionNumber nowVersion, String[] args) { - File f = AppDataUpgraderPackGzTask.HMCL_VER_FILE; - if (!ArrayUtils.contains(args, "--noupdate")) - try { - if (f.exists()) { - Map m = C.GSON.fromJson(FileUtils.read(f), Map.class); - String s = m.get("ver"); - if (s != null && VersionNumber.check(s).compareTo(nowVersion) > 0) { - String j = m.get("loc"); - if (j != null) { - File jar = new File(j); - if (jar.exists() && launchNewerVersion(args, jar)) - System.exit(0); - } - } - } - } catch (JsonSyntaxException ex) { - f.delete(); - } catch (IOException | PrivilegedActionException t) { - HMCLog.err("Failed to execute newer version application", t); - } - } - - @Override - public void accept(SimpleEvent event) { - final VersionNumber version = event.getValue(); - ((UpdateChecker) event.getSource()).requestDownloadLink().reg(map -> { - if (MessageBox.show(C.i18n("update.newest_version") + version.firstVer + "." + version.secondVer + "." + version.thirdVer + "\n" - + C.i18n("update.should_open_link"), - MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION) - if (map != null && map.containsKey("jar") && !StrUtils.isBlank(map.get("jar"))) - try { - String hash = null; - if (map.containsKey("jarsha1")) - hash = map.get("jarsha1"); - if (TaskWindow.factory().append(new AppDataUpgraderJarTask(map.get("jar"), version.version, hash)).execute()) { - new ProcessBuilder(new String[] { IOUtils.getJavaDir(), "-jar", AppDataUpgraderJarTask.getSelf(version.version).getAbsolutePath() }).directory(new File("").getAbsoluteFile()).start(); - System.exit(0); - } - } catch (IOException ex) { - Main.LOGGER.log(Level.SEVERE, "Failed to create upgrader", ex); - } - else if (map != null && map.containsKey("pack") && !StrUtils.isBlank(map.get("pack"))) - try { - String hash = null; - if (map.containsKey("packsha1")) - hash = map.get("packsha1"); - if (TaskWindow.factory().append(new AppDataUpgraderPackGzTask(map.get("pack"), version.version, hash)).execute()) { - new ProcessBuilder(new String[] { IOUtils.getJavaDir(), "-jar", AppDataUpgraderPackGzTask.getSelf(version.version).getAbsolutePath() }).directory(new File("").getAbsoluteFile()).start(); - System.exit(0); - } - } catch (IOException ex) { - HMCLog.err("Failed to create upgrader", ex); - } - else { - String url = C.URL_PUBLISH; - if (map != null) - if (map.containsKey(OS.os().checked_name)) - url = map.get(OS.os().checked_name); - else if (map.containsKey(OS.UNKOWN.checked_name)) - url = map.get(OS.UNKOWN.checked_name); - if (url == null) - url = C.URL_PUBLISH; - try { - java.awt.Desktop.getDesktop().browse(new URI(url)); - } catch (URISyntaxException | IOException e) { - HMCLog.err("Failed to browse uri: " + url, e); - Utils.setClipborad(url); - MessageBox.show(C.i18n("update.no_browser")); - } - } - }).execute(); - } - - public static class AppDataUpgraderPackGzTask extends Task { - - public static final File BASE_FOLDER = MCUtils.getWorkingDirectory("hmcl"); - public static final File HMCL_VER_FILE = new File(BASE_FOLDER, "hmclver.json"); - - public static File getSelf(String ver) { - return new File(BASE_FOLDER, "HMCL-" + ver + ".jar"); - } - - private final String downloadLink, newestVersion, expectedHash; - File tempFile; - - public AppDataUpgraderPackGzTask(String downloadLink, String newestVersion, String hash) throws IOException { - this.downloadLink = downloadLink; - this.newestVersion = newestVersion; - this.expectedHash = hash; - tempFile = File.createTempFile("hmcl", ".pack.gz"); - } - - @Override - public Collection getDependTasks() { - return Arrays.asList(new FileDownloadTask(downloadLink, tempFile, expectedHash)); - } - - @Override - public void executeTask(boolean areDependTasksSucceeded) throws Exception { - if (!areDependTasksSucceeded) { - tempFile.delete(); - return; - } - HashMap json = new HashMap<>(); - File f = getSelf(newestVersion); - if (!FileUtils.makeDirectory(f.getParentFile())) - throw new IOException("Failed to make directories: " + f.getParent()); - - for (int i = 0; f.exists(); i++) - f = new File(BASE_FOLDER, "HMCL-" + newestVersion + (i > 0 ? "-" + i : "") + ".jar"); - if (!f.createNewFile()) - throw new IOException("Failed to create new file: " + f); - - try (JarOutputStream jos = new JarOutputStream(FileUtils.openOutputStream(f))) { - Pack200.newUnpacker().unpack(new GZIPInputStream(FileUtils.openInputStream(tempFile)), jos); - } - json.put("ver", newestVersion); - json.put("loc", f.getAbsolutePath()); - String result = C.GSON.toJson(json); - FileUtils.write(HMCL_VER_FILE, result); - } - - @Override - public String getInfo() { - return "Upgrade"; - } - - } - - public static class AppDataUpgraderJarTask extends Task { - - public static final File BASE_FOLDER = MCUtils.getWorkingDirectory("hmcl"); - public static final File HMCL_VER_FILE = new File(BASE_FOLDER, "hmclver.json"); - - public static File getSelf(String ver) { - return new File(BASE_FOLDER, "HMCL-" + ver + ".jar"); - } - - private final String downloadLink, newestVersion, expectedHash; - File tempFile; - - public AppDataUpgraderJarTask(String downloadLink, String newestVersion, String hash) throws IOException { - this.downloadLink = downloadLink; - this.newestVersion = newestVersion; - this.expectedHash = hash; - tempFile = File.createTempFile("hmcl", ".jar"); - } - - @Override - public Collection getDependTasks() { - return Arrays.asList(new FileDownloadTask(downloadLink, tempFile, expectedHash)); - } - - @Override - public void executeTask(boolean areDependTasksSucceeded) throws Exception { - if (!areDependTasksSucceeded) { - tempFile.delete(); - return; - } - HashMap json = new HashMap<>(); - File f = getSelf(newestVersion); - FileUtils.copyFile(tempFile, f); - json.put("ver", newestVersion); - json.put("loc", f.getAbsolutePath()); - String result = C.GSON.toJson(json); - FileUtils.write(HMCL_VER_FILE, result); - } - - @Override - public String getInfo() { - return "Upgrade"; - } - - } -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/upgrade/IUpgrader.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/upgrade/IUpgrader.java deleted file mode 100755 index 9812805e1..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/upgrade/IUpgrader.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.upgrade; - -import org.jackhuang.hmcl.api.event.SimpleEvent; -import org.jackhuang.hmcl.api.VersionNumber; -import org.jackhuang.hmcl.api.func.Consumer; - -/** - * - * @author huangyuhui - */ -public abstract class IUpgrader implements Consumer> { - - public static final IUpgrader NOW_UPGRADER = new AppDataUpgrader(); - - /** - * Paring arguments to decide on whether the upgrade is needed. - * - * @param nowVersion now launcher version - * @param args Application CommandLine Arguments - */ - public abstract void parseArguments(VersionNumber nowVersion, String[] args); - - /** - * Just download the new app. - * - * @param sender Should be VersionChecker - * @param number the newest version - * - * @return should return true - */ - @Override - public abstract void accept(SimpleEvent event); -} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/upgrade/NewFileUpgrader.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/upgrade/NewFileUpgrader.java deleted file mode 100755 index 19c1fc769..000000000 --- a/HMCL/src/main/java/org/jackhuang/hmcl/util/upgrade/NewFileUpgrader.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.upgrade; - -import java.io.File; -import java.io.IOException; -import org.jackhuang.hmcl.api.event.SimpleEvent; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.util.task.TaskWindow; -import org.jackhuang.hmcl.util.net.FileDownloadTask; -import org.jackhuang.hmcl.util.ArrayUtils; -import org.jackhuang.hmcl.api.VersionNumber; -import org.jackhuang.hmcl.util.sys.FileUtils; -import org.jackhuang.hmcl.util.sys.IOUtils; - -/** - * - * @author huangyuhui - */ -public class NewFileUpgrader extends IUpgrader { - - @Override - public void parseArguments(VersionNumber nowVersion, String[] args) { - int i = ArrayUtils.indexOf(args, "--removeOldLauncher"); - if (i != -1 && i < args.length - 1) { - File f = new File(args[i + 1]); - if (f.exists()) - f.deleteOnExit(); - } - } - - @Override - public void accept(SimpleEvent event) { - String str = requestDownloadLink(); - File newf = new File(FileUtils.getName(str)); - if (TaskWindow.factory().append(new FileDownloadTask(str, newf)).execute()) { - try { - new ProcessBuilder(new String[] { newf.getCanonicalPath(), "--removeOldLauncher", IOUtils.getRealPath() }).directory(new File("").getAbsoluteFile()).start(); - } catch (IOException ex) { - HMCLog.err("Failed to start new app", ex); - } - System.exit(0); - } - } - - private String requestDownloadLink() { - return null; - } - -} diff --git a/HMCL/src/main/resources/org/jackhuang/hmcl/background.jpg b/HMCL/src/main/resources/org/jackhuang/hmcl/background.jpg deleted file mode 100644 index bc7389d5240aa9bb28de1b8002041fae69cd8bf2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 83434 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%0D8a)@Q+M#4gX* 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 z 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 a)_jYGld(;6j&K9RfWgz%&t;ucLK6VQTB1Av diff --git a/HMCL/src/main/resources/org/jackhuang/hmcl/icon-new.png b/HMCL/src/main/resources/org/jackhuang/hmcl/icon-new.png deleted file mode 100644 index 1cbfd01d295f6d77133001491fdfefb8aa2672b7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28154 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
  • dnmJZA8q#&MkaaMdygpVo`6Ey@$@a)&eRoPKm3# zE8LXv7}#ft2yKOxtntEJ)sjQbJUeESfzOeCbo^wk)X3V~t=WQ-2hd?N*&fCg^d~Yi z675F2GSbb-k|&#cq-oD?OLt$;_qpnRXU#I<+|a%BmC}BN?q>yG7Vw7CoRI$a5fI0r zqcYwco!LIBkKcE_Cr_NXZQq1FdDv{Bj`@Oo?`44Hh$L)p>vvMZj{#QW z(7|pTwJ{R8d+j97j=kyUeXGafD62vroTtPuGBYx03GLhSTx2qD+{gr8<(zpM8HCl7 z-(^RpW@uMjLhx(%ohB;G7lQHEX>LOG-Ro)P+#NeuEcTuz%Wa+#D9JZ-;DI48^fqY@hLR#Uz%%?uj{TjyqJ#a zseLN?#^7Cky?8c4&392;%<;-+;>Q4+3UnrNfCQxkEi~ZC9#BGz4F^gPL#ju!wW|yx z_Rqgg&yQtJq zlr&T=8fXOfbfAq4nLeR$0hH9eJ2Y@Ft7hoUz>sHJUF0R1uPp7J-?k01SlC~fqc}=h z#eX>!lm#sYO<&IzPg!Xr*0YoDY(X2rJua!;fH$=@MHa^+Z|(4i3vPaSg^&RZ)gzx$H4Xa1kO>$R$BiR+I8tKcX zkC(}f-w{r;-a}_2$eUb&0*gx5^yP+64Ie=`72bs{Ux zbzvyeBh=iW3`<8Fmc68u`G__uqFOeW9Gb*&R9B&4#%@1mpy=0{{p;Y~f4Z-q1-rj` zBcZ1`c-if)AAEeT3-U~tc%udhvup77ws*FerMVaGr(XTo;fs*OqsA483Qw)pjaFgl zcX$}LgDq7*nTIOKxH9~Gseq6oiw~+bd|hE2WMOoz>+C5b6f;I|U39rXT0BJN`1IRY z^X!rATgBL+;c`r92fj`B9?Q3>On1!F0Q0O~ql|`@xrr9UYPJ^P5B%g z>UhvxM?T}>_Fo$p7+V z*2V8HwUMhmZ1R$R<-qS6XN`e4bDckPGD6M zee4#cL(|0fLY5N8UcP7IZDXt#lyOlH0#qUkgR+R?Rb2(wIY*RF(CD*$mOKJ;j~B6{ z3@LcqyG(2EeIGb7Wr$2G`lNQsn%GMG<74NeQ|nLLu2tufrgG&v`VMxyBc$jKpXvLX zR)@o19SGCo0>lMVQqOP`uLf+{tcP+Ob`;8V z?ws|@3ekw0MO-h^;J~rlsXh8+- z5%9LGH^i!{CJjw64e}%>1UFmEh>|X7hn*_8MXqyfX1T&|G`5D_!G-8w2B5+DNSsXl zItxrimVT6%1nu;+ezD3b0v*(=Gu~2jrfyk-<6u>o*fY%>#>4HnNeM?hUiU#vm^i!k z`NPFCs_BdUEmO zb21ljRLb82@pUUr=EoWIPdH4L9S(8S23StS+qUC}WxRR&580uOQQXK~=8JY`PM#%E zRx=$ZGB{g_wOcco?V)kU*w+OJc)f4G3kt&MxBESi*rV0Nxk#HM4d^4Wwvy#J7Y)mc z0T{K{9y#t@xOruD&CHu^=$Ip|G60mZ=X`hj<>{?pE4|AAmQ1;;h0C9w3%cuDnr9Bw#K_C4n~tDwIJr%Z}LIS?pU7` z>+*(g7Rk)oh1Q`B@;X->?2Oq`>t^aFZUnXUE{2z{suP)%aKbQ0S>mm8sJ`>*iInIuii zs4U{cl)p#iucMr+3T7j@_FKK3`2vEt!mwMDr@5;F=Y_5{93;-Fshb4Kz@s#8_Zzka z$%wlQDPSRLS(Xx56Y1MQ=G!=%B8NPUa@Xo`MY{w!uPiSq&TyMbiwwX$OSiodo@^4p zOYZuDMht3_WD0L;SS~PlXU)LzT?{vk_+%4|7B19DmN5@aQUy~F$vGAas%M&4_MV{I z{01E?1CoEH8=GYs$>R+_NrlpA@Yw?(6UFrj-78ab#FHnv*Wj0wAQYwJ^AAi!c=?_E2#rZOv#-+*=WZuPo(|U;Z?pJtfO%yW;c7{Pi&uS%aG6JB!K<2k@KG3-XJor}luxC`gX&$lcrB&O zt>vml=uh_Re3jdnKNas&*}FP)vEl2N=br9o=FEFQNAfM5xvXWsh~Dt^;^5^|PUY#DJU{$qs8IZ;7jRx7bDu60IH4*m(p$ z#rYZBYI?VWtq5EIh_ss}9(|uVZ`YC+6qB>G`%<;^~!*% zBcv#`wblqP6R2DY?HQv5Z`7M&M$AIJcR*YGK@ksm6diEGxk#5cHXotEq{~%SvrsT- zqs+HRG!Hp+NGu<9zi_e1(!op^I|9PZ z)^t1!gF7aaG&5%T%*3E$?7^-BVfn8b`a%-apR7Mht$~J;I-wie%BPQI#~v3)WJ0Nq zP-@tB!2dbP9ZvQNj@(y`UddD5O4 zF_Opj-0ZG-2x#0YE2_z5RV`}`BIf8=cS@Dvt_Z&XB-}v&U zsU|yQo0X&uB|@ww;wPC-GL(4L@wh!!5CIFl)H;4pFD$}{`K59-F{doB_0y|pw| zacnp^8*;~*05`=H?0f|2 zjo4}~M+ZSwnpR?48i>{Q!;o28_(wpEeSRfB&HD0Zg6WR57W@=|fYTTI4S%(T@=sIi zzf+E)r~c)B+t>NoPT%}jtiLGtr~4u>ssCP2k7@E>koY=3c+CQ*|4ss)a^PgEKYX#v zM4A5ei*l~?&+x}x#AiQ+uxXH1><6JHU!uVnSVCQOtoR{0S*QNVj|RaX77@XsB&H55 zg)|<~Dq%@eyTN(%(^S4gd^y^LW zn6B6t?f#3Ve9`VdA@Oy7W{Am!FiXlb+b{a#i+W5Gv7Ns8>-0RPul-B8e>wfXm-~Ma z;Xm5_^(s?NZb{RQ0k<|n2I-)jMpL8N5-#044TMn}1K-)C-!TKYTf3{Qnc9 Z5;|-;2h(UC8LemZo#%nw6+1&S{sTA*fqDP{ diff --git a/HMCL/src/main/resources/org/jackhuang/hmcl/icon.png b/HMCL/src/main/resources/org/jackhuang/hmcl/icon.png deleted file mode 100755 index 25f3cf6c80eeddc17c9e24683ac340ea142427a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5362 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 Qng9R*07*qoM6N<$f=Q}6H2?qr diff --git a/HMCL/src/main/resources/org/jackhuang/hmcl/log4j.xml b/HMCL/src/main/resources/org/jackhuang/hmcl/log4j.xml deleted file mode 100644 index 609a674ff..000000000 --- a/HMCL/src/main/resources/org/jackhuang/hmcl/log4j.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/HMCL/src/main/resources/org/jackhuang/hmcl/minimize.png b/HMCL/src/main/resources/org/jackhuang/hmcl/minimize.png deleted file mode 100755 index 25de72edb80cc8f1554c7a822d1ff79f6b4fdc9f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 232 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4fEX7WqAsj$Z!;#Vf4nJ z@XY~XM)oPecY%U3C9V-A!TD(=<%vb942~)JNvR5MnMJAP`9;~q3eLf1FZOKe0jf*# zba4!^=zV)-BX6^V0Ly`c0WFW$Gka}x$@VBoy8cmU=IjmkELmcl8cL++ZCTvCEqm=w zrGD=#Ey8{l4-?w{F1%*-s5O1T|D#b}mGckHFj&lgz&?lLpuEl_dHH}BMK9iS|7Tpi XL1>Cr^zXAk+Za4u{an^LB{Ts5oJmp; diff --git a/HMCLAPI/build.gradle b/HMCLAPI/build.gradle deleted file mode 100644 index ec9ac0aa8..000000000 --- a/HMCLAPI/build.gradle +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ - -plugins { - id "me.tatarka.retrolambda" version "3.5.0" - //id "org.jetbrains.kotlin.jvm" version "1.1.2-2" -} - -if (System.getenv("BUILD_NUMBER") != null) - version = System.getenv("BUILD_NUMBER") - -retrolambda { - javaVersion = JavaVersion.VERSION_1_7 -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/HMCLApi.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/HMCLApi.java deleted file mode 100644 index 080880a8f..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/HMCLApi.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api; - -import org.jackhuang.hmcl.api.event.EventBus; - -/** - * - * @author huang - */ -public class HMCLApi { - - /** - * Events. - */ - public static final EventBus EVENT_BUS = new EventBus(); - - public static VersionNumber HMCL_VERSION; -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/HMCLog.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/HMCLog.java deleted file mode 100644 index 6994b63ac..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/HMCLog.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api; - -import org.jackhuang.hmcl.api.ILogger; - -/** - * - * @author huangyuhui - */ -public class HMCLog { - - public static ILogger LOGGER; - - public static void log(String message) { - LOGGER.log(message); - } - - public static void warn(String message) { - LOGGER.warn(message); - } - - public static void warn(String msg, Throwable t) { - LOGGER.warn(msg, t); - } - - public static void err(String msg) { - LOGGER.err(msg); - } - - public static void err(String msg, Throwable t) { - LOGGER.err(msg, t); - } - -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/ILogger.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/ILogger.java deleted file mode 100644 index c9bafe118..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/ILogger.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api; - -/** - * - * @author huangyuhui - */ -public interface ILogger { - - void log(String message); - - void warn(String message); - - void warn(String msg, Throwable t); - - void err(String msg); - - void err(String msg, Throwable t); -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/IPlugin.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/IPlugin.java deleted file mode 100644 index fceb9d505..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/IPlugin.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api; - -import org.jackhuang.hmcl.api.ui.AddTabCallback; -import javax.swing.JFrame; -import org.jackhuang.hmcl.api.auth.IAuthenticator; -import org.jackhuang.hmcl.api.func.Consumer; - -/** - * Each plugin must implement this interface. - * - * @author huangyuhui - */ -public interface IPlugin { - - /** - * Register authenticators by calling IAuthenticator.LOGINS.add. - * - * @param apply call apply.accept(your authenticator) - */ - void onRegisterAuthenticators(Consumer apply); - - /** - * Call callback.addTab to add your customized panel to MainFrame RootPane. - * - * @param frame MainFrame - * @param callback call this if you want. - */ - void onAddTab(JFrame frame, AddTabCallback callback); -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/IProcess.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/IProcess.java deleted file mode 100644 index 93f073733..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/IProcess.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api; - -import java.util.List; - -/** - * - * @author huang - */ -public interface IProcess { - - int getExitCode(); - - Process getRawProcess(); - - String getStartupCommand(); - - List getStartupCommands(); - - List getStdOutLines(); - - boolean isRunning(); - - void stop(); - -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/PluginManager.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/PluginManager.java deleted file mode 100644 index 932439a8b..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/PluginManager.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api; - -import java.io.File; -import java.io.IOException; -import java.net.URL; -import java.net.URLClassLoader; -import org.jackhuang.hmcl.api.ui.AddTabCallback; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; -import javax.swing.JFrame; -import org.jackhuang.hmcl.api.auth.IAuthenticator; -import org.jackhuang.hmcl.api.func.Consumer; - -/** - * Can be only called by HMCL. - * - * @author huangyuhui - */ -public class PluginManager { - - private static final File PLUGINS_FILE = new File("plugins").getAbsoluteFile(); - private static final ArrayList PLUGINS = new ArrayList<>(); - - public static void getPlugin(Class cls) { - try { - IPlugin p = (IPlugin) cls.newInstance(); - PLUGINS.add(p); - } catch (Throwable e) { - System.err.println("Failed to new instance"); - e.printStackTrace(); - } - } - - public static void fireRegisterAuthenticators(Consumer callback) { - for (IPlugin p : PLUGINS) - p.onRegisterAuthenticators(callback); - } - - public static void fireAddTab(JFrame frame, AddTabCallback callback) { - for (IPlugin p : PLUGINS) - p.onAddTab(frame, callback); - } - - public static void loadPlugins() { - ArrayList urls = new ArrayList<>(); - ArrayList jars = new ArrayList<>(); - if (PLUGINS_FILE.isDirectory()) { - for (File f : PLUGINS_FILE.listFiles(f -> f.isFile() && f.getName().endsWith(".jar"))) - try { - jars.add(new JarFile(f)); - urls.add(f.toURI().toURL()); - } catch (IOException e) { - System.err.println("A malformed jar file: " + f); - e.printStackTrace(); - } - - URLClassLoader classLoader = new URLClassLoader(urls.toArray(new URL[urls.size()])); - for (JarFile f : jars) - for (Enumeration entries = f.entries(); entries.hasMoreElements();) - try { - JarEntry entry = entries.nextElement(); - String clsName = entry.getName(); - if (clsName.endsWith(".class") && !clsName.contains("$")) { - clsName = clsName.replace('/', '.').replace(".class", ""); - Class clazz = classLoader.loadClass(clsName); - if (IPlugin.class.isAssignableFrom(clazz)) - getPlugin(clazz); - } - } catch (ClassNotFoundException ex) { - ex.printStackTrace(); - } - } - } - -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/VersionNumber.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/VersionNumber.java deleted file mode 100644 index 50d7ef5e2..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/VersionNumber.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api; - -/** - * - * @author huangyuhui - */ -public final class VersionNumber implements Comparable { - - public final byte firstVer, secondVer, thirdVer; - public final String version; - - public VersionNumber(byte a, byte b, byte c) { - this(a, b, c, null); - } - - public VersionNumber(byte a, byte b, byte c, String version) { - firstVer = a; - secondVer = b; - thirdVer = c; - this.version = version; - } - - @Override - public String toString() { - return "" + firstVer + '.' + secondVer + '.' + thirdVer; - } - - public static VersionNumber check(String data) { - while (!data.isEmpty() && ((data.charAt(0) < '0' || data.charAt(0) > '9') && data.charAt(0) != '.')) - data = data.substring(1); - if (data.isEmpty()) - return null; - VersionNumber ur; - String[] ver = data.split("\\."); - if (ver.length >= 3) { - byte v1, v2, v3; - try { - v1 = Byte.parseByte(ver[0]); - v2 = Byte.parseByte(ver[1]); - v3 = Byte.parseByte(ver[2]); - ur = new VersionNumber(v1, v2, v3, data); - return ur; - } catch (Exception e) { - HMCLog.warn("Failed to parse the version", e); - } - } - return null; - } - - public static boolean isOlder(VersionNumber a, VersionNumber b) { - if (a.firstVer < b.firstVer) - return true; - else if (a.firstVer == b.firstVer) - if (a.secondVer < b.secondVer) - return true; - else if (a.secondVer == b.secondVer) - if (a.thirdVer < b.thirdVer) - return true; - return false; - } - - @Override - public int hashCode() { - int hash = 3; - hash = 83 * hash + this.firstVer; - hash = 83 * hash + this.secondVer; - hash = 83 * hash + this.thirdVer; - return hash; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - final VersionNumber other = (VersionNumber) obj; - if (this.firstVer != other.firstVer) - return false; - if (this.secondVer != other.secondVer) - return false; - if (this.thirdVer != other.thirdVer) - return false; - return true; - } - - @Override - public int compareTo(VersionNumber o) { - if (isOlder(this, o)) - return -1; - else if (isOlder(o, this)) - return 1; - else - return 0; - } - -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/Wrapper.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/Wrapper.java deleted file mode 100644 index 127f001b0..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/Wrapper.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api; - -/** - * - * @author huang - */ -public class Wrapper { - T value; - - public Wrapper(T value) { - this.value = value; - } - - public T getValue() { - return value; - } - - public void setValue(T value) { - this.value = value; - } - -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/auth/AuthenticationException.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/auth/AuthenticationException.java deleted file mode 100644 index 0c7ac36e2..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/auth/AuthenticationException.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.auth; - -/** - * Thrown if we are trying to log in but there's some problems like password wrong. - * - * @author huangyuhui - */ -public class AuthenticationException extends Exception { - - public AuthenticationException() { - } - - public AuthenticationException(String message) { - super(message); - } - - public AuthenticationException(String message, Throwable cause) { - super(message, cause); - } - - public AuthenticationException(Throwable cause) { - super(cause); - } -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/auth/IAuthenticator.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/auth/IAuthenticator.java deleted file mode 100644 index d6daf2751..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/auth/IAuthenticator.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.auth; - -import java.util.Map; - -/** - * - * @author huang - */ -public interface IAuthenticator { - - /** - * - * @return the name of login method. - */ - String getName(); - - String getPassword(); - - String getUserName(); - - /** - * Has password? - * - * @return has password? - */ - boolean hasPassword(); - - String id(); - - boolean isLoggedIn(); - - void logOut(); - - /** - * Login Method - * - * @param info username & password - * - * @return login result - * - * @throws - * org.jackhuang.hmcl.core.auth.AuthenticationException - */ - UserProfileProvider login(LoginInfo info) throws AuthenticationException; - - UserProfileProvider loginBySettings() throws AuthenticationException; - - void onLoadSettings(Map m); - - Map onSaveSettings(); - - void setPassword(String password); - - void setRememberMe(boolean is); - - void setUserName(String s); - -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/auth/LoginInfo.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/auth/LoginInfo.java deleted file mode 100644 index b26400b33..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/auth/LoginInfo.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.auth; - -/** - * - * @author huangyuhui - */ -public final class LoginInfo { - - public String username, password; - - public LoginInfo(String username, String password) { - this.username = username; - this.password = password; - } -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/auth/UserProfileProvider.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/auth/UserProfileProvider.java deleted file mode 100644 index 06000351b..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/auth/UserProfileProvider.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.auth; - -/** - * - * @author huangyuhui - */ -public final class UserProfileProvider { - - public String getUserName() { - return username; - } - - public UserProfileProvider setUserName(String username) { - this.username = username; - return this; - } - - public String getUserId() { - return userId; - } - - public UserProfileProvider setUserId(String userId) { - this.userId = userId; - return this; - } - - public String getSession() { - return session; - } - - public UserProfileProvider setSession(String session) { - this.session = session; - return this; - } - - public String getAccessToken() { - return accessToken; - } - - public UserProfileProvider setAccessToken(String accessToken) { - if (accessToken == null) - accessToken = "0"; - this.accessToken = accessToken; - return this; - } - - public String getUserProperties() { - return userProperties; - } - - public UserProfileProvider setUserProperties(String userProperties) { - this.userProperties = userProperties; - return this; - } - - public String getUserPropertyMap() { - return userPropertyMap; - } - - public UserProfileProvider setUserPropertyMap(String userPropertyMap) { - this.userPropertyMap = userPropertyMap; - return this; - } - - public String getOtherInfo() { - return otherInfo; - } - - public UserProfileProvider setOtherInfo(String otherInfo) { - this.otherInfo = otherInfo; - return this; - } - - public String getClientIdentifier() { - return clientIdentifier; - } - - public UserProfileProvider setClientIdentifier(String clientIdentifier) { - this.clientIdentifier = clientIdentifier; - return this; - } - - public String getUserType() { - return userType; - } - - public UserProfileProvider setUserType(String userType) { - this.userType = userType; - return this; - } - - private String username = ""; - private String userId = ""; - private String session = ""; - private String accessToken = ""; - private String userProperties = "{}"; - private String userPropertyMap = "{}"; - private String otherInfo = ""; - private String clientIdentifier = ""; - private String userType = "Offline"; -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/EventBus.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/EventBus.java deleted file mode 100644 index 736d94ae0..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/EventBus.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.event; - -import java.util.EventObject; -import java.util.HashMap; - -/** - * - * @author huang - */ -public class EventBus { - - HashMap events = new HashMap<>(); - - public EventBus() { - } - - public EventHandler channel(Class classOfT) { - if (!events.containsKey(classOfT)) - events.put(classOfT, new EventHandler<>()); - return events.get(classOfT); - } - - public void fireChannel(EventObject obj) { - channel((Class) obj.getClass()).fire(obj); - } - - public boolean fireChannelResulted(ResultedEvent obj) { - return channel((Class) obj.getClass()).fireResulted(obj); - } - -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/EventHandler.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/EventHandler.java deleted file mode 100644 index b7402a6d3..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/EventHandler.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.event; - -import java.util.ArrayList; -import java.util.EventObject; -import org.jackhuang.hmcl.api.func.Consumer; - -/** - * - * @author huangyuhui - * @param EventArgs - */ -public class EventHandler { - - ArrayList events = new ArrayList<>(); - - public EventHandler() { - } - - public void register(Consumer t) { - if (!events.contains(t)) - events.add(t); - } - - public void registerFirst(Consumer t) { - if (!events.contains(t)) - events.add(0, t); - } - - public void register(Runnable t) { - if (!events.contains(t)) - events.add(t); - } - - public void registerFirst(Runnable t) { - if (!events.contains(t)) - events.add(0, t); - } - - public void fire(T x) { - for (Object t : events) - if (t instanceof Consumer) { - ((Consumer) t).accept(x); - } else if (t instanceof Runnable) - ((Runnable) t).run(); - } - - public boolean fireResulted(T x) { - if (!(x instanceof ResultedEvent)) - throw new IllegalArgumentException("x should be ResultedEvent"); - ResultedEvent event = (ResultedEvent) x; - boolean flag = true; - for (Object t : events) - if (t instanceof Consumer) { - ((Consumer) t).accept(x); - if (!event.result()) - flag = false; - } else if (t instanceof Runnable) - ((Runnable) t).run(); - return flag; - } - -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/OutOfDateEvent.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/OutOfDateEvent.java deleted file mode 100644 index a5da93e61..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/OutOfDateEvent.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.event; - -import org.jackhuang.hmcl.api.VersionNumber; - -/** - * This event gets fired when we found that user's HMCL is out of date. - *
    - * This event is {@link org.jackhuang.hmcl.api.ResultedEvent} - * If this event is failed, HMCL will not ask user to upgrade the application. - *
    - * This event is fired on the {@link org.jackhuang.hmcl.api.HMCLApi#EVENT_BUS} - * @param source {@link org.jackhuang.hmcl.util.UpdateChecker} - * @param VersionNumber newest version - * @author huang - */ -public class OutOfDateEvent extends ResultedSimpleEvent { - - public OutOfDateEvent(Object source, VersionNumber value) { - super(source, value); - } - -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/PropertyChangedEvent.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/PropertyChangedEvent.java deleted file mode 100644 index 0b965830a..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/PropertyChangedEvent.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.event; - -import java.util.EventObject; - -/** - * - * @author huang - */ -public class PropertyChangedEvent extends EventObject { - - String propertyName; - T oldValue, newValue; - - public PropertyChangedEvent(Object source, String propertyName, T oldValue, T newValue) { - super(source); - this.propertyName = propertyName; - this.oldValue = oldValue; - this.newValue = newValue; - } - - public String getPropertyName() { - return propertyName; - } - - public T getNewValue() { - return newValue; - } - - public T getOldValue() { - return oldValue; - } -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/ResultedEvent.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/ResultedEvent.java deleted file mode 100644 index a0b0a7bb2..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/ResultedEvent.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.event; - -import java.util.EventObject; - -/** - * - * @author huang - */ -public class ResultedEvent extends EventObject { - protected boolean result = true; - - public ResultedEvent(Object sender) { - super(sender); - } - - public boolean result() { - return result; - } - - public void failed() { - setResult(false); - } - - public void setResult(boolean canceled) { - this.result = canceled; - } -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/ResultedSimpleEvent.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/ResultedSimpleEvent.java deleted file mode 100644 index 327ee41ad..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/ResultedSimpleEvent.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.event; - -/** - * - * @author huang - */ -public class ResultedSimpleEvent extends ResultedEvent { - - T value; - - public ResultedSimpleEvent(Object sender, T t) { - super(sender); - value = t; - } - - public T getValue() { - return value; - } - - public void setValue(T value) { - this.value = value; - } - -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/SimpleEvent.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/SimpleEvent.java deleted file mode 100644 index a0da11493..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/SimpleEvent.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.event; - -import java.util.EventObject; - -/** - * - * @author huang - */ -public class SimpleEvent extends EventObject { - private T value; - - public SimpleEvent(Object source, T value) { - super(source); - this.value = value; - } - - public T getValue() { - return value; - } - - public void setValue(T value) { - this.value = value; - } -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/config/AuthenticatorChangedEvent.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/config/AuthenticatorChangedEvent.java deleted file mode 100644 index 4835002fa..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/config/AuthenticatorChangedEvent.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.event.config; - -import org.jackhuang.hmcl.api.event.SimpleEvent; -import org.jackhuang.hmcl.api.auth.IAuthenticator; - -/** - * This event gets fired when the authenticator changed. - *
    - * This event is fired on the {@link org.jackhuang.hmcl.api.HMCLApi#EVENT_BUS} - * @param source {@link org.jackhuang.hmcl.setting.Config} - * @param IAuthenticator the new authenticator. - * @author huangyuhui - */ -public class AuthenticatorChangedEvent extends SimpleEvent { - - public AuthenticatorChangedEvent(Object source, IAuthenticator value) { - super(source, value); - } - -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/config/DownloadTypeChangedEvent.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/config/DownloadTypeChangedEvent.java deleted file mode 100644 index e1fd7baeb..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/config/DownloadTypeChangedEvent.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.event.config; - -import org.jackhuang.hmcl.api.event.SimpleEvent; - -/** - * This event gets fired when the download type changed. - *
    - * This event is fired on the {@link org.jackhuang.hmcl.api.HMCLApi#EVENT_BUS} - * @param source {@link org.jackhuang.hmcl.setting.Config} - * @param String the new downlaod type name - * @author huangyuhui - */ -public class DownloadTypeChangedEvent extends SimpleEvent { - - public DownloadTypeChangedEvent(Object source, String value) { - super(source, value); - } - -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/config/ThemeChangedEvent.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/config/ThemeChangedEvent.java deleted file mode 100644 index 7b7736413..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/config/ThemeChangedEvent.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.event.config; - -import org.jackhuang.hmcl.api.event.SimpleEvent; -import org.jackhuang.hmcl.api.ui.Theme; - -/** - * This event gets fired when the application theme changed. - *
    - * This event is fired on the {@link org.jackhuang.hmcl.api.HMCLApi#EVENT_BUS} - * @param source {@link org.jackhuang.hmcl.setting.Config} - * @param Theme the changed theme - * @author huangyuhui - */ -public class ThemeChangedEvent extends SimpleEvent { - - public ThemeChangedEvent(Object source, Theme value) { - super(source, value); - } - -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/launch/LaunchEvent.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/launch/LaunchEvent.java deleted file mode 100644 index 02682a1d0..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/launch/LaunchEvent.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.event.launch; - -import org.jackhuang.hmcl.api.IProcess; -import org.jackhuang.hmcl.api.event.SimpleEvent; - -/** - * This event gets fired when we launched the game. - *
    - * This event is fired on the {@link org.jackhuang.hmcl.api.HMCLApi#EVENT_BUS} - * @param source {@link org.jackhuang.hmcl.core.launch.GameLauncher} - * @param IProcess the game process - * @author huangyuhui - */ -public class LaunchEvent extends SimpleEvent { - - public LaunchEvent(Object source, IProcess value) { - super(source, value); - } - -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/launch/LaunchSucceededEvent.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/launch/LaunchSucceededEvent.java deleted file mode 100644 index d41b1d7c9..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/launch/LaunchSucceededEvent.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.event.launch; - -import java.util.List; -import org.jackhuang.hmcl.api.event.SimpleEvent; - -/** - * This event gets fired when we make the launching command successfully(not launched the game process). - *
    - * This event is fired on the {@link org.jackhuang.hmcl.api.HMCLApi#EVENT_BUS} - * @param source {@link org.jackhuang.hmcl.core.launch.GameLauncher} - * @param List<String> Our launching command. - * @author huangyuhui - */ -public class LaunchSucceededEvent extends SimpleEvent>{ - - public LaunchSucceededEvent(Object source, List value) { - super(source, value); - } - -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/launch/LaunchingState.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/launch/LaunchingState.java deleted file mode 100644 index 416cddd2d..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/launch/LaunchingState.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.event.launch; - -/** - * - * @author huangyuhui - */ -public enum LaunchingState { - Starting, - LoggingIn, - GeneratingLaunchingCodes, - DownloadingLibraries, - DecompressingNatives, - WaitingForGameLaunching, - Done -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/launch/LaunchingStateChangedEvent.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/launch/LaunchingStateChangedEvent.java deleted file mode 100644 index e7267fc49..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/launch/LaunchingStateChangedEvent.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.event.launch; - -import org.jackhuang.hmcl.api.event.SimpleEvent; - -/** - * This event gets fired when we are launching a game and mark what things we are doing. - *
    - * This event is fired on the {@link org.jackhuang.hmcl.api.HMCLApi#EVENT_BUS} - * @param source {@link org.jackhuang.hmcl.core.launch.GameLauncher} - * @param LaunchingState the launching state. - * @author huangyuhui - */ -public class LaunchingStateChangedEvent extends SimpleEvent { - - public LaunchingStateChangedEvent(Object source, LaunchingState value) { - super(source, value); - } - -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/launch/ProcessingLaunchOptionsEvent.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/launch/ProcessingLaunchOptionsEvent.java deleted file mode 100644 index cd621acca..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/launch/ProcessingLaunchOptionsEvent.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.event.launch; - -import org.jackhuang.hmcl.api.Wrapper; -import org.jackhuang.hmcl.api.event.SimpleEvent; -import org.jackhuang.hmcl.api.game.LaunchOptions; - -/** - * This event gets fired before generating launch command. - *
    - * Pay attension: If you need to terminate the launching process, you must throw - * {@link org.jackhuang.hmcl.core.RuntimeGameException anyway. - *
    - * This event is fired on the {@link org.jackhuang.hmcl.api.HMCLApi#EVENT_BUS} - * @param source {@link org.jackhuang.hmcl.core.launch.GameLauncher} - * @param LaunchOptions you can modify the value of this event to control the launching process. - * @author huang - */ -public class ProcessingLaunchOptionsEvent extends SimpleEvent> { - - public ProcessingLaunchOptionsEvent(Object source, Wrapper value) { - super(source, value); - } - -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/launch/ProcessingLoginResultEvent.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/launch/ProcessingLoginResultEvent.java deleted file mode 100644 index 1cf3e4b20..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/launch/ProcessingLoginResultEvent.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.event.launch; - -import org.jackhuang.hmcl.api.Wrapper; -import org.jackhuang.hmcl.api.auth.UserProfileProvider; -import org.jackhuang.hmcl.api.event.SimpleEvent; - -/** - * This event gets fired when we successfully logged in. - *
    - * Pay attension: If you need to terminate the launching process, you must throw - * {@link org.jackhuang.hmcl.core.RuntimeGameException anyway. - *
    - * This event is fired on the {@link org.jackhuang.hmcl.api.HMCLApi#EVENT_BUS} - * @param source {@link org.jackhuang.hmcl.core.launch.GameLauncher} - * @param UserProfileProvider you can modify the value of this event to control the user profile. - * @author huangyuhui - */ -public class ProcessingLoginResultEvent extends SimpleEvent> { - - public ProcessingLoginResultEvent(Object source, Wrapper value) { - super(source, value); - } - -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/process/JVMLaunchFailedEvent.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/process/JVMLaunchFailedEvent.java deleted file mode 100644 index c740aa701..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/process/JVMLaunchFailedEvent.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.event.process; - -import org.jackhuang.hmcl.api.IProcess; -import org.jackhuang.hmcl.api.event.SimpleEvent; - -/** - * This event gets fired when we launch the JVM and it got crashed. - *
    - * This event is fired on the {@link org.jackhuang.hmcl.api.HMCLApi#EVENT_BUS} - * @param source {@link org.jackhuang.hmcl.util.sys.JavaProcessMonitor} - * @param JavaProcess the crashed process. - * @author huangyuhui - */ -public class JVMLaunchFailedEvent extends SimpleEvent { - - public JVMLaunchFailedEvent(Object source, IProcess value) { - super(source, value); - } - -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/process/JavaProcessExitedAbnormallyEvent.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/process/JavaProcessExitedAbnormallyEvent.java deleted file mode 100644 index c8f3b1c91..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/process/JavaProcessExitedAbnormallyEvent.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.event.process; - -import org.jackhuang.hmcl.api.IProcess; -import org.jackhuang.hmcl.api.event.SimpleEvent; - -/** - * This event gets fired when a JavaProcess exited abnormally and the exit code is not zero. - *
    - * This event is fired on the {@link org.jackhuang.hmcl.api.HMCLApi#EVENT_BUS} - * @param source {@link org.jackhuang.hmcl.util.sys.JavaProcessMonitor} - * @param JavaProcess The process that exited abnormally. - * @author huangyuhui - */ -public class JavaProcessExitedAbnormallyEvent extends SimpleEvent { - - public JavaProcessExitedAbnormallyEvent(Object source, IProcess value) { - super(source, value); - } - -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/process/JavaProcessStartingEvent.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/process/JavaProcessStartingEvent.java deleted file mode 100644 index 81bb457c7..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/process/JavaProcessStartingEvent.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.event.process; - -import org.jackhuang.hmcl.api.IProcess; -import org.jackhuang.hmcl.api.event.SimpleEvent; - -/** - * This event gets fired when a JavaProcess is starting. - *
    - * This event is fired on the {@link org.jackhuang.hmcl.api.HMCLApi#EVENT_BUS} - * @param source {@link org.jackhuang.hmcl.util.sys.JavaProcessMonitor} - * @param JavaProcess the starting JavaProcess. - * @author huang - */ -public class JavaProcessStartingEvent extends SimpleEvent { - - public JavaProcessStartingEvent(Object source, IProcess value) { - super(source, value); - } - -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/process/JavaProcessStoppedEvent.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/process/JavaProcessStoppedEvent.java deleted file mode 100644 index a91879ec6..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/process/JavaProcessStoppedEvent.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.event.process; - -import org.jackhuang.hmcl.api.IProcess; -import org.jackhuang.hmcl.api.event.SimpleEvent; - -/** - * This event gets fired when minecraft process exited successfully and the exit code is 0. - *
    - * This event is fired on the {@link org.jackhuang.hmcl.api.HMCLApi#EVENT_BUS} - * @param source {@link org.jackhuang.hmcl.util.sys.JavaProcessMonitor} - * @param JavaProcess minecraft process - * @author huangyuhui - */ -public class JavaProcessStoppedEvent extends SimpleEvent { - - public JavaProcessStoppedEvent(Object source, IProcess value) { - super(source, value); - } - -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/version/LoadedOneVersionEvent.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/version/LoadedOneVersionEvent.java deleted file mode 100644 index 281b92d1a..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/version/LoadedOneVersionEvent.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.event.version; - -import org.jackhuang.hmcl.api.event.SimpleEvent; - -/** - * This event gets fired when a minecraft version has been loaded. - *
    - * This event is fired on the {@link org.jackhuang.hmcl.api.HMCLApi#EVENT_BUS} - * @param source {@link org.jackhuang.hmcl.core.version.MinecraftVersionManager} - * @param String the version id. - * @author huang - */ -public class LoadedOneVersionEvent extends SimpleEvent { - - public LoadedOneVersionEvent(Object source, String value) { - super(source, value); - } - -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/version/RefreshedVersionsEvent.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/version/RefreshedVersionsEvent.java deleted file mode 100644 index 8ebb5b2c0..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/version/RefreshedVersionsEvent.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.event.version; - -import java.util.EventObject; - -/** - * This event gets fired when all the versions in .minecraft folder are loaded. - *
    - * This event is fired on the {@link org.jackhuang.hmcl.api.HMCLApi#EVENT_BUS} - * @param source {@link org.jackhuang.hmcl.core.version.MinecraftVersionManager} - * @param IMinecraftService the .minecraft folder. - * @author huangyuhui - */ -public class RefreshedVersionsEvent extends EventObject { - - public RefreshedVersionsEvent(Object source) { - super(source); - } - -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/version/RefreshingVersionsEvent.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/version/RefreshingVersionsEvent.java deleted file mode 100644 index e16ad2a30..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/event/version/RefreshingVersionsEvent.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.event.version; - -import java.util.EventObject; - -/** - * This event gets fired when loading versions in a .minecraft folder. - *
    - * This event is fired on the {@link org.jackhuang.hmcl.api.HMCLApi#EVENT_BUS} - * @param source {@link org.jackhuang.hmcl.core.version.MinecraftVersionManager} - * @param IMinecraftService .minecraft folder. - * @author huang - */ -public class RefreshingVersionsEvent extends EventObject { - - public RefreshingVersionsEvent(Object source) { - super(source); - } - -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/func/BiFunction.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/func/BiFunction.java deleted file mode 100644 index 79477f6ff..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/func/BiFunction.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.func; - -/** - * - * @author huangyuhui - */ -public interface BiFunction { - - C apply(A a, B b); -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/func/CallbackIO.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/func/CallbackIO.java deleted file mode 100644 index 717199b59..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/func/CallbackIO.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.func; - -import java.io.IOException; - -/** - * - * @author huangyuhui - */ -public interface CallbackIO { - - void call(T t) throws IOException; -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/func/Consumer.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/func/Consumer.java deleted file mode 100644 index 70867753a..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/func/Consumer.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.func; - -import java.util.EventListener; - -/** - * - * @author huangyuhui - */ -public interface Consumer extends EventListener { - - void accept(T t); -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/func/Function.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/func/Function.java deleted file mode 100644 index c6546fd30..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/func/Function.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.func; - -/** - * - * @author huangyuhui - */ -public interface Function { - - R apply(T t); -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/func/NonFunction.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/func/NonFunction.java deleted file mode 100644 index 704e89c49..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/func/NonFunction.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.func; - -/** - * - * @author huangyuhui - */ -public interface NonFunction { - - T apply(); -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/func/Predicate.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/func/Predicate.java deleted file mode 100644 index 6eb10f8ed..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/func/Predicate.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.func; - -/** - * - * @author huangyuhui - */ -public interface Predicate { - - boolean apply(T t); -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/game/DecompressLibraryJob.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/game/DecompressLibraryJob.java deleted file mode 100644 index 81984a39e..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/game/DecompressLibraryJob.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.game; - -import java.io.File; - -/** - * @author huangyuhui - */ -public class DecompressLibraryJob { - - public File[] decompressFiles; - public Extract[] extractRules; - private File decompressTo; - - /** - * The length of these 2 arrays must be the same. - * - * @param decompressFiles - * @param extractRules - * @param decompressTo folder - */ - public DecompressLibraryJob(File[] decompressFiles, Extract[] extractRules, File decompressTo) { - this.decompressFiles = decompressFiles.clone(); - this.extractRules = extractRules.clone(); - this.decompressTo = decompressTo; - } - - public File getDecompressTo() { - return decompressTo; - } - - public void setDecompressTo(File decompressTo) { - this.decompressTo = decompressTo; - } - -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/game/Extract.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/game/Extract.java deleted file mode 100644 index 5c60ffee2..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/game/Extract.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.game; - -import com.google.gson.annotations.SerializedName; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -/** - * - * @author huangyuhui - */ -public class Extract implements Cloneable { - - @SerializedName("exclude") - public List exclude = new ArrayList<>(); - - public boolean allow(String path) { - return !startsWithOne(exclude, path); - } - - @Override - public Object clone() { - try { - return super.clone(); - } catch (CloneNotSupportedException ex) { - throw new InternalError(ex); - } - } - - public static boolean startsWithOne(Collection a, String match) { - if (a == null) - return false; - for (String b : a) - if (match.startsWith(b)) - return true; - return false; - } -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/game/GameDirType.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/game/GameDirType.java deleted file mode 100644 index 483e8e582..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/game/GameDirType.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.game; - -/** - * - * @author huangyuhui - */ -public enum GameDirType { - - ROOT_FOLDER, - VERSION_FOLDER; -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/game/IMinecraftLibrary.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/game/IMinecraftLibrary.java deleted file mode 100644 index 3156c4bcf..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/game/IMinecraftLibrary.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.game; - -import java.io.File; - -/** - * - * @author huang - */ -public interface IMinecraftLibrary extends Cloneable { - - boolean allow(); - - Extract getDecompressExtractRules(); - - /** - * Only used for IMinecraftProvider - * @param gameDir - * @return - */ - File getFilePath(File gameDir); - - String getName(); - - boolean isNative(); - - String getDownloadURL(String downloadSource); - -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/game/LaunchOptions.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/game/LaunchOptions.java deleted file mode 100644 index 1a17e5193..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/game/LaunchOptions.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.game; - -import java.io.File; - -/** - * - * @author huangyuhui - */ -public class LaunchOptions { - - private String name, versionName, javaArgs, minecraftArgs, maxMemory, permSize, width, height, serverIp, wrapper; - private String proxyHost, proxyPort, proxyUser, proxyPass, javaDir, launchVersion, type, precalledCommand; - private boolean fullscreen, noJVMArgs, notCheckGame; - private File gameDir; - - public String getVersionName() { - return versionName; - } - - public void setVersionName(String versionName) { - this.versionName = versionName; - } - - public File getGameDir() { - return gameDir; - } - - public void setGameDir(File gameDir) { - this.gameDir = gameDir; - } - - public void setJavaDir(String javaDir) { - this.javaDir = javaDir; - } - - public String getJavaDir() { - return javaDir; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getJavaArgs() { - return javaArgs; - } - - public void setJavaArgs(String javaArgs) { - this.javaArgs = javaArgs; - } - - public boolean hasJavaArgs() { - return getJavaArgs() != null && !getJavaArgs().trim().isEmpty(); - } - - public String getMaxMemory() { - return maxMemory; - } - - public void setMaxMemory(String maxMemory) { - this.maxMemory = maxMemory; - } - - public String getWrapper() { - return wrapper; - } - - public void setWrapper(String wrapper) { - this.wrapper = wrapper; - } - - public String getWidth() { - return width; - } - - public void setWidth(String width) { - this.width = width; - } - - public String getHeight() { - return height; - } - - public void setHeight(String height) { - this.height = height; - } - - public boolean isFullscreen() { - return fullscreen; - } - - public void setFullscreen(boolean fullscreen) { - this.fullscreen = fullscreen; - } - - public String getPermSize() { - return permSize; - } - - public void setPermSize(String permSize) { - this.permSize = permSize; - } - - public boolean isNoJVMArgs() { - return noJVMArgs; - } - - public void setNoJVMArgs(boolean noJVMArgs) { - this.noJVMArgs = noJVMArgs; - } - - public String getMinecraftArgs() { - return minecraftArgs; - } - - public void setMinecraftArgs(String minecraftArgs) { - this.minecraftArgs = minecraftArgs; - } - - public String getServerIp() { - return serverIp; - } - - public void setServerIp(String serverIp) { - this.serverIp = serverIp; - } - - public String getProxyHost() { - return proxyHost; - } - - public void setProxyHost(String proxyHost) { - this.proxyHost = proxyHost; - } - - public String getProxyPort() { - return proxyPort; - } - - public void setProxyPort(String proxyPort) { - this.proxyPort = proxyPort; - } - - public String getProxyUser() { - return proxyUser; - } - - public void setProxyUser(String proxyUser) { - this.proxyUser = proxyUser; - } - - public String getProxyPass() { - return proxyPass; - } - - public void setProxyPass(String proxyPass) { - this.proxyPass = proxyPass; - } - - public String getPrecalledCommand() { - return precalledCommand; - } - - public void setPrecalledCommand(String precalledCommand) { - this.precalledCommand = precalledCommand; - } - - public String getLaunchVersion() { - return launchVersion; - } - - public void setLaunchVersion(String launchVersion) { - this.launchVersion = launchVersion; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public boolean isNotCheckGame() { - return notCheckGame; - } - - public void setNotCheckGame(boolean notCheckGame) { - this.notCheckGame = notCheckGame; - } -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/ui/AddTabCallback.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/ui/AddTabCallback.java deleted file mode 100644 index 993fdcb94..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/ui/AddTabCallback.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.ui; - -/** - * Used for adding tab page to MainFrame. - * - * @author huang - */ -public interface AddTabCallback { - - /** - * Add your tab page to MainFrame. - * - * @param tabPage your customized tab page. - * @param id the id of your page. - * @param title you are supposed to localize your texts. - */ - void addTab(TopTabPage tabPage, String id, String title); -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/ui/Theme.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/ui/Theme.java deleted file mode 100644 index 60ccda3ce..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/ui/Theme.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.ui; - -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; - -/** - * - * @author huang - */ -public class Theme { - - public static final Map THEMES = new HashMap<>(); - - public final String id; - public final String localizedName; - public final Map settings; - - public Theme(String id, String localizedName, Map settings) { - this.id = id; - this.localizedName = localizedName; - this.settings = Objects.requireNonNull(settings, "Theme settings map may not be null."); - } - - @Override - public String toString() { - return localizedName; - } - - public String getId() { - return id; - } -} diff --git a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/ui/TopTabPage.java b/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/ui/TopTabPage.java deleted file mode 100644 index 3d9c7c50b..000000000 --- a/HMCLAPI/src/main/java/org/jackhuang/hmcl/api/ui/TopTabPage.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.api.ui; - -import javax.swing.JPanel; - -/** - * - * @author huangyuhui - */ -public abstract class TopTabPage extends JPanel { - - public abstract void onCreate(); - - public abstract boolean isCreated(); - - public abstract void onSelect(TopTabPage lastSelectedPage); - - public abstract boolean isSelected(); - - public abstract void onLeave(); - - public abstract int getId(); - - public abstract void setId(int id); -} diff --git a/HMCLCore/build.gradle b/HMCLCore/build.gradle index 3e1232c78..e69de29bb 100644 --- a/HMCLCore/build.gradle +++ b/HMCLCore/build.gradle @@ -1,34 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ - -plugins { - id "me.tatarka.retrolambda" version "3.5.0" - //id "org.jetbrains.kotlin.jvm" version "1.1.2-2" -} - -if (System.getenv("BUILD_NUMBER") != null) - version = System.getenv("BUILD_NUMBER") - -dependencies { - compile project(":HMCLAPI") - compile group: "org.commonjava.googlecode.markdown4j", name: "markdown4j", version: "2.2-cj-1.0" -} - -retrolambda { - javaVersion = JavaVersion.VERSION_1_7 -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/GameException.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/GameException.java deleted file mode 100644 index 6c50f2f6d..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/GameException.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core; - -/** - * Thrown if we have some problem generating launch command. - * @author huangyuhui - */ -public class GameException extends Exception { - - public GameException() { - } - - public GameException(String message) { - super(message); - } - - public GameException(String message, Throwable cause) { - super(message, cause); - } - - public GameException(Throwable cause) { - super(cause); - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/MCUtils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/MCUtils.java deleted file mode 100644 index f6aa7b9d1..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/MCUtils.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core; - -import java.io.File; -import java.io.IOException; -import org.jackhuang.hmcl.util.sys.FileUtils; -import org.jackhuang.hmcl.util.sys.OS; - -/** - * - * @author huang - */ -public final class MCUtils { - - public static File getWorkingDirectory(String baseName) { - String userhome = System.getProperty("user.home", "."); - File file; - switch (OS.os()) { - case LINUX: - file = new File(userhome, '.' + baseName + '/'); - break; - case WINDOWS: - String appdata = System.getenv("APPDATA"); - if (appdata != null) - file = new File(appdata, "." + baseName + '/'); - else - file = new File(userhome, '.' + baseName + '/'); - break; - case OSX: - file = new File(userhome, "Library/Application Support/" + baseName); - break; - default: - file = new File(userhome, baseName + '/'); - } - return file; - } - - public static File getLocation() { - return getWorkingDirectory("minecraft"); - } - - public static String minecraft() { - if (OS.os() == OS.OSX) - return "minecraft"; - return ".minecraft"; - } - - public static File getInitGameDir() { - File gameDir = new File(MCUtils.minecraft()); - if (!gameDir.exists()) { - File newFile = MCUtils.getLocation(); - if (newFile.exists()) - gameDir = newFile; - } - return gameDir; - } - - public static final String PROFILE = "{\"selectedProfile\": \"(Default)\",\"profiles\": {\"(Default)\": {\"name\": \"(Default)\"}},\"clientToken\": \"88888888-8888-8888-8888-888888888888\"}"; - - public static void tryWriteProfile(File gameDir) throws IOException { - File file = new File(gameDir, "launcher_profiles.json"); - if (!file.exists()) - FileUtils.write(file, PROFILE); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/RuntimeGameException.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/RuntimeGameException.java deleted file mode 100644 index dfe33774c..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/RuntimeGameException.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core; - -/** - * - * @author huang - */ -public class RuntimeGameException extends RuntimeException { - - public RuntimeGameException() { - } - - public RuntimeGameException(String message) { - super(message); - } - - public RuntimeGameException(String message, Throwable cause) { - super(message, cause); - } - - public RuntimeGameException(Throwable cause) { - super(cause); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/asset/AssetsIndex.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/asset/AssetsIndex.java deleted file mode 100644 index ed708cd03..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/asset/AssetsIndex.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.asset; - -import com.google.gson.annotations.SerializedName; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Set; - -/** - * - * @author huangyuhui - */ -public class AssetsIndex { - - public static final String DEFAULT_ASSET_NAME = "legacy"; - - @SerializedName("objects") - public Map objects; - - @SerializedName("virtual") - public boolean virtual; - - public AssetsIndex() { - this.objects = new LinkedHashMap<>(); - } - - public Map getFileMap() { - return this.objects; - } - - public Set getUniqueObjects() { - return new HashSet<>(this.objects.values()); - } - - public boolean isVirtual() { - return this.virtual; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/asset/AssetsMojangLoader.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/asset/AssetsMojangLoader.java deleted file mode 100644 index b8e78dcfb..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/asset/AssetsMojangLoader.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.asset; - -import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.Map; -import java.util.Objects; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.core.service.IMinecraftAssetService; -import org.jackhuang.hmcl.util.task.Task; -import org.jackhuang.hmcl.util.sys.FileUtils; -import org.jackhuang.hmcl.util.StrUtils; -import org.jackhuang.hmcl.core.download.IDownloadProvider; -import org.jackhuang.hmcl.core.version.MinecraftVersion; -import org.jackhuang.hmcl.api.VersionNumber; -import org.jackhuang.hmcl.util.task.TaskInfo; - -/** - * - * @author huangyuhui - */ -public class AssetsMojangLoader extends IAssetsHandler { - - public AssetsMojangLoader(String name) { - super(name); - } - - @Override - public Task getList(final MinecraftVersion mv, final IMinecraftAssetService mp) { - Objects.requireNonNull(mv); - String assetsId = mv.getAssetsIndex().getId(); - HMCLog.log("Gathering asset index: " + assetsId); - File f = mp.getIndexFile(assetsId); - return new TaskInfo("Gather asset index") { - @Override - public Collection getDependTasks() { - if (!f.exists()) - return Arrays.asList(mp.downloadMinecraftAssetsIndex(mv.getAssetsIndex())); - else - return null; - } - - @Override - public void executeTask(boolean areDependTasksSucceeded) throws Exception { - if (!areDependTasksSucceeded) - throw new IllegalStateException("Failed to get asset index"); - String result = FileUtils.read(f); - if (StrUtils.isBlank(result)) - throw new IllegalStateException("Index json is empty, please redownload it!"); - AssetsIndex o = C.GSON.fromJson(result, AssetsIndex.class); - assetsDownloadURLs = new ArrayList<>(); - assetsLocalNames = new ArrayList<>(); - assetsObjects = new ArrayList<>(); - HashSet loadedHashes = new HashSet<>(); - int pgs = 0; - if (o != null && o.getFileMap() != null) - for (Map.Entry e : o.getFileMap().entrySet()) { - if (loadedHashes.contains(e.getValue().getHash())) - continue; - loadedHashes.add(e.getValue().getHash()); - assetsObjects.add(e.getValue()); - assetsDownloadURLs.add(e.getValue().getLocation()); - assetsLocalNames.add(mp.getAssetObject(assetsId, e.getValue())); - if (ppl != null) - ppl.setProgress(this, ++pgs, o.getFileMap().size()); - } - } - }; - } - - @Override - public Task getDownloadTask(IDownloadProvider sourceType) { - return new AssetsTask(sourceType.getAssetsDownloadURL()); - } - - @Override - public boolean isVersionAllowed(String formattedVersion) { - VersionNumber ur = VersionNumber.check(formattedVersion); - if (ur == null) - return false; - return VersionNumber.check("1.6.0").compareTo(ur) <= 0; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/asset/AssetsObject.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/asset/AssetsObject.java deleted file mode 100644 index 8c932333b..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/asset/AssetsObject.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.asset; - -/** - * - * @author huangyuhui - */ -public class AssetsObject { - - private String hash; - private long size; - - public void setHash(String hash) { - this.hash = hash; - } - - public void setSize(long size) { - this.size = size; - } - - public AssetsObject(String hash, long size) { - this.hash = hash; - this.size = size; - } - - public String getHash() { - return this.hash; - } - - public long getSize() { - return this.size; - } - - public String getLocation() { - return hash.substring(0, 2) + "/" + hash; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; - AssetsObject that = (AssetsObject) o; - if (this.size != that.size) - return false; - return this.hash.equals(that.hash); - } - - @Override - public int hashCode() { - int result = this.hash.hashCode(); - result = 31 * result + (int) (this.size ^ this.size >>> 32); - return result; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/asset/IAssetsHandler.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/asset/IAssetsHandler.java deleted file mode 100644 index 4dd30917d..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/asset/IAssetsHandler.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.asset; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.core.service.IMinecraftAssetService; -import org.jackhuang.hmcl.core.download.IDownloadProvider; -import org.jackhuang.hmcl.core.version.MinecraftVersion; -import org.jackhuang.hmcl.util.task.Task; -import org.jackhuang.hmcl.util.net.FileDownloadTask; -import org.jackhuang.hmcl.util.code.DigestUtils; -import org.jackhuang.hmcl.util.sys.FileUtils; -import org.jackhuang.hmcl.util.sys.IOUtils; -import org.jackhuang.hmcl.util.task.TaskInfo; - -/** - * Assets - * - * @author huangyuhui - */ -public abstract class IAssetsHandler { - - protected ArrayList assetsDownloadURLs; - protected ArrayList assetsLocalNames; - protected final String name; - protected List assetsObjects; - - public IAssetsHandler(String name) { - this.name = name; - } - - public static final IAssetsHandler ASSETS_HANDLER; - - static { - ASSETS_HANDLER = new AssetsMojangLoader(C.i18n("assets.list.1_7_3_after")); - } - - /** - * interface name - * - * @return - */ - public String getName() { - return name; - } - - /** - * All the files assets needed - * - * @param mv The version that needs assets - * @param mp Asset Service - * @return just run it! - */ - public abstract Task getList(MinecraftVersion mv, IMinecraftAssetService mp); - - /** - * Will be invoked when the user invoked "Download all assets". - * - * @param sourceType Download Source - * - * @return Download File Task - */ - public abstract Task getDownloadTask(IDownloadProvider sourceType); - - public abstract boolean isVersionAllowed(String formattedVersion); - - protected class AssetsTask extends TaskInfo { - - ArrayList al; - String u; - - public AssetsTask(String url) { - super(C.i18n("assets.download")); - this.u = url; - } - - @Override - public void executeTask(boolean areDependTasksSucceeded) { - if (assetsDownloadURLs == null || assetsLocalNames == null || assetsObjects == null) - throw new IllegalStateException(C.i18n("assets.not_refreshed")); - int max = assetsDownloadURLs.size(); - al = new ArrayList<>(); - int hasDownloaded = 0; - for (int i = 0; i < max; i++) { - String mark = assetsDownloadURLs.get(i); - String url = u + mark; - File location = assetsLocalNames.get(i); - if (!FileUtils.makeDirectory(location.getParentFile())) - HMCLog.warn("Failed to make directories: " + location.getParent()); - if (location.isDirectory()) - continue; - boolean need = true; - try { - if (location.exists()) { - FileInputStream fis = FileUtils.openInputStream(location); - String sha = DigestUtils.sha1Hex(IOUtils.toByteArray(fis)); - IOUtils.closeQuietly(fis); - if (assetsObjects.get(i).getHash().equals(sha)) { - ++hasDownloaded; - HMCLog.log("File " + assetsLocalNames.get(i) + " has been downloaded successfully, skipped downloading."); - if (ppl != null) - ppl.setProgress(this, hasDownloaded, max); - continue; - } - } - } catch (IOException e) { - HMCLog.warn("Failed to get hash: " + location, e); - need = !location.exists(); - } - if (need) - al.add(new FileDownloadTask(url, location).setTag(assetsObjects.get(i).getHash())); - } - } - - @Override - public Collection getAfterTasks() { - return al; - } - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/asset/MinecraftAssetService.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/asset/MinecraftAssetService.java deleted file mode 100644 index d563e26a6..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/asset/MinecraftAssetService.java +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.asset; - -import com.google.gson.JsonSyntaxException; -import java.io.File; -import java.io.IOException; -import java.util.Arrays; -import java.util.Collection; -import java.util.Map; -import org.jackhuang.hmcl.core.GameException; -import org.jackhuang.hmcl.core.launch.IAssetProvider; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.core.service.IMinecraftAssetService; -import org.jackhuang.hmcl.core.service.IMinecraftService; -import org.jackhuang.hmcl.core.version.AssetIndexDownloadInfo; -import org.jackhuang.hmcl.core.version.MinecraftVersion; -import org.jackhuang.hmcl.util.ui.MessageBox; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.core.version.LoggingInfo; -import org.jackhuang.hmcl.util.task.Task; -import org.jackhuang.hmcl.util.task.TaskWindow; -import org.jackhuang.hmcl.util.net.FileDownloadTask; -import org.jackhuang.hmcl.util.sys.FileUtils; -import org.jackhuang.hmcl.util.task.ParallelTask; -import org.jackhuang.hmcl.util.task.TaskInfo; - -/** - * - * @author huangyuhui - */ -public class MinecraftAssetService extends IMinecraftAssetService { - - public MinecraftAssetService(IMinecraftService service) { - super(service); - } - - @Override - public Task downloadAssets(final String mcVersion) throws GameException { - return downloadAssets(service.version().getVersionById(mcVersion)); - } - - public Task downloadAssets(final MinecraftVersion mv) throws GameException { - if (mv == null) - return null; - Task task = IAssetsHandler.ASSETS_HANDLER.getList(mv.resolve(service.version()), service.asset()) - .with(IAssetsHandler.ASSETS_HANDLER.getDownloadTask(service.getDownloadType().getProvider())); - if (mv.logging != null && mv.logging.containsKey("client")) { - LoggingInfo info = mv.logging.get("client"); - File file = getLoggingObject(mv.assetIndex.getId(), info); - if (!file.exists()) - return new ParallelTask().addTask(task) - .addTask(new FileDownloadTask(info.file.url, file, info.file.sha1)); - } - return task; - } - - @Override - public File getLoggingObject(String assetId, LoggingInfo logging) { - return new File(getAssets(assetId), "log_configs/" + logging.file.getId()); - } - - @Override - public boolean refreshAssetsIndex(String id) throws GameException { - MinecraftVersion mv = service.version().getVersionById(id); - if (mv == null) - return false; - return downloadMinecraftAssetsIndexAsync(mv.resolve(service.version()).getAssetsIndex()); - } - - @Override - public Task downloadMinecraftAssetsIndex(AssetIndexDownloadInfo assetIndex) { - File assetsLocation = getAssets(assetIndex.getId()); - if (!FileUtils.makeDirectory(assetsLocation)) - HMCLog.warn("Failed to make directories: " + assetsLocation); - File assetsIndex = getIndexFile(assetIndex.getId()); - File renamed = null; - if (assetsIndex.exists()) { - renamed = new File(assetsLocation, "indexes/" + assetIndex.getId() + "-renamed.json"); - if (assetsIndex.renameTo(renamed)) - HMCLog.warn("Failed to rename " + assetsIndex + " to " + renamed); - } - File renamedFinal = renamed; - return new TaskInfo("Download Asset Index") { - @Override - public Collection getDependTasks() { - return Arrays.asList(new FileDownloadTask(assetIndex.getUrl(service.getDownloadType()), assetsIndex, assetIndex.sha1).setTag(assetIndex.getId() + ".json")); - } - - @Override - public void executeTask(boolean areDependTasksSucceeded) { - if (areDependTasksSucceeded) { - if (renamedFinal != null && !renamedFinal.delete()) - HMCLog.warn("Failed to delete " + renamedFinal + ", maybe you should do it."); - } else if (renamedFinal != null && !renamedFinal.renameTo(assetsIndex)) - HMCLog.warn("Failed to rename " + renamedFinal + " to " + assetsIndex); - } - }; - } - - @Override - public boolean downloadMinecraftAssetsIndexAsync(AssetIndexDownloadInfo assetIndex) { - File assetsDir = getAssets(assetIndex.getId()); - if (!FileUtils.makeDirectory(assetsDir)) - HMCLog.warn("Failed to make directories: " + assetsDir); - File assetsIndex = getIndexFile(assetIndex.getId()); - File renamed = null; - // This is unnecessary to do such backup job, FileDownloadTask can do this. - if (assetsIndex.exists()) { - renamed = new File(assetsDir, "indexes/" + assetIndex.getId() + "-renamed.json"); - if (assetsIndex.renameTo(renamed)) - HMCLog.warn("Failed to rename " + assetsIndex + " to " + renamed); - } - if (TaskWindow.factory() - .append(new FileDownloadTask(assetIndex.getUrl(service.getDownloadType()), assetsIndex, assetIndex.sha1).setTag(assetIndex.getId() + ".json")) - .execute()) { - if (renamed != null && !renamed.delete()) - HMCLog.warn("Failed to delete " + renamed + ", maybe you should do it."); - return true; - } - if (renamed != null && !renamed.renameTo(assetsIndex)) - HMCLog.warn("Failed to rename " + renamed + " to " + assetsIndex); - return false; - } - - @Override - public File getAssets(String assetId) { - return new File(service.baseDirectory(), "assets"); - } - - @Override - public File getIndexFile(String assetId) { - return new File(getAssets(assetId), "indexes/" + assetId + ".json"); - } - - @Override - public File getAssetObject(String assetId, String name) throws IOException { - try { - AssetsIndex index = C.GSON.fromJson(FileUtils.read(getIndexFile(assetId), "UTF-8"), AssetsIndex.class); - if (index == null || index.getFileMap() == null || index.getFileMap().get(name) == null) - throw new IOException("Assets file format malformed."); - return getAssetObject(assetId, index.getFileMap().get(name)); - } catch (JsonSyntaxException e) { - throw new IOException("Assets file format malformed.", e); - } - } - - protected boolean checkAssetsExistence(AssetIndexDownloadInfo assetIndex, LoggingInfo info) { - String assetId = assetIndex.getId(); - File indexFile = getIndexFile(assetId); - File assetDir = getAssets(assetId); - - if (!getAssets(assetId).exists() || !indexFile.isFile()) - return false; - - try { - String assetIndexContent = FileUtils.read(indexFile, "UTF-8"); - AssetsIndex index = (AssetsIndex) C.GSON.fromJson(assetIndexContent, AssetsIndex.class); - - if (index == null) - return false; - - if (info != null && !getLoggingObject(assetId, info).exists()) - return false; - - for (Map.Entry entry : index.getFileMap().entrySet()) - if (!assetObjectPath(assetDir, (AssetsObject) entry.getValue()).exists()) - return false; - return true; - } catch (IOException | JsonSyntaxException e) { - return false; - } - } - - protected File reconstructAssets(AssetIndexDownloadInfo assetIndex) { - File assetsDir = getAssets(assetIndex.getId()); - String assetVersion = assetIndex.getId(); - File indexFile = getIndexFile(assetVersion); - File virtualRoot = new File(new File(assetsDir, "virtual"), assetVersion); - - if (!indexFile.isFile()) { - HMCLog.warn("No assets index file " + virtualRoot + "; can't reconstruct assets"); - return assetsDir; - } - - try { - String assetIndexContent = FileUtils.read(indexFile, "UTF-8"); - AssetsIndex index = (AssetsIndex) C.GSON.fromJson(assetIndexContent, AssetsIndex.class); - - if (index == null) - return assetsDir; - if (index.isVirtual()) { - int cnt = 0; - HMCLog.log("Reconstructing virtual assets folder at " + virtualRoot); - int tot = index.getFileMap().entrySet().size(); - for (Map.Entry entry : index.getFileMap().entrySet()) { - File target = new File(virtualRoot, entry.getKey()); - File original = assetObjectPath(assetsDir, entry.getValue()); - if (original.exists()) { - cnt++; - if (!target.isFile()) - FileUtils.copyFile(original, target); - } - } - // If the scale new format existent file is lower then 0.1, use the old format. - if (cnt * 10 < tot) - return assetsDir; - } - } catch (IOException | JsonSyntaxException e) { - HMCLog.warn("Failed to create virutal assets.", e); - } - - return virtualRoot; - } - - @Override - public File getAssetObject(String assetId, AssetsObject object) { - return assetObjectPath(getAssets(assetId), object); - } - - public File assetObjectPath(File assetDir, AssetsObject object) { - return new File(assetDir, "objects/" + object.getLocation()); - } - - public final IAssetProvider ASSET_PROVIDER_IMPL = (t, allow) -> { - LoggingInfo logging = null; - if (t.logging != null) - logging = t.logging.get("client"); - if (allow && !checkAssetsExistence(t.getAssetsIndex(), logging)) - if (MessageBox.show(C.i18n("assets.no_assets"), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION) - TaskWindow.factory().execute(downloadAssets(t)); - return reconstructAssets(t.getAssetsIndex()).getAbsolutePath(); - }; -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/AbstractAuthenticator.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/AbstractAuthenticator.java deleted file mode 100644 index f3ebb6527..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/AbstractAuthenticator.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.auth; - -import org.jackhuang.hmcl.api.auth.IAuthenticator; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import org.jackhuang.hmcl.api.PluginManager; - -/** - * Login interface - * - * @author huangyuhui - */ -public abstract class AbstractAuthenticator implements IAuthenticator { - - public static final List LOGINS = new ArrayList<>(); - - static { - PluginManager.fireRegisterAuthenticators(LOGINS::add); - } - - protected String clientToken, username, password; - - public AbstractAuthenticator(String clientToken) { - this.clientToken = clientToken; - } - - public String getClientToken() { - return clientToken; - } - - - /** - * Has password? - * - * @return has password? - */ - @Override - public boolean hasPassword() { - return true; - } - - @Override - public boolean isLoggedIn() { - return false; - } - - @Override - public void setRememberMe(boolean is) { - - } - - @Override - public Map onSaveSettings() { - HashMap m = new HashMap<>(); - m.put("IAuthenticator_UserName", username); - return m; - } - - @Override - public void onLoadSettings(Map m) { - if (m == null) - return; - Object o = m.get("IAuthenticator_UserName"); - username = o instanceof String ? (String) o : ""; - } - - @Override - public String getUserName() { - return username; - } - - @Override - public void setUserName(String s) { - username = s; - } - - @Override - public String getPassword() { - return password; - } - - @Override - public void setPassword(String password) { - this.password = password; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/OfflineAuthenticator.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/OfflineAuthenticator.java deleted file mode 100644 index 843981f44..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/OfflineAuthenticator.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.auth; - -import org.jackhuang.hmcl.api.auth.UserProfileProvider; -import org.jackhuang.hmcl.api.auth.LoginInfo; -import org.jackhuang.hmcl.api.auth.AuthenticationException; -import java.util.HashMap; -import java.util.Map; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.util.StrUtils; -import org.jackhuang.hmcl.util.code.DigestUtils; - -/** - * - * @author huangyuhui - */ -public final class OfflineAuthenticator extends AbstractAuthenticator { - - Map uuidMap = new HashMap<>(); - - public OfflineAuthenticator(String clientToken) { - super(clientToken); - } - - @Override - public void onLoadSettings(Map m) { - super.onLoadSettings(m); - if (m == null) - return; - Object o = m.get("uuidMap"); - if (o != null && o instanceof Map) - uuidMap = (Map) o; - } - - @Override - public Map onSaveSettings() { - Map m = super.onSaveSettings(); - m.put("uuidMap", uuidMap); - return m; - } - - @Override - public UserProfileProvider login(LoginInfo info) throws AuthenticationException { - if (StrUtils.isBlank(info.username)) - throw new AuthenticationException(C.i18n("login.no_Player007")); - String uuid; - try { - uuid = getUUIDFromUserName(info.username); - } catch(IllegalArgumentException e) { - throw new AuthenticationException("Could not find md5 digest algorithm, please reinstall Java or even your OS.", e); - } - if (uuidMap != null && uuidMap.containsKey(info.username) && uuidMap.get(info.username) instanceof String) - uuid = (String) uuidMap.get(info.username); - else { - if (uuidMap == null) - uuidMap = new HashMap<>(); - uuidMap.put(info.username, uuid); - } - return new UserProfileProvider() - .setUserName(info.username) - .setSession(uuid) - .setUserId(uuid) - .setAccessToken(uuid) - .setUserType("Legacy") - .setClientIdentifier(clientToken); - } - - public static String getUUIDFromUserName(String str) { - return DigestUtils.md5Hex(str); - } - - @Override - public String id() { - return "offline"; - } - - @Override - public String getName() { - return C.i18n("login.methods.offline"); - } - - @Override - public boolean hasPassword() { - return false; - } - - @Override - public UserProfileProvider loginBySettings() { - return null; - } - - @Override - public void logOut() { - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/YggdrasilAuthenticator.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/YggdrasilAuthenticator.java deleted file mode 100644 index f64382f32..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/YggdrasilAuthenticator.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.auth; - -import org.jackhuang.hmcl.api.auth.UserProfileProvider; -import org.jackhuang.hmcl.api.auth.LoginInfo; -import org.jackhuang.hmcl.api.auth.AuthenticationException; -import com.google.gson.GsonBuilder; -import java.net.Proxy; -import java.util.Map; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.util.ArrayUtils; -import org.jackhuang.hmcl.core.auth.yggdrasil.GameProfile; -import org.jackhuang.hmcl.core.auth.yggdrasil.UUIDTypeAdapter; -import org.jackhuang.hmcl.core.auth.yggdrasil.PropertyMap; -import org.jackhuang.hmcl.core.auth.yggdrasil.YggdrasilAuthentication; -import org.jackhuang.hmcl.util.ui.MessageBox; -import org.jackhuang.hmcl.util.ui.SwingUtils; - -/** - * - * @author huangyuhui - */ -public final class YggdrasilAuthenticator extends AbstractAuthenticator { - - YggdrasilAuthentication ua; - - public YggdrasilAuthenticator(String clientToken) { - super(clientToken); - ua = new YggdrasilAuthentication(Proxy.NO_PROXY, clientToken); - } - - @Override - public UserProfileProvider login(LoginInfo info) throws AuthenticationException { - UserProfileProvider result = new UserProfileProvider(); - if (ua.canPlayOnline()) { - result.setUserName(ua.getSelectedProfile().name) - .setUserId(UUIDTypeAdapter.fromUUID(ua.getSelectedProfile().id)); - } else { - String usr = info.username; - if (info.username == null || !info.username.contains("@")) - throw new AuthenticationException(C.i18n("login.not_email")); - String pwd = info.password; - - if (!ua.isLoggedIn()) - ua.setPassword(pwd); - ua.setUserName(usr); - ua.logIn(); - if (!ua.isLoggedIn()) - throw new AuthenticationException(C.i18n("login.wrong_password")); - GameProfile selectedProfile = ua.getSelectedProfile(); - GameProfile[] profiles = ua.getAvailableProfiles(); - String username; - if (selectedProfile == null) - if (ArrayUtils.isNotEmpty(profiles)) { - String[] names = new String[profiles.length]; - for (int i = 0; i < profiles.length; i++) - names[i] = profiles[i].name; - int sel = SwingUtils.select(names, C.i18n("login.choose_charactor")); - if (sel == -1) - throw new AuthenticationException("No selection"); - selectedProfile = profiles[sel]; - username = names[sel]; - } else - username = MessageBox.showInputDialog(C.i18n("login.no_charactor")); - else - username = selectedProfile.name; - if (username == null) - throw new AuthenticationException("No player"); - result.setUserName(username) - .setUserId(selectedProfile == null ? OfflineAuthenticator.getUUIDFromUserName(username) : UUIDTypeAdapter.fromUUID(selectedProfile.id)); - } - return result.setUserType("mojang") - .setUserProperties(new GsonBuilder().registerTypeAdapter(PropertyMap.class, new PropertyMap.LegacySerializer()).create().toJson(ua.getUserProperties())) - .setUserPropertyMap(new GsonBuilder().registerTypeAdapter(PropertyMap.class, new PropertyMap.Serializer()).create().toJson(ua.getUserProperties())) - .setAccessToken(ua.getAuthenticatedToken()) - .setSession(ua.getAuthenticatedToken()) - .setClientIdentifier(clientToken); - } - - @Override - public boolean isLoggedIn() { - return ua.isLoggedIn(); - } - - @Override - public String id() { - return "yggdrasil"; - } - - @Override - public String getName() { - return C.i18n("login.methods.yggdrasil"); - } - - @Override - public Map onSaveSettings() { - Map m = ua.saveForStorage(); - m.putAll(super.onSaveSettings()); - return m; - } - - @Override - public void onLoadSettings(Map settings) { - super.onLoadSettings(settings); - if (settings == null) - return; - ua.loadFromStorage(settings); - } - - @Override - public UserProfileProvider loginBySettings() throws AuthenticationException { - UserProfileProvider result = new UserProfileProvider(); - ua.logIn(); - if (!ua.isLoggedIn()) - throw new AuthenticationException(C.i18n("login.wrong_password")); - GameProfile profile = ua.getSelectedProfile(); - result.setUserName(profile.name); - result.setUserId(profile.id.toString()); - result.setUserProperties(new GsonBuilder().registerTypeAdapter(PropertyMap.class, new PropertyMap.LegacySerializer()).create().toJson(ua.getUserProperties())); - result.setUserPropertyMap(new GsonBuilder().registerTypeAdapter(PropertyMap.class, new PropertyMap.Serializer()).create().toJson(ua.getUserProperties())); - result.setAccessToken(ua.getAuthenticatedToken()); - result.setSession(ua.getAuthenticatedToken()); - return result; - } - - @Override - public void logOut() { - ua.logOut(); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/AuthenticationRequest.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/AuthenticationRequest.java deleted file mode 100644 index 878ee5ddc..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/AuthenticationRequest.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.auth.yggdrasil; - -import java.util.HashMap; - -public class AuthenticationRequest { - - private HashMap agent; - private String username, password, clientToken; - private boolean requestUser = true; - - public HashMap getAgent() { - return agent; - } - - public void setAgent(HashMap agent) { - this.agent = agent; - } - - public String getUserName() { - return username; - } - - public void setUserName(String username) { - this.username = username; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public String getClientToken() { - return clientToken; - } - - public void setClientToken(String clientToken) { - this.clientToken = clientToken; - } - - public boolean isRequestUser() { - return requestUser; - } - - public void setRequestUser(boolean requestUser) { - this.requestUser = requestUser; - } - - public AuthenticationRequest(String username, String password, String clientToken) { - agent = new HashMap<>(); - agent.put("name", "Minecraft"); - agent.put("version", 1); - - this.username = username; - this.password = password; - this.clientToken = clientToken; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/GameProfile.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/GameProfile.java deleted file mode 100644 index 665a5a0c5..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/GameProfile.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.auth.yggdrasil; - -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParseException; -import com.google.gson.JsonSerializationContext; -import com.google.gson.JsonSerializer; -import java.lang.reflect.Type; -import java.util.Objects; -import java.util.UUID; -import org.jackhuang.hmcl.util.StrUtils; - -public class GameProfile { - - public final UUID id; - public final String name; - public final PropertyMap properties = new PropertyMap(); - private boolean legacy; - - public GameProfile(UUID id, String name) { - if (id == null && StrUtils.isBlank(name)) - throw new IllegalArgumentException("Name and ID cannot both be blank"); - - this.id = id; - this.name = name; - } - - public boolean isComplete() { - return id != null && StrUtils.isNotBlank(name); - } - - public boolean isLegacy() { - return legacy; - } - - @Override - public int hashCode() { - int hash = 7; - hash = 29 * hash + Objects.hashCode(this.id); - hash = 29 * hash + Objects.hashCode(this.name); - return hash; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; - - GameProfile that = (GameProfile) o; - - if (id != null ? !id.equals(that.id) : that.id != null) - return false; - return name != null ? name.equals(that.name) : that.name == null; - } - - public static class GameProfileSerializer implements JsonSerializer, JsonDeserializer { - - @Override - public GameProfile deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - if (!(json instanceof JsonObject)) - throw new JsonParseException("The json element is not a JsonObject."); - JsonObject object = (JsonObject) json; - UUID id = object.has("id") ? (UUID) context.deserialize(object.get("id"), UUID.class) : null; - String name = object.has("name") ? object.getAsJsonPrimitive("name").getAsString() : null; - return new GameProfile(id, name); - } - - @Override - public JsonElement serialize(GameProfile src, Type typeOfSrc, JsonSerializationContext context) { - JsonObject result = new JsonObject(); - if (src.id != null) - result.add("id", context.serialize(src.id)); - if (src.name != null) - result.addProperty("name", src.name); - return result; - } - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/Property.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/Property.java deleted file mode 100644 index a6cbe26ab..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/Property.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.auth.yggdrasil; - -public class Property { - - public final String name, value; - - public Property(String name, String value) { - this.name = name; - this.value = value; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/PropertyMap.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/PropertyMap.java deleted file mode 100644 index 22f21fe9b..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/PropertyMap.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.auth.yggdrasil; - -import com.google.gson.JsonArray; -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParseException; -import com.google.gson.JsonPrimitive; -import com.google.gson.JsonSerializationContext; -import com.google.gson.JsonSerializer; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import org.jackhuang.hmcl.api.HMCLog; - -public class PropertyMap extends HashMap { - - private static final long serialVersionUID = 362498820763181265L; - - public List> list() { - List> properties = new ArrayList<>(); - for (Property profileProperty : values()) { - Map property = new HashMap<>(); - property.put("name", profileProperty.name); - property.put("value", profileProperty.value); - properties.add(property); - } - return properties; - } - - public void fromList(List> list) { - try { - for (Map propertyMap : list) { - String name = propertyMap.get("name"); - String value = propertyMap.get("value"); - put(name, new Property(name, value)); - } - } catch (Throwable t) { - HMCLog.warn("Failed to deserialize properties", t); - } - } - - public static class Serializer implements JsonSerializer, JsonDeserializer { - - @Override - public PropertyMap deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - PropertyMap result = new PropertyMap(); - if ((json instanceof JsonObject)) { - JsonObject object = (JsonObject) json; - - for (Map.Entry entry : object.entrySet()) - if (entry.getValue() instanceof JsonArray) - for (JsonElement element : (JsonArray) entry.getValue()) - result.put(entry.getKey(), - new Property((String) entry.getKey(), element.getAsString())); - } else if ((json instanceof JsonArray)) - for (JsonElement element : (JsonArray) json) - if ((element instanceof JsonObject)) { - JsonObject object = (JsonObject) element; - String name = object.getAsJsonPrimitive("name").getAsString(); - String value = object.getAsJsonPrimitive("value").getAsString(); - result.put(name, new Property(name, value)); - } - - return result; - } - - @Override - public JsonElement serialize(PropertyMap src, Type typeOfSrc, JsonSerializationContext context) { - JsonArray result = new JsonArray(); - for (Property property : src.values()) { - JsonObject object = new JsonObject(); - object.addProperty("name", property.name); - object.addProperty("value", property.value); - result.add(object); - } - - return result; - } - } - - public static class LegacySerializer - implements JsonSerializer { - - @Override - public JsonElement serialize(PropertyMap src, Type typeOfSrc, JsonSerializationContext context) { - JsonObject result = new JsonObject(); - for (PropertyMap.Entry entry : src.entrySet()) { - JsonArray values = new JsonArray(); - values.add(new JsonPrimitive(entry.getValue().value)); - result.add(entry.getKey(), values); - } - return result; - } - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/RefreshRequest.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/RefreshRequest.java deleted file mode 100644 index ef0873f82..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/RefreshRequest.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.auth.yggdrasil; - -public class RefreshRequest { - - private String clientToken; - private String accessToken; - private GameProfile selectedProfile; - private boolean requestUser = true; - - public RefreshRequest(String accessToken, String clientToken) { - this.clientToken = clientToken; - this.accessToken = accessToken; - } - - public String getClientToken() { - return clientToken; - } - - public void setClientToken(String clientToken) { - this.clientToken = clientToken; - } - - public String getAccessToken() { - return accessToken; - } - - public void setAccessToken(String accessToken) { - this.accessToken = accessToken; - } - - public GameProfile getSelectedProfile() { - return selectedProfile; - } - - public void setSelectedProfile(GameProfile selectedProfile) { - this.selectedProfile = selectedProfile; - } - - public boolean isRequestUser() { - return requestUser; - } - - public void setRequestUser(boolean requestUser) { - this.requestUser = requestUser; - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/Response.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/Response.java deleted file mode 100644 index 7a0921a5b..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/Response.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.auth.yggdrasil; - -import com.google.gson.annotations.SerializedName; - -public class Response { - - @SerializedName("accessToken") - public String accessToken; - @SerializedName("clientToken") - public String clientToken; - @SerializedName("selectedProfile") - public GameProfile selectedProfile; - @SerializedName("availableProfiles") - public GameProfile[] availableProfiles; - @SerializedName("user") - public User user; - @SerializedName("error") - public String error; - @SerializedName("errorMessage") - public String errorMessage; - @SerializedName("cause") - public String cause; -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/UUIDTypeAdapter.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/UUIDTypeAdapter.java deleted file mode 100644 index 1cfe77a67..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/UUIDTypeAdapter.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.auth.yggdrasil; - -import com.google.gson.TypeAdapter; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonWriter; -import java.io.IOException; -import java.util.UUID; - -public class UUIDTypeAdapter extends TypeAdapter { - - @Override - public void write(JsonWriter out, UUID value) throws IOException { - out.value(fromUUID(value)); - } - - @Override - public UUID read(JsonReader in) throws IOException { - return fromString(in.nextString()); - } - - public static String fromUUID(UUID value) { - return value.toString().replace("-", ""); - } - - public static UUID fromString(String input) { - return UUID.fromString(input.replaceFirst("(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})", "$1-$2-$3-$4-$5")); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/User.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/User.java deleted file mode 100644 index 756a32987..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/User.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.auth.yggdrasil; - -public class User { - - private String id; - private PropertyMap properties; - - public User() { - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public PropertyMap getProperties() { - return properties; - } - - public void setProperties(PropertyMap properties) { - this.properties = properties; - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/UserType.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/UserType.java deleted file mode 100644 index 05294a039..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/UserType.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.auth.yggdrasil; - -import java.util.HashMap; -import java.util.Map; - -/** - * - * @author huang - */ -public enum UserType { - - LEGACY("legacy"), MOJANG("mojang"); - - private static final Map BY_NAME; - private final String name; - - private UserType(String name) { - this.name = name; - } - - public static UserType byName(String name) { - return (UserType) BY_NAME.get(name.toLowerCase()); - } - - public static UserType byLegacy(boolean isLegacy) { - return isLegacy ? LEGACY : MOJANG; - } - - public String getName() { - return this.name; - } - - static { - BY_NAME = new HashMap(); - for (UserType type : values()) - BY_NAME.put(type.name, type); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/ValidateRequest.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/ValidateRequest.java deleted file mode 100644 index a89571b80..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/ValidateRequest.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.auth.yggdrasil; - -/** - * - * @author huang - */ -public class ValidateRequest { - private String clientToken; - private String accessToken; - - public ValidateRequest(YggdrasilAuthentication authentication) { - clientToken = authentication.getClientToken(); - accessToken = authentication.getAuthenticatedToken(); - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/YggdrasilAuthentication.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/YggdrasilAuthentication.java deleted file mode 100644 index 3fed07c82..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/auth/yggdrasil/YggdrasilAuthentication.java +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.auth.yggdrasil; - -import org.jackhuang.hmcl.api.auth.AuthenticationException; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonParseException; -import java.io.IOException; -import java.net.Proxy; -import java.net.URL; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import org.jackhuang.hmcl.util.ArrayUtils; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.util.net.NetUtils; -import org.jackhuang.hmcl.util.StrUtils; - -public class YggdrasilAuthentication { - - public static final Gson GSON = new GsonBuilder() - .registerTypeAdapter(GameProfile.class, new GameProfile.GameProfileSerializer()) - .registerTypeAdapter(PropertyMap.class, new PropertyMap.Serializer()) - .registerTypeAdapter(UUID.class, new UUIDTypeAdapter()).create(); - - protected static final String BASE_URL = "https://authserver.mojang.com/"; - protected static final URL ROUTE_AUTHENTICATE = NetUtils.constantURL(BASE_URL + "authenticate"); - protected static final URL ROUTE_REFRESH = NetUtils.constantURL(BASE_URL + "refresh"); - protected static final URL ROUTE_VALIDATE = NetUtils.constantURL(BASE_URL + "validate"); - - protected static final String STORAGE_KEY_ACCESS_TOKEN = "accessToken"; - protected static final String STORAGE_KEY_PROFILE_NAME = "displayName"; - protected static final String STORAGE_KEY_PROFILE_ID = "uuid"; - protected static final String STORAGE_KEY_PROFILE_PROPERTIES = "profileProperties"; - protected static final String STORAGE_KEY_USER_NAME = "username"; - protected static final String STORAGE_KEY_USER_ID = "userid"; - protected static final String STORAGE_KEY_USER_PROPERTIES = "userProperties"; - - private final Proxy proxy; - private final String clientToken; - private final PropertyMap userProperties = new PropertyMap(); - - private String userid, username, password, accessToken; - private UserType userType; - private GameProfile selectedProfile; - private GameProfile[] profiles; - private boolean isOnline; - - public YggdrasilAuthentication(Proxy proxy, String clientToken) { - this.proxy = proxy; - this.clientToken = clientToken; - } - - // - public void setUserName(String username) { - if ((isLoggedIn()) && (canPlayOnline())) - throw new IllegalStateException("Cannot change username while logged in & online"); - - this.username = username; - } - - public void setPassword(String password) { - if ((isLoggedIn()) && (canPlayOnline()) && (StrUtils.isNotBlank(password))) - throw new IllegalStateException("Cannot set password while logged in & online"); - - this.password = password; - } - - public GameProfile getSelectedProfile() { - return this.selectedProfile; - } - - public String getUserId() { - return this.userid; - } - - public PropertyMap getUserProperties() { - if (isLoggedIn()) - return (PropertyMap) userProperties.clone(); - return new PropertyMap(); - } - - public GameProfile[] getAvailableProfiles() { - if (profiles == null) - return null; - else - return profiles.clone(); - } - - public String getAuthenticatedToken() { - return this.accessToken; - } - - public String getClientToken() { - return clientToken; - } - - // - // - public boolean canPlayOnline() { - return isLoggedIn() && getSelectedProfile() != null && this.isOnline; - } - - public boolean canLogIn() { - return !canPlayOnline() && StrUtils.isNotBlank(username) && (StrUtils.isNotBlank(password) || StrUtils.isNotBlank(getAuthenticatedToken())); - } - - public boolean isLoggedIn() { - return StrUtils.isNotBlank(this.accessToken); - } - - public void logIn() throws AuthenticationException { - if (StrUtils.isBlank(username)) - throw new AuthenticationException(C.i18n("login.invalid_username")); - - if (StrUtils.isNotBlank(getAuthenticatedToken())) { - if (StrUtils.isBlank(getUserId())) - if (StrUtils.isBlank(username)) - userid = username; - else - throw new AuthenticationException(C.i18n("login.invalid_uuid_and_username")); - if (checkTokenValidity()) { - isOnline = true; - return; - } - logInImpl(ROUTE_REFRESH, new RefreshRequest(getAuthenticatedToken(), clientToken)); - } else if (StrUtils.isNotBlank(password)) - logInImpl(ROUTE_AUTHENTICATE, new AuthenticationRequest(username, password, clientToken)); - else - throw new AuthenticationException(C.i18n("login.invalid_password")); - } - - private void logInImpl(URL url, Object input) throws AuthenticationException { - Response response = makeRequest(url, input, Response.class); - - if (!clientToken.equals(response.clientToken)) - throw new AuthenticationException(C.i18n("login.changed_client_token")); - - if (response.selectedProfile != null) - userType = UserType.byLegacy(response.selectedProfile.isLegacy()); - else if (ArrayUtils.isNotEmpty(response.availableProfiles)) - userType = UserType.byLegacy(response.availableProfiles[0].isLegacy()); - - User user = response.user; - userid = user != null && user.getId() != null ? user.getId() : username; - - isOnline = true; - profiles = response.availableProfiles; - selectedProfile = response.selectedProfile; - userProperties.clear(); - this.accessToken = response.accessToken; - - if (user != null && user.getProperties() != null) - userProperties.putAll(user.getProperties()); - } - - protected T makeRequest(URL url, Object input, Class clazz) - throws AuthenticationException { - try { - String jsonResult = input == null ? NetUtils.get(url, proxy) : NetUtils.post(url, GSON.toJson(input), "application/json", proxy); - T response = (T) GSON.fromJson(jsonResult, clazz); - if (response == null) - return null; - - if (StrUtils.isNotBlank(response.error)) { - HMCLog.err("Failed to log in, the auth server returned an error: " + response.error + ", message: " + response.errorMessage + ", cause: " + response.cause); - if (response.errorMessage != null && response.errorMessage.contains("Invalid token")) - response.errorMessage = C.i18n("login.invalid_token"); - throw new AuthenticationException("Request error: " + response.errorMessage); - } - - return response; - } catch (IOException | IllegalStateException | JsonParseException e) { - throw new AuthenticationException(C.i18n("login.failed.connect_authentication_server"), e); - } - } - - protected boolean checkTokenValidity() { - ValidateRequest request = new ValidateRequest(this); - try { - makeRequest(ROUTE_VALIDATE, request, Response.class); - return true; - } catch (AuthenticationException ex) { - return false; - } - } - - public void logOut() { - password = null; - userid = null; - selectedProfile = null; - userProperties.clear(); - - accessToken = null; - profiles = null; - isOnline = false; - } - - // - // - public void loadFromStorage(Map credentials) { - logOut(); - - try { - setUserName((String) credentials.get(STORAGE_KEY_USER_NAME)); - - if (credentials.containsKey(STORAGE_KEY_USER_ID)) - userid = (String) credentials.get(STORAGE_KEY_USER_ID); - else - userid = username; - - if (credentials.containsKey(STORAGE_KEY_USER_PROPERTIES)) - userProperties.fromList((List>) credentials.get(STORAGE_KEY_USER_PROPERTIES)); - - if ((credentials.containsKey(STORAGE_KEY_PROFILE_NAME)) && (credentials.containsKey(STORAGE_KEY_PROFILE_ID))) { - GameProfile profile = new GameProfile(UUIDTypeAdapter.fromString((String) credentials.get(STORAGE_KEY_PROFILE_ID)), (String) credentials.get(STORAGE_KEY_PROFILE_NAME)); - if (credentials.containsKey(STORAGE_KEY_PROFILE_PROPERTIES)) - profile.properties.fromList((List>) credentials.get(STORAGE_KEY_PROFILE_PROPERTIES)); - selectedProfile = profile; - } - - this.accessToken = (String) credentials.get(STORAGE_KEY_ACCESS_TOKEN); - } catch (Exception e) { - HMCLog.err("Failed to load yggdrasil authenticator settings, maybe its format is malformed.", e); - - logOut(); - } - } - - public Map saveForStorage() { - Map result = new HashMap<>(); - - if (username != null) - result.put(STORAGE_KEY_USER_NAME, username); - if (getUserId() != null) - result.put(STORAGE_KEY_USER_ID, getUserId()); - - if (!getUserProperties().isEmpty()) - result.put(STORAGE_KEY_USER_PROPERTIES, getUserProperties().list()); - - GameProfile sel = getSelectedProfile(); - if (sel != null) { - result.put(STORAGE_KEY_PROFILE_NAME, sel.name); - result.put(STORAGE_KEY_PROFILE_ID, sel.id); - if (!sel.properties.isEmpty()) - result.put(STORAGE_KEY_PROFILE_PROPERTIES, sel.properties.list()); - } - - if (StrUtils.isNotBlank(getAuthenticatedToken())) - result.put(STORAGE_KEY_ACCESS_TOKEN, getAuthenticatedToken()); - - return result; - } - - // -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/BMCLAPIDownloadProvider.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/BMCLAPIDownloadProvider.java deleted file mode 100644 index 7a773fc6c..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/BMCLAPIDownloadProvider.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.download; - -import org.jackhuang.hmcl.core.install.InstallerVersionList; -import org.jackhuang.hmcl.util.C; - -/** - * - * @author huangyuhui - */ -public class BMCLAPIDownloadProvider extends IDownloadProvider { - - @Override - public InstallerVersionList getForgeInstaller() { - return org.jackhuang.hmcl.core.install.forge.MinecraftForgeVersionList.getInstance(); - } - - @Override - public InstallerVersionList getLiteLoaderInstaller() { - return org.jackhuang.hmcl.core.install.liteloader.LiteLoaderVersionList.getInstance(); - } - - @Override - public InstallerVersionList getOptiFineInstaller() { - return org.jackhuang.hmcl.core.install.optifine.bmcl.OptiFineBMCLVersionList.getInstance(); - } - - @Override - public String getLibraryDownloadURL() { - return "http://bmclapi2.bangbang93.com/libraries"; - } - - @Override - public String getVersionsDownloadURL() { - return "http://bmclapi2.bangbang93.com/versions/"; - } - - @Override - public String getIndexesDownloadURL() { - return "http://bmclapi2.bangbang93.com/indexes/"; - } - - @Override - public String getVersionsListDownloadURL() { - return "http://bmclapi2.bangbang93.com/mc/game/version_manifest.json"; - } - - @Override - public String getAssetsDownloadURL() { - return "http://bmclapi2.bangbang93.com/assets/"; - } - - @Override - public String getParsedDownloadURL(String str) { - return str == null ? null - : str.replace("https://launchermeta.mojang.com", "http://bmclapi2.bangbang93.com") - .replace("https://launcher.mojang.com", "http://bmclapi2.bangbang93.com") - .replace("https://libraries.minecraft.net", "http://bmclapi2.bangbang93.com/libraries") - .replace("http://files.minecraftforge.net/maven", "http://bmclapi2.bangbang93.com/maven") - .replace(C.URL_LITELOADER_LIST, "http://bmclapi2.bangbang93.com/maven/com/mumfrey/liteloader/versions.json") - .replace("http://dl.liteloader.com/versions", "http://bmclapi2.bangbang93.com/maven"); - } - - @Override - public boolean isAllowedToUseSelfURL() { - return true; - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/CurseDownloadProvider.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/CurseDownloadProvider.java deleted file mode 100644 index 345dd22fa..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/CurseDownloadProvider.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.download; - -/** - * - * @author huangyuhui - */ -public class CurseDownloadProvider extends MojangDownloadProvider { - - @Override - public String getParsedDownloadURL(String str) { - return str == null ? null : str.replace("http://files.minecraftforge.net/maven", "http://ftb.cursecdn.com/FTB2/maven"); - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/DownloadLibraryJob.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/DownloadLibraryJob.java deleted file mode 100644 index 91c3bc00a..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/DownloadLibraryJob.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.download; - -import java.io.File; -import org.jackhuang.hmcl.api.game.IMinecraftLibrary; - -/** - * - * @author huangyuhui - */ -public class DownloadLibraryJob { - - public IMinecraftLibrary lib; - public String url; - public File path; - - public DownloadLibraryJob(IMinecraftLibrary n, String u, File p) { - url = u; - lib = n; - path = p; - } - - public DownloadLibraryJob parse(DownloadType type) { - String name = lib.getName(); - if (name.startsWith("net.minecraftforge:forge:") && url == null) { - String[] s = name.split(":"); - if (s.length == 3) - url = type.getProvider().getParsedDownloadURL("http://files.minecraftforge.net/maven/net/minecraftforge/forge/" + s[2] + "/forge-" + s[2] + "-universal.jar"); - } - if (name.startsWith("com.mumfrey:liteloader:") && url == null) { - String[] s = name.split(":"); - if (s.length == 3 && s[2].length() > 3) - url = type.getProvider().getParsedDownloadURL("http://dl.liteloader.com/versions/com/mumfrey/liteloader/" + s[2].substring(0, s[2].length() - 3) + "/liteloader-" + s[2] + ".jar"); - } - return this; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/DownloadType.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/DownloadType.java deleted file mode 100644 index 1f96a13d0..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/DownloadType.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.download; - -import org.jackhuang.hmcl.api.HMCLApi; -import org.jackhuang.hmcl.api.event.config.DownloadTypeChangedEvent; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.util.task.TaskWindow; - -/** - * - * @author huangyuhui - */ -public enum DownloadType { - - Mojang("download.mojang", new MojangDownloadProvider()), - BMCL("download.BMCL", new BMCLAPIDownloadProvider()), - Curse("Curse CDN", new CurseDownloadProvider()); - - private final String name; - private final IDownloadProvider provider; - - DownloadType(String a, IDownloadProvider provider) { - name = a; - this.provider = provider; - } - - public IDownloadProvider getProvider() { - return provider; - } - - public String getName() { - return C.i18n(name); - } - - private static DownloadType suggestedDownloadType = Mojang; - - public static DownloadType getSuggestedDownloadType() { - return suggestedDownloadType; - } - - public static void setSuggestedDownloadType(String id) { - DownloadType s = DownloadType.valueOf(id); - if (s == null) - throw new IllegalArgumentException("download type should not be null."); - TaskWindow.downloadSource = s.getName(); - DownloadType.suggestedDownloadType = s; - } - - static { - HMCLApi.EVENT_BUS.channel(DownloadTypeChangedEvent.class).register(t -> setSuggestedDownloadType(t.getValue())); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/IDownloadProvider.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/IDownloadProvider.java deleted file mode 100644 index 47c3b7532..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/IDownloadProvider.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.download; - -import org.jackhuang.hmcl.core.install.InstallerType; -import org.jackhuang.hmcl.core.install.InstallerVersionList; - -/** - * - * @author huangyuhui - */ -public abstract class IDownloadProvider { - - public InstallerVersionList getInstallerByType(InstallerType type) { - switch (type) { - case Forge: - return getForgeInstaller(); - case LiteLoader: - return getLiteLoaderInstaller(); - case OptiFine: - return getOptiFineInstaller(); - default: - return null; - } - } - - public abstract InstallerVersionList getForgeInstaller(); - - public abstract InstallerVersionList getLiteLoaderInstaller(); - - public abstract InstallerVersionList getOptiFineInstaller(); - - public abstract String getLibraryDownloadURL(); - - public abstract String getVersionsDownloadURL(); - - public abstract String getIndexesDownloadURL(); - - public abstract String getVersionsListDownloadURL(); - - public abstract String getAssetsDownloadURL(); - - /** - * For example, minecraft.json/assetIndex/url or - * minecraft.json/downloads/client/url - * - * @param str baseURL - * - * @return parsedURL - */ - public abstract String getParsedDownloadURL(String str); - - public abstract boolean isAllowedToUseSelfURL(); -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/MinecraftDownloadService.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/MinecraftDownloadService.java deleted file mode 100644 index 058b9d211..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/MinecraftDownloadService.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.download; - -import org.jackhuang.hmcl.core.service.IMinecraftDownloadService; -import com.google.gson.JsonSyntaxException; -import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.core.GameException; -import org.jackhuang.hmcl.core.service.IMinecraftService; -import org.jackhuang.hmcl.core.version.GameDownloadInfo; -import org.jackhuang.hmcl.api.game.IMinecraftLibrary; -import org.jackhuang.hmcl.core.version.MinecraftVersion; -import org.jackhuang.hmcl.util.net.FileDownloadTask; -import org.jackhuang.hmcl.api.func.Function; -import org.jackhuang.hmcl.util.sys.FileUtils; -import org.jackhuang.hmcl.util.task.Task; -import org.jackhuang.hmcl.util.task.TaskInfo; - -/** - * - * @author huangyuhui - */ -public class MinecraftDownloadService extends IMinecraftDownloadService { - - public MinecraftDownloadService(IMinecraftService service) { - super(service); - } - - @Override - public List getDownloadLibraries(MinecraftVersion mv) throws GameException { - ArrayList downloadLibraries = new ArrayList<>(); - if (mv == null) - return downloadLibraries; - MinecraftVersion v = mv.resolve(service.version()); - for (IMinecraftLibrary l : v.getLibraries()) - if (l != null && l.allow()) { - File ff = service.version().getLibraryFile(mv, l); - if (!ff.exists() && l.getDownloadURL(service.getDownloadType().name()) != null) { - String libURL = l.getDownloadURL(service.getDownloadType().name()); - if (libURL != null) - downloadLibraries.add(new DownloadLibraryJob(l, libURL, ff)); - } - } - return downloadLibraries; - } - - @Override - public Task downloadMinecraft(String id) { - return new TaskInfo("Download Minecraft") { - @Override - public Collection getDependTasks() { - return Arrays.asList(downloadMinecraftVersionJson(id)); - } - - @Override - public void executeTask(boolean areDependTasksSucceeded) throws Exception { - File vpath = new File(service.baseDirectory(), "versions/" + id); - if (!areDependTasksSucceeded) { - FileUtils.deleteDirectory(vpath); - throw new RuntimeException("Cannot continue because of download failing."); - } - File mvj = new File(vpath, id + ".jar"); - if (mvj.exists() && !mvj.delete()) - HMCLog.warn("Failed to delete " + mvj); - try { - MinecraftVersion mv = C.GSON.fromJson(FileUtils.readQuietly(new File(vpath, id + ".json")), MinecraftVersion.class); - if (mv == null) - throw new JsonSyntaxException("incorrect version"); - - afters.add(downloadMinecraftJar(mv, mvj)); - } catch (JsonSyntaxException ex) { - HMCLog.err("Failed to parse minecraft version json.", ex); - FileUtils.deleteDirectory(vpath); - } - } - - Collection afters = new HashSet<>(); - - @Override - public Collection getAfterTasks() { - return afters; - } - }; - } - - private static class DownloadTypeSwitcher implements Function { - - String suffix; - - public DownloadTypeSwitcher(String suffix) { - this.suffix = suffix; - } - - @Override - public String apply(Integer t) { - return DownloadType.values()[t / 2].getProvider().getVersionsDownloadURL() + suffix; - } - - } - - @Override - public Task downloadMinecraftJar(MinecraftVersion mv, File mvj) { - GameDownloadInfo i = mv.getClientDownloadInfo(); - return new FileDownloadTask(i.getUrl(service.getDownloadType()), mvj, i.sha1) - .setFailedCallbackReturnsNewURL(new DownloadTypeSwitcher(mv.id + "/" + mv.id + ".jar")).setTag(mv.id + ".jar"); - } - - @Override - public Task downloadMinecraftVersionJson(String id) { - return new TaskInfo("Download Minecraft Json") { - @Override - public void executeTask(boolean areDependTasksSucceeded) throws Exception { - List versions = MinecraftRemoteVersions.getRemoteVersions(service.getDownloadType()).justDo(); - MinecraftRemoteVersion currentVersion = null; - for (MinecraftRemoteVersion v : versions) - if (id.equals(v.id)) { - currentVersion = v; - break; - } - if (currentVersion == null) - throw new RuntimeException("Cannot find version: " + id + " in remote repository."); - String jsonURL = currentVersion.getUrl(service.getDownloadType()); - File vpath = new File(service.baseDirectory(), "versions/" + id); - File mvt = new File(vpath, id + ".json"); - if (!FileUtils.makeDirectory(vpath)) - HMCLog.warn("Failed to make directories: " + vpath); - if (mvt.exists() && !mvt.delete()) - HMCLog.warn("Failed to delete " + mvt); - - afters.add(new FileDownloadTask(jsonURL, mvt).setTag(id + ".json")); - } - - Collection afters = new HashSet<>(); - - @Override - public Collection getAfterTasks() { - return afters; - } - }; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/MinecraftRemoteLatestVersion.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/MinecraftRemoteLatestVersion.java deleted file mode 100644 index ebf073c4a..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/MinecraftRemoteLatestVersion.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.download; - -import com.google.gson.annotations.SerializedName; - -/** - * - * @author huangyuhui - */ -public class MinecraftRemoteLatestVersion { - - @SerializedName("snapshot") - public String snapshot; - - @SerializedName("release") - public String release; - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/MinecraftRemoteVersion.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/MinecraftRemoteVersion.java deleted file mode 100644 index 97fbbf151..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/MinecraftRemoteVersion.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.download; - -import com.google.gson.annotations.SerializedName; - -/** - * - * @author huangyuhui - */ -public class MinecraftRemoteVersion { - - @SerializedName("id") - public String id; - @SerializedName("time") - public String time; - @SerializedName("releaseTime") - public String releaseTime; - @SerializedName("type") - public String type; - @SerializedName("url") - private String url; - - public String getUrl(DownloadType type) { - if (url == null) - return type.getProvider().getVersionsDownloadURL() + id + "/" + id + ".json"; - return type.getProvider().getParsedDownloadURL(url); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/MinecraftRemoteVersions.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/MinecraftRemoteVersions.java deleted file mode 100644 index 9eb1e03e8..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/MinecraftRemoteVersions.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.download; - -import com.google.gson.annotations.SerializedName; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.util.net.HTTPGetTask; -import org.jackhuang.hmcl.util.task.Task; -import org.jackhuang.hmcl.util.task.TaskWorker; - -/** - * - * @author huangyuhui - */ -public class MinecraftRemoteVersions { - - @SerializedName("versions") - public ArrayList versions; - @SerializedName("latest") - public MinecraftRemoteLatestVersion latest; - - private static volatile MinecraftRemoteVersions INSTANCE = null; - private static final Object INSTANCE_LOCK = new Object(); - - public static RemoteVersionsTask getRemoteVersions(DownloadType type) { - return new RemoteVersionsTask(type) { - @Override - public void executeTask(boolean b) throws Exception { - synchronized (INSTANCE_LOCK) { - if (INSTANCE != null) - send(INSTANCE.versions.toArray(new MinecraftRemoteVersion[INSTANCE.versions.size()])); - else - super.executeTask(b); - } - } - }; - } - - public static RemoteVersionsTask refreshRomoteVersions(DownloadType type) { - return new RemoteVersionsTask(type); - } - - public static class RemoteVersionsTask extends TaskWorker { - - HTTPGetTask task; - @Override - public Collection getDependTasks() { - return Arrays.asList(task); - } - - DownloadType type; - - public RemoteVersionsTask(DownloadType type) { - this.type = type; - this.task = new HTTPGetTask(type.getProvider().getVersionsListDownloadURL()); - } - - @Override - public void executeTask(boolean b) throws Exception { - if (!b) throw new IllegalStateException("Previous http get task failed"); - MinecraftRemoteVersions r = C.GSON.fromJson(task.getResult(), MinecraftRemoteVersions.class); - if (r != null && r.versions != null) { - INSTANCE = r; - send(r.versions.toArray(new MinecraftRemoteVersion[r.versions.size()])); - } - } - - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/MojangDownloadProvider.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/MojangDownloadProvider.java deleted file mode 100644 index 913a63112..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/download/MojangDownloadProvider.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.download; - -import java.util.Locale; -import org.jackhuang.hmcl.core.install.InstallerVersionList; -import org.jackhuang.hmcl.util.lang.SupportedLocales; - -/** - * - * @author huangyuhui - */ -public class MojangDownloadProvider extends IDownloadProvider { - - @Override - public InstallerVersionList getForgeInstaller() { - return org.jackhuang.hmcl.core.install.forge.MinecraftForgeVersionList.getInstance(); - } - - @Override - public InstallerVersionList getLiteLoaderInstaller() { - return org.jackhuang.hmcl.core.install.liteloader.LiteLoaderVersionList.getInstance(); - } - - @Override - public InstallerVersionList getOptiFineInstaller() { - return org.jackhuang.hmcl.core.install.optifine.vanilla.OptiFineVersionList.getInstance(); - } - - @Override - public String getLibraryDownloadURL() { - return "https://libraries.minecraft.net"; - } - - @Override - public String getVersionsDownloadURL() { - return "http://s3.amazonaws.com/Minecraft.Download/versions/"; - } - - @Override - public String getIndexesDownloadURL() { - return "http://s3.amazonaws.com/Minecraft.Download/indexes/"; - } - - @Override - public String getVersionsListDownloadURL() { - return "https://launchermeta.mojang.com/mc/game/version_manifest.json"; - } - - @Override - public String getAssetsDownloadURL() { - return "http://resources.download.minecraft.net/"; - } - - @Override - public boolean isAllowedToUseSelfURL() { - return true; - } - - @Override - public String getParsedDownloadURL(String str) { - if (str == null) - return null; - else if (str.contains("scala-swing") || str.contains("scala-xml") || str.contains("scala-parser-combinators")) - return str.replace("http://files.minecraftforge.net/maven", "http://ftb.cursecdn.com/FTB2/maven/"); - else if (str.contains("typesafe") || str.contains("scala")) - if (SupportedLocales.getNowLocale().self == Locale.CHINA) - return str.replace("http://files.minecraftforge.net/maven", "http://maven.aliyun.com/nexus/content/groups/public"); - else - return str.replace("http://files.minecraftforge.net/maven", "http://repo1.maven.org/maven2"); - else - return str; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/InstallProfile.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/InstallProfile.java deleted file mode 100644 index 85cad09ef..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/InstallProfile.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.install; - -import com.google.gson.annotations.SerializedName; -import org.jackhuang.hmcl.core.version.MinecraftVersion; -import org.jackhuang.hmcl.core.install.forge.Install; - -/** - * - * @author huangyuhui - */ -public class InstallProfile { - - @SerializedName("install") - public Install install; - @SerializedName("versionInfo") - public MinecraftVersion versionInfo; -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/InstallerType.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/InstallerType.java deleted file mode 100644 index bbd98dfd2..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/InstallerType.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.install; - -/** - * - * @author huangyuhui - */ -public enum InstallerType { - Forge("forge"), OptiFine("optifine"), LiteLoader("liteloader"); - - public final String id; - - private InstallerType(String id) { - this.id = id; - } - - public String getLocalizedName() { - return this.name(); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/InstallerVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/InstallerVersionList.java deleted file mode 100644 index c69cd07a6..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/InstallerVersionList.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.install; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import org.jackhuang.hmcl.util.StrUtils; -import org.jackhuang.hmcl.util.task.Task; - -/** - * - * @author huangyuhui - */ -public abstract class InstallerVersionList { - - public Map> versionMap; - public List versions; - - /** - * Refresh installer versions list from the downloaded content. - * - * @param versions Minecraft versions you need to refresh - * - * @throws java.lang.Exception including network exceptions, IO exceptions. - */ - public abstract Task refresh(String[] versions); - - /** - * Installer name. - * - * @return installer name. - */ - public abstract String getName(); - - /** - * Get installers you want. - * - * @param mcVersion the installers to this Minecraft version. - * - * @return cached result. - */ - private List getVersionsImpl(String mcVersion) { - if (versions == null || versionMap == null) - return null; - if (StrUtils.isBlank(mcVersion)) - return versions; - List c = versionMap.get(mcVersion); - if (c == null) - return versions; - Collections.sort(c, InstallerVersionComparator.INSTANCE); - return c; - } - - /** - * Get installers you want, please cache this method's result to save time. - * - * @param mcVersion the installers to this Minecraft version. - * - * @return a copy of the cached data to prevent - * ConcurrentModificationException. - */ - public List getVersions(String mcVersion) { - List a = getVersionsImpl(mcVersion); - if (a == null) - return null; - else - return new ArrayList<>(a); - } - - public static class InstallerVersion implements Comparable { - - public String selfVersion, mcVersion; - public String installer, universal; - public String changelog; - - public InstallerVersion(String selfVersion, String mcVersion) { - this.selfVersion = selfVersion; - this.mcVersion = mcVersion; - } - - @Override - public int compareTo(InstallerVersion o) { - return selfVersion.compareTo(o.selfVersion); - } - - @Override - public int hashCode() { - return selfVersion.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - final InstallerVersion other = (InstallerVersion) obj; - return Objects.equals(this.selfVersion, other.selfVersion); - } - - } - - public static class InstallerVersionComparator implements Comparator, Serializable { - - private static final long serialVersionUID = 3276198781795213723L; - - public static final InstallerVersionComparator INSTANCE = new InstallerVersionComparator(); - - @Override - public int compare(InstallerVersion o1, InstallerVersion o2) { - return o2.compareTo(o1); - } - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/InstallerVersionNewerComparator.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/InstallerVersionNewerComparator.java deleted file mode 100644 index b04c8d14f..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/InstallerVersionNewerComparator.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.install; - -import java.io.Serializable; -import java.util.Comparator; -import org.jackhuang.hmcl.core.install.InstallerVersionList.InstallerVersion; - -/** - * - * @author huangyuhui - */ -public class InstallerVersionNewerComparator implements Comparator, Serializable { - - private static final long serialVersionUID = 14758562453742645L; - - @Override - public int compare(InstallerVersion o1, InstallerVersion o2) { - return o2.compareTo(o1); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/MinecraftInstallerService.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/MinecraftInstallerService.java deleted file mode 100644 index f5977e826..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/MinecraftInstallerService.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.install; - -import org.jackhuang.hmcl.core.service.IMinecraftInstallerService; -import java.io.File; -import org.jackhuang.hmcl.core.service.IMinecraftService; -import org.jackhuang.hmcl.core.install.InstallerVersionList.InstallerVersion; -import org.jackhuang.hmcl.core.install.forge.ForgeInstaller; -import org.jackhuang.hmcl.core.install.liteloader.LiteLoaderInstaller; -import org.jackhuang.hmcl.core.install.liteloader.LiteLoaderInstallerVersion; -import org.jackhuang.hmcl.core.install.optifine.OptiFineInstaller; -import org.jackhuang.hmcl.core.install.optifine.vanilla.OptiFineDownloadFormatter; -import org.jackhuang.hmcl.util.task.Task; -import org.jackhuang.hmcl.util.net.FileDownloadTask; -import org.jackhuang.hmcl.util.task.DeleteFileTask; - -/** - * - * @author huangyuhui - */ -public final class MinecraftInstallerService extends IMinecraftInstallerService { - - public MinecraftInstallerService(IMinecraftService service) { - super(service); - } - - @Override - public Task download(String installId, InstallerVersion v, InstallerType type) { - switch (type) { - case Forge: - return downloadForge(installId, v); - case OptiFine: - return downloadOptiFine(installId, v); - case LiteLoader: - return downloadLiteLoader(installId, v); - default: - return null; - } - } - - @Override - public Task downloadForge(String installId, InstallerVersion v) { - File filepath = new File("forge-installer.jar").getAbsoluteFile(); - if (v.installer == null) - return null; - else - return new FileDownloadTask(service.getDownloadType().getProvider().getParsedDownloadURL(v.installer), filepath).setTag("forge") - .with(new ForgeInstaller(service, filepath)) - .with(new DeleteFileTask(filepath)); - } - - @Override - public Task downloadOptiFine(String installId, InstallerVersion v) { - File filepath = new File("optifine-installer.jar").getAbsoluteFile(); - if (v.installer == null) - return null; - OptiFineDownloadFormatter task = new OptiFineDownloadFormatter(v.installer); - return task.with(new FileDownloadTask(filepath).registerPreviousResult(task).setTag("optifine")) - .with(new OptiFineInstaller(service, installId, v, filepath)) - .with(new DeleteFileTask(filepath)); - } - - @Override - public Task downloadLiteLoader(String installId, InstallerVersion v) { - if (!(v instanceof LiteLoaderInstallerVersion)) - throw new Error("Download lite loader but the version is not ll's."); - File filepath = new File("liteloader-universal.jar").getAbsoluteFile(); - FileDownloadTask task = (FileDownloadTask) new FileDownloadTask(v.universal, filepath).setTag("LiteLoader"); - return task.with(new LiteLoaderInstaller(service, installId, (LiteLoaderInstallerVersion) v).registerPreviousResult(task)) - .with(new DeleteFileTask(filepath)); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/forge/ForgeInstaller.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/forge/ForgeInstaller.java deleted file mode 100644 index 16375b971..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/forge/ForgeInstaller.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.install.forge; - -import org.jackhuang.hmcl.core.install.InstallProfile; -import java.io.File; -import java.io.FileOutputStream; -import java.io.InputStream; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.core.service.IMinecraftService; -import org.jackhuang.hmcl.util.task.Task; -import org.jackhuang.hmcl.util.sys.FileUtils; -import org.jackhuang.hmcl.core.version.MinecraftLibrary; -import org.jackhuang.hmcl.util.ui.MessageBox; -import org.jackhuang.hmcl.util.sys.IOUtils; - -/** - * - * @author huangyuhui - */ -public class ForgeInstaller extends Task { - - public File gameDir; - public File forgeInstaller; - public IMinecraftService mp; - - public ForgeInstaller(IMinecraftService mp, File forgeInstaller) { - this.gameDir = mp.baseDirectory(); - this.forgeInstaller = forgeInstaller; - this.mp = mp; - } - - @Override - public void executeTask(boolean areDependTasksSucceeded) throws Exception { - HMCLog.log("Extracting install profiles..."); - - try (ZipFile zipFile = new ZipFile(forgeInstaller)) { - ZipEntry entry = zipFile.getEntry("install_profile.json"); - String content = IOUtils.toString(zipFile.getInputStream(entry)); - InstallProfile profile = C.GSON.fromJson(content, InstallProfile.class); - File from = new File(gameDir, "versions" + File.separator + profile.install.getMinecraft()); - if (!from.exists()) - if (MessageBox.show(C.i18n("install.no_version_if_intall")) == MessageBox.YES_OPTION) { - if (!mp.version().install(profile.install.getMinecraft(), null)) - throw new IllegalStateException(C.i18n("install.no_version")); - } else - throw new IllegalStateException(C.i18n("install.no_version")); - File to = new File(gameDir, "versions" + File.separator + profile.install.getTarget()); - if (!FileUtils.makeDirectory(to)) - HMCLog.warn("Failed to make new version folder " + to); - - HMCLog.log("Copying jar..." + profile.install.getMinecraft() + ".jar to " + profile.install.getTarget() + ".jar"); - FileUtils.copyFile(new File(from, profile.install.getMinecraft() + ".jar"), - new File(to, profile.install.getTarget() + ".jar")); - - HMCLog.log("Creating new version profile..." + profile.install.getTarget() + ".json"); - FileUtils.write(new File(to, profile.install.getTarget() + ".json"), C.GSON.toJson(profile.versionInfo)); - - HMCLog.log("Extracting universal forge pack..." + profile.install.getFilePath()); - entry = zipFile.getEntry(profile.install.getFilePath()); - InputStream is = zipFile.getInputStream(entry); - MinecraftLibrary forge = new MinecraftLibrary(profile.install.getPath()); - - // We use options from the old vanilla version. - File file = mp.version().getLibraryFile(mp.version().getVersionById(profile.install.getMinecraft()), forge); - - if (!FileUtils.makeDirectory(file.getParentFile())) - HMCLog.warn("Failed to make library directory " + file.getParent()); - try (FileOutputStream fos = FileUtils.openOutputStream(file)) { - IOUtils.copyStream(is, fos); - } - mp.version().refreshVersions(); - } - } - - @Override - public String getInfo() { - return C.i18n("install.forge.install"); - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/forge/Install.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/forge/Install.java deleted file mode 100644 index d4a01cfe4..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/forge/Install.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.install.forge; - -import com.google.gson.annotations.SerializedName; - -/** - * - * @author huangyuhui - */ -public class Install { - - @SerializedName("profileName") - private String profileName; - @SerializedName("target") - private String target; - @SerializedName("path") - private String path; - @SerializedName("version") - private String version; - @SerializedName("filePath") - private String filePath; - @SerializedName("welcome") - private String welcome; - @SerializedName("minecraft") - private String minecraft; - @SerializedName("mirrorList") - private String mirrorList; - @SerializedName("logo") - private String logo; - - public Install() { - } - - public String getProfileName() { - return profileName; - } - - public void setProfileName(String profileName) { - this.profileName = profileName; - } - - public String getTarget() { - return target; - } - - public void setTarget(String target) { - this.target = target; - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - public String getFilePath() { - return filePath; - } - - public void setFilePath(String filePath) { - this.filePath = filePath; - } - - public String getWelcome() { - return welcome; - } - - public void setWelcome(String welcome) { - this.welcome = welcome; - } - - public String getMinecraft() { - return minecraft; - } - - public void setMinecraft(String minecraft) { - this.minecraft = minecraft; - } - - public String getMirrorList() { - return mirrorList; - } - - public void setMirrorList(String mirrorList) { - this.mirrorList = mirrorList; - } - - public String getLogo() { - return logo; - } - - public void setLogo(String logo) { - this.logo = logo; - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/forge/MinecraftForgeVersion.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/forge/MinecraftForgeVersion.java deleted file mode 100644 index 9c288e707..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/forge/MinecraftForgeVersion.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.install.forge; - -/** - * - * @author huangyuhui - */ -public class MinecraftForgeVersion { - - public String branch, mcversion, jobver, version; - public int build; - public double modified; - public String[][] files; - - public String getBranch() { - return branch; - } - - public void setBranch(String branch) { - this.branch = branch; - } - - public String getMCVersion() { - return mcversion; - } - - public void setMCVersion(String mcversion) { - this.mcversion = mcversion; - } - - public String getJobver() { - return jobver; - } - - public void setJobver(String jobver) { - this.jobver = jobver; - } - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - public int getBuild() { - return build; - } - - public void setBuild(int build) { - this.build = build; - } - - public double getModified() { - return modified; - } - - public void setModified(double modified) { - this.modified = modified; - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/forge/MinecraftForgeVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/forge/MinecraftForgeVersionList.java deleted file mode 100644 index 95e4f9ce7..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/forge/MinecraftForgeVersionList.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.install.forge; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.core.download.DownloadType; -import org.jackhuang.hmcl.util.StrUtils; -import org.jackhuang.hmcl.core.install.InstallerVersionList; -import org.jackhuang.hmcl.core.install.InstallerVersionNewerComparator; -import org.jackhuang.hmcl.util.task.Task; -import org.jackhuang.hmcl.util.task.TaskInfo; -import org.jackhuang.hmcl.util.net.HTTPGetTask; - -/** - * - * @author huangyuhui - */ -public class MinecraftForgeVersionList extends InstallerVersionList { - - private static volatile MinecraftForgeVersionList instance; - - public static MinecraftForgeVersionList getInstance() { - if (instance == null) - instance = new MinecraftForgeVersionList(); - return instance; - } - - public MinecraftForgeVersionRoot root; - - @Override - public Task refresh(String[] needed) { - if (root != null) - return null; - return new TaskInfo(C.i18n("install.forge.get_list")) { - HTTPGetTask task = new HTTPGetTask(DownloadType.getSuggestedDownloadType().getProvider().getParsedDownloadURL(C.URL_FORGE_LIST)); - - @Override - public Collection getDependTasks() { - return Arrays.asList(task.setTag("Official Forge Download Site")); - } - - @Override - public void executeTask(boolean areDependTasksSucceeded) throws Exception { - if (!areDependTasksSucceeded) - return; - String s = task.getResult(); - - root = C.GSON.fromJson(s, MinecraftForgeVersionRoot.class); - - versionMap = new HashMap<>(); - versions = new ArrayList<>(); - - for (Map.Entry arr : root.mcversion.entrySet()) { - String mcver = StrUtils.formatVersion(arr.getKey()); - ArrayList al = new ArrayList<>(); - for (int num : arr.getValue()) { - MinecraftForgeVersion v = root.number.get(num); - InstallerVersion iv = new InstallerVersion(v.version, StrUtils.formatVersion(v.mcversion)); - for (String[] f : v.files) { - String ver = v.mcversion + "-" + v.version; - if (!StrUtils.isBlank(v.branch)) - ver = ver + "-" + v.branch; - String filename = root.artifact + "-" + ver + "-" + f[1] + "." + f[0]; - String url = DownloadType.getSuggestedDownloadType().getProvider().getParsedDownloadURL(root.webpath + ver + "/" + filename); - switch (f[1]) { - case "installer": - iv.installer = url; - break; - case "universal": - iv.universal = url; - break; - case "changelog": - iv.changelog = url; - break; - default: - break; - } - } - if (StrUtils.isBlank(iv.installer) || StrUtils.isBlank(iv.universal)) - continue; - Collections.sort(al, new InstallerVersionNewerComparator()); - al.add(iv); - versions.add(iv); - } - - versionMap.put(mcver, al); - } - - Collections.sort(versions, new InstallerVersionComparator()); - } - }; - } - - @Override - public String getName() { - return "Forge - MinecraftForge Offical Site"; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/forge/MinecraftForgeVersionRoot.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/forge/MinecraftForgeVersionRoot.java deleted file mode 100644 index 3311751e5..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/forge/MinecraftForgeVersionRoot.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.install.forge; - -import com.google.gson.annotations.SerializedName; -import java.util.Map; - -/** - * - * @author huangyuhui - */ -public class MinecraftForgeVersionRoot { - - @SerializedName("artifact") - public String artifact; - @SerializedName("webpath") - public String webpath; - @SerializedName("adfly") - public String adfly; - @SerializedName("homepage") - public String homepage; - @SerializedName("name") - public String name; - @SerializedName("branches") - public Map branches; - @SerializedName("mcversion") - public Map mcversion; - @SerializedName("promos") - public Map promos; - @SerializedName("number") - public Map number; -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderBranch.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderBranch.java deleted file mode 100644 index b896ae349..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderBranch.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.install.liteloader; - -import com.google.gson.annotations.SerializedName; -import java.util.List; -import java.util.Map; -import org.jackhuang.hmcl.core.version.MinecraftLibrary; - -/** - * - * @author huang - */ -public class LiteLoaderBranch { - @SerializedName("libraries") - public List libraries; - - @SerializedName("com.mumfrey:liteloader") - public Map liteLoader; -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderInstaller.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderInstaller.java deleted file mode 100644 index 8794f13f9..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderInstaller.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.install.liteloader; - -import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.core.service.IMinecraftService; -import org.jackhuang.hmcl.util.task.Task; -import org.jackhuang.hmcl.util.task.comm.PreviousResult; -import org.jackhuang.hmcl.util.task.comm.PreviousResultRegistrar; -import org.jackhuang.hmcl.util.sys.FileUtils; -import org.jackhuang.hmcl.core.version.MinecraftLibrary; -import org.jackhuang.hmcl.core.version.MinecraftVersion; - -/** - * - * @author huangyuhui - */ -public class LiteLoaderInstaller extends Task implements PreviousResultRegistrar { - - public LiteLoaderInstallerVersion version; - public File installer; - public String installId; - public IMinecraftService service; - - public LiteLoaderInstaller(IMinecraftService service, String installId, LiteLoaderInstallerVersion v) { - this(service, installId, v, null); - } - - public LiteLoaderInstaller(IMinecraftService service, String installId, LiteLoaderInstallerVersion v, File installer) { - this.service = service; - this.installId = installId; - this.version = v; - this.installer = installer; - } - - @Override - public void executeTask(boolean areDependTasksSucceeded) throws Exception { - if (installId == null) - throw new IllegalStateException(C.i18n("install.no_version")); - if (pre.size() != 1 && installer == null) - throw new IllegalStateException("No registered previous task."); - if (installer == null) - installer = pre.get(pre.size() - 1).getResult(); - MinecraftVersion mv = (MinecraftVersion) service.version().getVersionById(installId).clone(); - mv.inheritsFrom = mv.id; - mv.jar = mv.jar == null ? mv.id : mv.jar; - mv.libraries = new ArrayList<>(Arrays.asList(version.libraries)); - - MinecraftLibrary ml = new MinecraftLibrary("com.mumfrey:liteloader:" + version.selfVersion); - ml.url = "http://dl.liteloader.com/versions"; - mv.libraries.add(0, ml); - - // We use options from the old vanilla version. - FileUtils.copyFile(installer, service.version().getLibraryFile(mv, ml)); - - mv.id += "-LiteLoader" + version.selfVersion; - - mv.mainClass = "net.minecraft.launchwrapper.Launch"; - mv.minecraftArguments += " --tweakClass " + version.tweakClass; - File folder = new File(service.baseDirectory(), "versions/" + mv.id); - if (!FileUtils.makeDirectory(folder)) - HMCLog.warn("Failed to create new liteloader version " + folder); - File json = new File(folder, mv.id + ".json"); - HMCLog.log("Creating new version profile..." + mv.id + ".json"); - FileUtils.write(json, C.GSON.toJson(mv)); - - service.version().refreshVersions(); - } - - @Override - public String getInfo() { - return C.i18n("install.liteloader.install"); - } - - ArrayList> pre = new ArrayList<>(); - - @Override - public Task registerPreviousResult(PreviousResult pr) { - pre.add(pr); - return this; - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderInstallerVersion.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderInstallerVersion.java deleted file mode 100644 index c973b5655..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderInstallerVersion.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.install.liteloader; - -import java.util.Arrays; -import java.util.Objects; -import org.jackhuang.hmcl.core.install.InstallerVersionList; -import org.jackhuang.hmcl.core.version.MinecraftLibrary; - -/** - * - * @author huang - */ -public class LiteLoaderInstallerVersion extends InstallerVersionList.InstallerVersion { - - public MinecraftLibrary[] libraries; - public String tweakClass; - - public LiteLoaderInstallerVersion(String selfVersion, String mcVersion) { - super(selfVersion, mcVersion); - } - - @Override - public int hashCode() { - int hash = 7; - hash = 13 * hash + Arrays.deepHashCode(this.libraries); - hash = 13 * hash + Objects.hashCode(this.tweakClass); - return hash; - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof LiteLoaderVersionList)) - return false; - if (this == obj) - return true; - final LiteLoaderInstallerVersion other = (LiteLoaderInstallerVersion) obj; - if (!Objects.equals(this.tweakClass, other.tweakClass)) - return false; - return Arrays.deepEquals(this.libraries, other.libraries); - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderMCVersions.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderMCVersions.java deleted file mode 100644 index a4bdd90ca..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderMCVersions.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.install.liteloader; - -import com.google.gson.annotations.SerializedName; - -/** - * - * @author huangyuhui - */ -public class LiteLoaderMCVersions { - - @SerializedName("repo") - public LiteLoaderRepo repo; - - @SerializedName("artefacts") - public LiteLoaderBranch artefacts; - - @SerializedName("snapshots") - public LiteLoaderBranch snapshots; -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderRepo.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderRepo.java deleted file mode 100644 index a8d94d7e2..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderRepo.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.install.liteloader; - -import com.google.gson.annotations.SerializedName; - -/** - * - * @author huang - */ -public class LiteLoaderRepo { - @SerializedName("stream") - public String stream; - @SerializedName("type") - public String type; - @SerializedName("url") - public String url; - @SerializedName("classifier") - public String classifier; -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderVersion.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderVersion.java deleted file mode 100644 index 4925e52f9..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderVersion.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.install.liteloader; - -import com.google.gson.annotations.SerializedName; -import java.util.List; -import org.jackhuang.hmcl.core.version.MinecraftLibrary; - -/** - * - * @author huangyuhui - */ -public class LiteLoaderVersion { - - @SerializedName("tweakClass") - public String tweakClass; - @SerializedName("file") - public String file; - @SerializedName("version") - public String version; - @SerializedName("md5") - public String md5; - @SerializedName("timestamp") - public String timestamp; - @SerializedName("lastSuccessfulBuild") - public int lastSuccessfulBuild; - @SerializedName("libraries") - public List libraries; -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderVersionList.java deleted file mode 100644 index 46ed08b23..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderVersionList.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.install.liteloader; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import org.jackhuang.hmcl.core.download.DownloadType; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.core.install.InstallerVersionList; -import org.jackhuang.hmcl.core.install.InstallerVersionNewerComparator; -import org.jackhuang.hmcl.core.version.MinecraftLibrary; -import org.jackhuang.hmcl.util.StrUtils; -import org.jackhuang.hmcl.util.task.Task; -import org.jackhuang.hmcl.util.task.TaskInfo; -import org.jackhuang.hmcl.util.net.HTTPGetTask; - -/** - * - * @author huangyuhui - */ -public class LiteLoaderVersionList extends InstallerVersionList { - - private static volatile LiteLoaderVersionList instance = null; - - public static LiteLoaderVersionList getInstance() { - if (instance == null) - instance = new LiteLoaderVersionList(); - return instance; - } - - public LiteLoaderVersionsRoot root; - - @Override - public Task refresh(String[] needed) { - if (root != null) - return null; - return new TaskInfo(C.i18n("install.liteloader.get_list")) { - HTTPGetTask task = new HTTPGetTask(DownloadType.getSuggestedDownloadType().getProvider().getParsedDownloadURL(C.URL_LITELOADER_LIST)); - - @Override - public Collection getDependTasks() { - return Arrays.asList(task.setTag("Official Liteloader Download Site")); - } - - private void doBranch(String version, LiteLoaderRepo repo, LiteLoaderBranch branch, List result, boolean snapshot) { - if (branch == null || branch.liteLoader == null) - return; - for (Map.Entry entry : branch.liteLoader.entrySet()) { - if ("latest".equals(entry.getKey())) - continue; - LiteLoaderVersion v = entry.getValue(); - LiteLoaderInstallerVersion iv = new LiteLoaderInstallerVersion(v.version.replace("SNAPSHOT", "SNAPSHOT-" + v.lastSuccessfulBuild), StrUtils.formatVersion(version)); - if (snapshot) - iv.universal = String.format("http://jenkins.liteloader.com/view/%s/job/LiteLoader %s/lastSuccessfulBuild/artifact/build/libs/liteloader-%s-release.jar", version, version, v.version); - else - iv.universal = DownloadType.getSuggestedDownloadType().getProvider().getParsedDownloadURL(repo.url + "com/mumfrey/liteloader/" + version + "/" + v.file); - iv.tweakClass = v.tweakClass; - HashSet set = new HashSet<>(); - if (v.libraries != null) - set.addAll(v.libraries); - iv.libraries = set.toArray(new MinecraftLibrary[set.size()]); - result.add(iv); - } - } - - @Override - public void executeTask(boolean areDependTasksSucceeded) throws Exception { - if (!areDependTasksSucceeded) - return; - String s = task.getResult(); - - root = C.GSON.fromJson(s, LiteLoaderVersionsRoot.class); - - versionMap = new HashMap<>(); - versions = new ArrayList<>(); - - for (Map.Entry arr : root.versions.entrySet()) { - ArrayList al = new ArrayList<>(); - LiteLoaderMCVersions mcv = arr.getValue(); - doBranch(arr.getKey(), mcv.repo, mcv.artefacts, al, false); - doBranch(arr.getKey(), mcv.repo, mcv.snapshots, al, true); - Collections.sort(al, new InstallerVersionNewerComparator()); - versions.addAll(al); - versionMap.put(StrUtils.formatVersion(arr.getKey()), al); - } - - Collections.sort(versions, InstallerVersionComparator.INSTANCE); - } - }; - } - - @Override - public String getName() { - return "LiteLoader - LiteLoader Official Site(By: Mumfrey)"; - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderVersionsMeta.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderVersionsMeta.java deleted file mode 100644 index af4fe01b4..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderVersionsMeta.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.install.liteloader; - -import com.google.gson.annotations.SerializedName; - -/** - * - * @author huangyuhui - */ -public class LiteLoaderVersionsMeta { - - @SerializedName("versions") - private String description; - @SerializedName("authors") - private String authors; - @SerializedName("url") - private String url; - - public LiteLoaderVersionsMeta() { - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public String getAuthors() { - return authors; - } - - public void setAuthors(String authors) { - this.authors = authors; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderVersionsRoot.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderVersionsRoot.java deleted file mode 100644 index c65ecae61..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/liteloader/LiteLoaderVersionsRoot.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.install.liteloader; - -import com.google.gson.annotations.SerializedName; -import java.util.Map; - -/** - * - * @author huangyuhui - */ -public class LiteLoaderVersionsRoot { - - @SerializedName("versions") - public Map versions; - @SerializedName("meta") - public LiteLoaderVersionsMeta meta; -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/optifine/OptiFineInstaller.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/optifine/OptiFineInstaller.java deleted file mode 100644 index b405294c1..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/optifine/OptiFineInstaller.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.install.optifine; - -import java.io.File; -import java.util.ArrayList; -import java.util.zip.ZipFile; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.core.install.InstallerVersionList; -import org.jackhuang.hmcl.core.service.IMinecraftService; -import org.jackhuang.hmcl.core.version.LibrariesDownloadInfo; -import org.jackhuang.hmcl.core.version.LibraryDownloadInfo; -import org.jackhuang.hmcl.util.task.Task; -import org.jackhuang.hmcl.util.task.comm.PreviousResult; -import org.jackhuang.hmcl.util.task.comm.PreviousResultRegistrar; -import org.jackhuang.hmcl.util.sys.FileUtils; -import org.jackhuang.hmcl.core.version.MinecraftLibrary; -import org.jackhuang.hmcl.core.version.MinecraftVersion; -import org.jackhuang.hmcl.api.HMCLog; - -/** - * - * @author huangyuhui - */ -public class OptiFineInstaller extends Task implements PreviousResultRegistrar { - - public File installer; - public IMinecraftService service; - public InstallerVersionList.InstallerVersion version; - public String installId; - - public OptiFineInstaller(IMinecraftService service, String installId, InstallerVersionList.InstallerVersion version, File installer) { - this.service = service; - this.installId = installId; - this.installer = installer; - this.version = version; - } - - @Override - public void executeTask(boolean areDependTasksSucceeded) throws Exception { - if (installId == null) - throw new Exception(C.i18n("install.no_version")); - String selfId = version.selfVersion; - MinecraftVersion mv = (MinecraftVersion) service.version().getVersionById(installId).clone(); - mv.inheritsFrom = mv.id; - mv.jar = mv.jar == null ? mv.id : mv.jar; - mv.libraries.clear(); - MinecraftLibrary library = new MinecraftLibrary("optifine:OptiFine:" + selfId); - library.downloads = new LibrariesDownloadInfo(); - library.downloads.artifact = new LibraryDownloadInfo(); - library.downloads.artifact.path = "optifine/OptiFine/" + selfId + "/OptiFine-" + selfId + ".jar"; - library.downloads.artifact.url = version.universal; - library.downloads.artifact.sha1 = null; - library.downloads.artifact.size = 0; - mv.libraries.add(0, library); - - // We use options from the old vanilla version. - FileUtils.copyFile(installer, service.version().getLibraryFile(service.version().getVersionById(installId), library)); - - mv.id += "-" + selfId; - try (ZipFile zipFile = new ZipFile(installer)) { - if (zipFile.getEntry("optifine/OptiFineTweaker.class") != null) { - if (!mv.mainClass.startsWith("net.minecraft.launchwrapper.")) { - mv.mainClass = "net.minecraft.launchwrapper.Launch"; - mv.libraries.add(1, new MinecraftLibrary("net.minecraft:launchwrapper:1.7")); - } - if (!mv.minecraftArguments.contains("FMLTweaker")) - mv.minecraftArguments += " --tweakClass optifine.OptiFineTweaker"; - } - } - File loc = new File(service.baseDirectory(), "versions/" + mv.id); - if (!FileUtils.makeDirectory(loc)) - HMCLog.warn("Failed to make directories: " + loc); - File json = new File(loc, mv.id + ".json"); - FileUtils.write(json, C.GSON.toJson(mv, MinecraftVersion.class)); - - service.version().refreshVersions(); - } - - @Override - public String getInfo() { - return "OptiFine Installer"; - } - - ArrayList> pre = new ArrayList<>(); - - @Override - public Task registerPreviousResult(PreviousResult pr) { - pre.add(pr); - return this; - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/optifine/OptiFineVersion.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/optifine/OptiFineVersion.java deleted file mode 100644 index 2fc842b0a..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/optifine/OptiFineVersion.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.install.optifine; - -/** - * - * @author huangyuhui - */ -public class OptiFineVersion { - - private String dl, ver, date, mirror, mcversion; - public String patch, type; // For BMCLAPI2. - - public String getDownloadLink() { - return dl; - } - - public void setDownloadLink(String dl) { - this.dl = dl; - } - - public String getVersion() { - return ver; - } - - public void setVersion(String ver) { - this.ver = ver; - } - - public String getDate() { - return date; - } - - public void setDate(String date) { - this.date = date; - } - - public String getMirror() { - return mirror; - } - - public void setMirror(String mirror) { - this.mirror = mirror; - } - - public String getMCVersion() { - return mcversion; - } - - public void setMCVersion(String mcver) { - this.mcversion = mcver; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/optifine/bmcl/OptiFineBMCLVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/optifine/bmcl/OptiFineBMCLVersionList.java deleted file mode 100644 index 2bd65aafd..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/optifine/bmcl/OptiFineBMCLVersionList.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.install.optifine.bmcl; - -import com.google.gson.reflect.TypeToken; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.util.ArrayUtils; -import org.jackhuang.hmcl.core.install.InstallerVersionList; -import org.jackhuang.hmcl.core.install.optifine.OptiFineVersion; -import org.jackhuang.hmcl.util.StrUtils; -import org.jackhuang.hmcl.util.task.Task; -import org.jackhuang.hmcl.util.task.TaskInfo; -import org.jackhuang.hmcl.util.net.HTTPGetTask; - -/** - * - * @author huangyuhui - */ -public class OptiFineBMCLVersionList extends InstallerVersionList { - - private static OptiFineBMCLVersionList instance; - - public static OptiFineBMCLVersionList getInstance() { - if (null == instance) - instance = new OptiFineBMCLVersionList(); - return instance; - } - - public ArrayList root; - - private static final Type TYPE = new TypeToken>() { - }.getType(); - - @Override - public Task refresh(String[] needed) { - return new TaskInfo(C.i18n("install.optifine.get_list")) { - HTTPGetTask task = new HTTPGetTask("http://bmclapi.bangbang93.com/optifine/versionlist"); - - @Override - public Collection getDependTasks() { - return Arrays.asList(task.setTag("BMCL Optifine Download Site")); - } - - @Override - public void executeTask(boolean areDependTasksSucceeded) throws Exception { - String s = task.getResult(); - - versionMap = new HashMap<>(); - versions = new ArrayList<>(); - - HashSet duplicates = new HashSet<>(); - - if (s == null) - return; - root = C.GSON.fromJson(s, TYPE); - for (OptiFineVersion v : root) { - v.setVersion(v.type + '_' + v.patch); - v.setMirror(String.format("http://bmclapi2.bangbang93.com/optifine/%s/%s/%s", v.getMCVersion(), v.type, v.patch)); - if (duplicates.contains(v.getMirror())) - continue; - else - duplicates.add(v.getMirror()); - InstallerVersion iv = new InstallerVersion(v.getVersion(), StrUtils.formatVersion(v.getMCVersion())); - - List al = ArrayUtils.tryGetMapWithList(versionMap, StrUtils.formatVersion(v.getMCVersion())); - iv.installer = iv.universal = v.getMirror(); - al.add(iv); - versions.add(iv); - } - - Collections.sort(versions, InstallerVersionComparator.INSTANCE); - } - }; - } - - @Override - public String getName() { - return "OptiFine - BMCLAPI(By: bangbang93)"; - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/optifine/vanilla/OptiFineDownloadFormatter.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/optifine/vanilla/OptiFineDownloadFormatter.java deleted file mode 100644 index f5d0b9e1f..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/optifine/vanilla/OptiFineDownloadFormatter.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.install.optifine.vanilla; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.util.task.Task; -import org.jackhuang.hmcl.util.task.comm.PreviousResult; -import org.jackhuang.hmcl.util.net.NetUtils; - -/** - * - * @author huangyuhui - */ -public class OptiFineDownloadFormatter extends Task implements PreviousResult { - - String url, result; - - public OptiFineDownloadFormatter(String url) { - this.url = url; - } - - @Override - public void executeTask(boolean areDependTasksSucceeded) throws Exception { - String content = NetUtils.get(url); - Pattern p = Pattern.compile("\"downloadx\\?f=OptiFine(.*)\""); - Matcher m = p.matcher(content); - while (m.find()) - result = m.group(1); - result = "http://optifine.net/downloadx?f=OptiFine" + result; - } - - @Override - public String getInfo() { - return C.i18n("install.optifine.get_download_link"); - } - - @Override - public String getResult() { - return result; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/optifine/vanilla/OptiFineVersionList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/optifine/vanilla/OptiFineVersionList.java deleted file mode 100644 index 7761e8b10..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/install/optifine/vanilla/OptiFineVersionList.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.install.optifine.vanilla; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import org.jackhuang.hmcl.core.install.InstallerVersionList; -import org.jackhuang.hmcl.core.install.optifine.OptiFineVersion; -import org.jackhuang.hmcl.util.ArrayUtils; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.util.StrUtils; -import org.jackhuang.hmcl.util.task.Task; -import org.jackhuang.hmcl.util.task.TaskInfo; -import org.jackhuang.hmcl.util.net.HTTPGetTask; -import org.w3c.dom.DOMException; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; - -/** - * - * @author huangyuhui - */ -public class OptiFineVersionList extends InstallerVersionList { - - private static OptiFineVersionList instance; - - public static OptiFineVersionList getInstance() { - if (null == instance) - instance = new OptiFineVersionList(); - return instance; - } - - public ArrayList root = new ArrayList<>(); - - @Override - public Task refresh(String[] sss) { - if (versions != null) - return null; - return new TaskInfo(C.i18n("install.optifine.get_list")) { - HTTPGetTask task = new HTTPGetTask("http://optifine.net/downloads"); - - @Override - public Collection getDependTasks() { - return Arrays.asList(task.setTag("Optifine Download Site")); - } - - @Override - public void executeTask(boolean areDependTasksSucceeded) throws Exception { - if (!areDependTasksSucceeded) - return; - String content = task.getResult(); - versionMap = new HashMap<>(); - versions = new ArrayList<>(); - - content = content.replace(" ", " ").replace(">", ">").replace("<", "<").replace("
    ", "
    "); - - try { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder db = factory.newDocumentBuilder(); - Document doc = db.parse(new ByteArrayInputStream(content.getBytes("UTF-8"))); - Element r = doc.getDocumentElement(); - NodeList tables = r.getElementsByTagName("table"); - for (int i = 0; i < tables.getLength(); i++) { - Element e = (Element) tables.item(i); - if ("downloadTable".equals(e.getAttribute("class"))) { - NodeList tr = e.getElementsByTagName("tr"); - for (int k = 0; k < tr.getLength(); k++) { - NodeList downloadLine = ((Element) tr.item(k)).getElementsByTagName("td"); - OptiFineVersion v = new OptiFineVersion(); - for (int j = 0; j < downloadLine.getLength(); j++) { - Element td = (Element) downloadLine.item(j); - if (StrUtils.startsWith(td.getAttribute("class"), "downloadLineMirror")) - v.setMirror(((Element) td.getElementsByTagName("a").item(0)).getAttribute("href")); - if (StrUtils.startsWith(td.getAttribute("class"), "downloadLineDownload")) - v.setDownloadLink(((Element) td.getElementsByTagName("a").item(0)).getAttribute("href")); - if (StrUtils.startsWith(td.getAttribute("class"), "downloadLineDate")) - v.setDate(td.getTextContent()); - if (StrUtils.startsWith(td.getAttribute("class"), "downloadLineFile")) - v.setVersion(td.getTextContent()); - } - if (StrUtils.isBlank(v.getMCVersion())) { - Pattern p = Pattern.compile("OptiFine (.*?) "); - Matcher m = p.matcher(v.getVersion()); - while (m.find()) - v.setMCVersion(StrUtils.formatVersion(m.group(1))); - } - InstallerVersion iv = new InstallerVersion(v.getVersion(), StrUtils.formatVersion(v.getMCVersion())); - iv.installer = iv.universal = v.getMirror(); - root.add(v); - versions.add(iv); - - List ivl = ArrayUtils.tryGetMapWithList(versionMap, StrUtils.formatVersion(v.getMCVersion())); - ivl.add(iv); - } - } - } - } catch (ParserConfigurationException | SAXException | IOException | DOMException ex) { - throw new RuntimeException(ex); - } - - Collections.sort(versions, InstallerVersionComparator.INSTANCE); - } - }; - } - - @Override - public String getName() { - return "OptiFine - OptiFine Official Site"; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/launch/AbstractMinecraftLoader.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/launch/AbstractMinecraftLoader.java deleted file mode 100644 index aa62adf24..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/launch/AbstractMinecraftLoader.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.launch; - -import org.jackhuang.hmcl.api.game.LaunchOptions; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.util.sys.JdkVersion; -import org.jackhuang.hmcl.util.MathUtils; -import org.jackhuang.hmcl.util.ui.MessageBox; -import org.jackhuang.hmcl.util.sys.OS; -import org.jackhuang.hmcl.util.sys.Platform; -import org.jackhuang.hmcl.util.StrUtils; -import org.jackhuang.hmcl.core.GameException; -import org.jackhuang.hmcl.api.auth.UserProfileProvider; -import org.jackhuang.hmcl.core.version.MinecraftVersion; -import org.jackhuang.hmcl.core.service.IMinecraftService; -import org.jackhuang.hmcl.core.service.IMinecraftLoader; - -/** - * - * @author huangyuhui - */ -public abstract class AbstractMinecraftLoader implements IMinecraftLoader { - - protected LaunchOptions options; - protected UserProfileProvider lr; - protected File gameDir; - protected IMinecraftService service; - protected final MinecraftVersion version; - - public AbstractMinecraftLoader(LaunchOptions options, IMinecraftService service, String versionId, UserProfileProvider lr) throws GameException { - if (service.version().getVersionById(versionId) == null) - throw new GameException("No version: " + versionId); - this.lr = lr; - - this.options = options; - this.service = service; - this.gameDir = service.baseDirectory(); - this.version = service.version().getVersionById(versionId).resolve(service.version()); - } - - @Override - public MinecraftVersion getMinecraftVersion() { - return version; - } - - public void makeHeadCommand(List res) { - HMCLog.log("On making head command."); - - if (StrUtils.isNotBlank(options.getWrapper())) - res.add(options.getWrapper()); - - JdkVersion jv = null; - try { - jv = JdkVersion.getJavaVersionFromExecutable(options.getJavaDir()); - } catch (IOException ex) { - HMCLog.err("Failed to read java version", ex); - } - res.add(options.getJavaDir()); - - if (options.hasJavaArgs()) - res.addAll(Arrays.asList(StrUtils.tokenize(options.getJavaArgs()))); - - if (!options.isNoJVMArgs()) { - appendJVMArgs(res); - - if (jv == null || !jv.isEarlyAccess()) { - if (OS.os() == OS.WINDOWS) - res.add("-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_minecraft.exe.heapdump"); - if (jv != null && jv.getParsedVersion() >= JdkVersion.JAVA_17) - res.add("-XX:+UseG1GC"); - else - res.add("-Xincgc"); - res.add("-XX:-UseAdaptiveSizePolicy"); - res.add("-XX:-OmitStackTraceInFastThrow"); - - res.add("-Xmn128m"); - } - if (!StrUtils.isBlank(options.getPermSize())) - if (jv == null || jv.getParsedVersion() < JdkVersion.JAVA_18) { - res.add("-XX:PermSize=" + options.getPermSize() + "m"); - if (jv != null && jv.getParsedVersion() < JdkVersion.JAVA_18) - MessageBox.showLocalized("advice.java8"); - } else if (jv.getParsedVersion() >= JdkVersion.JAVA_18) - res.add("-XX:MetaspaceSize=" + options.getPermSize() + "m"); - } - - if (jv != null) { - HMCLog.log("Java Version: " + jv.getVersion()); - HMCLog.log("Java Platform: " + jv.getPlatform().getBit()); - } - HMCLog.log("System Platform: " + Platform.getPlatform().getBit()); - - if (jv != null && jv.getPlatform() == Platform.BIT_32 && Platform.getPlatform() == Platform.BIT_64) - MessageBox.showLocalized("advice.os64butjdk32"); - - if (!StrUtils.isBlank(options.getMaxMemory())) { - int mem = MathUtils.parseMemory(options.getMaxMemory(), 2147483647); - if (jv != null && jv.getPlatform() == Platform.BIT_32 && mem > 1024) - MessageBox.show(C.i18n("launch.too_big_memory_alloc_64bit")); - else { - long a = OS.getTotalPhysicalMemory() / 1024 / 1024; - HMCLog.log("System Physical Memory: " + a); - if (a > 0 && a < mem) - MessageBox.show(C.i18n("launch.too_big_memory_alloc_free_space_too_low", a)); - } - String a = "-Xmx" + options.getMaxMemory(); - if (MathUtils.canParseInt(options.getMaxMemory())) - a += "m"; - res.add(a); - } - - res.add("-Djava.library.path=" + service.version().getDecompressNativesToLocation(version).getAbsolutePath()); - res.add("-Dfml.ignoreInvalidMinecraftCertificates=true"); - res.add("-Dfml.ignorePatchDiscrepancies=true"); - - if (OS.os() != OS.WINDOWS) - res.add("-Duser.home=" + gameDir.getParent()); - } - - @Override - public List makeLaunchingCommand() throws GameException { - HMCLog.log("*** Make shell command ***"); - - ArrayList res = new ArrayList<>(); - - makeHeadCommand(res); - makeSelf(res); - - HMCLog.log("On making launcher args."); - - if (StrUtils.isNotBlank(options.getHeight()) && StrUtils.isNotBlank(options.getWidth())) { - res.add("--height"); - res.add(options.getHeight()); - res.add("--width"); - res.add(options.getWidth()); - } - - String serverIp = options.getServerIp(); - if (StrUtils.isNotBlank(serverIp)) { - String[] args = serverIp.split(":"); - res.add("--server"); - res.add(args[0]); - res.add("--port"); - res.add(args.length > 1 ? args[1] : "25565"); - } - - if (options.isFullscreen()) - res.add("--fullscreen"); - - if (StrUtils.isNotBlank(options.getProxyHost()) && StrUtils.isNotBlank(options.getProxyPort()) && MathUtils.canParseInt(options.getProxyPort())) { - res.add("--proxyHost"); - res.add(options.getProxyHost()); - res.add("--proxyPort"); - res.add(options.getProxyPort()); - if (StrUtils.isNotBlank(options.getProxyUser()) && StrUtils.isNotBlank(options.getProxyPass())) { - res.add("--proxyUser"); - res.add(options.getProxyUser()); - res.add("--proxyPass"); - res.add(options.getProxyPass()); - } - } - - if (StrUtils.isNotBlank(options.getMinecraftArgs())) - res.addAll(Arrays.asList(options.getMinecraftArgs().split(" "))); - - return res; - } - - /** - * You must do these things: - *
      - *
    • minecraft class path
    • - *
    • main class
    • - *
    • minecraft arguments
    • - *
    - * - * @param list the command list you shoud edit. - */ - protected abstract void makeSelf(List list) throws GameException; - - protected void appendJVMArgs(List list) { - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/launch/DefaultGameLauncher.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/launch/DefaultGameLauncher.java deleted file mode 100644 index 7bb97abc8..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/launch/DefaultGameLauncher.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.launch; - -import org.jackhuang.hmcl.api.game.LaunchOptions; -import java.io.IOException; -import java.util.HashSet; -import java.util.List; -import org.jackhuang.hmcl.core.download.DownloadLibraryJob; -import org.jackhuang.hmcl.api.auth.LoginInfo; -import org.jackhuang.hmcl.core.service.IMinecraftService; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.util.ui.MessageBox; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.util.sys.CompressingUtils; -import org.jackhuang.hmcl.util.task.ParallelTask; -import org.jackhuang.hmcl.util.task.TaskWindow; -import org.jackhuang.hmcl.api.auth.IAuthenticator; -import org.jackhuang.hmcl.api.game.DecompressLibraryJob; - -public class DefaultGameLauncher extends GameLauncher { - - public DefaultGameLauncher(LaunchOptions options, IMinecraftService service, LoginInfo info, IAuthenticator lg) { - super(options, service, info, lg); - } - - @Override - public boolean downloadLibraries(List jobs) { - final TaskWindow.TaskWindowFactory dw = TaskWindow.factory(); - ParallelTask parallelTask = new ParallelTask(); - HashSet names = new HashSet<>(); - for (DownloadLibraryJob s : jobs) { - if (names.contains(s.lib.getName())) - continue; - names.add(s.lib.getName()); - parallelTask.addTask(new LibraryDownloadTask(s, service.getDownloadType())); - } - dw.append(parallelTask); - boolean flag = true; - if (jobs.size() > 0) - flag = dw.execute(); - if (!flag && MessageBox.show(C.i18n("launch.not_finished_downloading_libraries"), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION) - flag = true; - return flag; - } - - @Override - public boolean decompressLibraries(DecompressLibraryJob job) { - if (job == null) - return false; - for (int i = 0; i < job.decompressFiles.length; i++) - try { - CompressingUtils.unzip(job.decompressFiles[i], job.getDecompressTo(), job.extractRules[i]::allow, false); - } catch (IOException ex) { - HMCLog.err("Unable to decompress library: " + job.decompressFiles[i] + " to " + job.getDecompressTo(), ex); - } - return true; - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/launch/GameLauncher.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/launch/GameLauncher.java deleted file mode 100644 index bf8f0c3bd..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/launch/GameLauncher.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.launch; - -import org.jackhuang.hmcl.api.game.LaunchOptions; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.util.List; -import org.jackhuang.hmcl.api.HMCLApi; -import org.jackhuang.hmcl.api.game.DecompressLibraryJob; -import org.jackhuang.hmcl.api.event.launch.LaunchEvent; -import org.jackhuang.hmcl.api.event.launch.LaunchSucceededEvent; -import org.jackhuang.hmcl.api.event.launch.LaunchingState; -import org.jackhuang.hmcl.api.event.launch.LaunchingStateChangedEvent; -import org.jackhuang.hmcl.api.event.launch.ProcessingLoginResultEvent; -import org.jackhuang.hmcl.core.GameException; -import org.jackhuang.hmcl.core.RuntimeGameException; -import org.jackhuang.hmcl.api.auth.AuthenticationException; -import org.jackhuang.hmcl.api.auth.LoginInfo; -import org.jackhuang.hmcl.api.auth.UserProfileProvider; -import org.jackhuang.hmcl.core.service.IMinecraftLoader; -import org.jackhuang.hmcl.core.service.IMinecraftService; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.util.StrUtils; -import org.jackhuang.hmcl.util.code.Charsets; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.api.Wrapper; -import org.jackhuang.hmcl.util.sys.FileUtils; -import org.jackhuang.hmcl.util.sys.JavaProcess; -import org.jackhuang.hmcl.util.sys.OS; -import org.jackhuang.hmcl.api.auth.IAuthenticator; -import org.jackhuang.hmcl.core.download.DownloadLibraryJob; - -public abstract class GameLauncher { - - LaunchOptions options; - IMinecraftService service; - LoginInfo info; - UserProfileProvider result; - IAuthenticator login; - - public GameLauncher(LaunchOptions options, IMinecraftService version, LoginInfo info, IAuthenticator lg) { - this.options = options; - this.service = version; - this.info = info; - this.login = lg; - } - - public LaunchOptions getOptions() { - return options; - } - - public IMinecraftService getService() { - return service; - } - - public LoginInfo getInfo() { - return info; - } - - public UserProfileProvider getLoginResult() { - return result; - } - - private Object tag; - - public Object getTag() { - return tag; - } - - public void setTag(Object tag) { - this.tag = tag; - } - - /** - * Generates the launch command. - * - * @throws AuthenticationException having trouble logging in. - * @throws GameException having trouble completing the game or making lanch command. - * @throws RuntimeGameException will be thrown when someone processing login result. - * @see LaunchingStateChangedEvent - * @see DecompressLibrariesEvent - * @see LaunchSucceededEvent - * @see DownloadLibrariesEvent - * @see ProcessingLoginResultEvent - */ - public void makeLaunchCommand() throws AuthenticationException, GameException, RuntimeGameException { - HMCLog.log("Building process"); - HMCLog.log("Logging in..."); - HMCLApi.EVENT_BUS.fireChannel(new LaunchingStateChangedEvent(this, LaunchingState.LoggingIn)); - IMinecraftLoader loader; - if (info != null) - result = login.login(info); - else - result = login.loginBySettings(); - if (result == null) - throw new AuthenticationException("Result can not be null."); - Wrapper loginInfo = new Wrapper<>(result); - HMCLApi.EVENT_BUS.fireChannel(new ProcessingLoginResultEvent(this, loginInfo)); - result = loginInfo.getValue(); - - HMCLApi.EVENT_BUS.fireChannel(new LaunchingStateChangedEvent(this, LaunchingState.GeneratingLaunchingCodes)); - loader = service.launch(options, result); - - File file = service.version().getDecompressNativesToLocation(loader.getMinecraftVersion()); - if (file != null) - FileUtils.cleanDirectoryQuietly(file); - - if (!options.isNotCheckGame()) { - HMCLog.log("Detecting libraries..."); - HMCLApi.EVENT_BUS.fireChannel(new LaunchingStateChangedEvent(this, LaunchingState.DownloadingLibraries)); - if (!downloadLibraries(service.download().getDownloadLibraries(loader.getMinecraftVersion()))) - throw new GameException("Failed to download libraries"); - } - - HMCLog.log("Unpacking natives..."); - HMCLApi.EVENT_BUS.fireChannel(new LaunchingStateChangedEvent(this, LaunchingState.DecompressingNatives)); - DecompressLibraryJob job = service.version().getDecompressLibraries(loader.getMinecraftVersion()); - if (!decompressLibraries(job)) - throw new GameException("Failed to decompress natives"); - - HMCLApi.EVENT_BUS.fireChannel(new LaunchSucceededEvent(this, loader.makeLaunchingCommand())); - } - - public abstract boolean downloadLibraries(List jobs); - - public abstract boolean decompressLibraries(DecompressLibraryJob job); - - /** - * Launch the game "as soon as possible". - * - * @param str launch command - * @throws IOException failed creating process - */ - public void launch(List str) throws IOException { - if (!service.version().onLaunch(options.getLaunchVersion())) - return; - if (StrUtils.isNotBlank(options.getPrecalledCommand())) { - Process p = Runtime.getRuntime().exec(options.getPrecalledCommand()); - try { - if (p.isAlive()) - p.waitFor(); - } catch (InterruptedException ex) { - HMCLog.warn("Failed to invoke precalled command", ex); - } - } - HMCLog.log("Starting process"); - String s = StrUtils.makeCommand(str); - s = s.replace(result.getAccessToken(), ""); - s = s.replace(result.getSession(), ""); - s = s.replace(result.getUserId(), ""); - HMCLog.log(s); - ProcessBuilder builder = new ProcessBuilder(str); - if (options.getLaunchVersion() == null || service.baseDirectory() == null) - throw new Error("Fucking bug!"); - builder.directory(service.version().getRunDirectory(options.getLaunchVersion())) - .environment().put("APPDATA", service.baseDirectory().getAbsolutePath()); - JavaProcess jp = new JavaProcess(str, builder.start()); - HMCLog.log("Have started the process"); - HMCLApi.EVENT_BUS.fireChannel(new LaunchEvent(this, jp)); - } - - /** - * According to the name... - * - * @param launcherName the name of launch bat/sh - * @param str launch command - * - * @return launcher location - * - * @throws java.io.IOException write contents failed. - */ - public File makeLauncher(String launcherName, List str) throws IOException { - HMCLog.log("Making shell launcher..."); - service.version().onLaunch(options.getLaunchVersion()); - boolean isWin = OS.os() == OS.WINDOWS; - File f = new File(launcherName + (isWin ? ".bat" : ".sh")); - if (!f.exists() && !f.createNewFile()) - throw new IOException("Script file " + f.getAbsolutePath() + " does not exist but cannot be created."); - BufferedWriter writer; - try (FileOutputStream fos = FileUtils.openOutputStream(f)) { - writer = new BufferedWriter(new OutputStreamWriter(fos, Charsets.toCharset())); - if (isWin) { - writer.write("@echo off"); - writer.newLine(); - writer.write("set appdata=" + service.baseDirectory().getAbsolutePath()); - writer.newLine(); - writer.write("cd /D %appdata%"); - writer.newLine(); - } - if (StrUtils.isNotBlank(options.getPrecalledCommand())) { - writer.write(options.getPrecalledCommand()); - writer.newLine(); - } - writer.write(StrUtils.makeCommand(str)); - writer.close(); - } - if (!f.setExecutable(true)) - throw new IOException(C.i18n("launch.failed_sh_permission")); - - HMCLog.log("Command: " + StrUtils.parseParams("", str, " ")); - return f; - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/launch/IAssetProvider.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/launch/IAssetProvider.java deleted file mode 100644 index 8b5e54476..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/launch/IAssetProvider.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.launch; - -import org.jackhuang.hmcl.core.GameException; -import org.jackhuang.hmcl.core.version.MinecraftVersion; - -/** - * - * @author huang - */ -public interface IAssetProvider { - - String provide(MinecraftVersion mv, Boolean allowChecking) throws GameException; -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/launch/LibraryDownloadTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/launch/LibraryDownloadTask.java deleted file mode 100644 index 690bb0301..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/launch/LibraryDownloadTask.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.launch; - -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.core.download.DownloadLibraryJob; -import org.jackhuang.hmcl.core.download.DownloadType; -import org.jackhuang.hmcl.util.net.FileDownloadTask; - -/** - * - * @author huangyuhui - */ -public class LibraryDownloadTask extends FileDownloadTask { - - DownloadLibraryJob job; - - public LibraryDownloadTask(DownloadLibraryJob job, DownloadType downloadType) { - super(job.parse(downloadType).url, job.path); - this.job = job; - } - - @Override - public String getInfo() { - return C.i18n("download") + ": " + job.lib.getName(); - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/launch/MinecraftLoader.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/launch/MinecraftLoader.java deleted file mode 100644 index 8a6af8119..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/launch/MinecraftLoader.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.launch; - -import org.jackhuang.hmcl.api.game.LaunchOptions; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; -import org.jackhuang.hmcl.util.StrUtils; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.util.sys.OS; -import org.jackhuang.hmcl.core.GameException; -import org.jackhuang.hmcl.api.auth.UserProfileProvider; -import org.jackhuang.hmcl.core.version.MinecraftLibrary; -import org.jackhuang.hmcl.core.service.IMinecraftService; -import org.jackhuang.hmcl.core.version.LoggingInfo; - -/** - * - * @author huangyuhui - */ -public class MinecraftLoader extends AbstractMinecraftLoader { - - public MinecraftLoader(LaunchOptions p, IMinecraftService provider, UserProfileProvider lr) throws GameException { - super(p, provider, p.getLaunchVersion(), lr); - } - - @Override - protected void makeSelf(List res) throws GameException { - StringBuilder library = new StringBuilder(""); - ArrayList opt = new ArrayList<>(); - for (MinecraftLibrary l : version.libraries) - if (l.allow() && !l.isNative()) { - if (l.getName().toLowerCase(Locale.US).contains("optifine")) { - opt.add(l); - continue; - } - File f = service.version().getLibraryFile(version, l); - if (f == null) - continue; - library.append(f.getAbsolutePath()).append(File.pathSeparator); - } - for (MinecraftLibrary l : opt) { - File f = service.version().getLibraryFile(version, l); - if (f == null) - continue; - library.append(f.getAbsolutePath()).append(File.pathSeparator); - } - File f = version.getJar(service.baseDirectory()); - if (!f.exists()) - throw new GameException("Minecraft jar does not exist"); - library.append(f.getAbsolutePath()).append(File.pathSeparator); - res.add("-cp"); - res.add(library.toString().substring(0, library.length() - File.pathSeparator.length())); - res.add(version.mainClass); - - if (version.minecraftArguments == null) - throw new GameException(new NullPointerException("Minecraft Arguments can not be null.")); - String[] splitted = StrUtils.tokenize(version.minecraftArguments); - - String game_assets = assetProvider.provide(version, !options.isNotCheckGame()); - - for (String t : splitted) { - t = t.replace("${auth_player_name}", lr.getUserName()); - t = t.replace("${auth_session}", lr.getSession()); - t = t.replace("${auth_uuid}", lr.getUserId()); - t = t.replace("${version_name}", options.getVersionName()); - t = t.replace("${profile_name}", options.getName()); - t = t.replace("${version_type}", options.getType()); - t = t.replace("${game_directory}", service.version().getRunDirectory(version.id).getAbsolutePath()); - t = t.replace("${game_assets}", game_assets); - t = t.replace("${assets_root}", service.asset().getAssets(version.getAssetsIndex().getId()).getAbsolutePath()); - t = t.replace("${auth_access_token}", lr.getAccessToken()); - t = t.replace("${user_type}", lr.getUserType()); - t = t.replace("${assets_index_name}", version.getAssetsIndex().getId()); - t = t.replace("${user_properties}", lr.getUserProperties()); - res.add(t); - } - - if (res.indexOf("--gameDir") != -1 && res.indexOf("--workDir") != -1) { - res.add("--workDir"); - res.add(gameDir.getAbsolutePath()); - } - } - - @Override - protected void appendJVMArgs(List list) { - super.appendJVMArgs(list); - - try { - if (OS.os() == OS.OSX) { - list.add("-Xdock:icon=" + service.asset().getAssetObject(version.getAssetsIndex().getId(), "icons/minecraft.icns").getAbsolutePath()); - list.add("-Xdock:name=Minecraft"); - } - } catch (IOException e) { - HMCLog.err("Failed to append jvm arguments when searching for asset objects.", e); - } - - list.add("-Dminecraft.client.jar=" + version.getJar(service.baseDirectory()).getAbsolutePath()); - - if (version.logging != null && version.logging.containsKey("client")) { - LoggingInfo logging = version.logging.get("client"); - File file = service.asset().getLoggingObject(version.getAssetsIndex().getId(), logging); - if (file.exists()) - list.add(logging.argument.replace("${path}", file.getAbsolutePath())); - } - } - - private final IAssetProvider DEFAULT_ASSET_PROVIDER = (t, allow) -> { - return new File(service.baseDirectory(), "assets").getAbsolutePath(); - }; - - private IAssetProvider assetProvider = DEFAULT_ASSET_PROVIDER; - - public void setAssetProvider(IAssetProvider assetProvider) { - if (assetProvider == null) - this.assetProvider = DEFAULT_ASSET_PROVIDER; - else - this.assetProvider = assetProvider; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/mod/MinecraftModService.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/mod/MinecraftModService.java deleted file mode 100644 index 69d12ef09..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/mod/MinecraftModService.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.mod; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.core.service.IMinecraftModService; -import org.jackhuang.hmcl.core.service.IMinecraftService; -import org.jackhuang.hmcl.util.sys.FileUtils; - -/** - * - * @author huangyuhui - */ -public class MinecraftModService extends IMinecraftModService { - - Map> modCache = Collections.synchronizedMap(new HashMap<>()); - - public MinecraftModService(IMinecraftService service) { - super(service); - } - - @Override - public List getMods(String id) { - if (modCache.containsKey(id)) - return modCache.get(id); - else - return recacheMods(id); - } - - @Override - public List recacheMods(String id) { - File modsFolder = service.version().getRunDirectory(id, "mods"); - ArrayList mods = new ArrayList<>(); - File[] fs = modsFolder.listFiles(); - if (fs != null) - for (File f : fs) - if (ModInfo.isFileMod(f)) - mods.add(ModInfo.readModInfo(f)); - else if (f.isDirectory()) { - File[] ss = f.listFiles(); - if (ss != null) - for (File ff : ss) - if (ModInfo.isFileMod(ff)) - mods.add(ModInfo.readModInfo(ff)); - } - Collections.sort(mods); - modCache.put(id, mods); - return mods; - } - - @Override - public boolean addMod(String id, File f) { - try { - if (!ModInfo.isFileMod(f)) - return false; - if (!modCache.containsKey(id)) - recacheMods(id); - File modsFolder = service.version().getRunDirectory(id, "mods"); - if (!FileUtils.makeDirectory(modsFolder)) - HMCLog.warn("Failed to make directories: " + modsFolder); - File newf = new File(modsFolder, f.getName()); - FileUtils.copyFile(f, newf); - ModInfo i = ModInfo.readModInfo(f); - modCache.get(id).add(i); - return true; - } catch (IOException ex) { - HMCLog.warn("Failed to copy mod", ex); - return false; - } - } - - @Override - public boolean removeMod(String id, Object[] rows) { - if (rows.length == 0) - return true; - boolean flag = true; - for (Object r : rows) - if (r instanceof ModInfo) { - if (!((ModInfo) r).location.delete()) { - HMCLog.warn("Failed to delete mod" + r); - flag = false; - } - } else if (r instanceof Number) - if (!getMods(id).get(((Number) r).intValue()).location.delete()) { - HMCLog.warn("Failed to delete mod " + r + ", maybe not a file?"); - flag = false; - } - recacheMods(id); - return flag; - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/mod/ModAdviser.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/mod/ModAdviser.java deleted file mode 100644 index 74136fb81..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/mod/ModAdviser.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.mod; - -/** - * - * @author huang - */ -public interface ModAdviser { - - ModSuggestion advise(String fileName, boolean isDirectory); - - public static enum ModSuggestion { - SUGGESTED, - NORMAL, - HIDDEN - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/mod/ModInfo.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/mod/ModInfo.java deleted file mode 100644 index f0428c002..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/mod/ModInfo.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.mod; - -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.google.gson.JsonSyntaxException; -import com.google.gson.annotations.SerializedName; -import com.google.gson.reflect.TypeToken; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.List; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.util.StrUtils; -import org.jackhuang.hmcl.util.sys.FileUtils; - -/** - * - * @author huangyuhui - */ -public class ModInfo implements Comparable { - - @SerializedName("location") - public File location; - @SerializedName("modid") - public String modid; - @SerializedName("name") - public String name; - @SerializedName("description") - public String description; - @SerializedName("author") - public String author; - @SerializedName("version") - public String version; - @SerializedName("mcversion") - public String mcversion; - @SerializedName("url") - public String url; - @SerializedName("updateUrl") - public String updateUrl; - @SerializedName("credits") - public String credits; - @SerializedName("authorList") - public String[] authorList; - @SerializedName("authors") - public String[] authors; - - public boolean isActive() { - return !location.getName().endsWith(".disabled"); - } - - public void reverseModState() { - File f = location, newf; - if (f.getName().endsWith(".disabled")) - newf = new File(f.getParentFile(), f.getName().substring(0, f.getName().length() - ".disabled".length())); - else - newf = new File(f.getParentFile(), f.getName() + ".disabled"); - if (f.renameTo(newf)) - location = newf; - } - - @Override - public int compareTo(ModInfo o) { - return getFileName().compareToIgnoreCase(o.getFileName()); - } - - public String getName() { - return name == null ? FileUtils.removeExtension(location.getName()) : name; - } - - public String getAuthor() { - if (authorList != null && authorList.length > 0) - return StrUtils.parseParams("", authorList, ", "); - else if (authors != null && authors.length > 0) - return StrUtils.parseParams("", authors, ", "); - else if (StrUtils.isNotBlank(author)) - return author; - else - return "Unknown"; - } - - @Override - public boolean equals(Object obj) { - return obj != null && obj instanceof ModInfo && (((ModInfo) obj).location == location || ((ModInfo) obj).location.equals(location)); - } - - @Override - public int hashCode() { - return location.hashCode(); - } - - @Override - public String toString() { - return getFileName(); - } - - public String getFileName() { - String n = location.getName(); - return FileUtils.removeExtension(isActive() ? n : n.substring(0, n.length() - ".disabled".length())); - } - - public static boolean isFileMod(File file) { - if (file == null) - return false; - String name = file.getName(); - boolean disabled = name.endsWith(".disabled"); - if (disabled) - name = name.substring(0, name.length() - ".disabled".length()); - return name.endsWith(".zip") || name.endsWith(".jar") || name.endsWith("litemod"); - } - - private static ModInfo getForgeModInfo(File f, ZipFile jar, ZipEntry entry) throws IOException, JsonSyntaxException { - ModInfo i = new ModInfo(); - i.location = f; - - InputStreamReader streamReader = new InputStreamReader(jar.getInputStream(entry), "UTF-8"); - - JsonParser parser = new JsonParser(); - JsonElement element = parser.parse(streamReader); - List m = null; - if (element.isJsonArray()) - m = C.GSON.fromJson(element, new TypeToken>() { - }.getType()); - else if (element.isJsonObject()) { - JsonObject modInfo = element.getAsJsonObject(); - if (modInfo.has("modList") && modInfo.get("modList").isJsonArray()) - m = C.GSON.fromJson(modInfo.get("modList"), new TypeToken>() { - }.getType()); - } - - if (m != null && m.size() > 0) { - i = m.get(0); - i.location = f; - } - - return i; - } - - private static ModInfo getLiteLoaderModInfo(File f, ZipFile jar, ZipEntry entry) throws IOException { - ModInfo m = C.GSON.fromJson(new InputStreamReader(jar.getInputStream(entry), "UTF-8"), ModInfo.class); - if (m == null) - m = new ModInfo(); - m.location = f; - return m; - } - - public static ModInfo readModInfo(File f) { - ModInfo i = new ModInfo(); - i.location = f; - try { - try (ZipFile jar = new ZipFile(f)) { - ZipEntry entry = jar.getEntry("mcmod.info"); - if (entry != null) - return getForgeModInfo(f, jar, entry); - entry = jar.getEntry("litemod.json"); - if (entry != null) - return getLiteLoaderModInfo(f, jar, entry); - return i; - } - } catch (IOException ex) { - HMCLog.warn("File " + f + " is not a jar.", ex); - } catch (JsonSyntaxException ignore) { - } - return i; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/mod/ModpackManager.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/mod/ModpackManager.java deleted file mode 100644 index e1eb95b0a..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/mod/ModpackManager.java +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.mod; - -import java.awt.Dimension; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStreamReader; -import java.nio.file.FileSystemException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.zip.ZipFile; -import javax.swing.JFrame; -import javax.swing.JOptionPane; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.core.GameException; -import org.jackhuang.hmcl.core.service.IMinecraftProvider; -import org.jackhuang.hmcl.core.service.IMinecraftService; -import org.jackhuang.hmcl.core.version.MinecraftVersion; -import org.jackhuang.hmcl.api.func.CallbackIO; -import org.jackhuang.hmcl.util.sys.CompressingUtils; -import org.jackhuang.hmcl.util.sys.FileUtils; -import org.jackhuang.hmcl.util.sys.ZipEngine; -import org.jackhuang.hmcl.util.task.Task; -import org.jackhuang.hmcl.util.net.WebPage; -import org.jackhuang.hmcl.util.MinecraftVersionRequest; -import org.jackhuang.hmcl.util.sys.IOUtils; -import org.jackhuang.hmcl.util.task.NoShownTaskException; - -/** - * A mod pack(*.zip) includes these things: - *
      - *
    • sth created by the game automatically, including "mods", "scripts", - * "config", etc.. - *
    • pack.json, the same as Minecraft version configuration file: - * "gameDir/versions/{MCVER}/{MCVER}.json", will be renamed to that one. - *
    • all things should be included in "minecraft" folder under the root - * folder. - *
    - * - * This class can manage mod packs, for example, importing and exporting, the - * format of game is the offical one. - * Not compatible with MultiMC(no instance.cfg processor) & FTB(not leaving - * mcversion(jar) in pack.json). - * - * @author huangyuhui - */ -public final class ModpackManager { - - /** - * Install the compressed modpack. - * - * @param input modpack.zip - * @param service MinecraftService, whose version service only supports - * MinecraftVersionManager. - * @param id new version id, if null, will use suggested name from - * modpack - * - * @return The installing Task, may take long time, please consider - * TaskWindow. - */ - public static Task install(JFrame parFrame, final File input, final IMinecraftService service, final String idFUCK) { - return new Task() { - Collection c = new ArrayList<>(); - - @Override - public void executeTask(boolean areDependTasksSucceeded) throws Exception { - String id = idFUCK; - String description = C.i18n("modpack.task.install.will"); - - // Read modpack name and description from `modpack.json` - try (ZipFile zip = new ZipFile(input)) { - HashMap map = C.GSON.fromJson(new InputStreamReader(zip.getInputStream(zip.getEntry("modpack.json")), "UTF-8"), HashMap.class); - if (map != null) { - if (id == null) - if (map.containsKey("name") && map.get("name") instanceof String) - id = map.get("name"); - if (id != null) - description += id; - if (map.containsKey("description") && map.get("description") instanceof String) - description += "\n" + map.get("description"); - } - if (id == null) - throw new IllegalStateException("Illegal modpack id!"); - } - - // Show a window to let the user know that what and how the modpack is. - Object msgs[] = new Object[2]; - msgs[0] = C.i18n("modpack.task.install"); - msgs[1] = new WebPage(description); - ((WebPage) msgs[1]).setPreferredSize(new Dimension(800, 350)); - int result = JOptionPane.showOptionDialog(parFrame, msgs, (String) msgs[0], JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null); - if (result == JOptionPane.NO_OPTION) - throw new NoShownTaskException("Operation was canceled by user."); - - File versions = new File(service.baseDirectory(), "versions"); - - // `minecraft` folder is the existent root folder of the modpack - // Then we will decompress the modpack and there would be a folder named `minecraft` - // So if `minecraft` folder does exist, backup it and then restore it. - File oldFile = new File(versions, "minecraft"), newFile = null; - if (oldFile.exists()) { - newFile = new File(versions, "minecraft-" + System.currentTimeMillis()); - if (newFile.isDirectory()) - FileUtils.deleteDirectory(newFile); - else if (newFile.isFile()) - if (!newFile.delete()) - HMCLog.warn("Failed to delete file " + newFile); - if (!oldFile.renameTo(newFile)) - HMCLog.warn("Failed to rename " + oldFile + " to " + newFile); - } - - // If the user install the modpack into an existent version, maybe it wants to update the modpack - // So backup the game, copy the saved games. - File preVersion = new File(versions, id), preVersionRenamed = null; - if (preVersion.exists()) { - HMCLog.log("Backing up the game"); - String preId = id + "-" + System.currentTimeMillis(); - if (!preVersion.renameTo(preVersionRenamed = new File(versions, preId))) - HMCLog.warn("Failed to rename pre-version folder " + preVersion + " to a temp folder " + preVersionRenamed); - if (!new File(preVersionRenamed, id + ".json").renameTo(new File(preVersionRenamed, preId + ".json"))) - HMCLog.warn("Failed to rename pre json to new json"); - - if (!new File(preVersionRenamed, id + ".jar").renameTo(new File(preVersionRenamed, preId + ".jar"))) - HMCLog.warn("Failed to rename pre jar to new jar"); - } - - try { - final AtomicInteger b = new AtomicInteger(0); - HMCLog.log("Decompressing modpack"); - CompressingUtils.unzip(input, versions, t -> { - if (t.equals("minecraft/pack.json")) - b.incrementAndGet(); - return true; - }, true); - - // No pack.json here, illegal modpack. - if (b.get() < 1) - throw new FileNotFoundException(C.i18n("modpack.incorrect_format.no_json")); - File nowFile = new File(versions, id); - if (oldFile.exists() && !oldFile.renameTo(nowFile)) - HMCLog.warn("Failed to rename incorrect json " + oldFile + " to " + nowFile); - - File json = new File(nowFile, "pack.json"); - MinecraftVersion mv = C.GSON.fromJson(FileUtils.read(json), MinecraftVersion.class); - if (mv.jar == null) - throw new FileNotFoundException(C.i18n("modpack.incorrect_format.no_jar")); - - c.add(service.download().downloadMinecraftJar(mv, new File(nowFile, id + ".jar"))); - mv.jar = null; - FileUtils.write(json, C.GSON.toJson(mv)); - if (!json.renameTo(new File(nowFile, id + ".json"))) - HMCLog.warn("Failed to rename pack.json to new id"); - - // Restore the saved game from the old version. - if (preVersionRenamed != null) { - HMCLog.log("Restoring saves"); - File presaves = new File(preVersionRenamed, "saves"); - File saves = new File(nowFile, "saves"); - if (presaves.exists()) { - FileUtils.deleteDirectory(saves); - FileUtils.copyDirectory(presaves, saves); - } - } - } finally { - FileUtils.deleteDirectoryQuietly(oldFile); - if (newFile != null && !newFile.renameTo(oldFile)) - HMCLog.warn("Failed to restore version minecraft"); - } - } - - @Override - public String getInfo() { - return C.i18n("modpack.task.install"); - } - - @Override - public Collection getAfterTasks() { - return c; - } - }; - - } - - public static final List MODPACK_BLACK_LIST = Arrays.asList(new String[] { "usernamecache.json", "asm", "logs", "backups", "versions", "assets", "usercache.json", "libraries", "crash-reports", "launcher_profiles.json", "NVIDIA", "AMD", "TCNodeTracker", "screenshots", "natives", "native", "$native", "pack.json", "launcher.jar", "minetweaker.log", "launcher.pack.lzma", "hmclmc.log" }); - public static final List MODPACK_SUGGESTED_BLACK_LIST = Arrays.asList(new String[] { "fonts", "saves", "servers.dat", "options.txt", "optionsof.txt", "journeymap", "optionsshaders.txt", "mods/VoxelMods" }); - - public static ModAdviser MODPACK_PREDICATE = (String fileName, boolean isDirectory) -> { - if (match(MODPACK_BLACK_LIST, fileName, isDirectory)) - return ModAdviser.ModSuggestion.HIDDEN; - if (match(MODPACK_SUGGESTED_BLACK_LIST, fileName, isDirectory)) - return ModAdviser.ModSuggestion.NORMAL; - return ModAdviser.ModSuggestion.SUGGESTED; - }; - - private static boolean match(final List l, String fileName, boolean isDirectory) { - for (String s : l) - if (isDirectory) { - if (fileName.startsWith(s + "/")) - return true; - } else if (fileName.equals(s)) - return true; - return false; - } - - /** - * Export the game to a mod pack file. - * - * @param output mod pack file. - * @param baseFolder if the game dir type is ROOT_FOLDER, use ".minecraft", - * or use ".minecraft/versions/{MCVER}/" - * @param version to locate version.json - * - * @throws IOException if create tmp directory failed - */ - public static void export(File output, IMinecraftProvider provider, String version, List blacklist, Map modpackPreferences, CallbackIO callback) throws IOException, GameException { - final ArrayList b = new ArrayList<>(MODPACK_BLACK_LIST); - if (blacklist != null) - b.addAll(blacklist); - b.add(version + ".jar"); - b.add(version + ".json"); - HMCLog.log("Compressing game files without some files in blacklist, including files or directories: usernamecache.json, asm, logs, backups, versions, assets, usercache.json, libraries, crash-reports, launcher_profiles.json, NVIDIA, TCNodeTracker"); - ZipEngine zip = null; - try { - zip = new ZipEngine(output); - zip.putDirectory(provider.getRunDirectory(version), (String x, Boolean y) -> { - for (String s : b) - if (y) { - if (x.startsWith(s + "/")) - return null; - } else if (x.equals(s)) - return null; - return "minecraft/" + x; - }); - - MinecraftVersion mv = provider.getVersionById(version).resolve(provider); - MinecraftVersionRequest r = MinecraftVersionRequest.minecraftVersion(provider.getMinecraftJar(version)); - if (r.type != MinecraftVersionRequest.OK) - throw new FileSystemException(C.i18n("modpack.cannot_read_version") + ": " + MinecraftVersionRequest.getResponse(r)); - mv.jar = r.version; - mv.runDir = "version"; - zip.putTextFile(C.GSON.toJson(mv), "minecraft/pack.json"); - zip.putTextFile(C.GSON.toJson(modpackPreferences), "modpack.json"); - if (callback != null) - callback.call(zip); - } finally { - IOUtils.closeQuietly(zip); - } - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IMinecraftAssetService.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IMinecraftAssetService.java deleted file mode 100644 index 3c1dcc4d5..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IMinecraftAssetService.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.service; - -import java.io.File; -import java.io.IOException; -import org.jackhuang.hmcl.core.GameException; -import org.jackhuang.hmcl.core.asset.AssetsObject; -import org.jackhuang.hmcl.core.version.AssetIndexDownloadInfo; -import org.jackhuang.hmcl.core.version.LoggingInfo; -import org.jackhuang.hmcl.util.task.Task; - -/** - * - * @author huangyuhui - */ -public abstract class IMinecraftAssetService extends IMinecraftBasicService { - - public IMinecraftAssetService(IMinecraftService service) { - super(service); - } - - public abstract Task downloadAssets(String mcVersion) throws GameException; - - public abstract File getAssets(String assetId); - - public abstract File getIndexFile(String assetId); - - /** - * Redownload the Asset index json of the given version. - * - * @param mcVersion the given version name - * - * @return Is the action successful? - */ - public abstract boolean refreshAssetsIndex(String mcVersion) throws GameException; - - public abstract boolean downloadMinecraftAssetsIndexAsync(AssetIndexDownloadInfo assetId); - - public abstract Task downloadMinecraftAssetsIndex(AssetIndexDownloadInfo assetId); - - public abstract File getAssetObject(String assetVersion, String name) throws IOException; - - public abstract File getAssetObject(String assetId, AssetsObject assetsObject); - - public abstract File getLoggingObject(String assetId, LoggingInfo id); -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IMinecraftBasicService.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IMinecraftBasicService.java deleted file mode 100644 index 2ec510b06..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IMinecraftBasicService.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.service; - -/** - * - * @author huangyuhui - */ -public abstract class IMinecraftBasicService { - - public IMinecraftService service; - - public IMinecraftBasicService(IMinecraftService service) { - this.service = service; - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IMinecraftDownloadService.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IMinecraftDownloadService.java deleted file mode 100644 index bffb99d22..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IMinecraftDownloadService.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.service; - -import java.io.File; -import java.util.List; -import org.jackhuang.hmcl.core.GameException; -import org.jackhuang.hmcl.core.download.DownloadLibraryJob; -import org.jackhuang.hmcl.core.version.MinecraftVersion; -import org.jackhuang.hmcl.util.task.Task; - -/** - * - * @author huangyuhui - */ -public abstract class IMinecraftDownloadService extends IMinecraftBasicService { - - public IMinecraftDownloadService(IMinecraftService service) { - super(service); - } - - public abstract Task downloadMinecraft(String id); - - public abstract Task downloadMinecraftJar(MinecraftVersion mv, File f); - - public abstract Task downloadMinecraftVersionJson(String id); - - /** - * Get the libraries that need to download. - * - * @return the library collection - */ - public abstract List getDownloadLibraries(MinecraftVersion mv) throws GameException; - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IMinecraftInstallerService.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IMinecraftInstallerService.java deleted file mode 100644 index 04a6bed2c..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IMinecraftInstallerService.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.service; - -import org.jackhuang.hmcl.core.install.InstallerType; -import org.jackhuang.hmcl.core.install.InstallerVersionList; -import org.jackhuang.hmcl.util.task.Task; - -/** - * - * @author huangyuhui - */ -public abstract class IMinecraftInstallerService extends IMinecraftBasicService { - - public IMinecraftInstallerService(IMinecraftService service) { - super(service); - } - - public abstract Task download(String installId, InstallerVersionList.InstallerVersion v, InstallerType type); - - public abstract Task downloadForge(String installId, InstallerVersionList.InstallerVersion v); - - public abstract Task downloadOptiFine(String installId, InstallerVersionList.InstallerVersion v); - - public abstract Task downloadLiteLoader(String installId, InstallerVersionList.InstallerVersion v); - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IMinecraftLoader.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IMinecraftLoader.java deleted file mode 100644 index 16c210e4d..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IMinecraftLoader.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.service; - -import java.util.List; -import org.jackhuang.hmcl.core.GameException; -import org.jackhuang.hmcl.core.version.MinecraftVersion; - -/** - * - * @author huangyuhui - */ -public interface IMinecraftLoader { - - MinecraftVersion getMinecraftVersion(); - - List makeLaunchingCommand() throws GameException; -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IMinecraftModService.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IMinecraftModService.java deleted file mode 100644 index 9e17b288a..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IMinecraftModService.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.service; - -import java.io.File; -import java.util.List; -import org.jackhuang.hmcl.core.mod.ModInfo; - -/** - * - * @author huangyuhui - */ -public abstract class IMinecraftModService extends IMinecraftBasicService { - - public IMinecraftModService(IMinecraftService service) { - super(service); - } - - public abstract List getMods(String id); - - public abstract List recacheMods(String id); - - public abstract boolean addMod(String id, File f); - - public abstract boolean removeMod(String id, Object[] mods); -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IMinecraftProvider.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IMinecraftProvider.java deleted file mode 100644 index 0dc4a16c0..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IMinecraftProvider.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.service; - -import java.io.File; -import java.util.Collection; -import org.jackhuang.hmcl.core.GameException; -import org.jackhuang.hmcl.api.game.DecompressLibraryJob; -import org.jackhuang.hmcl.core.version.MinecraftVersion; -import org.jackhuang.hmcl.api.func.Consumer; -import org.jackhuang.hmcl.api.func.Predicate; -import org.jackhuang.hmcl.api.game.IMinecraftLibrary; - -/** - * Provide everything of the Minecraft of a Profile. - * - * @see - * org.jackhuang.hmcl.core.version.MinecraftVersionManager - * @author huangyuhui - */ -public abstract class IMinecraftProvider { - - protected T service; - - public IMinecraftProvider(T service) { - this.service = service; - } - - /** - * To download mod packs. - */ - public abstract void initializeMinecraft(); - - /** - * Get the run directory of given version. - * - * @param id the given version name - * - * @return the run directory - */ - public abstract File getRunDirectory(String id); - - public abstract File versionRoot(String id); - - public File getRunDirectory(String id, String subFolder) { - return new File(getRunDirectory(id), subFolder); - } - - public abstract void open(String version, String folder); - - /** - * Install a new version to this profile. - * - * @param version the new version name - * - * @return Is the action successful? - */ - public abstract boolean install(String version, Consumer callback); - - /** - * - * @param v should be resolved - * - * @return libraries of resolved minecraft version v. - */ - public abstract DecompressLibraryJob getDecompressLibraries(MinecraftVersion v) throws GameException; - - public abstract File getDecompressNativesToLocation(MinecraftVersion v); - - /** - * @return the Minecraft jar of selected version. - */ - public abstract File getMinecraftJar(String id); - - /** - * Rename version - * - * @param from The old name - * @param to The new name - * - * @return Is the action successful? - */ - public abstract boolean renameVersion(String from, String to); - - /** - * Remove the given version from disk. - * - * @param a the version name - * - * @return Is the action successful? - */ - public abstract boolean removeVersionFromDisk(String a); - - /** - * Choose a version randomly. - * - * @return the version - */ - public abstract MinecraftVersion getOneVersion(Predicate p); - - /** - * All Minecraft version in this profile. - * - * @return the collection of all Minecraft version - */ - public abstract Collection getVersions(); - - /** - * Get the Minecraft json instance of given version. - * - * @param id the given version name - * - * @return the Minecraft json instance - */ - public abstract MinecraftVersion getVersionById(String id); - - /** - * getVersions().size() - * - * @return getVersions().size() - */ - public abstract int getVersionCount(); - - /** - * Refind the versions in this profile. - * Must call onRefreshingVersions, onRefreshedVersions, onLoadedVersion - * Events. - */ - public abstract void refreshVersions(); - - /** - * Clean redundant files. - */ - public abstract void cleanFolder(); - - /** - * When GameLauncher launches the game, this function will be called. - * - * @return if false, will break the launch process. - */ - public abstract boolean onLaunch(String id); - - public File baseDirectory() { - return service.baseDirectory(); - } - - public abstract File getLibraryFile(MinecraftVersion version, IMinecraftLibrary library); - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IMinecraftService.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IMinecraftService.java deleted file mode 100644 index 0496e8678..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IMinecraftService.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.service; - -import java.io.File; -import org.jackhuang.hmcl.core.GameException; -import org.jackhuang.hmcl.api.auth.UserProfileProvider; -import org.jackhuang.hmcl.core.download.DownloadType; -import org.jackhuang.hmcl.api.game.LaunchOptions; - -/** - * - * @author huangyuhui - */ -public abstract class IMinecraftService { - - public abstract File baseDirectory(); - - public DownloadType getDownloadType() { - return DownloadType.getSuggestedDownloadType(); - } - - public abstract IMinecraftAssetService asset(); - - public abstract IMinecraftDownloadService download(); - - public abstract IMinecraftModService mod(); - - public abstract IMinecraftProvider version(); - - public abstract IMinecraftInstallerService install(); - - /** - * Provide the Minecraft Loader to generate the launching command. - * - * @see org.jackhuang.hmcl.core.service.IMinecraftLoader - * @param p player informations, including username & auth_token - * - * @return what you want - * - * @throws GameException circular denpendency versions - */ - public abstract IMinecraftLoader launch(LaunchOptions options, UserProfileProvider p) throws GameException; - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IProfile.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IProfile.java deleted file mode 100644 index 8b5a8ac43..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/service/IProfile.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.service; - -import java.io.File; -import org.jackhuang.hmcl.core.service.IMinecraftService; - -/** - * - * @author huangyuhui - */ -public interface IProfile { - - File getGameDir(); - - String getName(); - - String getSelectedVersion(); - - void onSelected(); - - IMinecraftService service(); - - void setGameDir(File gameDir); - - void setSelectedVersion(String selectedVersion); - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/AbstractMinecraftLibrary.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/AbstractMinecraftLibrary.java deleted file mode 100644 index ce68b277f..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/AbstractMinecraftLibrary.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.version; - -import org.jackhuang.hmcl.core.download.DownloadType; -import org.jackhuang.hmcl.api.game.IMinecraftLibrary; - -/** - * - * @author huangyuhui - */ -public abstract class AbstractMinecraftLibrary implements IMinecraftLibrary { - - private final String name; - - public AbstractMinecraftLibrary(String name) { - this.name = name; - } - - @Override - public String getName() { - return name; - } - - public abstract LibraryDownloadInfo getDownloadInfo(); - - @Override - public String getDownloadURL(String downloadSource) { - return getDownloadInfo().getUrl(DownloadType.valueOf(downloadSource)); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof MinecraftLibrary) - return ((MinecraftLibrary) obj).getName().equals(name); - return false; - } - - @Override - public int hashCode() { - int hash = 3; - hash = 89 * hash + (this.name != null ? this.name.hashCode() : 0); - return hash; - } - - @Override - public Object clone() { - try { - return super.clone(); - } catch (CloneNotSupportedException ex) { - throw new InternalError(ex); - } - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/AssetIndexDownloadInfo.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/AssetIndexDownloadInfo.java deleted file mode 100644 index bce033abb..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/AssetIndexDownloadInfo.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.version; - -import org.jackhuang.hmcl.core.download.DownloadType; - -/** - * - * @author huangyuhui - */ -public class AssetIndexDownloadInfo extends GameDownloadInfo { - - int totalSize; - - public AssetIndexDownloadInfo() { - } - - public AssetIndexDownloadInfo(String id) { - this.id = id; - url = null; - } - - @Override - public String getCustomizedURL(DownloadType dt) { - return dt.getProvider().getIndexesDownloadURL() + id + ".json"; - } - - public int getTotalSize() { - return totalSize; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/GameDownloadInfo.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/GameDownloadInfo.java deleted file mode 100644 index 43b7dada5..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/GameDownloadInfo.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.version; - -import com.google.gson.annotations.SerializedName; -import org.jackhuang.hmcl.core.download.DownloadType; -import org.jackhuang.hmcl.util.StrUtils; - -/** - * - * @author huangyuhui - */ -public class GameDownloadInfo implements Cloneable { - - @SerializedName("sha1") - public String sha1; - @SerializedName("size") - public int size; - @SerializedName("url") - public String url; - - /** - * Ready for AssetIndexDownloadInfo, and GameDownloadInfo also need this. - * And LoggingInfo will have this field in json. - */ - @SerializedName("id") - protected String id; - - /** - * Get the game download url. - * - * @param dt where to download? - * - * @return the download url - */ - public String getUrl(DownloadType dt) { - return getUrl(dt, dt.getProvider().isAllowedToUseSelfURL()); - } - - /** - * Get the game download url. - * - * @param dt where to download? - * @param allowSelf allow this game to be downloaded from its modified url? - * - * @return the download url - */ - public String getUrl(DownloadType dt, boolean allowSelf) { - if (StrUtils.isNotBlank(url) && allowSelf) - return dt.getProvider().getParsedDownloadURL(url); - else - return getCustomizedURL(dt); - } - - protected String getCustomizedURL(DownloadType dt) { - return dt.getProvider().getVersionsDownloadURL() + id + "/" + id + ".jar"; - } - - public String getId() { - return id; - } - - @Override - public Object clone() { - try { - return super.clone(); - } catch (CloneNotSupportedException ex) { - throw new Error(ex); - } - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/LibrariesDownloadInfo.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/LibrariesDownloadInfo.java deleted file mode 100644 index 7aeb0f250..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/LibrariesDownloadInfo.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.version; - -import com.google.gson.annotations.SerializedName; -import java.util.Map; - -/** - * - * @author huangyuhui - */ -public class LibrariesDownloadInfo { - - @SerializedName("classifiers") - public Map classifiers; - @SerializedName("artifact") - public LibraryDownloadInfo artifact; -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/LibraryDownloadInfo.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/LibraryDownloadInfo.java deleted file mode 100644 index aee587aa2..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/LibraryDownloadInfo.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.version; - -import com.google.gson.annotations.SerializedName; -import org.jackhuang.hmcl.core.download.DownloadType; -import org.jackhuang.hmcl.util.StrUtils; -import org.jackhuang.hmcl.util.sys.IOUtils; - -/** - * - * @author huangyuhui - */ -public class LibraryDownloadInfo extends GameDownloadInfo { - - @SerializedName("path") - public String path; - @SerializedName("forgeURL") - public String forgeURL; - - @Override - public String getUrl(DownloadType dt, boolean allowSelf) { - String myURL = dt.getProvider().getParsedDownloadURL(IOUtils.addURLSeparator(forgeURL == null ? dt.getProvider().getLibraryDownloadURL() : forgeURL) + path.replace('\\', '/')); - if (StrUtils.isNotBlank(url) && allowSelf) - myURL = dt.getProvider().getParsedDownloadURL(url); - if (!myURL.endsWith(".jar")) - if (path == null) - return null; - return myURL; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/LoggingInfo.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/LoggingInfo.java deleted file mode 100644 index a9aae5e7d..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/LoggingInfo.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.version; - -/** - * - * @author huang - */ -public class LoggingInfo implements Cloneable { - public GameDownloadInfo file; - public String argument; - public String type; - - @Override - public Object clone() { - try { - LoggingInfo info = (LoggingInfo) super.clone(); - info.file = (GameDownloadInfo) file.clone(); - return info; - } catch(CloneNotSupportedException e) { - throw new Error(e); - } - } - - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/MinecraftClassicVersion.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/MinecraftClassicVersion.java deleted file mode 100644 index 9d7df9cc2..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/MinecraftClassicVersion.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.version; - -import java.io.File; -import java.util.ArrayList; -import java.util.Set; -import org.jackhuang.hmcl.core.service.IMinecraftProvider; - -/** - * - * @author huangyuhui - */ -public class MinecraftClassicVersion extends MinecraftVersion { - - public MinecraftClassicVersion() { - super(); - - mainClass = "net.minecraft.client.Minecraft"; - id = "Classic"; - type = "release"; - processArguments = assets = releaseTime = time = null; - minecraftArguments = "${auth_player_name} ${auth_session} --workDir ${game_directory}"; - libraries = new ArrayList<>(); - libraries.add(new MinecraftOldLibrary("lwjgl")); - libraries.add(new MinecraftOldLibrary("jinput")); - libraries.add(new MinecraftOldLibrary("lwjgl_util")); - } - - @Override - public Object clone() { - return super.clone(); - } - - @Override - public MinecraftVersion resolve(IMinecraftProvider manager, Set resolvedSoFar) { - return this; - } - - @Override - public File getJar(File gameDir) { - return new File(gameDir, "bin/minecraft.jar"); - } - - @Override - public File getJar(File gameDir, String suffix) { - return new File(gameDir, "bin/minecraft" + suffix + ".jar"); - } - - @Override - public File getNatives(File gameDir) { - return new File(gameDir, "bin/natives"); - } - - @Override - public boolean isAllowedToUnpackNatives() { - return false; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/MinecraftLibrary.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/MinecraftLibrary.java deleted file mode 100644 index 06e17f28e..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/MinecraftLibrary.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.version; - -import org.jackhuang.hmcl.api.game.Extract; -import com.google.gson.annotations.SerializedName; -import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; -import org.jackhuang.hmcl.util.sys.OS; -import org.jackhuang.hmcl.util.sys.Platform; -import org.jackhuang.hmcl.util.StrUtils; - -/** - * - * @author huangyuhui - */ -public class MinecraftLibrary extends AbstractMinecraftLibrary { - - @SerializedName("rules") - public ArrayList rules; - @SerializedName("url") - public String url; - @SerializedName("natives") - public Natives natives; - @SerializedName("extract") - public Extract extract; - @SerializedName("downloads") - public LibrariesDownloadInfo downloads; - - public MinecraftLibrary(String name) { - super(name); - } - - /** - * is the library allowed to load. - * - * @return - */ - @Override - public boolean allow() { - if (rules != null) { - boolean flag = false; - for (Rules r : rules) - if ("disallow".equals(r.action())) - return false; - else if ("allow".equals(r.action())) - flag = true; - return flag; - } else - return true; - } - - private String formatArch(String nati) { - return nati == null ? "" : nati.replace("${arch}", Platform.getPlatform().getBit()); - } - - private String getNative() { - if (natives == null) - return ""; - switch (OS.os()) { - case WINDOWS: - return formatArch(natives.windows); - case OSX: - return formatArch(natives.osx); - default: - return formatArch(natives.linux); - } - } - - @Override - public boolean isNative() { - return natives != null && allow(); - } - - public String formatName() { - if (getName() == null) - return null; - String[] s = getName().split(":"); - if (s.length < 3) - return null; - StringBuilder sb = new StringBuilder(s[0].replace('.', '/')).append('/').append(s[1]).append('/').append(s[2]).append('/').append(s[1]).append('-').append(s[2]); - if (natives != null) - sb.append('-').append(getNative()); - return sb.append(".jar").toString(); - } - - @Override - public File getFilePath(File gameDir) { - LibraryDownloadInfo info = getDownloadInfo(); - if (info == null) - return null; - return new File(gameDir, "libraries/" + info.path); - } - - @Override - public Extract getDecompressExtractRules() { - return extract == null ? new Extract() : extract; - } - - @Override - public LibraryDownloadInfo getDownloadInfo() { - if (getName() == null) - return null; - if (downloads == null) - downloads = new LibrariesDownloadInfo(); - LibraryDownloadInfo info; - if (natives != null) { - if (downloads.classifiers == null) - downloads.classifiers = new HashMap<>(); - if (!downloads.classifiers.containsKey(getNative())) - downloads.classifiers.put(getNative(), info = new LibraryDownloadInfo()); - else info = downloads.classifiers.get(getNative()); - } else { - if (downloads.artifact == null) - downloads.artifact = new LibraryDownloadInfo(); - info = downloads.artifact; - } - if (StrUtils.isBlank(info.path)) { - info.path = formatName(); - if (info.path == null) - return null; - } - info.forgeURL = this.url; - return info; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/MinecraftOldLibrary.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/MinecraftOldLibrary.java deleted file mode 100644 index 56e6a1550..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/MinecraftOldLibrary.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.version; - -import java.io.File; - -/** - * - * @author huangyuhui - */ -public class MinecraftOldLibrary extends MinecraftLibrary { - - public MinecraftOldLibrary(String name) { - super(name); - } - - @Override - public boolean isNative() { - return false; - } - - @Override - public boolean allow() { - return true; - } - - @Override - public File getFilePath(File gameDir) { - return new File(gameDir, "bin/" + getName() + ".jar"); - } - - @Override - public Object clone() { - return super.clone(); - } - - @Override - public LibraryDownloadInfo getDownloadInfo() { - return new LibraryDownloadInfo(); - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/MinecraftVersion.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/MinecraftVersion.java deleted file mode 100644 index 504fd423b..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/MinecraftVersion.java +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.version; - -import org.jackhuang.hmcl.api.game.IMinecraftLibrary; -import com.google.gson.annotations.SerializedName; -import java.io.File; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.core.GameException; -import org.jackhuang.hmcl.core.service.IMinecraftProvider; -import org.jackhuang.hmcl.core.asset.AssetsIndex; -import org.jackhuang.hmcl.util.ArrayUtils; - -/** - * - * @author huangyuhui - */ -public class MinecraftVersion implements Cloneable, Comparable { - - @SerializedName("minecraftArguments") - public String minecraftArguments; - @SerializedName("mainClass") - public String mainClass; - @SerializedName("time") - public String time; - @SerializedName("id") - public String id; - @SerializedName("type") - public String type; - @SerializedName("processArguments") - public String processArguments; - @SerializedName("releaseTime") - public String releaseTime; - @SerializedName("jar") - public String jar; - @SerializedName("inheritsFrom") - public String inheritsFrom; - @SerializedName("runDir") - public String runDir; - @SerializedName("assets") - protected String assets; - @SerializedName("minimumLauncherVersion") - public int minimumLauncherVersion; - @SerializedName("hidden") - public boolean hidden; - @SerializedName("assetIndex") - public AssetIndexDownloadInfo assetIndex; - @SerializedName("downloads") - private Map downloads; - @SerializedName("libraries") - public ArrayList libraries; - @SerializedName("logging") - public Map logging; - - public MinecraftVersion() { - } - - public MinecraftVersion(String minecraftArguments, String mainClass, String time, String id, String type, String processArguments, String releaseTime, String assets, String jar, String inheritsFrom, String runDir, int minimumLauncherVersion, List libraries, boolean hidden, Map downloads, AssetIndexDownloadInfo assetIndexDownloadInfo, Map logging) { - this(); - this.minecraftArguments = minecraftArguments; - this.mainClass = mainClass; - this.time = time; - this.id = id; - this.type = type; - this.processArguments = processArguments; - this.releaseTime = releaseTime; - this.assets = assets; - this.jar = jar; - this.inheritsFrom = inheritsFrom; - this.minimumLauncherVersion = minimumLauncherVersion; - this.hidden = hidden; - this.runDir = runDir; - if (assetIndexDownloadInfo == null) - this.assetIndex = null; - else - this.assetIndex = (AssetIndexDownloadInfo) assetIndexDownloadInfo.clone(); - if (libraries == null) - this.libraries = new ArrayList<>(); - else { - this.libraries = new ArrayList<>(libraries.size()); - for (MinecraftLibrary library : libraries) - if (library != null) - this.libraries.add((MinecraftLibrary) library.clone()); - } - if (downloads == null) - this.downloads = null; - else { - this.downloads = new HashMap<>(downloads.size()); - for (Map.Entry entry : downloads.entrySet()) - this.downloads.put(entry.getKey(), (GameDownloadInfo) entry.getValue().clone()); - } - if (logging == null) - this.logging = null; - else { - this.logging = new HashMap<>(logging.size()); - for (Map.Entry entry : logging.entrySet()) - this.logging.put(entry.getKey(), (LoggingInfo) entry.getValue().clone()); - } - } - - @Override - public Object clone() { - try { - MinecraftVersion mv = (MinecraftVersion) super.clone(); - mv.libraries = (ArrayList) mv.libraries.clone(); - return mv; - } catch (CloneNotSupportedException ex) { - throw new InternalError(); - } - } - - public MinecraftVersion resolve(IMinecraftProvider provider) throws GameException { - return resolve(provider, new HashSet<>()); - } - - protected MinecraftVersion resolve(IMinecraftProvider provider, Set resolvedSoFar) throws GameException { - if (inheritsFrom == null) - return this; - if (!resolvedSoFar.add(id)) - throw new GameException(C.i18n("launch.circular_dependency_versions")); - - MinecraftVersion parent = provider.getVersionById(inheritsFrom); - if (parent == null) { - if (!provider.install(inheritsFrom, t -> t.hidden = true)) - return this; - parent = provider.getVersionById(inheritsFrom); - } - parent = parent.resolve(provider, resolvedSoFar); - MinecraftVersion result = new MinecraftVersion( - this.minecraftArguments != null ? this.minecraftArguments : parent.minecraftArguments, - this.mainClass != null ? this.mainClass : parent.mainClass, - this.time, this.id, this.type, parent.processArguments, this.releaseTime, - this.assets != null ? this.assets : parent.assets, - this.jar != null ? this.jar : parent.jar, - null, this.runDir, parent.minimumLauncherVersion, - this.libraries != null ? ArrayUtils.merge(this.libraries, parent.libraries) : parent.libraries, this.hidden, - this.downloads != null ? this.downloads : parent.downloads, - this.assetIndex != null ? this.assetIndex : parent.assetIndex, - this.logging != null ? this.logging : parent.logging); - - return result; - } - - public File getJar(File gameDir) { - String jarId = this.jar == null ? this.id : this.jar; - return new File(gameDir, "versions/" + jarId + "/" + jarId + ".jar"); - } - - public File getJar(File gameDir, String suffix) { - String jarId = this.jar == null ? this.id : this.jar; - return new File(gameDir, "versions/" + jarId + "/" + jarId + suffix + ".jar"); - } - - public File getNatives(File gameDir) { - return new File(gameDir, "versions/" + id + "/" + id + "-natives"); - } - - public boolean isAllowedToUnpackNatives() { - return true; - } - - @Override - public int compareTo(MinecraftVersion o) { - return id.compareTo(o.id); - } - - @Override - public int hashCode() { - int hash = 7; - hash = 53 * hash + Objects.hashCode(this.id); - return hash; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null || getClass() != obj.getClass()) - return false; - return Objects.equals(this.id, ((MinecraftVersion) obj).id); - } - - public AssetIndexDownloadInfo getAssetsIndex() { - if (assetIndex == null) - assetIndex = new AssetIndexDownloadInfo(assets == null ? AssetsIndex.DEFAULT_ASSET_NAME : assets); - return assetIndex; - } - - public GameDownloadInfo getClientDownloadInfo() { - if (downloads == null) - downloads = new HashMap<>(); - if (!downloads.containsKey("client")) - downloads.put("client", new GameDownloadInfo()); - GameDownloadInfo i = downloads.get("client"); - if (i.id == null) - i.id = id; - return i; - } - - public List getLibraries() { - return libraries == null ? new LinkedList<>() : Collections.unmodifiableList(libraries); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/MinecraftVersionManager.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/MinecraftVersionManager.java deleted file mode 100644 index d6a24c5b3..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/MinecraftVersionManager.java +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.version; - -import org.jackhuang.hmcl.api.game.Extract; -import org.jackhuang.hmcl.api.game.IMinecraftLibrary; -import org.jackhuang.hmcl.api.game.DecompressLibraryJob; -import com.google.gson.JsonSyntaxException; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Map; -import java.util.TreeMap; -import org.jackhuang.hmcl.api.HMCLApi; -import org.jackhuang.hmcl.api.event.version.LoadedOneVersionEvent; -import org.jackhuang.hmcl.api.event.version.RefreshedVersionsEvent; -import org.jackhuang.hmcl.api.event.version.RefreshingVersionsEvent; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.core.GameException; -import org.jackhuang.hmcl.core.service.IMinecraftProvider; -import org.jackhuang.hmcl.core.service.IMinecraftService; -import org.jackhuang.hmcl.util.sys.FileUtils; -import org.jackhuang.hmcl.core.MCUtils; -import org.jackhuang.hmcl.util.task.TaskWindow; -import org.jackhuang.hmcl.util.ui.MessageBox; -import org.jackhuang.hmcl.util.StrUtils; -import org.jackhuang.hmcl.api.func.Consumer; -import org.jackhuang.hmcl.api.func.Predicate; -import org.jackhuang.hmcl.util.sys.IOUtils; -import org.jackhuang.hmcl.util.ui.SwingUtils; - -/** - * - * @author huangyuhui - */ -public class MinecraftVersionManager extends IMinecraftProvider { - - final Map versions = new TreeMap<>(); - - /** - * - * @param p - */ - public MinecraftVersionManager(T p) { - super(p); - } - - @Override - public Collection getVersions() { - return versions.values(); - } - - @Override - public int getVersionCount() { - return versions.size(); - } - - @Override - public synchronized void refreshVersions() { - HMCLApi.EVENT_BUS.fireChannel(new RefreshingVersionsEvent(this)); - - try { - MCUtils.tryWriteProfile(baseDirectory()); - } catch (IOException ex) { - HMCLog.warn("Failed to create launcher_profiles.json, Forge/LiteLoader installer will not work.", ex); - } - - versions.clear(); - File oldDir = new File(baseDirectory(), "bin"); - if (oldDir.exists()) { - MinecraftClassicVersion v = new MinecraftClassicVersion(); - versions.put(v.id, v); - } - - File version = new File(baseDirectory(), "versions"); - File[] files = version.listFiles(); - if (files != null && files.length > 0) - for (File dir : files) { - String id = dir.getName(); - File jsonFile = new File(dir, id + ".json"); - - if (!dir.isDirectory()) - continue; - boolean ask = false; - File[] jsons = null; - if (!jsonFile.exists()) { - jsons = FileUtils.searchSuffix(dir, "json"); - if (jsons.length == 1) - ask = true; - } - if (ask) { - HMCLog.warn("Found not matched filenames version: " + id + ", json: " + jsons[0].getName()); - if (MessageBox.show(String.format(C.i18n("launcher.versions_json_not_matched"), id, jsons[0].getName()), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION) - if (!jsons[0].renameTo(jsonFile)) - HMCLog.warn("Failed to rename version json " + jsons[0]); - } - if (!jsonFile.exists()) { - if (MessageBox.show(C.i18n("launcher.versions_json_not_matched_cannot_auto_completion", id), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION) - FileUtils.deleteDirectoryQuietly(dir); - continue; - } - MinecraftVersion mcVersion; - try { - mcVersion = readJson(jsonFile); - if (mcVersion == null) - throw new JsonSyntaxException("Wrong json format, got null."); - } catch (JsonSyntaxException | IOException e) { - HMCLog.warn("Found wrong format json, try to fix it.", e); - if (MessageBox.show(C.i18n("launcher.versions_json_not_formatted", id), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION) { - TaskWindow.factory().execute(service.download().downloadMinecraftVersionJson(id)); - try { - mcVersion = readJson(jsonFile); - if (mcVersion == null) - throw new JsonSyntaxException("Wrong json format, got null."); - } catch (IOException | JsonSyntaxException ex) { - HMCLog.warn("Ignoring: " + dir + ", the json of this Minecraft is malformed.", ex); - continue; - } - } else - continue; - } - try { - if (!id.equals(mcVersion.id)) { - HMCLog.warn("Found: " + dir + ", it contains id: " + mcVersion.id + ", expected: " + id + ", this app will fix this problem."); - mcVersion.id = id; - FileUtils.writeQuietly(jsonFile, C.GSON.toJson(mcVersion)); - } - - versions.put(id, mcVersion); - HMCLApi.EVENT_BUS.fireChannel(new LoadedOneVersionEvent(this, id)); - } catch (Exception e) { - HMCLog.warn("Ignoring: " + dir + ", the json of this Minecraft is malformed.", e); - } - } - HMCLApi.EVENT_BUS.fireChannel(new RefreshedVersionsEvent(this)); - } - - @Override - public File versionRoot(String id) { - return new File(baseDirectory(), "versions/" + id); - } - - @Override - public boolean removeVersionFromDisk(String name) { - File version = versionRoot(name); - if (!version.exists()) - return true; - - versions.remove(name); - return FileUtils.deleteDirectoryQuietly(version); - } - - /** - * - * @param id version id - * @return null if json syntax is wrong or cannot read the json file. - */ - public MinecraftVersion readJson(String id) { - try { - return readJson(new File(versionRoot(id), id + ".json")); - } catch(IOException | JsonSyntaxException e) { - return null; - } - } - - public MinecraftVersion readJson(File file) throws IOException { - return C.GSON.fromJson(FileUtils.read(file, IOUtils.DEFAULT_CHARSET), MinecraftVersion.class); - } - - @Override - public boolean renameVersion(String from, String to) { - try { - File toDir = versionRoot(to); - if (!versionRoot(from).renameTo(toDir)) - return false; - File toJson = new File(toDir, to + ".json"); - File toJar = new File(toDir, to + ".jar"); - if (!new File(toDir, from + ".json").renameTo(toJson)) - HMCLog.warn("MinecraftVersionManager.RenameVersion: Failed to rename json"); - MinecraftVersion mcVersion = readJson(toJson); - mcVersion.id = to; - FileUtils.writeQuietly(toJson, C.GSON.toJson(mcVersion)); - File oldJar = new File(toDir, from + ".jar"); - if (oldJar.exists() && !oldJar.renameTo(toJar)) - HMCLog.warn("Failed to rename pre jar " + oldJar + " to new jar " + toJar); - return true; - } catch (IOException | JsonSyntaxException e) { - HMCLog.warn("Failed to rename " + from + " to " + to + ", the json of this Minecraft is malformed.", e); - return false; - } - } - - @Override - public File getRunDirectory(String id) { - if (getVersionById(id) != null) - if ("version".equals(getVersionById(id).runDir)) - return versionRoot(id); - return baseDirectory(); - } - - @Override - public boolean install(String id, Consumer callback) { - if (!TaskWindow.factory().append(service.download().downloadMinecraft(id)).execute()) - return false; - if (callback != null) { - File mvt = new File(versionRoot(id), id + ".json"); - MinecraftVersion v = readJson(id); - if (v == null) - return false; - callback.accept(v); - FileUtils.writeQuietly(mvt, C.GSON.toJson(v)); - } - refreshVersions(); - return true; - } - - @Override - public void open(String mv, String name) { - SwingUtils.openFolder((name == null) ? getRunDirectory(mv) : new File(getRunDirectory(mv), name)); - } - - @Override - public File getLibraryFile(MinecraftVersion version, IMinecraftLibrary lib) { - return lib.getFilePath(baseDirectory()); - } - - @Override - public DecompressLibraryJob getDecompressLibraries(MinecraftVersion v) throws GameException { - if (v.libraries == null) - throw new GameException("Wrong format: minecraft.json"); - ArrayList unzippings = new ArrayList<>(); - ArrayList extractRules = new ArrayList<>(); - for (IMinecraftLibrary l : v.libraries) - if (l.isNative() && v.isAllowedToUnpackNatives()) { - unzippings.add(getLibraryFile(v, l)); - extractRules.add(l.getDecompressExtractRules()); - } - return new DecompressLibraryJob(unzippings.toArray(new File[unzippings.size()]), extractRules.toArray(new Extract[extractRules.size()]), getDecompressNativesToLocation(v)); - } - - @Override - public File getDecompressNativesToLocation(MinecraftVersion v) { - return v == null ? null : v.getNatives(baseDirectory()); - } - - @Override - public File getMinecraftJar(String id) { - if (versions.containsKey(id)) - return versions.get(id).getJar(baseDirectory()); - else - return null; - } - - @Override - public MinecraftVersion getOneVersion(Predicate pred) { - for (MinecraftVersion v : versions.values()) - if (pred == null || pred.apply(v)) - return v; - return null; - } - - @Override - public MinecraftVersion getVersionById(String id) { - return StrUtils.isBlank(id) ? null : versions.get(id); - } - - @Override - public boolean onLaunch(String id) { - // Fix bug in Minecraft 1.8 - File resourcePacks = new File(getRunDirectory(id), "resourcepacks"); - if (!FileUtils.makeDirectory(resourcePacks)) - HMCLog.warn("Failed to make resourcePacks: " + resourcePacks); - return true; - } - - @Override - public void cleanFolder() { - for (MinecraftVersion s : getVersions()) { - FileUtils.deleteDirectoryQuietly(new File(versionRoot(s.id), s.id + "-natives")); - File f = getRunDirectory(s.id); - String[] dir = { "natives", "native", "$native", "AMD", "crash-reports", "logs", "asm", "NVIDIA", "server-resource-packs", "natives", "native" }; - for (String str : dir) - FileUtils.deleteDirectoryQuietly(new File(f, str)); - String[] files = { "output-client.log", "usercache.json", "usernamecache.json", "hmclmc.log" }; - for (String str : files) - if (!new File(f, str).delete()) - HMCLog.warn("Failed to delete " + str); - } - } - - @Override - public void initializeMinecraft() { - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/Natives.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/Natives.java deleted file mode 100644 index 47ad558d0..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/Natives.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.version; - -import com.google.gson.annotations.SerializedName; - -/** - * - * @author huangyuhui - */ -public class Natives implements Cloneable { - - @SerializedName("windows") - public String windows; - @SerializedName("osx") - public String osx; - @SerializedName("linux") - public String linux; - - @Override - protected Object clone() { - try { - return super.clone(); - } catch (CloneNotSupportedException ex) { - throw new InternalError(ex); - } - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/OSRestriction.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/OSRestriction.java deleted file mode 100644 index 4297d2e0d..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/OSRestriction.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.version; - -import com.google.gson.annotations.SerializedName; -import org.jackhuang.hmcl.util.StrUtils; -import org.jackhuang.hmcl.util.sys.OS; - -/** - * - * @author huangyuhui - */ -public class OSRestriction { - - @SerializedName("version") - private String version; - @SerializedName("name") - public String name; - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public boolean isCurrentOS() { - return StrUtils.isBlank(getName()) || OS.os().name().equalsIgnoreCase(getName()); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/Rules.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/Rules.java deleted file mode 100644 index 8e455eaa9..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/core/version/Rules.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.core.version; - -import com.google.gson.annotations.SerializedName; - -/** - * - * @author huangyuhui - */ -public class Rules { - - @SerializedName("action") - private String action; - @SerializedName("os") - private OSRestriction os; - - public Rules() { - } - - public String action() { - return os == null || os.isCurrentOS() ? action : null; - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/AbstractSwingWorker.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/AbstractSwingWorker.java deleted file mode 100644 index fbabebe59..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/AbstractSwingWorker.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; -import javax.swing.SwingWorker; -import org.jackhuang.hmcl.api.func.Consumer; - -/** - * - * @author huangyuhui - */ -public abstract class AbstractSwingWorker extends SwingWorker { - - List> processListeners = new ArrayList<>(); - List doneListeners = new ArrayList<>(); - - protected abstract void work() throws Exception; - - @Override - protected void done() { - for (Runnable c : doneListeners) - c.run(); - } - - @Override - protected Void doInBackground() throws Exception { - work(); - return null; - } - - public AbstractSwingWorker reg(Consumer c) { - processListeners.add(Objects.requireNonNull(c)); - return this; - } - - public AbstractSwingWorker regDone(Runnable c) { - doneListeners.add(Objects.requireNonNull(c)); - return this; - } - - @Override - protected void process(List chunks) { - for (T t : chunks) - for (Consumer c : processListeners) - c.accept(t); - } - - final List lastChunks = new ArrayList<>(); - - public void send(T... t) { - lastChunks.addAll(Arrays.asList(t)); - publish(t); - } - - public List justDo() throws Exception { - work(); - return lastChunks; - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ArrayUtils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ArrayUtils.java deleted file mode 100644 index edc43cc33..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ArrayUtils.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Map; - -/** - * - * @author huangyuhui - */ -public final class ArrayUtils { - - private ArrayUtils() { - } - - public static boolean isEmpty(T[] array) { - return array == null || array.length <= 0; - } - - public static boolean isNotEmpty(T[] array) { - return !isEmpty(array); - } - - public static boolean contains(T[] array, T objectToFind) { - return indexOf(array, objectToFind) != -1; - } - - public static int indexOf(T[] array, T valueToFind) { - return indexOf(array, valueToFind, 0); - } - - public static int indexOf(T[] array, T valueToFind, int startIndex) { - if (array == null) - return -1; - if (startIndex < 0) - startIndex = 0; - for (int i = startIndex; i < array.length; i++) - if (valueToFind.equals(array[i])) - return i; - return -1; - } - - public static int lastIndexOf(T[] array, T valueToFind, int startIndex) { - if (array == null) - return -1; - if (startIndex < 0) - return -1; - if (startIndex >= array.length) - startIndex = array.length - 1; - for (int i = startIndex; i >= 0; i--) - if (valueToFind.equals(array[i])) - return i; - return -1; - } - - public static ArrayList merge(List a, List b) { - ArrayList al = new ArrayList<>(a.size() + b.size()); - al.addAll(a); - al.addAll(b); - return al; - } - - public static List tryGetMapWithList(Map> map, String key) { - List l = (List) map.get(key); - if (l == null) - map.put(key, l = new ArrayList<>()); - return l; - } - - public static int matchArray(byte[] a, byte[] b) { - for (int i = 0; i < a.length - b.length; i++) { - int j = 1; - for (int k = 0; k < b.length; k++) { - if (b[k] == a[(i + k)]) - continue; - j = 0; - break; - } - if (j != 0) - return i; - } - return -1; - } - - public static boolean hasDuplicateElements(T[] t) { - return new HashSet<>(Arrays.asList(t)).size() < t.length; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/C.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/C.java deleted file mode 100644 index 1cdc12a61..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/C.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util; - -import org.jackhuang.hmcl.util.lang.SupportedLocales; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -/** - * - * @author huangyuhui - */ -public final class C { - - public static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); - - //http://repo1.maven.org/maven2 - public static final String URL_PUBLISH = "http://www.mcbbs.net/thread-142335-1-1.html"; - public static final String URL_CONTACT = "http://huangyuhui.duapp.com/hmcl.php"; - - public static final String URL_FORGE_LIST = "http://files.minecraftforge.net/maven/net/minecraftforge/forge/json"; - public static final String URL_LITELOADER_LIST = "http://dl.liteloader.com/versions/versions.json"; - - public static final String LINE_SEPARATOR = System.getProperty("line.separator"); - - private C() { - } - - public static String i18n(String a, Object... format) { - return SupportedLocales.getNowLocale().translate(a, format); - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/CollectionUtils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/CollectionUtils.java deleted file mode 100644 index 762649bfc..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/CollectionUtils.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util; - -import org.jackhuang.hmcl.api.func.Predicate; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; - -/** - * - * @author huangyuhui - */ -public final class CollectionUtils { - - private CollectionUtils() { - } - - public static ArrayList filter(Collection coll, Predicate p) { - ArrayList newColl = new ArrayList<>(); - for (T t : coll) - if (p.apply(t)) - newColl.add(t); - return newColl; - } - - public static boolean removeIf(Collection coll, Predicate p) { - boolean removed = false; - final Iterator each = coll.iterator(); - while (each.hasNext()) - if (p.apply(each.next())) { - each.remove(); - removed = true; - } - return removed; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/DoubleOutputStream.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/DoubleOutputStream.java deleted file mode 100644 index 37b20128d..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/DoubleOutputStream.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util; - -import java.io.IOException; -import java.io.OutputStream; - -/** - * - * @author huangyuhui - */ -public class DoubleOutputStream extends OutputStream { - - private OutputStream os1 = null; - private OutputStream os2 = null; - private boolean autoFlush = true; - - public DoubleOutputStream(OutputStream os1, OutputStream os2) { - this(os1, os2, true); - } - - private DoubleOutputStream(OutputStream os1, OutputStream os2, boolean autoFlush) { - this.os1 = os1; - this.os2 = os2; - this.autoFlush = autoFlush; - } - - @Override - public final void write(byte[] arr, int off, int len) throws IOException { - if (this.os1 != null) - this.os1.write(arr, off, len); - if (this.os2 != null) - this.os2.write(arr, off, len); - if (this.autoFlush) - flush(); - } - - @Override - public final void write(byte[] arr) throws IOException { - if (this.os1 != null) - this.os1.write(arr); - if (this.os2 != null) - this.os2.write(arr); - if (this.autoFlush) - flush(); - } - - @Override - public final void write(int i) throws IOException { - if (this.os1 != null) - this.os1.write(i); - if (this.os2 != null) - this.os2.write(i); - if (this.autoFlush) - flush(); - } - - @Override - public final void close() throws IOException { - flush(); - - if (this.os1 != null) - this.os1.close(); - if (this.os2 != null) - this.os2.close(); - } - - @Override - public final void flush() throws IOException { - if (this.os1 != null) - this.os1.flush(); - if (this.os2 != null) - this.os2.flush(); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/IUpdateChecker.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/IUpdateChecker.java deleted file mode 100644 index dce9baa7b..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/IUpdateChecker.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util; - -import org.jackhuang.hmcl.api.VersionNumber; -import java.util.Map; - -/** - * - * @author huangyuhui - */ -public interface IUpdateChecker { - - /** - * - */ - void checkOutdate(); - - /** - * Get the cached newest version number, use "process" method to - * download! - * - * @return the newest version number - * - * @see process - */ - VersionNumber getNewVersion(); - - /** - * Download the version number synchronously. When you execute this method - * first, should leave "showMessage" false. - * - * @param showMessage If it is requested to warn the user that there is a - * new version. - * - * @return the process observable. - */ - AbstractSwingWorker process(boolean showMessage); - - /** - * Get the download links. - * - * @return a JSON, which contains the server response. - */ - AbstractSwingWorker> requestDownloadLink(); - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/MathUtils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/MathUtils.java deleted file mode 100644 index b58850e21..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/MathUtils.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util; - -/** - * - * @author huang - */ -public final class MathUtils { - - private MathUtils() { - } - - public static int parseInt(String s, int def) { - try { - return Integer.parseInt(s); - } catch (Exception e) { - return def; - } - } - - public static boolean canParseInt(String s) { - try { - Integer.parseInt(s); - return true; - } catch (Exception e) { - return false; - } - } - - public static int parseMemory(String s, int def) { - try { - return Integer.parseInt(s); - } catch (Exception e) { - int a = parseInt(s.substring(0, s.length() - 1), def); - if (s.endsWith("g")) - return a * 1024; - else if (s.endsWith("k")) - return a / 1024; - else - return a; - } - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/MinecraftVersionRequest.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/MinecraftVersionRequest.java deleted file mode 100644 index fb62812fa..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/MinecraftVersionRequest.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util; - -import java.io.File; -import java.io.IOException; -import java.io.Serializable; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.util.sys.IOUtils; - -/** - * @author huangyuhui - */ -public class MinecraftVersionRequest implements Serializable { - - private static final long serialVersionUID = 1L; - - public static final int UNKOWN = 0, INVALID = 1, INVALID_JAR = 2, - MODIFIED = 3, OK = 4, NOT_FOUND = 5, UNREADABLE = 6, NOT_FILE = 7; - public int type; - public String version; - - public static String getResponse(MinecraftVersionRequest minecraftVersion) { - switch (minecraftVersion.type) { - case MinecraftVersionRequest.INVALID: - return C.i18n("minecraft.invalid"); - case MinecraftVersionRequest.INVALID_JAR: - return C.i18n("minecraft.invalid_jar"); - case MinecraftVersionRequest.NOT_FILE: - return C.i18n("minecraft.not_a_file"); - case MinecraftVersionRequest.NOT_FOUND: - return C.i18n("minecraft.not_found"); - case MinecraftVersionRequest.UNREADABLE: - return C.i18n("minecraft.not_readable"); - case MinecraftVersionRequest.MODIFIED: - return C.i18n("minecraft.modified") + ' ' + minecraftVersion.version; - case MinecraftVersionRequest.OK: - return minecraftVersion.version; - case MinecraftVersionRequest.UNKOWN: - default: - return "???"; - } - } - - private static int lessThan32(byte[] b, int x) { - for (; x < b.length; x++) - if (b[x] < 32) - return x; - return -1; - } - - private static MinecraftVersionRequest getVersionOfOldMinecraft(ZipFile file, ZipEntry entry) throws IOException { - MinecraftVersionRequest r = new MinecraftVersionRequest(); - byte[] tmp = IOUtils.toByteArray(file.getInputStream(entry)); - - byte[] bytes = "Minecraft Minecraft ".getBytes("ASCII"); - int j = ArrayUtils.matchArray(tmp, bytes); - if (j < 0) { - r.type = MinecraftVersionRequest.UNKOWN; - return r; - } - int i = j + bytes.length; - - if ((j = lessThan32(tmp, i)) < 0) { - r.type = MinecraftVersionRequest.UNKOWN; - return r; - } - String ver = new String(tmp, i, j - i, "ASCII"); - r.version = ver; - - r.type = file.getEntry("META-INF/MANIFEST.MF") == null - ? MinecraftVersionRequest.MODIFIED : MinecraftVersionRequest.OK; - return r; - } - - private static MinecraftVersionRequest getVersionOfNewMinecraft(ZipFile file, ZipEntry entry) throws IOException { - MinecraftVersionRequest r = new MinecraftVersionRequest(); - byte[] tmp = IOUtils.toByteArray(file.getInputStream(entry)); - - byte[] str = "-server.txt".getBytes("ASCII"); - int j = ArrayUtils.matchArray(tmp, str); - if (j < 0) { - r.type = MinecraftVersionRequest.UNKOWN; - return r; - } - int i = j + str.length; - i += 11; - j = lessThan32(tmp, i); - if (j < 0) { - r.type = MinecraftVersionRequest.UNKOWN; - return r; - } - r.version = new String(tmp, i, j - i, "ASCII"); - - char ch = r.version.charAt(0); - // 1.8.1+ - if (ch < '0' || ch > '9') { - str = "Can't keep up! Did the system time change, or is the server overloaded?".getBytes("ASCII"); - j = ArrayUtils.matchArray(tmp, str); - if (j < 0) { - r.type = MinecraftVersionRequest.UNKOWN; - return r; - } - i = -1; - while (j > 0) { - if (tmp[j] >= 48 && tmp[j] <= 57) { - i = j; - break; - } - j--; - } - if (i == -1) { - r.type = MinecraftVersionRequest.UNKOWN; - return r; - } - int k = i; - if (tmp[i + 1] >= (int) 'a' && tmp[i + 1] <= (int) 'z') - i++; - while (tmp[k] >= 48 && tmp[k] <= 57 || tmp[k] == (int) '-' || tmp[k] == (int) '.' || tmp[k] >= 97 && tmp[k] <= (int) 'z') - k--; - k++; - r.version = new String(tmp, k, i - k + 1, "ASCII"); - } - r.type = file.getEntry("META-INF/MANIFEST.MF") == null - ? MinecraftVersionRequest.MODIFIED : MinecraftVersionRequest.OK; - return r; - } - - public static MinecraftVersionRequest minecraftVersion(File file) { - MinecraftVersionRequest r = new MinecraftVersionRequest(); - if (file == null || !file.exists()) { - r.type = MinecraftVersionRequest.NOT_FOUND; - return r; - } - if (!file.isFile()) { - r.type = MinecraftVersionRequest.NOT_FILE; - return r; - } - if (!file.canRead()) { - r.type = MinecraftVersionRequest.UNREADABLE; - return r; - } - ZipFile f = null; - try { - f = new ZipFile(file); - ZipEntry minecraft = f - .getEntry("net/minecraft/client/Minecraft.class"); - if (minecraft != null) - return getVersionOfOldMinecraft(f, minecraft); - ZipEntry main = f.getEntry("net/minecraft/client/main/Main.class"); - ZipEntry minecraftserver = f.getEntry("net/minecraft/server/MinecraftServer.class"); - if ((main != null) && (minecraftserver != null)) - return getVersionOfNewMinecraft(f, minecraftserver); - r.type = MinecraftVersionRequest.INVALID; - return r; - } catch (IOException e) { - HMCLog.warn("Zip file is invalid", e); - r.type = MinecraftVersionRequest.INVALID_JAR; - return r; - } finally { - IOUtils.closeQuietly(f); - } - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Pair.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Pair.java deleted file mode 100644 index 73434805c..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Pair.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util; - -import java.util.Map; -import java.util.Objects; - -/** - * - * @author huangyuhui - * @param K Type - * @param V Type - */ -public class Pair implements Map.Entry { - - public K key; - public V value; - - public Pair(K k, V v) { - key = k; - value = v; - } - - @Override - public K getKey() { - return key; - } - - @Override - public V getValue() { - return value; - } - - @Override - public V setValue(V value) { - V t = this.value; - this.value = value; - return t; - } - - @Override - public int hashCode() { - int hash = 5; - hash = 29 * hash + Objects.hashCode(this.key); - hash = 29 * hash + Objects.hashCode(this.value); - return hash; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - final Pair other = (Pair) obj; - if (!Objects.equals(this.key, other.key)) - return false; - return Objects.equals(this.value, other.value); - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/StrUtils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/StrUtils.java deleted file mode 100644 index 206c12729..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/StrUtils.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util; - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.lang.reflect.Array; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.StringTokenizer; -import org.jackhuang.hmcl.api.func.Function; -import org.jackhuang.hmcl.api.func.Predicate; - -/** - * - * @author huang - */ -public final class StrUtils { - - private StrUtils() { - } - - public static String makeCommand(List cmd) { - StringBuilder cmdbuf = new StringBuilder(120); - for (int i = 0; i < cmd.size(); i++) { - if (i > 0) - cmdbuf.append(' '); - String s = cmd.get(i); - if (s.indexOf(' ') >= 0 || s.indexOf('\t') >= 0) - if (s.charAt(0) != '"') { - cmdbuf.append('"'); - cmdbuf.append(s); - if (s.endsWith("\\")) - cmdbuf.append("\\"); - cmdbuf.append('"'); - } else if (s.endsWith("\"")) - /* - * The argument has already been quoted. - */ - cmdbuf.append(s); - else - /* - * Unmatched quote for the argument. - */ - throw new IllegalArgumentException(); - else - cmdbuf.append(s); - } - String str = cmdbuf.toString(); - - return str; - } - - public static boolean startsWith(String base, String match) { - return base != null && base.startsWith(match); - } - - public static boolean startsWithOne(Collection a, String match) { - if (a == null) - return false; - for (String b : a) - if (startsWith(match, b)) - return true; - return false; - } - - public static boolean equalsOne(String base, String... a) { - for (String s : a) - if (base.equals(s)) - return true; - return false; - } - - public static boolean containsOne(List base, List match, Predicate pred) { - for (String a : base) - for (String b : match) - if (pred.apply(a) && a.toLowerCase().contains(b.toLowerCase())) - return true; - return false; - } - - public static int getCharShowTime(String s, char c) { - int res = 0; - for (int i = 0; i < s.length(); i++) - if (s.charAt(i) == c) - res++; - return res; - } - - public static String formatVersion(String ver) { - if (isBlank(ver)) - return null; - else - for (char ch : ver.toCharArray()) - if ((ch < '0' || ch > '9') && ch != '.') - return null; - int i = getCharShowTime(ver, '.'); - if (i == 1) - return ver + ".0"; - else - return ver; - } - - public static String parseParams(String addBefore, Collection objects, String addAfter) { - return parseParams(addBefore, objects.toArray(), addAfter); - } - - public static String parseParams(String addBefore, Object[] objects, String addAfter) { - return parseParams(t -> addBefore, objects, t -> addAfter); - } - - public static String parseParams(Function beforeFunc, Object[] params, Function afterFunc) { - if (params == null) - return ""; - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < params.length; i++) { - Object param = params[i]; - String addBefore = beforeFunc.apply(param), addAfter = afterFunc.apply(param); - if (i > 0) - sb.append(addAfter).append(addBefore); - if (param == null) - sb.append("null"); - else if (param.getClass().isArray()) { - sb.append("["); - if ((param instanceof Object[])) { - Object[] objs = (Object[]) param; - sb.append(parseParams(beforeFunc, objs, afterFunc)); - } else - for (int j = 0; j < Array.getLength(param); j++) { - if (j > 0) - sb.append(addAfter); - sb.append(addBefore).append(Array.get(param, j)); - } - sb.append("]"); - } else - sb.append(addBefore).append(params[i]); - } - return sb.toString(); - } - - public static String[] tokenize(String paramString1) { - return tokenize(paramString1, " \t\n\r\f"); - } - - public static String[] tokenize(String str, String delim) { - ArrayList al = new ArrayList<>(); - StringTokenizer tokenizer = new StringTokenizer(str, delim); - while (tokenizer.hasMoreTokens()) { - delim = tokenizer.nextToken(); - al.add(delim); - } - - return al.toArray(new String[al.size()]); - } - - public static boolean isBlank(String s) { - return s == null || s.trim().length() <= 0; - } - - public static boolean isNotBlank(String s) { - return !isBlank(s); - } - - public static String getStackTrace(Throwable t) { - StringWriter trace = new StringWriter(); - PrintWriter writer = new PrintWriter(trace); - t.printStackTrace(writer); - return trace.toString(); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/UpdateChecker.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/UpdateChecker.java deleted file mode 100644 index 4cf53e5e2..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/UpdateChecker.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util; - -import org.jackhuang.hmcl.util.ui.MessageBox; -import org.jackhuang.hmcl.api.VersionNumber; -import org.jackhuang.hmcl.api.event.EventHandler; -import org.jackhuang.hmcl.util.net.NetUtils; -import com.google.gson.JsonSyntaxException; -import java.io.IOException; -import org.jackhuang.hmcl.api.HMCLog; -import java.util.Map; -import org.jackhuang.hmcl.api.HMCLApi; -import org.jackhuang.hmcl.api.event.SimpleEvent; -import org.jackhuang.hmcl.api.event.OutOfDateEvent; - -/** - * - * @author huangyuhui - */ -public final class UpdateChecker implements IUpdateChecker { - - private volatile boolean outOfDate = false; - public VersionNumber base; - public String versionString; - public String type; - private Map download_link = null; - - public UpdateChecker(VersionNumber base, String type) { - this.base = base; - this.type = type; - } - - VersionNumber value; - - public boolean isOutOfDate() { - return outOfDate; - } - - @Override - public AbstractSwingWorker process(final boolean showMessage) { - return new AbstractSwingWorker() { - @Override - protected void work() throws Exception { - if (value == null) { - versionString = NetUtils.get("http://huangyuhui.duapp.com/info.php?type=" + type); - value = VersionNumber.check(versionString); - } - - if (value == null) { - HMCLog.warn("Failed to check update..."); - if (showMessage) - MessageBox.show(C.i18n("update.failed")); - } else if (VersionNumber.isOlder(base, value)) - outOfDate = true; - if (outOfDate) - publish(value); - } - }; - } - - @Override - public VersionNumber getNewVersion() { - return value; - } - - @Override - public synchronized AbstractSwingWorker> requestDownloadLink() { - return new AbstractSwingWorker>() { - @Override - protected void work() throws Exception { - if (download_link == null) - try { - download_link = C.GSON.>fromJson(NetUtils.get("http://huangyuhui.duapp.com/update_link.php?type=" + type), Map.class); - } catch (JsonSyntaxException | IOException e) { - HMCLog.warn("Failed to get update link.", e); - } - publish(download_link); - } - }; - } - - public final EventHandler> upgrade = new EventHandler<>(); - - @Override - public void checkOutdate() { - if (outOfDate) - if (HMCLApi.EVENT_BUS.fireChannelResulted(new OutOfDateEvent(this, getNewVersion()))) - upgrade.fire(new SimpleEvent<>(this, getNewVersion())); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Utils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Utils.java deleted file mode 100644 index 0fa4f86b6..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Utils.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util; - -import java.awt.HeadlessException; -import java.awt.Toolkit; -import java.awt.datatransfer.StringSelection; -import java.lang.reflect.Method; -import java.net.URL; -import java.net.URLClassLoader; -import java.security.AccessController; -import java.security.PrivilegedExceptionAction; - -/** - * @author huangyuhui - */ -public final class Utils { - - private Utils() { - } - - public static URL[] getURL() { - return ((URLClassLoader) Utils.class.getClassLoader()).getURLs(); - } - - public static void setClipborad(String text) { - try { - Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(text), null); - } catch(HeadlessException ignored) { - } - } - - /** - * In order to fight against the permission manager by Minecraft Forge. - * - * @param status exit code - */ - public static void shutdownForcely(int status) throws Exception { - AccessController.doPrivileged((PrivilegedExceptionAction) () -> { - Class z = Class.forName("java.lang.Shutdown"); - Method exit = z.getDeclaredMethod("exit", int.class); - exit.setAccessible(true); - exit.invoke(z, status); - return null; - }); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/code/Charsets.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/code/Charsets.java deleted file mode 100644 index f144b4d8e..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/code/Charsets.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.code; - -import java.nio.charset.Charset; -import java.nio.charset.UnsupportedCharsetException; -import org.jackhuang.hmcl.util.sys.IOUtils; - -public final class Charsets { - - private Charsets() { - } - - /*public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1"); - - public static final Charset US_ASCII = Charset.forName("US-ASCII"); - - public static final Charset UTF_16 = Charset.forName("UTF-16"); - - public static final Charset UTF_16BE = Charset.forName("UTF-16BE"); - - public static final Charset UTF_16LE = Charset.forName("UTF-16LE");*/ - - public static final Charset UTF_8 = Charset.forName("UTF-8"); - - public static final Charset DEFAULT_CHARSET = UTF_8; - - public static Charset toCharset(String charset) { - if (charset == null) return Charset.defaultCharset(); - try { - return Charset.forName(charset); - } catch(UnsupportedCharsetException ignored) { - return Charset.defaultCharset(); - } - } - - public static Charset toCharset() { - return toCharset(System.getProperty("sun.jnu.encoding", IOUtils.DEFAULT_CHARSET)); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/code/DigestUtils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/code/DigestUtils.java deleted file mode 100644 index b7f7522c4..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/code/DigestUtils.java +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.code; - -import java.io.IOException; -import java.io.InputStream; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -/** - * - * @author huangyuhui - */ -public final class DigestUtils { - - private DigestUtils() { - } - - private static final int STREAM_BUFFER_LENGTH = 1024; - - private static byte[] digest(MessageDigest digest, InputStream data) - throws IOException { - return updateDigest(digest, data).digest(); - } - - public static MessageDigest getDigest(String algorithm) { - try { - return MessageDigest.getInstance(algorithm); - } catch (NoSuchAlgorithmException e) { - throw new IllegalArgumentException(e); - } - } - - public static MessageDigest getMd2Digest() { - return getDigest("MD2"); - } - - public static MessageDigest getMd5Digest() { - return getDigest("MD5"); - } - - public static MessageDigest getSha1Digest() { - return getDigest("SHA-1"); - } - - public static MessageDigest getSha256Digest() { - return getDigest("SHA-256"); - } - - public static MessageDigest getSha384Digest() { - return getDigest("SHA-384"); - } - - public static MessageDigest getSha512Digest() { - return getDigest("SHA-512"); - } - - public static byte[] md2(byte[] data) { - return getMd2Digest().digest(data); - } - - public static byte[] md2(InputStream data) - throws IOException { - return digest(getMd2Digest(), data); - } - - public static byte[] md2(String data) { - return md2(data.getBytes(Charsets.UTF_8)); - } - - public static String md2Hex(byte[] data) { - return Hex.encodeHexString(md2(data)); - } - - public static String md2Hex(InputStream data) - throws IOException { - return Hex.encodeHexString(md2(data)); - } - - public static String md2Hex(String data) { - return Hex.encodeHexString(md2(data)); - } - - public static byte[] md5(byte[] data) { - return getMd5Digest().digest(data); - } - - public static byte[] md5(InputStream data) - throws IOException { - return digest(getMd5Digest(), data); - } - - public static byte[] md5(String data) { - return md5(data.getBytes(Charsets.UTF_8)); - } - - public static String md5Hex(byte[] data) { - return Hex.encodeHexString(md5(data)); - } - - public static String md5Hex(InputStream data) - throws IOException { - return Hex.encodeHexString(md5(data)); - } - - public static String md5Hex(String data) { - return Hex.encodeHexString(md5(data)); - } - - public static byte[] sha1(byte[] data) { - return getSha1Digest().digest(data); - } - - public static byte[] sha1(InputStream data) - throws IOException { - return digest(getSha1Digest(), data); - } - - public static byte[] sha1(String data) { - return sha1(data.getBytes(Charsets.UTF_8)); - } - - public static String sha1Hex(byte[] data) { - return Hex.encodeHexString(sha1(data)); - } - - public static String sha1Hex(InputStream data) - throws IOException { - return Hex.encodeHexString(sha1(data)); - } - - public static String sha1Hex(String data) { - return Hex.encodeHexString(sha1(data)); - } - - public static byte[] sha256(byte[] data) { - return getSha256Digest().digest(data); - } - - public static byte[] sha256(InputStream data) - throws IOException { - return digest(getSha256Digest(), data); - } - - public static byte[] sha256(String data) { - return sha256(data.getBytes(Charsets.UTF_8)); - } - - public static String sha256Hex(byte[] data) { - return Hex.encodeHexString(sha256(data)); - } - - public static String sha256Hex(InputStream data) - throws IOException { - return Hex.encodeHexString(sha256(data)); - } - - public static String sha256Hex(String data) { - return Hex.encodeHexString(sha256(data)); - } - - public static byte[] sha384(byte[] data) { - return getSha384Digest().digest(data); - } - - public static byte[] sha384(InputStream data) - throws IOException { - return digest(getSha384Digest(), data); - } - - public static byte[] sha384(String data) { - return sha384(data.getBytes(Charsets.UTF_8)); - } - - public static String sha384Hex(byte[] data) { - return Hex.encodeHexString(sha384(data)); - } - - public static String sha384Hex(InputStream data) - throws IOException { - return Hex.encodeHexString(sha384(data)); - } - - public static String sha384Hex(String data) { - return Hex.encodeHexString(sha384(data)); - } - - public static byte[] sha512(byte[] data) { - return getSha512Digest().digest(data); - } - - public static byte[] sha512(InputStream data) - throws IOException { - return digest(getSha512Digest(), data); - } - - public static byte[] sha512(String data) { - return sha512(data.getBytes(Charsets.UTF_8)); - } - - public static String sha512Hex(byte[] data) { - return Hex.encodeHexString(sha512(data)); - } - - public static String sha512Hex(InputStream data) - throws IOException { - return Hex.encodeHexString(sha512(data)); - } - - public static String sha512Hex(String data) { - return Hex.encodeHexString(sha512(data)); - } - - public static MessageDigest updateDigest(MessageDigest messageDigest, byte[] valueToDigest) { - messageDigest.update(valueToDigest); - return messageDigest; - } - - public static MessageDigest updateDigest(MessageDigest digest, InputStream data) - throws IOException { - byte[] buffer = new byte[STREAM_BUFFER_LENGTH]; - int read = data.read(buffer, 0, STREAM_BUFFER_LENGTH); - - while (read > -1) { - digest.update(buffer, 0, read); - read = data.read(buffer, 0, STREAM_BUFFER_LENGTH); - } - - return digest; - } - - public static MessageDigest updateDigest(MessageDigest messageDigest, String valueToDigest) { - messageDigest.update(valueToDigest.getBytes(Charsets.UTF_8)); - return messageDigest; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/code/Hex.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/code/Hex.java deleted file mode 100644 index 380721884..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/code/Hex.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.code; - -import java.nio.charset.Charset; - -public final class Hex { - - private static final char[] DIGITS_LOWER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; - - private static final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - private final Charset charset; - - public static byte[] decodeHex(char[] data) throws Exception { - int len = data.length; - - if ((len & 0x1) != 0) - throw new Exception("Odd number of characters."); - - byte[] out = new byte[len >> 1]; - - int i = 0; - for (int j = 0; j < len; i++) { - int f = toDigit(data[j], j) << 4; - j++; - f |= toDigit(data[j], j); - j++; - out[i] = (byte) (f & 0xFF); - } - - return out; - } - - public static char[] encodeHex(byte[] data) { - return encodeHex(data, true); - } - - public static char[] encodeHex(byte[] data, boolean toLowerCase) { - return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER); - } - - protected static char[] encodeHex(byte[] data, char[] toDigits) { - int l = data.length; - char[] out = new char[l << 1]; - - int i = 0; - for (int j = 0; i < l; i++) { - out[(j++)] = toDigits[((0xF0 & data[i]) >>> 4)]; - out[(j++)] = toDigits[(0xF & data[i])]; - } - return out; - } - - public static String encodeHexString(byte[] data) { - return new String(encodeHex(data)); - } - - protected static int toDigit(char ch, int index) { - int digit = Character.digit(ch, 16); - if (digit == -1) - throw new IllegalArgumentException("Illegal hexadecimal character " + ch + " at index " + index); - return digit; - } - - public Hex() { - this(Charsets.DEFAULT_CHARSET); - } - - public Hex(Charset charset) { - this.charset = charset; - } - - public byte[] decode(byte[] array) throws Exception { - return decodeHex(new String(array, getCharset()).toCharArray()); - } - - public Object decode(Object object) throws Exception { - try { - char[] charArray = (object instanceof String) ? ((String) object).toCharArray() : (char[]) (char[]) object; - return decodeHex(charArray); - } catch (ClassCastException e) { - throw new Exception(e.getMessage(), e); - } - } - - public byte[] encode(byte[] array) { - return encodeHexString(array).getBytes(getCharset()); - } - - public Object encode(Object object) - throws Exception { - try { - byte[] byteArray = (object instanceof String) ? ((String) object).getBytes(getCharset()) : (byte[]) (byte[]) object; - - return encodeHex(byteArray); - } catch (ClassCastException e) { - throw new Exception(e.getMessage(), e); - } - } - - public Charset getCharset() { - return this.charset; - } - - public String getCharsetName() { - return this.charset.name(); - } - - @Override - public String toString() { - return super.toString() + "[charsetName=" + this.charset + "]"; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/lang/Localization.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/lang/Localization.java deleted file mode 100644 index a31adaf9f..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/lang/Localization.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.lang; - -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; -import org.jackhuang.hmcl.util.sys.IOUtils; - -/** - * - * @author huangyuhui - */ -public final class Localization { - - private static final String ROOT_LOCATION = "/org/jackhuang/hmcl/lang/I18N%s.lang"; - - private static final Map INSTANCE = new HashMap<>(); - - private final Map lang = new HashMap<>(); - - private static InputStream getStream(String id) { - return Localization.class.getResourceAsStream(String.format(ROOT_LOCATION, id)); - } - - private Localization(Locale locale) { - InputStream is = getStream("_" + locale.getLanguage() + "_" + locale.getCountry()); - if (is == null) - is = getStream("_" + locale.getLanguage()); - if (is == null) - is = getStream(""); - if (is == null) - throw new InternalError("Language file missing"); - - try { - for (String s : IOUtils.readLines(is, IOUtils.DEFAULT_CHARSET)) - if (!s.isEmpty() && s.charAt(0) != 35) { - int i = s.indexOf('='); - if (i == -1) - continue; - lang.put(s.substring(0, i), s.substring(i + 1)); - } - } catch (IOException ex) { - throw new InternalError("Language file missing", ex); - } - } - - public synchronized String localize(String key) { - String s = lang.get(key); - return s == null ? key : s; - } - - public static Localization get(Locale l) { - if (!INSTANCE.containsKey(l)) - INSTANCE.put(l, new Localization(l)); - return INSTANCE.get(l); - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/lang/SupportedLocales.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/lang/SupportedLocales.java deleted file mode 100644 index 35c5347be..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/lang/SupportedLocales.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.lang; - -import java.util.Locale; - -/** - * - * @author huangyuhui - */ -public enum SupportedLocales { - def(Locale.getDefault(), "lang.default"), - en(Locale.ENGLISH, null), - zh(Locale.TRADITIONAL_CHINESE, null), - zh_CN(Locale.SIMPLIFIED_CHINESE, null), - vi(new Locale("vi"), null), - ru(new Locale("ru"), null); - - public Locale self; - private String showString, customized; - private Localization bundle; - - private SupportedLocales(Locale self, String customized) { - this.self = self; - try { - bundle = Localization.get(self); - showString = bundle.localize("lang"); - this.customized = customized; - } catch (Throwable ignore) { - showString = name(); - } - } - - public String showString() { - if (customized == null) - return showString; - else - return NOW_LOCALE.translate(customized); - } - - private static SupportedLocales NOW_LOCALE = def; - - public static SupportedLocales getNowLocale() { - return NOW_LOCALE; - } - - public static void setNowLocale(SupportedLocales newLocale) { - NOW_LOCALE = newLocale; - } - - public String translate(String key, Object... format) { - try { - return String.format(bundle.localize(key), format); - } catch (Exception ignore) { - return key; - } - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/AppenderControl.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/AppenderControl.java deleted file mode 100644 index 8efc6291f..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/AppenderControl.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.log; - -import org.jackhuang.hmcl.util.log.appender.IAppender; - -public class AppenderControl { - - private final ThreadLocal recursive = new ThreadLocal<>(); - private final IAppender appender; - private final Level level; - private final int intLevel; - - public AppenderControl(IAppender appender, Level level) { - this.appender = appender; - this.level = level; - this.intLevel = (level == null ? Level.ALL.level : level.level); - } - - public IAppender getAppender() { - return this.appender; - } - - public void callAppender(LogEvent event) { - if (this.level != null - && this.intLevel < event.level.level) - return; - - if (this.recursive.get() != null) { - System.err.println("Recursive call to appender " + this.appender.getName()); - return; - } - try { - this.recursive.set(this); - - try { - this.appender.append(event); - } catch (RuntimeException ex) { - System.err.println("An exception occurred processing Appender " + this.appender.getName()); - ex.printStackTrace(); - if (!this.appender.ignoreExceptions()) - throw ex; - } catch (Exception ex) { - System.err.println("An exception occurred processing Appender " + this.appender.getName()); - ex.printStackTrace(); - if (!this.appender.ignoreExceptions()) - throw new LoggingException(ex); - } - } finally { - this.recursive.set(null); - } - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/Configuration.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/Configuration.java deleted file mode 100644 index 8fba84333..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/Configuration.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.log; - -import java.util.ArrayList; -import org.jackhuang.hmcl.util.log.appender.ConsoleAppender; -import org.jackhuang.hmcl.util.log.appender.IAppender; -import org.jackhuang.hmcl.util.log.layout.DefaultLayout; - -/** - * - * @author huangyuhui - */ -public class Configuration { - - public ArrayList appenders = new ArrayList<>(); - - public static final Configuration DEFAULT; - - static { - DEFAULT = new Configuration(); - DEFAULT.appenders.add(new ConsoleAppender("Console", new DefaultLayout(), true, new ConsoleAppender.SystemOutStream(), true)); - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/Level.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/Level.java deleted file mode 100644 index 1ad696266..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/Level.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.log; - -import java.awt.Color; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * - * @author huangyuhui - */ -public enum Level { - - FATAL(1, Color.red), - ERROR(2, Color.red), - WARN(3, Color.orange), - INFO(4, Color.black), - DEBUG(5, Color.blue), - TRACE(6, Color.blue), - ALL(2147483647, Color.black); - - public final int level; - public final Color COLOR; - - private Level(int i, Color c) { - level = i; - COLOR = c; - } - - public boolean lessOrEqual(Level level) { - return this.level <= level.level; - } - - public static final Pattern MINECRAFT_LOGGER = Pattern.compile("\\[(?[0-9:]+)\\] \\[[^/]+/(?[^\\]]+)\\]"); - public static final Pattern MINECRAFT_LOGGER_CATEGORY = Pattern.compile("\\[(?[0-9:]+)\\] \\[[^/]+/(?[^\\]]+)\\] \\[(?[^\\]]+)\\]"); - public static final String JAVA_SYMBOL = "([a-zA-Z_$][a-zA-Z\\d_$]*\\.)+[a-zA-Z_$][a-zA-Z\\d_$]*"; - - public static Level guessLevel(String line) { - Level level = null; - Matcher m = MINECRAFT_LOGGER.matcher(line); - if (m.find()) { - // New style logs from log4j - String levelStr = m.group("level"); - if (null != levelStr) - switch (levelStr) { - case "INFO": - level = INFO; - break; - case "WARN": - level = WARN; - break; - case "ERROR": - level = ERROR; - break; - case "FATAL": - level = FATAL; - break; - case "TRACE": - level = TRACE; - break; - case "DEBUG": - level = DEBUG; - break; - default: - break; - } - Matcher m2 = MINECRAFT_LOGGER_CATEGORY.matcher(line); - if (m2.find()) { - String level2Str = m2.group("category"); - if (null != level2Str) - switch (level2Str) { - case "STDOUT": - level = INFO; - break; - case "STDERR": - level = ERROR; - break; - } - } - } else { - if (line.contains("[INFO]") || line.contains("[CONFIG]") || line.contains("[FINE]") - || line.contains("[FINER]") || line.contains("[FINEST]")) - level = INFO; - if (line.contains("[SEVERE]") || line.contains("[STDERR]")) - level = ERROR; - if (line.contains("[WARNING]")) - level = WARN; - if (line.contains("[DEBUG]")) - level = DEBUG; - } - if (line.contains("overwriting existing")) - return FATAL; - - /*if (line.contains("Exception in thread") - || line.matches("\\s+at " + JAVA_SYMBOL) - || line.matches("Caused by: " + JAVA_SYMBOL) - || line.matches("([a-zA-Z_$][a-zA-Z\\d_$]*\\.)+[a-zA-Z_$]?[a-zA-Z\\d_$]*(Exception|Error|Throwable)") - || line.matches("... \\d+ more$")) - return ERROR;*/ - return level; - } - - public static boolean isError(Level a) { - return a == null ? false : a.lessOrEqual(Level.ERROR); - } - - public static Level mergeLevel(Level a, Level b) { - if (a == null) return b; - else if (b == null) return a; - else return a.level < b.level ? a : b; - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/LogEvent.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/LogEvent.java deleted file mode 100644 index 5a9851fac..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/LogEvent.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.log; - -import org.jackhuang.hmcl.util.log.message.IMessage; - -/** - * - * @author huangyuhui - */ -public class LogEvent { - - public Level level; - public String threadName; - public Throwable thrown; - public IMessage message; - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/LoggingException.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/LoggingException.java deleted file mode 100644 index 0bee11c30..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/LoggingException.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.log; - -/** - * - * @author huangyuhui - */ -public class LoggingException extends RuntimeException { - - public LoggingException(Exception e) { - super(e); - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/appender/AbstractAppender.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/appender/AbstractAppender.java deleted file mode 100644 index feb8b71e3..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/appender/AbstractAppender.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.log.appender; - -import java.io.Serializable; -import org.jackhuang.hmcl.util.log.layout.ILayout; - -/** - * - * @author huangyuhui - */ -public abstract class AbstractAppender implements IAppender { - - String name; - private final ILayout layout; - private final boolean ignoreExceptions; - - public AbstractAppender(String name, ILayout layout) { - this(name, layout, true); - } - - public AbstractAppender(String name, ILayout layout, boolean ignoreExceptions) { - this.name = name; - this.layout = layout; - this.ignoreExceptions = ignoreExceptions; - } - - @Override - public String getName() { - return name; - } - - @Override - public boolean ignoreExceptions() { - return ignoreExceptions; - } - - @Override - public ILayout getLayout() { - return this.layout; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/appender/ConsoleAppender.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/appender/ConsoleAppender.java deleted file mode 100644 index 15496d524..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/appender/ConsoleAppender.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.log.appender; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.Serializable; -import org.jackhuang.hmcl.util.log.layout.ILayout; - -/** - * - * @author huangyuhui - */ -public class ConsoleAppender extends OutputStreamAppender { - - public ConsoleAppender(String name, ILayout layout, boolean ignoreExceptions, OutputStream stream, boolean immediateFlush) { - super(name, layout, ignoreExceptions, stream, true); - } - - public static class SystemOutStream extends OutputStream { - - @Override - public void close() { - } - - @Override - public void flush() { - System.out.flush(); - } - - @Override - public void write(byte[] b) throws IOException { - System.out.write(b); - } - - @Override - public void write(byte[] b, int off, int len) - throws IOException { - System.out.write(b, off, len); - } - - @Override - public void write(int b) throws IOException { - System.out.write(b); - } - } - - public static class SystemErrStream extends OutputStream { - - @Override - public void close() { - } - - @Override - public void flush() { - System.err.flush(); - } - - @Override - public void write(byte[] b) throws IOException { - System.err.write(b); - } - - @Override - public void write(byte[] b, int off, int len) - throws IOException { - System.err.write(b, off, len); - } - - @Override - public void write(int b) { - System.err.write(b); - } - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/appender/IAppender.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/appender/IAppender.java deleted file mode 100644 index bef4b223c..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/appender/IAppender.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.log.appender; - -import java.io.Serializable; -import org.jackhuang.hmcl.util.log.LogEvent; -import org.jackhuang.hmcl.util.log.layout.ILayout; - -/** - * - * @author huangyuhui - */ -public interface IAppender { - - void append(LogEvent event); - - String getName(); - - boolean ignoreExceptions(); - - ILayout getLayout(); - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/appender/OutputStreamAppender.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/appender/OutputStreamAppender.java deleted file mode 100644 index 5f0957153..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/appender/OutputStreamAppender.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.log.appender; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintStream; -import java.io.Serializable; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantReadWriteLock; -import org.jackhuang.hmcl.util.log.LogEvent; -import org.jackhuang.hmcl.util.log.LoggingException; -import org.jackhuang.hmcl.util.log.layout.ILayout; - -/** - * - * @author huangyuhui - */ -public abstract class OutputStreamAppender extends AbstractAppender { - - protected final OutputStream stream; - protected final boolean immediateFlush; - private final Lock readLock = new ReentrantReadWriteLock().readLock(); - - public OutputStreamAppender(String name, ILayout layout, boolean ignoreExceptions, OutputStream stream, boolean immediateFlush) { - super(name, layout, ignoreExceptions); - - this.immediateFlush = immediateFlush; - this.stream = stream; - } - - @Override - public void append(LogEvent event) { - this.readLock.lock(); - try { - byte[] bytes = getLayout().toByteArray(event); - if (bytes.length > 0) - stream.write(bytes); - if (event.thrown != null) - event.thrown.printStackTrace(new PrintStream(stream)); - } catch (IOException ex) { - System.err.println("Unable to write to stream for appender: " + getName()); - throw new LoggingException(ex); - } finally { - this.readLock.unlock(); - } - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/layout/AbstractStringLayout.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/layout/AbstractStringLayout.java deleted file mode 100644 index e4e970a02..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/layout/AbstractStringLayout.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.log.layout; - -import org.jackhuang.hmcl.util.log.LogEvent; - -/** - * - * @author huangyuhui - */ -public abstract class AbstractStringLayout implements ILayout { - - @Override - public byte[] toByteArray(LogEvent event) { - return toSerializable(event).getBytes(); - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/layout/DefaultLayout.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/layout/DefaultLayout.java deleted file mode 100644 index 1e59c708a..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/layout/DefaultLayout.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.log.layout; - -import java.text.SimpleDateFormat; -import java.util.Date; -import org.jackhuang.hmcl.util.log.LogEvent; - -/** - * - * @author huangyuhui - */ -public class DefaultLayout extends AbstractStringLayout { - - private static final SimpleDateFormat SDF = new SimpleDateFormat("HH:mm:ss"); - - @Override - public String toSerializable(LogEvent event) { - return "[" + SDF.format(new Date()) + "] [" + event.threadName + "/" + event.level.name() + "] " + event.message.getFormattedMessage() + "\n"; - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/layout/ILayout.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/layout/ILayout.java deleted file mode 100644 index 69a0b1749..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/layout/ILayout.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.log.layout; - -import java.io.Serializable; -import org.jackhuang.hmcl.util.log.LogEvent; - -/** - * - * @author huangyuhui - * @param - */ -public interface ILayout { - - byte[] toByteArray(LogEvent event); - - T toSerializable(LogEvent event); - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/logger/AbstractLogger.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/logger/AbstractLogger.java deleted file mode 100644 index c99359106..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/logger/AbstractLogger.java +++ /dev/null @@ -1,396 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.log.logger; - -import org.jackhuang.hmcl.util.log.Level; -import org.jackhuang.hmcl.util.log.message.IMessage; -import org.jackhuang.hmcl.util.log.message.IMessageFactory; -import org.jackhuang.hmcl.util.log.message.ParameterizedMessageFactory; -import org.jackhuang.hmcl.util.log.message.StringFormattedMessage; - -public abstract class AbstractLogger - implements ILogger { - - public static final Class DEFAULT_MESSAGE_FACTORY_CLASS = ParameterizedMessageFactory.class; - - private static final String THROWING = "throwing"; - private static final String CATCHING = "catching"; - private final String name; - private final IMessageFactory messageFactory; - - public AbstractLogger() { - this.name = getClass().getName(); - this.messageFactory = createDefaultMessageFactory(); - } - - public AbstractLogger(String name) { - this.name = name; - this.messageFactory = createDefaultMessageFactory(); - } - - public AbstractLogger(String name, IMessageFactory messageFactory) { - this.name = name; - this.messageFactory = (messageFactory == null ? createDefaultMessageFactory() : messageFactory); - } - - private IMessageFactory createDefaultMessageFactory() { - try { - return (IMessageFactory) DEFAULT_MESSAGE_FACTORY_CLASS.newInstance(); - } catch (InstantiationException | IllegalAccessException e) { - throw new IllegalStateException(e); - } - } - - @Override - public void catching(Level level, Throwable t) { - if (isEnabled(level, (Object) null, null)) - log(level, this.messageFactory.newMessage(CATCHING), t); - } - - @Override - public void catching(Throwable t) { - catching(Level.ERROR, t); - } - - @Override - public void entry() { - entry(new Object[0]); - } - - @Override - public void entry(Object[] params) { - if (isEnabled(Level.TRACE, (Object) null, null)) - log(Level.TRACE, entryMsg(params.length, params), null); - } - - private IMessage entryMsg(int count, Object[] params) { - if (count == 0) - return this.messageFactory.newMessage("entry"); - StringBuilder sb = new StringBuilder("entry params("); - int i = 0; - for (Object parm : params) { - if (parm != null) - sb.append(parm.toString()); - else - sb.append("null"); - i++; - if (i < params.length) - sb.append(", "); - } - sb.append(")"); - return this.messageFactory.newMessage(sb.toString()); - } - - @Override - public void error(IMessage msg) { - if (isEnabled(Level.ERROR, msg, null)) - log(Level.ERROR, msg, null); - } - - @Override - public void error(IMessage msg, Throwable t) { - if (isEnabled(Level.ERROR, msg, t)) - log(Level.ERROR, msg, t); - } - - @Override - public void error(Object message) { - if (isEnabled(Level.ERROR, message, null)) - log(Level.ERROR, this.messageFactory.newMessage(message), null); - } - - @Override - public void error(Object message, Throwable t) { - if (isEnabled(Level.ERROR, message, t)) - log(Level.ERROR, this.messageFactory.newMessage(message), t); - } - - @Override - public void error(String message) { - if (isEnabled(Level.ERROR, message)) - log(Level.ERROR, this.messageFactory.newMessage(message), null); - } - - @Override - public void error(String message, Object[] params) { - if (isEnabled(Level.ERROR, message, params)) { - IMessage msg = this.messageFactory.newMessage(message, params); - log(Level.ERROR, msg, msg.getThrowable()); - } - } - - @Override - public void error(String message, Throwable t) { - if (isEnabled(Level.ERROR, message, t)) - log(Level.ERROR, this.messageFactory.newMessage(message), t); - } - - @Override - public void fatal(IMessage msg) { - if (isEnabled(Level.FATAL, msg, null)) - log(Level.FATAL, msg, null); - } - - @Override - public void fatal(IMessage msg, Throwable t) { - if (isEnabled(Level.FATAL, msg, t)) - log(Level.FATAL, msg, t); - } - - @Override - public void fatal(Object message) { - if (isEnabled(Level.FATAL, message, null)) - log(Level.FATAL, this.messageFactory.newMessage(message), null); - } - - @Override - public void fatal(Object message, Throwable t) { - if (isEnabled(Level.FATAL, message, t)) - log(Level.FATAL, this.messageFactory.newMessage(message), t); - } - - @Override - public void fatal(String message) { - if (isEnabled(Level.FATAL, message)) - log(Level.FATAL, this.messageFactory.newMessage(message), null); - } - - @Override - public void fatal(String message, Object[] params) { - if (isEnabled(Level.FATAL, message, params)) { - IMessage msg = this.messageFactory.newMessage(message, params); - log(Level.FATAL, msg, msg.getThrowable()); - } - } - - @Override - public void fatal(String message, Throwable t) { - if (isEnabled(Level.FATAL, message, t)) - log(Level.FATAL, this.messageFactory.newMessage(message), t); - } - - @Override - public String getName() { - return this.name; - } - - @Override - public void info(IMessage msg) { - if (isEnabled(Level.INFO, msg, null)) - log(Level.INFO, msg, null); - } - - @Override - public void info(IMessage msg, Throwable t) { - if (isEnabled(Level.INFO, msg, t)) - log(Level.INFO, msg, t); - } - - @Override - public void info(Object message) { - if (isEnabled(Level.INFO, message, null)) - log(Level.INFO, this.messageFactory.newMessage(message), null); - } - - @Override - public void info(Object message, Throwable t) { - if (isEnabled(Level.INFO, message, t)) - log(Level.INFO, this.messageFactory.newMessage(message), t); - } - - @Override - public void info(String message) { - if (isEnabled(Level.INFO, message)) - log(Level.INFO, this.messageFactory.newMessage(message), null); - } - - @Override - public void info(String message, Object[] params) { - if (isEnabled(Level.INFO, message, params)) { - IMessage msg = this.messageFactory.newMessage(message, params); - log(Level.INFO, msg, msg.getThrowable()); - } - } - - @Override - public void info(String message, Throwable t) { - if (isEnabled(Level.INFO, message, t)) - log(Level.INFO, this.messageFactory.newMessage(message), t); - } - - protected abstract boolean isEnabled(Level paramLevel, IMessage paramIMessage, Throwable paramThrowable); - - protected abstract boolean isEnabled(Level paramLevel, Object paramObject, Throwable paramThrowable); - - protected abstract boolean isEnabled(Level paramLevel, String paramString); - - protected abstract boolean isEnabled(Level paramLevel, String paramString, Object[] paramArrayOfObject); - - protected abstract boolean isEnabled(Level paramLevel, String paramString, Throwable paramThrowable); - - protected abstract void abstractLog(Level level, IMessage msg, Throwable t); - - @Override - public boolean isErrorEnabled() { - return isEnabled(Level.ERROR); - } - - @Override - - public boolean isFatalEnabled() { - return isEnabled(Level.FATAL); - } - - @Override - public boolean isInfoEnabled() { - return isEnabled(Level.INFO); - } - - @Override - public boolean isTraceEnabled() { - return isEnabled(Level.TRACE); - } - - @Override - public boolean isWarnEnabled() { - return isEnabled(Level.WARN); - } - - @Override - public boolean isDebugEnabled() { - return isEnabled(Level.DEBUG); - } - - @Override - public boolean isEnabled(Level level) { - return isEnabled(level, (Object) null, null); - } - - @Override - public void log(Level level, IMessage msg) { - if (isEnabled(level, msg, null)) - log(level, msg, null); - } - - @Override - public void log(Level level, IMessage msg, Throwable t) { - if (isEnabled(level, msg, t)) - abstractLog(level, msg, t); - } - - @Override - public void log(Level level, Object message) { - if (isEnabled(level, message, null)) - log(level, this.messageFactory.newMessage(message), null); - } - - @Override - public void log(Level level, Object message, Throwable t) { - if (isEnabled(level, message, t)) - log(level, this.messageFactory.newMessage(message), t); - } - - @Override - public void log(Level level, String message) { - if (isEnabled(level, message)) - log(level, this.messageFactory.newMessage(message), null); - } - - @Override - public void log(Level level, String message, Object[] params) { - if (isEnabled(level, message, params)) { - IMessage msg = this.messageFactory.newMessage(message, params); - log(level, msg, msg.getThrowable()); - } - } - - @Override - public void log(Level level, String message, Throwable t) { - if (isEnabled(level, message, t)) - log(level, this.messageFactory.newMessage(message), t); - } - - @Override - public void printf(Level level, String format, Object[] params) { - if (isEnabled(level, format, params)) { - IMessage msg = new StringFormattedMessage(format, params); - log(level, msg, msg.getThrowable()); - } - } - - @Override - public T throwing(T t) { - return throwing(Level.ERROR, t); - } - - @Override - public T throwing(Level level, T t) { - if (isEnabled(level, (Object) null, null)) - log(level, this.messageFactory.newMessage(THROWING), t); - return t; - } - - @Override - public String toString() { - return this.name; - } - - @Override - public void warn(IMessage msg) { - if (isEnabled(Level.WARN, msg, null)) - log(Level.WARN, msg, null); - } - - @Override - public void warn(IMessage msg, Throwable t) { - if (isEnabled(Level.WARN, msg, t)) - log(Level.WARN, msg, t); - } - - @Override - public void warn(Object message) { - if (isEnabled(Level.WARN, message, null)) - log(Level.WARN, this.messageFactory.newMessage(message), null); - } - - @Override - public void warn(Object message, Throwable t) { - if (isEnabled(Level.WARN, message, t)) - log(Level.WARN, this.messageFactory.newMessage(message), t); - } - - @Override - public void warn(String message) { - if (isEnabled(Level.WARN, message)) - log(Level.WARN, this.messageFactory.newMessage(message), null); - } - - @Override - public void warn(String message, Object[] params) { - if (isEnabled(Level.WARN, message, params)) { - IMessage msg = this.messageFactory.newMessage(message, params); - log(Level.WARN, msg, msg.getThrowable()); - } - } - - @Override - public void warn(String message, Throwable t) { - if (isEnabled(Level.WARN, message, t)) - log(Level.WARN, this.messageFactory.newMessage(message), t); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/logger/ILogger.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/logger/ILogger.java deleted file mode 100644 index bb4624d0a..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/logger/ILogger.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.log.logger; - -import org.jackhuang.hmcl.util.log.Level; -import org.jackhuang.hmcl.util.log.message.IMessage; - -/** - * - * @author huangyuhui - */ -public interface ILogger { - - void catching(Level paramLevel, Throwable paramThrowable); - - void catching(Throwable paramThrowable); - - void entry(); - - void entry(Object[] paramArrayOfObject); - - void error(IMessage paramIMessage); - - void error(IMessage paramIMessage, Throwable paramThrowable); - - void error(Object paramObject); - - void error(Object paramObject, Throwable paramThrowable); - - void error(String paramString); - - void error(String paramString, Object[] paramArrayOfObject); - - void error(String paramString, Throwable paramThrowable); - - void fatal(IMessage paramIMessage); - - void fatal(IMessage paramIMessage, Throwable paramThrowable); - - void fatal(Object paramObject); - - void fatal(Object paramObject, Throwable paramThrowable); - - void fatal(String paramString); - - void fatal(String paramString, Object[] paramArrayOfObject); - - void fatal(String paramString, Throwable paramThrowable); - - String getName(); - - void info(IMessage paramIMessage); - - void info(IMessage paramIMessage, Throwable paramThrowable); - - void info(Object paramObject); - - void info(Object paramObject, Throwable paramThrowable); - - void info(String paramString); - - void info(String paramString, Object[] paramArrayOfObject); - - void info(String paramString, Throwable paramThrowable); - - boolean isDebugEnabled(); - - boolean isEnabled(Level paramLevel); - - boolean isErrorEnabled(); - - boolean isFatalEnabled(); - - boolean isInfoEnabled(); - - boolean isTraceEnabled(); - - boolean isWarnEnabled(); - - void log(Level paramLevel, IMessage paramIMessage); - - void log(Level paramLevel, IMessage paramIMessage, Throwable paramThrowable); - - void log(Level paramLevel, Object paramObject); - - void log(Level paramLevel, Object paramObject, Throwable paramThrowable); - - void log(Level paramLevel, String paramString); - - void log(Level paramLevel, String paramString, Object[] paramArrayOfObject); - - void log(Level paramLevel, String paramString, Throwable paramThrowable); - - void printf(Level paramLevel, String paramString, Object[] paramArrayOfObject); - - T throwing(Level paramLevel, T paramT); - - T throwing(T paramT); - - void warn(IMessage paramIMessage); - - void warn(IMessage paramIMessage, Throwable paramThrowable); - - void warn(Object paramObject); - - void warn(Object paramObject, Throwable paramThrowable); - - void warn(String paramString); - - void warn(String paramString, Object[] paramArrayOfObject); - - void warn(String paramString, Throwable paramThrowable); - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/logger/Logger.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/logger/Logger.java deleted file mode 100644 index ff9a00ef5..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/logger/Logger.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.log.logger; - -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import org.jackhuang.hmcl.util.log.AppenderControl; -import org.jackhuang.hmcl.util.log.Configuration; -import org.jackhuang.hmcl.util.log.Level; -import org.jackhuang.hmcl.util.log.LogEvent; -import org.jackhuang.hmcl.util.log.appender.IAppender; -import org.jackhuang.hmcl.util.log.message.IMessage; -import org.jackhuang.hmcl.util.log.message.IMessageFactory; - -public class Logger extends AbstractLogger { - - protected volatile PrivateConfig config; - private final Map appenders = new ConcurrentHashMap<>(); - - public Logger(String name) { - this(name, null, Level.INFO); - } - - public Logger(String name, IMessageFactory messageFactory, Level defaultLevel) { - this(name, Configuration.DEFAULT, messageFactory, defaultLevel); - } - - public Logger(String name, Configuration config, IMessageFactory messageFactory, Level defaultLevel) { - super(name, messageFactory); - this.config = new PrivateConfig(config, this, defaultLevel); - } - - public synchronized void setLevel(Level level) { - if (level != null) - this.config = new PrivateConfig(this.config, level); - } - - public synchronized Level getLevel() { - return this.config.level; - } - - @Override - public void abstractLog(Level level, IMessage data, Throwable t) { - LogEvent event = new LogEvent(); - event.level = level; - event.message = data; - event.thrown = t; - event.threadName = Thread.currentThread().getName(); - - log(event); - } - - public void log(LogEvent event) { - callAppenders(event); - } - - protected void callAppenders(LogEvent event) { - for (AppenderControl control : this.appenders.values()) - control.callAppender(event); - } - - @Override - public boolean isEnabled(Level level, String msg) { - return this.config.filter(level, msg); - } - - @Override - public boolean isEnabled(Level level, String msg, Throwable t) { - return this.config.filter(level, msg, t); - } - - @Override - public boolean isEnabled(Level level, String msg, Object[] p1) { - return this.config.filter(level, msg, p1); - } - - @Override - public boolean isEnabled(Level level, Object msg, Throwable t) { - return this.config.filter(level, msg, t); - } - - @Override - public boolean isEnabled(Level level, IMessage msg, Throwable t) { - return this.config.filter(level, msg, t); - } - - public void addAppender(IAppender appender) { - this.appenders.put(appender.getName(), new AppenderControl(appender, null)); - } - - public void removeAppender(IAppender appender) { - this.appenders.remove(appender.getName()); - } - - public Map getAppenders() { - Map map = new HashMap<>(); - for (Map.Entry entry : this.appenders.entrySet()) - map.put(entry.getKey(), ((AppenderControl) entry.getValue()).getAppender()); - return map; - } - - @Override - public String toString() { - String nameLevel = "" + getName() + ":" + getLevel(); - return nameLevel; - } - - protected class PrivateConfig { - - public final Configuration config; - private final Level level; - private final int intLevel; - private final Logger logger; - - public PrivateConfig(Configuration c, Logger logger, Level level) { - this.level = level; - this.intLevel = this.level.level; - this.logger = logger; - - this.config = c; - for (IAppender appender : config.appenders) - addAppender(appender); - } - - public PrivateConfig(PrivateConfig pc, Level level) { - this(pc.config, pc.logger, level); - } - - boolean filter(Level level, String msg) { - return this.intLevel >= level.level; - } - - boolean filter(Level level, String msg, Throwable t) { - return this.intLevel >= level.level; - } - - boolean filter(Level level, String msg, Object[] p1) { - return this.intLevel >= level.level; - } - - boolean filter(Level level, Object msg, Throwable t) { - return this.intLevel >= level.level; - } - - boolean filter(Level level, IMessage msg, Throwable t) { - return this.intLevel >= level.level; - } - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/message/AbstractMessageFactory.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/message/AbstractMessageFactory.java deleted file mode 100644 index b1b599f24..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/message/AbstractMessageFactory.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.log.message; - -/** - * - * @author huangyuhui - */ -public abstract class AbstractMessageFactory - implements IMessageFactory { - - @Override - public IMessage newMessage(Object message) { - return new ObjectMessage(message); - } - - @Override - public IMessage newMessage(String message) { - return new SimpleMessage(message); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/message/IMessage.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/message/IMessage.java deleted file mode 100644 index 7db79f14f..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/message/IMessage.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.log.message; - -import java.io.Serializable; - -/** - * - * @author huangyuhui - */ -public interface IMessage extends Serializable { - - String getFormattedMessage(); - - String getFormat(); - - Object[] getParameters(); - - Throwable getThrowable(); -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/message/IMessageFactory.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/message/IMessageFactory.java deleted file mode 100644 index 054606ffb..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/message/IMessageFactory.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.log.message; - -/** - * - * @author huangyuhui - */ -public abstract interface IMessageFactory { - - public abstract IMessage newMessage(Object paramObject); - - public abstract IMessage newMessage(String paramString); - - public abstract IMessage newMessage(String paramString, Object[] paramArrayOfObject); -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/message/ObjectMessage.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/message/ObjectMessage.java deleted file mode 100644 index 2b138b56e..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/message/ObjectMessage.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.log.message; - -public class ObjectMessage - implements IMessage { - - private static final long serialVersionUID = -5903272448334166185L; - private final Object obj; - - public ObjectMessage(Object obj) { - if (obj == null) - obj = "null"; - this.obj = obj; - } - - @Override - public String getFormattedMessage() { - return this.obj.toString(); - } - - @Override - public String getFormat() { - return this.obj.toString(); - } - - @Override - public Object[] getParameters() { - return new Object[] { this.obj }; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if ((o == null) || (getClass() != o.getClass())) - return false; - - ObjectMessage that = (ObjectMessage) o; - - return this.obj != null ? this.obj.equals(that.obj) : that.obj == null; - } - - @Override - public int hashCode() { - return this.obj != null ? this.obj.hashCode() : 0; - } - - @Override - public String toString() { - return "ObjectMessage[obj=" + this.obj.toString() + "]"; - } - - @Override - public Throwable getThrowable() { - return (this.obj instanceof Throwable) ? (Throwable) this.obj : null; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/message/ParameterizedMessage.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/message/ParameterizedMessage.java deleted file mode 100644 index 78925ab82..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/message/ParameterizedMessage.java +++ /dev/null @@ -1,356 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.log.message; - -import java.text.SimpleDateFormat; -import java.util.Arrays; -import java.util.Collection; -import java.util.Date; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -/** - * - * @author huangyuhui - */ -public class ParameterizedMessage - implements IMessage { - - public static final String RECURSION_PREFIX = "[..."; - public static final String RECURSION_SUFFIX = "...]"; - public static final String ERROR_PREFIX = "[!!!"; - public static final String ERROR_SEPARATOR = "=>"; - public static final String ERROR_MSG_SEPARATOR = ":"; - public static final String ERROR_SUFFIX = "!!!]"; - private static final long serialVersionUID = -665975803997290697L; - private static final int HASHVAL = 31; - private static final char DELIM_START = '{'; - private static final char DELIM_STOP = '}'; - private static final char ESCAPE_CHAR = '\\'; - private final String messagePattern; - private final String[] stringArgs; - private transient Object[] argArray; - private transient String formattedMessage; - private transient Throwable throwable; - - public ParameterizedMessage(String messagePattern, String[] stringArgs, Throwable throwable) { - this.messagePattern = messagePattern; - this.stringArgs = stringArgs; - this.throwable = throwable; - } - - public ParameterizedMessage(String messagePattern, Object[] objectArgs, Throwable throwable) { - this.messagePattern = messagePattern; - this.throwable = throwable; - this.stringArgs = parseArguments(objectArgs); - } - - public ParameterizedMessage(String messagePattern, Object[] arguments) { - this.messagePattern = messagePattern; - this.stringArgs = parseArguments(arguments); - } - - public ParameterizedMessage(String messagePattern, Object arg) { - this(messagePattern, new Object[] { arg }); - } - - public ParameterizedMessage(String messagePattern, Object arg1, Object arg2) { - this(messagePattern, new Object[] { arg1, arg2 }); - } - - private String[] parseArguments(Object[] arguments) { - if (arguments == null) - return null; - int argsCount = countArgumentPlaceholders(this.messagePattern); - int resultArgCount = arguments.length; - if ((argsCount < arguments.length) - && (this.throwable == null) && ((arguments[(arguments.length - 1)] instanceof Throwable))) { - this.throwable = ((Throwable) arguments[(arguments.length - 1)]); - resultArgCount--; - } - - this.argArray = new Object[resultArgCount]; - System.arraycopy(arguments, 0, this.argArray, 0, resultArgCount); - String[] strArgs; - if ((argsCount == 1) && (this.throwable == null) && (arguments.length > 1)) { - strArgs = new String[1]; - strArgs[0] = deepToString(arguments); - } else { - strArgs = new String[resultArgCount]; - for (int i = 0; i < strArgs.length; i++) - strArgs[i] = deepToString(arguments[i]); - } - return strArgs; - } - - @Override - public String getFormattedMessage() { - if (this.formattedMessage == null) - this.formattedMessage = formatMessage(this.messagePattern, this.stringArgs); - return this.formattedMessage; - } - - @Override - public String getFormat() { - return this.messagePattern; - } - - @Override - public Object[] getParameters() { - if (this.argArray != null) - return this.argArray; - return this.stringArgs; - } - - @Override - public Throwable getThrowable() { - return this.throwable; - } - - protected String formatMessage(String msgPattern, String[] sArgs) { - return format(msgPattern, sArgs); - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; - - ParameterizedMessage that = (ParameterizedMessage) o; - if (this.messagePattern != null ? !this.messagePattern.equals(that.messagePattern) : that.messagePattern != null) - return false; - - return Arrays.equals(this.stringArgs, that.stringArgs); - } - - @Override - public int hashCode() { - int result = this.messagePattern != null ? this.messagePattern.hashCode() : 0; - result = HASHVAL * result + (this.stringArgs != null ? Arrays.hashCode(this.stringArgs) : 0); - return result; - } - - public static String format(String messagePattern, Object[] arguments) { - if ((messagePattern == null) || (arguments == null) || (arguments.length == 0)) - return messagePattern; - - StringBuilder result = new StringBuilder(); - int escapeCounter = 0; - int currentArgument = 0; - for (int i = 0; i < messagePattern.length(); i++) { - char curChar = messagePattern.charAt(i); - if (curChar == ESCAPE_CHAR) - escapeCounter++; - else if ((curChar == DELIM_START) - && (i < messagePattern.length() - 1) - && (messagePattern.charAt(i + 1) == DELIM_STOP)) { - int escapedEscapes = escapeCounter / 2; - for (int j = 0; j < escapedEscapes; j++) - result.append(ESCAPE_CHAR); - - if (escapeCounter % 2 == 1) { - result.append(DELIM_START); - result.append(DELIM_STOP); - } else { - if (currentArgument < arguments.length) - result.append(arguments[currentArgument]); - else - result.append(DELIM_START).append(DELIM_STOP); - currentArgument++; - } - i++; - escapeCounter = 0; - } else { - if (escapeCounter > 0) { - for (int j = 0; j < escapeCounter; j++) - result.append(ESCAPE_CHAR); - escapeCounter = 0; - } - result.append(curChar); - } - } - return result.toString(); - } - - public static int countArgumentPlaceholders(String messagePattern) { - if (messagePattern == null) - return 0; - - int delim = messagePattern.indexOf(123); - - if (delim == -1) - return 0; - int result = 0; - boolean isEscaped = false; - for (int i = 0; i < messagePattern.length(); i++) { - char curChar = messagePattern.charAt(i); - switch (curChar) { - case ESCAPE_CHAR: - isEscaped = !isEscaped; - break; - case DELIM_START: - if ((!isEscaped) - && (i < messagePattern.length() - 1) - && (messagePattern.charAt(i + 1) == DELIM_STOP)) { - result++; - i++; - } - isEscaped = false; - break; - default: - isEscaped = false; - break; - } - } - return result; - } - - public static String deepToString(Object o) { - if (o == null) - return null; - if (o instanceof String) - return (String) o; - StringBuilder str = new StringBuilder(); - Set dejaVu = new HashSet<>(); - recursiveDeepToString(o, str, dejaVu); - return str.toString(); - } - - private static void recursiveDeepToString(Object o, StringBuilder str, Set dejaVu) { - if (o == null) { - str.append("null"); - return; - } - if ((o instanceof String)) { - str.append(o); - return; - } - Class oClass = o.getClass(); - if (oClass.isArray()) - if (oClass == byte[].class) - str.append(Arrays.toString((byte[]) (byte[]) o)); - else if (oClass == short[].class) - str.append(Arrays.toString((short[]) (short[]) o)); - else if (oClass == int[].class) - str.append(Arrays.toString((int[]) (int[]) o)); - else if (oClass == long[].class) - str.append(Arrays.toString((long[]) (long[]) o)); - else if (oClass == float[].class) - str.append(Arrays.toString((float[]) (float[]) o)); - else if (oClass == double[].class) - str.append(Arrays.toString((double[]) (double[]) o)); - else if (oClass == boolean[].class) - str.append(Arrays.toString((boolean[]) (boolean[]) o)); - else if (oClass == char[].class) - str.append(Arrays.toString((char[]) (char[]) o)); - else { - String id = identityToString(o); - if (dejaVu.contains(id)) - str.append(RECURSION_PREFIX).append(id).append(RECURSION_SUFFIX); - else { - dejaVu.add(id); - Object[] oArray = (Object[]) (Object[]) o; - str.append("["); - boolean first = true; - for (Object current : oArray) { - if (first) - first = false; - else - str.append(", "); - recursiveDeepToString(current, str, new HashSet<>(dejaVu)); - } - str.append("]"); - } - } - else if ((o instanceof Map)) { - String id = identityToString(o); - if (dejaVu.contains(id)) - str.append(RECURSION_PREFIX).append(id).append(RECURSION_SUFFIX); - else { - dejaVu.add(id); - Map oMap = (Map) o; - str.append("{"); - boolean isFirst = true; - for (Map.Entry current : oMap.entrySet()) { - if (isFirst) - isFirst = false; - else - str.append(", "); - Object key = current.getKey(); - Object value = current.getValue(); - recursiveDeepToString(key, str, new HashSet<>(dejaVu)); - str.append("="); - recursiveDeepToString(value, str, new HashSet<>(dejaVu)); - } - str.append("}"); - } - } else if ((o instanceof Collection)) { - String id = identityToString(o); - if (dejaVu.contains(id)) - str.append(RECURSION_PREFIX).append(id).append(RECURSION_SUFFIX); - else { - dejaVu.add(id); - Collection oCol = (Collection) o; - str.append("["); - boolean isFirst = true; - for (Object anOCol : oCol) { - if (isFirst) - isFirst = false; - else - str.append(", "); - recursiveDeepToString(anOCol, str, new HashSet<>(dejaVu)); - } - str.append("]"); - } - } else if ((o instanceof Date)) { - Date date = (Date) o; - SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); - - str.append(format.format(date)); - } else - try { - str.append(o.toString()); - } catch (Throwable t) { - str.append(ERROR_PREFIX); - str.append(identityToString(o)); - str.append(ERROR_SEPARATOR); - String msg = t.getMessage(); - String className = t.getClass().getName(); - str.append(className); - if (!className.equals(msg)) { - str.append(ERROR_MSG_SEPARATOR); - str.append(msg); - } - str.append(ERROR_SUFFIX); - } - } - - public static String identityToString(Object obj) { - if (obj == null) - return null; - return obj.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(obj)); - } - - @Override - public String toString() { - return "ParameterizedMessage[messagePattern=" + this.messagePattern + ", stringArgs=" + Arrays.toString(this.stringArgs) + ", throwable=" + this.throwable + "]"; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/message/ParameterizedMessageFactory.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/message/ParameterizedMessageFactory.java deleted file mode 100644 index 56b689bba..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/message/ParameterizedMessageFactory.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.log.message; - -/** - * - * @author huangyuhui - */ -public final class ParameterizedMessageFactory extends AbstractMessageFactory { - - @Override - public IMessage newMessage(String message, Object[] params) { - return new ParameterizedMessage(message, params); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/message/SimpleMessage.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/message/SimpleMessage.java deleted file mode 100644 index 8ddaafbbe..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/message/SimpleMessage.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.log.message; - -/** - * - * @author huangyuhui - */ -public class SimpleMessage - implements IMessage { - - private static final long serialVersionUID = -8398002534962715992L; - private final String message; - - public SimpleMessage() { - this(null); - } - - public SimpleMessage(String message) { - this.message = message; - } - - @Override - public String getFormattedMessage() { - return this.message; - } - - @Override - public String getFormat() { - return this.message; - } - - @Override - public Object[] getParameters() { - return null; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if ((o == null) || (getClass() != o.getClass())) - return false; - - SimpleMessage that = (SimpleMessage) o; - - return this.message != null ? this.message.equals(that.message) : that.message == null; - } - - @Override - public int hashCode() { - return this.message != null ? this.message.hashCode() : 0; - } - - @Override - public String toString() { - return "SimpleMessage[message=" + this.message + "]"; - } - - @Override - public Throwable getThrowable() { - return null; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/message/StringFormattedMessage.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/message/StringFormattedMessage.java deleted file mode 100644 index 3e5b3f24f..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/log/message/StringFormattedMessage.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.log.message; - -import java.util.Arrays; -import java.util.IllegalFormatException; - -public class StringFormattedMessage - implements IMessage { - - private static final long serialVersionUID = -665975803997290697L; - private final String messagePattern; - private final transient Object[] argArray; - private String[] stringArgs; - private transient String formattedMessage; - private transient Throwable throwable; - - public StringFormattedMessage(String messagePattern, Object[] arguments) { - this.messagePattern = messagePattern; - this.argArray = arguments; - if ((arguments != null) && (arguments.length > 0) && ((arguments[(arguments.length - 1)] instanceof Throwable))) - this.throwable = ((Throwable) arguments[(arguments.length - 1)]); - } - - @Override - public String getFormattedMessage() { - if (this.formattedMessage == null) - this.formattedMessage = formatMessage(this.messagePattern, this.argArray); - return this.formattedMessage; - } - - @Override - public String getFormat() { - return this.messagePattern; - } - - @Override - public Object[] getParameters() { - if (this.argArray != null) - return this.argArray; - return this.stringArgs; - } - - protected String formatMessage(String msgPattern, Object[] args) { - try { - return String.format(msgPattern, args); - } catch (IllegalFormatException ife) { - System.err.println("Unable to format msg: " + msgPattern); - ife.printStackTrace(); - } - return msgPattern; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if ((o == null) || (getClass() != o.getClass())) - return false; - - StringFormattedMessage that = (StringFormattedMessage) o; - - if (this.messagePattern != null ? !this.messagePattern.equals(that.messagePattern) : that.messagePattern != null) - return false; - - return Arrays.equals(this.stringArgs, that.stringArgs); - } - - @Override - public int hashCode() { - int result = this.messagePattern != null ? this.messagePattern.hashCode() : 0; - result = 31 * result + (this.stringArgs != null ? Arrays.hashCode(this.stringArgs) : 0); - return result; - } - - @Override - public String toString() { - return "StringFormatMessage[messagePattern=" + this.messagePattern + ", args=" + Arrays.toString(this.argArray) + "]"; - } - - @Override - public Throwable getThrowable() { - return this.throwable; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/net/FileDownloadTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/net/FileDownloadTask.java deleted file mode 100644 index a88e90f67..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/net/FileDownloadTask.java +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.net; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.RandomAccessFile; -import java.math.BigInteger; -import java.net.HttpURLConnection; -import java.net.URL; -import java.security.MessageDigest; -import java.util.ArrayList; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.util.code.DigestUtils; -import org.jackhuang.hmcl.api.func.Function; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.util.sys.FileUtils; -import org.jackhuang.hmcl.util.task.Task; -import org.jackhuang.hmcl.util.task.comm.PreviousResult; -import org.jackhuang.hmcl.util.task.comm.PreviousResultRegistrar; -import org.jackhuang.hmcl.util.sys.IOUtils; - -/** - * - * @author huangyuhui - */ -// This class downloads a file from a URL. -public class FileDownloadTask extends Task implements PreviousResult, PreviousResultRegistrar { - - protected URL url; // download URL - protected int downloaded = 0; // number of bytes downloaded - protected File filePath; - protected String expectedHash; - - protected Function failedCallbackReturnsNewURL; - - public FileDownloadTask setFailedCallbackReturnsNewURL(Function failedCallbackReturnsNewURL) { - this.failedCallbackReturnsNewURL = failedCallbackReturnsNewURL; - return this; - } - - public FileDownloadTask() { - } - - public FileDownloadTask(File filePath) { - this((URL) null, filePath); - } - - public FileDownloadTask(String url, File filePath) { - this(IOUtils.parseURL(url), filePath); - } - - public FileDownloadTask(URL url, File filePath) { - this(url, filePath, null); - } - - public FileDownloadTask(String url, File filePath, String hash) { - this(IOUtils.parseURL(url), filePath, hash); - } - - public FileDownloadTask(URL url, File file, String hash) { - this.url = url; - this.filePath = file; - this.expectedHash = hash; - } - - // Get this download's URL. - public String getUrl() { - return url.toString(); - } - - RandomAccessFile file = null; - InputStream stream = null; - boolean shouldContinue = true; - - private void closeFiles() { - IOUtils.closeQuietly(file); - file = null; - IOUtils.closeQuietly(stream); - stream = null; - } - - // Download file. - @Override - public void executeTask(boolean areDependTasksSucceeded) throws Exception { - for (PreviousResult p : al) - this.url = IOUtils.parseURL(p.getResult()); - - for (int repeat = 0; repeat < 6; repeat++) { - if (repeat > 0) - if (failedCallbackReturnsNewURL != null) { - URL tmp = IOUtils.parseURL(failedCallbackReturnsNewURL.apply(repeat)); - if (tmp != null) { - url = tmp; - HMCLog.warn("Switch to: " + url); - } - } - HMCLog.log("Downloading: " + url + " to: " + filePath); - if (!shouldContinue) - break; - try { - if (ppl != null) - ppl.setProgress(this, -1, 1); - - // Open connection to URL. - HttpURLConnection con = (HttpURLConnection) url.openConnection(); - - con.setDoInput(true); - con.setConnectTimeout(15000); - con.setReadTimeout(15000); - con.setRequestProperty("User-Agent", "Hello Minecraft!"); - - // Connect to server. - con.connect(); - - // Make sure response code is in the 200 range. - if (con.getResponseCode() / 100 != 2) - throw new IOException(C.i18n("download.not_200") + " " + con.getResponseCode()); - - // Check for valid content length. - int contentLength = con.getContentLength(); - if (contentLength < 1) - throw new IOException("The content length is invalid."); - - if (!FileUtils.makeDirectory(filePath.getParentFile())) - throw new IOException("Could not make directory"); - - // We use temp file to prevent files from aborting downloading and broken. - File tempFile = new File(filePath.getAbsolutePath() + ".hmd"); - if (!tempFile.exists()) - tempFile.createNewFile(); - else if (!tempFile.renameTo(tempFile)) // check file lock - throw new IllegalStateException("The temp file is locked, maybe there is an application using the file?"); - - // Open file and seek to the end of it. - file = new RandomAccessFile(tempFile, "rw"); - - MessageDigest digest = DigestUtils.getSha1Digest(); - - stream = con.getInputStream(); - int lastDownloaded = 0; - downloaded = 0; - long lastTime = System.currentTimeMillis(); - while (true) { - // Size buffer according to how much of the file is left to download. - if (!shouldContinue) { - closeFiles(); - filePath.delete(); - break; - } - - byte buffer[] = new byte[IOUtils.MAX_BUFFER_SIZE]; - - // Read from server into buffer. - int read = stream.read(buffer); - if (read == -1) - break; - - if (expectedHash != null) - digest.update(buffer, 0, read); - - // Write buffer to file. - file.write(buffer, 0, read); - downloaded += read; - - // Update progress information per second - long now = System.currentTimeMillis(); - if (ppl != null && (now - lastTime) >= 1000) { - ppl.setProgress(this, downloaded, contentLength); - ppl.setStatus(this, (downloaded - lastDownloaded) / 1024 + "KB/s"); - lastDownloaded = downloaded; - lastTime = now; - } - } - closeFiles(); - - // Restore temp file to original name. - if (aborted) - tempFile.delete(); - else { - if (filePath.exists()) - filePath.delete(); - tempFile.renameTo(filePath); - } - if (!shouldContinue) - break; - if (downloaded != contentLength) - throw new IllegalStateException("Unexptected file size: " + downloaded + ", expected: " + contentLength); - - // Check hash code - String hashCode = String.format("%1$040x", new BigInteger(1, digest.digest())); - if (expectedHash != null && !expectedHash.equalsIgnoreCase(hashCode)) - throw new IllegalStateException("Unexpected hash code: " + hashCode + ", expected: " + expectedHash); - - if (ppl != null) - ppl.onProgressProviderDone(this); - return; - } catch (IOException | IllegalStateException e) { - filePath.delete(); - setFailReason(new IOException(C.i18n("download.failed") + " " + url, e)); - } finally { - closeFiles(); - } - } - if (failReason != null) - throw failReason; - } - - @Override - public boolean abort() { - shouldContinue = false; - aborted = true; - return true; - } - - @Override - public String getInfo() { - return C.i18n("download") + ": " + (tag == null ? url : tag); - } - - @Override - public File getResult() { - return filePath; - } - - ArrayList> al = new ArrayList<>(); - - @Override - public Task registerPreviousResult(PreviousResult pr) { - al.add(pr); - return this; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/net/HTTPGetTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/net/HTTPGetTask.java deleted file mode 100644 index 2a1e81f2c..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/net/HTTPGetTask.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.net; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.Proxy; -import java.net.URL; -import java.nio.charset.Charset; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.util.task.comm.PreviousResult; -import org.jackhuang.hmcl.api.event.EventHandler; -import org.jackhuang.hmcl.api.event.SimpleEvent; -import org.jackhuang.hmcl.util.code.Charsets; -import org.jackhuang.hmcl.util.task.Task; - -/** - * - * @author huangyuhui - */ -public class HTTPGetTask extends Task implements PreviousResult { - - String url, result; - Charset encoding; - EventHandler> doneEvent = new EventHandler<>(); - boolean shouldContinue = true; - - public HTTPGetTask(String url) { - this(url, Charsets.UTF_8); - } - - public HTTPGetTask(String url, Charset encoding) { - this.url = url; - this.encoding = encoding; - } - - @Override - public void executeTask(boolean areDependTasksSucceeded) throws Exception { - Exception t = null; - for (int time = 0; time < 6; time++) { - if (time > 0) - HMCLog.warn("Failed to download, repeat times: " + time); - try { - if (ppl != null) - ppl.setProgress(this, -1, 1); - HttpURLConnection con = NetUtils.createConnection(new URL(url), Proxy.NO_PROXY); - - InputStream is = con.getInputStream(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - byte[] buf = new byte[4096]; - int size = con.getContentLength(), read = 0, len; - long lastTime = System.currentTimeMillis(); - while ((len = is.read(buf)) != -1) { - baos.write(buf, 0, len); - read += len; - - // Update progress information per second - long now = System.currentTimeMillis(); - if (ppl != null && (now - lastTime) >= 1000) { - ppl.setProgress(this, read, size); - lastTime = now; - } - if (!shouldContinue) - return; - } - result = baos.toString(encoding.name()); - doneEvent.fire(new SimpleEvent<>(this, result)); - return; - } catch (IOException ex) { - t = new IOException("Failed to get " + url, ex); - } - } - if (t != null) - throw t; - } - - @Override - public boolean abort() { - shouldContinue = false; - return aborted = true; - } - - @Override - public String getInfo() { - return C.i18n("download") + ": " + (tag == null ? url : tag); - } - - @Override - public String getResult() { - return result; - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/net/NetUtils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/net/NetUtils.java deleted file mode 100644 index b7f4cdee0..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/net/NetUtils.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.net; - -import org.jackhuang.hmcl.api.HMCLog; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.HttpURLConnection; -import java.net.MalformedURLException; -import java.net.Proxy; -import java.net.URL; -import java.util.Map; -import org.jackhuang.hmcl.util.code.Charsets; -import org.jackhuang.hmcl.util.sys.IOUtils; - -/** - * - * @author huangyuhui - */ -public final class NetUtils { - - private NetUtils() { - } - - public static HttpURLConnection createConnection(URL url, Proxy proxy) throws IOException { - HttpURLConnection con = (HttpURLConnection) url.openConnection(proxy); - con.setDoInput(true); - con.setUseCaches(false); - con.setConnectTimeout(15000); - con.setReadTimeout(15000); - return con; - } - - public static String get(String url, String encoding) throws IOException { - return IOUtils.toString(new URL(url).openConnection().getInputStream()); - } - - public static String get(String url) throws IOException { - return get(url, IOUtils.DEFAULT_CHARSET); - } - - public static String get(URL url, Proxy proxy) throws IOException { - return readData(createConnection(url, proxy)); - } - - public static String post(URL u, Map params) throws IOException { - StringBuilder sb = new StringBuilder(); - if (params != null) { - for (Map.Entry e : params.entrySet()) - sb.append(e.getKey()).append("=").append(e.getValue()).append("&"); - sb.deleteCharAt(sb.length() - 1); - } - return post(u, sb.toString()); - } - - public static String post(URL u, String post) throws IOException { - return post(u, post, "application/x-www-form-urlencoded"); - } - - public static String post(URL u, String post, String contentType) throws IOException { - return post(u, post, contentType, Proxy.NO_PROXY); - } - - public static String post(URL u, String post, String contentType, Proxy proxy) throws IOException { - byte[] bytes = post.getBytes(Charsets.UTF_8); - - HttpURLConnection con = createConnection(u, proxy); - con.setRequestMethod("POST"); - con.setDoOutput(true); - con.setRequestProperty("Content-Type", contentType + "; charset=utf-8"); - con.setRequestProperty("Content-Length", "" + bytes.length); - OutputStream os = null; - try { - os = con.getOutputStream(); - IOUtils.write(bytes, os); - } finally { - IOUtils.closeQuietly(os); - } - return readData(con); - } - - private static String readData(HttpURLConnection con) throws IOException { - InputStream is = null; - try { - is = con.getInputStream(); - return IOUtils.toString(is, Charsets.UTF_8); - } catch (IOException e) { - IOUtils.closeQuietly(is); - is = con.getErrorStream(); - if (is != null) - return IOUtils.toString(is, Charsets.UTF_8); - throw e; - } finally { - IOUtils.closeQuietly(is); - } - } - - public static URL constantURL(String url) { - try { - return new URL(url); - } catch (MalformedURLException ex) { - HMCLog.err("Failed to get url instance: " + url, ex); - return null; - } - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/net/WebFrame.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/net/WebFrame.java deleted file mode 100644 index b2bd606a7..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/net/WebFrame.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.net; - -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import javax.swing.JDialog; -import org.jackhuang.hmcl.util.StrUtils; -import org.jackhuang.hmcl.util.log.Level; -import org.jackhuang.hmcl.util.ui.GraphicsUtils; -import org.jackhuang.hmcl.util.ui.SwingUtils; - -/** - * - * @author huangyuhui - */ -public class WebFrame extends JDialog { - - public WebFrame(String... strs) { - this(("" + StrUtils.parseParams(t -> (""), strs, t -> "
    ") + "") - .replace(" ", " ").replace("\t", "    ")); - } - - public WebFrame(String content) { - super((JDialog) null, false); - addWindowListener(new WindowAdapter() { - @Override - public void windowClosing(WindowEvent e) { - SwingUtils.exitIfNoWindow(WebFrame.this); - } - }); - - add(new WebPage(content)); - pack(); - - setLocationRelativeTo(null); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/net/WebPage.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/net/WebPage.java deleted file mode 100644 index 249cb6578..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/net/WebPage.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.net; - -import javax.swing.JScrollPane; -import javax.swing.event.HyperlinkEvent; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.util.ui.SwingUtils; - -/** - * - * @author huangyuhui - */ -public class WebPage extends JScrollPane { - - private final javax.swing.JTextPane browser; - - /** - * Creates new form WebPagePanel - */ - public WebPage(String content) { - browser = new javax.swing.JTextPane(); - browser.setEditable(false); - browser.setMargin(null); - browser.setContentType("text/html"); - browser.addHyperlinkListener(he -> { - if (he.getEventType() == HyperlinkEvent.EventType.ACTIVATED) - try { - SwingUtils.openLink(he.getURL().toString()); - } catch (Exception e) { - HMCLog.err("Unexpected exception opening link " + he.getURL(), e); - } - }); - browser.setText(content); - - setViewportView(browser); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/CompressingUtils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/CompressingUtils.java deleted file mode 100644 index c31308604..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/CompressingUtils.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.sys; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; -import org.jackhuang.hmcl.api.func.Predicate; -import java.util.zip.ZipInputStream; -import org.jackhuang.hmcl.api.func.BiFunction; - -/** - * 文件压缩/解压类 - * - * @author huangyuhui - */ -public final class CompressingUtils { - - private CompressingUtils() { - } - - public static void zip(String sourceDir, String zipFile) throws IOException { - zip(new File(sourceDir), new File(zipFile), null); - } - - /** - * 功能:把 sourceDir 目录下的所有文件进行 zip 格式的压缩,保存为指定 zip 文件 - * - * @param sourceDir 源文件夹 - * @param zipFile 压缩生成的zip文件路径。 - * @param pathNameCallback callback(pathName, isDirectory) returns your - * modified pathName - * - * @throws java.io.IOException 压缩失败或无法读取 - */ - public static void zip(File sourceDir, File zipFile, BiFunction pathNameCallback) throws IOException { - try (ZipOutputStream zos = new ZipOutputStream(FileUtils.openOutputStream(zipFile))) { - String basePath; - if (sourceDir.isDirectory()) - basePath = sourceDir.getPath(); - else//直接压缩单个文件时,取父目录 - basePath = sourceDir.getParent(); - zipFile(sourceDir, basePath, zos, pathNameCallback); - zos.closeEntry(); - } - } - - /** - * 将文件压缩成zip文件 - * - * @param source zip文件路径 - * @param basePath 待压缩文件根目录 - * @param zos zip文件的os - * @param pathNameCallback callback(pathName, isDirectory) returns your - * modified pathName, null if you dont want this file zipped - */ - private static void zipFile(File source, String basePath, - ZipOutputStream zos, BiFunction pathNameCallback) throws IOException { - File[] files; - if (source.isDirectory()) - files = source.listFiles(); - else { - files = new File[1]; - files[0] = source; - } - String pathName;//存相对路径(相对于待压缩的根目录) - byte[] buf = new byte[1024]; - for (File file : files) - if (file.isDirectory()) { - pathName = file.getPath().substring(basePath.length() + 1) - + "/"; - if (pathNameCallback != null) - pathName = pathNameCallback.apply(pathName, true); - if (pathName == null) - continue; - zos.putNextEntry(new ZipEntry(pathName)); - zipFile(file, basePath, zos, pathNameCallback); - } else { - pathName = file.getPath().substring(basePath.length() + 1); - if (pathNameCallback != null) - pathName = pathNameCallback.apply(pathName, true); - if (pathName == null) - continue; - try (InputStream is = FileUtils.openInputStream(file)) { - zos.putNextEntry(new ZipEntry(pathName)); - IOUtils.copyStream(is, zos, buf); - } - } - } - - public static void unzip(File zipFileName, File extPlace) throws IOException { - unzip(zipFileName, extPlace, null, true); - } - - /** - * 将文件压缩成zip文件 - * - * @param zipFileName zip文件路径 - * @param extPlace 待压缩文件根目录 - * @param callback will be called for every entry in the zip file, - * returns false if you dont want this file unzipped. - * - * @throws java.io.IOException 解压失败或无法写入 - */ - public static void unzip(File zipFileName, File extPlace, Predicate callback, boolean ignoreExistsFile) throws IOException { - byte[] buf = new byte[1024]; - extPlace.mkdirs(); - try (ZipInputStream zipFile = new ZipInputStream(FileUtils.openInputStream(zipFileName))) { - if (zipFileName.exists()) { - String strPath, gbkPath, strtemp; - strPath = extPlace.getAbsolutePath(); - ZipEntry zipEnt; - while ((zipEnt = zipFile.getNextEntry()) != null) { - gbkPath = zipEnt.getName(); - if (callback != null) - if (!callback.apply(gbkPath)) - continue; - if (zipEnt.isDirectory()) { - strtemp = strPath + File.separator + gbkPath; - File dir = new File(strtemp); - dir.mkdirs(); - } else { - //读写文件 - gbkPath = zipEnt.getName(); - strtemp = strPath + File.separator + gbkPath; - //建目录 - String strsubdir = gbkPath; - for (int i = 0; i < strsubdir.length(); i++) - if (strsubdir.substring(i, i + 1).equalsIgnoreCase("/")) { - String temp = strPath + File.separator + strsubdir.substring(0, i); - File subdir = new File(temp); - if (!subdir.exists()) - subdir.mkdir(); - } - if (ignoreExistsFile && new File(strtemp).exists()) - continue; - try (FileOutputStream fos = FileUtils.openOutputStream(new File(strtemp))) { - IOUtils.copyStream(zipFile, fos, buf); - } - } - } - } - } - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/FileUtils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/FileUtils.java deleted file mode 100644 index 0ab4a630d..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/FileUtils.java +++ /dev/null @@ -1,376 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.sys; - -import java.io.File; -import java.io.FileFilter; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import org.jackhuang.hmcl.api.HMCLog; - -/** - * - * @author huangyuhui - */ -public final class FileUtils { - - private FileUtils() { - } - - public static boolean makeDirectory(File directory) { - return directory.isDirectory() || directory.mkdirs(); - } - - public static void deleteDirectory(File directory) - throws IOException { - if (!directory.exists()) - return; - - if (!isSymlink(directory)) - cleanDirectory(directory); - - if (!directory.delete()) { - String message = "Unable to delete directory " + directory + "."; - - throw new IOException(message); - } - } - - public static boolean deleteDirectoryQuietly(File directory) { - try { - deleteDirectory(directory); - return true; - } catch (Exception e) { - HMCLog.err("Failed to delete directory " + directory, e); - return false; - } - } - - public static boolean cleanDirectoryQuietly(File directory) { - try { - cleanDirectory(directory); - return true; - } catch (Exception e) { - HMCLog.err("Failed to clean directory " + directory, e); - return false; - } - } - - public static void cleanDirectory(File directory) - throws IOException { - if (!directory.exists()) { - if (!FileUtils.makeDirectory(directory)) - throw new IOException("Failed to create directory: " + directory); - return; - } - - if (!directory.isDirectory()) { - String message = directory + " is not a directory"; - throw new IllegalArgumentException(message); - } - - File[] files = directory.listFiles(); - if (files == null) - throw new IOException("Failed to list contents of " + directory); - - IOException exception = null; - for (File file : files) - try { - forceDelete(file); - } catch (IOException ioe) { - exception = ioe; - } - - if (null != exception) - throw exception; - } - - public static void forceDelete(File file) - throws IOException { - if (file.isDirectory()) - deleteDirectory(file); - else { - boolean filePresent = file.exists(); - if (!file.delete()) { - if (!filePresent) - throw new FileNotFoundException("File does not exist: " + file); - String message = "Unable to delete file: " + file; - - throw new IOException(message); - } - } - } - - public static boolean isSymlink(File file) - throws IOException { - Objects.requireNonNull(file, "File must not be null"); - if (File.separatorChar == '\\') - return false; - File fileInCanonicalDir; - if (file.getParent() == null) - fileInCanonicalDir = file; - else { - File canonicalDir = file.getParentFile().getCanonicalFile(); - fileInCanonicalDir = new File(canonicalDir, file.getName()); - } - - return !fileInCanonicalDir.getCanonicalFile().equals(fileInCanonicalDir.getAbsoluteFile()); - } - - public static void copyDirectory(File srcDir, File destDir) - throws IOException { - copyDirectory(srcDir, destDir, null); - } - - public static void copyDirectory(File srcDir, File destDir, FileFilter filter) - throws IOException { - Objects.requireNonNull(srcDir, "Source must not be null"); - Objects.requireNonNull(destDir, "Destination must not be null"); - if (!srcDir.exists()) - throw new FileNotFoundException("Source '" + srcDir + "' does not exist"); - if (!srcDir.isDirectory()) - throw new IOException("Source '" + srcDir + "' exists but is not a directory"); - if (srcDir.getCanonicalPath().equals(destDir.getCanonicalPath())) - throw new IOException("Source '" + srcDir + "' and destination '" + destDir + "' are the same"); - - List exclusionList = null; - if (destDir.getCanonicalPath().startsWith(srcDir.getCanonicalPath())) { - File[] srcFiles = filter == null ? srcDir.listFiles() : srcDir.listFiles(filter); - if ((srcFiles != null) && (srcFiles.length > 0)) { - exclusionList = new ArrayList<>(srcFiles.length); - for (File srcFile : srcFiles) { - File copiedFile = new File(destDir, srcFile.getName()); - exclusionList.add(copiedFile.getCanonicalPath()); - } - } - } - doCopyDirectory(srcDir, destDir, filter, exclusionList); - } - - private static void doCopyDirectory(File srcDir, File destDir, FileFilter filter, List exclusionList) - throws IOException { - File[] srcFiles = filter == null ? srcDir.listFiles() : srcDir.listFiles(filter); - if (srcFiles == null) - throw new IOException("Failed to list contents of " + srcDir); - if (destDir.exists()) { - if (!destDir.isDirectory()) - throw new IOException("Destination '" + destDir + "' exists but is not a directory"); - } else if (!FileUtils.makeDirectory(destDir)) - throw new IOException("Destination '" + destDir + "' directory cannot be created"); - - if (!destDir.canWrite()) - throw new IOException("Destination '" + destDir + "' cannot be written to"); - for (File srcFile : srcFiles) { - File dstFile = new File(destDir, srcFile.getName()); - if ((exclusionList == null) || (!exclusionList.contains(srcFile.getCanonicalPath()))) - if (srcFile.isDirectory()) - doCopyDirectory(srcFile, dstFile, filter, exclusionList); - else - doCopyFile(srcFile, dstFile); - } - if (!destDir.setLastModified(srcDir.lastModified())) - HMCLog.warn("Failed to set last modified date of dir: " + destDir); - } - - public static String read(File file) - throws IOException { - return IOUtils.toString(openInputStream(file)); - } - - public static String readQuietly(File file) { - try { - return IOUtils.toString(openInputStream(file)); - } catch (IOException ex) { - HMCLog.err("Failed to read file: " + file, ex); - return null; - } - } - - public static String read(File file, String charset) - throws IOException { - return IOUtils.toString(openInputStream(file), charset); - } - - public static void copyFileQuietly(File srcFile, File destFile) { - try { - copyFile(srcFile, destFile); - } catch (IOException ex) { - HMCLog.warn("Failed to copy file", ex); - } - } - - public static void copyFile(File srcFile, File destFile) - throws IOException { - Objects.requireNonNull(srcFile, "Source must not be null"); - Objects.requireNonNull(destFile, "Destination must not be null"); - if (!srcFile.exists()) - throw new FileNotFoundException("Source '" + srcFile + "' does not exist"); - if (srcFile.isDirectory()) - throw new IOException("Source '" + srcFile + "' exists but is a directory"); - if (srcFile.getCanonicalPath().equals(destFile.getCanonicalPath())) - throw new IOException("Source '" + srcFile + "' and destination '" + destFile + "' are the same"); - File parentFile = destFile.getParentFile(); - if (parentFile != null && !FileUtils.makeDirectory(parentFile)) - throw new IOException("Destination '" + parentFile + "' directory cannot be created"); - if (destFile.exists() && !destFile.canWrite()) - throw new IOException("Destination '" + destFile + "' exists but is read-only"); - doCopyFile(srcFile, destFile); - } - - public static void doCopyFile(File srcFile, File destFile) - throws IOException { - Files.copy(srcFile.toPath(), destFile.toPath(), StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING); - } - - public static int indexOfLastSeparator(String filename) { - if (filename == null) - return -1; - int lastUnixPos = filename.lastIndexOf(47); - int lastWindowsPos = filename.lastIndexOf(92); - return Math.max(lastUnixPos, lastWindowsPos); - } - - public static String getName(String filename) { - if (filename == null) - return null; - int index = indexOfLastSeparator(filename); - return filename.substring(index + 1); - } - - /** - * Get the file name without extensions. - * - * @param filename - * - * @return the file name without extensions - */ - public static String getBaseName(String filename) { - return removeExtension(getName(filename)); - } - - public static int indexOfExtension(String filename) { - if (filename == null) - return -1; - int extensionPos = filename.lastIndexOf(46); - int lastSeparator = indexOfLastSeparator(filename); - return lastSeparator > extensionPos ? -1 : extensionPos; - } - - public static String getExtension(String filename) { - if (filename == null) - return null; - int index = indexOfExtension(filename); - if (index == -1) - return ""; - return filename.substring(index + 1); - } - - public static String removeExtension(String filename) { - if (filename == null) - return null; - int index = indexOfExtension(filename); - if (index == -1) - return filename; - return filename.substring(0, index); - } - - public static boolean writeQuietly(File file, String data) { - try { - FileUtils.write(file, data); - return true; - } catch (IOException e) { - HMCLog.warn("Failed to write data to file: " + file, e); - return false; - } - } - - public static void write(File file, String data) - throws IOException { - write(file, data, "UTF-8", false); - } - - public static void write(File file, String data, String encoding) - throws IOException { - write(file, data, encoding, false); - } - - public static void write(File file, String data, String encoding, boolean append) - throws IOException { - OutputStream out = null; - try { - out = openOutputStream(file, append); - IOUtils.write(data, out, encoding); - } finally { - IOUtils.closeQuietly(out); - } - } - - public static FileInputStream openInputStream(File file) - throws IOException { - if (file.exists()) { - if (file.isDirectory()) - throw new IOException("File '" + file + "' exists but is a directory"); - if (!file.canRead()) - throw new IOException("File '" + file + "' cannot be read"); - } else - throw new FileNotFoundException("File '" + file + "' does not exist"); - return new FileInputStream(file); - } - - public static FileOutputStream openOutputStream(File file) - throws IOException { - return openOutputStream(file, false); - } - - public static FileOutputStream openOutputStream(File file, boolean append) - throws IOException { - if (file.exists()) { - if (file.isDirectory()) - throw new IOException("File '" + file + "' exists but is a directory"); - if (!file.canWrite()) - throw new IOException("File '" + file + "' cannot be written to"); - } else { - File parent = file.getParentFile(); - if (parent != null && !FileUtils.makeDirectory(parent)) - throw new IOException("Directory '" + parent + "' could not be created"); - if (!file.createNewFile()) - throw new IOException("File `" + file + "` cannot be created."); - } - - return new FileOutputStream(file, append); - } - - public static File[] searchSuffix(File dir, String suffix) { - ArrayList al = new ArrayList<>(); - File[] files = dir.listFiles(); - if (files == null) - return new File[0]; - for (File f : files) - if (f.getName().endsWith(suffix)) - al.add(f); - return al.toArray(new File[al.size()]); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/IOUtils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/IOUtils.java deleted file mode 100644 index 8847c1c90..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/IOUtils.java +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.sys; - -import java.io.BufferedReader; -import java.io.ByteArrayOutputStream; -import java.io.Closeable; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.PrintStream; -import java.io.UnsupportedEncodingException; -import java.net.InetAddress; -import java.net.MalformedURLException; -import java.net.NetworkInterface; -import java.net.SocketException; -import java.net.URL; -import java.net.UnknownHostException; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.List; -import org.jackhuang.hmcl.api.func.Consumer; -import org.jackhuang.hmcl.api.func.Function; -import org.jackhuang.hmcl.api.HMCLog; - -/** - * - * @author huang - */ -public final class IOUtils { - - private IOUtils() { - } - - public static String addSeparator(String path) { - if (path == null || path.trim().length() == 0) - return ""; - if (isSeparator(path.charAt(path.length() - 1))) - return path; - else - return path + File.separatorChar; - } - - public static String addURLSeparator(String path) { - if (path == null || path.trim().length() == 0) - return ""; - if (path.charAt(path.length() - 1) == '/') - return path; - else - return path + '/'; - } - - public static boolean isSeparator(char ch) { - return ch == File.separatorChar || ch == '/' || ch == '\\'; - } - - public static String removeLastSeparator(String dir) { - String t = dir.trim(); - char ch = t.charAt(t.length() - 1); - if (isSeparator(ch)) - return t.substring(0, t.length() - 1); - return t; - } - - public static void findAllFile(File f, Consumer callback) { - if (f.isDirectory()) { - File[] f1 = f.listFiles(); - int len = f1.length; - for (int i = 0; i < len; i++) - if (f1[i].isFile()) - callback.accept(f1[i].getName()); - } - } - - public static void findAllDir(File f, Consumer callback) { - if (f.isDirectory()) { - File[] f1 = f.listFiles(); - int len = f1.length; - for (int i = 0; i < len; i++) - if (f1[i].isDirectory()) - callback.accept(f1[i].getName()); - } - } - - public static String getRealPath() { - String realPath = IOUtils.class.getClassLoader().getResource("").getFile(); - File file = new File(realPath); - realPath = file.getAbsolutePath(); - try { - realPath = java.net.URLDecoder.decode(realPath, DEFAULT_CHARSET); - } catch (Exception e) { - e.printStackTrace(); - } - return realPath; - } - - public static boolean isAbsolutePath(String path) { - if (path == null) - return true; - return path.startsWith("/") || path.indexOf(':') > 0; - } - - public static String getLocalMAC() { - InetAddress addr; - try { - addr = InetAddress.getLocalHost(); - String ip = addr.getHostAddress(); - return getMacAddress(ip); - } catch (UnknownHostException e) { - HMCLog.warn("Failed to get local mac address because of the unknown host.", e); - } - return "ERROR"; - } - - public static String getMacAddress(String host) { - String mac; - StringBuilder sb = new StringBuilder(); - - try { - NetworkInterface ni = NetworkInterface.getByInetAddress(InetAddress.getByName(host)); - - byte[] macs = ni.getHardwareAddress(); - - for (int i = 0; i < macs.length; i++) { - mac = Integer.toHexString(macs[i] & 0xFF); - - if (mac.length() == 1) - mac = '0' + mac; - - sb.append(mac).append("-"); - } - - } catch (SocketException e) { - HMCLog.warn("Failed to get mac address because the socket has thrown an exception.", e); - } catch (UnknownHostException e) { - HMCLog.warn("Failed to get mac address because of the unknown host.", e); - } - - mac = sb.toString(); - mac = mac.substring(0, mac.length() - 1); - - return mac; - } - - public static String getJavaDir() { - return getJavaDir(System.getProperty("java.home")); - } - - public static String getJavaDir(String home) { - String path = home + File.separatorChar + "bin" + File.separatorChar; - path = addSeparator(path); - if (OS.os() == OS.WINDOWS && new File(path + "javaw.exe").isFile()) - return path + "javaw.exe"; - else - return path + "java"; - } - - public static List readLines(InputStream stream, String charset) throws IOException { - BufferedReader br = new BufferedReader(new InputStreamReader(stream, charset)); - ArrayList ret = new ArrayList<>(); - for (String line; (line = br.readLine()) != null; ret.add(line)); - return ret; - } - - public static ByteArrayOutputStream readFully(InputStream stream) throws IOException { - byte[] data = new byte[MAX_BUFFER_SIZE]; - ByteArrayOutputStream entryBuffer = new ByteArrayOutputStream(); - int len; - do { - len = stream.read(data); - if (len <= 0) - continue; - entryBuffer.write(data, 0, len); - } while (len != -1); - - return entryBuffer; - } - - public static byte[] toByteArray(InputStream stream) throws IOException { - return readFully(stream).toByteArray(); - } - - public static String toString(InputStream is) throws IOException { - return readFully(is).toString(); - } - - public static String toString(InputStream is, String charset) throws IOException { - return readFully(is).toString(charset); - } - - public static String toString(InputStream is, Charset charset) throws IOException { - return readFully(is).toString(charset.name()); - } - - public static void closeQuietly(Closeable closeable) { - try { - if (closeable != null) - closeable.close(); - } catch (IOException ioe) { - } - } - - public static void write(byte[] data, OutputStream output) - throws IOException { - if (data != null) - output.write(data); - } - - public static void write(String data, OutputStream output, String encoding) - throws IOException { - if (data != null) - output.write(data.getBytes(encoding)); - } - - public static URL parseURL(String str) { - try { - return new URL(str); - } catch (MalformedURLException ex) { - HMCLog.warn("Failed to parse URL:" + str); - return null; - } - } - - public static List readProcessByInputStream(String[] cmd) throws IOException, InterruptedException { - return readProcessImpl(cmd, p -> p.getInputStream()); - } - - public static List readProcessByErrorStream(String[] cmd) throws IOException, InterruptedException { - return readProcessImpl(cmd, p -> p.getErrorStream()); - } - - private static List readProcessImpl(String[] cmd, Function callback) throws IOException, InterruptedException { - JavaProcess jp = new JavaProcess(cmd, new ProcessBuilder(cmd).start()); - ArrayList lines = new ArrayList<>(); - try (BufferedReader br = new BufferedReader(new InputStreamReader(callback.apply(jp.getRawProcess()), Charset.defaultCharset()))) { - jp.getRawProcess().waitFor(); - String line; - while ((line = br.readLine()) != null) - lines.add(line); - } - return lines; - } - - public static void copyStream(InputStream input, OutputStream output) throws IOException { - copyStream(input, output, new byte[MAX_BUFFER_SIZE]); - } - - public static void copyStream(InputStream input, OutputStream output, byte[] buf) throws IOException { - int length; - while ((length = input.read(buf)) != -1) - output.write(buf, 0, length); - } - - /** - * Max buffer size downloading. - */ - public static final int MAX_BUFFER_SIZE = 4096; - - public static final String DEFAULT_CHARSET = "UTF-8"; - - public static PrintStream createPrintStream(OutputStream out, Charset charset) { - try { - return new PrintStream(out, false, charset.name()); - } catch (UnsupportedEncodingException ignore) { - return null; - } - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/Java.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/Java.java deleted file mode 100644 index fb64cd31f..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/Java.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.sys; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.api.HMCLog; - -/** - * - * @author huangyuhui - */ -public class Java { - - public static final List JAVA; - - static { - List temp = new ArrayList<>(); - temp.add(new Java("Default", System.getProperty("java.home"))); - temp.add(new Java("Custom", null)); - if (OS.os() == OS.WINDOWS) - temp.addAll(Java.queryAllJavaHomeInWindowsByReg().values()); - else if (OS.os() == OS.OSX) - temp.addAll(Java.queryAllJDKInMac()); - JAVA = Collections.unmodifiableList(temp); - } - - public static Java suggestedJava() { - for (Java j : JAVA) - if (j.name.startsWith("1.8") || j.name.startsWith("9")) - return j; - return JAVA.get(0); - } - - String name, home; - - public Java(String name, String home) { - this.name = name; - this.home = home; - } - - public String getName() { - return name; - } - - public String getLocalizedName() { - if (name.equals("Default")) - return C.i18n("settings.default"); - if (name.equals("Custom")) - return C.i18n("settings.custom"); - return name; - } - - public String getHome() { - return home; - } - - public String getJava() { - return IOUtils.getJavaDir(getHome()); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof Java) { - Java j = (Java) obj; - return (j.getName() == null && this.getName() == null) || ((Java) obj).getName().equals(this.getName()); - } else - return false; - } - - @Override - public int hashCode() { - return name.hashCode(); - } - - /* - * ----------------------------------- - * MAC OS X - * ----------------------------------- - */ - public static List queryAllJDKInMac() { - List ans = new ArrayList<>(); - File jre = new File("/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home"); - if (jre.exists()) - ans.add(new Java("JRE", jre.getPath())); - File f = new File("/Library/Java/JavaVirtualMachines/"); - if (f.exists()) - for (File a : f.listFiles()) - ans.add(new Java(a.getName(), new File(a, "Contents/Home").getAbsolutePath())); - return ans; - } - - /* - * ----------------------------------- - * WINDOWS - * ----------------------------------- - */ - public static Map queryAllJavaHomeInWindowsByReg() { - Map ans = new HashMap<>(); - try { - queryJava(ans, "HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment\\"); - queryJava(ans, "HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit\\"); - } catch (IOException | InterruptedException ex) { - HMCLog.err("Faield to query java", ex); - } - return ans; - } - - private static void queryJava(Map ans, String location) throws IOException, InterruptedException { - for (String java : queryRegSubFolders(location)) { - int s = 0; - for (char c : java.toCharArray()) - if (c == '.') - ++s; - if (s <= 1) - continue; - String javahome = queryRegValue(java, "JavaHome"), ver = java.substring(location.length()); - if (javahome != null && !ans.containsKey(ver)) - ans.put(ver, new Java(ver, javahome)); - } - } - - private static List queryRegSubFolders(String location) throws IOException, InterruptedException { - String[] cmd = new String[] { "cmd", "/c", "reg", "query", location }; - List l = IOUtils.readProcessByInputStream(cmd); - List ans = new ArrayList<>(); - for (String line : l) - if (line.startsWith(location) && !line.equals(location)) - ans.add(line); - return ans; - } - - private static String queryRegValue(String location, String name) throws IOException, InterruptedException { - String[] cmd = new String[] { "cmd", "/c", "reg", "query", location, "/v", name }; - List l = IOUtils.readProcessByInputStream(cmd); - boolean last = false; - for (String s : l) { - if (s.trim().isEmpty()) - continue; - if (last == true && s.trim().startsWith(name)) { - int begins = s.indexOf(name); - if (begins > 0) { - s = s.substring(begins + name.length()); - begins = s.indexOf("REG_SZ"); - if (begins > 0) { - s = s.substring(begins + "REG_SZ".length()); - return s.trim(); - } - } - } - if (s.trim().equals(location)) - last = true; - } - return null; - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/JavaProcess.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/JavaProcess.java deleted file mode 100644 index fcd5a5546..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/JavaProcess.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.sys; - -import java.util.ArrayList; -import org.jackhuang.hmcl.api.IProcess; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -/** - * - * @author huangyuhui - */ -public class JavaProcess implements IProcess { - - private final List commands; - private final Process process; - private final List stdOutLines = Collections.synchronizedList(new ArrayList<>()); - - public JavaProcess(List commands, Process process) { - this.commands = commands; - this.process = process; - } - - public JavaProcess(String[] commands, Process process) { - this(Arrays.asList(commands), process); - } - - @Override - public Process getRawProcess() { - return this.process; - } - - @Override - public List getStartupCommands() { - return this.commands; - } - - @Override - public String getStartupCommand() { - return this.process.toString(); - } - - @Override - public List getStdOutLines() { - return this.stdOutLines; - } - - @Override - public boolean isRunning() { - try { - this.process.exitValue(); - } catch (IllegalThreadStateException ex) { - return true; - } - - return false; - } - - @Override - public int getExitCode() { - try { - return this.process.exitValue(); - } catch (IllegalThreadStateException ex) { - ex.fillInStackTrace(); - throw ex; - } - } - - @Override - public String toString() { - return "JavaProcess[commands=" + this.commands + ", isRunning=" + isRunning() + "]"; - } - - @Override - public void stop() { - this.process.destroy(); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/JdkVersion.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/JdkVersion.java deleted file mode 100644 index 20dbc532e..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/JdkVersion.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.sys; - -import java.io.File; -import java.io.IOException; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.util.StrUtils; - -/** - * - * @author huangyuhui - */ -public final class JdkVersion implements Cloneable { - - private String ver; - - public String getVersion() { - return ver; - } - - public Platform getPlatform() { - return Platform.values()[platform]; - } - - public String getLocation() { - return location; - } - - public int getParsedVersion() { - return parseVersion(getVersion()); - } - /** - * -1 - unkown 0 - 32Bit 1 - 64Bit - */ - private int platform; - - private String location; - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof JdkVersion)) - return false; - JdkVersion b = (JdkVersion) obj; - if (b.location == null && location == null) - return true; - else if (b.location == null || location == null) - return false; - else - return new File(b.location).equals(new File(location)); - } - - @Override - public int hashCode() { - return location == null ? 0 : new File(location).hashCode(); - } - - @Override - protected Object clone() { - try { - return super.clone(); - } catch (CloneNotSupportedException ex) { - throw new Error(ex); - } - } - - public JdkVersion(String location) { - File f = new File(location); - if (f.exists() && f.isFile()) - f = f.getParentFile(); - this.location = f.getAbsolutePath(); - } - - public JdkVersion(String location, String ver, Platform platform) { - this(location); - this.ver = ver; - this.platform = platform.ordinal(); - } - - /** - * Constant identifying the 1.5 JVM (Java 5). - */ - public static final int UNKOWN = 2; - /** - * Constant identifying the 1.6 JVM (Java 6). - */ - public static final int JAVA_16 = 3; - /** - * Constant identifying the 1.7 JVM (Java 7). - */ - public static final int JAVA_17 = 4; - /** - * Constant identifying the 1.8 JVM (Java 8). - */ - public static final int JAVA_18 = 5; - /** - * Constant identifying the 1.9 JVM (Java 9). - */ - public static final int JAVA_19 = 6; - - private static int parseVersion(String javaVersion) { - if (StrUtils.isBlank(javaVersion)) - return UNKOWN; - int a = UNKOWN; - if (javaVersion.contains("1.9.") || javaVersion.startsWith("9")) - a = JAVA_19; - else if (javaVersion.contains("1.8.")) - a = JAVA_18; - else if (javaVersion.contains("1.7.")) - a = JAVA_17; - else if (javaVersion.contains("1.6.")) - a = JAVA_16; - return a; - } - - private static final Pattern p = Pattern.compile("java version \"[1-9]*\\.[1-9]*\\.[0-9]*(.*?)\""); - - public static JdkVersion getJavaVersionFromExecutable(String file) throws IOException { - String[] str = new String[]{file, "-version"}; - Platform platform = Platform.BIT_32; - String ver = null; - try { - for (String line : IOUtils.readProcessByErrorStream(str)) { - Matcher m = p.matcher(line); - if (m.find()) { - ver = m.group(); - ver = ver.substring("java version \"".length(), ver.length() - 1); - } - if (line.contains("64-Bit")) - platform = Platform.BIT_64; - } - } catch (InterruptedException | IOException e) { - HMCLog.warn("Failed to get java version", e); - } - return new JdkVersion(file, ver, platform); - } - - public boolean isEarlyAccess() { - return getVersion() != null && getVersion().endsWith("-ea"); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/OS.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/OS.java deleted file mode 100644 index eed9b44e7..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/OS.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.sys; - -import java.io.File; -import java.io.IOException; -import java.lang.management.ManagementFactory; -import java.util.Locale; -import org.jackhuang.hmcl.api.HMCLog; - -/** - * @author huangyuhui - */ -public enum OS { - - LINUX('/', "linux"), - WINDOWS('\\', "windows"), - OSX('/', "osx"), - UNKOWN('/', "universal"); - - public final char fileSeparator; - public final String checked_name; - - private OS(char fileSeparator, String n) { - this.fileSeparator = fileSeparator; - checked_name = n; - } - - public static OS os() { - String str = System.getProperty("os.name").toLowerCase(Locale.US); - if (str.contains("win")) - return OS.WINDOWS; - if (str.contains("mac")) - return OS.OSX; - if (str.contains("solaris")) - return OS.LINUX; - if (str.contains("sunos")) - return OS.LINUX; - if (str.contains("linux")) - return OS.LINUX; - if (str.contains("unix")) - return OS.LINUX; - return OS.UNKOWN; - } - - /** - * @return Free Physical Memory Size (Byte) - */ - public static long getTotalPhysicalMemory() { - try { - return ReflectionHelper.get(ManagementFactory.getOperatingSystemMXBean(), "getTotalPhysicalMemorySize"); - } catch (Throwable t) { - HMCLog.warn("Failed to get total physical memory size", t); - return 1024; - } - } - - public static int getSuggestedMemorySize() { - long total = getTotalPhysicalMemory(); - int memory = (int) (total / 1024 / 1024) / 4; - memory = Math.round((float) memory / 128.0f) * 128; - return memory; - } - - public static String getLinuxReleaseVersion() throws IOException { - return FileUtils.read(new File("/etc/issue")); - } - - public static String getSystemVersion() { - if (os() == LINUX) - try { - return getLinuxReleaseVersion(); - } catch (IOException e) { - HMCLog.warn("Failed to catch /etc/issue"); - } - return System.getProperty("os.name") + " (" + System.getProperty("os.arch") + "), " + System.getProperty("os.version"); - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/Platform.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/Platform.java deleted file mode 100644 index c68b96a13..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/Platform.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.sys; - -/** - * - * @author huangyuhui - */ -public enum Platform { - - UNKNOWN { - - @Override - public String getBit() { - return "unknown"; - } - - }, - BIT_32 { - - @Override - public String getBit() { - return "32"; - } - - }, - BIT_64 { - - @Override - public String getBit() { - return "64"; - } - - }; - - public abstract String getBit(); - - public static Platform getPlatform() { - return System.getProperty("os.arch").contains("64") ? BIT_64 : BIT_32; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/PrintlnEvent.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/PrintlnEvent.java deleted file mode 100644 index 1a609b221..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/PrintlnEvent.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.sys; - -import java.util.EventObject; - -/** - * For ProcessThread. - * @author huang - */ -public class PrintlnEvent extends EventObject { - - String line; - boolean error; - - public PrintlnEvent(Object source, String line, boolean isError) { - super(source); - this.line = line; - this.error = isError; - } - - public String getLine() { - return line; - } - - public boolean isError() { - return error; - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/ProcessMonitor.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/ProcessMonitor.java deleted file mode 100644 index 2da07097a..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/ProcessMonitor.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.sys; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.concurrent.CountDownLatch; -import org.jackhuang.hmcl.api.HMCLApi; -import org.jackhuang.hmcl.api.event.process.JVMLaunchFailedEvent; -import org.jackhuang.hmcl.api.event.process.JavaProcessExitedAbnormallyEvent; -import org.jackhuang.hmcl.api.event.process.JavaProcessStartingEvent; -import org.jackhuang.hmcl.api.event.process.JavaProcessStoppedEvent; -import org.jackhuang.hmcl.util.StrUtils; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.util.log.Level; -import org.jackhuang.hmcl.api.IProcess; -import org.jackhuang.hmcl.api.event.SimpleEvent; -import org.jackhuang.hmcl.api.func.Consumer; - -/** - * - * @author huangyuhui - */ -public class ProcessMonitor { - - public static final HashSet MONITORS = new HashSet<>(); - - private final CountDownLatch latch = new CountDownLatch(2); - ProcessThread inputThread; - ProcessThread errorThread; - WaitForThread waitForThread; - private final IProcess p; - - public ProcessMonitor(IProcess p) { - this.p = p; - inputThread = new ProcessThread(this, false); - errorThread = new ProcessThread(this, true); - inputThread.stopEvent.register(this::threadStopped); - inputThread.stopEvent.register(event -> processThreadStopped((ProcessThread) event.getSource())); - errorThread.stopEvent.register(this::threadStopped); - } - - public IProcess getProcess() { - return p; - } - - private Object tag; - - public Object getTag() { - return tag; - } - - public void setTag(Object tag) { - this.tag = tag; - } - - public void registerPrintlnEvent(Consumer c) { - inputThread.printlnEvent.register(c); - errorThread.printlnEvent.register(c); - } - - public void start() { - hasFired = false; - MONITORS.add(this); - HMCLApi.EVENT_BUS.fireChannel(new JavaProcessStartingEvent(this, p)); - inputThread.start(); - errorThread.start(); - } - - private void threadStopped(SimpleEvent event) { - latch.countDown(); - ProcessThread t = (ProcessThread) event.getSource(); - int exitCode = Integer.MAX_VALUE; - try { - exitCode = p.getExitCode(); - } catch(IllegalThreadStateException e) { - HMCLog.err("Failed to "); - } - if (p.getExitCode() != 0 || StrUtils.containsOne(t.getLines(), - Arrays.asList("Unable to launch"), // LaunchWrapper will terminate the application returning exit code 0, but this is an error state. - x -> Level.isError(Level.guessLevel(x)))) - synchronized (this) { - if (!hasFired) { - hasFired = true; - HMCLApi.EVENT_BUS.fireChannel(new JavaProcessExitedAbnormallyEvent(ProcessMonitor.this, p)); - } - } - if (p.getExitCode() != 0 && StrUtils.containsOne(t.getLines(), - Arrays.asList("Could not create the Java Virtual Machine.", - "Error occurred during initialization of VM", - "A fatal exception has occurred. Program will exit.", - "Unable to launch"), - x -> Level.isError(Level.guessLevel(x)))) - synchronized (this) { - if (!hasFired) { - hasFired = true; - HMCLApi.EVENT_BUS.fireChannel(new JVMLaunchFailedEvent(ProcessMonitor.this, p)); - } - } - } - - boolean hasFired = false; - - private void processThreadStopped(ProcessThread t1) { - MONITORS.remove(this); - errorThread.interrupt(); - HMCLApi.EVENT_BUS.fireChannel(new JavaProcessStoppedEvent(this, p)); - } - - public static void stopAll() { - for (ProcessMonitor monitor : MONITORS) { - monitor.getProcess().getRawProcess().destroy(); - monitor.inputThread.interrupt(); - monitor.errorThread.interrupt(); - } - } - - public void waitForCommandLineCompletion() { - try { - latch.await(); - } catch (InterruptedException ignore) { - } - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/ProcessThread.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/ProcessThread.java deleted file mode 100644 index e74c480f8..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/ProcessThread.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.sys; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.List; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.api.event.EventHandler; -import org.jackhuang.hmcl.api.event.SimpleEvent; -import org.jackhuang.hmcl.util.code.Charsets; -import org.jackhuang.hmcl.api.IProcess; - -/** - * Watch the process command line output(stdout or stderr). - * - * @author huangyuhui - */ -public class ProcessThread extends Thread { - - List lines = new ArrayList<>(); - ProcessMonitor monitor; - IProcess p; - boolean readError; - public final EventHandler printlnEvent = new EventHandler<>(); - public final EventHandler> stopEvent = new EventHandler<>(); - - public ProcessThread(ProcessMonitor monitor, boolean readError) { - this.monitor = monitor; - this.readError = readError; - p = monitor.getProcess(); - setDaemon(readError); - } - - public IProcess getProcess() { - return p; - } - - /** - * Only get stdout or stderr output according to readError(). - * Invoke this method only if the process thread has stopped. - */ - public List getLines() { - return lines; - } - - @Override - public void run() { - setName("ProcessMonitor"); - BufferedReader br = null; - try { - InputStream in = readError ? p.getRawProcess().getErrorStream() : p.getRawProcess().getInputStream(); - br = new BufferedReader(new InputStreamReader(in, Charsets.toCharset())); - - String line; - while (p.isRunning()) - while ((line = br.readLine()) != null) - println(line); - while ((line = br.readLine()) != null) - println(line); - } catch (IOException e) { - HMCLog.err("An error occured when reading process stdout/stderr.", e); - } finally { - IOUtils.closeQuietly(br); - } - stopEvent.fire(new SimpleEvent<>(this, p)); - } - - protected void println(String line) { - printlnEvent.fire(new PrintlnEvent(monitor, line, readError)); - lines.add(line); - p.getStdOutLines().add(line); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/ReflectionHelper.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/ReflectionHelper.java deleted file mode 100644 index 3b0fb9db5..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/ReflectionHelper.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.sys; - -import java.lang.reflect.AccessibleObject; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; -import sun.misc.Unsafe; - -/** - * This class is for breaking the module system of Java 9. - * @author huang - */ -public class ReflectionHelper { - - private static Unsafe unsafe = null; - private static long objectFieldOffset; - - static { - try { - unsafe = AccessController.doPrivileged(new PrivilegedExceptionAction () { - @Override - public Unsafe run() throws Exception { - Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafe.setAccessible(true); - return (Unsafe) theUnsafe.get(null); - } - }); - Field overrideField = AccessibleObject.class.getDeclaredField("override"); - objectFieldOffset = unsafe.objectFieldOffset(overrideField); - } catch (Throwable ex) { - } - } - - private static void setAccessible(AccessibleObject obj) { - unsafe.putBoolean(obj, objectFieldOffset, true); - } - - public static T get(Object obj, String fieldName) { - try { - Method method = obj.getClass().getDeclaredMethod(fieldName); - setAccessible(method); - return (T) method.invoke(obj); - } catch (Throwable ex) { - return null; - } - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/WaitForThread.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/WaitForThread.java deleted file mode 100644 index 05f05af95..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/WaitForThread.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.sys; - -import java.util.concurrent.CountDownLatch; -import org.jackhuang.hmcl.api.HMCLog; - -/** - * - * @author huang - */ -public class WaitForThread extends Thread { - - CountDownLatch latch; - Runnable done; - - public WaitForThread(CountDownLatch latch, Runnable done) { - this.latch = latch; - } - - @Override - public void run() { - try { - latch.await(); - } catch (InterruptedException ex) { - HMCLog.err("Interrupted latch waiting"); - } - done.run(); - } - - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/ZipEngine.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/ZipEngine.java deleted file mode 100644 index 4f0eba237..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/sys/ZipEngine.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.sys; - -import java.io.BufferedOutputStream; -import java.io.ByteArrayInputStream; -import java.io.Closeable; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.HashSet; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; -import org.jackhuang.hmcl.api.func.BiFunction; - -/** - * Non thread-safe - * - * @author huangyuhui - */ -public class ZipEngine implements Closeable { - - byte[] buf = new byte[1024]; - ZipOutputStream zos; - - public ZipEngine(File f) throws IOException { - zos = new ZipOutputStream(new BufferedOutputStream(FileUtils.openOutputStream(f))); - } - - @Override - public void close() throws IOException { - zos.closeEntry(); - zos.close(); - } - - public void putDirectory(File sourceDir) throws IOException { - putDirectory(sourceDir, null); - } - - /** - * 功能:把 sourceDir 目录下的所有文件进行 zip 格式的压缩,保存为指定 zip 文件 - * - * @param sourceDir 源文件夹 - * @param pathNameCallback callback(pathName, isDirectory) returns your - * modified pathName - * - * @throws java.io.IOException 压缩失败或无法读取 - */ - public void putDirectory(File sourceDir, BiFunction pathNameCallback) throws IOException { - putDirectoryImpl(sourceDir, sourceDir.isDirectory() ? sourceDir.getPath() : sourceDir.getParent(), pathNameCallback); - } - - /** - * 将文件压缩成zip文件 - * - * @param source zip文件路径 - * @param basePath 待压缩文件根目录 - * @param zos zip文件的os - * @param pathNameCallback callback(pathName, isDirectory) returns your - * modified pathName, null if you dont want this file zipped - */ - private void putDirectoryImpl(File source, String basePath, BiFunction pathNameCallback) throws IOException { - File[] files; - if (source.isDirectory()) - files = source.listFiles(); - else { - files = new File[1]; - files[0] = source; - } - if (files == null) - return; - String pathName;//存相对路径(相对于待压缩的根目录) - for (File file : files) - if (file.isDirectory()) { - pathName = file.getPath().substring(basePath.length() + 1) - + "/"; - pathName = pathName.replace('\\', '/'); - if (pathNameCallback != null) - pathName = pathNameCallback.apply(pathName, true); - if (pathName == null) - continue; - put(new ZipEntry(pathName)); - putDirectoryImpl(file, basePath, pathNameCallback); - } else { - if (".DS_Store".equals(file.getName())) // For Mac computers. - continue; - pathName = file.getPath().substring(basePath.length() + 1); - pathName = pathName.replace('\\', '/'); - if (pathNameCallback != null) - pathName = pathNameCallback.apply(pathName, false); - if (pathName == null) - continue; - putFile(file, pathName); - } - } - - public void putFile(File file, String pathName) throws IOException { - try (FileInputStream fis = FileUtils.openInputStream(file)) { - putStream(fis, pathName); - } - } - - public void putStream(InputStream is, String pathName) throws IOException { - put(new ZipEntry(pathName)); - IOUtils.copyStream(is, zos, buf); - } - - public void putTextFile(String text, String pathName) throws IOException { - putTextFile(text, "UTF-8", pathName); - } - - public void putTextFile(String text, String encoding, String pathName) throws IOException { - putStream(new ByteArrayInputStream(text.getBytes(encoding)), pathName); - } - - protected HashSet names = new HashSet<>(); - - public void put(ZipEntry entry) throws IOException { - if (names.add(entry.getName())) - zos.putNextEntry(entry); - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/DeleteFileTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/DeleteFileTask.java deleted file mode 100644 index 256325c02..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/DeleteFileTask.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.task; - -import java.io.File; -import java.io.IOException; - -/** - * - * @author huangyuhui - */ -public class DeleteFileTask extends Task { - - File f; - - public DeleteFileTask(File f) { - this.f = f; - } - - @Override - public void executeTask(boolean areDependTasksSucceeded) throws IOException { - if (!f.delete()) throw new IOException("Failed to delete" + f); - } - - @Override - public String getInfo() { - return "Delete: " + f.getAbsolutePath(); - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/DoingDoneListener.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/DoingDoneListener.java deleted file mode 100644 index 7c5e7c673..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/DoingDoneListener.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.task; - -import java.util.Collection; - -/** - * - * @author huangyuhui - */ -public interface DoingDoneListener { - - /** - * Task done. - * - * @param k - */ - void onDone(K k, Collection tasks); - - /** - * Before task executing. - * - * @param k - */ - void onDoing(K k, Collection tasks); - - /** - * Task failed. - * - * @param k - */ - void onFailed(K k); -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/DoubleTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/DoubleTask.java deleted file mode 100644 index 2bd7d2fa5..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/DoubleTask.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.task; - -import java.util.Arrays; -import java.util.Collection; - -/** - * - * @author huangyuhui - */ -public class DoubleTask extends TaskInfo { - - Task a, b; - boolean reliant; - - public DoubleTask(Task a, Task b) { - this(a, b, true); - } - - public DoubleTask(Task a, Task b, boolean reliant) { - this(a, b, "Double Task", reliant); - } - - public DoubleTask(Task a, Task b, String info, boolean reliant) { - super(info); - this.a = a; - this.b = b; - this.reliant = reliant; - hidden = true; - } - - @Override - public Collection getDependTasks() { - return Arrays.asList(a); - } - - @Override - public Collection getAfterTasks() { - return Arrays.asList(b); - } - - @Override - public void executeTask(boolean areDependTasksSucceeded) throws IllegalStateException { - if (!areDependTasksSucceeded && reliant) - throw new IllegalStateException("Depend tasks failed."); - } - - @Override - public Task setProgressProviderListener(ProgressProviderListener p) { - a.setProgressProviderListener(p); - b.setProgressProviderListener(p); - return this; - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/NoShownTaskException.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/NoShownTaskException.java deleted file mode 100644 index 40b20601d..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/NoShownTaskException.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.task; - -/** - * - * @author huangyuhui - */ -public class NoShownTaskException extends RuntimeException { - private static final long serialVersionUID = 4893571368018439312L; - - public NoShownTaskException(String msg) { - super(msg); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/ParallelTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/ParallelTask.java deleted file mode 100644 index 2cbffa361..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/ParallelTask.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.task; - -import java.util.Collection; -import java.util.HashSet; - -/** - * - * @author huangyuhui - */ -public class ParallelTask extends Task { - - Collection tasks = new HashSet<>(); - - public ParallelTask() { - hidden = true; - } - - @Override - public void executeTask(boolean areDependTasksSucceeded) throws Exception { - if (!areDependTasksSucceeded) - throw new Exception("Tasks failed"); - } - - @Override - public String getInfo() { - return "PARALLEL"; - } - - @Override - public Collection getDependTasks() { - return tasks; - } - - public ParallelTask addTask(Task t) { - tasks.add(t); - return this; - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/ProgressProviderListener.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/ProgressProviderListener.java deleted file mode 100644 index 3ef8f23eb..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/ProgressProviderListener.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.task; - -/** - * - * @author huangyuhui - */ -public interface ProgressProviderListener { - - void setProgress(Task task, int prog, int max); - - void setStatus(Task task, String sta); - - void onProgressProviderDone(Task task); -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/Task.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/Task.java deleted file mode 100644 index ad81e5637..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/Task.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.task; - -import java.util.Collection; -import org.jackhuang.hmcl.util.AbstractSwingWorker; - -/** - * Create a new instance when you use a task anyway. - * @author huangyuhui - */ -public abstract class Task { - - /** - * Run in a new thread(packed in TaskList). - * - * @param areDependTasksSucceeded Would be true if all of tasks which this task depends on have succeed. - * @throws java.lang.Throwable If a task throws an exception, this task will be marked as `failed`. - */ - public abstract void executeTask(boolean areDependTasksSucceeded) throws Exception; - - /** - * if this func returns false, TaskList will force abort the thread. run in - * main thread. - * - * @return is aborted. - */ - public boolean abort() { - aborted = true; - return false; - } - - protected boolean aborted = false; - - public boolean isAborted() { - return aborted; - } - - protected boolean hidden = false; - - public boolean isHidden() { - return hidden; - } - - public Exception getFailReason() { - return failReason; - } - protected Exception failReason = null; - - /** - * This method can be only invoked by TaskList. - * - * @param s what the `executeTask` throws. - */ - protected void setFailReason(Exception s) { - failReason = s; - } - - protected String tag; - - /** - * For FileDownloadTask: info replacement. - * - * @return - */ - public String getTag() { - return tag; - } - - public Task setTag(String tag) { - this.tag = tag; - return this; - } - - public abstract String getInfo(); - - public Collection getDependTasks() { - return null; - } - - public Collection getAfterTasks() { - return null; - } - - protected ProgressProviderListener ppl; - - public Task setProgressProviderListener(ProgressProviderListener p) { - ppl = p; - return this; - } - - public Task with(Task t) { - return new DoubleTask(this, t); - } - - public void runWithException() throws Exception { - Collection c = getDependTasks(); - if (c != null) - for (Task t : c) { - if (t.ppl == null) - t.setProgressProviderListener(this.ppl); - t.runWithException(); - } - executeTask(true); - c = getAfterTasks(); - if (c != null) - for (Task t : c) { - if (t.ppl == null) - t.setProgressProviderListener(this.ppl); - t.runWithException(); - } - } - - public void runAsync() { - new AbstractSwingWorker() { - @Override - protected void work() throws Exception { - runWithException(); - } - }.execute(); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/TaskInfo.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/TaskInfo.java deleted file mode 100644 index 3342d9d97..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/TaskInfo.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.task; - -/** - * - * @author huangyuhui - */ -public abstract class TaskInfo extends Task { - - public TaskInfo(String info) { - this.tag = info; - } - - @Override - public String getInfo() { - return tag; - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/TaskList.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/TaskList.java deleted file mode 100644 index 4b89d7a57..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/TaskList.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.task; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.EventObject; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.atomic.AtomicBoolean; -import org.jackhuang.hmcl.api.event.EventHandler; -import org.jackhuang.hmcl.api.HMCLog; - -/** - * - * @author huangyuhui - */ -public class TaskList extends Thread { - - List taskQueue = Collections.synchronizedList(new LinkedList<>()); - public final EventHandler doneEvent = new EventHandler<>(); - ArrayList> taskListener = new ArrayList<>(); - - int totTask; - boolean shouldContinue = true; - - public TaskList() { - setDaemon(true); - } - - public void addTaskListener(DoingDoneListener l) { - taskListener.add(l); - } - - public void addTask(Task task) { - taskQueue.add(task); - } - - public int taskCount() { - return totTask; - } - - private class Invoker implements Runnable { - - Task task; - CountDownLatch latch; - AtomicBoolean bool; - - public Invoker(Task task, CountDownLatch latch, AtomicBoolean bool) { - this.task = task; - this.latch = latch; - this.bool = bool; - } - - @Override - public void run() { - try { - if (!executeTask(task)) - bool.set(false); - } finally { - latch.countDown(); - } - } - - } - - ExecutorService EXECUTOR_SERVICE = Executors.newFixedThreadPool(8); - HashMap> futures = new HashMap<>(); - HashSet invokers = new HashSet<>(); - - private boolean processTasks(Collection c) { - if (c == null || c.isEmpty()) - return true; - this.totTask += c.size(); - AtomicBoolean bool = new AtomicBoolean(true); - CountDownLatch counter = new CountDownLatch(c.size()); - for (Task t2 : c) { - if (t2 == null) { - counter.countDown(); - continue; - } - Invoker thread = new Invoker(t2, counter, bool); - invokers.add(thread); - if (!EXECUTOR_SERVICE.isShutdown()) - futures.put(thread, EXECUTOR_SERVICE.submit(thread)); - } - try { - counter.await(); - return bool.get(); - } catch (InterruptedException ignore) { // this task is canceled, so failed. - return false; - } - } - - private boolean executeTask(Task t) { - if (!shouldContinue) - return false; - if (t == null) - return true; - - Collection c = t.getDependTasks(); - if (c == null) - c = new HashSet<>(); - HMCLog.log("Executing task: " + t.getInfo()); - for (DoingDoneListener d : taskListener) - d.onDoing(t, c); - boolean areDependTasksSucceeded = processTasks(c); - - boolean flag = true; - try { - t.executeTask(areDependTasksSucceeded); - } catch (Exception e) { - t.setFailReason(e); - flag = false; - } - if (flag) { - HMCLog.log((t.isAborted() ? "Task aborted: " : "Task finished: ") + t.getInfo()); - Collection at = t.getAfterTasks(); - if (at == null) - at = new HashSet<>(); - for (DoingDoneListener d : taskListener) - d.onDone(t, at); - processTasks(at); - } else { - HMCLog.err("Task failed: " + t.getInfo(), t.getFailReason()); - for (DoingDoneListener d : taskListener) - d.onFailed(t); - } - return flag; - } - - @Override - public void run() { - Thread.currentThread().setName("Task List"); - - totTask = taskQueue.size(); - while (!taskQueue.isEmpty()) - executeTask(taskQueue.remove(0)); - if (shouldContinue) { - HMCLog.log("Tasks are successfully finished."); - doneEvent.fire(new EventObject(this)); - } - } - - public boolean isEmpty() { - return taskQueue.isEmpty(); - } - - public void abort() { - shouldContinue = false; - final HashSet in = this.invokers; - EXECUTOR_SERVICE.shutdown(); - while (!in.isEmpty()) - synchronized (in) { - Invoker it = in.iterator().next(); - if (!it.task.abort() && futures.get(it) != null) - futures.get(it).cancel(true); - in.remove(it); - } - this.interrupt(); - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/TaskRunnable.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/TaskRunnable.java deleted file mode 100644 index d9013b599..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/TaskRunnable.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.task; - -/** - * - * @author huangyuhui - */ -public class TaskRunnable extends TaskInfo { - - private final Runnable r; - - public TaskRunnable(String info, Runnable r) { - super(info); - this.r = r; - } - - public TaskRunnable(Runnable r) { - this("TaskRunnable", r); - } - - @Override - public void executeTask(boolean areDependTasksSucceeded) { - r.run(); - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/TaskWindow.form b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/TaskWindow.form deleted file mode 100644 index 1a8026bcd..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/TaskWindow.form +++ /dev/null @@ -1,93 +0,0 @@ - - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/TaskWindow.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/TaskWindow.java deleted file mode 100644 index 2605bdc67..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/TaskWindow.java +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.task; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.LinkedList; -import javax.swing.SwingUtilities; -import javax.swing.table.TableColumn; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.util.ui.MessageBox; -import org.jackhuang.hmcl.util.StrUtils; -import org.jackhuang.hmcl.util.ui.SwingUtils; - -/** - * - * @author huangyuhui - */ -public class TaskWindow extends javax.swing.JDialog - implements ProgressProviderListener, DoingDoneListener { - - private static volatile TaskWindow INST = null; - - public static TaskWindowFactory factory() { - return new TaskWindowFactory(); - } - - boolean suc = false; - - private transient TaskList taskList; - private final ArrayList failReasons = new ArrayList<>(); - private String stackTrace = null, lastStackTrace = null; - - /** - * Creates new form DownloadWindow - */ - private TaskWindow() { - initComponents(); - - if (lstDownload.getColumnModel().getColumnCount() > 1) { - int i = 35; - TableColumn c = lstDownload.getColumnModel().getColumn(1); - c.setMinWidth(i); - c.setMaxWidth(i); - c.setPreferredWidth(i); - } - - setModal(true); - setLocationRelativeTo(null); - } - - private synchronized void clean() { - if (isVisible()) - return; - taskList = new TaskList(); - taskList.addTaskListener(this); - taskList.doneEvent.register(SwingUtils.invokeLater(() -> { - dispose(); - suc = true; - })); - } - - public static String downloadSource = ""; - - private boolean start() { - if (isVisible() || taskList == null || taskList.isAlive()) - return false; - pgsTotal.setValue(0); - suc = false; - SwingUtils.clearDefaultTable(lstDownload); - failReasons.clear(); - tasks.clear(); - try { - taskList.start(); - } catch (Exception e) { - HMCLog.err("Failed to start thread, maybe there're already a taskwindow here.", e); - HMCLog.err("There's the stacktrace of the this invoking."); - HMCLog.err(stackTrace); - HMCLog.err("There's the stacktrace of the last invoking."); - HMCLog.err(lastStackTrace); - MessageBox.show(C.i18n("taskwindow.no_more_instance")); - return false; - } - setTitle(C.i18n("taskwindow.title") + " - " + C.i18n("download.source") + ": " + downloadSource); - this.setVisible(true); - return this.areTasksFinished(); - } - - /** - * This method is called from within the constructor to initialize the form. - * WARNING: Do NOT modify this code. The content of this method is always - * regenerated by the Form Editor. - */ - @SuppressWarnings("unchecked") - // //GEN-BEGIN:initComponents - private void initComponents() { - - btnCancel = new javax.swing.JButton(); - pgsTotal = new javax.swing.JProgressBar(); - srlDownload = new javax.swing.JScrollPane(); - lstDownload = new javax.swing.JTable(); - - setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); - setTitle(C.i18n("taskwindow.title")); // NOI18N - addWindowListener(new java.awt.event.WindowAdapter() { - public void windowClosed(java.awt.event.WindowEvent evt) { - formWindowClosed(evt); - } - }); - - btnCancel.setText(C.i18n("taskwindow.cancel")); // NOI18N - btnCancel.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - btnCancelActionPerformed(evt); - } - }); - - pgsTotal.setStringPainted(true); - - lstDownload.setModel(SwingUtils.makeDefaultTableModel(new String[]{C.i18n("taskwindow.file_name"), C.i18n("taskwindow.download_progress")}, new Class[]{String.class, String.class}, new boolean[]{false,false}) - ); - lstDownload.setRowSelectionAllowed(false); - lstDownload.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); - srlDownload.setViewportView(lstDownload); - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); - getContentPane().setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addComponent(pgsTotal, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnCancel) - .addContainerGap()) - .addComponent(srlDownload, javax.swing.GroupLayout.DEFAULT_SIZE, 517, Short.MAX_VALUE) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(srlDownload, javax.swing.GroupLayout.DEFAULT_SIZE, 290, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(pgsTotal, javax.swing.GroupLayout.PREFERRED_SIZE, 22, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(btnCancel, javax.swing.GroupLayout.PREFERRED_SIZE, 22, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addContainerGap()) - ); - - pack(); - }// //GEN-END:initComponents - - private void btnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCancelActionPerformed - if (MessageBox.show(C.i18n("operation.confirm_stop"), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION) - this.dispose(); - }//GEN-LAST:event_btnCancelActionPerformed - - private void formWindowClosed(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosed - if (taskList == null) - return; - tasks.clear(); - - if (!this.failReasons.isEmpty()) { - String str = StrUtils.parseParams("", failReasons.toArray(), "\n"); - SwingUtilities.invokeLater(() -> MessageBox.show(str, C.i18n("message.error"), MessageBox.ERROR_MESSAGE)); - failReasons.clear(); - } - - if (!suc) { - SwingUtilities.invokeLater(taskList::abort); - HMCLog.log("Tasks have been canceled by user."); - } - taskList = null; - }//GEN-LAST:event_formWindowClosed - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JButton btnCancel; - private javax.swing.JTable lstDownload; - private javax.swing.JProgressBar pgsTotal; - private javax.swing.JScrollPane srlDownload; - // End of variables declaration//GEN-END:variables - - final ArrayList tasks = new ArrayList<>(); - final ArrayList progresses = new ArrayList<>(); - - @Override - public void setProgress(Task task, int progress, int max) { - SwingUtilities.invokeLater(() -> { - if (task == null) - return; - int idx = tasks.indexOf(task); - if (idx == -1) - return; - int pgs = progress * 100 / max; - if (progresses.size() > idx && progresses.get(idx) != pgs && lstDownload.getRowCount() > idx) { - SwingUtils.setValueAt(lstDownload, pgs < 0 ? "???" : pgs + "%", idx, 1); - progresses.set(idx, pgs); - } - }); - } - - @Override - public void onDoing(Task task, Collection taskCollection) { - if (task == null || task.isHidden()) - return; - task.setProgressProviderListener(this); - - SwingUtilities.invokeLater(() -> { - if (taskList == null) - return; - tasks.add(task); - progresses.add(-1); - SwingUtils.appendLast(lstDownload, task.getInfo(), "0%"); - SwingUtils.moveEnd(srlDownload); - }); - } - - public boolean areTasksFinished() { - return suc; - } - - @Override - public void onDone(Task task, Collection taskCollection) { - if (task == null || task.isHidden()) - return; - SwingUtilities.invokeLater(() -> { - if (taskList == null) - return; - pgsTotal.setMaximum(taskList.taskCount()); - pgsTotal.setValue(pgsTotal.getValue() + 1); - int idx = tasks.indexOf(task); - if (idx == -1) - return; - tasks.remove(idx); - progresses.remove(idx); - SwingUtils.removeRow(lstDownload, idx); - }); - } - - @Override - public void onFailed(Task task) { - if (task == null || task.isHidden()) - return; - SwingUtilities.invokeLater(() -> { - if (taskList == null) - return; - String msg = null; - if (task.getFailReason() != null && !(task.getFailReason() instanceof NoShownTaskException)) - if (StrUtils.isBlank(task.getFailReason().getLocalizedMessage())) - msg = task.getFailReason().getClass().getSimpleName(); - else - msg = task.getFailReason().getLocalizedMessage(); - if (msg != null) - failReasons.add(task.getInfo() + ": " + msg); - pgsTotal.setMaximum(taskList.taskCount()); - pgsTotal.setValue(pgsTotal.getValue() + 1); - int idx = tasks.indexOf(task); - if (idx == -1) - return; - SwingUtils.setValueAt(lstDownload, task.getFailReason(), idx, 0); - SwingUtils.setValueAt(lstDownload, "0%", idx, 1); - SwingUtils.moveEnd(srlDownload); - }); - } - - @Override - public void onProgressProviderDone(Task task) { - - } - - @Override - public void setStatus(Task task, String sta) { - if (task == null || task.isHidden()) - return; - SwingUtilities.invokeLater(() -> { - if (taskList == null) - return; - int idx = tasks.indexOf(task); - if (idx != -1) - SwingUtils.setValueAt(lstDownload, task.getInfo() + ": " + sta, idx, 0); - }); - } - - public static class TaskWindowFactory { - - LinkedList ll = new LinkedList<>(); - - public TaskWindowFactory append(Task ts) { - if (ts != null) - ll.add(ts); - return this; - } - - public boolean execute(Task... ts) { - for (Task t : ts) - append(t); - String stacktrace = StrUtils.getStackTrace(new Throwable()); - return SwingUtils.invokeAndWait(() -> { - if (INST == null) - INST = new TaskWindow(); - INST.clean(); - synchronized (INST) { - if (INST.isVisible()) - return false; - for (Task t : ll) - INST.taskList.addTask(t); - INST.lastStackTrace = INST.stackTrace; - INST.stackTrace = stacktrace; - return INST.start(); - } - }); - } - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/TaskWorker.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/TaskWorker.java deleted file mode 100644 index 9ac7bf826..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/TaskWorker.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.task; - -import java.util.List; -import org.jackhuang.hmcl.api.func.Consumer; -import org.jackhuang.hmcl.util.AbstractSwingWorker; - -/** - * - * @author huang - */ -public abstract class TaskWorker extends Task { - - protected final AbstractSwingWorker worker; - - public TaskWorker() { - worker = new AbstractSwingWorker() { - @Override - protected void work() throws Exception { - runWithException(); - } - }; - } - - public TaskWorker reg(Consumer c) { - worker.reg(c); - return this; - } - - public TaskWorker regDone(Runnable c) { - worker.regDone(c); - return this; - } - - public void send(T... result) { - worker.send(result); - } - - @Override - public String getInfo() { - return "TaskWorker"; - } - - @Override - public void runAsync() { - worker.execute(); - } - - public List justDo() throws Exception { - return worker.justDo(); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/comm/PreviousResult.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/comm/PreviousResult.java deleted file mode 100644 index 767a223c2..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/comm/PreviousResult.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.task.comm; - -/** - * - * @author huangyuhui - * @param Task result type - */ -public interface PreviousResult { - - T getResult(); - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/comm/PreviousResultRegistrar.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/comm/PreviousResultRegistrar.java deleted file mode 100644 index eb6afc517..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/task/comm/PreviousResultRegistrar.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.task.comm; - -import org.jackhuang.hmcl.util.task.Task; - -/** - * - * @author huangyuhui - * @param Previous task result type - */ -public interface PreviousResultRegistrar { - - /** - * - * @param pr previous task handler - * - * @return task self instance(factory mode!) - */ - Task registerPreviousResult(PreviousResult pr); -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/AbstractFilter.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/AbstractFilter.java deleted file mode 100644 index 005c173ef..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/AbstractFilter.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.ui; - -import java.awt.Rectangle; -import java.awt.RenderingHints; -import java.awt.geom.Point2D; -import java.awt.geom.Rectangle2D; -import java.awt.image.BufferedImage; -import java.awt.image.BufferedImageOp; -import java.awt.image.ColorModel; - -public abstract class AbstractFilter - implements BufferedImageOp { - - @Override - public abstract BufferedImage filter(BufferedImage paramBufferedImage1, BufferedImage paramBufferedImage2); - - @Override - public Rectangle2D getBounds2D(BufferedImage src) { - return new Rectangle(0, 0, src.getWidth(), src.getHeight()); - } - - @Override - public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel destCM) { - if (destCM == null) - destCM = src.getColorModel(); - - return new BufferedImage(destCM, destCM.createCompatibleWritableRaster(src.getWidth(), src.getHeight()), destCM.isAlphaPremultiplied(), null); - } - - @Override - public Point2D getPoint2D(Point2D srcPt, Point2D dstPt) { - return (Point2D) srcPt.clone(); - } - - @Override - public RenderingHints getRenderingHints() { - return null; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/BasicColors.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/BasicColors.java deleted file mode 100644 index 38702da5d..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/BasicColors.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.ui; - -import java.awt.Color; - -/** - * - * @author huangyuhui - */ -public final class BasicColors { - - private BasicColors() { - } - - private static Color getWebColor(String c) { - return new Color( - Integer.parseInt(c.substring(0, 2), 16), - Integer.parseInt(c.substring(2, 4), 16), - Integer.parseInt(c.substring(4, 6), 16) - ); - } - - public static final Color COLOR_RED = new Color(229, 0, 0); - public static final Color COLOR_RED_DARKER = new Color(157, 41, 51); - public static final Color COLOR_GREEN = new Color(90, 184, 96); - public static final Color COLOR_BLUE = new Color(16, 108, 163); - public static final Color COLOR_BLUE_DARKER = new Color(12, 94, 145); - public static final Color COLOR_WHITE_TEXT = new Color(254, 254, 254); - public static final Color COLOR_CENTRAL_BACK = new Color(25, 30, 34, 160); - - public static final Color[] BG_COLORS = new Color[] { - COLOR_BLUE, - getWebColor("1ABC9C"), - getWebColor("9B59B6"), - getWebColor("34495E"), - getWebColor("E67E22"), - getWebColor("E74C3C") - }; - - public static final Color[] BG_COLORS_DARKER = new Color[] { - COLOR_BLUE_DARKER, - getWebColor("16A085"), - getWebColor("8E44AD"), - getWebColor("2C3E50"), - getWebColor("D35400"), - getWebColor("C0392B") - }; -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/DropShadowBorder.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/DropShadowBorder.java deleted file mode 100644 index 2ce3ac780..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/DropShadowBorder.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.ui; - -import java.awt.AlphaComposite; -import java.awt.Color; -import java.awt.Component; -import java.awt.Composite; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Insets; -import java.awt.RenderingHints; -import java.awt.image.BufferedImage; -import java.util.HashMap; -import javax.swing.border.AbstractBorder; -import org.jackhuang.hmcl.util.Pair; - -public class DropShadowBorder extends AbstractBorder { - - private Color color; - private int thickness = 1; - private Insets insets = null; - RenderingHints hints; - - public DropShadowBorder(Color color, int thickness) { - this.thickness = thickness; - this.color = color; - this.hints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - - this.insets = new Insets(thickness * 4, thickness * 4, thickness * 4, thickness * 4); - } - - public void setColor(Color c) { - color = c; - } - - @Override - public Insets getBorderInsets(Component c) { - return this.insets; - } - - @Override - public Insets getBorderInsets(Component c, Insets insets) { - return getBorderInsets(c); - } - - private static final HashMap, BufferedImage> CACHE = new HashMap<>(); - - @Override - public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { - Pair pair = new Pair<>(width, height); - BufferedImage list; - int border = this.thickness * 4; - if (CACHE.containsKey(pair)) list = CACHE.get(pair); - else { - BufferedImage shadow = new BufferedImage(width, height, 2); - - Graphics2D g2 = shadow.createGraphics(); - g2.setRenderingHints(this.hints); - Composite oldComposite = g2.getComposite(); - AlphaComposite composite = AlphaComposite.getInstance(1, 0.0F); - g2.setComposite(composite); - g2.setColor(new Color(0, 0, 0, 0)); - g2.fillRect(0, 0, width, height); - g2.setComposite(oldComposite); - g2.setColor(this.color); - g2.fillRect(border, border + border / 6, width - border * 2, height - border * 2); - g2.dispose(); - - FastBlurFilter blur = new FastBlurFilter(this.thickness); - shadow = blur.filter(shadow, null); - shadow = blur.filter(shadow, null); - shadow = blur.filter(shadow, null); - shadow = blur.filter(shadow, null); - CACHE.put(pair, list = shadow); - } - g.drawImage(list, 0, 0, width, height, null); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/FastBlurFilter.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/FastBlurFilter.java deleted file mode 100644 index 087d4252d..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/FastBlurFilter.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.ui; - -import java.awt.image.BufferedImage; - -public class FastBlurFilter extends AbstractFilter { - - private final int radius; - - public FastBlurFilter() { - this(3); - } - - public FastBlurFilter(int radius) { - if (radius < 1) - radius = 1; - - this.radius = radius; - } - - public int getRadius() { - return this.radius; - } - - @Override - public BufferedImage filter(BufferedImage src, BufferedImage dst) { - int width = src.getWidth(); - int height = src.getHeight(); - return filter(src, new int[width * height], dst, new int[width * height]); - } - - public BufferedImage filter(BufferedImage src, int[] srcPixels, BufferedImage dst, int[] dstPixels) { - int width = src.getWidth(); - int height = src.getHeight(); - - if (dst == null) - dst = createCompatibleDestImage(src, null); - - GraphicsUtils.getPixels(src, 0, 0, width, height, srcPixels); - - blur(srcPixels, dstPixels, width, height, this.radius); - blur(dstPixels, srcPixels, height, width, this.radius); - - GraphicsUtils.setPixels(dst, 0, 0, width, height, srcPixels); - - return dst; - } - - static void blur(int[] srcPixels, int[] dstPixels, int width, int height, int radius) { - int windowSize = radius * 2 + 1; - int radiusPlusOne = radius + 1; - - int srcIndex = 0; - - int[] sumLookupTable = new int[256 * windowSize]; - for (int i = 0; i < sumLookupTable.length; i++) - sumLookupTable[i] = (i / windowSize); - - int[] indexLookupTable = new int[radiusPlusOne]; - if (radius < width) - for (int i = 0; i < indexLookupTable.length; i++) - indexLookupTable[i] = i; - else { - for (int i = 0; i < width; i++) - indexLookupTable[i] = i; - for (int i = width; i < indexLookupTable.length; i++) - indexLookupTable[i] = (width - 1); - } - - for (int y = 0; y < height; y++) { - int sumBlue; - int sumGreen; - int sumRed; - int sumAlpha = sumRed = sumGreen = sumBlue = 0; - int dstIndex = y; - - int pixel = srcPixels[srcIndex]; - sumAlpha += radiusPlusOne * (pixel >> 24 & 0xFF); - sumRed += radiusPlusOne * (pixel >> 16 & 0xFF); - sumGreen += radiusPlusOne * (pixel >> 8 & 0xFF); - sumBlue += radiusPlusOne * (pixel & 0xFF); - - for (int i = 1; i <= radius; i++) { - pixel = srcPixels[(srcIndex + indexLookupTable[i])]; - sumAlpha += (pixel >> 24 & 0xFF); - sumRed += (pixel >> 16 & 0xFF); - sumGreen += (pixel >> 8 & 0xFF); - sumBlue += (pixel & 0xFF); - } - - for (int x = 0; x < width; x++) { - dstPixels[dstIndex] = (sumLookupTable[sumAlpha] << 24 | sumLookupTable[sumRed] << 16 | sumLookupTable[sumGreen] << 8 | sumLookupTable[sumBlue]); - - dstIndex += height; - - int nextPixelIndex = x + radiusPlusOne; - if (nextPixelIndex >= width) - nextPixelIndex = width - 1; - - int previousPixelIndex = x - radius; - if (previousPixelIndex < 0) - previousPixelIndex = 0; - - int nextPixel = srcPixels[(srcIndex + nextPixelIndex)]; - int previousPixel = srcPixels[(srcIndex + previousPixelIndex)]; - - sumAlpha += (nextPixel >> 24 & 0xFF); - sumAlpha -= (previousPixel >> 24 & 0xFF); - - sumRed += (nextPixel >> 16 & 0xFF); - sumRed -= (previousPixel >> 16 & 0xFF); - - sumGreen += (nextPixel >> 8 & 0xFF); - sumGreen -= (previousPixel >> 8 & 0xFF); - - sumBlue += (nextPixel & 0xFF); - sumBlue -= (previousPixel & 0xFF); - } - - srcIndex += width; - } - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/GaussionPanel.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/GaussionPanel.java deleted file mode 100644 index 8f5b466da..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/GaussionPanel.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.ui; - -import java.awt.AlphaComposite; -import java.awt.Color; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Image; -import java.awt.Rectangle; -import java.awt.image.BufferedImage; -import java.util.ArrayList; -import java.util.List; -import javax.swing.JPanel; - -/** - * This component will allow some area blured to provide better UI. - * @author huangyuhui - */ -public class GaussionPanel extends JPanel { - - private transient BufferedImage aeroBuffer; - private transient Image backgroundImage; - private final List aeroObject = new ArrayList<>(); - private transient Graphics2D aeroGraphics; - private static final int RADIUS = 10; - private transient final StackBlurFilter stackBlurFilter = new StackBlurFilter(RADIUS); - private transient BufferedImage cache = null; - private boolean drawBackgroundLayer = false; - - public boolean isDrawBackgroundLayer() { - return drawBackgroundLayer; - } - - public void setDrawBackgroundLayer(boolean drawBackgroundLayer) { - this.drawBackgroundLayer = drawBackgroundLayer; - } - - public void setBackgroundImage(Image backgroundImage) { - this.backgroundImage = backgroundImage; - } - - /** - * The background will be blured under the aero object. - * @param aeroObject just need its bounds, keep it not opaque. - */ - public void addAeroObject(JPanel aeroObject) { - this.aeroObject.add(aeroObject); - cache = null; - } - - @Override - protected void paintComponent(Graphics g) { - super.paintComponent(g); - - if (backgroundImage == null) - return; - - // If we cache the processed background image, the CPU ratio will reduce 5%. - if (cache == null || getWidth() != cache.getWidth() || getHeight() != cache.getHeight()) { - cache = new BufferedImage(getWidth(), getHeight(), 2); - Graphics2D g2 = cache.createGraphics(); - g2.drawImage(backgroundImage, 0, 0, getWidth(), getHeight(), null); - for (JPanel panel : aeroObject) { - Rectangle aeroRect = panel.getBounds(); - if (aeroBuffer == null || aeroBuffer.getWidth() != aeroRect.width + RADIUS || aeroBuffer.getHeight() != aeroRect.height + RADIUS) { - if (aeroBuffer != null && aeroGraphics != null) { - aeroBuffer.flush(); - aeroGraphics.dispose(); - } - aeroBuffer = new BufferedImage(aeroRect.width + RADIUS, aeroRect.height + RADIUS, BufferedImage.TRANSLUCENT); - } - - aeroGraphics = aeroBuffer.createGraphics(); - aeroGraphics.setComposite(AlphaComposite.Src); - aeroGraphics.drawImage(backgroundImage, 0, 0, aeroBuffer.getWidth(), aeroBuffer.getHeight(), aeroRect.x, aeroRect.y, aeroRect.x + aeroRect.width, aeroRect.y + aeroRect.height, null); - aeroBuffer = stackBlurFilter.filter(aeroBuffer, null); - g2.drawImage(aeroBuffer, aeroRect.x, aeroRect.y, aeroRect.x + aeroRect.width, aeroRect.y + aeroRect.height, RADIUS / 2, RADIUS / 2, RADIUS / 2 + aeroRect.width, RADIUS / 2 + aeroRect.height, null); - - // Moved from GameSettingsPanel and LauncherSettingsPanel - if (drawBackgroundLayer) { - g2.setColor(Color.white); - g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.5f)); - g2.fillRect(0, 0, getWidth(), getHeight()); - } - } - g2.dispose(); - } - g.drawImage(cache, 0, 0, getWidth(), getHeight(), null); - } - -} \ No newline at end of file diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/GraphicsUtils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/GraphicsUtils.java deleted file mode 100644 index 672418db2..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/GraphicsUtils.java +++ /dev/null @@ -1,265 +0,0 @@ -package org.jackhuang.hmcl.util.ui; - -import java.awt.Color; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.RenderingHints; -import java.awt.Toolkit; -import java.awt.image.BufferedImage; -import java.awt.image.Raster; -import java.awt.image.WritableRaster; -import java.util.Map; -import javax.swing.plaf.synth.SynthContext; -import javax.swing.plaf.synth.SynthGraphicsUtils; - -/** - * NimbusGraphicsUtils - extends SynthGraphicsUtils to force all Synth painted - * text to be antialiased and provides some static helper methods. - * - * @author Created by Jasper Potts (Jan 4, 2007) - * @version 1.0 - */ -public class GraphicsUtils extends SynthGraphicsUtils { - - private Map desktopHints; - - /** - * Get rendering hints from a Graphics instance. "hintsToSave" is a Map of - * RenderingHint key-values. For each hint key present in that map, the - * value of that hint is obtained from the Graphics and stored as the value - * for the key in savedHints. - * - * @param g2d the graphics surface - * @param hintsToSave the list of rendering hints to set on the graphics - * @param savedHints a set where to save the previous rendering hints, - * might - * be null - * - * @return the previous set of rendering hints - */ - public static RenderingHints getRenderingHints(Graphics2D g2d, - Map hintsToSave, - RenderingHints savedHints) { - if (savedHints == null) - savedHints = new RenderingHints(null); - else - savedHints.clear(); - if (hintsToSave.isEmpty()) - return savedHints; - /* RenderingHints.keySet() returns Set */ - for (Object o : hintsToSave.keySet()) { - RenderingHints.Key key = (RenderingHints.Key) o; - Object value = g2d.getRenderingHint(key); - savedHints.put(key, value); - } - return savedHints; - } - - /** - * Overrides paintText in SynthGraphicsUtils to force all Synth painted text - * to be antialiased - */ - @Override - public void paintText(SynthContext ss, Graphics g, String text, int x, int y, int mnemonicIndex) { - Graphics2D g2 = (Graphics2D) g; - - // XXX: In Java SE 6, Synth already uses the desktop hints, this code should just check whether java.version < 1.6 - if (desktopHints == null) { - Toolkit toolkit = Toolkit.getDefaultToolkit(); - desktopHints = (Map) (toolkit.getDesktopProperty("awt.font.desktophints")); - } - - Object oldAA = null; - RenderingHints oldHints = null; - - if (desktopHints != null) { - oldHints = getRenderingHints(g2, desktopHints, null); - g2.addRenderingHints(desktopHints); - } else { - oldAA = g2.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING); - g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, - RenderingHints.VALUE_TEXT_ANTIALIAS_ON); - } - - super.paintText(ss, g, text, x, y, mnemonicIndex); - - if (oldHints != null) - g2.addRenderingHints(oldHints); - else if (oldAA != null) - g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, - oldAA); - } - - public static String getColor(Color c) { - return Integer.toHexString(c.getRGB() & 0xFFFFFF); - } - - /** - * Get a Color object from a web color string of the form "FF00AB" or - * "#FF00AB". - * - * @param c The color string - * - * @return The Color described - */ - public static Color getWebColor(String c) { - if (c.startsWith("#")) - c = c.substring(1); - return new Color( - Integer.parseInt(c.substring(0, 2), 16), - Integer.parseInt(c.substring(2, 4), 16), - Integer.parseInt(c.substring(4, 6), 16) - ); - } - - /** - * Get a Color object from a web color string of the form "FF00AB" or - * "#FF00AB". - * - * @param c The color string - * - * @return The Color described - */ - public static Color getWebColorWithAlpha(String c) { - if (c.startsWith("#")) - c = c.substring(1); - return new Color( - Integer.parseInt(c.substring(0, 2), 16), - Integer.parseInt(c.substring(2, 4), 16), - Integer.parseInt(c.substring(4, 6), 16), - Integer.parseInt(c.substring(6, 8), 16) - ); - } - - /** - * Get a Color that is 50% inbetween the two web colors given. The Web - * colors are of the form "FF00AB" or "#FF00AB". - * - * @param c1 The first color string - * @param c2 The second color string - * - * @return The Color middle color - */ - public static Color getMidWebColor(String c1, String c2) { - return getMidWebColor(c1, c2, 50); - } - - /** - * Get a Color that is 50% inbetween the two web colors given. The Web - * colors are of the form "FF00AB" or "#FF00AB". - * - * @param c1 The first color string - * @param c2 The second color string - * - * @return The Color middle color - */ - public static Color getMidWebColor(String c1, String c2, int percent) { - if (c1.startsWith("#")) - c1 = c1.substring(1); - if (c2.startsWith("#")) - c2 = c2.substring(1); - int rTop = Integer.parseInt(c1.substring(0, 2), 16); - int gTop = Integer.parseInt(c1.substring(2, 4), 16); - int bTop = Integer.parseInt(c1.substring(4, 6), 16); - int rBot = Integer.parseInt(c2.substring(0, 2), 16); - int gBot = Integer.parseInt(c2.substring(2, 4), 16); - int bBot = Integer.parseInt(c2.substring(4, 6), 16); - int rMid = rTop + ((rBot - rTop) * percent / 100); - int gMid = gTop + ((gBot - gTop) * percent / 100); - int bMid = bTop + ((bBot - bTop) * percent / 100); - return new Color(rMid, gMid, bMid); - } - - public static Color getMidWebColor(Color c1, Color c2, int percent) { - int rTop = c1.getRed(); - int gTop = c1.getGreen(); - int bTop = c1.getBlue(); - int aTop = c1.getAlpha(); - int rBot = c2.getRed(); - int gBot = c2.getGreen(); - int bBot = c2.getBlue(); - int aBot = c2.getAlpha(); - int rMid = rTop + ((rBot - rTop) * percent / 100); - int gMid = gTop + ((gBot - gTop) * percent / 100); - int bMid = bTop + ((bBot - bTop) * percent / 100); - int aMid = aTop + ((aBot - aTop) * percent / 100); - return new Color(rMid, gMid, bMid, aMid); - } - - /** - *

    Returns an array of pixels, stored as integers, from a - * BufferedImage. The pixels are grabbed from a rectangular - * area defined by a location and two dimensions. Calling this method on - * an image of type different from BufferedImage.TYPE_INT_ARGB - * and BufferedImage.TYPE_INT_RGB will unmanage the image.

    - * - * @param img the source image - * @param x the x location at which to start grabbing pixels - * @param y the y location at which to start grabbing pixels - * @param w the width of the rectangle of pixels to grab - * @param h the height of the rectangle of pixels to grab - * @param pixels a pre-allocated array of pixels of size w*h; can be null - * @return pixels if non-null, a new array of integers - * otherwise - * @throws IllegalArgumentException is pixels is non-null and - * of length < w*h - */ - public static int[] getPixels(BufferedImage img, - int x, int y, int w, int h, int[] pixels) { - if (w == 0 || h == 0) { - return new int[0]; - } - - if (pixels == null) { - pixels = new int[w * h]; - } else if (pixels.length < w * h) { - throw new IllegalArgumentException("pixels array must have a length" + - " >= w*h"); - } - - int imageType = img.getType(); - if (imageType == BufferedImage.TYPE_INT_ARGB || - imageType == BufferedImage.TYPE_INT_RGB) { - Raster raster = img.getRaster(); - return (int[]) raster.getDataElements(x, y, w, h, pixels); - } - - // Unmanages the image - return img.getRGB(x, y, w, h, pixels, 0, w); - } - - /** - *

    Writes a rectangular area of pixels in the destination - * BufferedImage. Calling this method on - * an image of type different from BufferedImage.TYPE_INT_ARGB - * and BufferedImage.TYPE_INT_RGB will unmanage the image.

    - * - * @param img the destination image - * @param x the x location at which to start storing pixels - * @param y the y location at which to start storing pixels - * @param w the width of the rectangle of pixels to store - * @param h the height of the rectangle of pixels to store - * @param pixels an array of pixels, stored as integers - * @throws IllegalArgumentException is pixels is non-null and - * of length < w*h - */ - public static void setPixels(BufferedImage img, - int x, int y, int w, int h, int[] pixels) { - if (pixels == null || w == 0 || h == 0) { - return; - } else if (pixels.length < w * h) { - throw new IllegalArgumentException("pixels array must have a length" + - " >= w*h"); - } - - int imageType = img.getType(); - if (imageType == BufferedImage.TYPE_INT_ARGB || - imageType == BufferedImage.TYPE_INT_RGB) { - WritableRaster raster = img.getRaster(); - raster.setDataElements(x, y, w, h, pixels); - } else { - // Unmanages the image - img.setRGB(x, y, w, h, pixels, 0, w); - } - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/IRepaint.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/IRepaint.java deleted file mode 100644 index 4e5c9aca7..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/IRepaint.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.ui; - -import java.awt.Rectangle; -import java.awt.Window; -import java.util.Collection; -import javax.swing.JComponent; - -/** - * - * @author huang - */ -public interface IRepaint { - - /** - * addDirtyRegion to? - * @return the component which needs repainting. - */ - JComponent getRepaintComponent(); - - /** - * addDirtyRegion to? - * @return the window which needs repainting. - */ - Window getRepaintWindow(); - - /** - * Repaint the component/window you want. - * @return the region where you want to repaint. - */ - Collection getRepaintRects(); -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/JFontComboBox.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/JFontComboBox.java deleted file mode 100644 index 12fb051b3..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/JFontComboBox.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.ui; - -import java.awt.Component; -import java.awt.Font; -import java.awt.GraphicsEnvironment; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; -import javax.swing.DefaultComboBoxModel; -import javax.swing.JComboBox; -import javax.swing.JLabel; -import javax.swing.JList; -import javax.swing.ListCellRenderer; - -/** - * - * @author huang - */ -public class JFontComboBox extends JComboBox implements ItemListener { - private static DefaultComboBoxModel defaultModel = null; - private int fontSize; - - protected static DefaultComboBoxModel getDefaultModel() { - if (defaultModel == null) - defaultModel = new DefaultComboBoxModel<>(GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames()); - return defaultModel; - } - - public JFontComboBox() { - super(); - setRenderer(new JFontComboBoxCellRenderer()); - setModel(getDefaultModel()); - addItemListener(this); - fontSize = getFont().getSize(); - } - - @Override - public void itemStateChanged(ItemEvent e) { - setFont(new Font(e.getItem().toString(), Font.PLAIN, fontSize)); - } - - public static class JFontComboBoxCellRenderer extends JLabel implements ListCellRenderer { - - @Override - public Component getListCellRendererComponent(JList list, String value, int index, boolean isSelected, boolean cellHasFocus) { - Font font = new Font(value, Font.PLAIN, 14); - setEnabled(list.isEnabled()); - setText(font.getFontName()); - setFont(font); - return this; - } - - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/JSystemFileChooser.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/JSystemFileChooser.java deleted file mode 100644 index 77869574a..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/JSystemFileChooser.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.ui; - -import java.io.File; -import javax.swing.JFileChooser; -import javax.swing.LookAndFeel; -import javax.swing.UIManager; -import javax.swing.UnsupportedLookAndFeelException; - -/** - * - * @author huangyuhui - */ -public class JSystemFileChooser extends JFileChooser { - - public JSystemFileChooser() { - super(); - } - - public JSystemFileChooser(File f) { - super(f); - } - - @Override - public void updateUI() { - LookAndFeel old = UIManager.getLookAndFeel(); - try { - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - } catch (ClassNotFoundException | IllegalAccessException | InstantiationException | UnsupportedLookAndFeelException ignored) { - old = null; - } - - super.updateUI(); - - if (old != null) - try { - UIManager.setLookAndFeel(old); - } catch (UnsupportedLookAndFeelException ignored) { - } - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/MessageBox.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/MessageBox.java deleted file mode 100644 index e08e7f43e..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/MessageBox.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.ui; - -import javax.swing.JOptionPane; -import javax.swing.UIManager; -import org.jackhuang.hmcl.util.C; - -/** - * @author huangyuhui - */ -public class MessageBox { - - private static final String TITLE = C.i18n("message.info"); - /** - * Buttons: OK - */ - public static final int DEFAULT_OPTION = -1; - /** - * Buttons: Yes No - */ - public static final int YES_NO_OPTION = 10; - /** - * Buttons: Yes No Cancel - */ - public static final int YES_NO_CANCEL_OPTION = 11; - /** - * Buttons: OK Cancel - */ - public static final int OK_CANCEL_OPTION = 12; - /** - * User Operation: Yes - */ - public static final int YES_OPTION = 0; - /** - * User Operation: No - */ - public static final int NO_OPTION = 1; - /** - * User Operation: Cancel - */ - public static final int CANCEL_OPTION = 2; - /** - * User Operation: OK - */ - public static final int OK_OPTION = 0; - /** - * User Operation: Closed Message Box - */ - public static final int CLOSED_OPTION = -1; - /** - * Message Box Type: Error - */ - public static final int ERROR_MESSAGE = 0; - /** - * Message Box Type: Info - */ - public static final int INFORMATION_MESSAGE = 1; - /** - * Message Box Type: Warning - */ - public static final int WARNING_MESSAGE = 2; - /** - * Message Box Type: Question - */ - public static final int QUESTION_MESSAGE = 3; - /** - * Message Box Type: Plain - */ - public static final int PLAIN_MESSAGE = -1; - - /** - * Show MsgBox with title and options - * - * @param Msg The Message - * @param Title The title of MsgBox. - * @param Option The type of MsgBox. - * - * @return user operation. - */ - public static int show(String Msg, String Title, int Option) { - switch (Option) { - case YES_NO_OPTION: - case YES_NO_CANCEL_OPTION: - case OK_CANCEL_OPTION: - return SwingUtils.invokeAndWait(() -> JOptionPane.showConfirmDialog(null, Msg, Title, Option - 10)); - default: - SwingUtils.invokeAndWait(() -> JOptionPane.showMessageDialog(null, Msg, Title, Option)); - } - return 0; - } - - public static String showInputDialog(String msg) { - return showInputDialog(msg, UIManager.getString("OptionPane.inputDialogTitle")); - } - - public static String showInputDialog(String msg, String title) { - return showInputDialog(msg, title, null); - } - - public static String showInputDialog(String msg, String title, String init) { - return (String) JOptionPane.showInputDialog(null, msg, title, JOptionPane.QUESTION_MESSAGE, null, null, init); - } - - /** - * Show MsgBox with options - * - * @param Msg The Message - * @param Option The type of MsgBox. - * - * @return User Operation - */ - public static int show(String Msg, int Option) { - return show(Msg, TITLE, Option); - } - - /** - * Show Default MsgBox - * - * @param Msg The Message - * - * @return User Operation - */ - public static int show(String Msg) { - return show(Msg, TITLE, INFORMATION_MESSAGE); - } - - public static int showLocalized(String msg) { - return show(C.i18n(msg)); - } - - static { - UIManager.put("OptionPane.cancelButtonText", C.i18n("button.cancel")); - UIManager.put("OptionPane.noButtonText", C.i18n("button.no")); - UIManager.put("OptionPane.okButtonText", C.i18n("button.ok")); - UIManager.put("OptionPane.yesButtonText", C.i18n("button.yes")); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/MyRepaintManager.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/MyRepaintManager.java deleted file mode 100644 index 2171c8f3d..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/MyRepaintManager.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.ui; - -import java.awt.Container; -import java.awt.Rectangle; -import java.awt.Window; -import javax.swing.JComponent; -import javax.swing.RepaintManager; - -/** - * - * @author huangyuhui - */ -public class MyRepaintManager extends RepaintManager { - - @Override - public void addDirtyRegion(JComponent c, int x, int y, int w, int h) { - super.addDirtyRegion(c, x, y, w, h); - - for (Container parent = c.getParent(); (parent instanceof JComponent || parent instanceof Window) && parent.isVisible(); parent = parent.getParent()) { - if (parent instanceof IRepaint) { - IRepaint d = (IRepaint) parent; - for (Rectangle r : d.getRepaintRects()) { - if (d.getRepaintComponent() != null) - super.addDirtyRegion(d.getRepaintComponent(), r.x, r.y, r.width, r.height); - if (d.getRepaintWindow() != null) - super.addDirtyRegion(d.getRepaintWindow(), r.x, r.y, r.width, r.height); - } - } - } - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/Page.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/Page.java deleted file mode 100644 index 84e14228f..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/Page.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.ui; - -import org.jackhuang.hmcl.api.ui.TopTabPage; -import java.awt.AlphaComposite; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.image.BufferedImage; -import javax.swing.SwingUtilities; -import javax.swing.Timer; - -/** - * - * @author huangyuhui - */ -public class Page extends TopTabPage { - - boolean selected = false; - public int id; - - @Override - public int getId() { - return id; - } - - @Override - public void setId(int id) { - this.id = id; - } - - @Override - public boolean isSelected() { - return selected; - } - - @Override - public void onSelect(TopTabPage lastSelectedPage) { - if (!selected) { - lastPage = (Page) lastSelectedPage; - animate(); - } - selected = true; - } - - @Override - public void onLeave() { - selected = false; - } - - boolean created = false; - - @Override - public void onCreate() { - created = true; - } - - @Override - public boolean isCreated() { - return created; - } - - // ------------------- - // Animation - // ------------------- - private static final int ANIMATION_LENGTH = 5; - - public Page() { - timer = new Timer(1, (e) -> { - SwingUtilities.invokeLater(() -> { - Page.this.repaint(); - offsetX += 0.14; - if (offsetX >= ANIMATION_LENGTH) { - timer.stop(); - Page.this.repaint(); - } - }); - }); - } - - BufferedImage cache = null, lastCache = null; - - @Override - public void paint(Graphics g) { - if (!(g instanceof Graphics2D)) { - super.paint(g); - return; - } - Graphics2D gg = (Graphics2D) g; - double pgs = Math.sin(Math.PI / 2 / ANIMATION_LENGTH * offsetX); - if (Math.abs(ANIMATION_LENGTH - offsetX) < 0.1) { - super.paint(g); - return; - } - - if (offsetX == 0) { - cache = cacheImpl(this); - if (lastPage != null) - lastCache = cacheImpl(lastPage); - } - int ori = lastPage != null ? (lastPage.getId() < getId() ? 1 : -1) : 1; - if (pgs >= 0.5) - animateImpl(gg, cache, (int) (((1 - (pgs - 0.5) * 2)) * totalOffset * ori), (float) ((pgs - 0.5) * 2)); - else - animateImpl(gg, lastCache, (int) (((- pgs * 2)) * totalOffset * ori), (float) (1 - pgs * 2)); - } - - BufferedImage cacheImpl(Page page) { - BufferedImage image = new BufferedImage(page.getWidth(), page.getHeight(), BufferedImage.TYPE_INT_ARGB); - Graphics2D g2d = image.createGraphics(); - if (isOpaque()) { - g2d.setColor(page.getBackground()); - g2d.fillRect(0, 0, page.getWidth(), page.getHeight()); - } - page.superPaint(g2d); - g2d.dispose(); - return image; - } - - void animateImpl(Graphics2D g, BufferedImage image, int left, float alpha) { - if (image == null) - return; - g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha)); - g.drawImage(image, left, 0, this); - } - - protected void superPaint(Graphics2D g) { - super.paint(g); - } - - double offsetX = ANIMATION_LENGTH, totalOffset = 20; - Page lastPage; - Timer timer; - - protected boolean animationEnabled = true; - - public Page setAnimationEnabled(boolean a) { - animationEnabled = a; - return this; - } - - public void animate() { - if (animationEnabled) { - offsetX = 0; - timer.start(); - } - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/StackBlurFilter.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/StackBlurFilter.java deleted file mode 100644 index f7a825b60..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/StackBlurFilter.java +++ /dev/null @@ -1,149 +0,0 @@ -package org.jackhuang.hmcl.util.ui; - -/* - * Copyright (c) 2007, Romain Guy - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * * Neither the name of the TimingFramework project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -import java.awt.image.BufferedImage; - -/** - *

    A stack blur filter can be used to create an approximation of a - * gaussian blur. The approximation is controlled by the number of times the - * {@link org.jdesktop.swingx.image.FastBlurFilter} is applied onto the source - * picture. The default number of iterations, 3, provides a decent compromise - * between speed and rendering quality.

    - *

    The force of the blur can be controlled with a radius and the - * default radius is 3. Since the blur clamps values on the edges of the - * source picture, you might need to provide a picture with empty borders - * to avoid artifacts at the edges. The performance of this filter are - * independant from the radius.

    - * - * @author Romain Guy -*/ -public class StackBlurFilter extends AbstractFilter { - private final int radius; - private final int iterations; - - /** - *

    Creates a new blur filter with a default radius of 3 and 3 iterations.

    - */ - public StackBlurFilter() { - this(3, 3); - } - - /** - *

    Creates a new blur filter with the specified radius and 3 iterations. - * If the radius is lower than 1, a radius of 1 will be used automatically.

    - * - * @param radius the radius, in pixels, of the blur - */ - public StackBlurFilter(int radius) { - this(radius, 3); - } - - /** - *

    Creates a new blur filter with the specified radius. If the radius - * is lower than 1, a radius of 1 will be used automatically. The number - * of iterations controls the approximation to a gaussian blur. If the - * number of iterations is lower than 1, one iteration will be used - * automatically.

    - * - * @param radius the radius, in pixels, of the blur - * @param iterations the number of iterations to approximate a gaussian blur - */ - public StackBlurFilter(int radius, int iterations) { - if (radius < 1) { - radius = 1; - } - if (iterations < 1) { - iterations = 1; - } - - this.radius = radius; - this.iterations = iterations; - } - - /** - *

    Returns the effective radius of the stack blur. If the radius of the - * blur is 1 and the stack iterations count is 3, then the effective blur - * radius is 1 * 3 = 3.

    - * @return the number of iterations times the blur radius - */ - public int getEffectiveRadius() { - return getIterations() * getRadius(); - } - - /** - *

    Returns the radius used by this filter, in pixels.

    - * - * @return the radius of the blur - */ - public int getRadius() { - return radius; - } - - /** - *

    Returns the number of iterations used to approximate a gaussian - * blur.

    - * - * @return the number of iterations used by this blur - */ - public int getIterations() { - return iterations; - } - - /** - * {@inheritDoc} - */ - @Override - public BufferedImage filter(BufferedImage src, BufferedImage dst) { - int width = src.getWidth(); - int height = src.getHeight(); - - if (dst == null) { - dst = createCompatibleDestImage(src, null); - } - - int[] srcPixels = new int[width * height]; - int[] dstPixels = new int[width * height]; - - GraphicsUtils.getPixels(src, 0, 0, width, height, srcPixels); - for (int i = 0; i < iterations; i++) { - // horizontal pass - FastBlurFilter.blur(srcPixels, dstPixels, width, height, radius); - // vertical pass - FastBlurFilter.blur(dstPixels, srcPixels, height, width, radius); - } - // the result is now stored in srcPixels due to the 2nd pass - GraphicsUtils.setPixels(dst, 0, 0, width, height, srcPixels); - - return dst; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/SwingUtils.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/SwingUtils.java deleted file mode 100644 index 1324dcb48..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/SwingUtils.java +++ /dev/null @@ -1,403 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.ui; - -import java.awt.Component; -import java.awt.EventQueue; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Graphics; -import java.awt.Image; -import java.awt.Toolkit; -import java.awt.Window; -import java.io.File; -import java.io.IOException; -import java.net.URI; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Random; -import javax.swing.DefaultListModel; -import javax.swing.ImageIcon; -import javax.swing.JComboBox; -import javax.swing.JComponent; -import javax.swing.JLabel; -import javax.swing.JList; -import javax.swing.JOptionPane; -import javax.swing.JScrollBar; -import javax.swing.JScrollPane; -import javax.swing.JTable; -import javax.swing.SwingUtilities; -import javax.swing.table.DefaultTableModel; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.util.StrUtils; -import org.jackhuang.hmcl.util.Utils; -import org.jackhuang.hmcl.api.func.NonFunction; -import org.jackhuang.hmcl.util.sys.OS; - -/** - * - * @author huang - */ -public final class SwingUtils { - - private SwingUtils() { - } - - /** - * Make DefaultTableModel by overriding getColumnClass and isCellEditable of - * DefaultTableModel. - * - * @param titleA The title of each column. - * @param typesA The type of each column value. - * @param canEditA Is column editable? - * - * @return - */ - public static DefaultTableModel makeDefaultTableModel(String[] titleA, final Class[] typesA, final boolean[] canEditA) { - return new DefaultTableModel(new Object[][] {}, titleA) { - Class[] types = typesA; - boolean[] canEdit = canEditA; - - @Override - public Class getColumnClass(int columnIndex) { - return types[columnIndex]; - } - - @Override - public boolean isCellEditable(int rowIndex, int columnIndex) { - return canEdit[columnIndex]; - } - }; - } - - public static void openFolder(File f) { - f.mkdirs(); - String path = f.getAbsolutePath(); - switch (OS.os()) { - case OSX: - try { - Runtime.getRuntime().exec(new String[] { "/usr/bin/open", path }); - } catch (IOException ex) { - HMCLog.err("Failed to open " + path + " through /usr/bin/open", ex); - } - break; - default: - try { - java.awt.Desktop.getDesktop().open(f); - } catch (Throwable ex) { - MessageBox.show(C.i18n("message.cannot_open_explorer") + ex.getMessage()); - HMCLog.warn("Failed to open " + path + " through java.awt.Desktop.getDesktop().open()", ex); - } - break; - } - } - - /** - * Open URL by java.awt.Desktop - * - * @param link null is allowed but will be ignored - */ - public static void openLink(String link) { - if (link == null) - return; - try { - java.awt.Desktop.getDesktop().browse(new URI(link)); - } catch (Throwable e) { - if (OS.os() == OS.OSX) - try { - Runtime.getRuntime().exec(new String[] { "/usr/bin/open", link }); - } catch (IOException ex) { - HMCLog.warn("Failed to open link: " + link, ex); - } - HMCLog.warn("Failed to open link: " + link, e); - } - } - - /** - * Move the cursor to the end of ScrollPane. - * - * @param pane the ScrollPane - */ - public static void moveEnd(JScrollPane pane) { - JScrollBar bar = pane.getVerticalScrollBar(); - bar.setValue(bar.getMaximum()); - } - - /** - * Get the DefaultListModel from JList. - * - * @param list - * - * @return Forcely Type casted to DefaultListModel - */ - public static DefaultListModel getDefaultListModel(JList list) { - return (DefaultListModel) list.getModel(); - } - - /** - * Clear the JTable - * - * @param table JTable with DefaultTableModel. - * - * @return To make the code succinct - */ - public static DefaultTableModel clearDefaultTable(JTable table) { - DefaultTableModel model = (DefaultTableModel) table.getModel(); - while (model.getRowCount() > 0) - model.removeRow(0); - return model; - } - - public static void appendLast(JTable table, Object... elements) { - DefaultTableModel model = (DefaultTableModel) table.getModel(); - model.addRow(elements); - } - - public static void setValueAt(JTable table, Object element, int row, int col) { - DefaultTableModel model = (DefaultTableModel) table.getModel(); - model.setValueAt(element, row, col); - } - - public static Object[] getValueBySelectedRow(JTable table, int rows[], int col) { - DefaultTableModel model = (DefaultTableModel) table.getModel(); - Object[] ret = new Object[rows.length]; - for (int i = 0; i < rows.length; i++) - ret[i] = model.getValueAt(rows[i], col); - return ret; - } - - public static void removeRow(JTable table, int row) { - DefaultTableModel model = (DefaultTableModel) table.getModel(); - model.removeRow(row); - } - - public static String getParsedJPanelText(JLabel jLabel1, String longString) { - if (StrUtils.isBlank(longString)) - return longString; - StringBuilder builder = new StringBuilder(); - char[] chars = longString.toCharArray(); - FontMetrics fontMetrics = jLabel1.getFontMetrics(jLabel1.getFont()); - for (int beginIndex = 0, limit = 1;; limit++) { - if (beginIndex + limit > chars.length) - break; - if (fontMetrics.charsWidth(chars, beginIndex, limit) < jLabel1.getWidth()) { - if (beginIndex + limit < chars.length) - continue; - builder.append(chars, beginIndex, limit); - break; - } - builder.append(chars, beginIndex, limit - 1).append("
    "); - beginIndex += limit - 1; - limit = 1; - } - return builder.toString(); - } - - private static final Map INVOKE_AND_WAIT_MAP = Collections.synchronizedMap(new HashMap<>()); - private static int INVOKE_AND_WAIT_ID = 0; - private static final Object INVOKE_AND_WAIT_LOCK = new Object(); - - public static T invokeAndWait(NonFunction x) { - int id; - synchronized (INVOKE_AND_WAIT_LOCK) { - id = ++INVOKE_AND_WAIT_ID; - } - int fuck = id; - Runnable r = () -> INVOKE_AND_WAIT_MAP.put(fuck, x.apply()); - invokeAndWait(r); - return (T) INVOKE_AND_WAIT_MAP.remove(id); - } - - public static void invokeAndWait(Runnable r) { - if (EventQueue.isDispatchThread()) - r.run(); - else - try { - EventQueue.invokeAndWait(r); - } catch (Exception e) { - HMCLog.err("Failed to invokeAndWait, the UI will work abnormally.", e); - r.run(); - } - } - - public static int select(String[] selList, String msg) { - JComboBox box = new JComboBox<>(selList); - Object msgs[] = new Object[2]; - msgs[0] = msg; - msgs[1] = box; - int result = JOptionPane.showOptionDialog(null, msgs, msg, JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null); - if (result == JOptionPane.CANCEL_OPTION) - return -1; - return box.getSelectedIndex(); - } - - public static void setEnabled(JComponent component, boolean t) { - synchronized (component.getTreeLock()) { - for (Component c : component.getComponents()) - if (c instanceof JComponent) - setEnabled((JComponent) c, t); - } - component.setEnabled(t); - } - - public static void exitIfNoWindow(Window thisFrame) { - exitIfNoWindow(thisFrame, false); - } - - public static void exitIfNoWindow(Window thisFrame, boolean neededDispose) { - boolean flag = false; - for (Window f : Window.getWindows()) { - if (f == thisFrame) - continue; - if (f.isVisible()) - flag = true; - } - if (!flag) - try { - Utils.shutdownForcely(0); - } catch (Exception e) { - MessageBox.show(C.i18n("launcher.exit_failed")); - HMCLog.err("Failed to shutdown forcely", e); - } - else - thisFrame.dispose(); - } - - public static ImageIcon scaleImage(ImageIcon i, int x, int y) { - return new ImageIcon(i.getImage().getScaledInstance(x, y, Image.SCALE_SMOOTH)); - } - - public static ImageIcon searchBackgroundImage(ImageIcon init, String bgpath, int width, int height) { - Random r = new Random(); - boolean loaded = false; - ImageIcon background = init; - - // bgpath - if (StrUtils.isNotBlank(bgpath) && !loaded) { - String[] backgroundPath = bgpath.split(";"); - if (backgroundPath.length > 0) { - int index = r.nextInt(backgroundPath.length); - background = new ImageIcon(Toolkit.getDefaultToolkit().getImage(backgroundPath[index]).getScaledInstance(width, height, Image.SCALE_DEFAULT)); - HMCLog.log("Prepared background image in bgpath."); - loaded = true; - } - } - - // bgskin - if (!loaded) { - File backgroundImageFile = new File("bg"); - if (backgroundImageFile.exists() && backgroundImageFile.isDirectory()) { - String[] backgroundPath = backgroundImageFile.list(); - if (backgroundPath.length > 0) { - int index = r.nextInt(backgroundPath.length); - background = new ImageIcon(Toolkit.getDefaultToolkit().getImage("bg" + File.separator + backgroundPath[index]).getScaledInstance(width, height, Image.SCALE_DEFAULT)); - HMCLog.log("Prepared background image in bgskin folder."); - loaded = true; - } - } - } - - // background.png - if (!loaded) { - File backgroundImageFile = new File("background.png"); - if (backgroundImageFile.exists()) { - loaded = true; - background = new ImageIcon(Toolkit.getDefaultToolkit().getImage(backgroundImageFile.getAbsolutePath()).getScaledInstance(width, height, Image.SCALE_DEFAULT)); - HMCLog.log("Prepared background image in background.png."); - } - } - - // background.jpg - if (!loaded) { - File backgroundImageFile = new File("background.jpg"); - if (backgroundImageFile.exists()) { - //loaded = true; - background = new ImageIcon(Toolkit.getDefaultToolkit().getImage(backgroundImageFile.getAbsolutePath()).getScaledInstance(width, height, Image.SCALE_DEFAULT)); - HMCLog.log("Prepared background image in background.jpg."); - } - } - - if (background == null) - return init; - return background; - } - - public static Runnable invokeLater(Runnable r) { - return () -> { - SwingUtilities.invokeLater(r); - }; - } - - /** - * Returns the FontMetrics for the current Font of the passed in Graphics. - * This method is used when a Graphics is available, typically when - * painting. If a Graphics is not available the JComponent method of the - * same name should be used. - *

    - * Callers should pass in a non-null JComponent, the exception to this is if - * a JComponent is not readily available at the time of painting. - *

    - * This does not necessarily return the FontMetrics from the Graphics. - * - * @param c JComponent requesting FontMetrics, may be null - * @param g Graphics Graphics - * @return the font metrics - */ - public static FontMetrics getFontMetrics(JComponent c, Graphics g) { - return getFontMetrics(c, g, g.getFont()); - } - - /** - * Returns the FontMetrics for the specified Font. This method is used when - * a Graphics is available, typically when painting. If a Graphics is not - * available the JComponent method of the same name should be used. - *

    - * Callers should pass in a non-null JComonent, the exception to this is if - * a JComponent is not readily available at the time of painting. - *

    - * This does not necessarily return the FontMetrics from the Graphics. - * - * @param c Graphics Graphics - * @param g the g - * @param font Font to get FontMetrics for - * @return the font metrics - */ - public static FontMetrics getFontMetrics(JComponent c, Graphics g, - Font font) { - if (c != null) - // Note: We assume that we're using the FontMetrics - // from the widget to layout out text, otherwise we can get - // mismatches when printing. - return c.getFontMetrics(font); - return Toolkit.getDefaultToolkit().getFontMetrics(font); - } - - /** - * Returns the width of the passed in String. - * - * @param c JComponent that will display the string, may be null - * @param fm FontMetrics used to measure the String width - * @param string String to get the width of - * @return the int - */ - public static int stringWidth(JComponent c, FontMetrics fm, String string) { - return fm.stringWidth(string); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/TintablePanel.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/TintablePanel.java deleted file mode 100644 index 8845c937c..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/TintablePanel.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.ui; - -/** - * - * @author huangyuhui - */ -import java.awt.Color; -import java.awt.EventQueue; -import java.awt.Graphics; -import javax.swing.ImageIcon; -import javax.swing.JLabel; -import javax.swing.JPanel; - -public class TintablePanel extends JPanel { - - private Color tintColor; - private boolean tintActive; - private JLabel overIcon = null; - - public TintablePanel() { - this.tintColor = new Color(0, 0, 0, 0); - } - - public Color getTintColor() { - return this.tintColor; - } - - public void setTintColor(Color color) { - this.tintColor = color; - } - - public void setOverIcon(ImageIcon image) { - if (this.overIcon != null) - remove(this.overIcon); - - this.overIcon = new JLabel(image); - this.overIcon.setVisible(false); - add(this.overIcon); - revalidate(); - } - - public boolean isTintActive() { - return this.tintActive; - } - - public void setTintActive(boolean tintActive) { - this.tintActive = tintActive; - - if (this.overIcon != null) { - this.overIcon.setVisible(tintActive); - EventQueue.invokeLater(TintablePanel.this::revalidate); - } - EventQueue.invokeLater(TintablePanel.this::repaint); - } - - @Override - public void doLayout() { - super.doLayout(); - - if (this.overIcon != null) { - int width = this.overIcon.getIcon().getIconWidth(); - int height = this.overIcon.getIcon().getIconHeight(); - this.overIcon.setBounds(getWidth() / 2 - width / 2, getHeight() / 2 - height / 2, width, height); - } - } - - @Override - public void paint(Graphics graphics) { - super.paint(graphics); - - if (this.tintActive) { - graphics.setColor(getTintColor()); - graphics.fillRect(0, 0, getWidth(), getHeight()); - } - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/WideComboBox.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/WideComboBox.java deleted file mode 100644 index 233a22ed3..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/WideComboBox.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.ui; - -import java.awt.Dimension; -import java.awt.FontMetrics; -import java.awt.Graphics; -import javax.swing.JComboBox; - -/** - * Make the popup menu of combo boxes wider. - * - * @author huangyuhui - */ -public class WideComboBox extends JComboBox { - - public WideComboBox() { - } - - private boolean layingOut = false; - public int customzedMinimumWidth = 300; - private FontMetrics fontMetrics = null; - - @Override - public void doLayout() { - try { - layingOut = true; - super.doLayout(); - } finally { - layingOut = false; - } - } - - @Override - public void paint(Graphics g) { - super.paint(g); - - fontMetrics = SwingUtils.getFontMetrics(this, g); - } - - @Override - public Dimension getSize() { - Dimension dim = super.getSize(); - if (!layingOut && fontMetrics != null) - for (int i = 0; i < getItemCount(); ++i) - dim.width = Math.max(dim.width, SwingUtils.stringWidth(this, fontMetrics, getItemAt(i)) + 5); - - return dim; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/checktree/CheckBoxTreeCellRenderer.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/checktree/CheckBoxTreeCellRenderer.java deleted file mode 100644 index e31bae52c..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/checktree/CheckBoxTreeCellRenderer.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.ui.checktree; - -import java.awt.Color; -import java.awt.Component; -import java.awt.Dimension; - -import javax.swing.JCheckBox; -import javax.swing.JPanel; -import javax.swing.JTree; -import javax.swing.UIManager; -import javax.swing.plaf.ColorUIResource; -import javax.swing.tree.TreeCellRenderer; - -public class CheckBoxTreeCellRenderer extends JPanel implements TreeCellRenderer { - - protected JCheckBox check; - protected CheckBoxTreeLabel label; - - public CheckBoxTreeCellRenderer() { - setLayout(null); - add(check = new JCheckBox()); - add(label = new CheckBoxTreeLabel()); - check.setBackground(UIManager.getColor("Tree.textBackground")); - label.setForeground(UIManager.getColor("Tree.textForeground")); - } - - /** - * 返回的是一个JPanel对象,该对象中包含一个JCheckBox对象 - * 和一个JLabel对象。并且根据每个结点是否被选中来决定JCheckBox - * 是否被选中。 - */ - @Override - public Component getTreeCellRendererComponent(JTree tree, Object value, - boolean selected, boolean expanded, boolean leaf, int row, - boolean hasFocus) { - String stringValue = tree.convertValueToText(value, selected, expanded, leaf, row, hasFocus); - setEnabled(tree.isEnabled()); - check.setSelected(((CheckBoxTreeNode) value).isSelected()); - label.setFont(tree.getFont()); - label.setText(stringValue); - label.setSelected(selected); - label.setFocus(hasFocus); - if (leaf) - label.setIcon(UIManager.getIcon("Tree.leafIcon")); - else if (expanded) - label.setIcon(UIManager.getIcon("Tree.openIcon")); - else - label.setIcon(UIManager.getIcon("Tree.closedIcon")); - - return this; - } - - @Override - public Dimension getPreferredSize() { - Dimension dCheck = check.getPreferredSize(); - Dimension dLabel = label.getPreferredSize(); - return new Dimension(dCheck.width + dLabel.width, dCheck.height < dLabel.height ? dLabel.height : dCheck.height); - } - - @Override - public void doLayout() { - Dimension dCheck = check.getPreferredSize(); - Dimension dLabel = label.getPreferredSize(); - int yCheck = 0; - int yLabel = 0; - if (dCheck.height < dLabel.height) - yCheck = (dLabel.height - dCheck.height) / 2; - else - yLabel = (dCheck.height - dLabel.height) / 2; - check.setLocation(0, yCheck); - check.setBounds(0, yCheck, dCheck.width, dCheck.height); - label.setLocation(dCheck.width, yLabel); - label.setBounds(dCheck.width, yLabel, dLabel.width, dLabel.height); - } - - @Override - public void setBackground(Color color) { - if (color instanceof ColorUIResource) - color = null; - super.setBackground(color); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/checktree/CheckBoxTreeLabel.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/checktree/CheckBoxTreeLabel.java deleted file mode 100644 index 292addd0d..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/checktree/CheckBoxTreeLabel.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.ui.checktree; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics; - -import javax.swing.JLabel; -import javax.swing.plaf.ColorUIResource; - -public class CheckBoxTreeLabel extends JLabel { - - private boolean isSelected; - private boolean hasFocus; - - public CheckBoxTreeLabel() { - } - - @Override - public void setBackground(Color color) { - if (color instanceof ColorUIResource) - color = null; - super.setBackground(color); - } - - @Override - public void paint(Graphics g) { - /*String str; - if ((str = getText()) != null) - if (0 < str.length()) { - if (isSelected) - g.setColor(UIManager.getColor("Tree.selectionBackground")); - else - g.setColor(UIManager.getColor("Tree.textBackground")); - Dimension d = getPreferredSize(); - int imageOffset = 0; - Icon currentIcon = getIcon(); - if (currentIcon != null) - imageOffset = currentIcon.getIconWidth() + Math.max(0, getIconTextGap() - 1); - g.fillRect(imageOffset, 0, d.width - 1 - imageOffset, d.height); - if (hasFocus) { - g.setColor(UIManager.getColor("Tree.selectionBorderColor")); - g.drawRect(imageOffset, 0, d.width - 1 - imageOffset, d.height - 1); - } - }*/ - super.paint(g); - } - - @Override - public Dimension getPreferredSize() { - Dimension retDimension = super.getPreferredSize(); - if (retDimension != null) - retDimension = new Dimension(retDimension.width + 3, retDimension.height); - return retDimension; - } - - public void setSelected(boolean isSelected) { - this.isSelected = isSelected; - } - - public void setFocus(boolean hasFocus) { - this.hasFocus = hasFocus; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/checktree/CheckBoxTreeNode.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/checktree/CheckBoxTreeNode.java deleted file mode 100644 index aaa474af1..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/checktree/CheckBoxTreeNode.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.ui.checktree; - -import javax.swing.tree.DefaultMutableTreeNode; -import org.jackhuang.hmcl.util.Pair; - -/** - * - * @author huangyuhui - */ -public class CheckBoxTreeNode extends DefaultMutableTreeNode { - - protected boolean isSelected; - - public CheckBoxTreeNode() { - this(null); - } - - public CheckBoxTreeNode(Object userObject) { - this(userObject, true, false); - } - - public CheckBoxTreeNode(Object userObject, boolean allowsChildren, boolean isSelected) { - super(userObject, allowsChildren); - this.isSelected = isSelected; - } - - @Override - public String toString() { - if (userObject instanceof Pair) - return "" + ((Pair) userObject).key + " - " + ((Pair) userObject).value + ""; - else - return userObject.toString(); - } - - public boolean isSelected() { - return isSelected; - } - - public void setSelected(boolean _isSelected) { - this.isSelected = _isSelected; - - if (_isSelected) { - // 如果选中,则将其所有的子结点都选中 - if (children != null) - for (Object obj : children) { - CheckBoxTreeNode node = (CheckBoxTreeNode) obj; - if (_isSelected != node.isSelected()) - node.setSelected(_isSelected); - } - // 向上检查,如果父结点的所有子结点都被选中,那么将父结点也选中 - CheckBoxTreeNode pNode = (CheckBoxTreeNode) parent; - // 开始检查pNode的所有子节点是否都被选中 - if (pNode != null) { - int index = 0; - for (; index < pNode.children.size(); ++index) { - CheckBoxTreeNode pChildNode = (CheckBoxTreeNode) pNode.children.get(index); - if (!pChildNode.isSelected()) - break; - } - /* - * 表明pNode所有子结点都已经选中,则选中父结点, - * 该方法是一个递归方法,因此在此不需要进行迭代,因为 - * 当选中父结点后,父结点本身会向上检查的。 - */ - if (index == pNode.children.size()) - if (pNode.isSelected() != _isSelected) - pNode.setSelected(_isSelected); - } - } else { - /* - * 如果是取消父结点导致子结点取消,那么此时所有的子结点都应该是选择上的; - * 否则就是子结点取消导致父结点取消,然后父结点取消导致需要取消子结点,但 - * 是这时候是不需要取消子结点的。 - */ - if (children != null) { - int index = 0; - for (; index < children.size(); ++index) { - CheckBoxTreeNode childNode = (CheckBoxTreeNode) children.get(index); - if (!childNode.isSelected()) - break; - } - // 从上向下取消的时候 - if (index == children.size()) - for (int i = 0; i < children.size(); ++i) { - CheckBoxTreeNode node = (CheckBoxTreeNode) children.get(i); - if (node.isSelected() != _isSelected) - node.setSelected(_isSelected); - } - } - - // 向上取消,只要存在一个子节点不是选上的,那么父节点就不应该被选上。 - CheckBoxTreeNode pNode = (CheckBoxTreeNode) parent; - if (pNode != null && pNode.isSelected() != _isSelected) - pNode.setSelected(_isSelected); - } - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/checktree/CheckBoxTreeNodeSelectionListener.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/checktree/CheckBoxTreeNodeSelectionListener.java deleted file mode 100644 index 0c7ed61c8..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/checktree/CheckBoxTreeNodeSelectionListener.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Hello Minecraft!. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.ui.checktree; - -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; - -import javax.swing.JTree; -import javax.swing.tree.TreePath; -import javax.swing.tree.DefaultTreeModel; - -public class CheckBoxTreeNodeSelectionListener extends MouseAdapter { - - @Override - public void mouseClicked(MouseEvent event) { - JTree tree = (JTree) event.getSource(); - int x = event.getX(); - int y = event.getY(); - int row = tree.getRowForLocation(x, y); - TreePath path = tree.getPathForRow(row); - if (path != null) { - CheckBoxTreeNode node = (CheckBoxTreeNode) path.getLastPathComponent(); - if (node != null) { - boolean isSelected = !node.isSelected(); - node.setSelected(isSelected); - ((DefaultTreeModel) tree.getModel()).nodeStructureChanged(node); - } - } - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/api/WizardDisplayer.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/api/WizardDisplayer.java deleted file mode 100644 index 5387aa166..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/api/WizardDisplayer.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * The contents of this file are subject to the terms of the Common Development - * and Distribution License (the License). You may not use this file except in - * compliance with the License. - * You can obtain a copy of the License at http://www.netbeans.org/cddl.html - * or http://www.netbeans.org/cddl.txt. - * When distributing Covered Code, include this CDDL Header Notice in each file - * and include the License file at http://www.netbeans.org/cddl.txt. - * If applicable, add the following below the CDDL Header, with the fields - * enclosed by brackets [] replaced by your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - */ -package org.jackhuang.hmcl.util.ui.wizard.api; - -import java.awt.Container; -import java.awt.Rectangle; -import java.util.Arrays; -import java.util.Map; -import javax.swing.Action; -import org.jackhuang.hmcl.util.ArrayUtils; -import org.jackhuang.hmcl.util.ui.wizard.api.displayer.WizardDisplayerImpl; -import org.jackhuang.hmcl.util.ui.wizard.spi.Wizard; - -/** - *

    Displaying Wizards

    - * Factory which can display a Wizard in a dialog onscreen or in an - * ad-hoc - * container. Usage: - *
    - * Wizard wizard = WizardPage.createWizard (new Class[] {WizardPageSubclass1.class,
    - *     WizardPageSubclass2.class, WizardPageSubclass3.class},
    - *     new MyWizardResultProducer();
    - * WizardDisplayer.showWizard (wizard);
    - * 
    - * Alternately you can implement WizardPanelProvider instead of - * WizardPage to provide the panels of the wizard. - *

    - * To use a Wizard in a JInternalFrame or similar, use - * WizardDisplayer.installInContainer(). You will need to implement - * WizardResultReceiver which will me notified when the wizard - * is finished or cancelled, to close the internal frame or whatever UI is - * showing the wizard. - *

    - *

    Customizing the default implementation

    - * The image on the left panel of the default implementation can be customized - * in the following ways: - *
      - *
    • Put an instance of java.awt.image.BufferedImage into - * UIManager with the key wizard.sidebar.image, i.e. - *
      - *    BufferedImage img = ImageIO.read (getClass().getResource ("MySideImage.png");
      - *    UIManager.put ("wizard.sidebar.image", img);
      - * 
      - *
    • - *
    • Use the system property wizard.sidebar.image to set a path - * within a JAR on the classpath to the image. The image must be visible - * to the classloader which loads WizardDisplayer, so this - * may not work in environments which manage the classpath. i.e. - *
      - *    System.setProperty ("wizard.sidebar.image", "com/foo/myapp/MySideImage.png");
      - * 
      - *
    • - *
    - * - *

    Providing a custom WizardDisplayer:

    - * The implementation of WizardDisplayer is pluggable. While the - * default implementation should be adequate for most cases, it is possible - * that in some cases one might want to completely replace the UI, buttons, - * etc. with custom UI code. To do that: - *
      - *
    • If the NetBeans Lookup library (org.openide.util.Lookup - * is on the classpath, the default implementation will be found in - * the default lookup (i.e. META-INF/services, same as - * JDK 6's ServiceLoader)
    • - *
    • If Lookup is not available or not found, WizardDisplayer - * will check the system - * property WizardDisplayer.default for a fully qualified - * class name of a subclass of WizardDisplayer. - *
    • - *
    • If no other implementation of WizardDisplayer is found - * by the above methods, the default implementation contained in this - * library will be used.
    • - *
    - * - * @author Tim Boudreau - */ -public abstract class WizardDisplayer { - - protected WizardDisplayer() { - } - - /** - * Display a wizard in a dialog, using the default implementation of - * WizardDisplayer. - * - * @param wizard The wizard to show. Must not be null - * @param rect The rectangle on screen for the wizard, may be - * null for default size - * @param help An action to invoke if the user presses the help - * button - * @param initialProperties are the initial values for properties to be - * shown - * and entered in the wizard. May be null. - */ - public static Object showWizard(Wizard wizard, Rectangle rect, Action help, Map initialProperties) { - // assert nonBuggyWizard (wizard); - // validate it - nonBuggyWizard(wizard); - - WizardDisplayer defaultInstance = getDefault(); - - return defaultInstance.show(wizard, rect, help, initialProperties); - } - - private static WizardDisplayer getDefault() { - return new WizardDisplayerImpl(); - } - - /** - * Show a wizard with default window placement and no Help button - */ - public static Object showWizard(Wizard wizard) { - return showWizard(wizard, null, null, null); - } - - /** - * Show a wizard. - * - * @param wizard the Wizard to show - * @param r the bounding rectangle for the wizard dialog on - * screen, null means "computed from first panel - * size" - * @param help An action to be called if the Help button is - * pressed - * @param initialProperties are used to set initial values for screens - * within the wizard. - * This may be null. - * - * @return Whatever object the wizard returns from its finish() - * method, if the Wizard was completed by the user. - */ - protected abstract Object show(Wizard wizard, Rectangle r, Action help, Map initialProperties); - - /** - * Instance implementation of installInContainer(). - */ - protected abstract void install(Container c, Object layoutConstraint, - Wizard awizard, Action helpAction, Map initialProperties, - WizardResultReceiver receiver); - - private static boolean nonBuggyWizard(Wizard wizard) { - String[] s = wizard.getAllSteps(); - // for JDK 1.4.2: replace assert with runtime exception - if (ArrayUtils.hasDuplicateElements(s)) - throw new RuntimeException("steps are duplicated: " + Arrays.asList(s)); - if (s.length == 1 && Wizard.UNDETERMINED_STEP.equals(s[0])) - // assert false : "Only ID may not be UNDETERMINED_ID"; - throw new RuntimeException("Only ID may not be UNDETERMINED_ID"); - for (int i = 0; i < s.length; i++) - if (Wizard.UNDETERMINED_STEP.equals(s[i]) && i != s.length - 1) - // assert false : "UNDETERMINED_ID may only be last element in" + - // " ids array " + Arrays.asList(s); - throw new RuntimeException("UNDETERMINED_ID may only be last element in ids array " + Arrays.asList(s)); - return true; - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/api/WizardResultReceiver.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/api/WizardResultReceiver.java deleted file mode 100644 index 27bc989be..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/api/WizardResultReceiver.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * The contents of this file are subject to the terms of the Common Development - * and Distribution License (the License). You may not use this file except in - * compliance with the License. - * - * You can obtain a copy of the License at http://www.netbeans.org/cddl.html - * or http://www.netbeans.org/cddl.txt. - * - * When distributing Covered Code, include this CDDL Header Notice in each file - * and include the License file at http://www.netbeans.org/cddl.txt. - * If applicable, add the following below the CDDL Header, with the fields - * enclosed by brackets [] replaced by your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun - * Microsystems, Inc. All Rights Reserved. - */ -package org.jackhuang.hmcl.util.ui.wizard.api; - -import java.util.Map; - -/** - * Object which is called when the wizard is completed or cancelled. Only - * useful if you want to call WizardDisplayer.installInContainer() to install - * a wizard in a custom container (such as a JInternalDialog) - this class - * is a callback to notify the caller that the Finish or Cancel button has - * been pressed. - * - * @author Tim Boudreau - */ -public interface WizardResultReceiver { - /** - * Called when the wizard has been completed, providing whatever object - * the wizard created as its result. - * @param wizardResult The object created by Wizard.finish() - */ - void finished (Object wizardResult); - /** - * Called when the wizard has been cancelled. - * @param settings The settings that were gathered thus far in the - * wizard - */ - void cancelled (Map settings); -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/api/displayer/InstructionsPanel.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/api/displayer/InstructionsPanel.java deleted file mode 100644 index 08a6ac03d..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/api/displayer/InstructionsPanel.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ - -package org.jackhuang.hmcl.util.ui.wizard.api.displayer; - -import java.awt.Container; - -/** - * Interface for providing the UI for instructions displayed in a wizard. - * - * @author Tim Boudreau - */ -public interface InstructionsPanel { - /** - * Get the component that will actually display the instructions. - * Note that this component should have a layout manager that can position - * a single component in a location that will not obscure the instructions, - * for showing a progress bar. - * - * This method should always return the same component. - * - * @return A component that can listen to the wizard, display the steps - * in that wizard, notice and update when they change, and optionally - * highlight the current step. - */ - public Container getComponent(); - /** - * Set whether or not the panel is in the summary page at the end of a - * wizard (in which case it should add a "summary" item to its - * list of steps and highlight that). - * - * @param val Whether or not the wizard has navigated to a summary page. - */ - public void setInSummaryPage (boolean val); -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/api/displayer/NavButtonManager.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/api/displayer/NavButtonManager.java deleted file mode 100644 index b297cb2b4..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/api/displayer/NavButtonManager.java +++ /dev/null @@ -1,631 +0,0 @@ -/* - * NavButtonManager.java created on Dec 9, 2006 - * - */ -package org.jackhuang.hmcl.util.ui.wizard.api.displayer; - -import java.awt.Cursor; -import java.awt.Dimension; -import java.awt.EventQueue; -import java.awt.Insets; -import java.awt.Window; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.NoSuchElementException; - -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.JDialog; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JRootPane; -import javax.swing.UIManager; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.util.ui.wizard.modules.MergeMap; -import org.jackhuang.hmcl.util.ui.wizard.spi.DeferredWizardResult; -import org.jackhuang.hmcl.util.ui.wizard.spi.Summary; -import org.jackhuang.hmcl.util.ui.wizard.spi.Wizard; -import org.jackhuang.hmcl.util.ui.wizard.spi.WizardException; -import org.jackhuang.hmcl.util.ui.wizard.spi.WizardObserver; -import org.jackhuang.hmcl.util.ui.wizard.spi.WizardPanel; -import org.jackhuang.hmcl.util.ui.wizard.spi.WizardPanelNavResult; - -/** - * Manage the button state and interaction with the wizard. - *

    - * This class is NOT AN API CLASS. There is no - * commitment that it will remain backward compatible or even exist in the - * future. The API of this library is in the packages - * org.netbeans.api.wizard - * and org.netbeans.spi.wizard. - * - * @author stanley@stanleyknutson.com - */ -public class NavButtonManager implements ActionListener { - - static final String NAME_NEXT = "next"; - - static final String NAME_PREV = "prev"; - - static final String NAME_FINISH = "finish"; - - static final String NAME_CANCEL = "cancel"; - - static final String NAME_CLOSE = "close"; - - /** - * Prefix for the name in deferredStatus - */ - static final String DEFERRED_FAILED = "FAILED_"; - - JButton next = null; - - JButton prev = null; - - JButton finish = null; - - JButton cancel = null; - - JButton help = null; - - JPanel buttons = null; - - // container can be JDialog or JFrame - private Window window; - - WizardDisplayerImpl parent; - - boolean suppressMessageDialog = false; - /** - * Deferred status of not null means we are waiting for a deferred result to - * be completed as part of the handling for some button Value of the - * deferredStatus is the NAME_* constant that triggered the deferred - * operation. - */ - String deferredStatus = null; - - NavButtonManager(WizardDisplayerImpl impl) { - parent = impl; - } - - protected void buildButtons(Action helpAction) { - - next = new JButton(C.i18n("wizard.next_>")); - next.setName(NAME_NEXT); - next.setMnemonic(C.i18n("wizard.next_mnemonic").charAt(0)); - - prev = new JButton(C.i18n("wizard.<_prev")); - prev.setName(NAME_PREV); - prev.setMnemonic(C.i18n("wizard.prev_mnemonic").charAt(0)); - - finish = new JButton(C.i18n("wizard.finish")); - finish.setName(NAME_FINISH); - finish.setMnemonic(C.i18n("wizard.finish_mnemonic").charAt(0)); - - cancel = new JButton(C.i18n("wizard.cancel")); - cancel.setName(NAME_CANCEL); - cancel.setMnemonic(C.i18n("wizard.cancel_mnemonic").charAt(0)); - - help = new JButton(); - if (helpAction != null) - help.setAction(helpAction); - if (helpAction == null || helpAction.getValue(Action.NAME) == null) { - help.setText(C.i18n("wizard.help")); - help.setMnemonic(C.i18n("wizard.help_mnemonic").charAt(0)); - } - - next.setDefaultCapable(true); - prev.setDefaultCapable(true); - - help.setVisible(helpAction != null); - - // Use standard default-button-last order on Aqua L&F - final boolean aqua = "Aqua".equals(UIManager.getLookAndFeel().getID()); - - buttons = new JPanel() { - @Override - public void doLayout() { - Insets ins = getInsets(); - JButton b = aqua ? finish : cancel; - - Dimension n = b.getPreferredSize(); - int y = ((getHeight() - (ins.top + ins.bottom)) / 2) - (n.height / 2); - int gap = 5; - int x = getWidth() - (12 + ins.right + n.width); - - b.setBounds(x, y, n.width, n.height); - - b = aqua ? next : finish; - n = b.getPreferredSize(); - x -= n.width + gap; - b.setBounds(x, y, n.width, n.height); - - b = aqua ? prev : next; - n = b.getPreferredSize(); - x -= n.width + gap; - b.setBounds(x, y, n.width, n.height); - - b = aqua ? cancel : prev; - n = b.getPreferredSize(); - x -= n.width + gap; - b.setBounds(x, y, n.width, n.height); - - b = help; - n = b.getPreferredSize(); - x -= n.width + (gap * 2); - b.setBounds(x, y, n.width, n.height); - } - }; - buttons.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, UIManager - .getColor("textText"))); - - buttons.add(prev); - buttons.add(next); - buttons.add(finish); - buttons.add(cancel); - buttons.add(help); - - next.addActionListener(this); - prev.addActionListener(this); - finish.addActionListener(this); - cancel.addActionListener(this); - } - - void connectListener() { - NavWizardObserver l = new NavWizardObserver(); - Wizard wizard = parent.getWizard(); - l.stepsChanged(wizard); - l.navigabilityChanged(wizard); - l.selectionChanged(wizard); - wizard.addWizardObserver(l); - } - - private void configureNavigationButtons(final Wizard wizard, final JButton prev, - final JButton next, final JButton finish) { - final String nextStep = wizard.getNextStep(); - final int fwdNavMode = wizard.getForwardNavigationMode(); - - WizardDisplayerImpl.checkLegalNavMode(fwdNavMode); - - final String problem = wizard.getProblem(); - - final boolean isDeferredResult = deferredStatus != null; - - final boolean canContinue = (fwdNavMode & Wizard.MODE_CAN_CONTINUE) != 0 && !isDeferredResult; - final boolean canFinish = (fwdNavMode & Wizard.MODE_CAN_FINISH) != 0 && !isDeferredResult; - final boolean enableFinish = canFinish && problem == null && !isDeferredResult; - final boolean enableNext = nextStep != null && canContinue && problem == null && !isDeferredResult; - final boolean enablePrevious = wizard.getPreviousStep() != null && !isDeferredResult; - - final Runnable runnable = () -> { - next.setEnabled(enableNext); - prev.setEnabled(enablePrevious); - finish.setEnabled(enableFinish); - JRootPane root = next.getRootPane(); - if (root != null) - if (next.isEnabled()) - root.setDefaultButton(next); - else if (finish.isEnabled()) - root.setDefaultButton(finish); - else if (prev.isEnabled()) - root.setDefaultButton(prev); - else - root.setDefaultButton(null); - }; - - if (EventQueue.isDispatchThread()) - runnable.run(); - else - EventQueue.invokeLater(runnable); - - } - - @Override - public void actionPerformed(ActionEvent event) { - - JButton button = (JButton) event.getSource(); - - String name = button.getName(); - - if (NAME_CANCEL.equals(name)) { - processCancel(event, true); - return; - } - - // probably an error status - if (deferredStatus != null) { - deferredResultFinished(event); - return; - } - - if (null != name) - switch (name) { - case NAME_NEXT: - processNext(); - break; - case NAME_PREV: - processPrev(); - break; - case NAME_FINISH: - processFinish(event); - break; - case NAME_CLOSE: - processClose(event); - // else ignore, we don't know it - break; - default: - break; - } - // else ignore, we don't know it - - parent.updateProblem(); - } - - void deferredResultFailed(final boolean canGoBack) { - final Runnable runnable = () -> { - if (!canGoBack) - getCancel().setText(getCloseString()); - getPrev().setEnabled(true); - getNext().setEnabled(false); - getCancel().setEnabled(true); - getFinish().setEnabled(false); - - if (NAME_CLOSE.equals(deferredStatus)) { - // no action - } else - deferredStatus = DEFERRED_FAILED + deferredStatus; - }; - if (EventQueue.isDispatchThread()) - runnable.run(); - else - EventQueue.invokeLater(runnable); - } - - void deferredResultFinished(Object o) { - String name = deferredStatus; - deferredStatus = null; - - configureNavigationButtons(parent.getWizard(), prev, next, finish); - - if (name.startsWith(DEFERRED_FAILED)) { - // Cancel clicked after a deferred failure - if (o instanceof ActionEvent) { - JButton button = (JButton) ((ActionEvent) o).getSource(); - name = button.getName(); - if (NAME_CANCEL.equals(name)) { - processCancel(o instanceof ActionEvent ? (ActionEvent) o - : null, false); - return; - } - } - // in failed state, so we always reload the current step's screen - String currentStep = parent.getCurrentStep(); - parent.navigateTo(currentStep); - return; - } - - switch (name) { - case NAME_NEXT: - processNextProceed(o); - break; - // else ignore, we don't know it - case NAME_PREV: - processPrevProceed(o); - break; - case NAME_CANCEL: - processCancel(o instanceof ActionEvent ? (ActionEvent) o - : null, false); - break; - case NAME_FINISH: - // allowFinish on the "down" click of the finish button - processFinishProceed(o); - break; - case NAME_CLOSE: - // the "up" click of the finish button: wizard.finish was a deferred result - Window dlg = getWindow(); - dlg.setVisible(false); - dlg.dispose(); - break; - default: - break; - } - - parent.updateProblem(); - } - - protected void processNext() { - WizardPanel panel = parent.getCurrentWizardPanel(); - Wizard wizard = parent.getWizard(); - MergeMap settings = parent.getSettings(); - - WizardPanelNavResult proceed = WizardPanelNavResult.PROCEED; - if (panel != null) { - String currentStep = parent.getCurrentStep(); - proceed = panel.allowNext(currentStep, settings, wizard); - if (proceed.isDeferredComputation()) { - deferredStatus = NAME_NEXT; - configureNavigationButtons(wizard, prev, next, finish); - parent.handleDeferredWizardResult(proceed, false); - return; - } - } - - processNextProceed(proceed); - } - - protected void processNextProceed(Object result) { - Wizard wizard = parent.getWizard(); - MergeMap settings = parent.getSettings(); - - if (WizardPanelNavResult.REMAIN_ON_PAGE.equals(result)) - // leave current panel displayed, assume problem is being shown - return; - // ignore other results - - String nextId = wizard.getNextStep(); - settings.push(nextId); - parent.navigateTo(nextId); - parent.setInSummary(false); - } - - protected void processPrev() { - WizardPanel panel = parent.getCurrentWizardPanel(); - Wizard wizard = parent.getWizard(); - MergeMap settings = parent.getSettings(); - - WizardPanelNavResult proceed = WizardPanelNavResult.PROCEED; - if (panel != null) { - String currentStep = parent.getCurrentStep(); - proceed = panel.allowBack(currentStep, settings, wizard); - if (proceed.isDeferredComputation()) { - deferredStatus = NAME_PREV; - parent.handleDeferredWizardResult(proceed, false); - return; - } - } - - processPrevProceed(proceed); - } - - protected void processPrevProceed(Object result) { - Wizard wizard = parent.getWizard(); - MergeMap settings = parent.getSettings(); - - if (WizardPanelNavResult.REMAIN_ON_PAGE.equals(result)) - // leave current panel displayed, assume problem is being shown - return; - // ignore other results - - String prevId = wizard.getPreviousStep(); - settings.popAndCalve(); - parent.setDeferredResult(null); - parent.navigateTo(prevId); - parent.setInSummary(false); - } - - protected void processFinish(ActionEvent event) { - WizardPanel panel = parent.getCurrentWizardPanel(); - Wizard wizard = parent.getWizard(); - MergeMap settings = parent.getSettings(); - - WizardPanelNavResult proceed = WizardPanelNavResult.PROCEED; - if (panel != null) { - String currentStep = parent.getCurrentStep(); - proceed = panel.allowFinish(currentStep, settings, wizard); - if (proceed.isDeferredComputation()) { - deferredStatus = NAME_FINISH; - parent.handleDeferredWizardResult((DeferredWizardResult) proceed, false); - return; - } - } - - processFinishProceed(proceed); - } - - protected void processFinishProceed(Object result) { - Wizard wizard = parent.getWizard(); - MergeMap settings = parent.getSettings(); - - if (WizardPanelNavResult.REMAIN_ON_PAGE.equals(result)) - // leave current panel displayed, assume problem is being shown - return; - try { - Object o = wizard.finish(settings); - // System.err.println("WIZARD FINISH GOT ME A " + o); - - boolean closeWindow = true; - - if (o instanceof DeferredWizardResult) { - final DeferredWizardResult r = (DeferredWizardResult) o; - finish.setEnabled(false); - cancel.setEnabled(r.canAbort()); - prev.setEnabled(false); - next.setEnabled(false); - - // the button still says "cancel" - deferredStatus = NAME_CANCEL; - // deferredStatus = NAME_CLOSE; - parent.handleDeferredWizardResult(r, true); - - closeWindow = false; - } else if (o instanceof Summary) { - parent.handleSummary((Summary) o); - parent.setWizardResult(((Summary) o).getResult()); - // setSummaryShowingMode will be called - // need to share code with NavProgress.finished code path - closeWindow = false; - } else - parent.setWizardResult(o); - - if (closeWindow) - // do cancel processing as well - processCancel(null, false); - } catch (WizardException we) { - if (!suppressMessageDialog) - JOptionPane.showMessageDialog(next, we.getLocalizedMessage()); - String id = we.getStepToReturnTo(); - String curr = settings.currID(); - try { - while (id != null && !id.equals(curr)) - curr = settings.popAndCalve(); - settings.push(id); - parent.navigateTo(id); - } catch (NoSuchElementException ex) { - IllegalStateException e = new IllegalStateException("Exception " - + "said to return to " + id + " but no such " - + "step found", ex); - throw e; - } - } - } - - protected void processCancel(ActionEvent event, boolean reallyCancel) { - DeferredWizardResult deferredResult = parent.getDeferredResult(); - if (deferredResult != null && deferredResult.canAbort()) - deferredResult.abort(); - Wizard wizard = parent.getWizard(); - MergeMap settings = parent.getSettings(); - - boolean closeWindow; - - if (reallyCancel && parent.cancel()) { - wizard.cancel(settings); - return; - } - - closeWindow = reallyCancel ? wizard.cancel(settings) : parent.receiver == null; - - // if we have the event (allowFinish was not deferred) then be very sure to close the proper dialog - if (closeWindow) { - Window win = event != null ? (Window) ((JComponent) event.getSource()).getTopLevelAncestor() - : getWindow(); - win.setVisible(false); - win.dispose(); - } - } - - protected void processClose(ActionEvent event) { - Window win = (Window) ((JComponent) event.getSource()).getTopLevelAncestor(); - win.setVisible(false); - win.dispose(); - } - - void updateButtons() { - Wizard wizard = parent.getWizard(); - if (!wizard.isBusy()) - configureNavigationButtons(wizard, prev, next, finish); - } - - void setSummaryShowingMode() { - next.setEnabled(false); - prev.setEnabled(false); - cancel.setEnabled(true); - finish.setEnabled(false); - if (window != null && parent.receiver == null && window instanceof JDialog) - ((JDialog) window).getRootPane().setDefaultButton(cancel); - - cancel.setText(getCloseString()); - cancel.setMnemonic(C.i18n("wizard.close_mnemonic").charAt(0)); - cancel.setName(NAME_CLOSE); - deferredStatus = null; // ?? should summary be different - } - - void setWindow(Window dlg) { - this.window = dlg; - } - - public JPanel getButtons() { - return buttons; - } - - public JButton getCancel() { - return cancel; - } - - public String getCloseString() { - return C.i18n("wizard.close"); - } - - public Window getWindow() { - return window; - } - - public JButton getFinish() { - return finish; - } - - public JButton getHelp() { - return help; - } - - public JButton getNext() { - return next; - } - - public WizardDisplayerImpl getParent() { - return parent; - } - - public JButton getPrev() { - return prev; - } - - public void initializeNavigation() { - Wizard wizard = parent.getWizard(); - prev.setEnabled(false); - next.setEnabled(wizard.getNextStep() != null); - int fwdNavMode = wizard.getForwardNavigationMode(); - WizardDisplayerImpl.checkLegalNavMode(fwdNavMode); - - finish.setEnabled((fwdNavMode & Wizard.MODE_CAN_FINISH) != 0); - - connectListener(); - } - - // ------------------------------------- - /** - * Listener for wizard changages that affect button state - */ - class NavWizardObserver implements WizardObserver { - - boolean wasBusy = false; - - @Override - public void stepsChanged(Wizard wizard) { - // do nothing - } - - @Override - public void navigabilityChanged(final Wizard wizard) { - final Runnable runnable = () -> { - if (wizard.isBusy()) { - next.setEnabled(false); - prev.setEnabled(false); - finish.setEnabled(false); - cancel.setEnabled(false); - parent.getOuterPanel().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - wasBusy = true; - return; - } else if (wasBusy) { - cancel.setEnabled(true); - parent.getOuterPanel().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - } - configureNavigationButtons(wizard, prev, next, finish); - - parent.updateProblem(); - }; - if (EventQueue.isDispatchThread()) - runnable.run(); - else - EventQueue.invokeLater(runnable); - } - - @Override - public void selectionChanged(Wizard wizard) { - // do nothing - } - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/api/displayer/NavProgress.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/api/displayer/NavProgress.java deleted file mode 100644 index d168f5c86..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/api/displayer/NavProgress.java +++ /dev/null @@ -1,147 +0,0 @@ -package org.jackhuang.hmcl.util.ui.wizard.api.displayer; - -import java.awt.Container; -import java.awt.EventQueue; -import java.lang.reflect.InvocationTargetException; - -import javax.swing.JLabel; -import javax.swing.JProgressBar; -import javax.swing.border.EmptyBorder; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.util.ui.wizard.spi.ResultProgressHandle; -import org.jackhuang.hmcl.util.ui.wizard.spi.Summary; - -/** - * Show progress bar for deferred results, with a label showing percent done and - * progress bar. - * - *

    - * This class is NOT AN API CLASS. There is no - * commitment that it will remain backward compatible or even exist in the - * future. The API of this library is in the packages - * org.netbeans.api.wizard - * and org.netbeans.spi.wizard. - * - * @author stanley@stanleyknutson.com - */ -public class NavProgress implements ResultProgressHandle { - - JProgressBar progressBar = new JProgressBar(); - - JLabel lbl = new JLabel(); - - WizardDisplayerImpl parent; - - String failMessage = null; - - Container ipanel = null; - - boolean isInitialized = false; - - /** - * isRunning is true until finished or failed is called - */ - boolean isRunning = true; - - NavProgress(WizardDisplayerImpl impl) { - this.parent = impl; - } - - @Override - public void addProgressComponents(Container panel) { - panel.add(lbl); - panel.add(progressBar); - isInitialized = true; - ipanel = panel; - } - - @Override - public void setProgress(final String description, final int currentStep, final int totalSteps) { - invoke(() -> { - lbl.setText(description == null ? " " : description); - setProgress(currentStep, totalSteps); - }); - } - - @Override - public void setProgress(final int currentStep, final int totalSteps) { - invoke(() -> { - if (totalSteps == -1) { - if (!progressBar.isIndeterminate()) - progressBar.setIndeterminate(true); - } else { - if (currentStep > totalSteps || currentStep < 0) { - if (currentStep == -1 && totalSteps == -1) - return; - throw new IllegalArgumentException("Bad step values: " - + currentStep + " out of " + totalSteps); - } - if (progressBar.isIndeterminate()) - progressBar.setIndeterminate(false); - progressBar.setMaximum(totalSteps); - progressBar.setValue(currentStep); - } - }); - } - - @Override - public void setBusy(final String description) { - invoke(() -> { - lbl.setText(description == null ? " " : description); - if (!progressBar.isIndeterminate()) - progressBar.setIndeterminate(true); - }); - } - - private void invoke(Runnable r) { - if (EventQueue.isDispatchThread()) - r.run(); - else - try { - EventQueue.invokeAndWait(r); - } catch (InvocationTargetException | InterruptedException ex) { - HMCLog.err("NavProgress: Error invoking operation", ex); - } - } - - @Override - public void finished(final Object o) { - isRunning = false; - Runnable r = () -> { - if (o instanceof Summary) { - Summary summary = (Summary) o; - parent.handleSummary(summary); - parent.setWizardResult(summary.getResult()); - } else if (parent.getDeferredResult() != null) { - parent.setWizardResult(o); - - // handle result based on which button was pushed - parent.getButtonManager().deferredResultFinished(o); - } - }; - invoke(r); - } - - @Override - public void failed(final String message, final boolean canGoBack) { - failMessage = message; - isRunning = false; - - Runnable r = () -> { - // cheap word wrap - JLabel comp = new JLabel("" + message); - comp.setBorder(new EmptyBorder(5, 5, 5, 5)); - parent.setCurrentWizardPanel(comp); - parent.getTtlLabel().setText(C.i18n("wizard.failed")); - NavButtonManager bm = parent.getButtonManager(); - bm.deferredResultFailed(canGoBack); - }; - invoke(r); - } - - @Override - public boolean isRunning() { - return isRunning; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/api/displayer/WizardDisplayerImpl.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/api/displayer/WizardDisplayerImpl.java deleted file mode 100644 index ed27578b3..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/api/displayer/WizardDisplayerImpl.java +++ /dev/null @@ -1,572 +0,0 @@ -/* - * The contents of this file are subject to the terms of the Common Development - * and Distribution License (the License). You may not use this file except in - * compliance with the License. - * You can obtain a copy of the License at http://www.netbeans.org/cddl.html - * or http://www.netbeans.org/cddl.txt. - * When distributing Covered Code, include this CDDL Header Notice in each file - * and include the License file at http://www.netbeans.org/cddl.txt. - * If applicable, add the following below the CDDL Header, with the fields - * enclosed by brackets [] replaced by your own identifying information: - * - * Written by Stanley@StanleyKnutson.com based on code from Tim B. - * - */ -package org.jackhuang.hmcl.util.ui.wizard.api.displayer; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.ComponentOrientation; -import java.awt.Container; -import java.awt.Cursor; -import java.awt.Dialog; -import java.awt.Dimension; -import java.awt.EventQueue; -import java.awt.Font; -import java.awt.Frame; -import java.awt.KeyboardFocusManager; -import java.awt.Rectangle; -import java.awt.Toolkit; -import java.awt.Window; -import java.awt.event.ActionEvent; -import java.awt.event.KeyEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.lang.reflect.InvocationTargetException; -import java.util.Map; -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.JDialog; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.KeyStroke; -import javax.swing.RootPaneContainer; -import javax.swing.UIManager; -import javax.swing.WindowConstants; -import javax.swing.border.Border; -import javax.swing.border.CompoundBorder; -import javax.swing.border.EmptyBorder; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.util.ui.wizard.api.WizardDisplayer; -import org.jackhuang.hmcl.util.ui.wizard.api.WizardResultReceiver; -import org.jackhuang.hmcl.util.ui.wizard.modules.InstructionsPanelImpl; -import org.jackhuang.hmcl.util.ui.wizard.modules.MergeMap; -import org.jackhuang.hmcl.util.ui.wizard.spi.DeferredWizardResult; -import org.jackhuang.hmcl.util.ui.wizard.spi.ResultProgressHandle; -import org.jackhuang.hmcl.util.ui.wizard.spi.Summary; -import org.jackhuang.hmcl.util.ui.wizard.spi.Wizard; -import org.jackhuang.hmcl.util.ui.wizard.spi.WizardPanel; - -/** - * Default implementation of WizardDisplayer. - * This class is NOT AN API CLASS. There is no - * commitment that it will remain backward compatible or even exist in the - * future. The API of this library is in the packages - * org.netbeans.api.wizard and - * org.netbeans.spi.wizard. - *

    - * Use WizardDisplayer.showWizard() or its other static methods to - * display wizards in a way which will continue to work over time. - * - * @author stanley@StanleyKnutson.com - * @author Tim Boudreau - */ -public class WizardDisplayerImpl extends WizardDisplayer { - - ResultProgressHandle progress = null; - - JLabel ttlLabel = null; - - JPanel ttlPanel = null; - - Wizard wizard = null; - - JPanel outerPanel = null; - - NavButtonManager buttonManager = null; - - InstructionsPanel instructions = null; - - MergeMap settings = null; - - JPanel inner = null; - - JLabel problem = null; - - Object wizardResult = null; - - WizardResultReceiver receiver = null; - - /** - * WizardPanel is the panel returned as the panel to display. Often a - * subclass of WizardPanel - */ - JComponent wizardPanel = null; - - boolean inSummary = false; - - DeferredWizardResult deferredResult = null; - - /** - * Default constructor used by WizardDisplayer static methods. - * - */ - public WizardDisplayerImpl() { - } - - protected void buildStepTitle() { - ttlLabel = new JLabel(wizard.getStepDescription(wizard.getAllSteps()[0])); - ttlLabel.setBorder(BorderFactory.createCompoundBorder(BorderFactory - .createEmptyBorder(5, 5, 12, 5), BorderFactory.createMatteBorder(0, 0, 1, 0, UIManager - .getColor("textText")))); - ttlPanel = new JPanel() { - @Override - public void doLayout() { - Dimension d = ttlLabel.getPreferredSize(); - if (ttlLabel.getComponentOrientation() == ComponentOrientation.RIGHT_TO_LEFT) - ttlLabel.setBounds(getWidth() - d.width, 0, getWidth(), d.height); - else - ttlLabel.setBounds(0, 0, getWidth(), d.height); - } - - @Override - public Dimension getPreferredSize() { - return ttlLabel.getPreferredSize(); - } - }; - ttlPanel.add(ttlLabel); - Font f = ttlLabel.getFont(); - if (f == null) - f = UIManager.getFont("controlFont"); - if (f != null) { - f = f.deriveFont(Font.BOLD); - ttlLabel.setFont(f); - } - - } - - /** - * Show a wizard - * - * @param awizard is the wizard to be displayed - * @param bounds for display, may be null for default of 0,0,400,600. - * @param helpAction - * @param initialProperties - initial values for the map - * - * @return value of the 'finish' processing - * - * @see - * org.netbeans.api.wizard.WizardDisplayer#show(org.netbeans.spi.wizard.Wizard, - * java.awt.Rectangle, javax.swing.Action, java.util.Map) - */ - private JPanel createOuterPanel(final Wizard awizard, Rectangle bounds, Action helpAction, - Map initialProperties) { - - this.wizard = awizard; - - outerPanel = new JPanel(); - - if (wizard.getAllSteps().length == 0) - throw new IllegalArgumentException("Wizard has no steps"); - - // initialize the ttl* stuff - buildStepTitle(); - - buttonManager = new NavButtonManager(this); - - outerPanel.setLayout(new BorderLayout()); - - Action kbdCancel = new AbstractAction() { - @Override - public void actionPerformed(ActionEvent e) { - JButton b = buttonManager.getCancel(); - if (b.isEnabled()) - b.doClick(); - } - }; - outerPanel.getInputMap(JPanel.WHEN_IN_FOCUSED_WINDOW).put( - KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "cancel"); - outerPanel.getActionMap().put("cancel", kbdCancel); - - instructions = createInstructionsPanel(); - - buttonManager.buildButtons(helpAction); - - inner = new JPanel(); - inner.setLayout(new BorderLayout()); - inner.add(ttlPanel, BorderLayout.NORTH); - - problem = new JLabel(" "); - Color fg = UIManager.getColor("nb.errorColor"); - problem.setForeground(fg == null ? Color.BLUE : fg); - inner.add(problem, BorderLayout.SOUTH); - problem.setPreferredSize(new Dimension(20, 20)); - - outerPanel.add(instructions.getComponent(), BorderLayout.WEST); - outerPanel.add(buttonManager.getButtons(), BorderLayout.SOUTH); - outerPanel.add(inner, BorderLayout.CENTER); - - String first = wizard.getAllSteps()[0]; - settings = new MergeMap(first); - - // introduce the initial properties as if they had been set on page 1 - // even though they may be defaults for page 2 - if (initialProperties != null) - settings.putAll(initialProperties); - - wizardPanel = wizard.navigatingTo(first, settings); - String desc = wizard.getLongDescription(first); - if (desc != null) - ttlLabel.setText(desc); - - inner.add(wizardPanel, BorderLayout.CENTER); - - buttonManager.initializeNavigation(); - return outerPanel; - } - - protected InstructionsPanel createInstructionsPanel() { - return new InstructionsPanelImpl(wizard); - } - - @Override - public void install(Container c, Object layoutConstraint, Wizard awizard, - Action helpAction, Map initialProperties, WizardResultReceiver receiver) { - JPanel pnl = createOuterPanel(awizard, new Rectangle(), helpAction, initialProperties); - if (layoutConstraint != null) - if (c instanceof RootPaneContainer) - ((RootPaneContainer) c).getContentPane().add(pnl, layoutConstraint); - else - c.add(pnl, layoutConstraint); - else if (c instanceof RootPaneContainer) - ((RootPaneContainer) c).getContentPane().add(pnl); - else - c.add(pnl); - this.receiver = receiver; - } - - private static boolean warned; - - @Override - public Object show(final Wizard awizard, Rectangle bounds, Action helpAction, - Map initialProperties) { - if (!EventQueue.isDispatchThread() && !warned) { - HMCLog.warn("WizardDisplayerImpl: show() should be called from the AWT Event Thread. This " - + "call may deadlock - c.f. " - + "http://java.net/jira/browse/WIZARD-33", new Throwable()); - warned = true; - } - createOuterPanel(awizard, bounds, helpAction, initialProperties); - Object result = showInDialog(bounds); - return result; - } - - protected JDialog createDialog() { - JDialog dlg; - Object o = findLikelyOwnerWindow(); - if (o instanceof Frame) - dlg = new JDialog((Frame) o); - else if (o instanceof Dialog) - dlg = new JDialog((Dialog) o); - else - dlg = new JDialog(); - return dlg; - } - - protected Object showInDialog(Rectangle bounds) { - // TODO: add flag for "showInFrame" - - JDialog dlg = createDialog(); - - buttonManager.setWindow(dlg); - - dlg.setTitle(wizard.getTitle()); - - dlg.getContentPane().setLayout(new BorderLayout()); - dlg.getContentPane().add(outerPanel, BorderLayout.CENTER); - if (bounds != null) - dlg.setBounds(bounds); - else - dlg.pack(); - dlg.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); - dlg.addWindowListener(new WindowAdapter() { - @Override - public void windowClosing(WindowEvent e) { - if (e.getWindow() instanceof JDialog) { - JDialog dlg = (JDialog) e.getWindow(); - boolean dontClose = false; - if (!wizard.isBusy()) { - DeferredWizardResult defResult; - synchronized (WizardDisplayerImpl.this) { - defResult = deferredResult; - } - try { - if (defResult != null && defResult.canAbort()) - defResult.abort(); - else if (defResult != null && !defResult.canAbort()) - dontClose = true; - } finally { - if (!dontClose && wizard.cancel(settings)) { - dlg.setVisible(false); - dlg.dispose(); - } - } - } - } - } - }); - - Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); - if (bounds == null) { - // XXX get screen insets? - int x = (d.width - dlg.getWidth()) / 2; - int y = (d.height - dlg.getHeight()) / 2; - dlg.setLocation(x, y); - } - - dlg.setModal(true); - dlg.getRootPane().setDefaultButton(buttonManager.getNext()); - dlg.setVisible(true); - - return wizardResult; - } - - private Window findLikelyOwnerWindow() { - return KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusedWindow(); - } - - /** - * Return the current wizard panel, or null if the currently displayed page - * is not a WizardPanel. - * - * @return - */ - public WizardPanel getCurrentWizardPanel() { - JComponent comp = wizardPanel; - if (comp instanceof WizardPanel) - return (WizardPanel) comp; - return null; - } - - public String getCurrentStep() { - return settings.currID(); - } - - // available in the package only - static void checkLegalNavMode(int i) { - switch (i) { - case Wizard.MODE_CAN_CONTINUE: - case Wizard.MODE_CAN_CONTINUE_OR_FINISH: - case Wizard.MODE_CAN_FINISH: - return; - default: - throw new IllegalArgumentException("Illegal forward " - + "navigation mode: " + i); - } - } - - /* - * private static final class LDlg extends JDialog { public LDlg() { - * } public LDlg (Frame frame) { super (frame); } - * - * public LDlg (Dialog dlg) { super (dlg); } - * - * public void setVisible (boolean val) { if (!val) { Thread.dumpStack(); } - * super.setVisible (val); } } - */ - /** - * Set the currently displayed panel. - * - * @parm comp is can be anything - it is not required to be a WizardPage or - * WizardPanel - * - */ - public void setCurrentWizardPanel(JComponent comp) { - inner.add(comp, BorderLayout.CENTER); - inner.remove(wizardPanel); - wizardPanel = comp; - inner.invalidate(); - inner.revalidate(); - inner.repaint(); - comp.requestFocus(); - if (!inSummary) - buttonManager.updateButtons(); - } - - void handleSummary(Summary summary) { - inSummary = true; - instructions.setInSummaryPage(true); - JComponent summaryComp = (JComponent) summary.getSummaryComponent(); // XXX - if (summaryComp.getBorder() != null) { - CompoundBorder b = new CompoundBorder(new EmptyBorder(5, 5, 5, 5), summaryComp - .getBorder()); - summaryComp.setBorder(b); - } - setCurrentWizardPanel((JComponent) summaryComp); // XXX - ttlLabel.setText(C.i18n("wizard.summary")); - getButtonManager().setSummaryShowingMode(); - summaryComp.requestFocus(); - - } - - protected ResultProgressHandle createProgressDisplay() { - return new NavProgress(this); - } - - void handleDeferredWizardResult(final DeferredWizardResult r, final boolean inSummary) { - synchronized (this) { - deferredResult = r; - } - wizardPanel.setEnabled(false); - progress = createProgressDisplay(); - Container inst = instructions.getComponent(); - progress.addProgressComponents(inst); - inst.invalidate(); - if (inst instanceof JComponent) - ((JComponent) inst).revalidate(); - inst.repaint(); - Runnable run = new Runnable() { - @Override - public void run() { - if (!EventQueue.isDispatchThread()) - try { - EventQueue.invokeLater(() -> buttonManager.getWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR))); - r.start(settings, progress); - if (progress.isRunning()) - progress.failed("Start method did not inidicate " - + "failure or finished in " + r, false); - - } finally { - try { - EventQueue.invokeAndWait(this); - } catch (InvocationTargetException | InterruptedException ex) { - HMCLog.err("Failed to invoke and wait", ex); - return; - } finally { - buttonManager.getWindow().setCursor(Cursor.getDefaultCursor()); - } - } - else { - synchronized (WizardDisplayerImpl.this) { - deferredResult = null; - } - buttonManager.getCancel().setEnabled(true); - Container inst = instructions.getComponent(); - inst.removeAll(); - inst.invalidate(); - if (inst instanceof JComponent) - ((JComponent) instructions).revalidate(); - inst.repaint(); - } - } - }; - Thread runner = new Thread(run, "Wizard Background Result Thread " + r); - runner.setDaemon(true); - runner.start(); - } - - public void navigateTo(String id) { - JComponent comp = wizard.navigatingTo(id, getSettings()); - String description = wizard.getLongDescription(id); - if (description == null) - description = wizard.getStepDescription(id); - getTtlLabel().setText(description); - setCurrentWizardPanel(comp); - } - - public NavButtonManager getButtonManager() { - return buttonManager; - } - - public synchronized DeferredWizardResult getDeferredResult() { - return deferredResult; - } - - public InstructionsPanel getInstructions() { - return instructions; - } - - public boolean isInSummary() { - return inSummary; - } - - public void setInSummary(final boolean state) { - inSummary = state; - Runnable r = () -> instructions.setInSummaryPage(state); - if (EventQueue.isDispatchThread()) - r.run(); - else - EventQueue.invokeLater(r); - } - - public JPanel getOuterPanel() { - return outerPanel; - } - - public MergeMap getSettings() { - return settings; - } - - public JLabel getTtlLabel() { - return ttlLabel; - } - - public JPanel getTtlPanel() { - return ttlPanel; - } - - public Wizard getWizard() { - return wizard; - } - - public JComponent getWizardPanel() { - return wizardPanel; - } - - public Object getWizardResult() { - return wizardResult; - } - - public void setWizardResult(Object wizardResult) { - this.wizardResult = wizardResult; - if (receiver != null) - receiver.finished(wizardResult); - } - - public synchronized void setDeferredResult(DeferredWizardResult deferredResult) { - this.deferredResult = deferredResult; - } - - /** - * Will only be called if there is a WizardResultReceiver - i.e. if the - * wizard is being displayed in some kind of custom container. Return true - * to indicate we should not try to close the parent window. - */ - boolean cancel() { - boolean result = receiver != null; - if (result) - receiver.cancelled(settings); - return result; - } - - void updateProblem() { - String prob = wizard.getProblem(); - problem.setText(prob == null ? " " : prob); - if (prob != null && prob.trim().length() == 0) - // Issue 3 - provide ability to disable next w/o - // showing the error line - prob = null; - Border b = prob == null ? BorderFactory.createEmptyBorder(1, 0, 0, 0) : BorderFactory - .createMatteBorder(1, 0, 0, 0, problem.getForeground()); - - Border b1 = BorderFactory.createCompoundBorder(BorderFactory - .createEmptyBorder(0, 12, 0, 12), b); - - problem.setBorder(b1); - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/modules/InstructionsPanelImpl.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/modules/InstructionsPanelImpl.java deleted file mode 100644 index a7b81d728..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/modules/InstructionsPanelImpl.java +++ /dev/null @@ -1,429 +0,0 @@ -/* - * The contents of this file are subject to the terms of the Common Development - * and Distribution License (the License). You may not use this file except in - * compliance with the License. - * You can obtain a copy of the License at http://www.netbeans.org/cddl.html - * or http://www.netbeans.org/cddl.txt. - * When distributing Covered Code, include this CDDL Header Notice in each file - * and include the License file at http://www.netbeans.org/cddl.txt. - * If applicable, add the following below the CDDL Header, with the fields - * enclosed by brackets [] replaced by your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - */ - /* - * InstructionsPanel.java - * - * Created on March 4, 2005, 8:59 PM - */ -package org.jackhuang.hmcl.util.ui.wizard.modules; - -import java.awt.Color; -import java.awt.Component; -import java.awt.Container; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.IllegalComponentStateException; -import java.awt.Insets; -import java.awt.RenderingHints; -import java.awt.image.BufferedImage; -import java.io.IOException; -import java.util.Locale; -import java.util.Arrays; -import javax.accessibility.Accessible; -import javax.accessibility.AccessibleContext; -import javax.accessibility.AccessibleRole; -import javax.accessibility.AccessibleState; -import javax.accessibility.AccessibleStateSet; -import javax.accessibility.AccessibleText; -import javax.imageio.ImageIO; -import javax.swing.CellRendererPane; -import javax.swing.JComponent; -import javax.swing.JEditorPane; -import javax.swing.UIManager; -import org.jackhuang.hmcl.util.C; -import org.jackhuang.hmcl.api.HMCLog; -import org.jackhuang.hmcl.util.ui.wizard.api.displayer.InstructionsPanel; -import org.jackhuang.hmcl.util.ui.wizard.spi.Wizard; -import org.jackhuang.hmcl.util.ui.wizard.spi.WizardObserver; - -/** - * A panel that displays a background image and optionally instructions from a - * wizard, tracking the selected panel and showing that in bold. - *
    - * This class is NOT AN API CLASS. There is no - * commitment that it will remain backward compatible or even exist in the - * future. The API of this library is in the packages - * org.netbeans.api.wizard and - * org.netbeans.spi.wizard. - *
    - * There is currently a single use-case for subclassing this - a navigation - * panel that wants to display a different image for each step. - * - * @author Tim Boudreau - */ -public class InstructionsPanelImpl extends JComponent implements WizardObserver, Accessible, InstructionsPanel { - - private transient final BufferedImage img; - private transient final Wizard wizard; - private static final int MARGIN = 5; - - public InstructionsPanelImpl(Wizard wiz) { - this(null, wiz); - Font f = UIManager.getFont("Tree.font"); - if (f != null) - setFont(f); - } - - /** - * Get the wizard this panel is monitoring. - * - * @return - */ - protected final Wizard getWizard() { - return wizard; - } - - @Override - public final Container getComponent() { - return this; - } - - /** - * Overridden to start listening to the wizard when added to a container - */ - @Override - public void addNotify() { - super.addNotify(); - wizard.addWizardObserver(this); - } - - /** - * Overridden to stop listening to the wizard when removed from a container - */ - @Override - public void removeNotify() { - wizard.removeWizardObserver(this); - super.removeNotify(); - } - - /** - * Get the image to be displayed. Note that unpredictable behavior may - * result if all images returned from this method are not the same size. - * Override to display a different wizard depending on the step. - * - * @return - */ - protected BufferedImage getImage() { //for unit test - return img; - } - - public InstructionsPanelImpl(BufferedImage img, Wizard wizard) { - if (img == null) - try { - img = ImageIO.read(InstructionsPanelImpl.class.getResourceAsStream("/org/jackhuang/hmcl/wizard.jpg")); - } catch (IOException | NullPointerException ioe) { - HMCLog.err("Failed to load wizard.jpg, maybe you have fuckingly modified the launcher file", ioe); - } - this.img = img; - this.wizard = wizard; - } - - @Override - public boolean isOpaque() { - return img != null; - } - - /** - * Paints the background image for this component, or fills the background - * with a color if no image present. - * - * @param g A Graphic2D to paint into - * @param x The x coordinate of the area that should contain the image - * @param y The y coordinate of the area that should contain the image - * @param w The width of the area that should contain the image - * @param h The height of the area that should contain the image - */ - protected void paintImage(Graphics2D g, int x, int y, int w, int h) { - BufferedImage image = getImage(); - if (image != null) - g.drawImage(image, x, y, w, h, this); - else { - Color c = g.getColor(); - g.setColor(Color.WHITE); - g.fillRect(x, y, w, h); - g.setColor(c); - } - } - - String[] steps = new String[0]; - - @Override - public final void paintComponent(Graphics g) { - Graphics2D g2d = (Graphics2D) g; - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - - Font f = getFont() != null ? getFont() : UIManager.getFont("controlFont"); - FontMetrics fm = g.getFontMetrics(f); - Insets ins = getInsets(); - int dx = ins.left; - int dy = ins.top; - int w = getWidth() - (ins.left + ins.right); - int hh = getHeight() - (ins.top + ins.bottom); - paintImage(g2d, dx, dy, w, hh); - String currentStep = wizard.getCurrentStep(); - if (!inSummaryPage) - //Don't fetch step list if in summary page, there will - //only be the base ones - steps = wizard.getAllSteps(); - String[] steps2 = this.steps; - if (inSummaryPage) { - String summaryStep = C.i18n("wizard.summary"); - String[] nue = new String[steps2.length + 1]; - System.arraycopy(steps2, 0, nue, 0, steps2.length); - nue[nue.length - 1] = summaryStep; - steps2 = nue; - } - int y = fm.getMaxAscent() + ins.top + MARGIN; - int x = ins.left + MARGIN; - int h = fm.getMaxAscent() + fm.getMaxDescent() + 3; - - Font boldFont = f.deriveFont(Font.BOLD); - g.setFont(boldFont); - g.drawString(C.i18n("wizard.steps"), x, y); - - int underlineY = ins.top + MARGIN + fm.getAscent() + 3; - g.drawLine(x, underlineY, x + (getWidth() - (x + ins.left + MARGIN)), - underlineY); - - int bottom = getComponentCount() == 0 ? getHeight() - getInsets().bottom - : getHeight() - getInsets().bottom - getComponents()[0].getPreferredSize().height; - - y += h + 10; - int first = 0; - int stop = steps2.length; - boolean wontFit = y + (h * (steps2.length)) > getHeight(); - if (wontFit) { - //try to center the current step - int availHeight = bottom - y; - int willFit = availHeight / h; - int currStepIndex = Arrays.asList(steps2).indexOf(currentStep); - int rangeStart = Math.max(0, currStepIndex - (willFit / 2)); - int rangeEnd = Math.min(rangeStart + willFit, steps2.length); - if (rangeStart + willFit > steps2.length) { - //Don't scroll off if there's room - rangeStart = steps2.length - willFit; - rangeEnd = steps2.length; - } - steps2 = (String[]) steps2.clone(); - if (rangeStart != 0) { - steps2[rangeStart] = elipsis; - first = rangeStart; - } - if (rangeEnd != steps2.length && rangeEnd > 0) { - steps2[rangeEnd - 1] = elipsis; - stop = rangeEnd; - } - } - - g.setFont(getFont()); - g.setColor(getForeground()); - - for (int i = first; i < stop; i++) { - boolean isUndetermined = Wizard.UNDETERMINED_STEP.equals(steps2[i]); - boolean canOnlyFinish = wizard.getForwardNavigationMode() - == Wizard.MODE_CAN_FINISH; - if (isUndetermined && canOnlyFinish) - break; - String curr; - if (!elipsis.equals(steps2[i])) - if (inSummaryPage && i == this.steps.length) - curr = (i + 1) + ". " + steps2[i]; - else - curr = (i + 1) + ". " + (isUndetermined - ? elipsis - : steps2[i].equals(elipsis) ? elipsis - : wizard.getStepDescription(steps2[i])); - else - curr = elipsis; - boolean selected = (steps2[i].equals(currentStep) && !inSummaryPage) - || (inSummaryPage && i == steps2.length - 1); - if (selected) - g.setFont(boldFont); - - int width = fm.stringWidth(curr); - while (width > getWidth() - (ins.left + ins.right) && curr.length() > 5) - curr = curr.substring(0, curr.length() - 5) + elipsis; - - g.drawString(curr, x, y); - if (selected) - g.setFont(f); - y += h; - } - } - - private int historicWidth = Integer.MIN_VALUE; - - private static final String elipsis = "..."; - - @Override - public final Dimension getPreferredSize() { - Font f = getFont() != null ? getFont() - : UIManager.getFont("controlFont"); - - Graphics g = getGraphics(); - if (g == null) - g = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB).getGraphics(); - f = f.deriveFont(Font.BOLD); - FontMetrics fm = g.getFontMetrics(f); - Insets ins = getInsets(); - int h = fm.getHeight(); - - String[] steps2 = wizard.getAllSteps(); - int w = Integer.MIN_VALUE; - for (int i = 0; i < steps2.length; i++) { - String desc = i + ". " + (Wizard.UNDETERMINED_STEP.equals(steps2[i]) - ? elipsis - : wizard.getStepDescription(steps2[i])); - w = Math.max(w, fm.stringWidth(desc) + MARGIN); - } - if (Integer.MIN_VALUE == w) - w = 250; - BufferedImage image = getImage(); - if (image != null) - w = Math.max(w, image.getWidth()); - //Make sure we can grow but not shrink - w = Math.max(w, historicWidth); - historicWidth = w; - return new Dimension(w, ins.top + ins.bottom + ((h + 3) * steps2.length)); - } - - private boolean inSummaryPage; - - @Override - public void setInSummaryPage(boolean val) { - this.inSummaryPage = val; - repaint(); - } - - @Override - public final Dimension getMinimumSize() { - return getPreferredSize(); - } - - @Override - public void stepsChanged(Wizard wizard) { - repaint(); - } - - @Override - public void navigabilityChanged(Wizard wizard) { - //do nothing - } - - @Override - public void selectionChanged(Wizard wizard) { - repaint(); - } - - @Override - public final void doLayout() { - Component[] c = getComponents(); - Insets ins = getInsets(); - int y = getHeight() - (MARGIN + ins.bottom); - int x = MARGIN + ins.left; - int w = getWidth() - ((MARGIN * 2) + ins.left + ins.right); - if (w < 0) - w = 0; - for (int i = c.length - 1; i >= 0; i--) { - Dimension d = c[i].getPreferredSize(); - c[i].setBounds(x, y - d.height, w, d.height); - y -= d.height; - } - } - - @Override - public final AccessibleContext getAccessibleContext() { - return new ACI(this); - } - - private static final class ACI extends AccessibleContext { - - private final Wizard wizard; - private final InstructionsPanelImpl panel; - - public ACI(InstructionsPanelImpl pnl) { - this.wizard = pnl.wizard; - panel = pnl; - if (pnl.getParent() instanceof Accessible) - setAccessibleParent((Accessible) pnl.getParent()); - } - - JEditorPane pane; - - @Override - public AccessibleText getAccessibleText() { - if (pane == null) { - //Cheat just a bit here - will do for now - the text is - //there, more or less where it should be, and a screen - //reader should be able to find it; exact bounds don't - //make much difference - pane = new JEditorPane(); - pane.setBounds(panel.getBounds()); - pane.getAccessibleContext().getAccessibleText(); - pane.setFont(panel.getFont()); - CellRendererPane cell = new CellRendererPane(); - cell.add(pane); - } - pane.setText(getText()); - pane.selectAll(); - pane.validate(); - return pane.getAccessibleContext().getAccessibleText(); - } - - public String getText() { - StringBuilder sb = new StringBuilder(); - String[] s = wizard.getAllSteps(); - for (String item : s) - sb.append(wizard.getStepDescription(item)).append('\n'); - return sb.toString(); - } - - @Override - public AccessibleRole getAccessibleRole() { - return AccessibleRole.LIST; - } - - @Override - public AccessibleStateSet getAccessibleStateSet() { - AccessibleState[] states = new AccessibleState[]{ - AccessibleState.VISIBLE, - AccessibleState.OPAQUE, - AccessibleState.SHOWING, - AccessibleState.MULTI_LINE,}; - return new AccessibleStateSet(states); - } - - @Override - public int getAccessibleIndexInParent() { - return -1; - } - - @Override - public int getAccessibleChildrenCount() { - return 0; - } - - @Override - public Accessible getAccessibleChild(int i) { - throw new IndexOutOfBoundsException("" + i); - } - - @Override - public Locale getLocale() throws IllegalComponentStateException { - return Locale.getDefault(); - } - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/modules/MergeMap.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/modules/MergeMap.java deleted file mode 100644 index 0e6baa493..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/modules/MergeMap.java +++ /dev/null @@ -1,281 +0,0 @@ -/* The contents of this file are subject to the terms of the Common Development -and Distribution License (the License). You may not use this file except in -compliance with the License. - You can obtain a copy of the License at http://www.netbeans.org/cddl.html -or http://www.netbeans.org/cddl.txt. - When distributing Covered Code, include this CDDL Header Notice in each file -and include the License file at http://www.netbeans.org/cddl.txt. -If applicable, add the following below the CDDL Header, with the fields -enclosed by brackets [] replaced by your own identifying information: -"Portions Copyrighted [year] [name of copyright owner]" */ - /* - * MergeMap.java - * - * Created on February 22, 2005, 4:06 PM - */ -package org.jackhuang.hmcl.util.ui.wizard.modules; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Set; -import java.util.Stack; - -/** - * A map which proxies a collection of sub-maps each of which has a - * unique id. Submaps can be added or removed en banc. Values from - * removed maps are retained; if push ("someKnownId") happens, the - * values previously added to the map while that ID was active reappear. - *

    - * This allows us to implement backward/forward semantics for wizards, - * in which each pane (identified with a unique ID) can add its own - * settings to the settings map, but if the user presses the Back - * button, the settings from the formerly active pane can disappear - - * but if the user moves forward again, they are not lost. - *

    - * Calling remove("someKeyBelongingToAnEarlierId") will completely - * remove that value; calling put ("someKeyBelongingToAnEarlierId", "newValue") - * replaces the earler value permanently. - *

    - * This class is NOT AN API CLASS. There is no - * commitment that it will remain backward compatible or even exist in the - * future. The API of this library is in the packages - * org.netbeans.api.wizard - * and org.netbeans.spi.wizard. - * - * @author Tim Boudreau - */ -public class MergeMap implements Map { - - private final Stack order = new Stack<>(); - private final Map> id2map = new HashMap<>(); - - /** - * Creates a new instance of MergeMap - */ - public MergeMap(String currID) { - push(currID); - } - - private static final String BASE = "__BASE"; - - /** - * Creates a MergeMap with a set of key/value pairs that are - * always there (they came from a legacy wizard - used for bridging the - * old NetBeans wizards API and this one - some bridged wizards will - * have a first panel that gathered some settings using the old APIs - * framework, and we need to inject them here. - */ - public MergeMap(String currId, Map everpresent) { - order.push(BASE); - id2map.put(BASE, everpresent); - push(currId); - } - - /** - * Move to a different ID (meaning add a new named map to proxy which can be - * calved off if necessary). - */ - public Map push(String id) { - // assert !order.contains(id) : id + " already present"; - if (order.contains(id)) - throw new RuntimeException(id + " already present"); -// assert !order.contains(id) : id + " already present"; - if (!order.isEmpty() && id.equals(order.peek())) - return (Map) id2map.get(id); - Map result = (Map) id2map.get(id); - if (result == null) { - result = new HashMap<>(); - id2map.put(id, result); - } - order.push(id); - return result; - } - - /** - * Get the ID of the current sub-map being written into. - */ - public String currID() { - return (String) order.peek(); - } - - /** - * Remove the current sub-map. Removes all of its settings from the - * MergedMap, but if push() is called with the returned value, the - * values associated with the ID being removed will be restored. - */ - public String popAndCalve() { - if (order.isEmpty()) - throw new NoSuchElementException("Cannot back out past first " - + "entry"); - //Get the current map - String result = (String) order.peek(); - Map curr = (Map) id2map.get(result); - order.pop(); - - //Though unlikely, it is possible that a later step in a wizard - //overwrote a key/value pair from a previous step of the wizard. - //We do not want to revert that write, so iterate all the keys - //we're removing, and if any of them are in steps lower on the - //stack, change those lower steps values to whatever was written - //into the map we're calving off - for (Iterator i = orderIterator(); i.hasNext();) { - Map other = (Map) id2map.get(i.next()); - for (K key : curr.keySet()) - if (other.containsKey(key)) - other.put(key, curr.get(key)); - } - return result; - } - - @Override - public void clear() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean containsKey(Object obj) { - for (Iterator i = orderIterator(); i.hasNext();) { - Map curr = (Map) id2map.get(i.next()); - if (curr.containsKey(obj)) - return true; - } - return false; - } - - @Override - public boolean containsValue(Object obj) { - for (Iterator i = orderIterator(); i.hasNext();) { - Map curr = (Map) id2map.get(i.next()); - if (curr.containsValue(obj)) - return true; - } - return false; - } - - @Override - public java.util.Set> entrySet() { - HashSet> result = new HashSet<>(); - for (Iterator i = orderIterator(); i.hasNext();) { - Map curr = (Map) id2map.get(i.next()); - result.addAll(curr.entrySet()); - } - return result; - } - - @Override - public V get(Object obj) { - for (Iterator i = orderIterator(); i.hasNext();) { - String id = (String) i.next(); - Map curr = (Map) id2map.get(id); - V result = curr.get(obj); - if (result != null) - return result; - } - return null; - } - - @Override - public boolean isEmpty() { - return size() == 0; - } - - @Override - public Set keySet() { - HashSet result = new HashSet<>(); - for (Iterator i = orderIterator(); i.hasNext();) { - Map curr = (Map) id2map.get(i.next()); - result.addAll(curr.keySet()); - } - return result; - } - - @Override - public V put(K obj, V obj1) { - Map curr = (Map) id2map.get(order.peek()); - return curr.put(obj, obj1); - } - - @Override - public void putAll(Map map) { - Map curr = (Map) id2map.get(order.peek()); - curr.putAll(map); - } - - private V doRemove(Object obj) { - Map curr = (Map) id2map.get(order.peek()); - V result = curr.remove(obj); - if (result == null) - for (Iterator i = orderIterator(); i.hasNext();) { - curr = (Map) id2map.get(i.next()); - result = curr.remove(obj); - if (result != null) - break; - } - return result; - } - - @Override - public V remove(Object obj) { - //Ensure we remove any duplicates in upper arrays - V result = get(obj); - while (get(obj) != null) - doRemove(obj); - return result; - } - - @Override - public int size() { - //using keySet() prunes duplicates - return keySet().size(); - } - - @Override - public Collection values() { - HashSet result = new HashSet<>(); - Set keys = keySet(); - for (Iterator i = keys.iterator(); i.hasNext();) - result.add(get(i.next())); - return result; - } - - private Iterator orderIterator() { - return new ReverseIterator(order); - } - - private static final class ReverseIterator implements Iterator { - - private int pos; - private final List l; - - public ReverseIterator(Stack s) { - pos = s.size() - 1; - l = new ArrayList<>(s); - } - - @Override - public boolean hasNext() { - return pos != -1; - } - - @Override - public String next() { - if (pos < 0) - throw new NoSuchElementException(); - String result = l.get(pos); - pos--; - return result; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/AbstractWizard.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/AbstractWizard.java deleted file mode 100644 index 507be421a..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/AbstractWizard.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.util.ui.wizard.spi; - -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import org.jackhuang.hmcl.api.func.Consumer; - -/** - * - * @author huang - */ -public abstract class AbstractWizard implements WizardImplementation { - - protected final List listenerList = Collections.synchronizedList(new LinkedList<>()); - - protected void fireChanged(Consumer r) { - WizardObserver[] listeners = listenerList.toArray(new WizardObserver[listenerList.size()]); - - for (int i = listeners.length - 1; i >= 0; i--) { - WizardObserver l = (WizardObserver) listeners[i]; - r.accept(l); - } - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/BranchingWizard.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/BranchingWizard.java deleted file mode 100644 index 293e4c1d8..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/BranchingWizard.java +++ /dev/null @@ -1,317 +0,0 @@ -/* The contents of this file are subject to the terms of the Common Development -and Distribution License (the License). You may not use this file except in -compliance with the License. - You can obtain a copy of the License at http://www.netbeans.org/cddl.html -or http://www.netbeans.org/cddl.txt. - When distributing Covered Code, include this CDDL Header Notice in each file -and include the License file at http://www.netbeans.org/cddl.txt. -If applicable, add the following below the CDDL Header, with the fields -enclosed by brackets [] replaced by your own identifying information: -"Portions Copyrighted [year] [name of copyright owner]" */ - - /* - * BranchingWizard.java - * - * Created on March 4, 2005, 10:56 PM - */ -package org.jackhuang.hmcl.util.ui.wizard.spi; - -import javax.swing.*; -import java.util.Arrays; -import java.util.Map; -import java.util.Objects; - -/** - * A Wizard with indeterminate branches. The actual branch decision-making is - * done by the WizardBranchController passed to the constructor. - *

    - * Wizards with arbitrary numbers of branches can be handled by a - * WizardBranchController by returning wizards created by another - * WizardBranchController's createWizard() method. - *

    - * One important point: There should be no duplicate IDs between steps of this - * wizard. - * - * @author Tim Boudreau - */ -final class BranchingWizard extends AbstractWizard { - - private final WizardBranchController brancher; - final WizardImplementation initialSteps; - - private WizardImplementation subsequentSteps; - private WizardImplementation activeWizard; - private WL wl; - - private String currStep; - private Map wizardData; - - public BranchingWizard(WizardBranchController brancher) { - this.brancher = brancher; - initialSteps = new SimpleWizard(brancher.getBase(), true); - setCurrent(initialSteps); - } - - protected final WizardImplementation createSecondary(Map settings) { - Wizard wiz = brancher.getWizardForStep(currStep, settings); - return wiz == null ? null : wiz.impl; - } - - private void checkForSecondary() { - if (wizardData == null) - return; - - WizardImplementation newSecondary = createSecondary(wizardData); - - /* - * johnflournoy 7/20/07 - * check for secondary should be adding the secondary to the activeWizard - * not the initial wizard. Adding it to the initial wizard was breaking - * multiple branching - to accomplish this created a new method: - * setSecondary() - */ - if (activeWizard instanceof BranchingWizard) - ((BranchingWizard) activeWizard).setSecondary(newSecondary); - else - this.setSecondary(newSecondary); - } - - /** - * Set the secondary for this BranchingWizard. - * - * @param newSecondary is a WizardImplementation. - */ - private void setSecondary(WizardImplementation newSecondary) { - /* johnflournoy added additional condition: secondary != this */ - if ((((subsequentSteps == null) != (newSecondary == null)) - || (subsequentSteps != null && !subsequentSteps.equals(newSecondary))) - && !this.equals(newSecondary)) - - /* - * johnflournoy: only set the subsequent steps if it - * this wizard owns the current step. - */ - if (Arrays.asList(initialSteps.getAllSteps()).contains(currStep)) { - subsequentSteps = newSecondary; - fireStepsChanged(); - } - } - - @Override - public int getForwardNavigationMode() { - return activeWizard.getForwardNavigationMode(); - } - - private void setCurrent(WizardImplementation wizard) { - if (activeWizard == wizard) - return; - - Objects.requireNonNull(wizard, "Can't set current wizard to null"); - - if ((activeWizard != null) && (wl != null)) - activeWizard.removeWizardObserver(wl); - - activeWizard = wizard; - - if (wl == null) - wl = new WL(); - - activeWizard.addWizardObserver(wl); - } - - @Override - public final boolean isBusy() { - return activeWizard.isBusy(); - } - - @Override - public final Object finish(Map settings) throws WizardException { - try { - Object result = activeWizard.finish(settings); - initialSteps.removeWizardObserver(wl); - //Can be null, we allow bail-out with finish mid-wizard now - if (subsequentSteps != null) - subsequentSteps.removeWizardObserver(wl); - return result; - } catch (WizardException we) { - if (we.getStepToReturnTo() != null) { - initialSteps.addWizardObserver(wl); - //Can be null, we allow bail-out with finish mid-wizard now - if (subsequentSteps != null) - subsequentSteps.addWizardObserver(wl); - } - throw we; - } - } - - @Override - public final String[] getAllSteps() { - String[] result; - if (subsequentSteps == null) { - String[] bsteps = initialSteps.getAllSteps(); - result = new String[bsteps.length + 1]; - System.arraycopy(bsteps, 0, result, 0, bsteps.length); - result[result.length - 1] = UNDETERMINED_STEP; - } else { - String[] bsteps = initialSteps.getAllSteps(); - String[] csteps = subsequentSteps.getAllSteps(); - result = new String[bsteps.length + csteps.length]; - System.arraycopy(bsteps, 0, result, 0, bsteps.length); - System.arraycopy(csteps, 0, result, bsteps.length, csteps.length); - } - return result; - } - - @Override - public String getCurrentStep() { - return currStep; - } - - @Override - public final String getNextStep() { - String result; - if (currStep == null) - result = getAllSteps()[0]; - else { - String[] steps = getAllSteps(); - int idx = Arrays.asList(steps).indexOf(currStep); - if (idx == -1) - throw new IllegalStateException("Current step not in" - + " available steps: " + currStep + " not in " - + Arrays.asList(steps)); - else if (idx == steps.length - 1) - if (subsequentSteps == null) - result = UNDETERMINED_STEP; - else - result = subsequentSteps.getNextStep(); - else { - WizardImplementation w = ownerOf(currStep); - if (w == initialSteps && idx == initialSteps.getAllSteps().length - 1) { - checkForSecondary(); - if (subsequentSteps != null) - result = subsequentSteps.getAllSteps()[0]; - else - result = UNDETERMINED_STEP; - } else - result = w.getNextStep(); - } - } - return getProblem() == null ? result : UNDETERMINED_STEP.equals(result) ? result : null; - } - - @Override - public final String getPreviousStep() { - if (activeWizard == subsequentSteps && subsequentSteps.getAllSteps()[0].equals(currStep)) - return initialSteps.getAllSteps()[initialSteps.getAllSteps().length - 1]; - else - return activeWizard.getPreviousStep(); - } - - @Override - public final String getProblem() { - return activeWizard.getProblem(); - } - - @Override - public final String getStepDescription(String id) { - WizardImplementation w = ownerOf(id); - if (w == null) - return null; - return w.getStepDescription(id); - } - - @Override - public final String getLongDescription(String id) { - WizardImplementation w = ownerOf(id); - if (w == null) - return null; - return w.getLongDescription(id); - } - - private WizardImplementation ownerOf(String id) { - if (UNDETERMINED_STEP.equals(id)) { - checkForSecondary(); - return subsequentSteps; - } - if (Arrays.asList(initialSteps.getAllSteps()).contains(id)) - return initialSteps; - else { - /* - * johnflournoy - * need to check an existing subsequentsteps to see if - * we can find the owner of "id", otherwise we were losing - * a wizard if we had multiple branches and we backed up to an - * earlier wizard and then went down the same path again. - */ - if (subsequentSteps != null) { - if (!Arrays.asList(subsequentSteps.getAllSteps()).contains(id)) - checkForSecondary(); - } else - checkForSecondary(); - - return subsequentSteps; - } - } - - @Override - public final String getTitle() { - return activeWizard.getTitle(); - } - - @Override - public final JComponent navigatingTo(String id, Map settings) { - currStep = Objects.requireNonNull(id); - wizardData = settings; - - WizardImplementation impl = Objects.requireNonNull(ownerOf(id), "No owning WizardImplementation for id " + id); - setCurrent(impl); - - return activeWizard.navigatingTo(id, settings); - } - - @Override - public final void removeWizardObserver(WizardObserver observer) { - listenerList.remove(observer); - } - - @Override - public final void addWizardObserver(WizardObserver observer) { - listenerList.add(observer); - } - - private void fireStepsChanged() { - fireChanged(l -> l.stepsChanged(null)); - } - - private void fireNavigabilityChanged() { - checkForSecondary(); - fireChanged(l -> l.navigabilityChanged(null)); - } - - private void fireSelectionChanged() { - fireChanged(l -> l.selectionChanged(null)); - } - - @Override - public boolean cancel(Map settings) { - return activeWizard == null ? true : activeWizard.cancel(settings); - } - - private class WL implements WizardObserver { - - @Override - public void stepsChanged(Wizard wizard) { - fireStepsChanged(); - } - - @Override - public void navigabilityChanged(Wizard wizard) { - fireNavigabilityChanged(); - } - - @Override - public void selectionChanged(Wizard wizard) { - fireSelectionChanged(); - } - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/DeferredWizardResult.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/DeferredWizardResult.java deleted file mode 100644 index 82804f329..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/DeferredWizardResult.java +++ /dev/null @@ -1,127 +0,0 @@ -/* The contents of this file are subject to the terms of the Common Development -and Distribution License (the License). You may not use this file except in -compliance with the License. - You can obtain a copy of the License at http://www.netbeans.org/cddl.html -or http://www.netbeans.org/cddl.txt. - When distributing Covered Code, include this CDDL Header Notice in each file -and include the License file at http://www.netbeans.org/cddl.txt. -If applicable, add the following below the CDDL Header, with the fields -enclosed by brackets [] replaced by your own identifying information: -"Portions Copyrighted [year] [name of copyright owner]" */ - - /* - * DeferredWizardResult.java - * - * Created on September 24, 2006, 3:42 AM - * - * To change this template, choose Tools | Template Manager - * and open the template in the editor. - */ -package org.jackhuang.hmcl.util.ui.wizard.spi; - -import java.util.Map; - -/** - * Object which can be returned from - * WizardPage.WizardResultProducer.finish() - * or WizardPanelProvider.finish(). A DeferredWizardResult does - * not immediately calculate its result; it is used for cases where some - * time consuming work needs to be performed to compute the result (such as - * creating files on disk), and a progress bar should be shown until the work - * is completed. - * - * @see org.jackhuang.hmcl.util.ui.wizard.spi.ResultProgressHandle - * - * @author Tim Boudreau - */ -public abstract class DeferredWizardResult { - - private final boolean canAbort; - - /** - * Creates a new instance of DeferredWizardResult which cannot be - * aborted and shows a progress bar. - */ - public DeferredWizardResult() { - canAbort = false; - } - - /** - * Creates a new instance of DeferredWizardResult which may or may not - * be able to be aborted. - * - * @param canAbort determine if background computation can be aborted by - * calling the abort() method - */ - public DeferredWizardResult(boolean canAbort) { - this.canAbort = canAbort; - } - - /** - * Begin computing the result. This method is called on a background - * thread, not the AWT event thread, and computation can immediately begin. - * Use the progress handle to set progress as the work progresses. - * - * IMPORTANT: This method MUST call either progress.finished with the - * result, - * or progress.failed with an error message. If this method returns without - * calling either of those methods, it will be assumed to have failed. - * - * @param settings The settings gathered over the course of the wizard - * @param progress A handle which can be used to affect the progress bar. - */ - public abstract void start(Map settings, ResultProgressHandle progress); - - /** - * If true, the background thread can be aborted. If it is possible to - * abort, then the UI may allow the dialog to be closed while the result - * is being computed. - */ - public final boolean canAbort() { - return canAbort; - } - - /** - * Abort computation of the result. This method will usually be called on - * the event thread, after start() has been called, and before - * finished() has been called on the - * ResultProgressHandle - * that is passed to start(), for example, if the user clicks - * the close button on the dialog showing the wizard while the result is - * being computed. - *

    - * This method does nothing by default - it is left empty so - * that people who do not want to support aborting background work do not - * have to override it. It is up to the implementor - * to set a flag or otherwise notify the background thread to halt - * computation. A simple method for doing so is as follows: - *

    -     * volatile Thread thread;
    -     * public void start (Map settings, ResultProgressHandle handle) {
    -     * try {
    -     *  synchronized (this) {
    -     *     thread = Thread.currentThread();
    -     *  }
    -     *
    -     *  //do the background computation, update progress.  Every so often,
    -     *  //check Thread.interrupted() and exit if true
    -     * } finally {
    -     *    synchronized (this) {
    -     *       thread = null;
    -     *    }
    -     *  }
    -     * }
    -     *
    -     * public synchronized void abort() {
    -     *  if (thread != null) thread.interrupt();
    -     * }
    -     * 
    - * or you can use a volatile boolean flag that you set in - * abort() and periodically check in the body of - * start(). - * - */ - public void abort() { - //do nothing - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/GenericListener.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/GenericListener.java deleted file mode 100644 index 04569bb49..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/GenericListener.java +++ /dev/null @@ -1,380 +0,0 @@ -/* The contents of this file are subject to the terms of the Common Development -and Distribution License (the License). You may not use this file except in -compliance with the License. - You can obtain a copy of the License at http://www.netbeans.org/cddl.html -or http://www.netbeans.org/cddl.txt. - When distributing Covered Code, include this CDDL Header Notice in each file -and include the License file at http://www.netbeans.org/cddl.txt. -If applicable, add the following below the CDDL Header, with the fields -enclosed by brackets [] replaced by your own identifying information: -"Portions Copyrighted [year] [name of copyright owner]" */ - - /* - * GenericListener.java - * - * Created on October 5, 2004, 12:36 AM - */ -package org.jackhuang.hmcl.util.ui.wizard.spi; - -import java.awt.Component; -import java.awt.Container; -import java.awt.Dialog; -import java.awt.Frame; -import java.awt.Window; -import java.awt.event.*; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.util.Arrays; -import java.util.EventObject; -import java.util.HashSet; -import java.util.Set; -import javax.swing.*; -import javax.swing.table.*; -import javax.swing.tree.*; -import javax.swing.ListSelectionModel; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; -import javax.swing.event.TableModelEvent; -import javax.swing.event.TableModelListener; -import javax.swing.event.TreeSelectionEvent; -import javax.swing.event.TreeSelectionListener; -import javax.swing.text.Document; -import javax.swing.text.JTextComponent; -import javax.swing.tree.TreeSelectionModel; - -/** - * A listener that can listen to just about any standard swing component - * that accepts user input and notify the panel that it needs to - * validate its contents. - * - * If you use subclasses of the swing components, you will also need to subclass - * this listener and override at least the methods isProbablyContainer, attachTo - * and detachFrom. - * - * @author Tim Boudreau - */ -final class GenericListener - implements ActionListener, PropertyChangeListener, ItemListener, - ContainerListener, DocumentListener, ChangeListener, - ListSelectionListener, TreeSelectionListener, TableModelListener { - - private final WizardPage wizardPage; - - private boolean ignoreEvents; - - /** - * Set of components that we're listening to models of, so we can look - * up the component from the model as needed - */ - private final Set listenedTo = new HashSet<>(); - - private final WizardPage.CustomComponentListener extListener; - private final WizardPage.CustomComponentNotifier extNotifier; - - public GenericListener(WizardPage wizardPage, WizardPage.CustomComponentListener l, - WizardPage.CustomComponentNotifier n) { - this.extListener = l; - this.extNotifier = n; - if ((extListener == null) != (extNotifier == null)) - throw new RuntimeException(); - // assert wizardPage != null : "WizardPage may not be null"; - if (wizardPage == null) - throw new IllegalArgumentException("WizardPage may not be null"); - this.wizardPage = wizardPage; - wizardPage.addContainerListener(this); - } - - public GenericListener(WizardPage page) { - this(page, null, null); - } - - /** - * Return true if the given component is likely to be a container such the - * each - * component within the container should be be considered as a user input. - * - * @param c - * - * @return true if the component children should have this listener added. - */ - protected boolean isProbablyAContainer(Component c) { - boolean result = extListener != null ? extListener.isContainer(c) : false; - if (!result) { - boolean isSwing = isSwingClass(c); - if (isSwing) - result = c instanceof JPanel || c instanceof JSplitPane || c instanceof JToolBar || c instanceof JViewport || c instanceof JScrollPane - || c instanceof JFrame || c instanceof JRootPane || c instanceof Window || c instanceof Frame || c instanceof Dialog - || c instanceof JTabbedPane || c instanceof JInternalFrame - || c instanceof JDesktopPane || c instanceof JLayeredPane - || c instanceof Box; - else - result = c instanceof Container; - } - return result; - } - - /** - * Return true if the given component is likely to be a swing primitive or a - * subclass. - * The default implmentation here just checks for the package of the - * component to be "javax.swing" - * If you use subclasses of swing components, you will need to override this - * method - * to get proper behavior. - * - * @param c - * - * @return true if the component should be examined more closely (see - * isProbablyAContainer) - */ - protected boolean isSwingClass(Component c) { - String packageName = c.getClass().getPackage().getName(); - boolean swing = packageName.equals("javax.swing"); - return swing; - } - - protected void attachTo(Component jc) { - if (extListener != null && extListener.accept(jc)) { - extListener.startListeningTo(jc, extNotifier); - listenedTo.add(jc); - if (wizardPage.getMapKeyFor(jc) != null) - wizardPage.maybeUpdateMap(jc); - return; - } - if (isProbablyAContainer(jc)) - attachToHierarchyOf((Container) jc); - else if (jc instanceof JList) { - listenedTo.add(jc); - ((JList) jc).addListSelectionListener(this); - } else if (jc instanceof JComboBox) - ((JComboBox) jc).addActionListener(this); - else if (jc instanceof JTree) { - listenedTo.add(jc); - ((JTree) jc).getSelectionModel().addTreeSelectionListener(this); - } else if (jc instanceof JToggleButton) - ((AbstractButton) jc).addItemListener(this); - else if (jc instanceof JFormattedTextField) //JFormattedTextField must be tested before JTextCompoent - jc.addPropertyChangeListener("value", this); - else if (jc instanceof JTextComponent) { - listenedTo.add(jc); - ((JTextComponent) jc).getDocument().addDocumentListener(this); - } else if (jc instanceof JColorChooser) { - listenedTo.add(jc); - ((JColorChooser) jc).getSelectionModel().addChangeListener(this); - } else if (jc instanceof JSpinner) - ((JSpinner) jc).addChangeListener(this); - else if (jc instanceof JSlider) - ((JSlider) jc).addChangeListener(this); - else if (jc instanceof JTable) { - listenedTo.add(jc); - ((JTable) jc).getSelectionModel().addListSelectionListener(this); - } - - if (accept(jc) && !(jc instanceof JPanel)) { - jc.addPropertyChangeListener("name", this); - if (wizardPage.getMapKeyFor(jc) != null) - wizardPage.maybeUpdateMap(jc); - } - } - - protected void detachFrom(Component jc) { - listenedTo.remove(jc); - if (extListener != null && extListener.accept(jc)) - extListener.stopListeningTo(jc); - if (isProbablyAContainer(jc)) - detachFromHierarchyOf((Container) jc); - else if (jc instanceof JList) - ((JList) jc).removeListSelectionListener(this); - else if (jc instanceof JComboBox) - ((JComboBox) jc).removeActionListener(this); - else if (jc instanceof JTree) - ((JTree) jc).getSelectionModel().removeTreeSelectionListener(this); - else if (jc instanceof JToggleButton) - ((AbstractButton) jc).removeActionListener(this); - else if (jc instanceof JTextComponent) { - } else if (jc instanceof JFormattedTextField) { //JFormattedTextField must be tested before JTextCompoent - jc.removePropertyChangeListener("value", this); - ((JTextComponent) jc).getDocument().removeDocumentListener(this); - } else if (jc instanceof JColorChooser) - ((JColorChooser) jc).getSelectionModel().removeChangeListener(this); - else if (jc instanceof JSpinner) - ((JSpinner) jc).removeChangeListener(this); - else if (jc instanceof JSlider) - ((JSlider) jc).removeChangeListener(this); - else if (jc instanceof JTable) - ((JTable) jc).getSelectionModel().removeListSelectionListener(this); - - if (accept(jc) && !(jc instanceof JPanel)) { - jc.removePropertyChangeListener("name", this); - Object key = wizardPage.getMapKeyFor(jc); - - if (key != null) - wizardPage.removeFromMap(key); - } - } - - private void detachFromHierarchyOf(Container container) { - container.removeContainerListener(this); - Component[] components = container.getComponents(); - for (Component component : components) - detachFrom(component); // Will callback recursively any nested JPanels - } - - void attachToHierarchyOf(Container container) { - if (!Arrays.asList(container.getContainerListeners()).contains(this)) - container.addContainerListener(this); - Component[] components = container.getComponents(); - for (Component component : components) - attachTo(component); // Will recursively add any child components in - } - - protected boolean accept(Component jc) { - if (extListener != null && extListener.accept(jc)) - return true; - if (!(jc instanceof JComponent)) - return false; - if (jc instanceof TableCellEditor || jc instanceof TreeCellEditor - || SwingUtilities.getAncestorOfClass(JTable.class, jc) != null - || SwingUtilities.getAncestorOfClass(JTree.class, jc) != null - || SwingUtilities.getAncestorOfClass(JList.class, jc) != null) - //Don't listen to cell editors, we can end up listening to them - //multiple times, and the tree/table model will give us the event - //we need - return false; - return isProbablyAContainer(jc) - || jc instanceof JList - || jc instanceof JComboBox - || jc instanceof JTree - || jc instanceof JToggleButton - || //covers toggle, radio, checkbox - jc instanceof JTextComponent - || jc instanceof JColorChooser - || jc instanceof JSpinner - || jc instanceof JSlider; - } - - void setIgnoreEvents(boolean val) { - ignoreEvents = val; - } - - private void fire(Object e) { - if (!ignoreEvents) { - setIgnoreEvents(true); - try { - //XXX this could be prettier... - if (e instanceof EventObject && ((EventObject) e).getSource() instanceof Component) - wizardPage.userInputReceived((Component) ((EventObject) e).getSource(), e); - else if (e instanceof TreeSelectionEvent) { - TreeSelectionModel mdl = (TreeSelectionModel) ((TreeSelectionEvent) e).getSource(); - for (Object o : listenedTo) - if (o instanceof JTree && ((JTree) o).getSelectionModel() == mdl) { - wizardPage.userInputReceived((Component) o, e); - break; - } - } else if (e instanceof DocumentEvent) { - Document document = ((DocumentEvent) e).getDocument(); - for (Component o : listenedTo) - if (o instanceof JTextComponent && ((JTextComponent) o).getDocument() == document) { - wizardPage.userInputReceived((Component) o, e); - break; - } - } else if (e instanceof ListSelectionEvent) { - ListSelectionModel model = (ListSelectionModel) ((ListSelectionEvent) e).getSource(); - for (Object o : listenedTo) - if (o instanceof JList && ((JList) o).getSelectionModel() == model) { - wizardPage.userInputReceived((Component) o, e); - break; - } else if (o instanceof JTable && ((JTable) o).getSelectionModel() == model) { - wizardPage.userInputReceived((Component) o, e); - break; - } - } else - wizardPage.userInputReceived(null, e); - } finally { - setIgnoreEvents(false); - } - } - } - - @Override - public void actionPerformed(ActionEvent e) { - fire(e); - } - - @Override - public void propertyChange(PropertyChangeEvent e) { - if (e.getSource() instanceof JComponent && "name".equals(e.getPropertyName())) { - // Note - most components do NOT fire a property change on - // setName(), but it is possible for this to be done intentionally - if (e.getOldValue() instanceof String) - wizardPage.removeFromMap(e.getOldValue()); - - } else if (e.getSource() instanceof JFormattedTextField && "value".equals(e.getPropertyName())) { - fire(e); - wizardPage.maybeUpdateMap((JComponent) e.getSource()); - } - } - - @Override - public void itemStateChanged(ItemEvent e) { - fire(e); - } - - @Override - public void componentAdded(ContainerEvent e) { -// if (extListener != null && extListener.accept(e.getChild())) { -// extListener.startListeningTo(e.getChild(), extNotifier); -// listenedTo.add (e.getChild()); -// } else if (accept(e.getChild())) { - if (accept(e.getChild())) - attachTo(e.getChild()); - } - - @Override - public void componentRemoved(ContainerEvent e) { - if (extListener != null && extListener.accept(e.getChild())) { - extListener.stopListeningTo(e.getChild()); - listenedTo.remove(e.getChild()); - } else if (accept(e.getChild())) - detachFrom(e.getChild()); - } - - @Override - public void insertUpdate(DocumentEvent e) { - fire(e); - } - - @Override - public void changedUpdate(DocumentEvent e) { - fire(e); - } - - @Override - public void removeUpdate(DocumentEvent e) { - fire(e); - } - - @Override - public void stateChanged(ChangeEvent e) { - fire(e); - } - - @Override - public void valueChanged(ListSelectionEvent e) { - fire(e); - } - - @Override - public void valueChanged(TreeSelectionEvent e) { - fire(e); - } - - @Override - public void tableChanged(TableModelEvent e) { - fire(e); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/ResultProgressHandle.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/ResultProgressHandle.java deleted file mode 100644 index 4f1a43600..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/ResultProgressHandle.java +++ /dev/null @@ -1,89 +0,0 @@ -package org.jackhuang.hmcl.util.ui.wizard.spi; - -import java.awt.Container; - -/** - * A controller for the progress bar shown in the user interface. Used in - * conjunction with DeferredWizardResult for cases where at - * the conclusion of the wizard, the work to create the final wizard result - * will take a while and needs to happen on a background thread. - * @author Tim Boudreau - */ -public interface ResultProgressHandle { - - /** - * Set the current position and total number of steps. Note it is - * inadvisable to be holding any locks when calling this method, as it - * may immediately update the GUI using - * EventQueue.invokeAndWait(). - * - * @param currentStep the current step in the progress of computing the - * result. - * @param totalSteps the total number of steps. Must be greater than - * or equal to currentStep. - */ - public abstract void setProgress (int currentStep, int totalSteps); - - /** - * Set the current position and total number of steps, and description - * of what the computation is doing. Note it is - * inadvisable to be holding any locks when calling this method, as it - * may immediately update the GUI using - * EventQueue.invokeAndWait(). - * @param description Text to describe what is being done, which can - * be displayed in the UI. - * @param currentStep the current step in the progress of computing the - * result. - * @param totalSteps the total number of steps. Must be greater than - * or equal to currentStep. - */ - public abstract void setProgress (String description, int currentStep, int totalSteps); - - /** - * Set the status as "busy" - a rotating icon will be displayed instead - * of a percent complete progress bar. - * - * Note it is inadvisable to be holding any locks when calling this method, as it - * may immediately update the GUI using - * EventQueue.invokeAndWait(). - * @param description Text to describe what is being done, which can - * be displayed in the UI. - */ - public abstract void setBusy (String description); - - /** - * Call this method when the computation is complete, and pass in the - * final result of the computation. The method doing the computation - * (DeferredWizardResult.start() or something it - * called) should exit immediately after calling this method. If the - * failed() method is called after this method has been - * called, a runtime exception may be thrown. - * @param result the Object which was computed, if any. - */ - public abstract void finished(Object result); - /** - * Call this method if computation fails. The message may be some text - * describing what went wrong, or null if no description. - * @param message The text to display to the user. The method - * doing the computation (DeferredWizardResult.start() or something it - * called). If the finished() method is called after this - * method has been called, a runtime exception may be thrown. - * should exit immediately after calling this method. - * It is A description of what went wrong, or null. - * @param canNavigateBack whether or not the Prev button should be - * enabled. - */ - public abstract void failed (String message, boolean canNavigateBack); - - /** - * Add the component to show for the progress display to the instructions panel. - */ - public abstract void addProgressComponents (Container panel); - - /** - * Returns true if the computation is still running, i.e., if neither finished or failed have been called. - * - * @return true if there is no result yet. - */ - public boolean isRunning(); -} \ No newline at end of file diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/SimpleWizard.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/SimpleWizard.java deleted file mode 100644 index 7c423971c..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/SimpleWizard.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * The contents of this file are subject to the terms of the Common Development - * and Distribution License (the License). You may not use this file except in - * compliance with the License. - * You can obtain a copy of the License at http://www.netbeans.org/cddl.html - * or http://www.netbeans.org/cddl.txt. - * When distributing Covered Code, include this CDDL Header Notice in each file - * and include the License file at http://www.netbeans.org/cddl.txt. - * If applicable, add the following below the CDDL Header, with the fields - * enclosed by brackets [] replaced by your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - */ - /* - * SimpleWizard.java - * - * Created on February 22, 2005, 2:33 PM - */ -package org.jackhuang.hmcl.util.ui.wizard.spi; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import javax.swing.JComponent; - -/** - * A simple implementation of Wizard for use in wizards which have a - * straightforward set of steps with no branching. To use, implement the - * simplified interface SimpleWizard.Info and pass that to the constructor. - * - * @see SimpleWizardInfo - * @author Tim Boudreau - */ -final class SimpleWizard extends AbstractWizard { - - private final Map ids2panels = new HashMap<>(); - - final SimpleWizardInfo info; - - private String currID = null; - private boolean subwizard; - - public SimpleWizard(WizardPanelProvider prov) { - this(new SimpleWizardInfo(prov), false); - } - - /** - * Creates a new instance of SimpleWizard - */ - public SimpleWizard(SimpleWizardInfo info) { - this.info = info; - info.setWizard(this); - } - - /** - * Creates a new instance of SimpleWizard - */ - public SimpleWizard(SimpleWizardInfo info, boolean subwizard) { - this.info = info; - this.subwizard = subwizard; - info.setWizard(this); - } - - @Override - public void addWizardObserver(WizardObserver observer) { - listenerList.add(observer); - } - - @Override - public void removeWizardObserver(WizardObserver observer) { - listenerList.remove(observer); - } - - @Override - public int getForwardNavigationMode() { - int result = info.getFwdNavMode(); - if (!subwizard && ((result & WizardController.MODE_CAN_CONTINUE) != 0) && isLastStep()) - result = WizardController.MODE_CAN_FINISH; - return result; - } - - boolean isLastStep() { - String[] steps = info.getSteps(); - return currID != null && steps.length > 0 && currID.equals(steps[steps.length - 1]); - } - - @Override - public String[] getAllSteps() { - String[] allSteps = info.getSteps(); - String[] result = new String[allSteps.length]; - //Defensive copy - System.arraycopy(allSteps, 0, result, 0, allSteps.length); - return result; - } - - @Override - public String getStepDescription(String id) { - int idx = Arrays.asList(info.getSteps()).indexOf(id); - if (idx == -1) - throw new IllegalArgumentException("Undefined id: " + id); - return info.getDescriptions()[idx]; - } - - @Override - public String getLongDescription(String id) { - return info.getLongDescription(id); - } - - @Override - public JComponent navigatingTo(String id, Map settings) { -// assert SwingUtilities.isEventDispatchThread(); - - // if info.getSteps() does not yet contain the ID, then create it - JComponent result = (JComponent) ids2panels.get(id); - currID = id; - if (result == null) { - result = info.createPanel(id, settings); - ids2panels.put(id, result); - } else { - info.update(); - info.recycleExistingPanel(id, settings, result); - } - fireSelectionChanged(); - return result; - } - - @Override - public String getCurrentStep() { - return currID; - } - - @Override - public String getNextStep() { - if (!info.isValid()) - return null; - if ((info.getFwdNavMode() & WizardController.MODE_CAN_CONTINUE) == 0) - return null; - - int idx = currentStepIndex(); - if (idx < info.getSteps().length - 1) - return info.getSteps()[idx + 1]; - else - return null; - } - - @Override - public String getPreviousStep() { - int idx = currentStepIndex(); - if (idx < info.getSteps().length && idx > 0) - return info.getSteps()[idx - 1]; - else - return null; - } - - int currentStepIndex() { - int idx = 0; - if (currID != null) - idx = Arrays.asList(info.getSteps()).indexOf(currID); - return idx; - } - - void fireNavigability() { - fireChanged(l -> l.navigabilityChanged(null)); - } - - private void fireSelectionChanged() { - fireChanged(l -> l.selectionChanged(null)); - } - - @Override - public Object finish(Map settings) throws WizardException { - return info.finish(settings); - } - - @Override - public boolean cancel(Map settings) { - return info.cancel(settings); - } - - @Override - public String getTitle() { - return info.getTitle(); - } - - @Override - public String getProblem() { - return info.getProblem(); - } - - @Override - public boolean isBusy() { - return info.isBusy(); - } - - @Override - public int hashCode() { - return info.hashCode() ^ 17; - } - - @Override - public boolean equals(Object o) { - if (o instanceof SimpleWizard) - return ((SimpleWizard) o).info.equals(info); - else - return false; - } - - @Override - public String toString() { - return "SimpleWizard for " + info; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/SimpleWizardInfo.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/SimpleWizardInfo.java deleted file mode 100644 index 700752d86..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/SimpleWizardInfo.java +++ /dev/null @@ -1,315 +0,0 @@ -/* - * The contents of this file are subject to the terms of the Common Development - * and Distribution License (the License). You may not use this file except in - * compliance with the License. - * You can obtain a copy of the License at http://www.netbeans.org/cddl.html - * or http://www.netbeans.org/cddl.txt. - * When distributing Covered Code, include this CDDL Header Notice in each file - * and include the License file at http://www.netbeans.org/cddl.txt. - * If applicable, add the following below the CDDL Header, with the fields - * enclosed by brackets [] replaced by your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - */ - - /* - * SimpleWizardInfo.java - * - * Created on March 4, 2005, 9:46 PM - */ -package org.jackhuang.hmcl.util.ui.wizard.spi; - -import java.awt.Color; -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; -import java.lang.ref.WeakReference; -import java.util.Arrays; -import java.util.Map; -import java.util.Objects; -import javax.swing.BorderFactory; -import javax.swing.JComponent; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; -import org.jackhuang.hmcl.util.ArrayUtils; -import org.jackhuang.hmcl.util.code.Charsets; -import org.jackhuang.hmcl.util.sys.IOUtils; - -/** - * Provides information about a simple wizard. Wraps a - * WizardPanelProvider and provides a connection to the instance of - * SimpleWizard created for it, acting as the WizardController for - * calls to WizardPanelProvider.createPanel(). - */ -public final class SimpleWizardInfo implements WizardControllerImplementation { - - private WeakReference wizard = null; - private final String[] descriptions; - private final String[] steps; - final int[] navModeByPanel; - private String problem = null; - private final String title; - private final WizardPanelProvider provider; - private boolean busy = false; - - SimpleWizardInfo(WizardPanelProvider provider) { - this(provider.title, provider.steps, provider.descriptions, provider); - } - - /** - * Create an instance of Info, which will provide panels for a simple, - * non-branching wizard, passing a localized title, a list of steps - * and descriptions. - */ - protected SimpleWizardInfo(String title, String[] steps, String[] descriptions, WizardPanelProvider provider) { - this.steps = Objects.requireNonNull(steps, "Null steps"); - this.descriptions = Objects.requireNonNull(descriptions, "Null descriptions"); - if (ArrayUtils.hasDuplicateElements(steps)) - throw new IllegalArgumentException("Duplicate ID: " + Arrays.asList(steps)); - if (descriptions.length != steps.length) - if (steps.length != descriptions.length + 1 && !WizardImplementation.UNDETERMINED_STEP.equals(steps[steps.length - 1])) - throw new IllegalArgumentException("Steps and descriptions " - + "array lengths not equal: " + Arrays.asList(steps) + ":" - + Arrays.asList(descriptions)); - navModeByPanel = new int[steps.length]; - Arrays.fill(navModeByPanel, -1); - this.title = title; - this.provider = provider; - } - - final void setWizard(SimpleWizard wizard) { - this.wizard = new WeakReference<>(wizard); - } - - final SimpleWizard getWizard() { - return wizard != null ? (SimpleWizard) wizard.get() : null; - } - - //pkg private for unit tests - final WizardController controller = new WizardController(this); - - /** - * Create a panel that represents a named step in the wizard. - * This method will be called exactly once in the life of - * a wizard. The panel should retain the passed settings Map, and - * add/remove values from it as the user enters information, calling - * setProblem() and setCanFinish() as - * appropriate in response to user input. - * - * @param id The name of the step, as supplied in the constructor - * @param settings A Map containing settings from earlier steps in - * the wizard - * - * @return A JComponent - */ - protected JComponent createPanel(String id, Map settings) { - try { - JComponent result = provider.createPanel(controller, id, settings); - if (result instanceof WizardPage) { - ((WizardPage) result).setController(controller); - ((WizardPage) result).setWizardDataMap(settings); - } - return result; - } catch (RuntimeException re) { - JTextArea jta = new JTextArea(); - jta.setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, Color.RED)); - ByteArrayOutputStream buf = new ByteArrayOutputStream(); - PrintStream str = IOUtils.createPrintStream(buf, Charsets.UTF_8); - re.printStackTrace(str); - jta.setText(new String(buf.toByteArray(), Charsets.UTF_8)); - setProblem(re.getLocalizedMessage()); - return new JScrollPane(jta); - } - } - - /** - * Instantiate whatever object (if any) the wizard creates from its - * gathered data. - */ - protected Object finish(Map settings) throws WizardException { - return provider.finish(settings); - } - - public String getLongDescription(String id) { - return provider.getLongDescription(id); - } - - /** - * The method provides a chance to call setProblem() or setCanFinish() when - * the user re-navigates to a panel they've already seen - in the case - * that the user pressed the Previous button and then the Next button. - *

    - * The default implementation does nothing, which is sufficient for - * most implementations. If whether this panel is valid or not could - * have changed because of changed data from a previous panel, - * you may want to override this method to ensure validity and currNavMode - * are set correctly. - *

    - * This method will not be called when a panel is first instantiated - * - - * createPanel() is expected to set validity and currNavMode - * appropriately. - *

    - * The settings Map passed to this method will always be the same - * Settings map instance that was passed to createPanel() - * when the panel was created. - */ - protected void recycleExistingPanel(String id, Map settings, JComponent panel) { - provider.recycle(id, controller, settings, panel); - } - - private int index() { - SimpleWizard a = getWizard(); - return a == null ? 0 : a.currentStepIndex(); - } - - @Override - public final void setBusy(boolean value) { - if (value != busy) { - busy = value; - fire(); - } - } - - /** - * Set whether or not the contents of this panel are valid. When - * user-entered information in a panel changes, call this method as - * appropriate. - */ - @Override - public final void setProblem(String value) { - this.problem = value; - int idx = index(); - provider.setKnownProblem(problem, idx); - fire(); - } - - private int currNavMode = WizardController.MODE_CAN_CONTINUE; - - /** - * Set whether or not the Finish button should be enabled. Neither - * the Finish nor Next buttons will be enabled if setProblem has - * been called with non-null. - *

    - * Legal values are: WizardController.MODE_CAN_CONTINUE, - * WizardController.MODE_CAN_FINISH or - * WizardController.MODE_CAN_CONTINUE_OR_FINISH. - *

    - * This method is used to set what means of forward navigation should - * be available if the current panel is in a valid state (problem is - * null). It is not a way to disable both the next button - * and the finish button, only a way to choose either or both. - * - * @param value The forward navigation mode - * - * @see setProblem - */ - @Override - public final void setForwardNavigationMode(int value) { - switch (value) { - case WizardController.MODE_CAN_CONTINUE: - case WizardController.MODE_CAN_FINISH: - case WizardController.MODE_CAN_CONTINUE_OR_FINISH: - break; - default: - throw new IllegalArgumentException(Integer.toString(value)); - } - if (currNavMode != value) { - currNavMode = value; - fire(); - } - navModeByPanel[index()] = value; - } - - public final int getFwdNavMode() { - return currNavMode; - } - - final String getTitle() { - return title; - } - - final void update() { - int idx = index(); - boolean change = navModeByPanel[idx] != -1 && currNavMode != navModeByPanel[idx]; - setProblem(provider.getKnownProblem(idx)); - currNavMode = navModeByPanel[idx] == -1 ? WizardController.MODE_CAN_CONTINUE : navModeByPanel[idx]; - if (change) - fire(); - } - - final void fire() { - WizardImplementation wiz = getWizard(); - if (wiz != null) - getWizard().fireNavigability(); - } - - final boolean isValid() { - return getProblem() == null; - } - - final boolean canFinish() { - return isValid() && (currNavMode != -1 && (currNavMode - & WizardController.MODE_CAN_FINISH) != 0); - } - - final boolean canContinue() { - return isValid() && (currNavMode == -1 || (currNavMode - & WizardController.MODE_CAN_CONTINUE) != 0); - } - - String[] getDescriptions() { - return descriptions; - } - - String[] getSteps() { - return steps; - } - - // lookup the step by name - boolean containsStep(String name) { - for (String step : steps) - if (name.equals(step)) - return true; - return false; - } - - final String getProblem() { - return problem; - } - - boolean isBusy() { - return busy; - } - - @Override - public boolean equals(Object o) { - if (o != null && o.getClass() == getClass()) { - SimpleWizardInfo info = (SimpleWizardInfo) o; - - // assert info.descriptions != null : "Info.descriptions == null"; - // assert info.steps != null : "Info.steps == null"; - if (info.descriptions == null || info.steps == null) - throw new RuntimeException("Invalid info object"); - - return Arrays.equals(info.descriptions, descriptions) - && Arrays.equals(info.steps, steps) - && (info.title == null ? title == null : info.title.equals(title)); - } else - return false; - } - - @Override - public int hashCode() { - int result = 0; - for (int i = 0; i < steps.length; i++) - result += (steps[i].hashCode() * (i + 1)) ^ 31; - return result + (title == null ? 0 : title.hashCode()); - } - - boolean cancel(Map settings) { - return provider.cancel(settings); - } - - public WizardPanelProvider getProvider() { - return provider; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/Summary.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/Summary.java deleted file mode 100644 index af4571af1..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/Summary.java +++ /dev/null @@ -1,137 +0,0 @@ -/* The contents of this file are subject to the terms of the Common Development -and Distribution License (the License). You may not use this file except in -compliance with the License. - You can obtain a copy of the License at http://www.netbeans.org/cddl.html -or http://www.netbeans.org/cddl.txt. - When distributing Covered Code, include this CDDL Header Notice in each file -and include the License file at http://www.netbeans.org/cddl.txt. -If applicable, add the following below the CDDL Header, with the fields -enclosed by brackets [] replaced by your own identifying information: -"Portions Copyrighted [year] [name of copyright owner]" */ - /* - * Summary.java - * - * Created on September 24, 2006, 4:05 AM - * - * To change this template, choose Tools | Template Manager - * and open the template in the editor. - */ -package org.jackhuang.hmcl.util.ui.wizard.spi; - -import java.awt.Component; -import java.awt.Font; -import java.util.Objects; -import javax.swing.JList; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; -import javax.swing.UIManager; -import org.jackhuang.hmcl.util.ArrayUtils; -import org.jackhuang.hmcl.util.StrUtils; - -/** - * Object which may be returned from - * WizardPage.WizardResultProducer.finish() - * or WizardPanelProvider.finish(), or passed to - * DeferredWizardResult.ResultProgressHandle.finish(). If an - * instance of Summary is used, then the UI should, rather - * than disappearing, show the component provided by the Summary - * object. Convenience constructors are provided for plain text and list style - * views. - * - * @author Tim Boudreau - */ -public class Summary { - - private final Component comp; - private Object result; - - /** - * Create a Summary object which will display the - * passed String in a text component of some sort. - * - * @param text The text to display - must be non-null, greater than zero - * length and not completely whitespace - * @param result The result that should be returned when the Wizard is - * closed - * - * @return the requested Summary object - */ - public Summary(String text, Object result) { - //XXX this is creating components off the AWT thread - needs to change - //to use invokeAndWait where appropriate - if (StrUtils.isBlank(text)) - throw new IllegalArgumentException("Text is empty or all whitespace"); - this.result = result; - JTextArea jta = new JTextArea(); - jta.setText(text); - jta.setWrapStyleWord(true); - jta.setLineWrap(true); - jta.getCaret().setBlinkRate(0); - jta.setEditable(false); - jta.getCaret().setVisible(true); - Font f = UIManager.getFont("Label.font"); - if (f != null) //may be on old GTK L&F, etc. - jta.setFont(f); - comp = new JScrollPane(jta); - } - - /** - * Create a Summary object that will display the passed - * Strings in a JList or similar. - * - * @param items A non-null list of one or more Strings to be displayed - * @param result The result that should be returned when the Wizard is - * closed - * - * @return the requested Summary object - */ - public Summary(String[] items, Object result) { - if (ArrayUtils.isEmpty(items)) - throw new IllegalArgumentException("Items array empty"); - this.result = result; - JList list = new JList<>(items); - comp = new JScrollPane(list); - } - - /** - * Create a Summary object that will display the passed - * component. - * - * @param comp A custom component to show on the summary page after the - * Wizard has been completed - * @param result The result that should be returned when the - * Wizard is - * closed - * - * @return the requested Summary object - */ - public Summary(Component comp, Object result) { - this.result = result; - this.comp = Objects.requireNonNull(comp, "Null component"); - } - - /** - * Get the component that will display the summary information. - * - * @return an appropriate component, the type of which may differ depending - * on the factory method used to create this component - */ - public Component getSummaryComponent() { - return comp; - } - - /** - * Get the object that represents the actual result of whatever the - * Wizard - * that created this Summary object computes. Note this method - * may not - * return another instance of Summary or an instance of - * DeferredWizardResult. - * - * @return the object passed to the factory method that created this - * Summary object, or null. - */ - public Object getResult() { - return result; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/Util.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/Util.java deleted file mode 100644 index b46b50a63..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/Util.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package org.jackhuang.hmcl.util.ui.wizard.spi; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; - -/** - * - * @author Tim Boudreau - */ -final class Util { - - private Util() { - } - - /** - * Get an array of step ids from an array of WizardPages - */ - static String[] getSteps(WizardPage[] pages) { - String[] result = new String[pages.length]; - - Set uniqueNames = new HashSet<>(pages.length); - for (int i = 0; i < pages.length; i++) { - result[i] = pages[i].id(); - if (result[i] == null || uniqueNames.contains(result[i])) { - result[i] = uniquify(getIDFromStaticMethod(pages[i].getClass()), - uniqueNames); - pages[i].id = result[i]; - } - uniqueNames.add(result[i]); - } - return result; - } - - static String uniquify(String s, Set used) { - String test = s; - if (test != null) { - int ix = 0; - while (used.contains(test)) - test = s + "_" + ix++; - } - return test; - } - - /** - * Get an array of descriptions from an array of WizardPages - */ - static String[] getDescriptions(WizardPage[] pages) { - String[] result = new String[pages.length]; - - for (int i = 0; i < pages.length; i++) { - result[i] = pages[i].description(); - if (result[i] == null) - result[i] = getDescriptionFromStaticMethod(pages[i].getClass()); - } - - return result; - } - - static String getIDFromStaticMethod(Class clazz) { - // System.err.println("GetID by method for " + clazz); - String result = null; - try { - Method m = clazz.getDeclaredMethod("getStep", new Class[]{}); - // assert m.getReturnType() == String.class; - result = Objects.requireNonNull((String) m.invoke(clazz, (Object[]) null), "getStep may not return null"); - } catch (Exception ex) { - //do nothing - } - return result == null ? clazz.getName() : result; - } - - /** - * Get an array of steps by looking for a static method getID() on each - * class object passed - */ - static String[] getSteps(Class[] pages) { - Objects.requireNonNull(pages, "Null array of classes"); - - String[] result = new String[pages.length]; - - Set used = new HashSet<>(pages.length); - for (int i = 0; i < pages.length; i++) { - Objects.requireNonNull(pages[i], "Null at " + i + " in array of panel classes"); - - if (!WizardPage.class.isAssignableFrom(pages[i])) - throw new IllegalArgumentException(pages[i] - + " is not a subclass of WizardPage"); - result[i] = uniquify(getIDFromStaticMethod(pages[i]), used); - if (result[i] == null) - result[i] = pages[i].getName(); - } - // System.err.println("Returning " + Arrays.asList(result)); - return result; - } - -// /** Determine if a default constructor is present for a class */ -// private static boolean hasDefaultConstructor (Class clazz) { -// try { -// Constructor c = clazz.getConstructor(new Class[0]); -// return c != null; -// } catch (Exception e) { -// return false; -// } -// } - /** - * Get an array of descriptions by looking for the static method - * getDescription() on each passed class object - */ - static String[] getDescriptions(Class[] pages) { - String[] result = new String[pages.length]; - - for (int i = 0; i < pages.length; i++) - result[i] = getDescriptionFromStaticMethod(pages[i]); - - return result; - } - - static String getDescriptionFromStaticMethod(Class clazz) { - Method m; - try { - m = clazz.getDeclaredMethod("getDescription", (Class[]) null); - } catch (NoSuchMethodException | SecurityException e) { - throw new IllegalArgumentException("Could not find or access " - + "public static String " + clazz.getName() - + ".getDescription() - make sure it exists"); - } - - if (m.getReturnType() != String.class) - throw new IllegalArgumentException("getStep has wrong " - + " return type: " + m.getReturnType() + " on " - + clazz); - - if (!Modifier.isStatic(m.getModifiers())) - throw new IllegalArgumentException("getStep is not " - + "static on " + clazz); - - return AccessController.doPrivileged((PrivilegedAction) () -> { - try { - m.setAccessible(true); - return (String) m.invoke(null, (Object[]) null); - } catch (InvocationTargetException | IllegalAccessException ite) { - throw new IllegalArgumentException("Could not invoke " - + "public static String " + clazz.getName() - + ".getDescription() - make sure it exists.", ite); - } - }); - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/Wizard.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/Wizard.java deleted file mode 100644 index 2bd5a4975..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/Wizard.java +++ /dev/null @@ -1,360 +0,0 @@ -/* The contents of this file are subject to the terms of the Common Development -and Distribution License (the License). You may not use this file except in -compliance with the License. - You can obtain a copy of the License at http://www.netbeans.org/cddl.html -or http://www.netbeans.org/cddl.txt. - When distributing Covered Code, include this CDDL Header Notice in each file -and include the License file at http://www.netbeans.org/cddl.txt. -If applicable, add the following below the CDDL Header, with the fields -enclosed by brackets [] replaced by your own identifying information: -"Portions Copyrighted [year] [name of copyright owner]" */ -package org.jackhuang.hmcl.util.ui.wizard.spi; - -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import javax.swing.JComponent; - -/** - * Encapsulates the logic and state of a Wizard. A Wizard gathers information - * into a Map, and then performs some action with that information when the - * user clicks Finish. To display a wizard, pass it to one of the methods - * on WizardDisplayer.getDefault(). - *

    - * A Wizard is a series of one or more steps represented - * by panels in the user interface. Each step is identified by a unique String - * ID. - * Panels are created, usually on-demand, as the user navigates through - * the UI of the wizard. Panels typically listen on components they contain - * and put values into the Map where the wizard gathers data. Note that if the - * user navigates backward, data entered on pages after the current one - * disappears from the Map. - *

    - * To create a Wizard, you do not implement or instantiate this class directly, - * but rather, use one of the convenience classes in this package. There are - * three: - *

      - *
    • WizardPage - use or subclass WizardPage, and pass an array - * of instances, or an array of the Class objects of your - * subclasses - * to WizardPage.createWizard(). This class offers the added - * convenience that standard Swing components will be listened to automatically, - * and if their Name property is set, the value from the component will be - * automatically put into the settings map. - *
    • - * - *
    • WizardPanelProvider - subclass this to create a Wizard - * with a fixed set of steps. You provide a set of unique ID strings to the - * constructor, for all of the steps in the wizard, and override - * createPanel() to create the GUI component that should be displayed for - * each step - it will be called on demand as the user moves through the - * wizard
    • - * - *
    • WizardBranchController - this is for creating complex - * wizards with decision points after which the future steps change, depending - * on what the user chooses. Create a simple wizard using WizardPage or - * WizardPanelProvider to represent the initial steps. - * Then override getWizardForStep() or - * getPanelProviderForStep() to return a different Wizard to - * represent the remaining steps at any point where the set of future steps - * changes. You can have as many branch points as you want, simply by - * using WizardBranchController to create the wizards for different decision - * points. - *

      - * In other words, a wizard with a different set of panels (or number of steps) - * depending on the user's decision is really three wizards composed into one - - * one wizard that provides the initial set of steps, and then two others, one - * or the other of which will actually provide the steps/panels after the - * decision point (the Wizards are created on demand, for efficiency, so if - * the user never changes his or her mind at the decision point, only two - * of the three Wizards are ever actually created). - *

    - * - * @see org.jackhuang.hmcl.util.ui.wizard.api.WizardDisplayer - * @see WizardPage - * @see WizardPanelProvider - * @see WizardBranchController - * - * @author Timothy Boudreau - */ -public final class Wizard { - - /** - * Constant that can be returned by getForwardNavigationMode() - * to indicate that the Next button can be enabled (or the Finish button - * if the current panel is the last one in the wizard). - */ - public static final int MODE_CAN_CONTINUE - = WizardController.MODE_CAN_CONTINUE; - - /** - * Constant that can be returned by getForwardNavigationMode to - * indicate - * that the Finish button can be enabled if the problem string is null. - */ - public static final int MODE_CAN_FINISH - = WizardController.MODE_CAN_FINISH; - /** - * Constant that can be returned by getForwardNavigationMode to - * indicate - * that both the Finish and Next buttons can be enabled if the problem - * string is null. This value is a bitmask - i.e. - * MODE_CAN_CONTINUE_OR_FINISH == MODE_CAN_CONTINUE | - * MODE_CAN_FINISH - */ - public static final int MODE_CAN_CONTINUE_OR_FINISH - = WizardController.MODE_CAN_CONTINUE_OR_FINISH; - - /** - * Special panel ID key indicating a branch point in the wizard, - * after which the next step(s) are unknown. - */ - public static final String UNDETERMINED_STEP = "_#UndeterminedStep"; - - final WizardImplementation impl; //package private for unit tests - - /** - * Creates a new instance of Wizard - */ - Wizard(WizardImplementation impl) { - this.impl = Objects.requireNonNull(impl); - } - - /** - * Notify the wizard that the user is navigating to a different panel, - * as identified by the passed id. - * - * @param id The id of the panel being navigated to - * @param wizardData The data gathered thus far as the user has progressed - * through the wizard. The contents of this map should not contain any - * key/values that were assigned on future panels, if the user is - * navigating backward. - * - * @return The component that should be shown for step id - * of the Wizard - */ - public JComponent navigatingTo(String id, Map wizardData) { - return impl.navigatingTo(id, wizardData); - } - - /** - * Get the current step the wizard is on, as determined by the most recent - * call to navigatingTo(). - */ - public String getCurrentStep() { - return impl.getCurrentStep(); - } - - /** - * Get the id of the step that comes after current step returned by - * getCurrentStep(). - * - * @return Null if this is the last step of the wizard; - * UNDETERMINED_STEP if this is a branch point and the - * user yet needs to do some interaction with the UI of the current - * panel to trigger computation of the id of the next step; otherwise, - * the unique id of the next step. - */ - public String getNextStep() { - return impl.getNextStep(); - } - - /** - * Get the id of the preceding step to the current one as returned by - * getCurrentStep(), or null if the current step is the - * first page of the wizard. - * - * @return the id of the previous step or null - */ - public String getPreviousStep() { - return impl.getPreviousStep(); - } - - /** - * Get the problem string that should be displayed to the user. - * - * @return A string describing what the user needs to do to enable - * the Next or Finish buttons, or null if the buttons may be enabled - */ - public String getProblem() { - return impl.getProblem(); - } - - /** - * Get the string IDs of all known steps in this wizard, terminating - * with UNDETERMINED_STEP if subsequent steps of the - * wizard depend on the user's interaction beyond that point. - * - * @return an array of strings which may individually be passed to - * navigatingTo to change the current step of the wizard - */ - public String[] getAllSteps() { - return impl.getAllSteps(); - } - - /** - * Get a long description for this panel. The long description should be - * used in preference to the short description in the top of a wizard - * panel in the UI, if it returns non-null. - * - * @param stepId The ID of the step for which a description is requested - * - * @return A more detailed localized description or null - */ - public String getLongDescription(String stepId) { - return impl.getLongDescription(stepId); - } - - /** - * Get a localized String description of the step for the passed id, - * which may be displayed in the UI of the wizard. - * - * @param id A step id among those returned by getAllSteps() - */ - public String getStepDescription(String id) { - return impl.getStepDescription(id); - } - - /** - * Called when the user has clicked the finish button. This method - * computes whatever the result of the wizard is. - * - * @param settings The complete set of key-value pairs gathered by the - * various panels as the user proceeded through the wizard - * - * @return An implementation-dependent object that is the outcome of - * the wizard. May be null. Special return values are instances of - * DeferredWizardResult and Summary which will affect the behavior of - * the UI. - */ - public Object finish(Map settings) throws WizardException { - return impl.finish(settings); - } - - /** - * Called when the user has clicked the Cancel button in the wizard UI - * or otherwise closed the UI component without completing the wizard. - * - * @param settings The (possibly incomplete) set of key-value pairs gathered - * by the - * various panels as the user proceeded through the wizard - * - * @return true if the UI may indeed be closed, false if closing should - * not be permitted - */ - public boolean cancel(Map settings) { - return impl.cancel(settings); - } - - /** - * Get the title of the Wizard that should be displayed in its dialog - * titlebar (if any). - * - * @return A localized string - */ - public String getTitle() { - return impl.getTitle(); - } - - /** - * Determine if the wizard is busy doing work in a background thread and - * all navigation controls should be disabled. - * - * @return whether or not the wizard is busy - */ - public boolean isBusy() { - return impl.isBusy(); - } - - /** - * Get the navigation mode, which determines the enablement state of - * the Next and Finish buttons. - * - * @return one of the constants MODE_CAN_CONTINUE, - * MODE_CAN_FINISH, or - * MODE_CAN_CONTINUE_OR_FINISH. - */ - public int getForwardNavigationMode() { - return impl.getForwardNavigationMode(); - } - - private volatile boolean listeningToImpl = false; - private final List listeners = Collections.synchronizedList( - new LinkedList<>()); - - private WizardObserver l = null; - - /** - * Add a WizardObserver that will be notified of navigability and step - * changes. - * - * @param observer A WizardObserver - */ - public void addWizardObserver(WizardObserver observer) { - listeners.add(observer); - if (!listeningToImpl) { - l = new ImplL(); - impl.addWizardObserver(l); - listeningToImpl = true; - } - } - - /** - * Remove a WizardObserver. - * - * @param observer A WizardObserver - */ - public void removeWizardObserver(WizardObserver observer) { - listeners.remove(observer); - if (listeningToImpl && listeners.isEmpty()) { - impl.removeWizardObserver(l); - l = null; - listeningToImpl = false; - } - } - - private class ImplL implements WizardObserver { - - @Override - public void stepsChanged(Wizard wizard) { - WizardObserver[] l = (WizardObserver[]) listeners.toArray( - new WizardObserver[listeners.size()]); - for (WizardObserver l1 : l) - l1.stepsChanged(Wizard.this); - } - - @Override - public void navigabilityChanged(Wizard wizard) { - WizardObserver[] l = (WizardObserver[]) listeners.toArray( - new WizardObserver[listeners.size()]); - for (WizardObserver l1 : l) - l1.navigabilityChanged(Wizard.this); - } - - @Override - public void selectionChanged(Wizard wizard) { - WizardObserver[] l = (WizardObserver[]) listeners.toArray( - new WizardObserver[listeners.size()]); - for (WizardObserver l1 : l) - l1.selectionChanged(Wizard.this); - } - } - - @Override - public int hashCode() { - return impl.hashCode() * 17; - } - - @Override - public boolean equals(Object o) { - if (o == this) - return true; - else if (o instanceof Wizard) - return impl.equals(((Wizard) o).impl); - else - return false; - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardBranchController.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardBranchController.java deleted file mode 100644 index 0df71c2fa..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardBranchController.java +++ /dev/null @@ -1,175 +0,0 @@ -/* The contents of this file are subject to the terms of the Common Development -and Distribution License (the License). You may not use this file except in -compliance with the License. - You can obtain a copy of the License at http://www.netbeans.org/cddl.html -or http://www.netbeans.org/cddl.txt. - When distributing Covered Code, include this CDDL Header Notice in each file -and include the License file at http://www.netbeans.org/cddl.txt. -If applicable, add the following below the CDDL Header, with the fields -enclosed by brackets [] replaced by your own identifying information: -"Portions Copyrighted [year] [name of copyright owner]" */ - /* - * WizardBranchController.java - * - * Created on March 5, 2005, 6:33 PM - */ -package org.jackhuang.hmcl.util.ui.wizard.spi; - -import java.util.Map; -import java.util.Objects; - -/** - * Extend this class to create wizards which have branch points in them - - * either override getWizardForStep to return one or another a - * wizard which - * represents the subsequent steps after a decision point, or override - * getPanelProviderForStep to provide instances of - * WizardPanelProvider - * if there are no subsequent branch points and the continuation is a - * simple wizard. - *

    - * The basic idea is to supply a base wizard for the initial steps, stopping - * at the branch point. The panel for the branch point should put enough - * information into the settings map that the WizardBranchController can - * decide what to return as the remaining steps of the wizard. - *

    - * The result is a Wizard which embeds sub-wizards; when the - * PanelProvider passed to the constructor runs out of steps, - * the master Wizard will try to find a sub-Wizard - * by calling getWizardForStep. If non-null, the user seamlessly - * continues in the returned wizard. To create Wizards with - * multiple branches, simply override getWizardForStep to create - * another WizardBranchController and return the result of its - * createWizard method. - *

    - * Note that it is important to cache the instances of - * WizardPanelProvider - * or Wizard which are returned here - this class's methods may - * be called frequently to determine if the sequence of steps (the next wizard) - * have changed. - * - * @author Tim Boudreau - */ -public abstract class WizardBranchController { - - private final SimpleWizardInfo base; - - /** - * Create a new WizardBranchController. The base argument - * provides the initial step(s) of the wizard up; when the user comes to - * the last step of the base wizard, this WizardBranchController will be - * asked for a wizard to provide subsequent panes. So the base wizard - * should put some token into the settings map based on what the user - * selects on its final pane, which the WizardBranchController can use - * to decide what the next steps should be. - */ - protected WizardBranchController(WizardPanelProvider base) { - this(new SimpleWizardInfo(base)); - } - - /** - * Create a new WizardBranchController using the passed WizardPage - * instances as the initial pages of the wizard. - * - * @param pages An array of WizardPage instances - */ - protected WizardBranchController(WizardPage[] pages) { - this(WizardPage.createWizardPanelProvider(pages)); - } - - /** - * Create a new WizardBranchController using the passed WizardPage - * as the initial page of the wizard. The initial page should - * determine the subsequent steps of the wizard. - * - * @param onlyPage An instance of WizardPage - */ - protected WizardBranchController(WizardPage onlyPage) { - this(WizardPage.createWizardPanelProvider(onlyPage)); - } - - /** - * Create a new WizardBranchController, using the passed - * SimpleWizardInfo - * for the initial panes of the wizard. - */ - WizardBranchController(SimpleWizardInfo base) { - this.base = Objects.requireNonNull(base, "No base"); - } - - /** - * Get the wizard which represents the subsequent panes after this step. - * The UI for the current step should have put sufficient data into the - * settings map to decide what to return; return null if not. - *

    - * The default implementation delegates to - * getPanelProviderForStep() - * and returns a Wizard representing the result of that - * call. - *

    - * Note: This method can be called very frequently, to determine - * if the sequence of steps has changed - so it needs to run fast. - * Returning the same instance every time the same arguments are passed - * is highly recommended. It will typically be called whenever a change - * is fired by the base wizard (i.e. every call setProblem() - * should generate a check to see if the navigation has changed). - *

    - * Note that the wizard for the subsequent steps will be instantiated - * as soon as it is known what the user's choice is, so the list of - * pending steps can be updated (this does not mean that all subsequent - * panel UI components of the wizard will be instantiated, just the - * Wizard object itself, which will create panels on demand if they - * have not already been created). - * - * @param step The current step the user is on in the wizard - * @param settings The settings map, which previous panes of the wizard - * have been writing information into - */ - protected Wizard getWizardForStep(String step, Map settings) { - WizardPanelProvider provider = getPanelProviderForStep(step, settings); - return provider == null ? null : provider.createWizard(); - } - - /** - * Override this method to return a WizardPanelProvider - * representing the - * steps from here to the final step of the wizard, varying the returned - * object based on the contents of the map and the step in question. - * The default implementation of this method throws an Error - - * either override this method, or override getWizardForStep() - * (in which case this method will not be called). - *

    - * Note: This method can be called very frequently, to determine - * if the sequence of steps has changed - so it needs to run fast. - * Returning the same instance every time called with equivalent arguments - * is highly recommended. - * - * @param step The string ID of the current step - * @param settings The settings map, which previous panes of the wizard - * will have written content into - */ - protected WizardPanelProvider getPanelProviderForStep(String step, Map settings) { - throw new Error("Override either createInfoForStep or " - + "createWizardForStep"); - } - - SimpleWizardInfo getBase() { - return base; - } - - private WizardImplementation wizard = null; - private Wizard real = null; - - /** - * Create a Wizard to represent this branch controller. The resulting - * Wizard instance is cached; subsequent calls to this method will return - * the same instance. - */ - public final Wizard createWizard() { - if (wizard == null) { - wizard = new BranchingWizard(this); - real = new Wizard(wizard); - } - return real; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardController.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardController.java deleted file mode 100644 index ef861673f..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardController.java +++ /dev/null @@ -1,120 +0,0 @@ -/* The contents of this file are subject to the terms of the Common Development -and Distribution License (the License). You may not use this file except in -compliance with the License. - You can obtain a copy of the License at http://www.netbeans.org/cddl.html -or http://www.netbeans.org/cddl.txt. - When distributing Covered Code, include this CDDL Header Notice in each file -and include the License file at http://www.netbeans.org/cddl.txt. -If applicable, add the following below the CDDL Header, with the fields -enclosed by brackets [] replaced by your own identifying information: -"Portions Copyrighted [year] [name of copyright owner]" */ -/* - * WizardController.java - * - * Created on March 5, 2005, 7:24 PM - */ - -package org.jackhuang.hmcl.util.ui.wizard.spi; - -/** - * Controller which can be used to modify the UI state of a wizard. Passed - * as an argument to methods of WizardPanelProvider. Use this - * interface - * to determine whether the Next/Finish buttons should be enabled, and if some - * problem explanation text should be displayed. - *

    - * If you are using {@link WizardPage WizardPage}, methods equivalent to this - * interface are available directly on instances of WizardPage. - * - * @see WizardPanelProvider - * @author Tim Boudreau - */ -public final class WizardController { - /** - * Constant that can be passed to setForwardNavigationMode to indicate - * that the Next button can be enabled if the problem string is null. - * Value is identical to the similarly named constant on Wizard. - */ - public static final int MODE_CAN_CONTINUE = 1; - /** - * Constant that can be passed to setForwardNavigationMode to indicate - * that the Finish button can be enabled if the problem string is null. - * Value is identical to the similarly named constant on Wizard. - */ - public static final int MODE_CAN_FINISH = 2; - /** - * Constant that can be passed to setForwardNavigationMode to indicate - * that both the Finish and Next buttons can be enabled if the problem - * string is null. This value is a bitmask - i.e. - * MODE_CAN_CONTINUE_OR_FINISH == MODE_CAN_CONTINUE | - * MODE_CAN_FINISH. - * Value is identical to the similarly named constant on - * Wizard. - */ - public static final int MODE_CAN_CONTINUE_OR_FINISH = - MODE_CAN_CONTINUE | MODE_CAN_FINISH; - - private final WizardControllerImplementation impl; - - WizardController (WizardControllerImplementation impl) { - this.impl = impl; - } - - /** - * Indicate that there is a problem with what the user has (or has not) - * input, such that the Next/Finish buttons should be disabled until the - * user has made some change. - *

    - * If you want to disable the Next/Finish buttons, do that by calling - * this method with a short description of what is wrong. - *

    - * Pass null to indicate there is no problem; non-null indicates there is - * a problem - the passed string should be a localized, human-readable - * description that assists the user in correcting the situation. It will - * be displayed in the UI. - */ - public void setProblem (String value) { - impl.setProblem (value); - } - - /** - * Set the forward navigation mode. This method determines whether - * the Next button, the Finish button or both should be enabled if the - * problem string is set to null. - *

    - * On panels where, based on the UI state, the only reasonable next - * step is to finish the wizard (even though there may be more panels - * if the UI is in a different state), set the navigation mode to - * MODE_CAN_FINISH, and the Finish button will be enabled, and the - * Next button not. - *

    - * On panels where, based on the UI state, the user could either continue - * or complete the wizard at that point, set the navigation mode to - * MODE_CAN_CONTINUE_OR_FINISH. - *

    - * If the finish button should not be enabled, set the navigation mode - * to MODE_CAN_CONTINUE. This is the default on any panel if no - * explicit call to setForwardNavigationMode() has been made. - * - * @param navigationMode Legal values are MODE_CAN_CONTINUE, - * MODE_CAN_FINISH or MODE_CAN_CONTINUE_OR_FINISH - */ - public void setForwardNavigationMode (int navigationMode) { - impl.setForwardNavigationMode(navigationMode); - } - - /** - * Indicate that some sort of background process is happening (presumably - * a progress bar is being shown to the user) which cannot be interrupted. - * Calling this menu disables all navigation and the ability to close - * the wizard dialog. Use this option with caution and liberal use of - * finally to reenable navigation. - */ - public void setBusy (boolean busy) { - impl.setBusy (busy); - } - - WizardControllerImplementation getImpl() { - return impl; - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardControllerImplementation.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardControllerImplementation.java deleted file mode 100644 index bb9b6704b..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardControllerImplementation.java +++ /dev/null @@ -1,70 +0,0 @@ -/* The contents of this file are subject to the terms of the Common Development -and Distribution License (the License). You may not use this file except in -compliance with the License. - You can obtain a copy of the License at http://www.netbeans.org/cddl.html -or http://www.netbeans.org/cddl.txt. - When distributing Covered Code, include this CDDL Header Notice in each file -and include the License file at http://www.netbeans.org/cddl.txt. -If applicable, add the following below the CDDL Header, with the fields -enclosed by brackets [] replaced by your own identifying information: -"Portions Copyrighted [year] [name of copyright owner]" */ - -package org.jackhuang.hmcl.util.ui.wizard.spi; - -/** - * Internal, non-public SPI for wizard controller; allows the actual WizardController - * class to be final, so it does not imply that the API user should implement - * it, and methods can be added safely to it if desired. - * - * @see WizardController - * @author Tim Boudreau - */ -interface WizardControllerImplementation { - /** - * Indicate that there is a problem with what the user has (or has not) - * input, such that the Next/Finish buttons should be disabled until the - * user has made some change. - *

    - * If you want to disable the Next/Finish buttons, do that by calling - * this method with a short description of what is wrong. - *

    - * Pass null to indicate there is no problem; non-null indicates there is - * a problem - the passed string should be a localized, human-readable - * description that assists the user in correcting the situation. It will - * be displayed in the UI. - */ - void setProblem (String value); - - /** - * Set the forward navigation mode. This method determines whether - * the Next button, the Finish button or both should be enabled if the - * problem string is set to null. - *

    - * On panels where, based on the UI state, the only reasonable next - * step is to finish the wizard (even though there may be more panels - * if the UI is in a different state), set the navigation mode to - * MODE_CAN_FINISH, and the Finish button will be enabled, and the - * Next button not. - *

    - * On panels where, based on the UI state, the user could either continue - * or complete the wizard at that point, set the navigation mode to - * MODE_CAN_CONTINUE_OR_FINISH. - *

    - * If the finish button should not be enabled, set the navigation mode - * to MODE_CAN_CONTINUE. This is the default on any panel if no - * explicit call to setForwardNavigationMode() has been made. - * - * @param navigationMode Legal values are MODE_CAN_CONTINUE, - * MODE_CAN_FINISH or MODE_CAN_CONTINUE_OR_FINISH - */ - void setForwardNavigationMode (int navigationMode); - - /** - * Indicate that some sort of background process is happening (presumably - * a progress bar is being shown to the user) which cannot be interrupted. - * Calling this menu disables all navigation and the ability to close - * the wizard dialog. Use this option with caution and liberal use of - * finally to reenable navigation. - */ - void setBusy (boolean busy); -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardException.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardException.java deleted file mode 100644 index 1e47a68e1..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardException.java +++ /dev/null @@ -1,52 +0,0 @@ -/* The contents of this file are subject to the terms of the Common Development -and Distribution License (the License). You may not use this file except in -compliance with the License. - You can obtain a copy of the License at http://www.netbeans.org/cddl.html -or http://www.netbeans.org/cddl.txt. - When distributing Covered Code, include this CDDL Header Notice in each file -and include the License file at http://www.netbeans.org/cddl.txt. -If applicable, add the following below the CDDL Header, with the fields -enclosed by brackets [] replaced by your own identifying information: -"Portions Copyrighted [year] [name of copyright owner]" */ -/* - * WizardException.java - * - * Created on February 22, 2005, 3:56 PM - */ - -package org.jackhuang.hmcl.util.ui.wizard.spi; - -/** - * Some arguments a user enters in a wizard may be too expensive to validate - * as the user is going through the wizard. Therefore, Wizard.finish() throws - * WizardException. - *

    - * Exceptions of this type always have a localized message, and optionally - * provide a step in the wizard that to return to, so that the user can - * enter corrected information. - * - * @author Tim Boudreau - */ -public final class WizardException extends Exception { - private final String localizedMessage; - private final String step; - /** Creates a new instance of WizardException */ - public WizardException(String localizedMessage, String stepToReturnTo) { - super ("wizardException"); - this.localizedMessage = localizedMessage; - this.step = stepToReturnTo; - } - - public WizardException (String localizedMessage) { - this (localizedMessage, Wizard.UNDETERMINED_STEP); - } - - public String getLocalizedMessage() { - return localizedMessage; - } - - public String getStepToReturnTo() { - return step; - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardImplementation.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardImplementation.java deleted file mode 100644 index 8a47422a2..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardImplementation.java +++ /dev/null @@ -1,246 +0,0 @@ -/* The contents of this file are subject to the terms of the Common Development -and Distribution License (the License). You may not use this file except in -compliance with the License. - You can obtain a copy of the License at http://www.netbeans.org/cddl.html -or http://www.netbeans.org/cddl.txt. - When distributing Covered Code, include this CDDL Header Notice in each file -and include the License file at http://www.netbeans.org/cddl.txt. -If applicable, add the following below the CDDL Header, with the fields -enclosed by brackets [] replaced by your own identifying information: -"Portions Copyrighted [year] [name of copyright owner]" */ -/* - * Wizard.java - * - * Created on February 22, 2005, 2:18 PM - */ - -package org.jackhuang.hmcl.util.ui.wizard.spi; - -import java.util.Map; -import javax.swing.JComponent; - -/** - * Non-public mirror interface to the final Wizard class. A Wizard delegates to - * its WizardImplementation for all of its functions. This interface is - * implemented by several internal classes. - * - * @author Tim Boudreau - * @see Wizard - * @see WizardPage - * @see WizardPanelProvider - * @see WizardBranchController - * @see org.netbeans.api.wizard.WizardDisplayer - */ -interface WizardImplementation { - /** - * Constant that can be returned by getForwardNavigationMode to indicate - * that the Next button can be enabled if the problem string is null. - */ - public static final int MODE_CAN_CONTINUE = - WizardController.MODE_CAN_CONTINUE; - - /** - * Constant that can be returned by getForwardNavigationMode to indicate - * that the Finish button can be enabled if the problem string is null. - */ - public static final int MODE_CAN_FINISH = - WizardController.MODE_CAN_FINISH; - /** - * Constant that can be returned by getForwardNavigationMode to indicate - * that both the Finish and Next buttons can be enabled if the problem - * string is null. This value is a bitmask - i.e. - * MODE_CAN_CONTINUE_OR_FINISH == MODE_CAN_CONTINUE | - * MODE_CAN_FINISH - */ - public static final int MODE_CAN_CONTINUE_OR_FINISH = - WizardController.MODE_CAN_CONTINUE_OR_FINISH; - - /** - * Special panel ID key indicating a branch point in the wizard, - * after which the next step(s) are unknown. - */ - public static final String UNDETERMINED_STEP = "_#UndeterminedStep"; - - /** - * Set which step of the wizard is currently being displayed and get - * the component for that step. This method is passed a Map into which - * panels may put key/value pairs that represent user input. This Map - * is what the finish() method will use to decide what to - * do. - *

    - * The ID passed - * becomes the currently active step of the wizard as of this call. - *

    - * If the user has already been to this step, and some key/value pairs - * were written to the wizard data map, and the user then - * then pressed the Back button, and later pressed Next again, the - * wizard data map may already contain key/value pairs for this - * step. Panels whose components - * are affected by data entered in the map in preceding steps should - * update their UI based on the map's current contents, at the time a - * step is re-displayed, to ensure they are in - * sync with any changes the user may have made on preceding panels - * since the last time this panel was shown. - *

    - * If this method is called as a result of - * the user pressing the Back button, the wizard data map will not - * contain any key/value pairs added by the subsequent panels. It - * will only key/value pairs from - * panels that precede this one and any written the last time this - * panel was visited. The wizard data map shall never contain - * keys and values from future steps in the wizard. - *

    - * Implementations are expected to return the same component if - * navigatingTo() is called repeatedly with the same ID. - * Components should be constructed once, then reused for the lifetime - * of the wizard. - *

    - * Note: The consequences of a later panel writing or deleting - * a key/value pair that was put into the wizard data map by - * an earlier panel are - * undefined. Each step should use only its own unique keys, not - * modify those from earlier steps. - *
    - * - * - * @param id The ID of the to-be-current panel - * @param wizardData The map into which panels should write key/value pairs - * in response to user input - the place where user data is aggregated - * @return The UI component for this step, which should be displayed in - * the wizard - */ - public JComponent navigatingTo(String id, Map wizardData); - - /** - * Get the String ID of the current panel. - * If there is no current panel, return null. - * - * @return The unique ID of the step currently - * presented in the UI, as determined by the last call to - * navigateTo - */ - public String getCurrentStep(); - - /** - * Get the String ID of the next panel. If the Next button should be - * disabled, or this is the final step of the wizard, return null. - * - * @return The unique ID of the step that follows the one currently - * presented in the UI, as determined by the last call to - * navigateTo - */ - public String getNextStep(); - - /** - * Get the String ID of the previous panel. If the Prev button should - * be disabled, return null. - * @return the String ID of the step that precedes the one currently - * presented in this Wizards UI, or null if it is either - * the first step or the preceding step is unknown, as determined by the last call to - * navigateTo - */ - public String getPreviousStep(); - - /** - * Get a human readable description of the reason the Next/Finish button - * is not enabled (i.e. "#\foo is not a legal filename"). - * @return A localized string that describes why the Next/Finish button - * is not enabled, or null if one or the other or both should be enabled - */ - public String getProblem(); - - /** - * Get String IDs for the entire list of known steps in the - * wizard (regardless of whether - * Finish/Next can be enabled or not). If there is a branch point in - * the wizard and it cannot be determined what step will be next beyond - * that point, make the final entry in the returned array the constant - * UNDETERMINED_STEP, and fire stepsChange() to any listeners - * once the later steps become known. - *

    - * The return value of this method must be an array of Strings at least - * one String in length. If length == 1, the single step ID may not be - * UNDETERMINED_STEP; UNDETERMINED_STEP may only be the last ID, and only - * may be used if there is more than one step. - * - * @return An array of strings that constitute unique IDs of each step - * in the wizard. The returned array may not contain duplicate entries. - */ - public String[] getAllSteps(); - - /** - * Get a human-readable description for a given panel, as identified by - * the passed ID. - */ - public String getStepDescription(String id); - - public String getLongDescription(String id); - - /** - * Add a listener for changes in the count or order of steps in this - * wizard and for changes in Next/Previous/Finish button enablement. - * @param listener A listener to add - */ - public void addWizardObserver(WizardObserver listener); - - /** - * Remove a listener for changes in the count or order of steps in this - * wizard and for changes in Next/Previous/Finish button enablement. - * @param listener A listener to remove - */ - public void removeWizardObserver(WizardObserver listener); - - /** - * Finish the wizard, (optionally) instantiating some Object and returning - * it. For cases where the map may contain wizardData too expensive to - * validate on the fly, - * this method may throw a WizardException with a localized message - * indicating the problem; that exception can indicate a step in the - * wizard to return to to allow the user to correct the information. - *

    - * No methods on a Wizard instance should be called after - * that Wizard's finish() method has been - * called - the results are undefined. - * - * @param settings A map containing all of the wizardData the user has - * entered as they traversed this wizard - presumably enough to do - * whatever this method needs to do (if not, that's a bug in the - * implementation of Wizard). - */ - public Object finish(Map settings) throws WizardException; - - /** Get the title of the wizard. - * @return A human-readable, localized title that should be displayed - * in any dialog showing this wizard - */ - public String getTitle(); - - /** Determine if all navigation buttons should be disabled - if the - * wizard is currently doing some kind of progress/background processing - * task that cannot be interrupted. - */ - public boolean isBusy(); - - /** - * Get the forward navigation mode of this wizard. This - * determines whether the Next button, the Finish button or both should - * be enabled, if the problem string returned from getProblem - * is null. If the problem is set to non-null, the UI should disable - * all forward navigation. - *

    - * This method should never return any value but - * MODE_CAN_CONTINUE, MODE_CAN_FINISH or MODE_CAN_CONTINUE_OR_FINISH - - * it is not a mechanism for disabling all forward navigation (return - * non null from getProblem() for that, or true - * from isBusy() to temporarily disable all navigation). - *

    - * On the final step of the wizard, this method should always return - * MODE_CAN_FINISH. - */ - public int getForwardNavigationMode(); - - /** - * Called when the user cancels the wizard. - */ - public boolean cancel(Map settings); -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardObserver.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardObserver.java deleted file mode 100644 index 8c7516a6b..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardObserver.java +++ /dev/null @@ -1,40 +0,0 @@ -/* The contents of this file are subject to the terms of the Common Development -and Distribution License (the License). You may not use this file except in -compliance with the License. - You can obtain a copy of the License at http://www.netbeans.org/cddl.html -or http://www.netbeans.org/cddl.txt. - When distributing Covered Code, include this CDDL Header Notice in each file -and include the License file at http://www.netbeans.org/cddl.txt. -If applicable, add the following below the CDDL Header, with the fields -enclosed by brackets [] replaced by your own identifying information: -"Portions Copyrighted [year] [name of copyright owner]" */ -package org.jackhuang.hmcl.util.ui.wizard.spi; - -/** - * Observer which can detect changes in the state of a wizard as the - * user proceeds. Only likely to be used by implementations of - * WizardDisplayer. - */ -public interface WizardObserver { - /** - * Called when the number or names of the steps of the - * wizard changes (for example, the user made a choice in one pane which - * affects the flow of subsequent steps). - * @param wizard The wizard whose steps have changed - */ - public void stepsChanged(Wizard wizard); - - /** - * Called when the enablement of the next/previous/finish buttons - * change, or the problem text changes. - * @param wizard The wizard whose navigability has changed - */ - public void navigabilityChanged(Wizard wizard); - - /** - * Called whenever the current step changes. - * - * @param wizard The wizard whose current step has changed - */ - public void selectionChanged(Wizard wizard); -} \ No newline at end of file diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardPage.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardPage.java deleted file mode 100644 index b057b6c91..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardPage.java +++ /dev/null @@ -1,1122 +0,0 @@ -/* The contents of this file are subject to the terms of the Common Development -and Distribution License (the License). You may not use this file except in -compliance with the License. - You can obtain a copy of the License at http://www.netbeans.org/cddl.html -or http://www.netbeans.org/cddl.txt. - When distributing Covered Code, include this CDDL Header Notice in each file -and include the License file at http://www.netbeans.org/cddl.txt. -If applicable, add the following below the CDDL Header, with the fields -enclosed by brackets [] replaced by your own identifying information: -"Portions Copyrighted [year] [name of copyright owner]" */ - /* - * FixedWizard.java - * - * Created on August 19, 2005, 9:11 PM - */ -package org.jackhuang.hmcl.util.ui.wizard.spi; - -import java.beans.Beans; -import javax.swing.*; -import javax.swing.text.JTextComponent; -import javax.swing.tree.TreePath; -import java.awt.Color; -import java.awt.Component; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import org.jackhuang.hmcl.util.ArrayUtils; - -/** - * A convenience JPanel subclass that makes it easy to create wizard panels. - * This class provides a number of conveniences: - *

    - * Automatic listening to child components
    - * If you add an editable component (all standard Swing controls are supported) - * to a WizardPage or a child JPanel inside it, a listener is automatically - * attached to it. If user input occurs, the following things happen, in order: - *

      - *
    • If the name property of the component has been set, then the - * value from the component (i.e. Boolean for checkboxes, selected item(s) for - * lists/combo boxes/trees, etc.) will automatically be added to the wizard - * settings map, with the component name as the key.
    • - *
    • Regardless of whether the name property is set, - * validateContents() will be called. You can override that method - * to enable/disable the finish button, call setProblem() to - * disable navigation and display a string to the user, etc. - *
    - *

    - * The above behavior can be disabled by passing false to the - * appropriate constructor. In that case, validateContents will - * never be called automatically. - *

    - * If you have custom components that WizardPage will not know how to listen to - * automatically, attach an appropriate listener to them and optionally call - * userInputReceived() with the component and the event if you want - * to run your automatic validation code. - *

    - * For convenience, this class implements the relevant methods for accessing the - * WizardController and the settings map for the wizard that the - * panel is a part of. - *

    - * Instances of WizardPage can be returned from a WizardPanelProvider; this - * class also offers two methods for conveniently assembling a wizard: - *

      - *
    • Pass an array of already instantiated WizardPages to - * createWizard(). Note that for large wizards, it is preferable to - * construct the panels on demand rather than at construction time.
    • - *
    • Construct a wizard out of WizardPages, instantiating the panels as - * needed: Pass an array of classes all of which - *
        - *
      • Are subclasses of WizardPage
      • - *
      • Have a static method with the following signature: - *
          - *
        • public static String getDescription()
        • - *
        - *
      • - *
      - *
    - *

    - * Note that during development of a wizard, it is worthwhile to test/run with - * assertions enabled, as there is quite a bit of validity checking via - * assertions that can help find problems early. - *

    Using Custom Components

    - * If the autoListen constructor argument is true, a WizardPage - * will automatically listen to components which have a name, if they are - * standard Swing components it knows how to listen to. If you are using custom - * components, implement WizardPage.CustomComponentListener and return it from - * createCustomComponentListener() to add supplementary listening - * code for custom components. - *

    - * Note: Swing components do not fire property changes when setName() is called. - * If your component's values are not being propagated into the settings map, - * make sure you are calling setName() before adding the component to the - * hierarchy. - *

    - * Also note that cell editors in tables and lists and so forth are always - * ignored by the automatic listening code. - * - * @author Tim Boudreau - */ -public class WizardPage extends JPanel implements WizardPanel { - - private final String description; - String id; - - //Have an initial dummy map so it's never null. We'll dump its contents - //into the real map the first time it's set - private Map wizardData; - //An initial wizardController that will dump its settings into the real - //one the first time it's set - private WizardControllerImplementation wc = new WC(); - private WizardController controller = new WizardController(wc); - - //Flag to make sure we don't reenter userInputReceieved from maybeUpdateMap() - private boolean inBeginUIChanged = false; - //Flag to make sure we don't reenter userInputReceived because the - //implementation of validateContents changed a component's value, triggering - //a new event on GenericListener - private boolean inUiChanged = false; - private CustomComponentListener ccl; - private boolean autoListen; - - /** - * Create a WizardPage with the passed description and auto-listening - * behavior. - * - * @param stepDescription the localized description of this step - * @param autoListen if true, components added will automatically be - * listened to for user input - */ - public WizardPage(String stepDescription, boolean autoListen) { - this(null, stepDescription, autoListen); - } - - /** - * Construct a new WizardPage with the passed step id and description. Use - * this constructor for WizardPages which will be constructed ahead of time - * and passed in an array to createWizard. - * - * @param stepId the unique ID for the step represented. If null, the class - * name or a variant of it will be used - * @param stepDescription the localized description of this step - * @param autoListen if true, components added will automatically be - * listened to for user input - * - * @see #validateContents - */ - public WizardPage(String stepId, String stepDescription, boolean autoListen) { - id = stepId == null ? getClass().getName() : stepId; - this.autoListen = autoListen; - description = stepDescription; - - } - - private boolean listening; - - private void startListening() { - listening = true; - if (autoListen) { - //It will attach itself - GenericListener gl = new GenericListener(this, ccl = createCustomComponentListener(), - ccl == null ? null : new CustomComponentNotifierImpl(this)); - gl.attachToHierarchyOf(this); - } else if ((ccl = createCustomComponentListener()) != null) - throw new IllegalStateException("CustomComponentListener " - + "will never be called if the autoListen parameter is " - + "false"); - setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); //XXX - } - - /** - * Create an auto-listening WizardPage with the passed description - * - * @param stepDescription the localized description of this step - */ - public WizardPage(String stepDescription) { - this(null, stepDescription); - } - - /** - * Create an auto-listening WizardPage with the passed description - * - * @param stepId The unique id for the step. If null, an id will be - * generated - * @param stepDescription the localized description of this step - * - */ - public WizardPage(String stepId, String stepDescription) { - this(stepId, stepDescription, true); - } - - /** - * Use this constructor or the default constructor if you intend to pass an - * array of Class objects to lazily create WizardPanels. - */ - protected WizardPage(boolean autoListen) { - this(null, null, autoListen); - } - - /** - * Default constructor. AutoListening will be on by default. - */ - protected WizardPage() { - this(true); - } - - /** - * If you are using custom Swing or AWT components which the WizardPage will - * not know how to automatically listen to, you may want to override this - * method, implement CustomComponentListener and return an instance of it. - * - * @return A CustomComponentListener implementation, or null (the default). - */ - protected CustomComponentListener createCustomComponentListener() { - return null; - } - - /** - * Implement this class if you are using custom Swing or AWT components, and - * return an instance of it from - * WizardPage.createCustomComponentListener(). - */ - public static abstract class CustomComponentListener { - - /** - * Indicates that this CustomComponentListener will take responsibility - * for noticing events from the passed component, and that the - * WizardPage should not try to automatically listen on it (which it can - * only do for standard Swing components and their children). - *

    - * Note that this method may be called frequently and any test it does - * should be fast. - *

    - * Important: The return value from this method should always be - * the same for any given component, for the lifetime of the WizardPage. - * - * @param c A component - * - * @return Whether or not this CustomComponentListener will listen on - * the passed component. If true, the component will later be passed to - * startListeningTo() - */ - public abstract boolean accept(Component c); - - /** - * Begin listening for events on the component. When an event occurs, - * call the eventOccurred() method on the passed - * CustomComponentNotifier. - * - * @param c The component to start listening to - * @param n An object that can be called to update the settings map when - * an interesting event occurs on the component - */ - public abstract void startListeningTo(Component c, CustomComponentNotifier n); - - /** - * Stop listening for events on a component. - * - * @param c The component to stop listening to - */ - public abstract void stopListeningTo(Component c); - - /** - * Determine if the passed component is a container whose children may - * need to be listened on. Returns false by default. - * - * @param c A component which might be a container - */ - public boolean isContainer(Component c) { - return false; - } - - /** - * Get the map key for this component's value. By default, returns the - * component's name. Will only be passed components which the - * accept() method returned true for. - *

    - * Important: The return value from this method should always be - * the same for any given component, for the lifetime of the WizardPage. - * - * @param c the component, which the accept method earlier returned true - * for - * - * @return A string key that should be used in the Wizard's settings map - * for the name of this component's value - */ - public String keyFor(Component c) { - return c.getName(); - } - - /** - * Get the value currently set on the passed component. Will only be - * passed components which the accept() method returned - * true for, and which keyFor() returned non-null. - * - * @param c the component - * - * @return An object representing the current value of this component. - * For example, if it were a JTextComponent, the value - * would likely be the return value of - * JTextComponent.getText() - */ - public abstract Object valueFor(Component c); - } - - /** - * Object which is passed to - * CustomComponentListener.startListeningTo(), which can be - * called when an event has occurred on a custom component the - * CustomComponentListener has claimed (by returning - * true from its accept() method). - */ - public static abstract class CustomComponentNotifier { - - private CustomComponentNotifier() { - } - - /** - * Method which may be called when an event occurred on a custom - * component. - * - * @param c the component - * @param eventObject the event object from the component, or null (with - * the exception of javax.swing.text.DocumentEvent, it will - * likely be a subclass of java.util.EventObject). - */ - public abstract void userInputReceived(Component c, Object eventObject); - } - - private static final class CustomComponentNotifierImpl extends CustomComponentNotifier { - - private final WizardPage page; - - private CustomComponentNotifierImpl(WizardPage page) { - this.page = page; //Slightly smaller footprint a nested, not inner class - } - - @Override - public void userInputReceived(Component c, Object event) { - if (!page.ccl.accept(c)) - return; - page.userInputReceived(c, event); - } - } - - String id() { - return getID(); - } - - String description() { - return getDescription(); - } - - private String getID() { - return id; - } - - private String getDescription() { - return description; - } - - @Override - public void addNotify() { - super.addNotify(); - if (!listening) - startListening(); - - renderingPage(); - inValidateContents = true; - try { - setProblem(validateContents(null, null)); - } finally { - inValidateContents = false; - } - } - - @Override - public WizardPanelNavResult allowBack(String stepName, Map settings, Wizard wizard) { - return WizardPanelNavResult.PROCEED; - } - - @Override - public WizardPanelNavResult allowFinish(String stepName, Map settings, Wizard wizard) { - return WizardPanelNavResult.PROCEED; - } - - @Override - public WizardPanelNavResult allowNext(String stepName, Map settings, Wizard wizard) { - return WizardPanelNavResult.PROCEED; - } - - private boolean inValidateContents = false; - - /** - * Called whenever the page is rendered. This can be used by the page as a - * notification to load page-specific information in its fields. - *

    - * By default, this method does nothing. - */ - protected void renderingPage() { - // Empty - } - - /** - * Create a simple Wizard from an array of WizardPages - */ - public static Wizard createWizard(WizardPage[] contents, WizardResultProducer finisher) { - return new WPP(contents, finisher).createWizard(); - } - - public static Wizard createWizard(String title, WizardPage[] contents, WizardResultProducer finisher) { - return new WPP(title, contents, finisher).createWizard(); - } - - public static Wizard createWizard(String title, WizardPage[] contents) { - return createWizard(title, contents, WizardResultProducer.NO_OP); - } - - /** - * Create a simple Wizard from an array of WizardPages, with a no-op - * WizardResultProducer. - */ - public static Wizard createWizard(WizardPage[] contents) { - return createWizard(contents, WizardResultProducer.NO_OP); - } - - /** - * Create simple Wizard from an array of classes, each of which is a unique - * subclass of WizardPage. - */ - public static Wizard createWizard(Class[] wizardPageClasses, WizardResultProducer finisher) { - return new CWPP(wizardPageClasses, finisher).createWizard(); - } - - /** - * Create simple Wizard from an array of classes, each of which is a unique - * subclass of WizardPage. - */ - public static Wizard createWizard(String title, Class[] wizardPageClasses, WizardResultProducer finisher) { - return new CWPP(title, wizardPageClasses, finisher).createWizard(); - } - - /** - * Create simple Wizard from an array of classes, each of which is a unique - * subclass of WizardPage. - */ - public static Wizard createWizard(String title, Class[] wizardPageClasses) { - return new CWPP(title, wizardPageClasses, - WizardResultProducer.NO_OP).createWizard(); - } - - /** - * Create a simple Wizard from an array of classes, each of which is a - * unique subclass of WizardPage, with a no-op WizardResultProducer. - */ - public static Wizard createWizard(Class[] wizardPageClasses) { - return createWizard(wizardPageClasses, WizardResultProducer.NO_OP); - } - - /** - * Called by createPanelForStep, with whatever map is passed. In the current - * impl this is always the same Map, but that is not guaranteed. If any - * content was added by calls to putWizardData() during the constructor, - * etc., such data is copied to the settings map the first time this method - * is called. - * - * Subclasses do NOT need to override this method, they can override - * renderPage which is always called AFTER the map has been made valid. - */ - void setWizardDataMap(Map m) { - if (m == null) - wizardData = new HashMap<>(); - else { - if (wizardData instanceof HashMap) - // our initial map has keys for all of our components - // but with dummy empty values - // So make sure we don't override data that was put in as part of the initialProperties - for (Map.Entry entry : (Set) wizardData.entrySet()) { - Object key = entry.getKey(); - if (!m.containsKey(key)) - m.put(key, entry.getValue()); - } - wizardData = m; - } - } - - /** - * Set the WizardController. In the current impl, this is always the same - * object, but the API does not guarantee that. The first time this is - * called, it will update the state of the passed controller to match any - * state that was set by components during the construction of this - * component - */ - void setController(WizardController controller) { - if (controller.getImpl() instanceof WC) - ((WC) controller.getImpl()).configure(controller); - - this.controller = controller; - } - - /** - * Get the WizardController for interacting with the Wizard that contains - * this panel. Return value will never be null. - */ - private WizardController getController() { - return controller; - } - - /** - * Set the problem string. Call this method if next/finish should be - * disabled. The passed string will be visible to the user, and should be a - * short, localized description of what is wrong. - */ - protected final void setProblem(String value) { - getController().setProblem(value); - } - - /** - * Set whether the finish, next or both buttons should be enabled, assuming - * no problem string is set. - * - * @param value WizardController.MODE_CAN_CONTINUE, - * WizardController.MODE_CAN_FINISH or - * WizardController.MODE_CAN_CONTINUE_OR_FINISH; - */ - protected final void setForwardNavigationMode(int value) { - getController().setForwardNavigationMode(value); - } - - /** - * Disable all navigation. Useful if some background task is being completed - * during which no navigation should be allowed. Use with care, as it - * disables the cancel button as well. - */ - protected final void setBusy(boolean busy) { - getController().setBusy(busy); - } - - /** - * Store a value in response to user interaction with a GUI component. - */ - protected final void putWizardData(Object key, Object value) { - getWizardDataMap().put(key, value); - if (!inBeginUIChanged && !inValidateContents) { - inValidateContents = true; - try { - setProblem(validateContents(null, null)); - } finally { - inValidateContents = false; - } - } - } - - /** - * Returns all of the keys in the wizard data map. - */ - protected final Object[] getWizardDataKeys() { - return getWizardDataMap().keySet().toArray(); - } - - /** - * Retrieve a value stored in the wizard map, which may have been - * putWizardData there by this panel or any previous panel in the wizard - * which contains this panel. - */ - protected final Object getWizardData(Object key) { - return getWizardDataMap().get(key); - } - - /** - * Determine if the wizard map contains the requested key. - */ - protected final boolean wizardDataContainsKey(Object key) { - return getWizardDataMap().containsKey(key); - } - - /** - * Called when an event is received from one of the components in the panel - * that indicates user input. Typically you won't need to touch this method, - * unless your panel contains custom components which are not subclasses of - * any standard Swing component, which the framework won't know how to - * listen for changes on. For such cases, attach a listener to the custom - * component, and call this method with the event if you want validation to - * run when input happens. Automatic updating of the settings map will not - * work for such custom components, for obvious reasons, so update the - * settings map, if needed, in validateContents for this case. - * - * @param source The component that the user interacted with (if it can be - * determined from the event) or null - * @param event Usually an instance of EventObject, except in the case of - * DocumentEvent. - */ - protected final void userInputReceived(Component source, Object event) { - if (inBeginUIChanged) - return; - - //Update the map no matter what - inBeginUIChanged = true; - - if (source != null) - try { - maybeUpdateMap(source); - } finally { - inBeginUIChanged = false; - } - - //Possibly some programmatic change from checkState could cause - //a recursive call - if (inUiChanged) - return; - - inUiChanged = true; - inValidateContents = true; - try { - setProblem(validateContents(source, event)); - } finally { - inUiChanged = false; - inValidateContents = false; - } - } - - /** - * Puts the value from the component in the settings map if the component's - * name property is not null - */ - void maybeUpdateMap(Component comp) { - Object mapKey = getMapKeyFor(comp); - // debug: System.err.println("MaybeUpdateMap " + mapKey + " from " + comp); - if (mapKey != null) { - Object value = valueFrom(comp); - putWizardData(mapKey, value); - } - } - - /** - * Callback for GenericListener to remove a component's value if its name - * changes or it is removed from the panel. - */ - void removeFromMap(Object key) { - getWizardDataMap().remove(key); - } - - /** - * Given an ad-hoc swing component, fetch the likely value based on its - * state. The default implementation handles most common swing components. - * If you are using custom components and have assigned them names, override - * this method to handle getting an appropriate value out of your custom - * component and call super for the others. - */ - protected Object valueFrom(Component comp) { - if (ccl != null && ccl.accept(comp)) - return ccl.valueFor(comp); - if (comp instanceof JRadioButton || comp instanceof JCheckBox || comp instanceof JToggleButton) - return ((AbstractButton) comp).getModel().isSelected() ? Boolean.TRUE : Boolean.FALSE; - else if (comp instanceof JTree) { - TreePath path = ((JTree) comp).getSelectionPath(); - if (path != null) - return path.getLastPathComponent(); - } else if (comp instanceof JFormattedTextField) - return ((JFormattedTextField) comp).getValue(); - else if (comp instanceof JList) { - Object[] o = ((JList) comp).getSelectedValues(); - if (o.length > 1) - return o; - else if (o.length == 1) - return o[0]; - } else if (comp instanceof JTextComponent) - return ((JTextComponent) comp).getText(); - else if (comp instanceof JComboBox) - return ((JComboBox) comp).getSelectedItem(); - else if (comp instanceof JColorChooser) - return ((JColorChooser) comp).getSelectionModel().getSelectedColor(); - else if (comp instanceof JSpinner) - return ((JSpinner) comp).getValue(); - else if (comp instanceof JSlider) - return ((JSlider) comp).getValue(); - - return null; - } - - /** - * Given an ad-hoc swing component, set the value as the property from the - * settings. The default implementation handles most common swing - * components. If you are using custom components and have assigned them - * names, override this method to handle getting an appropriate value out of - * your custom component and call super for the others. - */ - protected void valueTo(Map settings, Component comp) { - String name = comp.getName(); - Object value = settings.get(name); - if (comp instanceof JRadioButton || comp instanceof JCheckBox || comp instanceof JToggleButton) { - if (value instanceof Boolean) - ((AbstractButton) comp).getModel().setSelected(((Boolean) value)); -// TOFIX: JTree - } else if (comp instanceof JFormattedTextField) - ((JFormattedTextField) comp).setValue(value); // } else if (comp instanceof JTree) { - // TreePath path = ((JTree) comp).getSelectionPath(); - // if (path != null) { - // return path.getLastPathComponent(); - // } - else if (comp instanceof JList) { - if (value instanceof Object[]) - throw new IllegalArgumentException("can't handle multi-select lists"); - ((JList) comp).setSelectedValue(value, true); - } else if (comp instanceof JTextComponent) - ((JTextComponent) comp).setText((String) value); - else if (comp instanceof JComboBox) - ((JComboBox) comp).setSelectedItem(value); - else if (comp instanceof JColorChooser) - ((JColorChooser) comp).getSelectionModel().setSelectedColor((Color) value); - else if (comp instanceof JSpinner) - ((JSpinner) comp).setValue(value); - else if (comp instanceof JSlider) - ((JSlider) comp).setValue(((Integer) value)); - } - - /** - * Get the map key that should be used to automatically put the value - * represented by this component into the wizard data map. - *

    - * The default implementation returns the result of - * c.getName(), which is almost always sufficient and - * convenient - just set the component names in a GUI builder and everything - * will be handled. - * - * @return null if the component's value should not be automatically written - * to the wizard data map, or an object which is the key that later code - * will use to find this value. By default, it returns the component's name. - */ - protected Object getMapKeyFor(Component c) { - if (ccl != null && ccl.accept(c)) - return ccl.keyFor(c); - else - return c.getName(); - } - - /** - * Called when user interaction has occurred on a component contained by - * this panel or one of its children. Override this method to check if all - * of the values are legal, such that the Next/Finish button should be - * enabled, optionally calling setForwardNavigationMode() if - * warranted. - *

    - * This method also may be called with a null argument an effect of calling - * putWizardData() from someplace other than within this - * method. - *

    - * Note that this method may be called very frequently, so it is important - * that validation code be fast. For cases such as - * DocumentEvents, it may be desirable to delay validation with - * a timer, if the implementation of this method is too expensive to call on - * each keystroke. - *

    - * Either the component, or the event, or both may be null on some calls to - * this method (such as when it is called because the settings map has been - * written to). - *

    - * The default implementation returns null. - * - * @param component The component the user interacted with, if it can be - * determined. The infrastructure does track the owners of list models and - * such, and can find the associated component, so this will usually (but - * not necessarily) be non-null. - * @param event The event object (if any) that triggered this call to - * validateContents. For most cases this will be an instance of EventObject, - * and can be used to directly detect what component the user interacted - * with. Since javax.swing.text.DocumentEvent is not a subclass of - * EventObject, the type of the argument is Object, so these events may be - * passed. - * - * @return A localized string describing why navigation should be disabled, - * or null if the state of the components is valid and forward navigation - * should be enabled. - */ - protected String validateContents(Component component, Object event) { - return null; - } - - /** - * Called if the user is navigating into this panel when it has already been - * displayed at least once - the user has navigated back to this panel, or - * back past this panel and is now navigating forward again. - *

    - * If some of the UI needs to be set up based on values from earlier pages - * that may have changed, do that here, fetching values from the settings - * map by calling getWizardData(). - *

    - * The default implementation simply calls - * validateContents (null, null). - */ - protected void recycle() { - setProblem(validateContents(null, null)); - } - - /** - * Get the settings map into which the wizard gathers settings. Return value - * will never be null. - */ - // the map is empty during construction, then later set to the map from the containing WizardController - protected Map getWizardDataMap() { - if (wizardData == null) - wizardData = new HashMap(); - return wizardData; - } - - private String longDescription; - - /** - * Set the long description of this page. This method may be called only - * once and should be called from within the constructor. - * - * @param desc The long description for this step - */ - protected void setLongDescription(String desc) { - if (!Beans.isDesignTime() && this.longDescription != null) - throw new IllegalStateException("Long description already set to" - + " " + desc); - this.longDescription = desc; - } - - /** - * Get the long description of this page, which should be used in the title - * area of the wizard's UI if non-null. To use, call setLongDescription() in - * your WizardPage's constructor. It may be set only once. - * - * @return the description - */ - public final String getLongDescription() { - return longDescription; - } - - static WizardPanelProvider createWizardPanelProvider(WizardPage page) { - return new WPP(new WizardPage[] { page }, WizardResultProducer.NO_OP); - } - - static WizardPanelProvider createWizardPanelProvider(WizardPage[] page) { - return new WPP(page, WizardResultProducer.NO_OP); - } - - /** - * WizardPanelProvider that takes an array of already created WizardPages - */ - static final class WPP extends WizardPanelProvider { - - private final WizardPage[] pages; - private final WizardResultProducer finish; - - WPP(WizardPage[] pages, WizardResultProducer finish) { - super(Util.getSteps(pages), Util.getDescriptions(pages)); - - //Fail-fast validation - don't wait until something goes wrong - //if the data are bad - // assert valid(pages) == null : valid(pages); - // assert finish != null; - String v = valid(pages); - if (v != null) - throw new RuntimeException(v); - if (finish == null) - throw new RuntimeException("finish must not be null"); - - this.pages = pages; - this.finish = finish; - } - - WPP(String title, WizardPage[] pages, WizardResultProducer finish) { - super(title, Util.getSteps(pages), Util.getDescriptions(pages)); - - //Fail-fast validation - don't wait until something goes wrong - //if the data are bad - // assert valid(pages) == null : valid(pages); - // assert finish != null; - String v = valid(pages); - if (v != null) - throw new RuntimeException(v); - if (finish == null) - throw new RuntimeException("finish must not be null"); - - this.pages = pages; - this.finish = finish; - } - - @Override - protected JComponent createPanel(WizardController controller, String id, - Map wizardData) { - int idx = indexOfStep(id); - - // assert idx != -1 : "Bad ID passed to createPanel: " + id; - if (idx == -1) - throw new RuntimeException("Bad ID passed to createPanel: " + id); - pages[idx].setController(controller); - pages[idx].setWizardDataMap(wizardData); - - return pages[idx]; - } - - /** - * Make sure we haven't been passed bogus data - */ - private String valid(WizardPage[] pages) { - if (ArrayUtils.hasDuplicateElements(pages)) - return "Duplicate entry in array: " - + Arrays.asList(pages); - - for (int i = 0; i < pages.length; i++) - if (pages[i] == null) - return "Null entry at " + i + " in pages array"; - - return null; - } - - @Override - protected Object finish(Map settings) throws WizardException { - return finish.finish(settings); - } - - @Override - public boolean cancel(Map settings) { - return finish.cancel(settings); - } - - @Override - public String getLongDescription(String stepId) { - for (WizardPage wizardPage : pages) - if (stepId.equals(wizardPage.getID())) - return wizardPage.getLongDescription(); - return null; - } - } - - /** - * WizardPanelProvider that takes an array of WizardPage subclasses and - * instantiates them on demand - */ - private static final class CWPP extends WizardPanelProvider { - - private final Class[] classes; - private final WizardResultProducer finish; - private final String[] longDescriptions; - - CWPP(String title, Class[] classes, WizardResultProducer finish) { - super(title, Util.getSteps(classes), Util.getDescriptions(classes)); - _validateArgs(classes, finish); - this.finish = finish; - this.classes = classes; - longDescriptions = new String[classes.length]; - } - - private void _validateArgs(Class[] classes, WizardResultProducer finish) { - Objects.requireNonNull(classes, "Class array may not be null"); - Objects.requireNonNull(finish, "WizardResultProducer may not be null"); - if (ArrayUtils.hasDuplicateElements(classes)) - throw new RuntimeException("Duplicate entries in class array"); - } - - CWPP(Class[] classes, WizardResultProducer finish) { - super(Util.getSteps(classes), Util.getDescriptions(classes)); - longDescriptions = new String[classes.length]; - _validateArgs(classes, finish); - - this.classes = classes; - this.finish = finish; - } - - @Override - protected JComponent createPanel(WizardController controller, String id, Map wizardData) { - int idx = indexOfStep(id); - - // assert idx != -1 : "Bad ID passed to createPanel: " + id; - if (idx == -1) - throw new RuntimeException("Bad ID passed to createPanel: " + id); - try { - WizardPage result = (WizardPage) classes[idx].newInstance(); - longDescriptions[idx] = result.getLongDescription(); - - result.setController(controller); - result.setWizardDataMap(wizardData); - - return result; - } catch (IllegalAccessException | InstantiationException e) { - // really IllegalArgumentException, but we need to have the "cause" get shown in stack trace - throw new RuntimeException("Could not instantiate " - + classes[idx], e); - } - } - - @Override - protected Object finish(Map settings) throws WizardException { - return finish.finish(settings); - } - - @Override - public boolean cancel(Map settings) { - return finish.cancel(settings); - } - - @Override - public String toString() { - return super.toString() + " for " + finish; - } - - @Override - public String getLongDescription(String stepId) { - int idx = indexOfStep(stepId); - if (idx != -1) - return longDescriptions[idx] == null ? descriptions[idx] - : longDescriptions[idx]; - return null; - } - } - - /** - * A dummy wizard controller which is used until the panel has actually been - * put into use; so state can be set during the constructor, etc. Its state - * will be dumped into the real one once there is a real one. - */ - private static final class WC implements WizardControllerImplementation { - - private String problem = null; - private int canFinish = -1; - private Boolean busy = null; - - @Override - public void setProblem(String value) { - this.problem = value; - } - - @Override - public void setForwardNavigationMode(int value) { - switch (value) { - case WizardController.MODE_CAN_CONTINUE: - case WizardController.MODE_CAN_FINISH: - case WizardController.MODE_CAN_CONTINUE_OR_FINISH: - break; - default: - throw new IllegalArgumentException(Integer.toString(value)); - } - - canFinish = value; - } - - @Override - public void setBusy(boolean busy) { - this.busy = busy ? Boolean.TRUE : Boolean.FALSE; - } - - void configure(WizardController other) { - if (other == null) - return; - - if (busy != null) - other.setBusy(busy); - - if (canFinish != -1) - other.setForwardNavigationMode(canFinish); - - if (problem != null) - other.setProblem(problem); - } - } - - /** - * Interface that is passed to WizardPage.createWizard(). For wizards - * created from a set of WizardPages or WizardPage subclasses, this is the - * object that whose code will be run to create or do whatever the wizard - * does when the user clicks the Finish button. - */ - public static interface WizardResultProducer { - - /** - * Conclude a wizard, doing whatever the wizard does with the data - * gathered into the map on the various panels. - *

    - * If an instance of Summary is returned from this method, - * the UI shall display it on a final page and disable all navigation - * buttons except the Close/Cancel button. - *

    - * If an instance of DeferredWizardResult is returned from - * this method, the UI shall display some sort of progress bar while the - * result is computed in the background. If that - * DeferredWizardResult produces a Summary - * object, that summary shall be displayed as described above. - * - * @param wizardData the map with key-value pairs which has been - * populated by the UI as the user progressed through the wizard - * - * @return an object composed based on what the user entered in the - * wizard - somethingmeaningful to whatever code invoked the wizard, or - * null. Note special handling if an instance of - * DeferredWizardResult or Summary is returned - * from this method. - */ - Object finish(Map wizardData) throws WizardException; - - /** - * Called when the user presses the cancel button. Almost all - * implementations will want to return true. - */ - boolean cancel(Map settings); - - /** - * A no-op WizardResultProducer that returns null. - */ - WizardResultProducer NO_OP = new WizardResultProducer() { - @Override - public Object finish(Map wizardData) { - return wizardData; - } - - @Override - public boolean cancel(Map settings) { - return true; - } - - @Override - public String toString() { - return "NO_OP WizardResultProducer"; - } - }; - } - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardPanel.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardPanel.java deleted file mode 100644 index 55bf5eaba..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardPanel.java +++ /dev/null @@ -1,97 +0,0 @@ -/* The contents of this file are subject to the terms of the Common Development -and Distribution License (the License). You may not use this file except in -compliance with the License. - You can obtain a copy of the License at http://www.netbeans.org/cddl.html -or http://www.netbeans.org/cddl.txt. - When distributing Covered Code, include this CDDL Header Notice in each file -and include the License file at http://www.netbeans.org/cddl.txt. - */ -package org.jackhuang.hmcl.util.ui.wizard.spi; - -import java.util.Map; - -/** - * This is an optional interface for panels that want to be notified when - * the next and back buttons are pressed. - * - * The WizardPanelProvider is NOT required to create panels that implement - * this interface. - * - * Each of these methods returns a WizardPanelNavResult that can be used to - * indicate PROCEED or REMAIN_ON_PAGE. - * - * The result can also be an instance of a subclass of WizardPanelNavResult - * that implements the start method to use a background thread - * to determine if the next page can be shown. - * - * @author stanley@stanleyknutson.com - */ -public interface WizardPanel { - - /** - * This method is invoked when the "next" button has been pushed, - * to do a final validation of input (such as doing a database login). - * - * If this method return false, then the "next" button will not change the - * displayed panel. Presumably some error will have been shown to the user. - * - * @param stepName - * @param settings - * @param wizard - * - * @return WizardPanelNavResult.PROCEED if the "next" button should proceed, - * WizardPanelNavResult.REMAIN_ON_PAGE if "next" should not proceed, - * or a instance of subclass of WizardPanelResult that will do some - * background computation - * and call the progress.finished method with one of those constants - * (or call progress.failed with the error message) - */ - public WizardPanelNavResult allowNext(String stepName, Map settings, Wizard wizard); - - /** - * This method is invoked when the "back" button has been pushed, - * to discard any data from the setings that will not been needed and for - * which the - * normal "just hide that data" is not the desired behavior. - * (See MergeMap for discussion of the "hide the data" behavior) - * - * If this method return false, then the "next" button will not change the - * displayed panel. Presumably some error will have been shown to the user. - * - * @param stepName - * @param settings - * @param wizard - * - * @return WizardPanelNavResult.PROCEED if the "back" button should proceed, - * WizardPanelNavResult.REMAIN_ON_PAGE if "back" should not proceed, - * or a instance of subclass of WizardPanelResult that will do some - * background computation - * and call the progress.finished method with one of those constants. - * (or call progress.failed with the error message) - */ - public WizardPanelNavResult allowBack(String stepName, Map settings, Wizard wizard); - - /** - * This method is invoked when the "finish" button has been pushed, - * to allow veto of the finish action BEFORE the wizard finish method is - * invoked. - * - * If this method return false, then the "finish" button will have no - * effect. - * Presumably some error will have been shown to the user. - * - * @param stepName - * @param settings - * @param wizard - * - * @return WizardPanelNavResult.PROCEED if the "finish" button should - * proceed, - * WizardPanelNavResult.REMAIN_ON_PAGE if "finish" should not proceed, - * or a instance of subclass of WizardPanelResult that will do some - * background computation - * and call the progress.finished method with one of those constants. - * (or call progress.failed with the error message) - */ - public WizardPanelNavResult allowFinish(String stepName, Map settings, Wizard wizard); - -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardPanelNavResult.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardPanelNavResult.java deleted file mode 100644 index 09b0e3ccc..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardPanelNavResult.java +++ /dev/null @@ -1,70 +0,0 @@ -/* The contents of this file are subject to the terms of the Common Development -and Distribution License (the License). You may not use this file except in -compliance with the License. - You can obtain a copy of the License at http://www.netbeans.org/cddl.html -or http://www.netbeans.org/cddl.txt. - When distributing Covered Code, include this CDDL Header Notice in each file -and include the License file at http://www.netbeans.org/cddl.txt. - */ -package org.jackhuang.hmcl.util.ui.wizard.spi; - -import java.util.Map; - -/** - * Result class for the methods in WizardPanel. - * - * For immediate action, one of the two constantants PROCEED or REMAIN_ON_PAGE - * should be returned. Otherwise an instance of a subclass should be returned - * that computes a Boolean result. - * - * @author stanley@stanleyknutson.com - */ -public abstract class WizardPanelNavResult extends DeferredWizardResult { - - /** - * value for procced to next step in the wizard. - */ - public static final WizardPanelNavResult PROCEED = new WPNRimmediate(true); - /** - * Value to remain on the current page in the wizard - */ - public static final WizardPanelNavResult REMAIN_ON_PAGE = new WPNRimmediate(false); - - private WizardPanelNavResult() { - super(); - } - - public boolean isDeferredComputation() { - return true; - } - - /* - * internal class for the constants only - */ - private final static class WPNRimmediate extends WizardPanelNavResult { - - boolean value; - - WPNRimmediate(boolean v) { - value = v; - } - - public boolean isDeferredComputation() { - return false; - } - - public boolean equals(Object o) { - return o instanceof WPNRimmediate && ((WPNRimmediate) o).value == value; - } - - public int hashCode() { - return value ? 1 : 2; - } - - public void start(Map settings, ResultProgressHandle progress) { - // Should never get here, this is supposed to be immediate! - throw new RuntimeException("Immediate result was called as deferral!"); - } - - } -} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardPanelProvider.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardPanelProvider.java deleted file mode 100644 index b98953f03..000000000 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ui/wizard/spi/WizardPanelProvider.java +++ /dev/null @@ -1,312 +0,0 @@ -/* The contents of this file are subject to the terms of the Common Development -and Distribution License (the License). You may not use this file except in -compliance with the License. - You can obtain a copy of the License at http://www.netbeans.org/cddl.html -or http://www.netbeans.org/cddl.txt. - When distributing Covered Code, include this CDDL Header Notice in each file -and include the License file at http://www.netbeans.org/cddl.txt. -If applicable, add the following below the CDDL Header, with the fields -enclosed by brackets [] replaced by your own identifying information: -"Portions Copyrighted [year] [name of copyright owner]" */ - /* - * PanelProvider.java - * - * Created on March 5, 2005, 7:25 PM - */ -package org.jackhuang.hmcl.util.ui.wizard.spi; - -import java.util.Arrays; -import java.util.Map; -import java.util.Objects; -import javax.swing.JComponent; -import org.jackhuang.hmcl.util.ArrayUtils; - -/** - * (Note: WizardPage offers somewhat simpler functionality for - * creating a wizard than does WizardPanelProvider; the only advantage of - * WizardPanelProvider is that it does not require one to subclass - * a panel component). - *

    - * A simple interface for providing a fixed set of panels for a wizard. To use, - * simply implement createPanel() to create the appropriate UI - * component for a given step (a unique String ID - one of the ones passed in - * the constructor in the steps array), and implement - * finish() to do whatever should be done when the wizard is - * finished. - *

    - * To control whether the Next/Finish buttons are enabled, components created in - * createPanel() should call methods on the - * WizardController passed. The created panels should listen on the UI - * components they create, updating the settings Map when the user changes their - * input. - *

    - * Super-simple one-pane wizard example - if the checkbox is checked, the user - * can continue: - *

    - * public class MyProvider extends WizardPanelProvider {
    - *    public MyProvider() {
    - *       //here we pass a localized title for the wizard,
    - *       //the ID of the one step it will have, and a localized description
    - *       //the wizard can show for that one step
    - *       super ("Click the box", "click", "Click the checkbox");
    - *    }
    - *    protected JComponent createPanel (final WizardController controller, String id, final Map settings) {
    - *       //A quick sanity check
    - *       assert "click".equals (id);
    - *       //Remember this method will only be called once for any panel
    - *       final JCheckBox result = new JCheckBox();
    - *       result.addActionListener (new ActionListener() {
    - *          public void actionPerformed (ActionEvent ae) {
    - *             //Typically you want to write the result of some user
    - *             //action into the settings map as soon as they do it 
    - *             settings.put ("boxSelected", result.isSelected() ? Boolean.TRUE : Boolean.FALSE);
    - *             if (result.isSelected()) {
    - *                controller.setProblem(null);
    - *             } else {
    - *                controller.setProblem("The box is not checked");
    - *             }
    - *             controller.setCanFinish(true); //won't matter if we called setProblem() with non-null
    - *          }
    - *       });
    - *       return result;
    - *    }
    - *
    - *    protected Object finish (Map settings) throws WizardException {
    - *       //if we had some interesting information (Strings a user put in a
    - *       //text field or something, we'd generate some interesting object or
    - *       //create some files or something here
    - *       return null;
    - *    }
    - * }
    - * 
    - * - * @author Tim Boudreau - */ -public abstract class WizardPanelProvider { - - final String title; - final String[] descriptions; - final String[] steps; - final String[] knownProblems; - - /** - * Create a WizardPanelProvider. The passed array of steps and descriptions - * will be used as IDs and localized descriptions of the various steps in - * the wizard. Use this constructor (which passes not title) for sub-wizards - * used in a WizardBranchController, where the first pane will - * determine the title, and the titles of the sub-wizards will never be - * shown. - * - * @param steps A set of unique IDs identifying each step of this wizard. - * Each ID must occur only once in the array of steps. - * - * @param descriptions A set of human-readable descriptions corresponding - * 1:1 with the unique IDs passed as the steps parameter - */ - protected WizardPanelProvider(String[] steps, String[] descriptions) { - this(null, steps, descriptions); - } - - /** - * Create a WizardPanelProvider with the provided title, steps and - * descriptions. The steps parameter are unique IDs of panels, - * which will be passed to createPanel to create panels for - * various steps in the wizard, as the user navigates it. The - * descriptions parameter is a set of localized descriptions - * that can appear in the Wizard to describe each step. - * - * @param title A human readable title for the wizard dialog - * @param steps An array of unique IDs for the various panels of this wizard - * @param descriptions An array of descriptions corresponding 1:1 with the - * unique IDs. These must be human readable, localized strings. - */ - protected WizardPanelProvider(String title, String[] steps, String[] descriptions) { - this.title = title; - this.steps = steps; - this.descriptions = descriptions; - knownProblems = new String[steps.length]; - if (steps.length != descriptions.length) - throw new IllegalArgumentException("Length of steps and" - + " descriptions arrays do not match"); - // assert validData (steps, descriptions) == null : validData (steps, descriptions); - String v = validData(steps, descriptions); - if (v != null) - throw new RuntimeException(v); - } - - private String validData(String[] steps, String[] descriptions) { - if (steps.length != descriptions.length) - return steps.length + " steps but " + descriptions.length - + " descriptions"; - for (int i = 0; i < steps.length; i++) { - Objects.requireNonNull(steps[i], "Step id " + i + " is null"); - Objects.requireNonNull(descriptions[i], "Description " + i + " is null"); - } - if (ArrayUtils.hasDuplicateElements(steps)) - return "Duplicate step ids: " + Arrays.asList(steps); - return null; - } - - /** - * Convenience constructor to create a WizardPanelProvider which has only - * one step to it. Mainly useful for initial steps in a - * WizardBranchController. - * - * @param title A human readable title for the wizard dialog - * @param singleStep The unique ID of the only step this wizard has - * @param singleDescription The human-readable description of what the user - * should do in the one step of this one-step wizard or sub-wizard - */ - protected WizardPanelProvider(String title, String singleStep, String singleDescription) { - this(title, new String[] { singleStep }, new String[] { singleDescription }); - } - - /** - * Create a panel that represents a named step in the wizard. This method - * will be called exactly once in the life of a wizard. The panel - * should retain the passed settings Map, and add/remove values from it as - * the user enters information, calling setProblem() and - * setCanFinish() as appropriate in response to user input. - * - * @param controller - the object which controls whether the Next/Finish - * buttons in the wizard are enabled, and what instructions are displayed to - * the user if they are not - * @param id The name of the step, one of the array of steps passed in the - * constructor - * @param settings A Map containing settings from earlier steps in the - * wizard. It is safe to retain a reference to this map and put values in it - * as the user manipulates the UI; the reference should be refreshed - * whenever this method is called again. - * @return A JComponent that should be displayed in the center of the wizard - */ - protected abstract JComponent createPanel(WizardController controller, String id, Map settings); - - /** - * Instantiate whatever object (if any) the wizard creates from its gathered - * data. The default implementation is a no-op that returns null. - *

    - * If an instance of Summary is returned from this method, the - * UI shall display it on a final page and disable all navigation buttons - * except the Close/Cancel button. - *

    - * If an instance of DeferredWizardResult is returned from this - * method, the UI shall display some sort of progress bar while the result - * is computed in the background. If that DeferredWizardResult - * produces a Summary object, that summary shall be displayed - * as described above. - *

    - * The default implementation returns the settings map it is passed. - * - * @param settings The settings map, now fully populated with all settings - * needed to complete the wizard (this method will only be called if - * setProblem(null) and setCanFinish(true) have - * been called on the WizardController passed to - * createPanel(). - * @return an object composed based on what the user entered in the wizard - - * somethingmeaningful to whatever code invoked the wizard, or null. Note - * special handling if an instance of DeferredWizardResult or - * Summary is returned from this method. - */ - protected Object finish(Map settings) throws WizardException { - return settings; - } - - /** - * The method provides a chance to call setProblem() or setCanFinish() when - * the user re-navigates to a panel they've already seen - in the case that - * the user pressed the Previous button and then the Next button. - *

    - * The default implementation does nothing, which is sufficient for most - * cases. If whether this panel is valid or not could have changed because - * of changed data from a previous panel, or it displays data entered on - * previous panes which may have changed, you may want to override this - * method to ensure validity and canFinish are set correctly, and that the - * components have the correct text. - *

    - * This method will not be called when a panel is first instantiated - * - createPanel() is expected to set validity and canFinish - * appropriately. - *

    - * The settings Map passed to this method will always be the same Settings - * map instance that was passed to createPanel() when the panel - * was created. - *

    - * If you are implementing WizardPanelProvider and some of the pages are - * WizardPages, you should call the super implementation if you - * override this method. - */ - protected void recycleExistingPanel(String id, WizardController controller, Map wizardData, JComponent panel) { - //do nothing - } - - void recycle(String id, WizardController controller, Map wizardData, JComponent panel) { - if (panel instanceof WizardPage) { - WizardPage page = (WizardPage) panel; - page.setController(controller); - page.setWizardDataMap(wizardData); - page.recycle(); - } - recycleExistingPanel(id, controller, wizardData, panel); - } - - private Wizard wizard; - - /** - * Create a Wizard for this PanelProvider. The instance created by this - * method is cached and the same instance will be returned on subsequent - * calls. - */ - public final Wizard createWizard() { - if (wizard == null) - wizard = new Wizard(new SimpleWizard(this)); - return wizard; - } - - /** - * This method can optionally be overridden to provide a longer description - * of a step to be shown in the top of its panel. The default implementation - * returns null, indicating that the short description should be used. - * - * @param stepId a unique id for one step of the wizard - * @return An alternate description for use in the top of the wizard page - * when this page is the current one, or null - */ - public String getLongDescription(String stepId) { - return null; - } - - /** - * Convenience method to get the index into the array of steps passed to the - * constructor of a specific step id. - */ - protected final int indexOfStep(String id) { - return Arrays.asList(steps).indexOf(id); - } - - void setKnownProblem(String problem, int idx) { - //Record a problem message so we can put it back if the user does - //prev and then next - if (idx >= 0) //setProblem() can be called during initialization - knownProblems[idx] = problem; - } - - String getKnownProblem(int idx) { - return knownProblems[idx]; - } - - /** - * Called if the user invokes cancel. The default impl returns true. - * - * @return false to abort cancellation (almost all implementations will want - * to return true - this is really only applicable in cases such as an OS - * installer or such). - */ - public boolean cancel(Map settings) { - return true; - } - - @Override - public String toString() { - return super.toString() + " with wizard " + wizard; - } -} diff --git a/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N.lang b/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N.lang deleted file mode 100644 index 0480601f9..000000000 --- a/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N.lang +++ /dev/null @@ -1,440 +0,0 @@ -# Hello Minecraft! Launcher. -# Copyright (C) 2013 huangyuhui -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see {http://www.gnu.org/licenses/}. -# -#author: huangyuhui, dxNeil -launch.failed=Failed to launch. -launch.failed_creating_process=Failed to create process, maybe your java path is wrong, please modify your java path. -launch.failed_sh_permission=Failed to add permission to the launch script. -launch.failed_packing_jar=Failed to pack the jar. -launch.unsupported_launcher_version=Sorry, the launcher cannot launch minecraft, but will retry launching it. -launch.too_big_memory_alloc_64bit=You have allocated too much memory, because of your 32-Bit Java Runtime Environment, your game probably crash. The maximum memory is 1024MB. The launcher will try to launch it. -launch.too_big_memory_alloc_free_space_too_low=You have allocated too much memory, because the physical memory size is %dMB, your game probably crash. The launcher will try to launch it. -launch.cannot_create_jvm=We find that it cannot create java virutal machine. The Java argements may have problems. You can enable the no args mode in the settings. -launch.circular_dependency_versions=Found circular dependency versions, please check if your client has been modified. -launch.not_finished_downloading_libraries=Did not finish downloading libraries, continue launching game? -launch.not_finished_decompressing_natives=Did not finish decompressing native libraries, continue launching game? -launch.wrong_javadir=Incorrect Java directory, will reset to default Java directory. -launch.exited_abnormally=Game exited abnormally, please visit the log, or ask someone for help. - -launch.state.logging_in=Logging In -launch.state.generating_launching_codes=Generating Launching Codes -launch.state.downloading_libraries=Downloading dependencies -launch.state.decompressing_natives=Decompressing natives -launch.state.waiting_launching=Waiting for game launching - -install.no_version=The version is not found. -install.no_version_if_intall=The required version is not found, do you wish to install the version automatically? -install.not_refreshed=The installer list is not refreshed. -install.download_list=Download List - -install.liteloader.get_list=Get LiteLoader List -install.liteloader.install=Install LiteLoader - -install.forge.get_list=Get Forge List -install.forge.install=Install Forge -install.forge.get_changelogs=Get Forge Changelogs - -install.optifine.install=Install OptiFine -install.optifine.get_list=Get OptiFine Download List -install.optifine.get_download_link=Get the Download Link of OptiFine - -install.failed_forge=Failed to install 'Forge'. -install.failed_optifine=Failed to install 'OptiFine'. -install.failed_liteloader=Failed to install 'LiteLoader'. -install.failed_download_forge=Failed to download 'Forge'. -install.failed_download_optifine=Failed to download 'OptiFine'. -install.failed=Failed to install -install.success=Install successfully -install.no_forge=No Forge -install.choose_forge=Choose the version you want to install Forge -install.version=Version -install.mcversion=Game Version -install.time=Time -install.release_time=Release Time -install.type=Type -install.please_refresh=If you want to install something please click "Refresh" button. - -crash.launcher=Launcher has crashed! -crash.minecraft=Minecraft has crashed! - -login.choose_charactor=Please choose the character you want -login.no_charactor=No character in this account. -login.your_password=Your password -login.failed=Failed to login -login.no_Player007=You have not set a username! -login.wrong_password=Incorrect password or username -login.invalid_username=Invalid username -login.invalid_uuid_and_username=Invalid UUID and username -login.invalid_password=Invalid password -login.invalid_access_token=Invalid Access Token -login.changed_client_token=The server response has changed the client token. -login.not_email=The username must be a e-mail. -login.type=Login -login.username=Name -login.account=Email -login.invalid_token=Please log out and re-input your password to log in. -login.no_valid_character=No valid character, please visit skinme.cc and create your own character. - -proxy.username=Account -proxy.password=Password -proxy.host=Host -proxy.port=Port - -login.failed.connect_authentication_server=Cannot connect the authentication server. Check your network. - -login.profile.not_logged_in=You are not logged in, you can't modify the profile! -login.profile.selected=Can't modify the profile, logout and go retry. - -login.methods.yggdrasil=Mojang -login.methods.offline=Offline -login.methods.no_method=No login method - -log.playername_null=The player name is empty. - -minecraft.no_selected_version=No selected Minecraft version -minecraft.wrong_path=Wrong Minecraft path, the launcher could not find the path. - -operation.stopped=The operation was aborted. -operation.confirm_stop=Terminate the operations? - -ui.login.password=Password -ui.more=More - -crash.advice.UnsupportedClassVersionError=Maybe your java is too old, try to update the java. -crash.advice.ConcurrentModificationException=Maybe your Java is newer than 1.8.0_11, you could downgrade to Java 7. -crash.advice.ClassNotFoundException=Minecraft or mods are incomplete. Retry if there are some libraries that have not downloaded or update your game and mods! Or you can try Game Settings -> Manage (Version) -> Delete library files to solve the problem. -crash.advice.NoSuchFieldError=Minecraft or mods are incomplete. Retry if there are some libraries that have not downloaded or update your game and mods! -crash.advice.LWJGLException=Maybe your video driver does not work well, please update your video driver. -crash.advice.SecurityException=Maybe you have modified minecraft.jar but have not removed the META-INF. -crash.advice.OutOfMemoryError=The maximum memory of JVM is too small, please modify it. -crash.advice.otherwise=Maybe mods caused problems. - -crash.advice.OpenGL=Maybe drivers caused problems. -crash.advice.no_lwjgl=Maybe drivers caused problems. - -crash.advice.no=No advice. - -crash.user_fault=Your OS or Java environment may not be properly installed resulting in crashing of this software, please check your Java Environment or your computer! -crash.headless=If your OS is Linux, please use Oracle JDK instead of OpenJDK, or add "-Djava.awt.headless=false" JVM argument, or check if your Xserver works normally. -crash.NoClassDefFound=Please check "HMCL" software is complete. - -crash.error=Minecraft has crashed. -crash.main_class_not_found=Main Class is not found, may be your mc has been broken. -crash.class_path_wrong=Maybe the launch script is malformed. - -ui.label.newProfileWindow.new_profile_name=New Profile Name: -ui.label.newProfileWindow.copy_from=Copy From: -ui.newProfileWindow.title=New Config - -ui.button.ok=OK -ui.button.refresh=Refresh -ui.button.run=Play -ui.button.settings=Settings -ui.button.about=About -ui.button.others=Others -ui.button.logout=Log Out -ui.button.download=Download -ui.button.retry=Retry -ui.button.delete=Delete -ui.button.install=Install -ui.button.info=Info -ui.button.save=Save -ui.button.copy=Copy -ui.button.clear=Clear -ui.button.close=Close -ui.button.explore=Explore -ui.button.test=Test -ui.button.preview=Preview -button.cancel=Cancel -button.ok=OK -button.yes=Yes -button.no=No - -ui.label.version=Version -ui.label.password=Password -ui.label.profile=Profile - -ui.message.first_load=Please enter your name. -ui.message.enter_password=Please enter your password. -ui.message.launching=Launching... -ui.message.making=Generating... -ui.message.sure_remove=Sure to remove profile %s? -ui.message.update_java=Please upgrade your Java. -ui.message.open_jdk=We have found that you started this application using OpenJDK, which will cause so many troubles drawing the UI. We suggest you using Oracle JDK instead. - -ui.label.settings=Settings -ui.label.crashing=Hello Minecraft! Launcher has crashed! -ui.label.crashing_out_dated=Hello Minecraft! Launcher has crashed! Your launcher is outdated. Update it! -ui.label.failed_set=Failed to set: - -download=Download -download.mojang=Mojang -download.BMCL=BMCLAPI (bangbang93, http://bmclapi.bangbang93.com/) -download.rapid_data=RapidData (https://www.rapiddata.org/) -download.not_200=Failed to download, the response code -download.failed=Failed to download -download.successfully=Downloaded successfully -download.source=Download Source - -message.error=Error -message.cannot_open_explorer=Cannot open explorer: -message.cancelled=Cancelled -message.info=Info -message.loading=Loading... - -folder.game=Game Dir -folder.mod=Mod -folder.coremod=Core Mod -folder.config=Configs -folder.resourcepacks=Resourcepacks -folder.screenshots=Screenshots -folder.saves=Saves - -settings.tabs.game_download=Games -settings.tabs.installers=Installers -settings.tabs.assets_downloads=Assets - -settings=Settings -settings.explore=Explore -settings.manage=Manage -settings.cannot_remove_default_config=Cannot remove the default configution. -settings.max_memory=Max Memory/MB -settings.java_dir=Java Dir -settings.game_directory=Game Directory -settings.dimension=Game Window Dimension -settings.fullscreen=Fullscreen -settings.update_version=Update version json. -settings.run_directory=Run Directory(Version Isolation) -settings.physical_memory=Physical Memory Size -settings.choose_javapath=Choose Java Directory. -settings.default=Default -settings.custom=Custom -settings.choose_gamedir=Choose Game Directory -settings.failed_load=Failed to load settings file. Remove it? -settings.test_game=Test game - -settings.type.none=No version here, please turn to game download tab. -settings.type.global=Click here to switch to version specialized setting. Now it is global setting. -settings.type.special=Click here to switch to global setting. Not it is version specialized setting. - -modpack=Mod pack -modpack.choose=Choose a modpack zip file which you want to import. If you want to update the modpack, please enter the version you want to update. -modpack.export_error=Failed to export the modpack, maybe the format of your game directory is incorrect or failed to manage files. -modpack.export_finished=Exporting the modpack finished. See -modpack.included_launcher=The modpack is included the launcher, you can publish it directly. -modpack.not_included_launcher=You can use the modpack by clicking the "Import Modpack" button. -modpack.enter_name=Enter your desired name for this game. - -modpack.task.save=Export Modpack -modpack.task.install=Import Modpack -modpack.task.install.error=Failed to install the modpack. Maybe the files is incorrect, or a management issue occurred. -modpack.task.install.will=Install the modpack: - -modpack.wizard=Exporting the modpack wizard -modpack.wizard.step.1=Basic options -modpack.wizard.step.1.title=Set the basic options to the modpack. -modpack.wizard.step.initialization.include_launcher=Include the launcher -modpack.wizard.step.initialization.exported_version=The exported game version -modpack.wizard.step.initialization.save=Choose a location to export the game files to -modpack.wizard.step.initialization.warning=Before making modpack, you should ensure that your game can launch successfully,
    and that your Minecraft is release, not snapshot.
    and that it is not allowed to add mods which is not allowed to distribute to the modpack. -modpack.wizard.step.2=Files selection -modpack.wizard.step.2.title=Choose the files you do not want to put in the modpack. -modpack.wizard.step.3=Description -modpack.wizard.step.3.title=Describe your modpack. - -modpack.desc=Describe your modpack, including precautions, changlog, supporting Markdown(also supporting online pictures). -modpack.incorrect_format.no_json=The format of the modpack is incorrect, pack.json is missing. -modpack.incorrect_format.no_jar=The format of the modpack is incorrect, pack.json does not have attribute 'jar' -modpack.cannot_read_version=Failed to gather the game version -modpack.not_a_valid_location=Not a valid modpack location -modpack.name=Modpack Name -modpack.not_a_valid_name=Not a valid modpack name - -modpack.files.servers_dat=Multiplayer servers list -modpack.files.saves=Saved games -modpack.files.mods=Mods -modpack.files.config=Mod configs -modpack.files.liteconfig=Mod configurations -modpack.files.resourcepacks=Resource(Texture) packs -modpack.files.options_txt=Game options -modpack.files.optionsshaders_txt=Shaders options -modpack.files.mods.voxelmods=VoxelMods (including VoxelMap) options -modpack.files.dumps=NEI debug output -modpack.files.scripts=MineTweaker configuration -modpack.files.blueprints=BuildCraft blueprints - -mods=Mods -mods.choose_mod=Choose your mods -mods.failed=Failed to add mods -mods.add=Add -mods.remove=Remove -mods.default_information=Please ensure that you have installed Forge or LiteLoader before installing mods!
    You can drop your mod files from explorer/finder, and delete mods by the delete button.
    Disable a mod by leaving the check box unchecked; Choose an item to get the information.
    - -advancedsettings=Advanced -advancedsettings.launcher_visible=Launcher Visibility -advancedsettings.debug_mode=Debug Mode -advancedsettings.java_permanent_generation_space=PermGen Space/MB -advancedsettings.jvm_args=Java VM Arguments -advancedsettings.Minecraft_arguments=Minecraft Arguments -advancedsettings.launcher_visibility.close=Close the launcher when the game launched. -advancedsettings.launcher_visibility.hide=Hide the launcher when the game launched. -advancedsettings.launcher_visibility.keep=Keep the launcher visible. -advancedsettings.launcher_visibility.hide_reopen=Hide the launcher and re-open when game closes. -advancedsettings.game_dir.default=Default (.minecraft/) -advancedsettings.game_dir.independent=Independent (.minecraft/versions//, except assets,libraries) -advancedsettings.no_jvm_args=No Default JVM Args -advancedsettings.no_common=Not using common path -advancedsettings.java_args_default=Default java args: -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode -XX:-UseAdaptiveSizePolicy -XX:MaxPermSize=???m -Xmx???m -Dfml.ignoreInvalidMinecraftCertificates=true -Dfml.ignorePatchDiscrepancies=true -advancedsettings.wrapper_launcher=Wrapper Launcher(like optirun...) -advancedsettings.precall_command=Precalling command(will be executed before game launching) -advancedsettings.server_ip=Server Host -advancedsettings.cancel_wrapper_launcher=Cancel Wrapper Launcher -advancedsettings.dont_check_game_completeness=Don't check game completeness - -mainwindow.show_log=Show Logs -mainwindow.make_launch_script=Make Launching Script. -mainwindow.make_launch_script_failed=Failed to make script. -mainwindow.enter_script_name=Enter the script name. -mainwindow.make_launch_succeed=Finished script creation. -mainwindow.no_version=No version found. Switch to Game Downloads Tab? - -launcher.about=About Author
    Minecraft Forum ID: klkl6523
    Copyright (c) 2013 huangyuhui
    Opened source under GPL v3 license:http://github.com/huanghongxun/HMCL/
    This software used project Gson which is under Apache License 2.0, thanks contributors. -launcher.download_source=Download Source -launcher.background_location=Background Location -launcher.common_location=Common Location -launcher.exit_failed=Failed to shutdown. -launcher.versions_json_not_matched=The version %s is malformed! There are a json:%s in this version. Do you want to fix this problem? -launcher.versions_json_not_matched_cannot_auto_completion=The version %s lost version information file, delete it? -launcher.versions_json_not_formatted=The version information of %s is malformed! Redownload it? -launcher.choose_bgpath=Choose background path. -launcher.choose_commonpath=Choose common path. -launcher.commpath_tooltip=This app will save all game libraries and assets here unless there are existant files in game folder. -launcher.background_tooltip=The laucher uses a default background.
    If you use custom background.png, link it and it will be used.
    If there is "bg" subdirectory, this app will chooses one picture in "bgskin" randomly.
    If you set the background setting, this app will use it. -launcher.update_launcher=Check for update -launcher.enable_shadow=Enable Window Shadow -launcher.enable_animation=Enable Animation -launcher.enable_blur=Enable Blur -launcher.theme=Theme -launcher.proxy=Proxy -launcher.decorated=Enable system window border(in order to fix the problem that the ui become all gray in Linux OS) -launcher.modpack=Documentations for modpacks. -launcher.lang=Language -launcher.restart=Options will be in operations only if restart this app. -launcher.log_font=Log Font -launcher.tab.general=General -launcher.tab.ui=UI -launcher.tab.about=About - -launcher.title.game=Games -launcher.title.main=Home -launcher.title.launcher=Launcher - -versions.release=Release -versions.snapshot=Snapshot -versions.old_beta=Beta -versions.old_alpha=Old Alpha - -versions.manage.rename=Rename this version -versions.manage.rename.message=Please enter the new name -versions.manage.remove=Delete this version -versions.manage.remove.confirm=Sure to remove the version -versions.manage.redownload_json=Redownload Minecraft Configuration(minecraft.json) -versions.manage.redownload_assets_index=Redownload Assets Index -versions.mamage.remove_libraries=Delete library files - -advice.os64butjdk32=Your OS is 64-Bit but your Java is 32-Bit. The 64-Bit Java is recommended. -advice.java8=Java 8 is suggested, which can make game run more fluently. And many mods and Minecraft 1.12 and newer versions requires Java 8. - -assets.download_all=Download Assets Files -assets.not_refreshed=The assets list is not refreshed, please refresh it once. -assets.failed=Failed to get the list, try again. -assets.list.1_7_3_after=1.7.3 And higher -assets.list.1_6=1.6(BMCLAPI) -assets.unkown_type_select_one=Unknown game version: %s, please choose an asset type. -assets.type=Asset Type -assets.download=Download Assets -assets.no_assets=Assets are not complete, complete them? -assets.failed_download=Failed to download assets, may cause no sounds and language files. - -gamedownload.not_refreshed=The game list is not refreshed, please refresh it once. - -taskwindow.title=Tasks -taskwindow.single_progress=Single progress -taskwindow.total_progress=Total progress -taskwindow.cancel=Cancel -taskwindow.no_more_instance=Maybe you opened more than one task window, don't open it again! -taskwindow.file_name=Task -taskwindow.download_progress=Pgs. - -setupwindow.include_minecraft=Import game -setupwindow.find_in_configurations=Finished importing. You can find it in the configuration selection bar. -setupwindow.give_a_name=Give a name to the new game. -setupwindow.new=New -setupwindow.no_empty_name=Version name cannot be empty. -setupwindow.clean=Clean game files - -update.no_browser=Cannot open any browser. The link has been copied to the clipboard. Paste it to a browser address bar to update. -update.should_open_link=Are you willing to update the launcher? -update.newest_version=Newest version: -update.failed=Failed to check for updates. -update.found=(Found Update!) - -logwindow.terminate_game=Terminate Game -logwindow.title=Log -logwindow.contact=Contact Us -logwindow.show_lines=Show Lines -logwindow.search=Search - -selector.choose=Choose - -serverlistview.title=Choose a server -serverlistview.name=Name -serverlistview.type=Type -serverlistview.version=Version -serverlistview.info=Information - -minecraft.invalid=Invalid -minecraft.invalid_jar=Invalid Jar -minecraft.not_a_file=Not a file -minecraft.not_found=Not found -minecraft.not_readable=Not readable -minecraft.modified=(Modified!) - -color.red=Red -color.blue=Blue -color.green=Green -color.orange=Orange -color.dark_blue=Dark Blue -color.purple=Purple - -wizard.next_>=Next > -wizard.next_mnemonic=N -wizard.<_prev=< Prev -wizard.prev_mnemonic=P -wizard.finish=Finish -wizard.finish_mnemonic=F -wizard.cancel=Cancel -wizard.cancel_mnemonic=C -wizard.help=Help -wizard.help_mnemonic=H -wizard.close=Close -wizard.close_mnemonic=C -wizard.summary=Summary -wizard.failed=Failed -wizard.steps=Steps - -lang=English -lang.default=Belong to OS language. diff --git a/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N.properties b/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N.properties deleted file mode 100644 index ca52b6fae..000000000 --- a/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N.properties +++ /dev/null @@ -1,440 +0,0 @@ -# Hello Minecraft! Launcher. -# Copyright (C) 2013 huangyuhui -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see {http://www.gnu.org/licenses/}. -# -#author: huangyuhui, dxNeil -launch.failed=Failed to launch. -launch.failed_creating_process=Failed to create process, maybe your java path is wrong, please modify your java path. -launch.failed_sh_permission=Failed to add permission to the launch script. -launch.failed_packing_jar=Failed to pack the jar. -launch.unsupported_launcher_version=Sorry, the launcher cannot launch minecraft, but will retry launching it. -launch.too_big_memory_alloc_64bit=You have allocated too much memory, because of your 32-Bit Java Runtime Environment, your game probably crash. The maximum memory is 1024MB. The launcher will try to launch it. -launch.too_big_memory_alloc_free_space_too_low=You have allocated too much memory, because the physical memory size is %dMB, your game probably crash. The launcher will try to launch it. -launch.cannot_create_jvm=We find that it cannot create java virutal machine. The Java argements may have problems. You can enable the no args mode in the settings. -launch.circular_dependency_versions=Found circular dependency versions, please check if your client has been modified. -launch.not_finished_downloading_libraries=Did not finish downloading libraries, continue launching game? -launch.not_finished_decompressing_natives=Did not finish decompressing native libraries, continue launching game? -launch.wrong_javadir=Incorrect Java directory, will reset to default Java directory. -launch.exited_abnormally=Game exited abnormally, please visit the log, or ask someone for help. - -launch.state.logging_in=Logging In -launch.state.generating_launching_codes=Generating Launching Codes -launch.state.downloading_libraries=Downloading dependencies -launch.state.decompressing_natives=Decompressing natives -launch.state.waiting_launching=Waiting for game launching - -install.no_version=The version is not found. -install.no_version_if_intall=The required version is not found, do you wish to install the version automatically? -install.not_refreshed=The installer list is not refreshed. -install.download_list=Download List - -install.liteloader.get_list=Get LiteLoader List -install.liteloader.install=Install LiteLoader - -install.forge.get_list=Get Forge List -install.forge.install=Install Forge -install.forge.get_changelogs=Get Forge Changelogs - -install.optifine.install=Install OptiFine -install.optifine.get_list=Get OptiFine Download List -install.optifine.get_download_link=Get the Download Link of OptiFine - -install.failed_forge=Failed to install 'Forge'. -install.failed_optifine=Failed to install 'OptiFine'. -install.failed_liteloader=Failed to install 'LiteLoader'. -install.failed_download_forge=Failed to download 'Forge'. -install.failed_download_optifine=Failed to download 'OptiFine'. -install.failed=Failed to install -install.success=Install successfully -install.no_forge=No Forge -install.choose_forge=Choose the version you want to install Forge -install.version=Version -install.mcversion=Game Version -install.time=Time -install.release_time=Release Time -install.type=Type -install.please_refresh=If you want to install something please click "Refresh" button. - -crash.launcher=Launcher has crashed! -crash.minecraft=Minecraft has crashed! - -login.choose_charactor=Please choose the character you want -login.no_charactor=No character in this account. -login.your_password=Your password -login.failed=Failed to login -login.no_Player007=You have not set a username! -login.wrong_password=Incorrect password or username -login.invalid_username=Invalid username -login.invalid_uuid_and_username=Invalid UUID and username -login.invalid_password=Invalid password -login.invalid_access_token=Invalid Access Token -login.changed_client_token=The server response has changed the client token. -login.not_email=The username must be a e-mail. -login.type=Login -login.username=Name -login.account=Email -login.invalid_token=Please log out and re-input your password to log in. -login.no_valid_character=No valid character, please visit skinme.cc and create your own character. - -proxy.username=Account -proxy.password=Password -proxy.host=Host -proxy.port=Port - -login.failed.connect_authentication_server=Cannot connect the authentication server. Check your network. - -login.profile.not_logged_in=You are not logged in, you can't modify the profile! -login.profile.selected=Can't modify the profile, logout and go retry. - -login.methods.yggdrasil=Mojang -login.methods.offline=Offline -login.methods.no_method=No login method - -log.playername_null=The player name is empty. - -minecraft.no_selected_version=No selected Minecraft version -minecraft.wrong_path=Wrong Minecraft path, the launcher could not find the path. - -operation.stopped=The operation was aborted. -operation.confirm_stop=Terminate the operations? - -ui.login.password=Password -ui.more=More - -crash.advice.UnsupportedClassVersionError=Maybe your java is too old, try to update the java. -crash.advice.ConcurrentModificationException=Maybe your Java is newer than 1.8.0_11, you could downgrade to Java 7. -crash.advice.ClassNotFoundException=Minecraft or mods are incomplete. Retry if there are some libraries that have not downloaded or update your game and mods! Or you can try Game Settings -> Manage (Version) -> Delete library files to solve the problem. -crash.advice.NoSuchFieldError=Minecraft or mods are incomplete. Retry if there are some libraries that have not downloaded or update your game and mods! -crash.advice.LWJGLException=Maybe your video driver does not work well, please update your video driver. -crash.advice.SecurityException=Maybe you have modified minecraft.jar but have not removed the META-INF. -crash.advice.OutOfMemoryError=The maximum memory of JVM is too small, please modify it. -crash.advice.otherwise=Maybe mods caused problems. - -crash.advice.OpenGL=Maybe drivers caused problems. -crash.advice.no_lwjgl=Maybe drivers caused problems. - -crash.advice.no=No advice. - -crash.user_fault=Your OS or Java environment may not be properly installed resulting in crashing of this software, please check your Java Environment or your computer! -crash.headless=If your OS is Linux, please use Oracle JDK instead of OpenJDK, or add "-Djava.awt.headless=false" JVM argument, or check if your Xserver works normally. -crash.NoClassDefFound=Please check "HMCL" software is complete. - -crash.error=Minecraft has crashed. -crash.main_class_not_found=Main Class is not found, may be your mc has been broken. -crash.class_path_wrong=Maybe the launch script is malformed. - -ui.label.newProfileWindow.new_profile_name=New Profile Name: -ui.label.newProfileWindow.copy_from=Copy From: -ui.newProfileWindow.title=New Config - -ui.button.ok=OK -ui.button.refresh=Refresh -ui.button.run=Play -ui.button.settings=Settings -ui.button.about=About -ui.button.others=Others -ui.button.logout=Log Out -ui.button.download=Download -ui.button.retry=Retry -ui.button.delete=Delete -ui.button.install=Install -ui.button.info=Info -ui.button.save=Save -ui.button.copy=Copy -ui.button.clear=Clear -ui.button.close=Close -ui.button.explore=Explore -ui.button.test=Test -ui.button.preview=Preview -button.cancel=Cancel -button.ok=OK -button.yes=Yes -button.no=No - -ui.label.version=Version -ui.label.password=Password -ui.label.profile=Profile - -ui.message.first_load=Please enter your name. -ui.message.enter_password=Please enter your password. -ui.message.launching=Launching... -ui.message.making=Generating... -ui.message.sure_remove=Sure to remove profile %s? -ui.message.update_java=Please upgrade your Java. -ui.message.open_jdk=We have found that you started this application using OpenJDK, which will cause so many troubles drawing the UI. We suggest you using Oracle JDK instead. - -ui.label.settings=Settings -ui.label.crashing=Hello Minecraft! Launcher has crashed! -ui.label.crashing_out_dated=Hello Minecraft! Launcher has crashed! Your launcher is outdated. Update it! -ui.label.failed_set=Failed to set: - -download=Download -download.mojang=Mojang -download.BMCL=BMCLAPI (bangbang93, http://bmclapi.bangbang93.com/) -download.rapid_data=RapidData (https://www.rapiddata.org/) -download.not_200=Failed to download, the response code -download.failed=Failed to download -download.successfully=Downloaded successfully -download.source=Download Source - -message.error=Error -message.cannot_open_explorer=Cannot open explorer: -message.cancelled=Cancelled -message.info=Info -message.loading=Loading... - -folder.game=Game Dir -folder.mod=Mod -folder.coremod=Core Mod -folder.config=Configs -folder.resourcepacks=Resourcepacks -folder.screenshots=Screenshots -folder.saves=Saves - -settings.tabs.game_download=Games -settings.tabs.installers=Installers -settings.tabs.assets_downloads=Assets - -settings=Settings -settings.explore=Explore -settings.manage=Manage -settings.cannot_remove_default_config=Cannot remove the default configution. -settings.max_memory=Max Memory/MB -settings.java_dir=Java Dir -settings.game_directory=Game Directory -settings.dimension=Game Window Dimension -settings.fullscreen=Fullscreen -settings.update_version=Update version json. -settings.run_directory=Run Directory(Version Isolation) -settings.physical_memory=Physical Memory Size -settings.choose_javapath=Choose Java Directory. -settings.default=Default -settings.custom=Custom -settings.choose_gamedir=Choose Game Directory -settings.failed_load=Failed to load settings file. Remove it? -settings.test_game=Test game - -settings.type.none=No version here, please turn to game download tab. -settings.type.global=Click here to switch to version specialized setting. Now it is global setting. -settings.type.special=Click here to switch to global setting. Not it is version specialized setting. - -modpack=Mod pack -modpack.choose=Choose a modpack zip file which you want to import. If you want to update the modpack, please enter the version you want to update. -modpack.export_error=Failed to export the modpack, maybe the format of your game directory is incorrect or failed to manage files. -modpack.export_finished=Exporting the modpack finished. See -modpack.included_launcher=The modpack is included the launcher, you can publish it directly. -modpack.not_included_launcher=You can use the modpack by clicking the "Import Modpack" button. -modpack.enter_name=Enter your desired name for this game. - -modpack.task.save=Export Modpack -modpack.task.install=Import Modpack -modpack.task.install.error=Failed to install the modpack. Maybe the files is incorrect, or a management issue occurred. -modpack.task.install.will=Install the modpack: - -modpack.wizard=Exporting the modpack wizard -modpack.wizard.step.1=Basic options -modpack.wizard.step.1.title=Set the basic options to the modpack. -modpack.wizard.step.initialization.include_launcher=Include the launcher -modpack.wizard.step.initialization.exported_version=The exported game version -modpack.wizard.step.initialization.save=Choose a location to export the game files to -modpack.wizard.step.initialization.warning=Before making modpack, you should ensure that your game can launch successfully,
    and that your Minecraft is release, not snapshot.
    and that it is not allowed to add mods which is not allowed to distribute to the modpack. -modpack.wizard.step.2=Files selection -modpack.wizard.step.2.title=Choose the files you do not want to put in the modpack. -modpack.wizard.step.3=Description -modpack.wizard.step.3.title=Describe your modpack. - -modpack.desc=Describe your modpack, including precautions, changlog, supporting Markdown(also supporting online pictures). -modpack.incorrect_format.no_json=The format of the modpack is incorrect, pack.json is missing. -modpack.incorrect_format.no_jar=The format of the modpack is incorrect, pack.json does not have attribute 'jar' -modpack.cannot_read_version=Failed to gather the game version -modpack.not_a_valid_location=Not a valid modpack location -modpack.name=Modpack Name -modpack.not_a_valid_name=Not a valid modpack name - -modpack.files.servers_dat=Multiplayer servers list -modpack.files.saves=Saved games -modpack.files.mods=Mods -modpack.files.config=Mod configs -modpack.files.liteconfig=Mod configurations -modpack.files.resourcepacks=Resource(Texture) packs -modpack.files.options_txt=Game options -modpack.files.optionsshaders_txt=Shaders options -modpack.files.mods.voxelmods=VoxelMods (including VoxelMap) options -modpack.files.dumps=NEI debug output -modpack.files.scripts=MineTweaker configuration -modpack.files.blueprints=BuildCraft blueprints - -mods=Mods -mods.choose_mod=Choose your mods -mods.failed=Failed to add mods -mods.add=Add -mods.remove=Remove -mods.default_information=Please ensure that you have installed Forge or LiteLoader before installing mods!
    You can drop your mod files from explorer/finder, and delete mods by the delete button.
    Disable a mod by leaving the check box unchecked; Choose an item to get the information.
    - -advancedsettings=Advanced -advancedsettings.launcher_visible=Launcher Visibility -advancedsettings.debug_mode=Debug Mode -advancedsettings.java_permanent_generation_space=PermGen Space/MB -advancedsettings.jvm_args=Java VM Arguments -advancedsettings.Minecraft_arguments=Minecraft Arguments -advancedsettings.launcher_visibility.close=Close the launcher when the game launched. -advancedsettings.launcher_visibility.hide=Hide the launcher when the game launched. -advancedsettings.launcher_visibility.keep=Keep the launcher visible. -advancedsettings.launcher_visibility.hide_reopen=Hide the launcher and re-open when game closes. -advancedsettings.game_dir.default=Default (.minecraft/) -advancedsettings.game_dir.independent=Independent (.minecraft/versions//, except assets,libraries) -advancedsettings.no_jvm_args=No Default JVM Args -advancedsettings.no_common=Not using common path -advancedsettings.java_args_default=Default java args: -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode -XX:-UseAdaptiveSizePolicy -XX:MaxPermSize=???m -Xmx???m -Dfml.ignoreInvalidMinecraftCertificates=true -Dfml.ignorePatchDiscrepancies=true -advancedsettings.wrapper_launcher=Wrapper Launcher(like optirun...) -advancedsettings.precall_command=Precalling command(will be executed before game launching) -advancedsettings.server_ip=Server Host -advancedsettings.cancel_wrapper_launcher=Cancel Wrapper Launcher -advancedsettings.dont_check_game_completeness=Don't check game completeness - -mainwindow.show_log=Show Logs -mainwindow.make_launch_script=Make Launching Script. -mainwindow.make_launch_script_failed=Failed to make script. -mainwindow.enter_script_name=Enter the script name. -mainwindow.make_launch_succeed=Finished script creation. -mainwindow.no_version=No version found. Switch to Game Downloads Tab? - -launcher.about=About Author
    Minecraft Forum ID: klkl6523
    Copyright (c) 2013 huangyuhui
    Opened source under GPL v3 license:http://github.com/huanghongxun/HMCL/
    This software used project Gson which is under Apache License 2.0, thanks contributors. -launcher.download_source=Download Source -launcher.background_location=Background Location -launcher.common_location=Common Location -launcher.exit_failed=Failed to shutdown. -launcher.versions_json_not_matched=The version %s is malformed! There are a json:%s in this version. Do you want to fix this problem? -launcher.versions_json_not_matched_cannot_auto_completion=The version %s lost version information file, delete it? -launcher.versions_json_not_formatted=The version information of %s is malformed! Redownload it? -launcher.choose_bgpath=Choose background path. -launcher.choose_commonpath=Choose common path. -launcher.commpath_tooltip=This app will save all game libraries and assets here unless there are existant files in game folder. -launcher.background_tooltip=The laucher uses a default background.
    If you use custom background.png, link it and it will be used.
    If there is "bg" subdirectory, this app will chooses one picture in "bgskin" randomly.
    If you set the background setting, this app will use it. -launcher.update_launcher=Check for update -launcher.enable_shadow=Enable Window Shadow -launcher.enable_animation=Enable Animation -launcher.enable_blur=Enable Blur -launcher.theme=Theme -launcher.proxy=Proxy -launcher.decorated=Enable system window border(in order to fix the problem that the ui become all gray in Linux OS) -launcher.modpack=Documentations for modpacks. -launcher.lang=Language -launcher.restart=Options will be in operations only if restart this app. -launcher.log_font=Log Font -launcher.tab.general=General -launcher.tab.ui=UI -launcher.tab.about=About - -launcher.title.game=Games -launcher.title.main=Home -launcher.title.launcher=Launcher - -versions.release=Release -versions.snapshot=Snapshot -versions.old_beta=Beta -versions.old_alpha=Old Alpha - -versions.manage.rename=Rename this version -versions.manage.rename.message=Please enter the new name -versions.manage.remove=Delete this version -versions.manage.remove.confirm=Sure to remove the version -versions.manage.redownload_json=Redownload Minecraft Configuration(minecraft.json) -versions.manage.redownload_assets_index=Redownload Assets Index -versions.mamage.remove_libraries=Delete library files - -advice.os64butjdk32=Your OS is 64-Bit but your Java is 32-Bit. The 64-Bit Java is recommended. -advice.java8=Java 8 is suggested, which can make game run more fluently. And many mods and Minecraft 1.12 and newer versions requires Java 8. - -assets.download_all=Download Assets Files -assets.not_refreshed=The assets list is not refreshed, please refresh it once. -assets.failed=Failed to get the list, try again. -assets.list.1_7_3_after=1.7.3 And higher -assets.list.1_6=1.6(BMCLAPI) -assets.unkown_type_select_one=Unknown game version: %s, please choose an asset type. -assets.type=Asset Type -assets.download=Download Assets -assets.no_assets=Assets are not complete, complete them? -assets.failed_download=Failed to download assets, may cause no sounds and language files. - -gamedownload.not_refreshed=The game list is not refreshed, please refresh it once. - -taskwindow.title=Tasks -taskwindow.single_progress=Single progress -taskwindow.total_progress=Total progress -taskwindow.cancel=Cancel -taskwindow.no_more_instance=Maybe you opened more than one task window, don't open it again! -taskwindow.file_name=Task -taskwindow.download_progress=Pgs. - -setupwindow.include_minecraft=Import game -setupwindow.find_in_configurations=Finished importing. You can find it in the configuration selection bar. -setupwindow.give_a_name=Give a name to the new game. -setupwindow.new=New -setupwindow.no_empty_name=Version name cannot be empty. -setupwindow.clean=Clean game files - -update.no_browser=Cannot open any browser. The link has been copied to the clipboard. Paste it to a browser address bar to update. -update.should_open_link=Are you willing to update the launcher? -update.newest_version=Newest version: -update.failed=Failed to check for updates. -update.found=(Found Update!) - -logwindow.terminate_game=Terminate Game -logwindow.title=Log -logwindow.contact=Contact Us -logwindow.show_lines=Show Lines -logwindow.search=Search - -selector.choose=Choose - -serverlistview.title=Choose a server -serverlistview.name=Name -serverlistview.type=Type -serverlistview.version=Version -serverlistview.info=Information - -minecraft.invalid=Invalid -minecraft.invalid_jar=Invalid Jar -minecraft.not_a_file=Not a file -minecraft.not_found=Not found -minecraft.not_readable=Not readable -minecraft.modified=(Modified!) - -color.red=Red -color.blue=Blue -color.green=Green -color.orange=Orange -color.dark_blue=Dark Blue -color.purple=Purple - -wizard.next_>=Next > -wizard.next_mnemonic=N -wizard.<_prev=< Prev -wizard.prev_mnemonic=P -wizard.finish=Finish -wizard.finish_mnemonic=F -wizard.cancel=Cancel -wizard.cancel_mnemonic=C -wizard.help=Help -wizard.help_mnemonic=H -wizard.close=Close -wizard.close_mnemonic=C -wizard.summary=Summary -wizard.failed=Failed -wizard.steps=Steps - -lang=English -lang.default=Belong to OS language. diff --git a/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_ru.lang b/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_ru.lang deleted file mode 100644 index 0ffea179b..000000000 --- a/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_ru.lang +++ /dev/null @@ -1,440 +0,0 @@ -# Hello Minecraft! Launcher. -# Copyright (C) 2013 huangyuhui -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see {http://www.gnu.org/licenses/}. -# -#author: malyha2014@yandex.ru -launch.failed=Не удалось запустить. -launch.failed_creating_process=Не удалось создать процесс, возможно, ваш путь java - указан не верно, пожалуйста, измените свой путь java. -launch.failed_sh_permission=Не удалось добавить разрешение на запуск скрипта. -launch.failed_packing_jar=Не удалось упаковать в jar. -launch.unsupported_launcher_version=Извините, Launcher не может запустить minecraft, но повторяет попытку запуска. -launch.too_big_memory_alloc_64bit=Вы выделили слишком много памяти, потому что 32-разрядная Среда выполнения java, то игра скорее всего приведет к крашу. Максимальный объем памяти 1024МБ. Лаунчер будет пытаться запустить его. -launch.too_big_memory_alloc_free_space_too_low=Вы выделили слишком много памяти, потому что размер физической памяти составляет %dMB, ваша игра скорее всего приведет к крашу. Лаунчер будет пытаться запустить его. -launch.cannot_create_jvm=Мы видим, что он не может создать java виртуальная машина. В Java агреманы могут возникнуть проблемы. Вы можете включить режим No args в настройках. -launch.circular_dependency_versions=Нашли круговой версии зависимостей, пожалуйста, проверьте, если ваш клиент был изменен. -launch.not_finished_downloading_libraries=Не закончив загрузку библиотек, продолжить запуск игры? -launch.not_finished_decompressing_natives=Не закончил распаковки собственных библиотек, продолжить запуск игры? -launch.wrong_javadir=Неправильные каталоги java, будут сброшены по умолчанию каталогов java. -launch.exited_abnormally=Игра завершилась аварийно, пожалуйста, посетите журнал, или попросить кого-то о помощи. - -launch.state.logging_in=Вход -launch.state.generating_launching_codes=Генерирования стартового кода -launch.state.downloading_libraries=Загрузки зависимостей -launch.state.decompressing_natives=Туземцев распаковки -launch.state.waiting_launching=Ждем запуска игры - -install.no_version=Версия не найдена. -install.no_version_if_intall=Нужная версия не найдена, вы хотите, чтобы автоматически установить версию? -install.not_refreshed=Список установки не обновляется. -install.download_list=Скачать список - -install.liteloader.get_list=Получить список LiteLoader -install.liteloader.install=Установить LiteLoader - -install.forge.get_list=Получить список Forge -install.forge.install=Установить Forge -install.forge.get_changelogs=Получить список изменений Forge - -install.optifine.install=Установить OptiFine -install.optifine.get_list=Получить OptiFine лист -install.optifine.get_download_link=Получить скачивание OptiFine - -install.failed_forge=Не удалось установить 'Forge'. -install.failed_optifine=Не удалось установить 'OptiFine'. -install.failed_liteloader=Не удалось установить 'LiteLoader'. -install.failed_download_forge=Не удалось скачать 'Forge'. -install.failed_download_optifine=Не удалось скачать 'OptiFine'. -install.failed=Не удалось установить -install.success=Успешная установка -install.no_forge=Нету Forge -install.choose_forge=Выберите версию, которую вы хотите установить Forge -install.version=Версия -install.mcversion=Версия игры -install.time=Время -install.release_time=Время выпуска -install.type=Тип -install.please_refresh=Если вы хотите установить что-то, пожалуйста, нажмите кнопку "Обновить". - -crash.launcher=Лаунчер крашнулся! -crash.minecraft=Minecraft крашнулся! - -login.choose_charactor=Пожалуйста, выберите символ, который вы хотите -login.no_charactor=Нет персонажа на этом аккаунте. -login.your_password=Пароль -login.failed=Не удалось войти -login.no_Player007=Не задано имя пользователя! -login.wrong_password=Неправильный пароль или имя пользователя -login.invalid_username=Неверное имя пользователя -login.invalid_uuid_and_username=Недопустимый UUID и имя пользователя -login.invalid_password=Неверный пароль -login.invalid_access_token=Недопустимый маркер доступа -login.changed_client_token=Ответ сервера был изменен маркер клиента. -login.not_email=Имя пользователя-это адрес электронной почты. -login.type=Логин -login.username=Ник -login.account=Почта -login.invalid_token=Пожалуйста, выйдите и повторно введите пароль для входа в систему. -login.no_valid_character=Не допустимый характер, пожалуйста, посетите skinme.cc и создать своего собственного персонажа. - -proxy.username=Аккаунт -proxy.password=Пароль -proxy.host=Хост -proxy.port=Порт - -login.failed.connect_authentication_server=Не удается подключиться к серверу авторизации. Проверьте вашу сеть. - -login.profile.not_logged_in=Вы не вошли в систему, Вы не можете изменить профиль! -login.profile.selected=Не могу изменить профиль, выйти и пойти повторить. - -login.methods.yggdrasil=Email и пароль -login.methods.offline=Введите ваш ник -login.methods.no_method=Нет способа входа - -log.playername_null=Ник игрока пусто. - -minecraft.no_selected_version=Не выбрана Minecraft версия -minecraft.wrong_path=Неправильный путь Minecraft, лаунчер не может найти путь. - -operation.stopped=Операция была прервана. -operation.confirm_stop=Прекращать операции? - -ui.login.password=Пароль -ui.more=Больше - -crash.advice.UnsupportedClassVersionError=Может быть, ваша версия java старая, попробуйте обновить java. -crash.advice.ConcurrentModificationException=Может быть, ваш java новее, чем 1.8.0_11, вы можете понизить до версии java 7. -crash.advice.ClassNotFoundException=Minecraft или моды, являются неполными. Повторите, если есть какие-то библиотеки, которые не скачали или обновить игру и модов! Или вы можете попробовать настройки игры -> Управление (версии) -> библиотека удалить файлы, чтобы решить проблему. -crash.advice.NoSuchFieldError=Майнкрафт или моды, являются неполными. Повторите, если есть какие-то библиотеки, которые не скачали или обновить игру и модов! -crash.advice.LWJGLException=Может быть, ваш видео драйвер не работает, пожалуйста, обновите ваш видео драйвер. -crash.advice.SecurityException=Может быть, вы изменили minecraft.jar но не удалили META-INF. -crash.advice.OutOfMemoryError=Максимум памяти для JVM слишком мал, пожалуйста, измените его. -crash.advice.otherwise=Может быть моды вызвали проблемы. - -crash.advice.OpenGL=Может быть драйвера вызвали проблемы. -crash.advice.no_lwjgl=Может быть драйвера вызвали проблемы. - -crash.advice.no=Никакие советы. - -crash.user_fault=Вашей операционной системы или среды java не может быть установлен неправильно, в результате сбой этой программы, пожалуйста, проверьте вашу среду java или компьютер! -crash.headless=Если ваша ОС Linux можно использовать Oracle версии jdk вместо openjdk, то или добавить "-Djava.awt.headless=false" аргумент jvm, или проверить, если ваш x-сервер работает нормально. -crash.NoClassDefFound=Пожалуйста, проверьте "Launcher" программное обеспечение в комплекте. - -crash.error=Minecraft крашнулся. -crash.main_class_not_found=Главный Класс не найден, может быть ваш МК был нарушен. -crash.class_path_wrong=Может запустить скрипт неправильный. - -ui.label.newProfileWindow.new_profile_name=Новое Имя Профиля: -ui.label.newProfileWindow.copy_from=Скопировать Из: -ui.newProfileWindow.title=Новый Конфиг - -ui.button.ok=OK -ui.button.refresh=Обновить -ui.button.run=Играть -ui.button.settings=Настройки -ui.button.about=About -ui.button.others=Другие -ui.button.logout=Выйти -ui.button.download=Скачать -ui.button.retry=Повторить -ui.button.delete=Удалить -ui.button.install=Установить -ui.button.info=Информация -ui.button.save=Сохранить -ui.button.copy=Скопировать -ui.button.clear=Очистить -ui.button.close=Закрыть -ui.button.explore=Выбрать -ui.button.test=Тест -ui.button.preview=Показать -button.cancel=Отменить -button.ok=OK -button.yes=да -button.no=Неа - -ui.label.version=Версия -ui.label.password=Пароль -ui.label.profile=Профиль - -ui.message.first_load=Пожалуйста, введите ваш ник. -ui.message.enter_password=Пожалуйста, введите Ваш пароль. -ui.message.launching=Запуск... -ui.message.making=Генерация... -ui.message.sure_remove=Не забудьте удалить профиль %s? -ui.message.update_java=Пожалуйста, обновите ваш Java. -ui.message.open_jdk=Мы уже выяснили, что вы начали это приложение, используя OpenJDK, который станет причиной стольких бед для рисования интерфейса. Мы предлагаем Вам вместо того, чтобы с помощью Oracle версии JDK. - -ui.label.settings=Настройки -ui.label.crashing=Hello Minecraft! Launcher крашнулся! -ui.label.crashing_out_dated=Hello Minecraft! Launcher крашнулся! Ваш лаунчер устарел. Обновить его -ui.label.failed_set=Не удалось установить: - -download=Скачать -download.mojang=Mojang -download.BMCL=BMCLAPI (bangbang93, http://bmclapi.bangbang93.com/) -download.rapid_data=RapidData (https://www.rapiddata.org/) -download.not_200=Не удалось скачать, код ответа -download.failed=Не удалось скачать -download.successfully=Успешно скачал -download.source=Скачать Исходник - -message.error=Ошибка -message.cannot_open_explorer=Cannot open explorer: -message.cancelled=Отменен -message.info=Информация -message.loading=Загрузка... - -folder.game=Game Dir -folder.mod=Мод -folder.coremod=Core Mod -folder.config=Конфигурации -folder.resourcepacks=Ресурс паки -folder.screenshots=Скриншоты -folder.saves=Сохранить - -settings.tabs.game_download=Скачать игру -settings.tabs.installers=Установщик -settings.tabs.assets_downloads=Дополнения - -settings=Настройки -settings.explore=Выбрать -settings.manage=Управлять -settings.cannot_remove_default_config=Не удается удалить configution по умолчанию. -settings.max_memory=Max Memory/MB -settings.java_dir=Java Dir -settings.game_directory=Директории Игры -settings.dimension=Игра Окно Измерения -settings.fullscreen=Полноэкранный -settings.update_version=Обновление версии в формате json. -settings.run_directory=Запуск Каталога(Изоляция Версия) -settings.physical_memory=Размер Физической Памяти -settings.choose_javapath=Выбрать Каталог Java. -settings.default=Default -settings.custom=Выбрать -settings.choose_gamedir=Выбрать Директорию Игры -settings.failed_load=Не смог файл загрузить настройки. Удалить его? -settings.test_game=Тестовая игра - -settings.type.none=Нет версии игры, пожалуйста, откройте на разделе скачать игры. -settings.type.global=Нажмите здесь, чтобы перейти в специализированных версий. Сейчас это глобальная настройка. -settings.type.special=Нажмите здесь, чтобы перейти в глобальные настройки. Не это версии специализированных условиях. - -modpack=Мод пак -modpack.choose=Выбрать zip-файл, пакет, который вы хотите импортировать. Если вы хотите обновить пакет, пожалуйста, введите версию вы хотите обновить. -modpack.export_error=Не удалось экспортировать пакет, может быть Формат вашей игровой директории некорректно или не работать с файлами. -modpack.export_finished=Экспорт произведений, готовые. Смотреть -modpack.included_launcher=В пакет входит пусковая установка, вы можете опубликовать его сразу. -modpack.not_included_launcher=Вы можете использовать пакет, нажав кнопку "Импорт произведений". -modpack.enter_name=Введите желаемое имя для этой игры. - -modpack.task.save=Эскпортировать Modpack -modpack.task.install=Импортировать Modpack -modpack.task.install.error=Не удалось установить пакет. Может быть, файлы неправильно, или возникла проблема управления. -modpack.task.install.will=Установить пакет: - -modpack.wizard=Экспорт modpack мастер -modpack.wizard.step.1=Основные варианты -modpack.wizard.step.1.title=Набор основных вариантов modpack. -modpack.wizard.step.initialization.include_launcher=Включить лаунчер -modpack.wizard.step.initialization.exported_version=Экспортируемые версии игры -modpack.wizard.step.initialization.save=Выберите папку для экспорта игровых файлов для -modpack.wizard.step.initialization.warning=Прежде чем сделать суд, вы должны убедиться, что ваша игра сможет успешно запуска,
    и что ваш minecraft-это релиз, а не снимок.
    а что нельзя добавить модов, которые не позволили раздавать modpack. -modpack.wizard.step.2=Выбор файлов -modpack.wizard.step.2.title=Выберите файлы, которые Вы не хотите положить в modpack. -modpack.wizard.step.3=Описание -modpack.wizard.step.3.title=Опишите ваш modpack. - -modpack.desc=Опишите свою modpack, включая меры предосторожности, changlog, поддерживая уценки(также поддерживает онлайн-картинки). -modpack.incorrect_format.no_json=Формат произведений, является неверным, пакет.json-это отсутствует. -modpack.incorrect_format.no_jar=Формат modpack неправильно, пакет.json не имеет атрибут 'банку' -modpack.cannot_read_version=Не удалось собрать версии игры -modpack.not_a_valid_location=Не является допустимым modpack расположение -modpack.name=Modpack Название -modpack.not_a_valid_name=Не является допустимым modpack название - -modpack.files.servers_dat=Список многопользовательских серверов -modpack.files.saves=Сохраненные игры -modpack.files.mods=Моды -modpack.files.config=Mod конфигурации -modpack.files.liteconfig=Mod конфигурации -modpack.files.resourcepacks=Ресурс(текстур) паки -modpack.files.options_txt=Варианты игры -modpack.files.optionsshaders_txt=Варианты шейдеры -modpack.files.mods.voxelmods=VoxelMods (включая VoxelMap) функции -modpack.files.dumps=NEI отладочный вывод -modpack.files.scripts=MineTweaker конфигурации -modpack.files.blueprints=BuildCraft чертежи - -mods=Моды -mods.choose_mod=Выбрать ваши моды -mods.failed=Не удалось добавить моды -mods.add=Добавить -mods.remove=Удалить -mods.default_information=Пожалуйста, убедитесь, что у вас есть установленный Forge или LiteLoader перед установкой модов!
    Вы можете оставить свой mod файлов из проводника/Finder и удаление модов с помощью кнопки удалить.
    Отключить мод, оставив флажок снят; выбрать товар, чтобы получить информацию.
    - -advancedsettings=Расширенный -advancedsettings.launcher_visible=Лаунчер Видимость -advancedsettings.debug_mode=Режим Отладки -advancedsettings.java_permanent_generation_space=PermGen Space/MB -advancedsettings.jvm_args=Java VM Arguments -advancedsettings.Minecraft_arguments=Майнкрафт Аргументы -advancedsettings.launcher_visibility.close=Закрыть лаунчер, если игра запущена. -advancedsettings.launcher_visibility.hide=Скрывать запуска, когда игра запущена. -advancedsettings.launcher_visibility.keep=Держите пусковую видны. -advancedsettings.launcher_visibility.hide_reopen=Скрывать запуска и повторного открытия, когда игра закрывается. -advancedsettings.game_dir.default=По умолчанию (.minecraft/) -advancedsettings.game_dir.independent=Независимые (.minecraft/версии/<номер версии>/, за исключением активов,библиотеки) -advancedsettings.no_jvm_args=No Default JVM Args -advancedsettings.no_common=Не использовать общий путь -advancedsettings.java_args_default=Default java args: -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode -XX:-UseAdaptiveSizePolicy -XX:MaxPermSize=???m -Xmx???m -Dfml.ignoreInvalidMinecraftCertificates=true -Dfml.ignorePatchDiscrepancies=true -advancedsettings.wrapper_launcher=Лаунчер-оболочку(как и optirun...) -advancedsettings.precall_command=Команда Precalling(будут выполняться до запуска игры) -advancedsettings.server_ip=Сервера -advancedsettings.cancel_wrapper_launcher=Отмена Запуска Оболочки -advancedsettings.dont_check_game_completeness=Не проверить полноту игры - -mainwindow.show_log=Показать Логи -mainwindow.make_launch_script=Сделать Запуск Скрипта. -mainwindow.make_launch_script_failed=Не удалось сделать скрипт. -mainwindow.enter_script_name=Введите имя скрипта. -mainwindow.make_launch_succeed=Закончил создание скрипта. -mainwindow.no_version=Версии не найдены. Переключить на вкладку загрузки игры? - -launcher.about=Об Авторе
    Майнкрафт форум ID: klkl6523
    Copyright (c) 2013 huangyuhui
    Opened source under GPL v3 license:http://github.com/huanghongxun/HMCL/
    This software used project Gson which is under Apache License 2.0, thanks contributors. -launcher.download_source=Скачать Исходники -launcher.background_location=Фон Расположение -launcher.common_location=Общее Расположение -launcher.exit_failed=Не удалось закрыть. -launcher.versions_json_not_matched=Версия %s уродлив! Есть в формате json:%s в этой версии. Хотите ли вы решить эту проблему? -launcher.versions_json_not_matched_cannot_auto_completion=Версия %s потерянной информации версии файла, удалить его? -launcher.versions_json_not_formatted=Сведения о версии %s уродлив! Повторная загрузка? -launcher.choose_bgpath=Выберите фоновый пути. -launcher.choose_commonpath=Выбрать общий путь. -launcher.commpath_tooltip=Это приложение будет сохранить все игровые библиотеки и активы здесь, если там нет файлов в папку с игрой. -launcher.background_tooltip=Лаучер использует по умолчанию фон.
    Если вы используете пользовательский фон.PNG, ссылку и оно будет использоваться.
    Если есть "БГ" подкаталог, это приложение выбирает одну картинку в "bgskin" случайно.
    Если вы установите параметр фон, это приложение будет использовать его. -launcher.update_launcher=Проверить обновления -launcher.enable_shadow=Включить Window Shadow -launcher.enable_animation=Включить Animation -launcher.enable_blur=Включить Blur -launcher.theme=Тема -launcher.proxy=Прокси -launcher.decorated=Включить границы окна(для того, чтобы исправить эту проблему, что пользовательский интерфейс становятся все серые в ОС Linux) -launcher.modpack=Документация для modpacks. -launcher.lang=Язык (Language) -launcher.restart=Варианты будут в операции, только если перезапустить это приложение. -launcher.log_font=Шрифт Лога -launcher.tab.general=Общие -launcher.tab.ui=Интерфейс -launcher.tab.about=Автор - -launcher.title.game=Игры -launcher.title.main=Главная -launcher.title.launcher=Лаунчер - -versions.release=Release -versions.snapshot=Snapshot -versions.old_beta=Beta -versions.old_alpha=Old Alpha - -versions.manage.rename=Переименовать эту версию -versions.manage.rename.message=Пожалуйста, введите новый ник -versions.manage.remove=Удалить версию -versions.manage.remove.confirm=Не забудьте удалить версию -versions.manage.redownload_json=Повторная загрузка конфигурации в Minecraft(minecraft.json) -versions.manage.redownload_assets_index=Индекс Перекачайте Активов -versions.mamage.remove_libraries=Библиотека удалять файлы - -advice.os64butjdk32=Ваша ОС 64-битных но ваш java является 32-разрядной. В 64-разрядной версии java рекомендуется. -advice.java8=Java 8 представляет предположил, что может сделать игру работать более плавно. И много модов и Майнкрафт 1.12 и новые версии требуется java 8. - -assets.download_all=Скачать Файлы -assets.not_refreshed=Список активов не обновляется, пожалуйста, обновите его один раз. -assets.failed=Не удалось получить список, попробуйте еще раз. -assets.list.1_7_3_after=1.7.3 и выше -assets.list.1_6=1.6(BMCLAPI) -assets.unkown_type_select_one=Неизвестная версия игры: %s, пожалуйста, выберите тип актива. -assets.type=Тип Актива -assets.download=Скачать Активы -assets.no_assets=Активов не завершена, завершить их? -assets.failed_download=Не удалось загрузить активы, может вызвать никаких звуков и языковые файлы. - -gamedownload.not_refreshed=Список игр не обновляется, пожалуйста, обновите его один раз. - -taskwindow.title=Задачи -taskwindow.single_progress=Один прогресс -taskwindow.total_progress=Общий прогресс -taskwindow.cancel=Отменить -taskwindow.no_more_instance=Может быть, вы открыли больше чем одно окно задач, не открыть его снова! -taskwindow.file_name=Задача -taskwindow.download_progress=Проценты. - -setupwindow.include_minecraft=Импорт игры -setupwindow.find_in_configurations=Завершения импорта. Вы можете найти его в панели выбора конфигурации. -setupwindow.give_a_name=Дать название новой игры. -setupwindow.new=Новое -setupwindow.no_empty_name=Название версии не может быть пустым. -setupwindow.clean=Чистые файлы игры - -update.no_browser=Не можете открыть любым браузером. Ссылка была скопирована в буфер обмена. Вставьте его в адресную строку браузера обновить. -update.should_open_link=Вы готовы обновить лаунчер? -update.newest_version=Самая новая версия: -update.failed=Не удалось проверить наличие обновлений. -update.found=(Нашел Обновление!) - -logwindow.terminate_game=Завершить Игру -logwindow.title=Лог -logwindow.contact=Свяжитесь С Нами -logwindow.show_lines=Показать Строки -logwindow.search=Поиск - -selector.choose=Выбрать - -serverlistview.title=Выбрать сервер -serverlistview.name=Название -serverlistview.type=Тип -serverlistview.version=Версия -serverlistview.info=Информация - -minecraft.invalid=Invalid -minecraft.invalid_jar=Invalid Jar -minecraft.not_a_file=Not a file -minecraft.not_found=Not found -minecraft.not_readable=Not readable -minecraft.modified=(Modified!) - -color.red=Красный -color.blue=Голубой -color.green=Зеленый -color.orange=Оранжевый -color.dark_blue=Темно-Синий -color.purple=Фиолетовый - -wizard.next_>=Next > -wizard.next_mnemonic=N -wizard.<_prev=< Prev -wizard.prev_mnemonic=P -wizard.finish=Finish -wizard.finish_mnemonic=F -wizard.cancel=Cancel -wizard.cancel_mnemonic=C -wizard.help=Help -wizard.help_mnemonic=H -wizard.close=Close -wizard.close_mnemonic=C -wizard.summary=Summary -wizard.failed=Failed -wizard.steps=Steps - -lang=Russian -lang.default=Belong to OS language. diff --git a/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_ru.properties b/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_ru.properties deleted file mode 100644 index 96d388298..000000000 --- a/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_ru.properties +++ /dev/null @@ -1,441 +0,0 @@ -# Hello Minecraft! Launcher. -# Copyright (C) 2013 huangyuhui -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see {http://www.gnu.org/licenses/}. -# -#author: malyha2014@yandex.ru -launch.failed=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c. -launch.failed_creating_process=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0432\u0430\u0448 \u043f\u0443\u0442\u044c java - \u0443\u043a\u0430\u0437\u0430\u043d \u043d\u0435 \u0432\u0435\u0440\u043d\u043e, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u0435 \u0441\u0432\u043e\u0439 \u043f\u0443\u0442\u044c java. -launch.failed_sh_permission=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 \u0437\u0430\u043f\u0443\u0441\u043a \u0441\u043a\u0440\u0438\u043f\u0442\u0430. -launch.failed_packing_jar=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0443\u043f\u0430\u043a\u043e\u0432\u0430\u0442\u044c \u0432 jar. -launch.unsupported_launcher_version=\u0418\u0437\u0432\u0438\u043d\u0438\u0442\u0435, Launcher \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c minecraft, \u043d\u043e \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0435\u0442 \u043f\u043e\u043f\u044b\u0442\u043a\u0443 \u0437\u0430\u043f\u0443\u0441\u043a\u0430. -launch.too_big_memory_alloc_64bit=\u0412\u044b \u0432\u044b\u0434\u0435\u043b\u0438\u043b\u0438 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043c\u043d\u043e\u0433\u043e \u043f\u0430\u043c\u044f\u0442\u0438, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e 32-\u0440\u0430\u0437\u0440\u044f\u0434\u043d\u0430\u044f \u0421\u0440\u0435\u0434\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f java, \u0442\u043e \u0438\u0433\u0440\u0430 \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u0442 \u043a \u043a\u0440\u0430\u0448\u0443. \u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u043e\u0431\u044a\u0435\u043c \u043f\u0430\u043c\u044f\u0442\u0438 1024\u041c\u0411. \u041b\u0430\u0443\u043d\u0447\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0435\u0433\u043e. -launch.too_big_memory_alloc_free_space_too_low=\u0412\u044b \u0432\u044b\u0434\u0435\u043b\u0438\u043b\u0438 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043c\u043d\u043e\u0433\u043e \u043f\u0430\u043c\u044f\u0442\u0438, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0440\u0430\u0437\u043c\u0435\u0440 \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438 \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 %dMB, \u0432\u0430\u0448\u0430 \u0438\u0433\u0440\u0430 \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u0442 \u043a \u043a\u0440\u0430\u0448\u0443. \u041b\u0430\u0443\u043d\u0447\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0435\u0433\u043e. -launch.cannot_create_jvm=\u041c\u044b \u0432\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u043e\u043d \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0442\u044c java \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u0430\u044f \u043c\u0430\u0448\u0438\u043d\u0430. \u0412 Java \u0430\u0433\u0440\u0435\u043c\u0430\u043d\u044b \u043c\u043e\u0433\u0443\u0442 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0443\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b. \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0440\u0435\u0436\u0438\u043c No args \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445. -launch.circular_dependency_versions=\u041d\u0430\u0448\u043b\u0438 \u043a\u0440\u0443\u0433\u043e\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435, \u0435\u0441\u043b\u0438 \u0432\u0430\u0448 \u043a\u043b\u0438\u0435\u043d\u0442 \u0431\u044b\u043b \u0438\u0437\u043c\u0435\u043d\u0435\u043d. -launch.not_finished_downloading_libraries=\u041d\u0435 \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u0432 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a, \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c \u0437\u0430\u043f\u0443\u0441\u043a \u0438\u0433\u0440\u044b? -launch.not_finished_decompressing_natives=\u041d\u0435 \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043b \u0440\u0430\u0441\u043f\u0430\u043a\u043e\u0432\u043a\u0438 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a, \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c \u0437\u0430\u043f\u0443\u0441\u043a \u0438\u0433\u0440\u044b? -launch.wrong_javadir=\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0435 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0438 java, \u0431\u0443\u0434\u0443\u0442 \u0441\u0431\u0440\u043e\u0448\u0435\u043d\u044b \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u043e\u0432 java. -launch.exited_abnormally=\u0418\u0433\u0440\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043b\u0430\u0441\u044c \u0430\u0432\u0430\u0440\u0438\u0439\u043d\u043e, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435 \u0436\u0443\u0440\u043d\u0430\u043b, \u0438\u043b\u0438 \u043f\u043e\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u043a\u043e\u0433\u043e-\u0442\u043e \u043e \u043f\u043e\u043c\u043e\u0449\u0438. - -launch.state.logging_in=\u0412\u0445\u043e\u0434 -launch.state.generating_launching_codes=\u0413\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0442\u0430\u0440\u0442\u043e\u0432\u043e\u0433\u043e \u043a\u043e\u0434\u0430 -launch.state.downloading_libraries=\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 -launch.state.decompressing_natives=\u0422\u0443\u0437\u0435\u043c\u0446\u0435\u0432 \u0440\u0430\u0441\u043f\u0430\u043a\u043e\u0432\u043a\u0438 -launch.state.waiting_launching=\u0416\u0434\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0438\u0433\u0440\u044b - -install.no_version=\u0412\u0435\u0440\u0441\u0438\u044f \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430. -install.no_version_if_intall=\u041d\u0443\u0436\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430, \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435, \u0447\u0442\u043e\u0431\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0432\u0435\u0440\u0441\u0438\u044e? -install.not_refreshed=\u0421\u043f\u0438\u0441\u043e\u043a \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043d\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442\u0441\u044f. -install.download_list=\u0421\u043a\u0430\u0447\u0430\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a - -install.liteloader.get_list=\u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a LiteLoader -install.liteloader.install=\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c LiteLoader - -install.forge.get_list=\u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a Forge -install.forge.install=\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c Forge -install.forge.get_changelogs=\u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 Forge - -install.optifine.install=\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c OptiFine -install.optifine.get_list=\u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c OptiFine \u043b\u0438\u0441\u0442 -install.optifine.get_download_link=\u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u0435 OptiFine - -install.failed_forge=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c 'Forge'. -install.failed_optifine=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c 'OptiFine'. -install.failed_liteloader=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c 'LiteLoader'. -install.failed_download_forge=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0441\u043a\u0430\u0447\u0430\u0442\u044c 'Forge'. -install.failed_download_optifine=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0441\u043a\u0430\u0447\u0430\u0442\u044c 'OptiFine'. -install.failed=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c -install.success=\u0423\u0441\u043f\u0435\u0448\u043d\u0430\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 -install.no_forge=\u041d\u0435\u0442\u0443 Forge -install.choose_forge=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0432\u0435\u0440\u0441\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c Forge -install.version=\u0412\u0435\u0440\u0441\u0438\u044f -install.mcversion=\u0412\u0435\u0440\u0441\u0438\u044f \u0438\u0433\u0440\u044b -install.time=\u0412\u0440\u0435\u043c\u044f -install.release_time=\u0412\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u0443\u0441\u043a\u0430 -install.type=\u0422\u0438\u043f -install.please_refresh=\u0415\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0447\u0442\u043e-\u0442\u043e, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043d\u0430\u0436\u043c\u0438\u0442\u0435 \u043a\u043d\u043e\u043f\u043a\u0443 "\u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c". - -crash.launcher=\u041b\u0430\u0443\u043d\u0447\u0435\u0440 \u043a\u0440\u0430\u0448\u043d\u0443\u043b\u0441\u044f! -crash.minecraft=Minecraft \u043a\u0440\u0430\u0448\u043d\u0443\u043b\u0441\u044f! - -login.choose_charactor=\u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0441\u0438\u043c\u0432\u043e\u043b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 -login.no_charactor=\u041d\u0435\u0442 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0430 \u043d\u0430 \u044d\u0442\u043e\u043c \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u0435. -login.your_password=\u041f\u0430\u0440\u043e\u043b\u044c -login.failed=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0432\u043e\u0439\u0442\u0438 -login.no_Player007=\u041d\u0435 \u0437\u0430\u0434\u0430\u043d\u043e \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f! -login.wrong_password=\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u043f\u0430\u0440\u043e\u043b\u044c \u0438\u043b\u0438 \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f -login.invalid_username=\u041d\u0435\u0432\u0435\u0440\u043d\u043e\u0435 \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f -login.invalid_uuid_and_username=\u041d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0439 UUID \u0438 \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f -login.invalid_password=\u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 \u043f\u0430\u0440\u043e\u043b\u044c -login.invalid_access_token=\u041d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0439 \u043c\u0430\u0440\u043a\u0435\u0440 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 -login.changed_client_token=\u041e\u0442\u0432\u0435\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0431\u044b\u043b \u0438\u0437\u043c\u0435\u043d\u0435\u043d \u043c\u0430\u0440\u043a\u0435\u0440 \u043a\u043b\u0438\u0435\u043d\u0442\u0430. -login.not_email=\u0418\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f-\u044d\u0442\u043e \u0430\u0434\u0440\u0435\u0441 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b. -login.type=\u041b\u043e\u0433\u0438\u043d -login.username=\u041d\u0438\u043a -login.account=\u041f\u043e\u0447\u0442\u0430 -login.invalid_token=\u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0432\u044b\u0439\u0434\u0438\u0442\u0435 \u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u043f\u0430\u0440\u043e\u043b\u044c \u0434\u043b\u044f \u0432\u0445\u043e\u0434\u0430 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443. -login.no_valid_character=\u041d\u0435 \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0439 \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435 skinme.cc \u0438 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0432\u043e\u0435\u0433\u043e \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0430. - -proxy.username=\u0410\u043a\u043a\u0430\u0443\u043d\u0442 -proxy.password=\u041f\u0430\u0440\u043e\u043b\u044c -proxy.host=\u0425\u043e\u0441\u0442 -proxy.port=\u041f\u043e\u0440\u0442 - -login.failed.connect_authentication_server=\u041d\u0435 \u0443\u0434\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f \u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438. \u041f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435 \u0432\u0430\u0448\u0443 \u0441\u0435\u0442\u044c. - -login.profile.not_logged_in=\u0412\u044b \u043d\u0435 \u0432\u043e\u0448\u043b\u0438 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443, \u0412\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u0440\u043e\u0444\u0438\u043b\u044c! -login.profile.selected=\u041d\u0435 \u043c\u043e\u0433\u0443 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u0440\u043e\u0444\u0438\u043b\u044c, \u0432\u044b\u0439\u0442\u0438 \u0438 \u043f\u043e\u0439\u0442\u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u044c. - -login.methods.yggdrasil=Email \u0438 \u043f\u0430\u0440\u043e\u043b\u044c -login.methods.offline=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0432\u0430\u0448 \u043d\u0438\u043a -login.methods.no_method=\u041d\u0435\u0442 \u0441\u043f\u043e\u0441\u043e\u0431\u0430 \u0432\u0445\u043e\u0434\u0430 - -log.playername_null=\u041d\u0438\u043a \u0438\u0433\u0440\u043e\u043a\u0430 \u043f\u0443\u0441\u0442\u043e. - -minecraft.no_selected_version=\u041d\u0435 \u0432\u044b\u0431\u0440\u0430\u043d\u0430 Minecraft \u0432\u0435\u0440\u0441\u0438\u044f -minecraft.wrong_path=\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u043f\u0443\u0442\u044c Minecraft, \u043b\u0430\u0443\u043d\u0447\u0435\u0440 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u043d\u0430\u0439\u0442\u0438 \u043f\u0443\u0442\u044c. - -operation.stopped=\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u0431\u044b\u043b\u0430 \u043f\u0440\u0435\u0440\u0432\u0430\u043d\u0430. -operation.confirm_stop=\u041f\u0440\u0435\u043a\u0440\u0430\u0449\u0430\u0442\u044c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438? - -ui.login.password=\u041f\u0430\u0440\u043e\u043b\u044c -ui.more=\u0411\u043e\u043b\u044c\u0448\u0435 - -crash.advice.UnsupportedClassVersionError=\u041c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c, \u0432\u0430\u0448\u0430 \u0432\u0435\u0440\u0441\u0438\u044f java \u0441\u0442\u0430\u0440\u0430\u044f, \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c java. -crash.advice.ConcurrentModificationException=\u041c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c, \u0432\u0430\u0448 java \u043d\u043e\u0432\u0435\u0435, \u0447\u0435\u043c 1.8.0_11, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u043d\u0438\u0437\u0438\u0442\u044c \u0434\u043e \u0432\u0435\u0440\u0441\u0438\u0438 java 7. -crash.advice.ClassNotFoundException=Minecraft \u0438\u043b\u0438 \u043c\u043e\u0434\u044b, \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043d\u0435\u043f\u043e\u043b\u043d\u044b\u043c\u0438. \u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0435, \u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u0441\u043a\u0430\u0447\u0430\u043b\u0438 \u0438\u043b\u0438 \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0438\u0433\u0440\u0443 \u0438 \u043c\u043e\u0434\u043e\u0432! \u0418\u043b\u0438 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0438\u0433\u0440\u044b -> \u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 (\u0432\u0435\u0440\u0441\u0438\u0438) -> \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0444\u0430\u0439\u043b\u044b, \u0447\u0442\u043e\u0431\u044b \u0440\u0435\u0448\u0438\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443. -crash.advice.NoSuchFieldError=\u041c\u0430\u0439\u043d\u043a\u0440\u0430\u0444\u0442 \u0438\u043b\u0438 \u043c\u043e\u0434\u044b, \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043d\u0435\u043f\u043e\u043b\u043d\u044b\u043c\u0438. \u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0435, \u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u0441\u043a\u0430\u0447\u0430\u043b\u0438 \u0438\u043b\u0438 \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0438\u0433\u0440\u0443 \u0438 \u043c\u043e\u0434\u043e\u0432! -crash.advice.LWJGLException=\u041c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c, \u0432\u0430\u0448 \u0432\u0438\u0434\u0435\u043e \u0434\u0440\u0430\u0439\u0432\u0435\u0440 \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u0435 \u0432\u0430\u0448 \u0432\u0438\u0434\u0435\u043e \u0434\u0440\u0430\u0439\u0432\u0435\u0440. -crash.advice.SecurityException=\u041c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c, \u0432\u044b \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u0438 minecraft.jar \u043d\u043e \u043d\u0435 \u0443\u0434\u0430\u043b\u0438\u043b\u0438 META-INF. -crash.advice.OutOfMemoryError=\u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u043f\u0430\u043c\u044f\u0442\u0438 \u0434\u043b\u044f JVM \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043c\u0430\u043b, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u0435 \u0435\u0433\u043e. -crash.advice.otherwise=\u041c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043c\u043e\u0434\u044b \u0432\u044b\u0437\u0432\u0430\u043b\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b. - -crash.advice.OpenGL=\u041c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430 \u0432\u044b\u0437\u0432\u0430\u043b\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b. -crash.advice.no_lwjgl=\u041c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430 \u0432\u044b\u0437\u0432\u0430\u043b\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b. - -crash.advice.no=\u041d\u0438\u043a\u0430\u043a\u0438\u0435 \u0441\u043e\u0432\u0435\u0442\u044b. - -crash.user_fault=\u0412\u0430\u0448\u0435\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0438\u043b\u0438 \u0441\u0440\u0435\u0434\u044b java \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e, \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0441\u0431\u043e\u0439 \u044d\u0442\u043e\u0439 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435 \u0432\u0430\u0448\u0443 \u0441\u0440\u0435\u0434\u0443 java \u0438\u043b\u0438 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440! -crash.headless=\u0415\u0441\u043b\u0438 \u0432\u0430\u0448\u0430 \u041e\u0421 Linux \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Oracle \u0432\u0435\u0440\u0441\u0438\u0438 jdk \u0432\u043c\u0435\u0441\u0442\u043e openjdk, \u0442\u043e \u0438\u043b\u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c "-Djava.awt.headless=false" \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 jvm, \u0438\u043b\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u0435\u0441\u043b\u0438 \u0432\u0430\u0448 x-\u0441\u0435\u0440\u0432\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e. -crash.NoClassDefFound=\u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435 "Launcher" \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0435 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u0435 \u0432 \u043a\u043e\u043c\u043f\u043b\u0435\u043a\u0442\u0435. - -crash.error=Minecraft \u043a\u0440\u0430\u0448\u043d\u0443\u043b\u0441\u044f. -crash.main_class_not_found=\u0413\u043b\u0430\u0432\u043d\u044b\u0439 \u041a\u043b\u0430\u0441\u0441 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d, \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432\u0430\u0448 \u041c\u041a \u0431\u044b\u043b \u043d\u0430\u0440\u0443\u0448\u0435\u043d. -crash.class_path_wrong=\u041c\u043e\u0436\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u043a\u0440\u0438\u043f\u0442 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439. - -ui.label.newProfileWindow.new_profile_name=\u041d\u043e\u0432\u043e\u0435 \u0418\u043c\u044f \u041f\u0440\u043e\u0444\u0438\u043b\u044f: -ui.label.newProfileWindow.copy_from=\u0421\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0418\u0437: -ui.newProfileWindow.title=\u041d\u043e\u0432\u044b\u0439 \u041a\u043e\u043d\u0444\u0438\u0433 - -ui.button.ok=OK -ui.button.refresh=\u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c -ui.button.run=\u0418\u0433\u0440\u0430\u0442\u044c -ui.button.settings=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 -ui.button.about=About -ui.button.others=\u0414\u0440\u0443\u0433\u0438\u0435 -ui.button.logout=\u0412\u044b\u0439\u0442\u0438 -ui.button.download=\u0421\u043a\u0430\u0447\u0430\u0442\u044c -ui.button.retry=\u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u044c -ui.button.delete=\u0423\u0434\u0430\u043b\u0438\u0442\u044c -ui.button.install=\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c -ui.button.info=\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f -ui.button.save=\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c -ui.button.copy=\u0421\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c -ui.button.clear=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u044c -ui.button.close=\u0417\u0430\u043a\u0440\u044b\u0442\u044c -ui.button.explore=\u0412\u044b\u0431\u0440\u0430\u0442\u044c -ui.button.test=\u0422\u0435\u0441\u0442 -ui.button.preview=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c -button.cancel=\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c -button.ok=OK -button.yes=\u0434\u0430 -button.no=\u041d\u0435\u0430 - -ui.label.version=\u0412\u0435\u0440\u0441\u0438\u044f -ui.label.password=\u041f\u0430\u0440\u043e\u043b\u044c -ui.label.profile=\u041f\u0440\u043e\u0444\u0438\u043b\u044c - -ui.message.first_load=\u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u0432\u0430\u0448 \u043d\u0438\u043a. -ui.message.enter_password=\u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u0412\u0430\u0448 \u043f\u0430\u0440\u043e\u043b\u044c. -ui.message.launching=\u0417\u0430\u043f\u0443\u0441\u043a... -ui.message.making=\u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f... -ui.message.sure_remove=\u041d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c\u0442\u0435 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u043f\u0440\u043e\u0444\u0438\u043b\u044c %s? -ui.message.update_java=\u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u0435 \u0432\u0430\u0448 Java. -ui.message.open_jdk=\u041c\u044b \u0443\u0436\u0435 \u0432\u044b\u044f\u0441\u043d\u0438\u043b\u0438, \u0447\u0442\u043e \u0432\u044b \u043d\u0430\u0447\u0430\u043b\u0438 \u044d\u0442\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f OpenJDK, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0442\u0430\u043d\u0435\u0442 \u043f\u0440\u0438\u0447\u0438\u043d\u043e\u0439 \u0441\u0442\u043e\u043b\u044c\u043a\u0438\u0445 \u0431\u0435\u0434 \u0434\u043b\u044f \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430. \u041c\u044b \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u043c \u0412\u0430\u043c \u0432\u043c\u0435\u0441\u0442\u043e \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Oracle \u0432\u0435\u0440\u0441\u0438\u0438 JDK. - -ui.label.settings=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 -ui.label.crashing=Hello Minecraft! Launcher \u043a\u0440\u0430\u0448\u043d\u0443\u043b\u0441\u044f! -ui.label.crashing_out_dated=Hello Minecraft! Launcher \u043a\u0440\u0430\u0448\u043d\u0443\u043b\u0441\u044f! \u0412\u0430\u0448 \u043b\u0430\u0443\u043d\u0447\u0435\u0440 \u0443\u0441\u0442\u0430\u0440\u0435\u043b. \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0435\u0433\u043e -ui.label.failed_set=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c: - -download=\u0421\u043a\u0430\u0447\u0430\u0442\u044c -download.mojang=Mojang -download.BMCL=BMCLAPI (bangbang93, http://bmclapi.bangbang93.com/) -download.rapid_data=RapidData (https://www.rapiddata.org/) -download.not_200=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0441\u043a\u0430\u0447\u0430\u0442\u044c, \u043a\u043e\u0434 \u043e\u0442\u0432\u0435\u0442\u0430 -download.failed=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0441\u043a\u0430\u0447\u0430\u0442\u044c -download.successfully=\u0423\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u043a\u0430\u0447\u0430\u043b -download.source=\u0421\u043a\u0430\u0447\u0430\u0442\u044c \u0418\u0441\u0445\u043e\u0434\u043d\u0438\u043a - -message.error=\u041e\u0448\u0438\u0431\u043a\u0430 -message.cannot_open_explorer=Cannot open explorer: -message.cancelled=\u041e\u0442\u043c\u0435\u043d\u0435\u043d -message.info=\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f -message.loading=\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430... - -folder.game=Game Dir -folder.mod=\u041c\u043e\u0434 -folder.coremod=Core Mod -folder.config=\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 -folder.resourcepacks=\u0420\u0435\u0441\u0443\u0440\u0441 \u043f\u0430\u043a\u0438 -folder.screenshots=\u0421\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u044b -folder.saves=\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c - -settings.tabs.game_download=\u0421\u043a\u0430\u0447\u0430\u0442\u044c \u0438\u0433\u0440\u0443 -settings.tabs.installers=\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0449\u0438\u043a -settings.tabs.assets_downloads=\u0414\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f - -settings=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 -settings.explore=\u0412\u044b\u0431\u0440\u0430\u0442\u044c -settings.manage=\u0423\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c -settings.cannot_remove_default_config=\u041d\u0435 \u0443\u0434\u0430\u0435\u0442\u0441\u044f \u0443\u0434\u0430\u043b\u0438\u0442\u044c configution \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e. -settings.max_memory=Max Memory/MB -settings.java_dir=Java Dir -settings.game_directory=\u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u0418\u0433\u0440\u044b -settings.dimension=\u0418\u0433\u0440\u0430 \u041e\u043a\u043d\u043e \u0418\u0437\u043c\u0435\u0440\u0435\u043d\u0438\u044f -settings.fullscreen=\u041f\u043e\u043b\u043d\u043e\u044d\u043a\u0440\u0430\u043d\u043d\u044b\u0439 -settings.update_version=\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 json. -settings.run_directory=\u0417\u0430\u043f\u0443\u0441\u043a \u041a\u0430\u0442\u0430\u043b\u043e\u0433\u0430(\u0418\u0437\u043e\u043b\u044f\u0446\u0438\u044f \u0412\u0435\u0440\u0441\u0438\u044f) -settings.physical_memory=\u0420\u0430\u0437\u043c\u0435\u0440 \u0424\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u041f\u0430\u043c\u044f\u0442\u0438 -settings.choose_javapath=\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u041a\u0430\u0442\u0430\u043b\u043e\u0433 Java. -settings.default=Default -settings.custom=\u0412\u044b\u0431\u0440\u0430\u0442\u044c -settings.choose_gamedir=\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u0414\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e \u0418\u0433\u0440\u044b -settings.failed_load=\u041d\u0435 \u0441\u043c\u043e\u0433 \u0444\u0430\u0439\u043b \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438. \u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0435\u0433\u043e? -settings.test_game=\u0422\u0435\u0441\u0442\u043e\u0432\u0430\u044f \u0438\u0433\u0440\u0430 - -settings.type.none=\u041d\u0435\u0442 \u0432\u0435\u0440\u0441\u0438\u0438 \u0438\u0433\u0440\u044b, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043e\u0442\u043a\u0440\u043e\u0439\u0442\u0435 \u043d\u0430 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u0441\u043a\u0430\u0447\u0430\u0442\u044c \u0438\u0433\u0440\u044b. -settings.type.global=\u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u0437\u0434\u0435\u0441\u044c, \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u0432 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0432\u0435\u0440\u0441\u0438\u0439. \u0421\u0435\u0439\u0447\u0430\u0441 \u044d\u0442\u043e \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u0430\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430. -settings.type.special=\u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u0437\u0434\u0435\u0441\u044c, \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u0432 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438. \u041d\u0435 \u044d\u0442\u043e \u0432\u0435\u0440\u0441\u0438\u0438 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u0445. - -modpack=\u041c\u043e\u0434 \u043f\u0430\u043a -modpack.choose=\u0412\u044b\u0431\u0440\u0430\u0442\u044c zip-\u0444\u0430\u0439\u043b, \u043f\u0430\u043a\u0435\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c. \u0415\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u043f\u0430\u043a\u0435\u0442, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u0432\u0435\u0440\u0441\u0438\u044e \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c. -modpack.export_error=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0430\u043a\u0435\u0442, \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0424\u043e\u0440\u043c\u0430\u0442 \u0432\u0430\u0448\u0435\u0439 \u0438\u0433\u0440\u043e\u0432\u043e\u0439 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0438\u043b\u0438 \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0444\u0430\u0439\u043b\u0430\u043c\u0438. -modpack.export_finished=\u042d\u043a\u0441\u043f\u043e\u0440\u0442 \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0439, \u0433\u043e\u0442\u043e\u0432\u044b\u0435. \u0421\u043c\u043e\u0442\u0440\u0435\u0442\u044c -modpack.included_launcher=\u0412 \u043f\u0430\u043a\u0435\u0442 \u0432\u0445\u043e\u0434\u0438\u0442 \u043f\u0443\u0441\u043a\u043e\u0432\u0430\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0441\u0440\u0430\u0437\u0443. -modpack.not_included_launcher=\u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0430\u043a\u0435\u0442, \u043d\u0430\u0436\u0430\u0432 \u043a\u043d\u043e\u043f\u043a\u0443 "\u0418\u043c\u043f\u043e\u0440\u0442 \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0439". -modpack.enter_name=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0436\u0435\u043b\u0430\u0435\u043c\u043e\u0435 \u0438\u043c\u044f \u0434\u043b\u044f \u044d\u0442\u043e\u0439 \u0438\u0433\u0440\u044b. - -modpack.task.save=\u042d\u0441\u043a\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c Modpack -modpack.task.install=\u0418\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c Modpack -modpack.task.install.error=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043f\u0430\u043a\u0435\u0442. \u041c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c, \u0444\u0430\u0439\u043b\u044b \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e, \u0438\u043b\u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f. -modpack.task.install.will=\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043f\u0430\u043a\u0435\u0442: - -modpack.wizard=\u042d\u043a\u0441\u043f\u043e\u0440\u0442 modpack \u043c\u0430\u0441\u0442\u0435\u0440 -modpack.wizard.step.1=\u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b -modpack.wizard.step.1.title=\u041d\u0430\u0431\u043e\u0440 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 modpack. -modpack.wizard.step.initialization.include_launcher=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043b\u0430\u0443\u043d\u0447\u0435\u0440 -modpack.wizard.step.initialization.exported_version=\u042d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c\u044b\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u0438\u0433\u0440\u044b -modpack.wizard.step.initialization.save=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043f\u0430\u043f\u043a\u0443 \u0434\u043b\u044f \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430 \u0438\u0433\u0440\u043e\u0432\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 \u0434\u043b\u044f -modpack.wizard.step.initialization.warning=\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0443\u0434, \u0432\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u0432\u0430\u0448\u0430 \u0438\u0433\u0440\u0430 \u0441\u043c\u043e\u0436\u0435\u0442 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430,
    \u0438 \u0447\u0442\u043e \u0432\u0430\u0448 minecraft-\u044d\u0442\u043e \u0440\u0435\u043b\u0438\u0437, \u0430 \u043d\u0435 \u0441\u043d\u0438\u043c\u043e\u043a.
    \u0430 \u0447\u0442\u043e \u043d\u0435\u043b\u044c\u0437\u044f \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043c\u043e\u0434\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b\u0438 \u0440\u0430\u0437\u0434\u0430\u0432\u0430\u0442\u044c modpack. -modpack.wizard.step.2=\u0412\u044b\u0431\u043e\u0440 \u0444\u0430\u0439\u043b\u043e\u0432 -modpack.wizard.step.2.title=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0444\u0430\u0439\u043b\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0412\u044b \u043d\u0435 \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u0432 modpack. -modpack.wizard.step.3=\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 -modpack.wizard.step.3.title=\u041e\u043f\u0438\u0448\u0438\u0442\u0435 \u0432\u0430\u0448 modpack. - -modpack.desc=\u041e\u043f\u0438\u0448\u0438\u0442\u0435 \u0441\u0432\u043e\u044e modpack, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u043c\u0435\u0440\u044b \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u043e\u0440\u043e\u0436\u043d\u043e\u0441\u0442\u0438, changlog, \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044f \u0443\u0446\u0435\u043d\u043a\u0438(\u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043e\u043d\u043b\u0430\u0439\u043d-\u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0438). -modpack.incorrect_format.no_json=\u0424\u043e\u0440\u043c\u0430\u0442 \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0439, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0435\u0432\u0435\u0440\u043d\u044b\u043c, \u043f\u0430\u043a\u0435\u0442.json-\u044d\u0442\u043e \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442. -modpack.incorrect_format.no_jar=\u0424\u043e\u0440\u043c\u0430\u0442 modpack \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e, \u043f\u0430\u043a\u0435\u0442.json \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 '\u0431\u0430\u043d\u043a\u0443' -modpack.cannot_read_version=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0432\u0435\u0440\u0441\u0438\u0438 \u0438\u0433\u0440\u044b -modpack.not_a_valid_location=\u041d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u043c modpack \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 -modpack.name=Modpack \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 -modpack.not_a_valid_name=\u041d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u043c modpack \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 - -modpack.files.servers_dat=\u0421\u043f\u0438\u0441\u043e\u043a \u043c\u043d\u043e\u0433\u043e\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u0432 -modpack.files.saves=\u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u043d\u044b\u0435 \u0438\u0433\u0440\u044b -modpack.files.mods=\u041c\u043e\u0434\u044b -modpack.files.config=Mod \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 -modpack.files.liteconfig=Mod \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 -modpack.files.resourcepacks=\u0420\u0435\u0441\u0443\u0440\u0441(\u0442\u0435\u043a\u0441\u0442\u0443\u0440) \u043f\u0430\u043a\u0438 -modpack.files.options_txt=\u0412\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u0438\u0433\u0440\u044b -modpack.files.optionsshaders_txt=\u0412\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u0448\u0435\u0439\u0434\u0435\u0440\u044b -modpack.files.mods.voxelmods=VoxelMods (\u0432\u043a\u043b\u044e\u0447\u0430\u044f VoxelMap) \u0444\u0443\u043d\u043a\u0446\u0438\u0438 -modpack.files.dumps=NEI \u043e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u044b\u0439 \u0432\u044b\u0432\u043e\u0434 -modpack.files.scripts=MineTweaker \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 -modpack.files.blueprints=BuildCraft \u0447\u0435\u0440\u0442\u0435\u0436\u0438 - -mods=\u041c\u043e\u0434\u044b -mods.choose_mod=\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u0432\u0430\u0448\u0438 \u043c\u043e\u0434\u044b -mods.failed=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043c\u043e\u0434\u044b -mods.add=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c -mods.remove=\u0423\u0434\u0430\u043b\u0438\u0442\u044c -mods.default_information=\u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0443\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0439 Forge \u0438\u043b\u0438 LiteLoader \u043f\u0435\u0440\u0435\u0434 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u043e\u0439 \u043c\u043e\u0434\u043e\u0432!
    \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0441\u0432\u043e\u0439 mod \u0444\u0430\u0439\u043b\u043e\u0432 \u0438\u0437 \u043f\u0440\u043e\u0432\u043e\u0434\u043d\u0438\u043a\u0430/Finder \u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u043c\u043e\u0434\u043e\u0432 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043d\u043e\u043f\u043a\u0438 \u0443\u0434\u0430\u043b\u0438\u0442\u044c.
    \u041e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043c\u043e\u0434, \u043e\u0441\u0442\u0430\u0432\u0438\u0432 \u0444\u043b\u0430\u0436\u043e\u043a \u0441\u043d\u044f\u0442; \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u0442\u043e\u0432\u0430\u0440, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e.
    - -advancedsettings=\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u0439 -advancedsettings.launcher_visible=\u041b\u0430\u0443\u043d\u0447\u0435\u0440 \u0412\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u044c -advancedsettings.debug_mode=\u0420\u0435\u0436\u0438\u043c \u041e\u0442\u043b\u0430\u0434\u043a\u0438 -advancedsettings.java_permanent_generation_space=PermGen Space/MB -advancedsettings.jvm_args=Java VM Arguments -advancedsettings.Minecraft_arguments=\u041c\u0430\u0439\u043d\u043a\u0440\u0430\u0444\u0442 \u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b -advancedsettings.launcher_visibility.close=\u0417\u0430\u043a\u0440\u044b\u0442\u044c \u043b\u0430\u0443\u043d\u0447\u0435\u0440, \u0435\u0441\u043b\u0438 \u0438\u0433\u0440\u0430 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u0430. -advancedsettings.launcher_visibility.hide=\u0421\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0437\u0430\u043f\u0443\u0441\u043a\u0430, \u043a\u043e\u0433\u0434\u0430 \u0438\u0433\u0440\u0430 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u0430. -advancedsettings.launcher_visibility.keep=\u0414\u0435\u0440\u0436\u0438\u0442\u0435 \u043f\u0443\u0441\u043a\u043e\u0432\u0443\u044e \u0432\u0438\u0434\u043d\u044b. -advancedsettings.launcher_visibility.hide_reopen=\u0421\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0433\u043e \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u044f, \u043a\u043e\u0433\u0434\u0430 \u0438\u0433\u0440\u0430 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f. -advancedsettings.game_dir.default=\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e (.minecraft/) -advancedsettings.game_dir.independent=\u041d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b\u0435 (.minecraft/\u0432\u0435\u0440\u0441\u0438\u0438/<\u043d\u043e\u043c\u0435\u0440 \u0432\u0435\u0440\u0441\u0438\u0438>/, \u0437\u0430 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u0430\u043a\u0442\u0438\u0432\u043e\u0432,\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438) -advancedsettings.no_jvm_args=No Default JVM Args -advancedsettings.no_common=\u041d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u0449\u0438\u0439 \u043f\u0443\u0442\u044c -advancedsettings.java_args_default=Default java args: -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode -XX:-UseAdaptiveSizePolicy -XX:MaxPermSize=???m -Xmx???m -Dfml.ignoreInvalidMinecraftCertificates=true -Dfml.ignorePatchDiscrepancies=true -advancedsettings.wrapper_launcher=\u041b\u0430\u0443\u043d\u0447\u0435\u0440-\u043e\u0431\u043e\u043b\u043e\u0447\u043a\u0443(\u043a\u0430\u043a \u0438 optirun...) -advancedsettings.precall_command=\u041a\u043e\u043c\u0430\u043d\u0434\u0430 Precalling(\u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0434\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0438\u0433\u0440\u044b) -advancedsettings.server_ip=\u0421\u0435\u0440\u0432\u0435\u0440\u0430 -advancedsettings.cancel_wrapper_launcher=\u041e\u0442\u043c\u0435\u043d\u0430 \u0417\u0430\u043f\u0443\u0441\u043a\u0430 \u041e\u0431\u043e\u043b\u043e\u0447\u043a\u0438 -advancedsettings.dont_check_game_completeness=\u041d\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0442\u0443 \u0438\u0433\u0440\u044b - -mainwindow.show_log=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u041b\u043e\u0433\u0438 -mainwindow.make_launch_script=\u0421\u0434\u0435\u043b\u0430\u0442\u044c \u0417\u0430\u043f\u0443\u0441\u043a \u0421\u043a\u0440\u0438\u043f\u0442\u0430. -mainwindow.make_launch_script_failed=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441\u043a\u0440\u0438\u043f\u0442. -mainwindow.enter_script_name=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0438\u043c\u044f \u0441\u043a\u0440\u0438\u043f\u0442\u0430. -mainwindow.make_launch_succeed=\u0417\u0430\u043a\u043e\u043d\u0447\u0438\u043b \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u0430. -mainwindow.no_version=\u0412\u0435\u0440\u0441\u0438\u0438 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u044b. \u041f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043d\u0430 \u0432\u043a\u043b\u0430\u0434\u043a\u0443 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438\u0433\u0440\u044b? - -launcher.about=\u041e\u0431 \u0410\u0432\u0442\u043e\u0440\u0435
    \u041c\u0430\u0439\u043d\u043a\u0440\u0430\u0444\u0442 \u0444\u043e\u0440\u0443\u043c ID: klkl6523
    Copyright (c) 2013 huangyuhui
    Opened source under GPL v3 license:http://github.com/huanghongxun/HMCL/
    This software used project Gson which is under Apache License 2.0, thanks contributors. -launcher.download_source=\u0421\u043a\u0430\u0447\u0430\u0442\u044c \u0418\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 -launcher.background_location=\u0424\u043e\u043d \u0420\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 -launcher.common_location=\u041e\u0431\u0449\u0435\u0435 \u0420\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 -launcher.exit_failed=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0437\u0430\u043a\u0440\u044b\u0442\u044c. -launcher.versions_json_not_matched=\u0412\u0435\u0440\u0441\u0438\u044f %s \u0443\u0440\u043e\u0434\u043b\u0438\u0432! \u0415\u0441\u0442\u044c \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 json:%s \u0432 \u044d\u0442\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438. \u0425\u043e\u0442\u0438\u0442\u0435 \u043b\u0438 \u0432\u044b \u0440\u0435\u0448\u0438\u0442\u044c \u044d\u0442\u0443 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443? -launcher.versions_json_not_matched_cannot_auto_completion=\u0412\u0435\u0440\u0441\u0438\u044f %s \u043f\u043e\u0442\u0435\u0440\u044f\u043d\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u0432\u0435\u0440\u0441\u0438\u0438 \u0444\u0430\u0439\u043b\u0430, \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0435\u0433\u043e? -launcher.versions_json_not_formatted=\u0421\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e \u0432\u0435\u0440\u0441\u0438\u0438 %s \u0443\u0440\u043e\u0434\u043b\u0438\u0432! \u041f\u043e\u0432\u0442\u043e\u0440\u043d\u0430\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430? -launcher.choose_bgpath=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0444\u043e\u043d\u043e\u0432\u044b\u0439 \u043f\u0443\u0442\u0438. -launcher.choose_commonpath=\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u043e\u0431\u0449\u0438\u0439 \u043f\u0443\u0442\u044c. -launcher.commpath_tooltip=\u042d\u0442\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432\u0441\u0435 \u0438\u0433\u0440\u043e\u0432\u044b\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438 \u0430\u043a\u0442\u0438\u0432\u044b \u0437\u0434\u0435\u0441\u044c, \u0435\u0441\u043b\u0438 \u0442\u0430\u043c \u043d\u0435\u0442 \u0444\u0430\u0439\u043b\u043e\u0432 \u0432 \u043f\u0430\u043f\u043a\u0443 \u0441 \u0438\u0433\u0440\u043e\u0439. -launcher.background_tooltip=\u041b\u0430\u0443\u0447\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0444\u043e\u043d.
    \u0415\u0441\u043b\u0438 \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0444\u043e\u043d.PNG, \u0441\u0441\u044b\u043b\u043a\u0443 \u0438 \u043e\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f.
    \u0415\u0441\u043b\u0438 \u0435\u0441\u0442\u044c "\u0411\u0413" \u043f\u043e\u0434\u043a\u0430\u0442\u0430\u043b\u043e\u0433, \u044d\u0442\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u0442 \u043e\u0434\u043d\u0443 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0443 \u0432 "bgskin" \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e.
    \u0415\u0441\u043b\u0438 \u0432\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0444\u043e\u043d, \u044d\u0442\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e. -launcher.update_launcher=\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f -launcher.enable_shadow=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c Window Shadow -launcher.enable_animation=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c Animation -launcher.enable_blur=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c Blur -launcher.theme=\u0422\u0435\u043c\u0430 -launcher.proxy=\u041f\u0440\u043e\u043a\u0441\u0438 -launcher.decorated=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0433\u0440\u0430\u043d\u0438\u0446\u044b \u043e\u043a\u043d\u0430(\u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u044d\u0442\u0443 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443, \u0447\u0442\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0442\u0441\u044f \u0432\u0441\u0435 \u0441\u0435\u0440\u044b\u0435 \u0432 \u041e\u0421 Linux) -launcher.modpack=\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0434\u043b\u044f modpacks. -launcher.lang=\u042f\u0437\u044b\u043a (Language) -launcher.restart=\u0412\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u0431\u0443\u0434\u0443\u0442 \u0432 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438, \u0442\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u043b\u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u044d\u0442\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. -launcher.log_font=\u0428\u0440\u0438\u0444\u0442 \u041b\u043e\u0433\u0430 -launcher.tab.general=\u041e\u0431\u0449\u0438\u0435 -launcher.tab.ui=\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 -launcher.tab.about=\u0410\u0432\u0442\u043e\u0440 - -launcher.title.game=\u0418\u0433\u0440\u044b -launcher.title.main=\u0413\u043b\u0430\u0432\u043d\u0430\u044f -launcher.title.launcher=\u041b\u0430\u0443\u043d\u0447\u0435\u0440 - -versions.release=Release -versions.snapshot=Snapshot -versions.old_beta=Beta -versions.old_alpha=Old Alpha - -versions.manage.rename=\u041f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u0443 \u0432\u0435\u0440\u0441\u0438\u044e -versions.manage.rename.message=\u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u043d\u043e\u0432\u044b\u0439 \u043d\u0438\u043a -versions.manage.remove=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0432\u0435\u0440\u0441\u0438\u044e -versions.manage.remove.confirm=\u041d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c\u0442\u0435 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0432\u0435\u0440\u0441\u0438\u044e -versions.manage.redownload_json=\u041f\u043e\u0432\u0442\u043e\u0440\u043d\u0430\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0432 Minecraft(minecraft.json) -versions.manage.redownload_assets_index=\u0418\u043d\u0434\u0435\u043a\u0441 \u041f\u0435\u0440\u0435\u043a\u0430\u0447\u0430\u0439\u0442\u0435 \u0410\u043a\u0442\u0438\u0432\u043e\u0432 -versions.mamage.remove_libraries=\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0443\u0434\u0430\u043b\u044f\u0442\u044c \u0444\u0430\u0439\u043b\u044b - -advice.os64butjdk32=\u0412\u0430\u0448\u0430 \u041e\u0421 64-\u0431\u0438\u0442\u043d\u044b\u0445 \u043d\u043e \u0432\u0430\u0448 java \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f 32-\u0440\u0430\u0437\u0440\u044f\u0434\u043d\u043e\u0439. \u0412 64-\u0440\u0430\u0437\u0440\u044f\u0434\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 java \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f. -advice.java8=Java 8 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043b, \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0438\u0433\u0440\u0443 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043f\u043b\u0430\u0432\u043d\u043e. \u0418 \u043c\u043d\u043e\u0433\u043e \u043c\u043e\u0434\u043e\u0432 \u0438 \u041c\u0430\u0439\u043d\u043a\u0440\u0430\u0444\u0442 1.12 \u0438 \u043d\u043e\u0432\u044b\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f java 8. - -assets.download_all=\u0421\u043a\u0430\u0447\u0430\u0442\u044c \u0424\u0430\u0439\u043b\u044b -assets.not_refreshed=\u0421\u043f\u0438\u0441\u043e\u043a \u0430\u043a\u0442\u0438\u0432\u043e\u0432 \u043d\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442\u0441\u044f, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u0435 \u0435\u0433\u043e \u043e\u0434\u0438\u043d \u0440\u0430\u0437. -assets.failed=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a, \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0435\u0449\u0435 \u0440\u0430\u0437. -assets.list.1_7_3_after=1.7.3 \u0438 \u0432\u044b\u0448\u0435 -assets.list.1_6=1.6(BMCLAPI) -assets.unkown_type_select_one=\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u0438\u0433\u0440\u044b: %s, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0442\u0438\u043f \u0430\u043a\u0442\u0438\u0432\u0430. -assets.type=\u0422\u0438\u043f \u0410\u043a\u0442\u0438\u0432\u0430 -assets.download=\u0421\u043a\u0430\u0447\u0430\u0442\u044c \u0410\u043a\u0442\u0438\u0432\u044b -assets.no_assets=\u0410\u043a\u0442\u0438\u0432\u043e\u0432 \u043d\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0430, \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u0438\u0445? -assets.failed_download=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0430\u043a\u0442\u0438\u0432\u044b, \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u0437\u0432\u0443\u043a\u043e\u0432 \u0438 \u044f\u0437\u044b\u043a\u043e\u0432\u044b\u0435 \u0444\u0430\u0439\u043b\u044b. - -gamedownload.not_refreshed=\u0421\u043f\u0438\u0441\u043e\u043a \u0438\u0433\u0440 \u043d\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442\u0441\u044f, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u0435 \u0435\u0433\u043e \u043e\u0434\u0438\u043d \u0440\u0430\u0437. - -taskwindow.title=\u0417\u0430\u0434\u0430\u0447\u0438 -taskwindow.single_progress=\u041e\u0434\u0438\u043d \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0441 -taskwindow.total_progress=\u041e\u0431\u0449\u0438\u0439 \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0441 -taskwindow.cancel=\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c -taskwindow.no_more_instance=\u041c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c, \u0432\u044b \u043e\u0442\u043a\u0440\u044b\u043b\u0438 \u0431\u043e\u043b\u044c\u0448\u0435 \u0447\u0435\u043c \u043e\u0434\u043d\u043e \u043e\u043a\u043d\u043e \u0437\u0430\u0434\u0430\u0447, \u043d\u0435 \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u0435\u0433\u043e \u0441\u043d\u043e\u0432\u0430! -taskwindow.file_name=\u0417\u0430\u0434\u0430\u0447\u0430 -taskwindow.download_progress=\u041f\u0440\u043e\u0446\u0435\u043d\u0442\u044b. - -setupwindow.include_minecraft=\u0418\u043c\u043f\u043e\u0440\u0442 \u0438\u0433\u0440\u044b -setupwindow.find_in_configurations=\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0438\u043c\u043f\u043e\u0440\u0442\u0430. \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043d\u0430\u0439\u0442\u0438 \u0435\u0433\u043e \u0432 \u043f\u0430\u043d\u0435\u043b\u0438 \u0432\u044b\u0431\u043e\u0440\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438. -setupwindow.give_a_name=\u0414\u0430\u0442\u044c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043d\u043e\u0432\u043e\u0439 \u0438\u0433\u0440\u044b. -setupwindow.new=\u041d\u043e\u0432\u043e\u0435 -setupwindow.no_empty_name=\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u043c. -setupwindow.clean=\u0427\u0438\u0441\u0442\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0438\u0433\u0440\u044b - -update.no_browser=\u041d\u0435 \u043c\u043e\u0436\u0435\u0442\u0435 \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u043b\u044e\u0431\u044b\u043c \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u043c. \u0421\u0441\u044b\u043b\u043a\u0430 \u0431\u044b\u043b\u0430 \u0441\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u0432 \u0431\u0443\u0444\u0435\u0440 \u043e\u0431\u043c\u0435\u043d\u0430. \u0412\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u0435\u0433\u043e \u0432 \u0430\u0434\u0440\u0435\u0441\u043d\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c. -update.should_open_link=\u0412\u044b \u0433\u043e\u0442\u043e\u0432\u044b \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u043b\u0430\u0443\u043d\u0447\u0435\u0440? -update.newest_version=\u0421\u0430\u043c\u0430\u044f \u043d\u043e\u0432\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f: -update.failed=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439. -update.found=(\u041d\u0430\u0448\u0435\u043b \u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435!) - -logwindow.terminate_game=\u0417\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u0418\u0433\u0440\u0443 -logwindow.title=\u041b\u043e\u0433 -logwindow.contact=\u0421\u0432\u044f\u0436\u0438\u0442\u0435\u0441\u044c \u0421 \u041d\u0430\u043c\u0438 -logwindow.show_lines=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0421\u0442\u0440\u043e\u043a\u0438 -logwindow.search=\u041f\u043e\u0438\u0441\u043a - -selector.choose=\u0412\u044b\u0431\u0440\u0430\u0442\u044c - -serverlistview.title=\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440 -serverlistview.name=\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 -serverlistview.type=\u0422\u0438\u043f -serverlistview.version=\u0412\u0435\u0440\u0441\u0438\u044f -serverlistview.info=\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f - -minecraft.invalid=Invalid -minecraft.invalid_jar=Invalid Jar -minecraft.not_a_file=Not a file -minecraft.not_found=Not found -minecraft.not_readable=Not readable -minecraft.modified=(Modified!) - -color.red=\u041a\u0440\u0430\u0441\u043d\u044b\u0439 -color.blue=\u0413\u043e\u043b\u0443\u0431\u043e\u0439 -color.green=\u0417\u0435\u043b\u0435\u043d\u044b\u0439 -color.orange=\u041e\u0440\u0430\u043d\u0436\u0435\u0432\u044b\u0439 -color.dark_blue=\u0422\u0435\u043c\u043d\u043e-\u0421\u0438\u043d\u0438\u0439 -color.purple=\u0424\u0438\u043e\u043b\u0435\u0442\u043e\u0432\u044b\u0439 - -wizard.next_>=Next > -wizard.next_mnemonic=N -wizard.<_prev=< Prev -wizard.prev_mnemonic=P -wizard.finish=Finish -wizard.finish_mnemonic=F -wizard.cancel=Cancel -wizard.cancel_mnemonic=C -wizard.help=Help -wizard.help_mnemonic=H -wizard.close=Close -wizard.close_mnemonic=C -wizard.summary=Summary -wizard.failed=Failed -wizard.steps=Steps - -lang=Russian -lang.default=Belong to OS language. - diff --git a/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_vi.lang b/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_vi.lang deleted file mode 100644 index a5a32c980..000000000 --- a/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_vi.lang +++ /dev/null @@ -1,438 +0,0 @@ -# Hello Minecraft! Launcher. -# Copyright (C) 2013 huangyuhui -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see {http://www.gnu.org/licenses/}. -# -#author: LADBOSSHOSS -launch.failed=Mở minecraft không thành công. -launch.failed_creating_process=Tạo tiến trình chạy thất bại, có thể nơi bạn cài java đã bị sai, vui lòng hãy chỉnh sửa lại đường dẫn cài java. -launch.failed_sh_permission=Thêm quyền vào đoạn mã chạy launcher thất bại. -launch.failed_packing_jar=Đóng gói file jar thất bại -launch.unsupported_launcher_version=Xin lỗi, launcher không mở được minecraft, nhưng launcher sẽ cố gắng để chạy. -launch.too_big_memory_alloc_64bit=Bạn đã cho minecraft dùng quá nhiều RAM, vì máy bạn dùng 32-Bit Java Runtime Environment, Minecraft có thể bị crash. Mức RAM cho minecraft dùng cao nhất là 1024MB. Launcher sẽ thử để chạy mnecraft -launch.too_big_memory_alloc_free_space_too_low=Bạn đã cho minecraft dùng quá nhiều RAM, vì ram của bạn chỉ có %dMB, minecraft có thể bị crash. Launcher sẽ thử để chạy -launch.cannot_create_jvm=Launcher không tạo được máy ảo java để chạy minecraft. Java argument có thể có vấn đề, bạn có thể bật chế độ no args trong cài đặt -launch.circular_dependency_versions=Đã tìm thấy phiên bản minecraft không phù hợp, xin hãy xem phiên bản minecraft đã được chỉnh sửa hay không. -launch.not_finished_downloading_libraries=Không download được libraries cho minecraft, có tiếp tục mở game không? -launch.not_finished_decompressing_natives=Không giải nén được libraries cho minecraft, có tiếp tục mở game không? -launch.wrong_javadir=Đường dẫn cài java bị sai, launcher sẽ reset lại đường dẫn java đúng -launch.exited_abnormally=Minecraft đã bị thoát bất thường, hãy xem file log, hoặc nói với người khác giúp. - -launch.state.logging_in=Đang đăng nhập... -launch.state.generating_launching_codes=Đang tạo code chạy minecraft -launch.state.downloading_libraries=Downloading... -launch.state.decompressing_natives=Giải nén... -launch.state.waiting_launching=Waiting for game launching - -install.no_version=Không tìm thấy phiên bản minecraft. -install.no_version_if_intall=Phiên bản cần thiết không thấy, có nên cài đặt phiên bản tự động không? -install.not_refreshed=Danh sách cài chưa được làm mới -install.download_list=Danh sách download - -install.liteloader.get_list=Lấy LiteLoader List -install.liteloader.install=Cài LiteLoader - -install.forge.get_list=Get Forge List -install.forge.install=Cài Forge -install.forge.get_changelogs=Lấy Forge Changelogs - -install.optifine.install=Cài OptiFine -install.optifine.get_list=Lấy OptiFine Download List -install.optifine.get_download_link=Lấy download link của Optifine - -install.failed_forge=Không cài được Forge -install.failed_optifine=Không cài được Optifine -install.failed_liteloader=Không cài được LiteLoader -install.failed_download_forge=Failed to Download Forge -install.failed_download_optifine=Failed to Download OptiFine -install.failed=Không cài được -install.success=Cài đặt thành công -install.no_forge=No Forge -install.choose_forge=Chọn phiên bản bạn muốn cài Forge -install.version=Phiên bản -install.mcversion=Game Version -install.time=Time -install.release_time=Thời gian phát hành -install.type=Type -install.please_refresh=Nếu bạn muốn cài một thứ gì đó, hãy ấn nút "Tải lại". - -crash.launcher=Launcher bị crash rồi! -crash.minecraft=Minecraft bị crash rồi! - -login.choose_charactor=Xin hãy chọn nhân vật bạn muốn -login.no_charactor=Không có nhân vật trong tài khoản này. -login.your_password=Mật khẩu của bạn -login.failed=Không đăng nhập được -login.no_Player007=You have not set username! -login.wrong_password=Mật khẩu hoặc username đã sai. -login.invalid_username=Username không đúng -login.invalid_uuid_and_username=UUID và username không đúng -login.invalid_password=Mật khẩu không đúng -login.invalid_access_token=Access Token bị sai -login.changed_client_token=Server đã thay đổi client token. -login.not_email=Username phải là email -login.type=Login -login.username=Username: -login.account=Email: -login.invalid_token=Hãy đăng xuất và đăng nhập lại. -login.no_valid_character=Không có nhân vật hợp lệ, hãy vào trang web skinme.cc và tạo một nhân vật cho bạn. - -proxy.username=Tài khoản -proxy.password=Mật khẩu -proxy.host=Host -proxy.port=Số cổng - -login.failed.connect_authentication_server=Không thể kết nối đến máy chủ xác thực, hãy xem lại kết nối mạng của bạn - -login.profile.not_logged_in=Không đăng nhập vào được và không thể chính sửa cấu hình. -login.profile.selected=Không chỉnh sửa được cấu hình, bạn phải đăng xuất ra rồi làm lại. - -login.methods.yggdrasil=Mojang -login.methods.offline=Offline -login.methods.no_method=Không có chế độ nào - -log.playername_null=Tên của người chơi trống. - -minecraft.no_selected_version=Bạn chưa chọn phiên bản minecraft! -minecraft.wrong_path=Đường dẫn minecraft bị sai, launcher không tìm thấy được đường dẫn - -operation.stopped=Quá trình đã được dừng lại. -operation.confirm_stop=Dừng lại quá trình không? - -ui.login.password=Mật khẩu -ui.more=Xem thêm - -crash.advice.UnsupportedClassVersionError=Phiên bản java của bạn quá cũ, hãy thử cập nhật phiên bản java -crash.advice.ConcurrentModificationException=Có thể phiên bản java của bạn mới hơn phiên bản 1.8.0_11, Bạn có thể hạ cấp java xuông phiên bản 7. -crash.advice.ClassNotFoundException=Minecraft hoặc mod chưa được hoàn thành. Hãy thử lại nếu có một số libraries chưa được tải về hoặc cập nhật phiên bản minecraft và mod. Hoặc bạn có thể chọn Game Settings -> Manage (Version) -> Xóa libraries để sửa lỗi. -crash.advice.NoSuchFieldError=Minecraft hoặc mod chưa được hoàn thành. Hãy thử lại nếu có một số libraries chưa được tải về hoặc cập nhật phiên bản minecraft và mod. -crash.advice.LWJGLException=Có thể video driver của bạn không hoạt động tốt cho lắm, hãy thử cập nhật video driver của bạn. -crash.advice.SecurityException=Có thể bạn đã chỉnh sửa file minecraft.jar nhưng bạn chưa xóa file META-INF -crash.advice.OutOfMemoryError=Lượng RAM cao nhất của máy áo java quá nhỏ, hãy chỉnh sửa nó. -crash.advice.otherwise=Có thể mods đã làm ra lỗi. -crash.advice.OpenGL=Có thể drivers đã làm ra lỗi -crash.advice.no_lwjgl=Có thể drivers đã làm ra lỗi -crash.advice.no=Không có lời khuyên. - -crash.user_fault=Hệ điều hành hoặc java của bạn có thể đã cài đặt không đúng cách dẫn đến sự crash của launcher, hãy cài lại java và xem lại máy tính của bạn! -crash.headless=Nếu hệ điều hành của bạn là Linux, hãy dùng Oracle JDK thay cho OpenJDK, hoặc thêm vào "-Djava.awt.headless=false" vào argument của máy ảo java, hoặc xem nếu Xserver có hoạt động hay không -crash.NoClassDefFound=Hãy kiểm tra phần mềm "HMCL" đã hoàn thành - -crash.error=Minecraft đã bị crash. -crash.main_class_not_found=Class chính của minecraft không tìm thấy, có lẽ phiên bản minecraft đã bị lỗi. -crash.class_path_wrong=Có lẽ đoạn mã chạy launcher đã bị lỗi - -ui.label.newProfileWindow.new_profile_name=Tên cấu hình mới: -ui.label.newProfileWindow.copy_from=Copy từ: -ui.newProfileWindow.title=Cấu hình mới - -ui.button.ok=OK -ui.button.refresh=Tải lại -ui.button.run=Play -ui.button.settings=Cài đặt -ui.button.about=About -ui.button.others=Khác -ui.button.logout=Đăng xuất -ui.button.download=Tải về -ui.button.retry=Thử lại -ui.button.delete=Xóa -ui.button.install=Cài -ui.button.info=Thông tin -ui.button.save=Lưu -ui.button.copy=Copy -ui.button.clear=Xóa -ui.button.close=Đóng -ui.button.explore=Explore -ui.button.test=Test -ui.button.preview=Xem trước -button.cancel=Thoát -button.ok=OK -button.yes=Yes -button.no=No - -ui.label.version=Phiên bản -ui.label.password=Mật khẩu -ui.label.profile=Cấu hình - -ui.message.first_load=Hãy nhập username của bạn vào. -ui.message.enter_password=Hãy nhập mật khẩu của bạn -ui.message.launching=Launching... -ui.message.making=Generating... -ui.message.sure_remove=Bạn có chắc chắn xóa cấu hình %s không? -ui.message.update_java=Hãy cập nhật phiên bản java của bạn. - -ui.label.settings=Cài đặt -ui.label.crashing=HMCL Minecraft Launcher đã bị crash! -ui.label.crashing_out_dated=HL Minecraft Launcher đã bị crash! Và launcher của bạn không phải là phiên bản mới nhất. cập nhật nó đi! -ui.label.failed_set=Failed to set: -ui.message.open_jdk=We have found that you started this application using OpenJDK, which will cause so many troubles drawing the UI. We suggest you using Oracle JDK instead. - -download=Download -download.mojang=Mojang -download.BMCL=BMCLAPI (bangbang93, http://bmclapi.bangbang93.com/) -download.rapid_data=RapidData (https://www.rapiddata.org/) -download.not_200=Download không thành công, the response code -download.failed=Download không thành công. -download.successfully=Download thành công. -download.source=Download Source - -message.error=Lỗi -message.cannot_open_explorer=Cannot open explorer: -message.cancelled=Đã thoảt -message.info=Thông tin -message.loading=Loading... - -folder.game=Thư mục minecraft -folder.mod=Mod -folder.coremod=Core Mod -folder.config=Cấu hình -folder.resourcepacks=Resourcepacks -folder.screenshots=Ảnh chụp màn hình -folder.saves=Thế giới - -settings.tabs.game_download=Games -settings.tabs.installers=Trình cài đặt -settings.tabs.assets_downloads=Assets - -settings=Settings -settings.explore=Explore -settings.manage=Manage -settings.cannot_remove_default_config=Không thể xóa cấu hình mặc định -settings.max_memory=RAM cao nhất(MB) -settings.java_dir=Thư mục Java -settings.game_directory=Thư mục minecraft -settings.dimension=Khu vực cửa sổ của game -settings.fullscreen=Toàn màn hình -settings.update_version=Update version json. -settings.run_directory=Run Directory(Version Isolation) -settings.physical_memory=Dung lượgg RAM vật lý -settings.choose_javapath=Chọn thư mục java -settings.default=Mặc định -settings.custom=Tùy chỉnh -settings.choose_gamedir=Chọn thư mục game -settings.failed_load=Đọc file cấu hình thất bại. Xóa nó không? -settings.test_game=Chạy thử game - -settings.type.none=No version here, please turn to game download tab. -settings.type.global=Click here to switch to version specialized setting. Now it is global setting. -settings.type.special=Click here to switch to global setting. Not it is version specialized setting. - -modpack=Mod pack -modpack.choose=Chọn modpack zip file mà bạn muốn nhập vào. Nếu bạn muốn cập nhật phiên bản của modpack, Hãy nhập vào phiên bản bạn muốn cập nhật. -modpack.export_error=Xuất modpack ra thất bại, có thể định dạng của thư mục chứa dữ liệu bị sai hoặc không thể quản lý file. -modpack.export_finished=Xuất modpack ra thành công. Xem -modpack.included_launcher=Modpack đã được tích hợp trong launcher, Bạn có thể publish nó. -modpack.not_included_launcher=Dùng nút "Cài Modpack" để cài modpack. -modpack.enter_name=Hãy cho một cái tên mà bạn thích. - -modpack.task.save=Xuất Modpack -modpack.task.install=Cài Modpack -modpack.task.install.error=Cài modpack không thành công, có lẽ file modpack không đúng hoặc là không thể quản lý file -modpack.task.install.will=Launcher sẽ cài modpack: - -modpack.wizard=Công cụ xuất modpack -modpack.wizard.step.1=Tùy chọn cơ bản -modpack.wizard.step.1.title=Chọn các tùy chọn cơ bản cho modpack. -modpack.wizard.step.initialization.include_launcher=Include the launcher -modpack.wizard.step.initialization.exported_version=Phiên bản đã được xuất -modpack.wizard.step.initialization.save=Chọn một thư mục mà bạn muốn xuất game data -modpack.wizard.step.initialization.warning=Trước khi tạo modpack, bạn phải chắc chắn rằng minecraft có thể chạy,
    và phiên bản minecraft là chính thức, không phải là snapshot.
    và nó không cho thêm mods mà không có quyền để tạo modpack. -modpack.wizard.step.2=Chọn file -modpack.wizard.step.2.title=Chọn file bạn không muốn thêm vào modpack -modpack.wizard.step.3=Miêu tả -modpack.wizard.step.3.title=Miêu tả modpack của bạn. - -modpack.desc=Miêu tả modpack của bạn, bao gồm đề phòng, sự thay đổi, dấu gạch xuống(và một số hình ảnh). -modpack.incorrect_format.no_json=Định dạng của modpack không đúng, file pack.json bị thiếu -modpack.incorrect_format.no_jar=Định dạng của modpack không đúng, file pack.json không có đặc tính jar -modpack.cannot_read_version=Lấy phiên bản của minecraft thất bại -modpack.not_a_valid_location=Nơi chứa modpack không đúng -modpack.name=Tên của modpack -modpack.not_a_valid_name=Tên của modpack không đúng - -modpack.files.servers_dat=Danh sách server -modpack.files.saves=Thư mục chứa dữ liệu thế giới -modpack.files.mods=Mods -modpack.files.config=Cấu hình của mod -modpack.files.liteconfig=Cấu hình của LiteLoader -modpack.files.resourcepacks=Resource(Texutre) packs -modpack.files.options_txt=Tùy chọn của game -modpack.files.optionsshaders_txt=Tùy chọn của shaders -modpack.files.mods.voxelmods=Tùy chọn của VoxelMod(tính cả VoxelMap) -modpack.files.dumps=NEI debug output -modpack.files.scripts=Cấu hình của MineTweaker -modpack.files.blueprints=Bản thiết kế cho BuildCraft - -mods=Mods -mods.choose_mod=Chọn mods -mods.failed=Tải mods thất bại -mods.add=Thêm -mods.remove=Xóa -mods.default_information=Bạn hãy chắc chắn rằng bạn đã cài Forge hoặc LiteLoader trước khi cài mods!
    Bạn có thể kéo file mods vào trong cửa sổ này để thêm, và xóa mods bằng cách ấn nút xóa.
    Tắt mods bằng cách bỏ dấu v ở chỗ hộp kiểm; Chọn một mục để biết thêm thông tin.
    - -advancedsettings=Nâng cao -advancedsettings.launcher_visible=Sự hiển thị của launcher -advancedsettings.debug_mode=Chế độ gỡ lỗi -advancedsettings.java_permanent_generation_space=Dung lượng PermGen/MB -advancedsettings.jvm_args=Arguments của máy ảo java -advancedsettings.Minecraft_arguments=Arguments của minecraft -advancedsettings.launcher_visibility.close=Đóng launcher sau khi minecraft được mở. -advancedsettings.launcher_visibility.hide=Ẩn launcher sau khi minecraft được mở. -advancedsettings.launcher_visibility.keep=Để cho launcher hiển thị. -advancedsettings.launcher_visibility.hide_reopen=Hide the launcher and re-open when game closes. -advancedsettings.game_dir.default=Mặc định (.minecraft/) -advancedsettings.game_dir.independent=Independent (.minecraft/versions//, trừ thư mục assets,libraries) -advancedsettings.no_jvm_args=Không có arguments mặc định cho máy ảo java -advancedsettings.no_common=Not using common path -advancedsettings.java_args_default=Java arguments mặc định: -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode -XX:-UseAdaptiveSizePolicy -XX:MaxPermSize=???m -Xmx???m -Dfml.ignoreInvalidMinecraftCertificates=true -Dfml.ignorePatchDiscrepancies=true -advancedsettings.wrapper_launcher=Wrapper Launcher(dạng như optirun...) -advancedsettings.precall_command=Câu lệnh được chạy trước khi game mở -advancedsettings.server_ip=Máy chủ -advancedsettings.cancel_wrapper_launcher=Hủy bỏ Wrapper Launcher -advancedsettings.dont_check_game_completeness=Không kiểm tra game có đầy đủ không. - -mainwindow.show_log=Xem logs -mainwindow.make_launch_script=Tạo đoạn mã launching -mainwindow.make_launch_script_failed=Tạo đoạn mã thất bại -mainwindow.enter_script_name=Nhập tên của đoạn mã. -mainwindow.make_launch_succeed=Đã tạo đoạn mã. -mainwindow.no_version=Không có phiên bản minecraft nào được tìm thấy. Chuyển sang tab Game Download? - -launcher.about=Về tác giả
    Minecraft Forum ID: klkl6523
    Copyright (c) 2013 huangyuhui
    http://github.com/huanghongxun/HMCL/
    Phần mềm này dùng project Gson, cảm ơn người đóng góp. -launcher.download_source=Download Source -launcher.background_location=Background Location -launcher.common_location=Common Location -launcher.exit_failed=Tắt launcher thất bại. -launcher.versions_json_not_matched=The version %s is malformed! There are a json:%s in this version. Do you want to fix this problem? -launcher.versions_json_not_matched_cannot_auto_completion=The version %s lost version information file, delete it? -launcher.versions_json_not_formatted=The version information of %s is malformed! Redownload it? -launcher.choose_bgpath=Choose background path. -launcher.choose_commonpath=Choose common path. -launcher.commpath_tooltip=This app will save all game libraries and assets here unless there are existant files in game folder. -launcher.background_tooltip=This app uses the default background at first.
    If there is background.png in the directory, it will be used.
    If there is "bg" subdirectory, this app will chooses one picture in "bgskin" randomly.
    If you set the background setting, this app will use it. -launcher.update_launcher=Check for update -launcher.enable_shadow=Enable Window Shadow -launcher.enable_animation=Enable Animation -launcher.enable_blur=Enable Blur -launcher.theme=Theme -launcher.proxy=Proxy -launcher.decorated=Enable system window border(in order to fix the problem that the ui become all gray in Linux OS) -launcher.modpack=Documentations for modpacks. -launcher.lang=Language -launcher.restart=Options will be in operations only if restart this app. -launcher.log_font=Log Font -launcher.tab.general=General -launcher.tab.ui=UI -launcher.tab.about=About - -launcher.title.game=Phiên bản & Mods -launcher.title.main=HMCL Main -launcher.title.launcher=Launcher - -versions.release=Chính thức -versions.snapshot=Snapshot -versions.old_beta=Beta -versions.old_alpha=Old Alpha - -versions.manage.rename=Đổi tên phiên bản này -versions.manage.rename.message=Nhập tên mới -versions.manage.remove=Xóa phiên bản này -versions.manage.remove.confirm=Bạn có chắc để xóa phiên bản này không? -versions.manage.redownload_json=Download lại cấu hình của minecraft(minecraft.json) -versions.manage.redownload_assets_index=Download lại Assets Index -versions.mamage.remove_libraries=Xóa libraries file - -advice.os64butjdk32=Hệ điều hành của bạn là 64-Bit nhưng phiên bản Java của bạn là 32-Bit. Khuyên bạn nên dùng Java 64-Bit. -advice.java8=Java 8 is suggested, which can make game run more fluently. And many mods and Minecraft 1.12 and newer versions requires Java 8. - -assets.download_all=Download file assets -assets.not_refreshed=Danh sách assets chưa được load lại, bạn hãy ấn nút Tải lại. -assets.failed=Lấy danh sách thất bại, hãy thử lại. -assets.list.1_7_3_after=1.7.3 và cao hơn -assets.list.1_6=1.6(BMCLAPI) -assets.unkown_type_select_one=Phiên bản minecraft chưa được biết: %s, hãy chọn một loại asset. -assets.type=Loại asset -assets.download=Download Assets -assets.no_assets=Assets chưa được hoàn thành, hoàn thành nó không? -assets.failed_download=Download asset thất bại, có thể sẽ không có âm thanh và ngôn ngữ. - -gamedownload.not_refreshed=Danh sách phiên bản chưa được load lại, bạn hãy ấn nút Tải lại. - -taskwindow.title=Tasks -taskwindow.single_progress=Single progress -taskwindow.total_progress=Total progress -taskwindow.cancel=Cancel -taskwindow.no_more_instance=Maybe you opened more than one task window, dont open it again! -taskwindow.file_name=Task -taskwindow.download_progress=Pgs. - -setupwindow.include_minecraft=Import game -setupwindow.find_in_configurations=Finished importing. You can find it in the configuration selection bar. -setupwindow.give_a_name=Give a name to the new game. -setupwindow.new=New -setupwindow.no_empty_name=Version name cannot be empty. -setupwindow.clean=Clean game files - -update.no_browser=Không thể mở trình duyệt. Đường link đã được copy vào clipboard. Bạn có thể paste nó vào thanh đường link. -update.should_open_link=Bạn có muốn cập nhật launcher không? -update.newest_version=Phiên bản mới nhất: -update.failed=Kiểm tra cập nhật thất bại. -update.found=(Đã tìm thấy bản cập nhật!) - -logwindow.terminate_game=Tắt Game -logwindow.title=HMCL Error Log (Hãy đăng cái này lên forum!) -logwindow.contact=Contact Us -logwindow.show_lines=Show Lines -logwindow.search=Search - -selector.choose=Chọn - -serverlistview.title=Chọn máy chủ -serverlistview.name=Tên -serverlistview.type=Lọai -serverlistview.version=Phiên bản -serverlistview.info=Thông tin - -minecraft.invalid=Không hợp lệ -minecraft.invalid_jar=File jar không hợp lệ -minecraft.not_a_file=Not a file -minecraft.not_found=Không tìm thấy -minecraft.not_readable=Không đọc được -minecraft.modified=(Đã sửa đổi!) - -color.red=Đỏ -color.blue=Xanh da trời -color.green=Xanh lục -color.orange=Cam -color.dark_blue=Xanh da trời tối -color.purple=Tím - -wizard.next_>=Next > -wizard.next_mnemonic=N -wizard.<_prev=< Prev -wizard.prev_mnemonic=P -wizard.finish=Finish -wizard.finish_mnemonic=F -wizard.cancel=Cancel -wizard.cancel_mnemonic=C -wizard.help=Help -wizard.help_mnemonic=H -wizard.close=Close -wizard.close_mnemonic=C -wizard.summary=Summary -wizard.failed=Failed -wizard.steps=Steps - -lang=Vietnamese -lang.default=Thuộc về ngôn ngữ của hệ điều hành \ No newline at end of file diff --git a/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_vi.properties b/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_vi.properties deleted file mode 100644 index 8073b8296..000000000 --- a/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_vi.properties +++ /dev/null @@ -1,438 +0,0 @@ -# Hello Minecraft! Launcher. -# Copyright (C) 2013 huangyuhui -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see {http://www.gnu.org/licenses/}. -# -#author: LADBOSSHOSS -launch.failed=M\u1edf minecraft kh\u00f4ng th\u00e0nh c\u00f4ng. -launch.failed_creating_process=T\u1ea1o ti\u1ebfn tr\u00ecnh ch\u1ea1y th\u1ea5t b\u1ea1i, c\u00f3 th\u1ec3 n\u01a1i b\u1ea1n c\u00e0i java \u0111\u00e3 b\u1ecb sai, vui l\u00f2ng h\u00e3y ch\u1ec9nh s\u1eeda l\u1ea1i \u0111\u01b0\u1eddng d\u1eabn c\u00e0i java. -launch.failed_sh_permission=Th\u00eam quy\u1ec1n v\u00e0o \u0111o\u1ea1n m\u00e3 ch\u1ea1y launcher th\u1ea5t b\u1ea1i. -launch.failed_packing_jar=\u0110\u00f3ng g\u00f3i file jar th\u1ea5t b\u1ea1i -launch.unsupported_launcher_version=Xin l\u1ed7i, launcher kh\u00f4ng m\u1edf \u0111\u01b0\u1ee3c minecraft, nh\u01b0ng launcher s\u1ebd c\u1ed1 g\u1eafng \u0111\u1ec3 ch\u1ea1y. -launch.too_big_memory_alloc_64bit=B\u1ea1n \u0111\u00e3 cho minecraft d\u00f9ng qu\u00e1 nhi\u1ec1u RAM, v\u00ec m\u00e1y b\u1ea1n d\u00f9ng 32-Bit Java Runtime Environment, Minecraft c\u00f3 th\u1ec3 b\u1ecb crash. M\u1ee9c RAM cho minecraft d\u00f9ng cao nh\u1ea5t l\u00e0 1024MB. Launcher s\u1ebd th\u1eed \u0111\u1ec3 ch\u1ea1y mnecraft -launch.too_big_memory_alloc_free_space_too_low=B\u1ea1n \u0111\u00e3 cho minecraft d\u00f9ng qu\u00e1 nhi\u1ec1u RAM, v\u00ec ram c\u1ee7a b\u1ea1n ch\u1ec9 c\u00f3 %dMB, minecraft c\u00f3 th\u1ec3 b\u1ecb crash. Launcher s\u1ebd th\u1eed \u0111\u1ec3 ch\u1ea1y -launch.cannot_create_jvm=Launcher kh\u00f4ng t\u1ea1o \u0111\u01b0\u1ee3c m\u00e1y \u1ea3o java \u0111\u1ec3 ch\u1ea1y minecraft. Java argument c\u00f3 th\u1ec3 c\u00f3 v\u1ea5n \u0111\u1ec1, b\u1ea1n c\u00f3 th\u1ec3 b\u1eadt ch\u1ebf \u0111\u1ed9 no args trong c\u00e0i \u0111\u1eb7t -launch.circular_dependency_versions=\u0110\u00e3 t\u00ecm th\u1ea5y phi\u00ean b\u1ea3n minecraft kh\u00f4ng ph\u00f9 h\u1ee3p, xin h\u00e3y xem phi\u00ean b\u1ea3n minecraft \u0111\u00e3 \u0111\u01b0\u1ee3c ch\u1ec9nh s\u1eeda hay kh\u00f4ng. -launch.not_finished_downloading_libraries=Kh\u00f4ng download \u0111\u01b0\u1ee3c libraries cho minecraft, c\u00f3 ti\u1ebfp t\u1ee5c m\u1edf game kh\u00f4ng? -launch.not_finished_decompressing_natives=Kh\u00f4ng gi\u1ea3i n\u00e9n \u0111\u01b0\u1ee3c libraries cho minecraft, c\u00f3 ti\u1ebfp t\u1ee5c m\u1edf game kh\u00f4ng? -launch.wrong_javadir=\u0110\u01b0\u1eddng d\u1eabn c\u00e0i java b\u1ecb sai, launcher s\u1ebd reset l\u1ea1i \u0111\u01b0\u1eddng d\u1eabn java \u0111\u00fang -launch.exited_abnormally=Minecraft \u0111\u00e3 b\u1ecb tho\u00e1t b\u1ea5t th\u01b0\u1eddng, h\u00e3y xem file log, ho\u1eb7c n\u00f3i v\u1edbi ng\u01b0\u1eddi kh\u00e1c gi\u00fap. - -launch.state.logging_in=\u0110ang \u0111\u0103ng nh\u1eadp... -launch.state.generating_launching_codes=\u0110ang t\u1ea1o code ch\u1ea1y minecraft -launch.state.downloading_libraries=Downloading... -launch.state.decompressing_natives=Gi\u1ea3i n\u00e9n... -launch.state.waiting_launching=Waiting for game launching - -install.no_version=Kh\u00f4ng t\u00ecm th\u1ea5y phi\u00ean b\u1ea3n minecraft. -install.no_version_if_intall=Phi\u00ean b\u1ea3n c\u1ea7n thi\u1ebft kh\u00f4ng th\u1ea5y, c\u00f3 n\u00ean c\u00e0i \u0111\u1eb7t phi\u00ean b\u1ea3n t\u1ef1 \u0111\u1ed9ng kh\u00f4ng? -install.not_refreshed=Danh s\u00e1ch c\u00e0i ch\u01b0a \u0111\u01b0\u1ee3c l\u00e0m m\u1edbi -install.download_list=Danh s\u00e1ch download - -install.liteloader.get_list=L\u1ea5y LiteLoader List -install.liteloader.install=C\u00e0i LiteLoader - -install.forge.get_list=Get Forge List -install.forge.install=C\u00e0i Forge -install.forge.get_changelogs=L\u1ea5y Forge Changelogs - -install.optifine.install=C\u00e0i OptiFine -install.optifine.get_list=L\u1ea5y OptiFine Download List -install.optifine.get_download_link=L\u1ea5y download link c\u1ee7a Optifine - -install.failed_forge=Kh\u00f4ng c\u00e0i \u0111\u01b0\u1ee3c Forge -install.failed_optifine=Kh\u00f4ng c\u00e0i \u0111\u01b0\u1ee3c Optifine -install.failed_liteloader=Kh\u00f4ng c\u00e0i \u0111\u01b0\u1ee3c LiteLoader -install.failed_download_forge=Failed to Download Forge -install.failed_download_optifine=Failed to Download OptiFine -install.failed=Kh\u00f4ng c\u00e0i \u0111\u01b0\u1ee3c -install.success=C\u00e0i \u0111\u1eb7t th\u00e0nh c\u00f4ng -install.no_forge=No Forge -install.choose_forge=Ch\u1ecdn phi\u00ean b\u1ea3n b\u1ea1n mu\u1ed1n c\u00e0i Forge -install.version=Phi\u00ean b\u1ea3n -install.mcversion=Game Version -install.time=Time -install.release_time=Th\u1eddi gian ph\u00e1t h\u00e0nh -install.type=Type -install.please_refresh=N\u1ebfu b\u1ea1n mu\u1ed1n c\u00e0i m\u1ed9t th\u1ee9 g\u00ec \u0111\u00f3, h\u00e3y \u1ea5n n\u00fat "T\u1ea3i l\u1ea1i". - -crash.launcher=Launcher b\u1ecb crash r\u1ed3i! -crash.minecraft=Minecraft b\u1ecb crash r\u1ed3i! - -login.choose_charactor=Xin h\u00e3y ch\u1ecdn nh\u00e2n v\u1eadt b\u1ea1n mu\u1ed1n -login.no_charactor=Kh\u00f4ng c\u00f3 nh\u00e2n v\u1eadt trong t\u00e0i kho\u1ea3n n\u00e0y. -login.your_password=M\u1eadt kh\u1ea9u c\u1ee7a b\u1ea1n -login.failed=Kh\u00f4ng \u0111\u0103ng nh\u1eadp \u0111\u01b0\u1ee3c -login.no_Player007=You have not set username! -login.wrong_password=M\u1eadt kh\u1ea9u ho\u1eb7c username \u0111\u00e3 sai. -login.invalid_username=Username kh\u00f4ng \u0111\u00fang -login.invalid_uuid_and_username=UUID v\u00e0 username kh\u00f4ng \u0111\u00fang -login.invalid_password=M\u1eadt kh\u1ea9u kh\u00f4ng \u0111\u00fang -login.invalid_access_token=Access Token b\u1ecb sai -login.changed_client_token=Server \u0111\u00e3 thay \u0111\u1ed5i client token. -login.not_email=Username ph\u1ea3i l\u00e0 email -login.type=Login -login.username=Username: -login.account=Email: -login.invalid_token=H\u00e3y \u0111\u0103ng xu\u1ea5t v\u00e0 \u0111\u0103ng nh\u1eadp l\u1ea1i. -login.no_valid_character=Kh\u00f4ng c\u00f3 nh\u00e2n v\u1eadt h\u1ee3p l\u1ec7, h\u00e3y v\u00e0o trang web skinme.cc v\u00e0 t\u1ea1o m\u1ed9t nh\u00e2n v\u1eadt cho b\u1ea1n. - -proxy.username=T\u00e0i kho\u1ea3n -proxy.password=M\u1eadt kh\u1ea9u -proxy.host=Host -proxy.port=S\u1ed1 c\u1ed5ng - -login.failed.connect_authentication_server=Kh\u00f4ng th\u1ec3 k\u1ebft n\u1ed1i \u0111\u1ebfn m\u00e1y ch\u1ee7 x\u00e1c th\u1ef1c, h\u00e3y xem l\u1ea1i k\u1ebft n\u1ed1i m\u1ea1ng c\u1ee7a b\u1ea1n - -login.profile.not_logged_in=Kh\u00f4ng \u0111\u0103ng nh\u1eadp v\u00e0o \u0111\u01b0\u1ee3c v\u00e0 kh\u00f4ng th\u1ec3 ch\u00ednh s\u1eeda c\u1ea5u h\u00ecnh. -login.profile.selected=Kh\u00f4ng ch\u1ec9nh s\u1eeda \u0111\u01b0\u1ee3c c\u1ea5u h\u00ecnh, b\u1ea1n ph\u1ea3i \u0111\u0103ng xu\u1ea5t ra r\u1ed3i l\u00e0m l\u1ea1i. - -login.methods.yggdrasil=Mojang -login.methods.offline=Offline -login.methods.no_method=Kh\u00f4ng c\u00f3 ch\u1ebf \u0111\u1ed9 n\u00e0o - -log.playername_null=T\u00ean c\u1ee7a ng\u01b0\u1eddi ch\u01a1i tr\u1ed1ng. - -minecraft.no_selected_version=B\u1ea1n ch\u01b0a ch\u1ecdn phi\u00ean b\u1ea3n minecraft! -minecraft.wrong_path=\u0110\u01b0\u1eddng d\u1eabn minecraft b\u1ecb sai, launcher kh\u00f4ng t\u00ecm th\u1ea5y \u0111\u01b0\u1ee3c \u0111\u01b0\u1eddng d\u1eabn - -operation.stopped=Qu\u00e1 tr\u00ecnh \u0111\u00e3 \u0111\u01b0\u1ee3c d\u1eebng l\u1ea1i. -operation.confirm_stop=D\u1eebng l\u1ea1i qu\u00e1 tr\u00ecnh kh\u00f4ng? - -ui.login.password=M\u1eadt kh\u1ea9u -ui.more=Xem th\u00eam - -crash.advice.UnsupportedClassVersionError=Phi\u00ean b\u1ea3n java c\u1ee7a b\u1ea1n qu\u00e1 c\u0169, h\u00e3y th\u1eed c\u1eadp nh\u1eadt phi\u00ean b\u1ea3n java -crash.advice.ConcurrentModificationException=C\u00f3 th\u1ec3 phi\u00ean b\u1ea3n java c\u1ee7a b\u1ea1n m\u1edbi h\u01a1n phi\u00ean b\u1ea3n 1.8.0_11, B\u1ea1n c\u00f3 th\u1ec3 h\u1ea1 c\u1ea5p java xu\u00f4ng phi\u00ean b\u1ea3n 7. -crash.advice.ClassNotFoundException=Minecraft ho\u1eb7c mod ch\u01b0a \u0111\u01b0\u1ee3c ho\u00e0n th\u00e0nh. H\u00e3y th\u1eed l\u1ea1i n\u1ebfu c\u00f3 m\u1ed9t s\u1ed1 libraries ch\u01b0a \u0111\u01b0\u1ee3c t\u1ea3i v\u1ec1 ho\u1eb7c c\u1eadp nh\u1eadt phi\u00ean b\u1ea3n minecraft v\u00e0 mod. Ho\u1eb7c b\u1ea1n c\u00f3 th\u1ec3 ch\u1ecdn Game Settings -> Manage (Version) -> X\u00f3a libraries \u0111\u1ec3 s\u1eeda l\u1ed7i. -crash.advice.NoSuchFieldError=Minecraft ho\u1eb7c mod ch\u01b0a \u0111\u01b0\u1ee3c ho\u00e0n th\u00e0nh. H\u00e3y th\u1eed l\u1ea1i n\u1ebfu c\u00f3 m\u1ed9t s\u1ed1 libraries ch\u01b0a \u0111\u01b0\u1ee3c t\u1ea3i v\u1ec1 ho\u1eb7c c\u1eadp nh\u1eadt phi\u00ean b\u1ea3n minecraft v\u00e0 mod. -crash.advice.LWJGLException=C\u00f3 th\u1ec3 video driver c\u1ee7a b\u1ea1n kh\u00f4ng ho\u1ea1t \u0111\u1ed9ng t\u1ed1t cho l\u1eafm, h\u00e3y th\u1eed c\u1eadp nh\u1eadt video driver c\u1ee7a b\u1ea1n. -crash.advice.SecurityException=C\u00f3 th\u1ec3 b\u1ea1n \u0111\u00e3 ch\u1ec9nh s\u1eeda file minecraft.jar nh\u01b0ng b\u1ea1n ch\u01b0a x\u00f3a file META-INF -crash.advice.OutOfMemoryError=L\u01b0\u1ee3ng RAM cao nh\u1ea5t c\u1ee7a m\u00e1y \u00e1o java qu\u00e1 nh\u1ecf, h\u00e3y ch\u1ec9nh s\u1eeda n\u00f3. -crash.advice.otherwise=C\u00f3 th\u1ec3 mods \u0111\u00e3 l\u00e0m ra l\u1ed7i. -crash.advice.OpenGL=C\u00f3 th\u1ec3 drivers \u0111\u00e3 l\u00e0m ra l\u1ed7i -crash.advice.no_lwjgl=C\u00f3 th\u1ec3 drivers \u0111\u00e3 l\u00e0m ra l\u1ed7i -crash.advice.no=Kh\u00f4ng c\u00f3 l\u1eddi khuy\u00ean. - -crash.user_fault=H\u1ec7 \u0111i\u1ec1u h\u00e0nh ho\u1eb7c java c\u1ee7a b\u1ea1n c\u00f3 th\u1ec3 \u0111\u00e3 c\u00e0i \u0111\u1eb7t kh\u00f4ng \u0111\u00fang c\u00e1ch d\u1eabn \u0111\u1ebfn s\u1ef1 crash c\u1ee7a launcher, h\u00e3y c\u00e0i l\u1ea1i java v\u00e0 xem l\u1ea1i m\u00e1y t\u00ednh c\u1ee7a b\u1ea1n! -crash.headless=N\u1ebfu h\u1ec7 \u0111i\u1ec1u h\u00e0nh c\u1ee7a b\u1ea1n l\u00e0 Linux, h\u00e3y d\u00f9ng Oracle JDK thay cho OpenJDK, ho\u1eb7c th\u00eam v\u00e0o "-Djava.awt.headless=false" v\u00e0o argument c\u1ee7a m\u00e1y \u1ea3o java, ho\u1eb7c xem n\u1ebfu Xserver c\u00f3 ho\u1ea1t \u0111\u1ed9ng hay kh\u00f4ng -crash.NoClassDefFound=H\u00e3y ki\u1ec3m tra ph\u1ea7n m\u1ec1m "HMCL" \u0111\u00e3 ho\u00e0n th\u00e0nh - -crash.error=Minecraft \u0111\u00e3 b\u1ecb crash. -crash.main_class_not_found=Class ch\u00ednh c\u1ee7a minecraft kh\u00f4ng t\u00ecm th\u1ea5y, c\u00f3 l\u1ebd phi\u00ean b\u1ea3n minecraft \u0111\u00e3 b\u1ecb l\u1ed7i. -crash.class_path_wrong=C\u00f3 l\u1ebd \u0111o\u1ea1n m\u00e3 ch\u1ea1y launcher \u0111\u00e3 b\u1ecb l\u1ed7i - -ui.label.newProfileWindow.new_profile_name=T\u00ean c\u1ea5u h\u00ecnh m\u1edbi: -ui.label.newProfileWindow.copy_from=Copy t\u1eeb: -ui.newProfileWindow.title=C\u1ea5u h\u00ecnh m\u1edbi - -ui.button.ok=OK -ui.button.refresh=T\u1ea3i l\u1ea1i -ui.button.run=Play -ui.button.settings=C\u00e0i \u0111\u1eb7t -ui.button.about=About -ui.button.others=Kh\u00e1c -ui.button.logout=\u0110\u0103ng xu\u1ea5t -ui.button.download=T\u1ea3i v\u1ec1 -ui.button.retry=Th\u1eed l\u1ea1i -ui.button.delete=X\u00f3a -ui.button.install=C\u00e0i -ui.button.info=Th\u00f4ng tin -ui.button.save=L\u01b0u -ui.button.copy=Copy -ui.button.clear=X\u00f3a -ui.button.close=\u0110\u00f3ng -ui.button.explore=Explore -ui.button.test=Test -ui.button.preview=Xem tr\u01b0\u1edbc -button.cancel=Tho\u00e1t -button.ok=OK -button.yes=Yes -button.no=No - -ui.label.version=Phi\u00ean b\u1ea3n -ui.label.password=M\u1eadt kh\u1ea9u -ui.label.profile=C\u1ea5u h\u00ecnh - -ui.message.first_load=H\u00e3y nh\u1eadp username c\u1ee7a b\u1ea1n v\u00e0o. -ui.message.enter_password=H\u00e3y nh\u1eadp m\u1eadt kh\u1ea9u c\u1ee7a b\u1ea1n -ui.message.launching=Launching... -ui.message.making=Generating... -ui.message.sure_remove=B\u1ea1n c\u00f3 ch\u1eafc ch\u1eafn x\u00f3a c\u1ea5u h\u00ecnh %s kh\u00f4ng? -ui.message.update_java=H\u00e3y c\u1eadp nh\u1eadt phi\u00ean b\u1ea3n java c\u1ee7a b\u1ea1n. - -ui.label.settings=C\u00e0i \u0111\u1eb7t -ui.label.crashing=HMCL Minecraft Launcher \u0111\u00e3 b\u1ecb crash! -ui.label.crashing_out_dated=HL Minecraft Launcher \u0111\u00e3 b\u1ecb crash! V\u00e0 launcher c\u1ee7a b\u1ea1n kh\u00f4ng ph\u1ea3i l\u00e0 phi\u00ean b\u1ea3n m\u1edbi nh\u1ea5t. c\u1eadp nh\u1eadt n\u00f3 \u0111i! -ui.label.failed_set=Failed to set: -ui.message.open_jdk=We have found that you started this application using OpenJDK, which will cause so many troubles drawing the UI. We suggest you using Oracle JDK instead. - -download=Download -download.mojang=Mojang -download.BMCL=BMCLAPI (bangbang93, http://bmclapi.bangbang93.com/) -download.rapid_data=RapidData (https://www.rapiddata.org/) -download.not_200=Download kh\u00f4ng th\u00e0nh c\u00f4ng, the response code -download.failed=Download kh\u00f4ng th\u00e0nh c\u00f4ng. -download.successfully=Download th\u00e0nh c\u00f4ng. -download.source=Download Source - -message.error=L\u1ed7i -message.cannot_open_explorer=Cannot open explorer: -message.cancelled=\u0110\u00e3 tho\u1ea3t -message.info=Th\u00f4ng tin -message.loading=Loading... - -folder.game=Th\u01b0 m\u1ee5c minecraft -folder.mod=Mod -folder.coremod=Core Mod -folder.config=C\u1ea5u h\u00ecnh -folder.resourcepacks=Resourcepacks -folder.screenshots=\u1ea2nh ch\u1ee5p m\u00e0n h\u00ecnh -folder.saves=Th\u1ebf gi\u1edbi - -settings.tabs.game_download=Games -settings.tabs.installers=Tr\u00ecnh c\u00e0i \u0111\u1eb7t -settings.tabs.assets_downloads=Assets - -settings=Settings -settings.explore=Explore -settings.manage=Manage -settings.cannot_remove_default_config=Kh\u00f4ng th\u1ec3 x\u00f3a c\u1ea5u h\u00ecnh m\u1eb7c \u0111\u1ecbnh -settings.max_memory=RAM cao nh\u1ea5t(MB) -settings.java_dir=Th\u01b0 m\u1ee5c Java -settings.game_directory=Th\u01b0 m\u1ee5c minecraft -settings.dimension=Khu v\u1ef1c c\u1eeda s\u1ed5 c\u1ee7a game -settings.fullscreen=To\u00e0n m\u00e0n h\u00ecnh -settings.update_version=Update version json. -settings.run_directory=Run Directory(Version Isolation) -settings.physical_memory=Dung l\u01b0\u1ee3gg RAM v\u1eadt l\u00fd -settings.choose_javapath=Ch\u1ecdn th\u01b0 m\u1ee5c java -settings.default=M\u1eb7c \u0111\u1ecbnh -settings.custom=T\u00f9y ch\u1ec9nh -settings.choose_gamedir=Ch\u1ecdn th\u01b0 m\u1ee5c game -settings.failed_load=\u0110\u1ecdc file c\u1ea5u h\u00ecnh th\u1ea5t b\u1ea1i. X\u00f3a n\u00f3 kh\u00f4ng? -settings.test_game=Ch\u1ea1y th\u1eed game - -settings.type.none=No version here, please turn to game download tab. -settings.type.global=Click here to switch to version specialized setting. Now it is global setting. -settings.type.special=Click here to switch to global setting. Not it is version specialized setting. - -modpack=Mod pack -modpack.choose=Ch\u1ecdn modpack zip file m\u00e0 b\u1ea1n mu\u1ed1n nh\u1eadp v\u00e0o. N\u1ebfu b\u1ea1n mu\u1ed1n c\u1eadp nh\u1eadt phi\u00ean b\u1ea3n c\u1ee7a modpack, H\u00e3y nh\u1eadp v\u00e0o phi\u00ean b\u1ea3n b\u1ea1n mu\u1ed1n c\u1eadp nh\u1eadt. -modpack.export_error=Xu\u1ea5t modpack ra th\u1ea5t b\u1ea1i, c\u00f3 th\u1ec3 \u0111\u1ecbnh d\u1ea1ng c\u1ee7a th\u01b0 m\u1ee5c ch\u1ee9a d\u1eef li\u1ec7u b\u1ecb sai ho\u1eb7c kh\u00f4ng th\u1ec3 qu\u1ea3n l\u00fd file. -modpack.export_finished=Xu\u1ea5t modpack ra th\u00e0nh c\u00f4ng. Xem -modpack.included_launcher=Modpack \u0111\u00e3 \u0111\u01b0\u1ee3c t\u00edch h\u1ee3p trong launcher, B\u1ea1n c\u00f3 th\u1ec3 publish n\u00f3. -modpack.not_included_launcher=D\u00f9ng n\u00fat "C\u00e0i Modpack" \u0111\u1ec3 c\u00e0i modpack. -modpack.enter_name=H\u00e3y cho m\u1ed9t c\u00e1i t\u00ean m\u00e0 b\u1ea1n th\u00edch. - -modpack.task.save=Xu\u1ea5t Modpack -modpack.task.install=C\u00e0i Modpack -modpack.task.install.error=C\u00e0i modpack kh\u00f4ng th\u00e0nh c\u00f4ng, c\u00f3 l\u1ebd file modpack kh\u00f4ng \u0111\u00fang ho\u1eb7c l\u00e0 kh\u00f4ng th\u1ec3 qu\u1ea3n l\u00fd file -modpack.task.install.will=Launcher s\u1ebd c\u00e0i modpack: - -modpack.wizard=C\u00f4ng c\u1ee5 xu\u1ea5t modpack -modpack.wizard.step.1=T\u00f9y ch\u1ecdn c\u01a1 b\u1ea3n -modpack.wizard.step.1.title=Ch\u1ecdn c\u00e1c t\u00f9y ch\u1ecdn c\u01a1 b\u1ea3n cho modpack. -modpack.wizard.step.initialization.include_launcher=Include the launcher -modpack.wizard.step.initialization.exported_version=Phi\u00ean b\u1ea3n \u0111\u00e3 \u0111\u01b0\u1ee3c xu\u1ea5t -modpack.wizard.step.initialization.save=Ch\u1ecdn m\u1ed9t th\u01b0 m\u1ee5c m\u00e0 b\u1ea1n mu\u1ed1n xu\u1ea5t game data -modpack.wizard.step.initialization.warning=Tr\u01b0\u1edbc khi t\u1ea1o modpack, b\u1ea1n ph\u1ea3i ch\u1eafc ch\u1eafn r\u1eb1ng minecraft c\u00f3 th\u1ec3 ch\u1ea1y,
    v\u00e0 phi\u00ean b\u1ea3n minecraft l\u00e0 ch\u00ednh th\u1ee9c, kh\u00f4ng ph\u1ea3i l\u00e0 snapshot.
    v\u00e0 n\u00f3 kh\u00f4ng cho th\u00eam mods m\u00e0 kh\u00f4ng c\u00f3 quy\u1ec1n \u0111\u1ec3 t\u1ea1o modpack. -modpack.wizard.step.2=Ch\u1ecdn file -modpack.wizard.step.2.title=Ch\u1ecdn file b\u1ea1n kh\u00f4ng mu\u1ed1n th\u00eam v\u00e0o modpack -modpack.wizard.step.3=Mi\u00eau t\u1ea3 -modpack.wizard.step.3.title=Mi\u00eau t\u1ea3 modpack c\u1ee7a b\u1ea1n. - -modpack.desc=Mi\u00eau t\u1ea3 modpack c\u1ee7a b\u1ea1n, bao g\u1ed3m \u0111\u1ec1 ph\u00f2ng, s\u1ef1 thay \u0111\u1ed5i, d\u1ea5u g\u1ea1ch xu\u1ed1ng(v\u00e0 m\u1ed9t s\u1ed1 h\u00ecnh \u1ea3nh). -modpack.incorrect_format.no_json=\u0110\u1ecbnh d\u1ea1ng c\u1ee7a modpack kh\u00f4ng \u0111\u00fang, file pack.json b\u1ecb thi\u1ebfu -modpack.incorrect_format.no_jar=\u0110\u1ecbnh d\u1ea1ng c\u1ee7a modpack kh\u00f4ng \u0111\u00fang, file pack.json kh\u00f4ng c\u00f3 \u0111\u1eb7c t\u00ednh jar -modpack.cannot_read_version=L\u1ea5y phi\u00ean b\u1ea3n c\u1ee7a minecraft th\u1ea5t b\u1ea1i -modpack.not_a_valid_location=N\u01a1i ch\u1ee9a modpack kh\u00f4ng \u0111\u00fang -modpack.name=T\u00ean c\u1ee7a modpack -modpack.not_a_valid_name=T\u00ean c\u1ee7a modpack kh\u00f4ng \u0111\u00fang - -modpack.files.servers_dat=Danh s\u00e1ch server -modpack.files.saves=Th\u01b0 m\u1ee5c ch\u1ee9a d\u1eef li\u1ec7u th\u1ebf gi\u1edbi -modpack.files.mods=Mods -modpack.files.config=C\u1ea5u h\u00ecnh c\u1ee7a mod -modpack.files.liteconfig=C\u1ea5u h\u00ecnh c\u1ee7a LiteLoader -modpack.files.resourcepacks=Resource(Texutre) packs -modpack.files.options_txt=T\u00f9y ch\u1ecdn c\u1ee7a game -modpack.files.optionsshaders_txt=T\u00f9y ch\u1ecdn c\u1ee7a shaders -modpack.files.mods.voxelmods=T\u00f9y ch\u1ecdn c\u1ee7a VoxelMod(t\u00ednh c\u1ea3 VoxelMap) -modpack.files.dumps=NEI debug output -modpack.files.scripts=C\u1ea5u h\u00ecnh c\u1ee7a MineTweaker -modpack.files.blueprints=B\u1ea3n thi\u1ebft k\u1ebf cho BuildCraft - -mods=Mods -mods.choose_mod=Ch\u1ecdn mods -mods.failed=T\u1ea3i mods th\u1ea5t b\u1ea1i -mods.add=Th\u00eam -mods.remove=X\u00f3a -mods.default_information=B\u1ea1n h\u00e3y ch\u1eafc ch\u1eafn r\u1eb1ng b\u1ea1n \u0111\u00e3 c\u00e0i Forge ho\u1eb7c LiteLoader tr\u01b0\u1edbc khi c\u00e0i mods!
    B\u1ea1n c\u00f3 th\u1ec3 k\u00e9o file mods v\u00e0o trong c\u1eeda s\u1ed5 n\u00e0y \u0111\u1ec3 th\u00eam, v\u00e0 x\u00f3a mods b\u1eb1ng c\u00e1ch \u1ea5n n\u00fat x\u00f3a.
    T\u1eaft mods b\u1eb1ng c\u00e1ch b\u1ecf d\u1ea5u v \u1edf ch\u1ed7 h\u1ed9p ki\u1ec3m; Ch\u1ecdn m\u1ed9t m\u1ee5c \u0111\u1ec3 bi\u1ebft th\u00eam th\u00f4ng tin.
    - -advancedsettings=N\u00e2ng cao -advancedsettings.launcher_visible=S\u1ef1 hi\u1ec3n th\u1ecb c\u1ee7a launcher -advancedsettings.debug_mode=Ch\u1ebf \u0111\u1ed9 g\u1ee1 l\u1ed7i -advancedsettings.java_permanent_generation_space=Dung l\u01b0\u1ee3ng PermGen/MB -advancedsettings.jvm_args=Arguments c\u1ee7a m\u00e1y \u1ea3o java -advancedsettings.Minecraft_arguments=Arguments c\u1ee7a minecraft -advancedsettings.launcher_visibility.close=\u0110\u00f3ng launcher sau khi minecraft \u0111\u01b0\u1ee3c m\u1edf. -advancedsettings.launcher_visibility.hide=\u1ea8n launcher sau khi minecraft \u0111\u01b0\u1ee3c m\u1edf. -advancedsettings.launcher_visibility.keep=\u0110\u1ec3 cho launcher hi\u1ec3n th\u1ecb. -advancedsettings.launcher_visibility.hide_reopen=Hide the launcher and re-open when game closes. -advancedsettings.game_dir.default=M\u1eb7c \u0111\u1ecbnh (.minecraft/) -advancedsettings.game_dir.independent=Independent (.minecraft/versions//, tr\u1eeb th\u01b0 m\u1ee5c assets,libraries) -advancedsettings.no_jvm_args=Kh\u00f4ng c\u00f3 arguments m\u1eb7c \u0111\u1ecbnh cho m\u00e1y \u1ea3o java -advancedsettings.no_common=Not using common path -advancedsettings.java_args_default=Java arguments m\u1eb7c \u0111\u1ecbnh: -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode -XX:-UseAdaptiveSizePolicy -XX:MaxPermSize=???m -Xmx???m -Dfml.ignoreInvalidMinecraftCertificates=true -Dfml.ignorePatchDiscrepancies=true -advancedsettings.wrapper_launcher=Wrapper Launcher(d\u1ea1ng nh\u01b0 optirun...) -advancedsettings.precall_command=C\u00e2u l\u1ec7nh \u0111\u01b0\u1ee3c ch\u1ea1y tr\u01b0\u1edbc khi game m\u1edf -advancedsettings.server_ip=M\u00e1y ch\u1ee7 -advancedsettings.cancel_wrapper_launcher=H\u1ee7y b\u1ecf Wrapper Launcher -advancedsettings.dont_check_game_completeness=Kh\u00f4ng ki\u1ec3m tra game c\u00f3 \u0111\u1ea7y \u0111\u1ee7 kh\u00f4ng. - -mainwindow.show_log=Xem logs -mainwindow.make_launch_script=T\u1ea1o \u0111o\u1ea1n m\u00e3 launching -mainwindow.make_launch_script_failed=T\u1ea1o \u0111o\u1ea1n m\u00e3 th\u1ea5t b\u1ea1i -mainwindow.enter_script_name=Nh\u1eadp t\u00ean c\u1ee7a \u0111o\u1ea1n m\u00e3. -mainwindow.make_launch_succeed=\u0110\u00e3 t\u1ea1o \u0111o\u1ea1n m\u00e3. -mainwindow.no_version=Kh\u00f4ng c\u00f3 phi\u00ean b\u1ea3n minecraft n\u00e0o \u0111\u01b0\u1ee3c t\u00ecm th\u1ea5y. Chuy\u1ec3n sang tab Game Download? - -launcher.about=V\u1ec1 t\u00e1c gi\u1ea3
    Minecraft Forum ID: klkl6523
    Copyright (c) 2013 huangyuhui
    http://github.com/huanghongxun/HMCL/
    Ph\u1ea7n m\u1ec1m n\u00e0y d\u00f9ng project Gson, c\u1ea3m \u01a1n ng\u01b0\u1eddi \u0111\u00f3ng g\u00f3p. -launcher.download_source=Download Source -launcher.background_location=Background Location -launcher.common_location=Common Location -launcher.exit_failed=T\u1eaft launcher th\u1ea5t b\u1ea1i. -launcher.versions_json_not_matched=The version %s is malformed! There are a json:%s in this version. Do you want to fix this problem? -launcher.versions_json_not_matched_cannot_auto_completion=The version %s lost version information file, delete it? -launcher.versions_json_not_formatted=The version information of %s is malformed! Redownload it? -launcher.choose_bgpath=Choose background path. -launcher.choose_commonpath=Choose common path. -launcher.commpath_tooltip=This app will save all game libraries and assets here unless there are existant files in game folder. -launcher.background_tooltip=This app uses the default background at first.
    If there is background.png in the directory, it will be used.
    If there is "bg" subdirectory, this app will chooses one picture in "bgskin" randomly.
    If you set the background setting, this app will use it. -launcher.update_launcher=Check for update -launcher.enable_shadow=Enable Window Shadow -launcher.enable_animation=Enable Animation -launcher.enable_blur=Enable Blur -launcher.theme=Theme -launcher.proxy=Proxy -launcher.decorated=Enable system window border(in order to fix the problem that the ui become all gray in Linux OS) -launcher.modpack=Documentations for modpacks. -launcher.lang=Language -launcher.restart=Options will be in operations only if restart this app. -launcher.log_font=Log Font -launcher.tab.general=General -launcher.tab.ui=UI -launcher.tab.about=About - -launcher.title.game=Phi\u00ean b\u1ea3n & Mods -launcher.title.main=HMCL Main -launcher.title.launcher=Launcher - -versions.release=Ch\u00ednh th\u1ee9c -versions.snapshot=Snapshot -versions.old_beta=Beta -versions.old_alpha=Old Alpha - -versions.manage.rename=\u0110\u1ed5i t\u00ean phi\u00ean b\u1ea3n n\u00e0y -versions.manage.rename.message=Nh\u1eadp t\u00ean m\u1edbi -versions.manage.remove=X\u00f3a phi\u00ean b\u1ea3n n\u00e0y -versions.manage.remove.confirm=B\u1ea1n c\u00f3 ch\u1eafc \u0111\u1ec3 x\u00f3a phi\u00ean b\u1ea3n n\u00e0y kh\u00f4ng? -versions.manage.redownload_json=Download l\u1ea1i c\u1ea5u h\u00ecnh c\u1ee7a minecraft(minecraft.json) -versions.manage.redownload_assets_index=Download l\u1ea1i Assets Index -versions.mamage.remove_libraries=X\u00f3a libraries file - -advice.os64butjdk32=H\u1ec7 \u0111i\u1ec1u h\u00e0nh c\u1ee7a b\u1ea1n l\u00e0 64-Bit nh\u01b0ng phi\u00ean b\u1ea3n Java c\u1ee7a b\u1ea1n l\u00e0 32-Bit. Khuy\u00ean b\u1ea1n n\u00ean d\u00f9ng Java 64-Bit. -advice.java8=Java 8 is suggested, which can make game run more fluently. And many mods and Minecraft 1.12 and newer versions requires Java 8. - -assets.download_all=Download file assets -assets.not_refreshed=Danh s\u00e1ch assets ch\u01b0a \u0111\u01b0\u1ee3c load l\u1ea1i, b\u1ea1n h\u00e3y \u1ea5n n\u00fat T\u1ea3i l\u1ea1i. -assets.failed=L\u1ea5y danh s\u00e1ch th\u1ea5t b\u1ea1i, h\u00e3y th\u1eed l\u1ea1i. -assets.list.1_7_3_after=1.7.3 v\u00e0 cao h\u01a1n -assets.list.1_6=1.6(BMCLAPI) -assets.unkown_type_select_one=Phi\u00ean b\u1ea3n minecraft ch\u01b0a \u0111\u01b0\u1ee3c bi\u1ebft: %s, h\u00e3y ch\u1ecdn m\u1ed9t lo\u1ea1i asset. -assets.type=Lo\u1ea1i asset -assets.download=Download Assets -assets.no_assets=Assets ch\u01b0a \u0111\u01b0\u1ee3c ho\u00e0n th\u00e0nh, ho\u00e0n th\u00e0nh n\u00f3 kh\u00f4ng? -assets.failed_download=Download asset th\u1ea5t b\u1ea1i, c\u00f3 th\u1ec3 s\u1ebd kh\u00f4ng c\u00f3 \u00e2m thanh v\u00e0 ng\u00f4n ng\u1eef. - -gamedownload.not_refreshed=Danh s\u00e1ch phi\u00ean b\u1ea3n ch\u01b0a \u0111\u01b0\u1ee3c load l\u1ea1i, b\u1ea1n h\u00e3y \u1ea5n n\u00fat T\u1ea3i l\u1ea1i. - -taskwindow.title=Tasks -taskwindow.single_progress=Single progress -taskwindow.total_progress=Total progress -taskwindow.cancel=Cancel -taskwindow.no_more_instance=Maybe you opened more than one task window, dont open it again! -taskwindow.file_name=Task -taskwindow.download_progress=Pgs. - -setupwindow.include_minecraft=Import game -setupwindow.find_in_configurations=Finished importing. You can find it in the configuration selection bar. -setupwindow.give_a_name=Give a name to the new game. -setupwindow.new=New -setupwindow.no_empty_name=Version name cannot be empty. -setupwindow.clean=Clean game files - -update.no_browser=Kh\u00f4ng th\u1ec3 m\u1edf tr\u00ecnh duy\u1ec7t. \u0110\u01b0\u1eddng link \u0111\u00e3 \u0111\u01b0\u1ee3c copy v\u00e0o clipboard. B\u1ea1n c\u00f3 th\u1ec3 paste n\u00f3 v\u00e0o thanh \u0111\u01b0\u1eddng link. -update.should_open_link=B\u1ea1n c\u00f3 mu\u1ed1n c\u1eadp nh\u1eadt launcher kh\u00f4ng? -update.newest_version=Phi\u00ean b\u1ea3n m\u1edbi nh\u1ea5t: -update.failed=Ki\u1ec3m tra c\u1eadp nh\u1eadt th\u1ea5t b\u1ea1i. -update.found=(\u0110\u00e3 t\u00ecm th\u1ea5y b\u1ea3n c\u1eadp nh\u1eadt!) - -logwindow.terminate_game=T\u1eaft Game -logwindow.title=HMCL Error Log (H\u00e3y \u0111\u0103ng c\u00e1i n\u00e0y l\u00ean forum!) -logwindow.contact=Contact Us -logwindow.show_lines=Show Lines -logwindow.search=Search - -selector.choose=Ch\u1ecdn - -serverlistview.title=Ch\u1ecdn m\u00e1y ch\u1ee7 -serverlistview.name=T\u00ean -serverlistview.type=L\u1ecdai -serverlistview.version=Phi\u00ean b\u1ea3n -serverlistview.info=Th\u00f4ng tin - -minecraft.invalid=Kh\u00f4ng h\u1ee3p l\u1ec7 -minecraft.invalid_jar=File jar kh\u00f4ng h\u1ee3p l\u1ec7 -minecraft.not_a_file=Not a file -minecraft.not_found=Kh\u00f4ng t\u00ecm th\u1ea5y -minecraft.not_readable=Kh\u00f4ng \u0111\u1ecdc \u0111\u01b0\u1ee3c -minecraft.modified=(\u0110\u00e3 s\u1eeda \u0111\u1ed5i!) - -color.red=\u0110\u1ecf -color.blue=Xanh da tr\u1eddi -color.green=Xanh l\u1ee5c -color.orange=Cam -color.dark_blue=Xanh da tr\u1eddi t\u1ed1i -color.purple=T\u00edm - -wizard.next_>=Next > -wizard.next_mnemonic=N -wizard.<_prev=< Prev -wizard.prev_mnemonic=P -wizard.finish=Finish -wizard.finish_mnemonic=F -wizard.cancel=Cancel -wizard.cancel_mnemonic=C -wizard.help=Help -wizard.help_mnemonic=H -wizard.close=Close -wizard.close_mnemonic=C -wizard.summary=Summary -wizard.failed=Failed -wizard.steps=Steps - -lang=Vietnamese -lang.default=Thu\u1ed9c v\u1ec1 ng\u00f4n ng\u1eef c\u1ee7a h\u1ec7 \u0111i\u1ec1u h\u00e0nh diff --git a/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_zh.lang b/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_zh.lang deleted file mode 100644 index 628b724b4..000000000 --- a/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_zh.lang +++ /dev/null @@ -1,440 +0,0 @@ -# Hello Minecraft! Launcher. -# Copyright (C) 2013 huangyuhui -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see {http://www.gnu.org/licenses/}. -# -#author: byStarTW -launch.failed=啟動失敗 -launch.failed_creating_process=啟動失敗,在新建新任務時發生錯誤,可能是 Java 路徑錯誤。 -launch.failed_sh_permission=為啟動資料添加權限時發生錯誤 -launch.failed_packing_jar=在打包jar時發生錯誤 -launch.unsupported_launcher_version=對不起,本啟動器現在可能不能啟動這個版本的Minecraft,但啟動器還是會嘗試啟動,請盡快將此問題報告給作者。 -launch.too_big_memory_alloc_64bit=您設定的記憶體大小過大,由於可能超過了32位元Java的記憶體分配限制,所以可能無法啟動遊戲,請將記憶體調至1024MB或更小,啟動器仍會嘗試啟動。 -launch.too_big_memory_alloc_free_space_too_low=您設定的記憶體大小過大,由於超過了系統記憶體大小%dMB,所以可能影響遊戲體驗或無法啟動遊戲,啟動器仍會嘗試啟動。 -launch.cannot_create_jvm=擷取到無法創建Java虛擬機,可能是Java參數有問題,可以在設定中開啟無參數模式啟動。 -launch.circular_dependency_versions=發現遊戲版本多次利用,請確認您的客戶端未被修改或修改導致出現此問題。 -launch.not_finished_downloading_libraries=未完成遊戲資料庫的下載,還要繼續啟動遊戲嗎? -launch.not_finished_decompressing_natives=未能解壓遊戲執行庫,還要繼續啟動遊戲嗎? -launch.wrong_javadir=錯誤的Java路徑,將自動重置為預設Java路徑。 -launch.exited_abnormally=遊戲非正常退出,請查看日誌資料,或聯繫他人尋求幫助。 - -launch.state.logging_in=登錄中 -launch.state.generating_launching_codes=正在生成啟動代碼 -launch.state.downloading_libraries=正在下載必要文件 -launch.state.decompressing_natives=正在釋放執行庫 -launch.state.waiting_launching=等待遊戲啟動 - -install.no_version=未找到要安裝的對應MC版本 -install.no_version_if_intall=未找到要安裝的對應MC版本,是否自動安裝需要的MC版本? -install.not_refreshed=未重整列表 -install.download_list=下載列表 - -install.liteloader.get_list=獲取LiteLoader列表 -install.liteloader.install=安裝LiteLoader - -install.forge.get_list=獲取Forge列表 -install.forge.install=安裝Forge -install.forge.get_changelogs=獲取Forge更新記錄 - -install.optifine.install=安裝OptiFine -install.optifine.get_list=獲取OptiFine列表 -install.optifine.get_download_link=獲取OptiFine下載地址 - -install.failed_forge=安裝Forge失敗 -install.failed_optifine=安裝OptiFine失敗 -install.failed_liteloader=安裝LiteLoader失敗 -install.failed_download_forge=下載Forge失敗 -install.failed_download_optifine=下載OptiFine失敗 -install.failed=安裝失敗 -install.success=安裝成功 -install.no_forge=沒有安裝Forge -install.choose_forge=選擇你安裝的Forge版本 -install.version=版本 -install.mcversion=遊戲版本 -install.time=時間 -install.release_time=釋放時間 -install.type=類型 -install.please_refresh=如需使用自動安裝請點擊右側重整按鈕 - -crash.launcher=啟動器崩潰了! -crash.minecraft=Minecraft崩潰了! - -login.choose_charactor=請選擇您要使用的角色 -login.no_charactor=該帳號沒有角色 -login.your_password=您的密碼 -login.failed=登錄失敗: -login.no_Player007=你還未設定用戶名! -login.wrong_password=可能是您的用戶名或密碼錯誤 -login.invalid_username=無效的用戶名 -login.invalid_uuid_and_username=無效的UUID和用戶名 -login.invalid_password=無效的密碼 -login.invalid_access_token=無效的訪問權杖 -login.changed_client_token=伺服器回應已經修改客戶端權杖 -login.not_email=用戶名必須是郵箱 -login.type=登錄 -login.username=名字 -login.account=郵箱 -login.invalid_token=請嘗試登出並重新輸入密碼登錄 -login.no_valid_character=無有效的角色,自行到skinme.cc登陸並創建角色 - -proxy.username=帳戶 -proxy.password=密碼 -proxy.host=主機 -proxy.port=Port - -login.failed.connect_authentication_server=無法連接認證伺服器,可能是網絡問題 - -login.profile.not_logged_in=無法修改遊戲資料同時未登錄 -login.profile.selected=無法修改遊戲資料. 你必須登出再返回. - -login.methods.yggdrasil=正版登錄 -login.methods.offline=離線模式 -login.methods.no_method=沒有登入方式... - -log.playername_null=玩家名為空,這代表著登錄方法出現問題 - -minecraft.no_selected_version=沒有選擇任何一個Minecraft版本 -minecraft.wrong_path=錯誤的Minecraft路徑,啟動器未找到設定的Minecraft路徑,請檢查。 - -operation.stopped=操作被強行終止 -operation.confirm_stop=真的要終止操作嗎? - -ui.login.password=密碼 -ui.more=更多 - -crash.advice.UnsupportedClassVersionError=這可能是因為您的Java版本過於老舊,可以嘗試更換最新Java並在版本設定的Java路徑中設定. -crash.advice.ConcurrentModificationException=這可能是因為您的Java版本高於Java 1.8.0_11導致的,可以嘗試卸載Java8安裝Java7。 -crash.advice.ClassNotFoundException=Minecraft不完整或Mod衝突,如果有未能下載的資料請下載成功後重試或是用戶端損壞請重試請重新製作用戶端或下載整合包解決問題,另可嘗試遊戲設定->(版本)管理->刪除庫資料解決問題 -crash.advice.NoSuchFieldError=Minecraft不完整或Mod衝突,如果有未能下載的資料請下載成功後重試或是用戶端損壞請重試請重新製作用戶端或下載整合包解決問題。 -crash.advice.LWJGLException=您的電腦不正常,可能需要使用驅動精靈或其他安裝器更新顯卡驅動。 -crash.advice.SecurityException=可能是您修改了minecraft.jar但未刪除META-INF資料夾的原因。請通過壓縮軟體刪除jar中的META-INF資料夾。 -crash.advice.OutOfMemoryError=記憶體溢出,您設定的Minecraft最大記憶體過小,請調大! -crash.advice.otherwise=可能是Mod或其他問題。 - -crash.advice.OpenGL=可能是顯卡/聲卡驅動問題,也可能是Mod導致的問題。 -crash.advice.no_lwjgl=可能是遊戲依賴庫不完整或解壓依賴庫時出錯。可以通過下載整合包解決問題。 - -crash.advice.no=無建議。 - -crash.user_fault=您的系統或Java環境可能安裝不當導致本軟體崩潰,請檢查您的Java環境或您的電腦!可以嘗試重新安裝Java。 -crash.headless=如果您的操作系統是Linux,請注意不要使用OpenJDK,務必使用Oracle JDK,或嘗試添加-Djava.awt.headless=false參數,或檢查您的Xserver是否正常 -crash.NoClassDefFound=請確認HMCL本體是否完整 - -crash.error=您的Minecraft崩潰了。 -crash.main_class_not_found=找不到主類,可能是您的JSON資料填寫錯誤。無法啟動遊戲。可以通過下載整合包解決問題。 -crash.class_path_wrong=解析Class Path時出現錯誤,此錯誤本不應該發生。可能是啟動腳本錯誤,請仔細檢查啟動腳本。 - -ui.label.newProfileWindow.new_profile_name=新配置名: -ui.label.newProfileWindow.copy_from=複製配置: -ui.newProfileWindow.title=新建配置 - -ui.button.ok=確認 -ui.button.refresh=重整 -ui.button.run=啟動Minecraft -ui.button.settings= -ui.button.about=關於 -ui.button.others=其他 -ui.button.logout=登出 -ui.button.download=下載 -ui.button.retry=重試 -ui.button.delete=刪除 -ui.button.install=安裝 -ui.button.info=信息 -ui.button.save=保存 -ui.button.copy=複製 -ui.button.clear=清除 -ui.button.close=關閉 -ui.button.explore=瀏覽 -ui.button.test=測試 -ui.button.preview=預覽 -button.cancel=取消 -button.ok=確定 -button.yes=是 -button.no=不 - -ui.label.version=版本 -ui.label.password=密碼 -ui.label.profile=配置 - -ui.message.first_load=請在左邊輸入您的帳號 -ui.message.enter_password=請在左邊輸入您的密碼 -ui.message.launching=啟動中 -ui.message.making=生成中 -ui.message.sure_remove=真的要刪除配置%s嗎? -ui.message.update_java=請更新您的Java -ui.message.open_jdk=我們發現到您正在使用OpenJDK,這可能會導致很多介面問題,我們建議您更換Oracle JDK。 - -ui.label.settings=選項 -ui.label.crashing=Hello Minecraft! Launcher遇到了無法處理的錯誤,請複制下列內容並通過mcbbs、貼吧或Minecraft Forum反饋bug。 -ui.label.crashing_out_dated=Hello Minecraft! Launcher遇到了無法處理的錯誤,已檢測到您的啟動器不是最新版本,請更新後再試! -ui.label.failed_set=設定失敗: - -download=下載 -download.mojang=官方 -download.BMCL=BMCLAPI (bangbang93, http://bmclapi.bangbang93.com/) -download.rapid_data=RapidData (銳網雲計算, https://www.rapiddata.org/) -download.not_200=下載失敗,回復碼 -download.failed=下載失敗 -download.successfully=下載完成 -download.source=下載源 - -message.error=錯誤 -message.cannot_open_explorer=無法打開資料管理器: -message.cancelled=已取消 -message.info=提示 -message.loading=加載中... - -folder.game=遊戲資料夾 -folder.mod=MOD資料夾 -folder.coremod=核心MOD資料夾 -folder.config=配置資料夾 -folder.resourcepacks=資源包資料夾 -folder.screenshots=截圖資料夾 -folder.saves=存檔資料夾 - -settings.tabs.game_download=遊戲下載 -settings.tabs.installers=自動安裝 -settings.tabs.assets_downloads=資源下載 - -settings=普通設定 -settings.explore=瀏覽 -settings.manage=管理 -settings.cannot_remove_default_config=不能刪除預設配置 -settings.max_memory=最大記憶體(MB) -settings.java_dir=Java路徑 -settings.game_directory=遊戲路徑 -settings.dimension=遊戲窗口解析度 -settings.fullscreen=全螢幕 -settings.update_version=更新版本資料 -settings.run_directory=執行路徑(版本隔離) -settings.physical_memory=實體記憶體大小 -settings.choose_javapath=選擇Java路徑 -settings.default=預設 -settings.custom=自定義 -settings.choose_gamedir=選擇遊戲路徑 -settings.failed_load=設定資料加載失敗,可能是升級了啟動器或被人工修改造成錯誤,是否清除? -settings.test_game=測試遊戲 - -settings.type.none=缺少游戲版本,請切換到遊戲下載頁下載遊戲 -settings.type.global=點擊此處切換為版本特定設定。該版本正在使用全局設定,修改以下設定會影響到其他使用全局設定的版本 -settings.type.special=點擊此處切換為全局設定。該版本正在使用版本特定設定,修改以下設定不會影響到其他版本設定 - -modpack=懶人包 -modpack.choose=選擇要導入的遊戲懶人包資料,如果您希望更新懶人包,請輸入要更新的版本名 -modpack.export_error=導出失敗,可能是您的遊戲資料夾格式不正確或操作資料失敗 -modpack.export_finished=懶人包導出完成,參見 -modpack.included_launcher=懶人包已包含啟動器,可直接發布 -modpack.not_included_launcher=懶人包未包含啟動器,可使用本軟件的導入懶人包功能導入懶人包 -modpack.enter_name=給遊戲起個你喜歡的名字 - -modpack.task.save=導出懶人包 -modpack.task.install=導入懶人包 -modpack.task.install.error=安裝失敗,可能是懶人包格式不正確或操作資料失敗 -modpack.task.install.will=將會安裝懶人包: - -modpack.wizard=導出懶人包嚮導 -modpack.wizard.step.1=基本設定 -modpack.wizard.step.1.title=設定懶人包的主要資訊 -modpack.wizard.step.initialization.include_launcher=包含啟動器 -modpack.wizard.step.initialization.exported_version=要導出的遊戲版本 -modpack.wizard.step.initialization.save=選擇要導出到的遊戲懶人包位置 -modpack.wizard.step.initialization.warning=在製作懶人包前,請您確認您選擇的版本可以正常啟動,
    並保證您的Minecraft是正式版而非快照版,
    而且不應當將不允許非官方途徑傳播的Mod、材質包等納入整合包。
    懶人包會保存您目前的下載源設定 -modpack.wizard.step.2=資料選擇 -modpack.wizard.step.2.title=選中你不想加到懶人包中的資料(夾) -modpack.wizard.step.3=懶人包描述 -modpack.wizard.step.3.title=描述你要製作的懶人包。 - -modpack.desc=描述你要製作的懶人包,比如懶人包注意事項和更新記錄,支持Markdown(圖片請用網路圖片)。 -modpack.incorrect_format.no_json=懶人包格式錯誤,pack.json丟失 -modpack.incorrect_format.no_jar=懶人包格式錯誤,pack.json丟失jar欄位 -modpack.cannot_read_version=讀取遊戲版本失敗 -modpack.not_a_valid_location=不是一個有效懶人包位置 -modpack.name=懶人包名稱 -modpack.not_a_valid_name=不是一個有效的懶人包名稱 - -modpack.files.servers_dat=多人遊戲伺服器列表 -modpack.files.saves=遊戲存檔 -modpack.files.mods=Mod -modpack.files.config=Mod設定檔 -modpack.files.liteconfig=Mod設定檔 -modpack.files.resourcepacks=資源包(材質包) -modpack.files.options_txt=遊戲設定 -modpack.files.optionsshaders_txt=光影設定 -modpack.files.mods.voxelmods=VoxelMods設定,如小地圖 -modpack.files.dumps=NEI調試輸出 -modpack.files.scripts=MineTweaker配置 -modpack.files.blueprints=BuildCraft藍圖 - -mods=Mod管理 -mods.choose_mod=選擇模組 -mods.failed=添加失敗 -mods.add=添加 -mods.remove=刪除 -mods.default_information=您可以拖動mod到列表中來添加mod,同時使用刪除鍵可快速刪除選中mod
    選擇mod可以獲取mod資訊 - -advancedsettings=進階設定 -advancedsettings.launcher_visible=啟動器可見性 -advancedsettings.debug_mode=偵錯模式 -advancedsettings.java_permanent_generation_space=記憶體永久保存區域/MB -advancedsettings.jvm_args=Java虛擬機參數(不必填寫) -advancedsettings.Minecraft_arguments=Minecraft額外參數(不必填寫) -advancedsettings.launcher_visibility.close=遊戲啟動後結束啟動器 -advancedsettings.launcher_visibility.hide=遊戲啟動後隱藏啟動器 -advancedsettings.launcher_visibility.keep=保持啟動器可見 -advancedsettings.launcher_visibility.hide_reopen=隱藏啟動器並在遊戲結束後重新打開 -advancedsettings.game_dir.default=預設(.minecraft/) -advancedsettings.game_dir.independent=各版本獨立(.minecraft/versions/<版本名>/,除assets,libraries) -advancedsettings.no_jvm_args=不添加預設的JVM參數(使用Java9時必勾) -advancedsettings.no_common=不使用公共路徑 -advancedsettings.java_args_default=啟動器預設添加的參數(請不要重複添加):-XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode -XX:-UseAdaptiveSizePolicy -XX:MaxPermSize=???m -Xmx???m -Dfml. ignoreInvalidMinecraftCertificates=true -Dfml.ignorePatchDiscrepancies=true -advancedsettings.wrapper_launcher=前置指令(不必填寫,如optirun) -advancedsettings.precall_command=啟動前執行命令(不必填寫,將在遊戲啟動前調用) -advancedsettings.server_ip=直接進入伺服器IP (不必填寫,啟動遊戲後直接進入對應伺服器) -advancedsettings.cancel_wrapper_launcher=取消包裹啟動器(出現奇怪問題時可嘗試使用,與調試模式衝突) -advancedsettings.dont_check_game_completeness=不檢查遊戲完整性 - -mainwindow.show_log=查看日誌 -mainwindow.make_launch_script=生成啟動腳本 -mainwindow.make_launch_script_failed=生成啟動腳本失敗 -mainwindow.enter_script_name=輸入要生成腳本的資料名 -mainwindow.make_launch_succeed=啟動腳本已生成完畢: -mainwindow.no_version=未找到任何版本,是否進入遊戲下載? - -launcher.about=預設背景圖感謝gamerteam提供。
    關於作者:
    百度ID:huanghongxun20
    mcbbs:huanghongxun
    Minecraft Forum ID: klkl6523
    歡迎提交Bug哦
    Copyright (c) 2013-2016 huangyuhui.
    免責聲明:Minecraft軟體版權歸Mojang AB所有,遊戲由於誤操作本啟動器而丟失數據的概不負責。
    本啟動器在GPLv3協議下開源:http://github.com/huanghongxun/HMCL/ ,感謝issues和pull requests貢獻者
    本軟體使用了基於Apache License 2.0的Gson項目,感謝貢獻者。 -launcher.download_source=下載源 -launcher.background_location=背景地址 -launcher.common_location=公用資料夾 -launcher.exit_failed=強制退出失敗,可能是Forge 1.7.10及更高版本導致的,無法解決。 -launcher.versions_json_not_matched=版本%s格式不規範!該版本資料夾下有json:%s,是否更名這個資料來規範格式? -launcher.versions_json_not_matched_cannot_auto_completion=版本%s缺失必要的版本資訊資料,是否刪除該版本? -launcher.versions_json_not_formatted=版本%s資訊資料格式錯誤,是否重新下載? -launcher.choose_bgpath=選擇背景路徑 -launcher.choose_commonpath=選擇公用路徑 -launcher.commpath_tooltip=啟動器將所有遊戲資源跟執行庫檔案放在此處集中管理。如果遊戲資料夾有現成的將不會使用公用庫檔案。 -launcher.background_tooltip=啟動器預設使用自帶的背景
    如果當前目錄有background.png,則會使用該資料作為背景
    如果當前目錄有bg子目錄,則會隨機使用裡面的一張圖作為背景
    如果該背景位址被修改,則會使用背景位址裡的一張圖作為背景
    背景位址允許有多個位址,使用半形分號";"(不包含雙引號)分隔 -launcher.update_launcher=檢查更新 -launcher.enable_shadow=啟用窗口陰影 -launcher.enable_animation=啟用動態效果 -launcher.enable_blur=啟用主介面模糊 -launcher.theme=主題 -launcher.proxy=代理 -launcher.decorated=啟用視窗邊框(Linux下可解決程式介面全灰問題) -launcher.modpack=整合包作者幫助 -launcher.lang=語言 -launcher.restart=本介面選項需要重啟本啟動器生效 -launcher.log_font=日誌字體 -launcher.tab.general=通用 -launcher.tab.ui=介面 -launcher.tab.about=關於 - -launcher.title.game=遊戲設定 -launcher.title.main=主頁 -launcher.title.launcher=啟動器設定 - -versions.release=穩定版 -versions.snapshot=快照版 -versions.old_beta=測試版 -versions.old_alpha=遠古版 - -versions.manage.rename=重新命名該版本 -versions.manage.rename.message=請輸入要改成的名字 -versions.manage.remove=刪除該版本 -versions.manage.remove.confirm=真的要刪除版本 -versions.manage.redownload_json=重新下載版本配置(minecraft.json) -versions.manage.redownload_assets_index=重新下載資源配置(assets_index.json) -versions.mamage.remove_libraries=刪除所有庫檔 - -advice.os64butjdk32=您的系統是64-bit,但是Java是32位的,推薦您安裝64位Java. -advice.java8=檢測到您未使用Java 8及更新版本,Java 8能使遊戲更流暢而且Minecraft 1.12及更新版本和很多Mod強制需要需要Java 8。 - -assets.download_all=下載資源資料 -assets.not_refreshed=資源列表未重整,請重整一次。 -assets.failed=獲取列表失敗,請重整重試。 -assets.list.1_7_3_after=1.7.3及以後 -assets.list.1_6=1.6(BMCLAPI) -assets.unkown_type_select_one=無法解析遊戲版本:%s,請選擇一種資源類型下載。 -assets.type=資源類型 -assets.download=下載資源 -assets.no_assets=資源資料不完整,是否補全? -assets.failed_download=下載資源資料失敗,可能導致沒有中文語系或音樂。 - -gamedownload.not_refreshed=遊戲下載列表未重整,請再重整一次。 - -taskwindow.title=任務 -taskwindow.single_progress=單項進度 -taskwindow.total_progress=總進度 -taskwindow.cancel=取消 -taskwindow.no_more_instance=可能同時打開了多個任務窗口,請不要多次打開! -taskwindow.file_name=任務 -taskwindow.download_progress=進度 - -setupwindow.include_minecraft=導入遊戲資料夾 -setupwindow.find_in_configurations=導入完成,快到配置下拉清單中找新遊戲路徑吧! -setupwindow.give_a_name=給新遊戲路徑起個名字吧 -setupwindow.new=新建 -setupwindow.no_empty_name=名字不可為空 -setupwindow.clean=清理遊戲資料 - -update.no_browser=無法打開瀏覽器,網址已經複製到剪貼版了,您可以手動Copy網址打開頁面 -update.should_open_link=是否更新? -update.newest_version=最新版本為: -update.failed=檢查更新失敗 -update.found=(發現更新!) - -logwindow.terminate_game=結束遊戲進程 -logwindow.title=日誌 -logwindow.contact=聯繫我們 -logwindow.show_lines=顯示行數 -logwindow.search=查找 - -selector.choose=選擇 - -serverlistview.title=選擇伺服器 -serverlistview.name=名稱 -serverlistview.type=類型 -serverlistview.version=版本 -serverlistview.info=信息 - -minecraft.invalid=無效的 -minecraft.invalid_jar=無效的jar包 -minecraft.not_a_file=不是資料 -minecraft.not_found=找不到minecraft.jar -minecraft.not_readable=minecraft.jar不可讀 -minecraft.modified=(修改的!) - -color.red=紅色 -color.blue=藍色 -color.green=綠色 -color.orange=橙色 -color.dark_blue=深藍色 -color.purple=紫色 - -wizard.next_>=下一步 > -wizard.next_mnemonic=下 -wizard.<_prev=< 上一步 -wizard.prev_mnemonic=上 -wizard.finish=完成 -wizard.finish_mnemonic=完 -wizard.cancel=取消 -wizard.cancel_mnemonic=取 -wizard.help=說明 -wizard.help_mnemonic=幫 -wizard.close=關閉 -wizard.close_mnemonic=關 -wizard.summary=概要 -wizard.failed=失敗 -wizard.steps=步驟 - -lang=繁體中文 -lang.default=跟隨系統語言 diff --git a/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_zh.properties b/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_zh.properties deleted file mode 100644 index 2e9c90896..000000000 --- a/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_zh.properties +++ /dev/null @@ -1,440 +0,0 @@ -# Hello Minecraft! Launcher. -# Copyright (C) 2013 huangyuhui -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see {http://www.gnu.org/licenses/}. -# -#author: byStarTW -launch.failed=\u555f\u52d5\u5931\u6557 -launch.failed_creating_process=\u555f\u52d5\u5931\u6557\uff0c\u5728\u65b0\u5efa\u65b0\u4efb\u52d9\u6642\u767c\u751f\u932f\u8aa4\uff0c\u53ef\u80fd\u662f Java \u8def\u5f91\u932f\u8aa4\u3002 -launch.failed_sh_permission=\u70ba\u555f\u52d5\u8cc7\u6599\u6dfb\u52a0\u6b0a\u9650\u6642\u767c\u751f\u932f\u8aa4 -launch.failed_packing_jar=\u5728\u6253\u5305jar\u6642\u767c\u751f\u932f\u8aa4 -launch.unsupported_launcher_version=\u5c0d\u4e0d\u8d77\uff0c\u672c\u555f\u52d5\u5668\u73fe\u5728\u53ef\u80fd\u4e0d\u80fd\u555f\u52d5\u9019\u500b\u7248\u672c\u7684Minecraft\uff0c\u4f46\u555f\u52d5\u5668\u9084\u662f\u6703\u5617\u8a66\u555f\u52d5\uff0c\u8acb\u76e1\u5feb\u5c07\u6b64\u554f\u984c\u5831\u544a\u7d66\u4f5c\u8005\u3002 -launch.too_big_memory_alloc_64bit=\u60a8\u8a2d\u5b9a\u7684\u8a18\u61b6\u9ad4\u5927\u5c0f\u904e\u5927\uff0c\u7531\u65bc\u53ef\u80fd\u8d85\u904e\u4e8632\u4f4d\u5143Java\u7684\u8a18\u61b6\u9ad4\u5206\u914d\u9650\u5236\uff0c\u6240\u4ee5\u53ef\u80fd\u7121\u6cd5\u555f\u52d5\u904a\u6232\uff0c\u8acb\u5c07\u8a18\u61b6\u9ad4\u8abf\u81f31024MB\u6216\u66f4\u5c0f\uff0c\u555f\u52d5\u5668\u4ecd\u6703\u5617\u8a66\u555f\u52d5\u3002 -launch.too_big_memory_alloc_free_space_too_low=\u60a8\u8a2d\u5b9a\u7684\u8a18\u61b6\u9ad4\u5927\u5c0f\u904e\u5927\uff0c\u7531\u65bc\u8d85\u904e\u4e86\u7cfb\u7d71\u8a18\u61b6\u9ad4\u5927\u5c0f%dMB\uff0c\u6240\u4ee5\u53ef\u80fd\u5f71\u97ff\u904a\u6232\u9ad4\u9a57\u6216\u7121\u6cd5\u555f\u52d5\u904a\u6232\uff0c\u555f\u52d5\u5668\u4ecd\u6703\u5617\u8a66\u555f\u52d5\u3002 -launch.cannot_create_jvm=\u64f7\u53d6\u5230\u7121\u6cd5\u5275\u5efaJava\u865b\u64ec\u6a5f\uff0c\u53ef\u80fd\u662fJava\u53c3\u6578\u6709\u554f\u984c\uff0c\u53ef\u4ee5\u5728\u8a2d\u5b9a\u4e2d\u958b\u555f\u7121\u53c3\u6578\u6a21\u5f0f\u555f\u52d5\u3002 -launch.circular_dependency_versions=\u767c\u73fe\u904a\u6232\u7248\u672c\u591a\u6b21\u5229\u7528\uff0c\u8acb\u78ba\u8a8d\u60a8\u7684\u5ba2\u6236\u7aef\u672a\u88ab\u4fee\u6539\u6216\u4fee\u6539\u5c0e\u81f4\u51fa\u73fe\u6b64\u554f\u984c\u3002 -launch.not_finished_downloading_libraries=\u672a\u5b8c\u6210\u904a\u6232\u8cc7\u6599\u5eab\u7684\u4e0b\u8f09\uff0c\u9084\u8981\u7e7c\u7e8c\u555f\u52d5\u904a\u6232\u55ce\uff1f -launch.not_finished_decompressing_natives=\u672a\u80fd\u89e3\u58d3\u904a\u6232\u57f7\u884c\u5eab\uff0c\u9084\u8981\u7e7c\u7e8c\u555f\u52d5\u904a\u6232\u55ce\uff1f -launch.wrong_javadir=\u932f\u8aa4\u7684Java\u8def\u5f91\uff0c\u5c07\u81ea\u52d5\u91cd\u7f6e\u70ba\u9810\u8a2dJava\u8def\u5f91\u3002 -launch.exited_abnormally=\u904a\u6232\u975e\u6b63\u5e38\u9000\u51fa\uff0c\u8acb\u67e5\u770b\u65e5\u8a8c\u8cc7\u6599\uff0c\u6216\u806f\u7e6b\u4ed6\u4eba\u5c0b\u6c42\u5e6b\u52a9\u3002 - -launch.state.logging_in=\u767b\u9304\u4e2d -launch.state.generating_launching_codes=\u6b63\u5728\u751f\u6210\u555f\u52d5\u4ee3\u78bc -launch.state.downloading_libraries=\u6b63\u5728\u4e0b\u8f09\u5fc5\u8981\u6587\u4ef6 -launch.state.decompressing_natives=\u6b63\u5728\u91cb\u653e\u57f7\u884c\u5eab -launch.state.waiting_launching=\u7b49\u5f85\u904a\u6232\u555f\u52d5 - -install.no_version=\u672a\u627e\u5230\u8981\u5b89\u88dd\u7684\u5c0d\u61c9MC\u7248\u672c -install.no_version_if_intall=\u672a\u627e\u5230\u8981\u5b89\u88dd\u7684\u5c0d\u61c9MC\u7248\u672c\uff0c\u662f\u5426\u81ea\u52d5\u5b89\u88dd\u9700\u8981\u7684MC\u7248\u672c\uff1f -install.not_refreshed=\u672a\u91cd\u6574\u5217\u8868 -install.download_list=\u4e0b\u8f09\u5217\u8868 - -install.liteloader.get_list=\u7372\u53d6LiteLoader\u5217\u8868 -install.liteloader.install=\u5b89\u88ddLiteLoader - -install.forge.get_list=\u7372\u53d6Forge\u5217\u8868 -install.forge.install=\u5b89\u88ddForge -install.forge.get_changelogs=\u7372\u53d6Forge\u66f4\u65b0\u8a18\u9304 - -install.optifine.install=\u5b89\u88ddOptiFine -install.optifine.get_list=\u7372\u53d6OptiFine\u5217\u8868 -install.optifine.get_download_link=\u7372\u53d6OptiFine\u4e0b\u8f09\u5730\u5740 - -install.failed_forge=\u5b89\u88ddForge\u5931\u6557 -install.failed_optifine=\u5b89\u88ddOptiFine\u5931\u6557 -install.failed_liteloader=\u5b89\u88ddLiteLoader\u5931\u6557 -install.failed_download_forge=\u4e0b\u8f09Forge\u5931\u6557 -install.failed_download_optifine=\u4e0b\u8f09OptiFine\u5931\u6557 -install.failed=\u5b89\u88dd\u5931\u6557 -install.success=\u5b89\u88dd\u6210\u529f -install.no_forge=\u6c92\u6709\u5b89\u88ddForge -install.choose_forge=\u9078\u64c7\u4f60\u5b89\u88dd\u7684Forge\u7248\u672c -install.version=\u7248\u672c -install.mcversion=\u904a\u6232\u7248\u672c -install.time=\u6642\u9593 -install.release_time=\u91cb\u653e\u6642\u9593 -install.type=\u985e\u578b -install.please_refresh=\u5982\u9700\u4f7f\u7528\u81ea\u52d5\u5b89\u88dd\u8acb\u9ede\u64ca\u53f3\u5074\u91cd\u6574\u6309\u9215 - -crash.launcher=\u555f\u52d5\u5668\u5d29\u6f70\u4e86\uff01 -crash.minecraft=Minecraft\u5d29\u6f70\u4e86\uff01 - -login.choose_charactor=\u8acb\u9078\u64c7\u60a8\u8981\u4f7f\u7528\u7684\u89d2\u8272 -login.no_charactor=\u8a72\u5e33\u865f\u6c92\u6709\u89d2\u8272 -login.your_password=\u60a8\u7684\u5bc6\u78bc -login.failed=\u767b\u9304\u5931\u6557\uff1a -login.no_Player007=\u4f60\u9084\u672a\u8a2d\u5b9a\u7528\u6236\u540d\uff01 -login.wrong_password=\u53ef\u80fd\u662f\u60a8\u7684\u7528\u6236\u540d\u6216\u5bc6\u78bc\u932f\u8aa4 -login.invalid_username=\u7121\u6548\u7684\u7528\u6236\u540d -login.invalid_uuid_and_username=\u7121\u6548\u7684UUID\u548c\u7528\u6236\u540d -login.invalid_password=\u7121\u6548\u7684\u5bc6\u78bc -login.invalid_access_token=\u7121\u6548\u7684\u8a2a\u554f\u6b0a\u6756 -login.changed_client_token=\u4f3a\u670d\u5668\u56de\u61c9\u5df2\u7d93\u4fee\u6539\u5ba2\u6236\u7aef\u6b0a\u6756 -login.not_email=\u7528\u6236\u540d\u5fc5\u9808\u662f\u90f5\u7bb1 -login.type=\u767b\u9304 -login.username=\u540d\u5b57 -login.account=\u90f5\u7bb1 -login.invalid_token=\u8acb\u5617\u8a66\u767b\u51fa\u4e26\u91cd\u65b0\u8f38\u5165\u5bc6\u78bc\u767b\u9304 -login.no_valid_character=\u7121\u6709\u6548\u7684\u89d2\u8272\uff0c\u81ea\u884c\u5230skinme.cc\u767b\u9678\u4e26\u5275\u5efa\u89d2\u8272 - -proxy.username=\u5e33\u6236 -proxy.password=\u5bc6\u78bc -proxy.host=\u4e3b\u6a5f -proxy.port=Port - -login.failed.connect_authentication_server=\u7121\u6cd5\u9023\u63a5\u8a8d\u8b49\u4f3a\u670d\u5668,\u53ef\u80fd\u662f\u7db2\u7d61\u554f\u984c - -login.profile.not_logged_in=\u7121\u6cd5\u4fee\u6539\u904a\u6232\u8cc7\u6599\u540c\u6642\u672a\u767b\u9304 -login.profile.selected=\u7121\u6cd5\u4fee\u6539\u904a\u6232\u8cc7\u6599. \u4f60\u5fc5\u9808\u767b\u51fa\u518d\u8fd4\u56de. - -login.methods.yggdrasil=\u6b63\u7248\u767b\u9304 -login.methods.offline=\u96e2\u7dda\u6a21\u5f0f -login.methods.no_method=\u6c92\u6709\u767b\u5165\u65b9\u5f0f... - -log.playername_null=\u73a9\u5bb6\u540d\u70ba\u7a7a\uff0c\u9019\u4ee3\u8868\u8457\u767b\u9304\u65b9\u6cd5\u51fa\u73fe\u554f\u984c - -minecraft.no_selected_version=\u6c92\u6709\u9078\u64c7\u4efb\u4f55\u4e00\u500bMinecraft\u7248\u672c -minecraft.wrong_path=\u932f\u8aa4\u7684Minecraft\u8def\u5f91\uff0c\u555f\u52d5\u5668\u672a\u627e\u5230\u8a2d\u5b9a\u7684Minecraft\u8def\u5f91\uff0c\u8acb\u6aa2\u67e5\u3002 - -operation.stopped=\u64cd\u4f5c\u88ab\u5f37\u884c\u7d42\u6b62 -operation.confirm_stop=\u771f\u7684\u8981\u7d42\u6b62\u64cd\u4f5c\u55ce\uff1f - -ui.login.password=\u5bc6\u78bc -ui.more=\u66f4\u591a - -crash.advice.UnsupportedClassVersionError=\u9019\u53ef\u80fd\u662f\u56e0\u70ba\u60a8\u7684Java\u7248\u672c\u904e\u65bc\u8001\u820a\uff0c\u53ef\u4ee5\u5617\u8a66\u66f4\u63db\u6700\u65b0Java\u4e26\u5728\u7248\u672c\u8a2d\u5b9a\u7684Java\u8def\u5f91\u4e2d\u8a2d\u5b9a. -crash.advice.ConcurrentModificationException=\u9019\u53ef\u80fd\u662f\u56e0\u70ba\u60a8\u7684Java\u7248\u672c\u9ad8\u65bcJava 1.8.0_11\u5c0e\u81f4\u7684,\u53ef\u4ee5\u5617\u8a66\u5378\u8f09Java8\u5b89\u88ddJava7\u3002 -crash.advice.ClassNotFoundException=Minecraft\u4e0d\u5b8c\u6574\u6216Mod\u885d\u7a81\uff0c\u5982\u679c\u6709\u672a\u80fd\u4e0b\u8f09\u7684\u8cc7\u6599\u8acb\u4e0b\u8f09\u6210\u529f\u5f8c\u91cd\u8a66\u6216\u662f\u7528\u6236\u7aef\u640d\u58de\u8acb\u91cd\u8a66\u8acb\u91cd\u65b0\u88fd\u4f5c\u7528\u6236\u7aef\u6216\u4e0b\u8f09\u6574\u5408\u5305\u89e3\u6c7a\u554f\u984c\uff0c\u53e6\u53ef\u5617\u8a66\u904a\u6232\u8a2d\u5b9a->\uff08\u7248\u672c\uff09\u7ba1\u7406->\u522a\u9664\u5eab\u8cc7\u6599\u89e3\u6c7a\u554f\u984c -crash.advice.NoSuchFieldError=Minecraft\u4e0d\u5b8c\u6574\u6216Mod\u885d\u7a81\uff0c\u5982\u679c\u6709\u672a\u80fd\u4e0b\u8f09\u7684\u8cc7\u6599\u8acb\u4e0b\u8f09\u6210\u529f\u5f8c\u91cd\u8a66\u6216\u662f\u7528\u6236\u7aef\u640d\u58de\u8acb\u91cd\u8a66\u8acb\u91cd\u65b0\u88fd\u4f5c\u7528\u6236\u7aef\u6216\u4e0b\u8f09\u6574\u5408\u5305\u89e3\u6c7a\u554f\u984c\u3002 -crash.advice.LWJGLException=\u60a8\u7684\u96fb\u8166\u4e0d\u6b63\u5e38\uff0c\u53ef\u80fd\u9700\u8981\u4f7f\u7528\u9a45\u52d5\u7cbe\u9748\u6216\u5176\u4ed6\u5b89\u88dd\u5668\u66f4\u65b0\u986f\u5361\u9a45\u52d5\u3002 -crash.advice.SecurityException=\u53ef\u80fd\u662f\u60a8\u4fee\u6539\u4e86minecraft.jar\u4f46\u672a\u522a\u9664META-INF\u8cc7\u6599\u593e\u7684\u539f\u56e0\u3002\u8acb\u901a\u904e\u58d3\u7e2e\u8edf\u9ad4\u522a\u9664jar\u4e2d\u7684META-INF\u8cc7\u6599\u593e\u3002 -crash.advice.OutOfMemoryError=\u8a18\u61b6\u9ad4\u6ea2\u51fa\uff0c\u60a8\u8a2d\u5b9a\u7684Minecraft\u6700\u5927\u8a18\u61b6\u9ad4\u904e\u5c0f\uff0c\u8acb\u8abf\u5927\uff01 -crash.advice.otherwise=\u53ef\u80fd\u662fMod\u6216\u5176\u4ed6\u554f\u984c\u3002 - -crash.advice.OpenGL=\u53ef\u80fd\u662f\u986f\u5361/\u8072\u5361\u9a45\u52d5\u554f\u984c\uff0c\u4e5f\u53ef\u80fd\u662fMod\u5c0e\u81f4\u7684\u554f\u984c\u3002 -crash.advice.no_lwjgl=\u53ef\u80fd\u662f\u904a\u6232\u4f9d\u8cf4\u5eab\u4e0d\u5b8c\u6574\u6216\u89e3\u58d3\u4f9d\u8cf4\u5eab\u6642\u51fa\u932f\u3002\u53ef\u4ee5\u901a\u904e\u4e0b\u8f09\u6574\u5408\u5305\u89e3\u6c7a\u554f\u984c\u3002 - -crash.advice.no=\u7121\u5efa\u8b70\u3002 - -crash.user_fault=\u60a8\u7684\u7cfb\u7d71\u6216Java\u74b0\u5883\u53ef\u80fd\u5b89\u88dd\u4e0d\u7576\u5c0e\u81f4\u672c\u8edf\u9ad4\u5d29\u6f70\uff0c\u8acb\u6aa2\u67e5\u60a8\u7684Java\u74b0\u5883\u6216\u60a8\u7684\u96fb\u8166\uff01\u53ef\u4ee5\u5617\u8a66\u91cd\u65b0\u5b89\u88ddJava\u3002 -crash.headless=\u5982\u679c\u60a8\u7684\u64cd\u4f5c\u7cfb\u7d71\u662fLinux\uff0c\u8acb\u6ce8\u610f\u4e0d\u8981\u4f7f\u7528OpenJDK\uff0c\u52d9\u5fc5\u4f7f\u7528Oracle JDK\uff0c\u6216\u5617\u8a66\u6dfb\u52a0-Djava.awt.headless=false\u53c3\u6578\uff0c\u6216\u6aa2\u67e5\u60a8\u7684Xserver\u662f\u5426\u6b63\u5e38 -crash.NoClassDefFound=\u8acb\u78ba\u8a8dHMCL\u672c\u9ad4\u662f\u5426\u5b8c\u6574 - -crash.error=\u60a8\u7684Minecraft\u5d29\u6f70\u4e86\u3002 -crash.main_class_not_found=\u627e\u4e0d\u5230\u4e3b\u985e\uff0c\u53ef\u80fd\u662f\u60a8\u7684JSON\u8cc7\u6599\u586b\u5beb\u932f\u8aa4\u3002\u7121\u6cd5\u555f\u52d5\u904a\u6232\u3002\u53ef\u4ee5\u901a\u904e\u4e0b\u8f09\u6574\u5408\u5305\u89e3\u6c7a\u554f\u984c\u3002 -crash.class_path_wrong=\u89e3\u6790Class Path\u6642\u51fa\u73fe\u932f\u8aa4\uff0c\u6b64\u932f\u8aa4\u672c\u4e0d\u61c9\u8a72\u767c\u751f\u3002\u53ef\u80fd\u662f\u555f\u52d5\u8173\u672c\u932f\u8aa4\uff0c\u8acb\u4ed4\u7d30\u6aa2\u67e5\u555f\u52d5\u8173\u672c\u3002 - -ui.label.newProfileWindow.new_profile_name=\u65b0\u914d\u7f6e\u540d: -ui.label.newProfileWindow.copy_from=\u8907\u88fd\u914d\u7f6e: -ui.newProfileWindow.title=\u65b0\u5efa\u914d\u7f6e - -ui.button.ok=\u78ba\u8a8d -ui.button.refresh=\u91cd\u6574 -ui.button.run=\u555f\u52d5Minecraft -ui.button.settings= -ui.button.about=\u95dc\u65bc -ui.button.others=\u5176\u4ed6 -ui.button.logout=\u767b\u51fa -ui.button.download=\u4e0b\u8f09 -ui.button.retry=\u91cd\u8a66 -ui.button.delete=\u522a\u9664 -ui.button.install=\u5b89\u88dd -ui.button.info=\u4fe1\u606f -ui.button.save=\u4fdd\u5b58 -ui.button.copy=\u8907\u88fd -ui.button.clear=\u6e05\u9664 -ui.button.close=\u95dc\u9589 -ui.button.explore=\u700f\u89bd -ui.button.test=\u6e2c\u8a66 -ui.button.preview=\u9810\u89bd -button.cancel=\u53d6\u6d88 -button.ok=\u78ba\u5b9a -button.yes=\u662f -button.no=\u4e0d - -ui.label.version=\u7248\u672c -ui.label.password=\u5bc6\u78bc -ui.label.profile=\u914d\u7f6e - -ui.message.first_load=\u8acb\u5728\u5de6\u908a\u8f38\u5165\u60a8\u7684\u5e33\u865f -ui.message.enter_password=\u8acb\u5728\u5de6\u908a\u8f38\u5165\u60a8\u7684\u5bc6\u78bc -ui.message.launching=\u555f\u52d5\u4e2d -ui.message.making=\u751f\u6210\u4e2d -ui.message.sure_remove=\u771f\u7684\u8981\u522a\u9664\u914d\u7f6e%s\u55ce\uff1f -ui.message.update_java=\u8acb\u66f4\u65b0\u60a8\u7684Java -ui.message.open_jdk=\u6211\u5011\u767c\u73fe\u5230\u60a8\u6b63\u5728\u4f7f\u7528OpenJDK\uff0c\u9019\u53ef\u80fd\u6703\u5c0e\u81f4\u5f88\u591a\u4ecb\u9762\u554f\u984c\uff0c\u6211\u5011\u5efa\u8b70\u60a8\u66f4\u63dbOracle JDK\u3002 - -ui.label.settings=\u9078\u9805 -ui.label.crashing=Hello Minecraft! Launcher\u9047\u5230\u4e86\u7121\u6cd5\u8655\u7406\u7684\u932f\u8aa4\uff0c\u8acb\u8907\u5236\u4e0b\u5217\u5167\u5bb9\u4e26\u901a\u904emcbbs\u3001\u8cbc\u5427\u6216Minecraft Forum\u53cd\u994bbug\u3002 -ui.label.crashing_out_dated=Hello Minecraft! Launcher\u9047\u5230\u4e86\u7121\u6cd5\u8655\u7406\u7684\u932f\u8aa4\uff0c\u5df2\u6aa2\u6e2c\u5230\u60a8\u7684\u555f\u52d5\u5668\u4e0d\u662f\u6700\u65b0\u7248\u672c\uff0c\u8acb\u66f4\u65b0\u5f8c\u518d\u8a66\uff01 -ui.label.failed_set=\u8a2d\u5b9a\u5931\u6557\uff1a - -download=\u4e0b\u8f09 -download.mojang=\u5b98\u65b9 -download.BMCL=BMCLAPI (bangbang93, http://bmclapi.bangbang93.com/) -download.rapid_data=RapidData (\u92b3\u7db2\u96f2\u8a08\u7b97, https://www.rapiddata.org/) -download.not_200=\u4e0b\u8f09\u5931\u6557\uff0c\u56de\u5fa9\u78bc -download.failed=\u4e0b\u8f09\u5931\u6557 -download.successfully=\u4e0b\u8f09\u5b8c\u6210 -download.source=\u4e0b\u8f09\u6e90 - -message.error=\u932f\u8aa4 -message.cannot_open_explorer=\u7121\u6cd5\u6253\u958b\u8cc7\u6599\u7ba1\u7406\u5668: -message.cancelled=\u5df2\u53d6\u6d88 -message.info=\u63d0\u793a -message.loading=\u52a0\u8f09\u4e2d... - -folder.game=\u904a\u6232\u8cc7\u6599\u593e -folder.mod=MOD\u8cc7\u6599\u593e -folder.coremod=\u6838\u5fc3MOD\u8cc7\u6599\u593e -folder.config=\u914d\u7f6e\u8cc7\u6599\u593e -folder.resourcepacks=\u8cc7\u6e90\u5305\u8cc7\u6599\u593e -folder.screenshots=\u622a\u5716\u8cc7\u6599\u593e -folder.saves=\u5b58\u6a94\u8cc7\u6599\u593e - -settings.tabs.game_download=\u904a\u6232\u4e0b\u8f09 -settings.tabs.installers=\u81ea\u52d5\u5b89\u88dd -settings.tabs.assets_downloads=\u8cc7\u6e90\u4e0b\u8f09 - -settings=\u666e\u901a\u8a2d\u5b9a -settings.explore=\u700f\u89bd -settings.manage=\u7ba1\u7406 -settings.cannot_remove_default_config=\u4e0d\u80fd\u522a\u9664\u9810\u8a2d\u914d\u7f6e -settings.max_memory=\u6700\u5927\u8a18\u61b6\u9ad4\uff08MB\uff09 -settings.java_dir=Java\u8def\u5f91 -settings.game_directory=\u904a\u6232\u8def\u5f91 -settings.dimension=\u904a\u6232\u7a97\u53e3\u89e3\u6790\u5ea6 -settings.fullscreen=\u5168\u87a2\u5e55 -settings.update_version=\u66f4\u65b0\u7248\u672c\u8cc7\u6599 -settings.run_directory=\u57f7\u884c\u8def\u5f91(\u7248\u672c\u9694\u96e2) -settings.physical_memory=\u5be6\u9ad4\u8a18\u61b6\u9ad4\u5927\u5c0f -settings.choose_javapath=\u9078\u64c7Java\u8def\u5f91 -settings.default=\u9810\u8a2d -settings.custom=\u81ea\u5b9a\u7fa9 -settings.choose_gamedir=\u9078\u64c7\u904a\u6232\u8def\u5f91 -settings.failed_load=\u8a2d\u5b9a\u8cc7\u6599\u52a0\u8f09\u5931\u6557\uff0c\u53ef\u80fd\u662f\u5347\u7d1a\u4e86\u555f\u52d5\u5668\u6216\u88ab\u4eba\u5de5\u4fee\u6539\u9020\u6210\u932f\u8aa4\uff0c\u662f\u5426\u6e05\u9664\uff1f -settings.test_game=\u6e2c\u8a66\u904a\u6232 - -settings.type.none=\u7f3a\u5c11\u6e38\u6232\u7248\u672c\uff0c\u8acb\u5207\u63db\u5230\u904a\u6232\u4e0b\u8f09\u9801\u4e0b\u8f09\u904a\u6232 -settings.type.global=\u9ede\u64ca\u6b64\u8655\u5207\u63db\u70ba\u7248\u672c\u7279\u5b9a\u8a2d\u5b9a\u3002\u8a72\u7248\u672c\u6b63\u5728\u4f7f\u7528\u5168\u5c40\u8a2d\u5b9a\uff0c\u4fee\u6539\u4ee5\u4e0b\u8a2d\u5b9a\u6703\u5f71\u97ff\u5230\u5176\u4ed6\u4f7f\u7528\u5168\u5c40\u8a2d\u5b9a\u7684\u7248\u672c -settings.type.special=\u9ede\u64ca\u6b64\u8655\u5207\u63db\u70ba\u5168\u5c40\u8a2d\u5b9a\u3002\u8a72\u7248\u672c\u6b63\u5728\u4f7f\u7528\u7248\u672c\u7279\u5b9a\u8a2d\u5b9a\uff0c\u4fee\u6539\u4ee5\u4e0b\u8a2d\u5b9a\u4e0d\u6703\u5f71\u97ff\u5230\u5176\u4ed6\u7248\u672c\u8a2d\u5b9a - -modpack=\u61f6\u4eba\u5305 -modpack.choose=\u9078\u64c7\u8981\u5c0e\u5165\u7684\u904a\u6232\u61f6\u4eba\u5305\u8cc7\u6599\uff0c\u5982\u679c\u60a8\u5e0c\u671b\u66f4\u65b0\u61f6\u4eba\u5305\uff0c\u8acb\u8f38\u5165\u8981\u66f4\u65b0\u7684\u7248\u672c\u540d -modpack.export_error=\u5c0e\u51fa\u5931\u6557\uff0c\u53ef\u80fd\u662f\u60a8\u7684\u904a\u6232\u8cc7\u6599\u593e\u683c\u5f0f\u4e0d\u6b63\u78ba\u6216\u64cd\u4f5c\u8cc7\u6599\u5931\u6557 -modpack.export_finished=\u61f6\u4eba\u5305\u5c0e\u51fa\u5b8c\u6210\uff0c\u53c3\u898b -modpack.included_launcher=\u61f6\u4eba\u5305\u5df2\u5305\u542b\u555f\u52d5\u5668\uff0c\u53ef\u76f4\u63a5\u767c\u5e03 -modpack.not_included_launcher=\u61f6\u4eba\u5305\u672a\u5305\u542b\u555f\u52d5\u5668\uff0c\u53ef\u4f7f\u7528\u672c\u8edf\u4ef6\u7684\u5c0e\u5165\u61f6\u4eba\u5305\u529f\u80fd\u5c0e\u5165\u61f6\u4eba\u5305 -modpack.enter_name=\u7d66\u904a\u6232\u8d77\u500b\u4f60\u559c\u6b61\u7684\u540d\u5b57 - -modpack.task.save=\u5c0e\u51fa\u61f6\u4eba\u5305 -modpack.task.install=\u5c0e\u5165\u61f6\u4eba\u5305 -modpack.task.install.error=\u5b89\u88dd\u5931\u6557\uff0c\u53ef\u80fd\u662f\u61f6\u4eba\u5305\u683c\u5f0f\u4e0d\u6b63\u78ba\u6216\u64cd\u4f5c\u8cc7\u6599\u5931\u6557 -modpack.task.install.will=\u5c07\u6703\u5b89\u88dd\u61f6\u4eba\u5305\uff1a - -modpack.wizard=\u5c0e\u51fa\u61f6\u4eba\u5305\u56ae\u5c0e -modpack.wizard.step.1=\u57fa\u672c\u8a2d\u5b9a -modpack.wizard.step.1.title=\u8a2d\u5b9a\u61f6\u4eba\u5305\u7684\u4e3b\u8981\u8cc7\u8a0a -modpack.wizard.step.initialization.include_launcher=\u5305\u542b\u555f\u52d5\u5668 -modpack.wizard.step.initialization.exported_version=\u8981\u5c0e\u51fa\u7684\u904a\u6232\u7248\u672c -modpack.wizard.step.initialization.save=\u9078\u64c7\u8981\u5c0e\u51fa\u5230\u7684\u904a\u6232\u61f6\u4eba\u5305\u4f4d\u7f6e -modpack.wizard.step.initialization.warning=\u5728\u88fd\u4f5c\u61f6\u4eba\u5305\u524d,\u8acb\u60a8\u78ba\u8a8d\u60a8\u9078\u64c7\u7684\u7248\u672c\u53ef\u4ee5\u6b63\u5e38\u555f\u52d5,
    \u4e26\u4fdd\u8b49\u60a8\u7684Minecraft\u662f\u6b63\u5f0f\u7248\u800c\u975e\u5feb\u7167\u7248,
    \u800c\u4e14\u4e0d\u61c9\u7576\u5c07\u4e0d\u5141\u8a31\u975e\u5b98\u65b9\u9014\u5f91\u50b3\u64ad\u7684Mod\u3001\u6750\u8cea\u5305\u7b49\u7d0d\u5165\u6574\u5408\u5305\u3002
    \u61f6\u4eba\u5305\u6703\u4fdd\u5b58\u60a8\u76ee\u524d\u7684\u4e0b\u8f09\u6e90\u8a2d\u5b9a -modpack.wizard.step.2=\u8cc7\u6599\u9078\u64c7 -modpack.wizard.step.2.title=\u9078\u4e2d\u4f60\u4e0d\u60f3\u52a0\u5230\u61f6\u4eba\u5305\u4e2d\u7684\u8cc7\u6599(\u593e) -modpack.wizard.step.3=\u61f6\u4eba\u5305\u63cf\u8ff0 -modpack.wizard.step.3.title=\u63cf\u8ff0\u4f60\u8981\u88fd\u4f5c\u7684\u61f6\u4eba\u5305\u3002 - -modpack.desc=\u63cf\u8ff0\u4f60\u8981\u88fd\u4f5c\u7684\u61f6\u4eba\u5305\uff0c\u6bd4\u5982\u61f6\u4eba\u5305\u6ce8\u610f\u4e8b\u9805\u548c\u66f4\u65b0\u8a18\u9304\uff0c\u652f\u6301Markdown(\u5716\u7247\u8acb\u7528\u7db2\u8def\u5716\u7247)\u3002 -modpack.incorrect_format.no_json=\u61f6\u4eba\u5305\u683c\u5f0f\u932f\u8aa4\uff0cpack.json\u4e1f\u5931 -modpack.incorrect_format.no_jar=\u61f6\u4eba\u5305\u683c\u5f0f\u932f\u8aa4\uff0cpack.json\u4e1f\u5931jar\u6b04\u4f4d -modpack.cannot_read_version=\u8b80\u53d6\u904a\u6232\u7248\u672c\u5931\u6557 -modpack.not_a_valid_location=\u4e0d\u662f\u4e00\u500b\u6709\u6548\u61f6\u4eba\u5305\u4f4d\u7f6e -modpack.name=\u61f6\u4eba\u5305\u540d\u7a31 -modpack.not_a_valid_name=\u4e0d\u662f\u4e00\u500b\u6709\u6548\u7684\u61f6\u4eba\u5305\u540d\u7a31 - -modpack.files.servers_dat=\u591a\u4eba\u904a\u6232\u4f3a\u670d\u5668\u5217\u8868 -modpack.files.saves=\u904a\u6232\u5b58\u6a94 -modpack.files.mods=Mod -modpack.files.config=Mod\u8a2d\u5b9a\u6a94 -modpack.files.liteconfig=Mod\u8a2d\u5b9a\u6a94 -modpack.files.resourcepacks=\u8cc7\u6e90\u5305(\u6750\u8cea\u5305) -modpack.files.options_txt=\u904a\u6232\u8a2d\u5b9a -modpack.files.optionsshaders_txt=\u5149\u5f71\u8a2d\u5b9a -modpack.files.mods.voxelmods=VoxelMods\u8a2d\u5b9a\uff0c\u5982\u5c0f\u5730\u5716 -modpack.files.dumps=NEI\u8abf\u8a66\u8f38\u51fa -modpack.files.scripts=MineTweaker\u914d\u7f6e -modpack.files.blueprints=BuildCraft\u85cd\u5716 - -mods=Mod\u7ba1\u7406 -mods.choose_mod=\u9078\u64c7\u6a21\u7d44 -mods.failed=\u6dfb\u52a0\u5931\u6557 -mods.add=\u6dfb\u52a0 -mods.remove=\u522a\u9664 -mods.default_information=\u60a8\u53ef\u4ee5\u62d6\u52d5mod\u5230\u5217\u8868\u4e2d\u4f86\u6dfb\u52a0mod\uff0c\u540c\u6642\u4f7f\u7528\u522a\u9664\u9375\u53ef\u5feb\u901f\u522a\u9664\u9078\u4e2dmod
    \u9078\u64c7mod\u53ef\u4ee5\u7372\u53d6mod\u8cc7\u8a0a - -advancedsettings=\u9032\u968e\u8a2d\u5b9a -advancedsettings.launcher_visible=\u555f\u52d5\u5668\u53ef\u898b\u6027 -advancedsettings.debug_mode=\u5075\u932f\u6a21\u5f0f -advancedsettings.java_permanent_generation_space=\u8a18\u61b6\u9ad4\u6c38\u4e45\u4fdd\u5b58\u5340\u57df/MB -advancedsettings.jvm_args=Java\u865b\u64ec\u6a5f\u53c3\u6578(\u4e0d\u5fc5\u586b\u5beb) -advancedsettings.Minecraft_arguments=Minecraft\u984d\u5916\u53c3\u6578(\u4e0d\u5fc5\u586b\u5beb) -advancedsettings.launcher_visibility.close=\u904a\u6232\u555f\u52d5\u5f8c\u7d50\u675f\u555f\u52d5\u5668 -advancedsettings.launcher_visibility.hide=\u904a\u6232\u555f\u52d5\u5f8c\u96b1\u85cf\u555f\u52d5\u5668 -advancedsettings.launcher_visibility.keep=\u4fdd\u6301\u555f\u52d5\u5668\u53ef\u898b -advancedsettings.launcher_visibility.hide_reopen=\u96b1\u85cf\u555f\u52d5\u5668\u4e26\u5728\u904a\u6232\u7d50\u675f\u5f8c\u91cd\u65b0\u6253\u958b -advancedsettings.game_dir.default=\u9810\u8a2d(.minecraft/) -advancedsettings.game_dir.independent=\u5404\u7248\u672c\u7368\u7acb(.minecraft/versions/<\u7248\u672c\u540d>/,\u9664assets,libraries) -advancedsettings.no_jvm_args=\u4e0d\u6dfb\u52a0\u9810\u8a2d\u7684JVM\u53c3\u6578(\u4f7f\u7528Java9\u6642\u5fc5\u52fe) -advancedsettings.no_common=\u4e0d\u4f7f\u7528\u516c\u5171\u8def\u5f91 -advancedsettings.java_args_default=\u555f\u52d5\u5668\u9810\u8a2d\u6dfb\u52a0\u7684\u53c3\u6578\uff08\u8acb\u4e0d\u8981\u91cd\u8907\u6dfb\u52a0\uff09\uff1a-XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode -XX:-UseAdaptiveSizePolicy -XX:MaxPermSize=???m -Xmx???m -Dfml. ignoreInvalidMinecraftCertificates=true -Dfml.ignorePatchDiscrepancies=true -advancedsettings.wrapper_launcher=\u524d\u7f6e\u6307\u4ee4(\u4e0d\u5fc5\u586b\u5beb,\u5982optirun) -advancedsettings.precall_command=\u555f\u52d5\u524d\u57f7\u884c\u547d\u4ee4(\u4e0d\u5fc5\u586b\u5beb,\u5c07\u5728\u904a\u6232\u555f\u52d5\u524d\u8abf\u7528) -advancedsettings.server_ip=\u76f4\u63a5\u9032\u5165\u4f3a\u670d\u5668IP (\u4e0d\u5fc5\u586b\u5beb\uff0c\u555f\u52d5\u904a\u6232\u5f8c\u76f4\u63a5\u9032\u5165\u5c0d\u61c9\u4f3a\u670d\u5668) -advancedsettings.cancel_wrapper_launcher=\u53d6\u6d88\u5305\u88f9\u555f\u52d5\u5668(\u51fa\u73fe\u5947\u602a\u554f\u984c\u6642\u53ef\u5617\u8a66\u4f7f\u7528,\u8207\u8abf\u8a66\u6a21\u5f0f\u885d\u7a81) -advancedsettings.dont_check_game_completeness=\u4e0d\u6aa2\u67e5\u904a\u6232\u5b8c\u6574\u6027 - -mainwindow.show_log=\u67e5\u770b\u65e5\u8a8c -mainwindow.make_launch_script=\u751f\u6210\u555f\u52d5\u8173\u672c -mainwindow.make_launch_script_failed=\u751f\u6210\u555f\u52d5\u8173\u672c\u5931\u6557 -mainwindow.enter_script_name=\u8f38\u5165\u8981\u751f\u6210\u8173\u672c\u7684\u8cc7\u6599\u540d -mainwindow.make_launch_succeed=\u555f\u52d5\u8173\u672c\u5df2\u751f\u6210\u5b8c\u7562: -mainwindow.no_version=\u672a\u627e\u5230\u4efb\u4f55\u7248\u672c\uff0c\u662f\u5426\u9032\u5165\u904a\u6232\u4e0b\u8f09\uff1f - -launcher.about=\u9810\u8a2d\u80cc\u666f\u5716\u611f\u8b1dgamerteam\u63d0\u4f9b\u3002
    \u95dc\u65bc\u4f5c\u8005\uff1a
    \u767e\u5ea6ID\uff1ahuanghongxun20
    mcbbs\uff1ahuanghongxun
    Minecraft Forum ID: klkl6523
    \u6b61\u8fce\u63d0\u4ea4Bug\u54e6
    Copyright (c) 2013-2016 huangyuhui.
    \u514d\u8cac\u8072\u660e\uff1aMinecraft\u8edf\u9ad4\u7248\u6b0a\u6b78Mojang AB\u6240\u6709\uff0c\u904a\u6232\u7531\u65bc\u8aa4\u64cd\u4f5c\u672c\u555f\u52d5\u5668\u800c\u4e1f\u5931\u6578\u64da\u7684\u6982\u4e0d\u8ca0\u8cac\u3002
    \u672c\u555f\u52d5\u5668\u5728GPLv3\u5354\u8b70\u4e0b\u958b\u6e90:http://github.com/huanghongxun/HMCL/ ,\u611f\u8b1dissues\u548cpull requests\u8ca2\u737b\u8005
    \u672c\u8edf\u9ad4\u4f7f\u7528\u4e86\u57fa\u65bcApache License 2.0\u7684Gson\u9805\u76ee\uff0c\u611f\u8b1d\u8ca2\u737b\u8005\u3002 -launcher.download_source=\u4e0b\u8f09\u6e90 -launcher.background_location=\u80cc\u666f\u5730\u5740 -launcher.common_location=\u516c\u7528\u8cc7\u6599\u593e -launcher.exit_failed=\u5f37\u5236\u9000\u51fa\u5931\u6557\uff0c\u53ef\u80fd\u662fForge 1.7.10\u53ca\u66f4\u9ad8\u7248\u672c\u5c0e\u81f4\u7684\uff0c\u7121\u6cd5\u89e3\u6c7a\u3002 -launcher.versions_json_not_matched=\u7248\u672c%s\u683c\u5f0f\u4e0d\u898f\u7bc4\uff01\u8a72\u7248\u672c\u8cc7\u6599\u593e\u4e0b\u6709json:%s\uff0c\u662f\u5426\u66f4\u540d\u9019\u500b\u8cc7\u6599\u4f86\u898f\u7bc4\u683c\u5f0f\uff1f -launcher.versions_json_not_matched_cannot_auto_completion=\u7248\u672c%s\u7f3a\u5931\u5fc5\u8981\u7684\u7248\u672c\u8cc7\u8a0a\u8cc7\u6599\uff0c\u662f\u5426\u522a\u9664\u8a72\u7248\u672c\uff1f -launcher.versions_json_not_formatted=\u7248\u672c%s\u8cc7\u8a0a\u8cc7\u6599\u683c\u5f0f\u932f\u8aa4\uff0c\u662f\u5426\u91cd\u65b0\u4e0b\u8f09\uff1f -launcher.choose_bgpath=\u9078\u64c7\u80cc\u666f\u8def\u5f91 -launcher.choose_commonpath=\u9078\u64c7\u516c\u7528\u8def\u5f91 -launcher.commpath_tooltip=\u555f\u52d5\u5668\u5c07\u6240\u6709\u904a\u6232\u8cc7\u6e90\u8ddf\u57f7\u884c\u5eab\u6a94\u6848\u653e\u5728\u6b64\u8655\u96c6\u4e2d\u7ba1\u7406\u3002\u5982\u679c\u904a\u6232\u8cc7\u6599\u593e\u6709\u73fe\u6210\u7684\u5c07\u4e0d\u6703\u4f7f\u7528\u516c\u7528\u5eab\u6a94\u6848\u3002 -launcher.background_tooltip=\u555f\u52d5\u5668\u9810\u8a2d\u4f7f\u7528\u81ea\u5e36\u7684\u80cc\u666f
    \u5982\u679c\u7576\u524d\u76ee\u9304\u6709background.png\uff0c\u5247\u6703\u4f7f\u7528\u8a72\u8cc7\u6599\u4f5c\u70ba\u80cc\u666f
    \u5982\u679c\u7576\u524d\u76ee\u9304\u6709bg\u5b50\u76ee\u9304\uff0c\u5247\u6703\u96a8\u6a5f\u4f7f\u7528\u88e1\u9762\u7684\u4e00\u5f35\u5716\u4f5c\u70ba\u80cc\u666f
    \u5982\u679c\u8a72\u80cc\u666f\u4f4d\u5740\u88ab\u4fee\u6539\uff0c\u5247\u6703\u4f7f\u7528\u80cc\u666f\u4f4d\u5740\u88e1\u7684\u4e00\u5f35\u5716\u4f5c\u70ba\u80cc\u666f
    \u80cc\u666f\u4f4d\u5740\u5141\u8a31\u6709\u591a\u500b\u4f4d\u5740\uff0c\u4f7f\u7528\u534a\u5f62\u5206\u865f";"(\u4e0d\u5305\u542b\u96d9\u5f15\u865f)\u5206\u9694 -launcher.update_launcher=\u6aa2\u67e5\u66f4\u65b0 -launcher.enable_shadow=\u555f\u7528\u7a97\u53e3\u9670\u5f71 -launcher.enable_animation=\u555f\u7528\u52d5\u614b\u6548\u679c -launcher.enable_blur=\u555f\u7528\u4e3b\u4ecb\u9762\u6a21\u7cca -launcher.theme=\u4e3b\u984c -launcher.proxy=\u4ee3\u7406 -launcher.decorated=\u555f\u7528\u8996\u7a97\u908a\u6846(Linux\u4e0b\u53ef\u89e3\u6c7a\u7a0b\u5f0f\u4ecb\u9762\u5168\u7070\u554f\u984c) -launcher.modpack=\u6574\u5408\u5305\u4f5c\u8005\u5e6b\u52a9 -launcher.lang=\u8a9e\u8a00 -launcher.restart=\u672c\u4ecb\u9762\u9078\u9805\u9700\u8981\u91cd\u555f\u672c\u555f\u52d5\u5668\u751f\u6548 -launcher.log_font=\u65e5\u8a8c\u5b57\u9ad4 -launcher.tab.general=\u901a\u7528 -launcher.tab.ui=\u4ecb\u9762 -launcher.tab.about=\u95dc\u65bc - -launcher.title.game=\u904a\u6232\u8a2d\u5b9a -launcher.title.main=\u4e3b\u9801 -launcher.title.launcher=\u555f\u52d5\u5668\u8a2d\u5b9a - -versions.release=\u7a69\u5b9a\u7248 -versions.snapshot=\u5feb\u7167\u7248 -versions.old_beta=\u6e2c\u8a66\u7248 -versions.old_alpha=\u9060\u53e4\u7248 - -versions.manage.rename=\u91cd\u65b0\u547d\u540d\u8a72\u7248\u672c -versions.manage.rename.message=\u8acb\u8f38\u5165\u8981\u6539\u6210\u7684\u540d\u5b57 -versions.manage.remove=\u522a\u9664\u8a72\u7248\u672c -versions.manage.remove.confirm=\u771f\u7684\u8981\u522a\u9664\u7248\u672c -versions.manage.redownload_json=\u91cd\u65b0\u4e0b\u8f09\u7248\u672c\u914d\u7f6e(minecraft.json) -versions.manage.redownload_assets_index=\u91cd\u65b0\u4e0b\u8f09\u8cc7\u6e90\u914d\u7f6e(assets_index.json) -versions.mamage.remove_libraries=\u522a\u9664\u6240\u6709\u5eab\u6a94 - -advice.os64butjdk32=\u60a8\u7684\u7cfb\u7d71\u662f64-bit\uff0c\u4f46\u662fJava\u662f32\u4f4d\u7684\uff0c\u63a8\u85a6\u60a8\u5b89\u88dd64\u4f4dJava. -advice.java8=\u6aa2\u6e2c\u5230\u60a8\u672a\u4f7f\u7528Java 8\u53ca\u66f4\u65b0\u7248\u672c\uff0cJava 8\u80fd\u4f7f\u904a\u6232\u66f4\u6d41\u66a2\u800c\u4e14Minecraft 1.12\u53ca\u66f4\u65b0\u7248\u672c\u548c\u5f88\u591aMod\u5f37\u5236\u9700\u8981\u9700\u8981Java 8\u3002 - -assets.download_all=\u4e0b\u8f09\u8cc7\u6e90\u8cc7\u6599 -assets.not_refreshed=\u8cc7\u6e90\u5217\u8868\u672a\u91cd\u6574\uff0c\u8acb\u91cd\u6574\u4e00\u6b21\u3002 -assets.failed=\u7372\u53d6\u5217\u8868\u5931\u6557\uff0c\u8acb\u91cd\u6574\u91cd\u8a66\u3002 -assets.list.1_7_3_after=1.7.3\u53ca\u4ee5\u5f8c -assets.list.1_6=1.6(BMCLAPI) -assets.unkown_type_select_one=\u7121\u6cd5\u89e3\u6790\u904a\u6232\u7248\u672c\uff1a%s\uff0c\u8acb\u9078\u64c7\u4e00\u7a2e\u8cc7\u6e90\u985e\u578b\u4e0b\u8f09\u3002 -assets.type=\u8cc7\u6e90\u985e\u578b -assets.download=\u4e0b\u8f09\u8cc7\u6e90 -assets.no_assets=\u8cc7\u6e90\u8cc7\u6599\u4e0d\u5b8c\u6574\uff0c\u662f\u5426\u88dc\u5168\uff1f -assets.failed_download=\u4e0b\u8f09\u8cc7\u6e90\u8cc7\u6599\u5931\u6557\uff0c\u53ef\u80fd\u5c0e\u81f4\u6c92\u6709\u4e2d\u6587\u8a9e\u7cfb\u6216\u97f3\u6a02\u3002 - -gamedownload.not_refreshed=\u904a\u6232\u4e0b\u8f09\u5217\u8868\u672a\u91cd\u6574\uff0c\u8acb\u518d\u91cd\u6574\u4e00\u6b21\u3002 - -taskwindow.title=\u4efb\u52d9 -taskwindow.single_progress=\u55ae\u9805\u9032\u5ea6 -taskwindow.total_progress=\u7e3d\u9032\u5ea6 -taskwindow.cancel=\u53d6\u6d88 -taskwindow.no_more_instance=\u53ef\u80fd\u540c\u6642\u6253\u958b\u4e86\u591a\u500b\u4efb\u52d9\u7a97\u53e3\uff0c\u8acb\u4e0d\u8981\u591a\u6b21\u6253\u958b\uff01 -taskwindow.file_name=\u4efb\u52d9 -taskwindow.download_progress=\u9032\u5ea6 - -setupwindow.include_minecraft=\u5c0e\u5165\u904a\u6232\u8cc7\u6599\u593e -setupwindow.find_in_configurations=\u5c0e\u5165\u5b8c\u6210\uff0c\u5feb\u5230\u914d\u7f6e\u4e0b\u62c9\u6e05\u55ae\u4e2d\u627e\u65b0\u904a\u6232\u8def\u5f91\u5427\uff01 -setupwindow.give_a_name=\u7d66\u65b0\u904a\u6232\u8def\u5f91\u8d77\u500b\u540d\u5b57\u5427 -setupwindow.new=\u65b0\u5efa -setupwindow.no_empty_name=\u540d\u5b57\u4e0d\u53ef\u70ba\u7a7a -setupwindow.clean=\u6e05\u7406\u904a\u6232\u8cc7\u6599 - -update.no_browser=\u7121\u6cd5\u6253\u958b\u700f\u89bd\u5668\uff0c\u7db2\u5740\u5df2\u7d93\u8907\u88fd\u5230\u526a\u8cbc\u7248\u4e86\uff0c\u60a8\u53ef\u4ee5\u624b\u52d5Copy\u7db2\u5740\u6253\u958b\u9801\u9762 -update.should_open_link=\u662f\u5426\u66f4\u65b0\uff1f -update.newest_version=\u6700\u65b0\u7248\u672c\u70ba\uff1a -update.failed=\u6aa2\u67e5\u66f4\u65b0\u5931\u6557 -update.found=(\u767c\u73fe\u66f4\u65b0!) - -logwindow.terminate_game=\u7d50\u675f\u904a\u6232\u9032\u7a0b -logwindow.title=\u65e5\u8a8c -logwindow.contact=\u806f\u7e6b\u6211\u5011 -logwindow.show_lines=\u986f\u793a\u884c\u6578 -logwindow.search=\u67e5\u627e - -selector.choose=\u9078\u64c7 - -serverlistview.title=\u9078\u64c7\u4f3a\u670d\u5668 -serverlistview.name=\u540d\u7a31 -serverlistview.type=\u985e\u578b -serverlistview.version=\u7248\u672c -serverlistview.info=\u4fe1\u606f - -minecraft.invalid=\u7121\u6548\u7684 -minecraft.invalid_jar=\u7121\u6548\u7684jar\u5305 -minecraft.not_a_file=\u4e0d\u662f\u8cc7\u6599 -minecraft.not_found=\u627e\u4e0d\u5230minecraft.jar -minecraft.not_readable=minecraft.jar\u4e0d\u53ef\u8b80 -minecraft.modified=(\u4fee\u6539\u7684!) - -color.red=\u7d05\u8272 -color.blue=\u85cd\u8272 -color.green=\u7da0\u8272 -color.orange=\u6a59\u8272 -color.dark_blue=\u6df1\u85cd\u8272 -color.purple=\u7d2b\u8272 - -wizard.next_>=\u4e0b\u4e00\u6b65 > -wizard.next_mnemonic=\u4e0b -wizard.<_prev=< \u4e0a\u4e00\u6b65 -wizard.prev_mnemonic=\u4e0a -wizard.finish=\u5b8c\u6210 -wizard.finish_mnemonic=\u5b8c -wizard.cancel=\u53d6\u6d88 -wizard.cancel_mnemonic=\u53d6 -wizard.help=\u8aaa\u660e -wizard.help_mnemonic=\u5e6b -wizard.close=\u95dc\u9589 -wizard.close_mnemonic=\u95dc -wizard.summary=\u6982\u8981 -wizard.failed=\u5931\u6557 -wizard.steps=\u6b65\u9a5f - -lang=\u7e41\u9ad4\u4e2d\u6587 -lang.default=\u8ddf\u96a8\u7cfb\u7d71\u8a9e\u8a00 diff --git a/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_zh_CN.lang b/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_zh_CN.lang deleted file mode 100644 index a0c15aa91..000000000 --- a/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_zh_CN.lang +++ /dev/null @@ -1,440 +0,0 @@ -# Hello Minecraft! Launcher. -# Copyright (C) 2013 huangyuhui -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see {http://www.gnu.org/licenses/}. -# -#author: huangyuhui -launch.failed=启动失败 -launch.failed_creating_process=启动失败,在创建新进程时发生错误,可能是Java路径错误。 -launch.failed_sh_permission=为启动文件添加权限时发生错误 -launch.failed_packing_jar=在打包jar时发生错误 -launch.unsupported_launcher_version=对不起,本启动器现在可能不能启动这个版本的Minecraft,但启动器还是会尝试启动,请尽快将此问题报告给作者。 -launch.too_big_memory_alloc_64bit=您设置的内存大小过大,由于可能超过了32位Java的内存分配限制,所以可能无法启动游戏,请将内存调至1024MB或更小,启动器仍会尝试启动。 -launch.too_big_memory_alloc_free_space_too_low=您设置的内存大小过大,由于超过了系统内存大小%dMB,所以可能影响游戏体验或无法启动游戏,启动器仍会尝试启动。 -launch.cannot_create_jvm=截获到无法创建Java虚拟机,可能是Java参数有问题,可以在设置中开启无参数模式启动 -launch.circular_dependency_versions=发现游戏版本循环引用,请确认您的客户端未被修改或修改导致出现此问题。 -launch.not_finished_downloading_libraries=未完成游戏依赖库的下载,还要继续启动游戏吗? -launch.not_finished_decompressing_natives=未能解压游戏本地库,还要继续启动游戏吗? -launch.wrong_javadir=错误的Java路径,将自动重置为默认Java路径。 -launch.exited_abnormally=游戏非正常退出,请查看日志文件,或联系他人寻求帮助。 - -launch.state.logging_in=登录中 -launch.state.generating_launching_codes=正在生成启动代码 -launch.state.downloading_libraries=正在下载必要文件 -launch.state.decompressing_natives=正在释放本地文件 -launch.state.waiting_launching=等待游戏启动 - -install.no_version=未找到要安装的对应MC版本 -install.no_version_if_intall=未找到要安装的对应MC版本,是否自动安装需要的MC版本? -install.not_refreshed=未刷新列表 -install.download_list=下载列表 - -install.liteloader.get_list=获取LiteLoader列表 -install.liteloader.install=安装LiteLoader - -install.forge.get_list=获取Forge列表 -install.forge.install=安装Forge -install.forge.get_changelogs=获取Forge更新记录 - -install.optifine.install=安装OptiFine -install.optifine.get_list=获取OptiFine列表 -install.optifine.get_download_link=获取OptiFine下载地址 - -install.failed_forge=安装Forge失败 -install.failed_optifine=安装OptiFine失败 -install.failed_liteloader=安装LiteLoader失败 -install.failed_download_forge=下载Forge失败 -install.failed_download_optifine=下载OptiFine失败 -install.failed=安装失败 -install.success=安装成功 -install.no_forge=没有安装Forge -install.choose_forge=选择你安装的Forge版本 -install.version=版本 -install.mcversion=游戏版本 -install.time=时间 -install.release_time=释放时间 -install.type=类型 -install.please_refresh=如需使用自动安装请点击右侧刷新按钮 - -crash.launcher=启动器崩溃了! -crash.minecraft=Minecraft崩溃了!请认真阅读建议。 - -login.choose_charactor=请选择您要使用的角色 -login.no_charactor=该帐号没有角色 -login.your_password=您的密码 -login.failed=登录失败: -login.no_Player007=你还未设置用户名! -login.wrong_password=可能是您的用户名或密码错误 -login.invalid_username=无效的用户名 -login.invalid_uuid_and_username=无效的UUID和用户名 -login.invalid_password=无效的密码 -login.invalid_access_token=无效的访问令牌 -login.changed_client_token=服务器回应已经修改客户端令牌 -login.not_email=用户名必须是邮箱 -login.type=登录 -login.username=名字 -login.account=邮箱 -login.invalid_token=请尝试登出并重新输入密码登录 -login.no_valid_character=无有效的角色,自行到skinme.cc登陆并创建角色 - -proxy.username=账户 -proxy.password=密码 -proxy.host=主机 -proxy.port=端口 - -login.failed.connect_authentication_server=无法连接认证服务器,可能是网络问题 - -login.profile.not_logged_in=无法修改游戏资料同时未登录 -login.profile.selected=无法修改游戏资料. 你必须登出再返回. - -login.methods.yggdrasil=正版登录 -login.methods.offline=离线模式 -login.methods.no_method=没有登入方式... - -log.playername_null=玩家名为空,这代表着登录方法出现问题 - -minecraft.no_selected_version=没有选择任何一个Minecraft版本 -minecraft.wrong_path=错误的Minecraft路径,启动器未找到设定的Minecraft路径,请检查。 - -operation.stopped=操作被强行终止 -operation.confirm_stop=真的要终止操作吗? - -ui.login.password=密码 -ui.more=更多 - -crash.advice.UnsupportedClassVersionError=这可能是因为您的Java版本过于老旧,可以尝试更换最新Java并在版本设置的Java路径中设置. -crash.advice.ConcurrentModificationException=这可能是因为您的Java版本高于Java 1.8.0_11导致的,可以尝试卸载Java8安装Java7。 -crash.advice.ClassNotFoundException=Minecraft不完整或Mod冲突,如果有未能下载的文件请下载成功后重试或是客户端损坏请重试请重新制作客户端或下载整合包解决问题,另可尝试游戏设置->(版本)管理->删除库文件解决问题 -crash.advice.NoSuchFieldError=Minecraft不完整或Mod冲突,如果有未能下载的文件请下载成功后重试或是客户端损坏请重试请重新制作客户端或下载整合包解决问题。 -crash.advice.LWJGLException=您的电脑不正常,可能需要使用驱动精灵或其他安装器更新显卡驱动。 -crash.advice.SecurityException=可能是您修改了minecraft.jar但未删除META-INF文件夹的原因。请通过压缩软件删除jar中的META-INF文件夹。 -crash.advice.OutOfMemoryError=内存溢出,您设置的Minecraft最大内存过小,请调大! -crash.advice.otherwise=可能是Mod或其他问题。 - -crash.advice.OpenGL=可能是显卡/声卡驱动问题,也可能是Mod导致的问题。 -crash.advice.no_lwjgl=可能是游戏依赖库不完整或解压依赖库时出错。可以通过下载整合包解决问题。 - -crash.advice.no=无建议。 - -crash.user_fault=您的系统或Java环境可能安装不当导致本软件崩溃,请检查您的Java环境或您的电脑!可以尝试重新安装Java。 -crash.headless=如果您的操作系统是Linux,请注意不要使用OpenJDK,务必使用Oracle JDK,或尝试添加-Djava.awt.headless=false参数,或检查您的Xserver是否正常 -crash.NoClassDefFound=请确认HMCL本体是否完整 - -crash.error=您的Minecraft崩溃了。 -crash.main_class_not_found=找不到主类,可能是您的JSON文件填写错误。无法启动游戏。可以通过下载整合包解决问题。 -crash.class_path_wrong=解析Class Path时出现错误,此错误本不应该发生。可能是启动脚本错误,请仔细检查启动脚本。 - -ui.label.newProfileWindow.new_profile_name=新配置名: -ui.label.newProfileWindow.copy_from=复制配置: -ui.newProfileWindow.title=新建配置 - -ui.button.ok=确认 -ui.button.refresh=刷新 -ui.button.run=启动Minecraft -ui.button.settings= -ui.button.about=关于 -ui.button.others=其他 -ui.button.logout=登出 -ui.button.download=下载 -ui.button.retry=重试 -ui.button.delete=删除 -ui.button.install=安装 -ui.button.info=信息 -ui.button.save=保存 -ui.button.copy=复制 -ui.button.clear=清除 -ui.button.close=关闭 -ui.button.explore=浏览 -ui.button.test=测试 -ui.button.preview=预览 -button.cancel=取消 -button.ok=确定 -button.yes=是 -button.no=不 - -ui.label.version=版本 -ui.label.password=密码 -ui.label.profile=配置 - -ui.message.first_load=请在左边输入您的账号 -ui.message.enter_password=请在左边输入您的密码 -ui.message.launching=启动中 -ui.message.making=生成中 -ui.message.sure_remove=真的要删除配置%s吗? -ui.message.update_java=请更新您的Java -ui.message.open_jdk=我们发现您正在使用OpenJDK,这会导致很多界面问题,我们建议您更换Oracle JDK。 - -ui.label.settings=选项 -ui.label.crashing=Hello Minecraft!遇到了无法处理的错误,请复制下列内容并通过mcbbs、贴吧、Github或Minecraft Forum反馈bug。 -ui.label.crashing_out_dated=Hello Minecraft! Launcher遇到了无法处理的错误,已检测到您的启动器不是最新版本,请更新后再试! -ui.label.failed_set=设置失败: - -download=下载 -download.mojang=官方 -download.BMCL=BMCLAPI (bangbang93, http://bmclapi.bangbang93.com/) -download.rapid_data=RapidData (锐网云计算, https://www.rapiddata.org/) -download.not_200=下载失败,回复码 -download.failed=下载失败 -download.successfully=下载完成 -download.source=下载源 - -message.error=错误 -message.cannot_open_explorer=无法打开文件管理器: -message.cancelled=已取消 -message.info=提示 -message.loading=加载中... - -folder.game=游戏文件夹 -folder.mod=MOD文件夹 -folder.coremod=核心MOD文件夹 -folder.config=配置文件夹 -folder.resourcepacks=资源包文件夹 -folder.screenshots=截图文件夹 -folder.saves=存档文件夹 - -settings.tabs.game_download=游戏下载 -settings.tabs.installers=自动安装 -settings.tabs.assets_downloads=资源下载 - -settings=普通设置 -settings.explore=浏览 -settings.manage=管理 -settings.cannot_remove_default_config=不能删除默认配置 -settings.max_memory=最大内存/MB -settings.java_dir=Java路径 -settings.game_directory=游戏路径 -settings.dimension=游戏窗口分辨率 -settings.fullscreen=全屏 -settings.update_version=更新版本文件 -settings.run_directory=运行路径(版本隔离) -settings.physical_memory=物理内存大小 -settings.choose_javapath=选择Java路径 -settings.default=默认 -settings.custom=自定义 -settings.choose_gamedir=选择游戏路径 -settings.failed_load=设置文件加载失败,可能是升级了启动器或被人工修改造成错误,是否清除? -settings.test_game=测试游戏 - -settings.type.none=缺少游戏版本,请切换到游戏下载页下载游戏 -settings.type.global=点击此处切换为版本特定设置。该版本正在使用全局设置,修改以下设置会影响到其他使用全局设置的版本 -settings.type.special=点击此处切换为全局设置。该版本正在使用版本特定设置,修改以下设置不会影响到其他版本设置 - -modpack=整合包 -modpack.choose=选择要导入的游戏整合包文件,如果您希望更新整合包,请输入要更新的版本名 -modpack.export_error=导出失败,可能是您的游戏文件夹格式不正确或操作文件失败 -modpack.export_finished=整合包导出完成,参见 -modpack.included_launcher=整合包已包含启动器,可直接发布 -modpack.not_included_launcher=整合包未包含启动器,可使用本软件的导入整合包功能导入整合包 -modpack.enter_name=给游戏起个你喜欢的名字 - -modpack.task.save=导出整合包 -modpack.task.install=导入整合包 -modpack.task.install.error=安装失败,可能是整合包格式不正确或操作文件失败 -modpack.task.install.will=将会安装整合包: - -modpack.wizard=导出整合包向导 -modpack.wizard.step.1=基本设置 -modpack.wizard.step.1.title=设置整合包的主要信息 -modpack.wizard.step.initialization.include_launcher=包含启动器 -modpack.wizard.step.initialization.exported_version=要导出的游戏版本 -modpack.wizard.step.initialization.save=选择要导出到的游戏整合包位置 -modpack.wizard.step.initialization.warning=在制作整合包前,请您确认您选择的版本可以正常启动,
    并保证您的Minecraft是正式版而非快照版,
    而且不应当将不允许非官方途径传播的Mod、材质包等纳入整合包。
    整合包会保存您目前的下载源设置 -modpack.wizard.step.2=文件选择 -modpack.wizard.step.2.title=选中你不想加到整合包中的文件(夹) -modpack.wizard.step.3=整合包描述 -modpack.wizard.step.3.title=描述你要制作的整合包 - -modpack.desc=描述你要制作的整合包,比如整合包注意事项和更新记录,支持Markdown(图片请用网络图片)。 -modpack.incorrect_format.no_json=整合包格式错误,pack.json丢失 -modpack.incorrect_format.no_jar=整合包格式错误,pack.json丢失jar字段 -modpack.cannot_read_version=读取游戏版本失败 -modpack.not_a_valid_location=不是一个有效整合包位置 -modpack.name=整合包名称 -modpack.not_a_valid_name=不是一个有效的整合包名称 - -modpack.files.servers_dat=多人游戏服务器列表 -modpack.files.saves=游戏存档 -modpack.files.mods=Mod -modpack.files.config=Mod配置文件 -modpack.files.liteconfig=Mod配置文件 -modpack.files.resourcepacks=资源包(材质包) -modpack.files.options_txt=游戏设定 -modpack.files.optionsshaders_txt=光影设定 -modpack.files.mods.voxelmods=VoxelMods配置,如小地图 -modpack.files.dumps=NEI调试输出 -modpack.files.scripts=MineTweaker配置 -modpack.files.blueprints=BuildCraft蓝图 - -mods=Mod管理 -mods.choose_mod=选择模组 -mods.failed=添加失败 -mods.add=添加 -mods.remove=删除 -mods.default_information=安装Mod前你需要确保已安装Forge或LiteLoader!
    您可以从资源管理器拖动mod文件到列表中来添加mod,同时使用删除键可快速删除选中mod
    点掉mod前面的勾可禁用mod,不会加载;选择mod可以获取mod信息
    - -advancedsettings=高级设置 -advancedsettings.launcher_visible=启动器可见性 -advancedsettings.debug_mode=调试模式 -advancedsettings.java_permanent_generation_space=内存永久保存区域(不必填写,MB) -advancedsettings.jvm_args=Java虚拟机参数(不必填写) -advancedsettings.Minecraft_arguments=Minecraft额外参数(不必填写) -advancedsettings.launcher_visibility.close=游戏启动后结束启动器 -advancedsettings.launcher_visibility.hide=游戏启动后隐藏启动器 -advancedsettings.launcher_visibility.keep=保持启动器可见 -advancedsettings.launcher_visibility.hide_reopen=隐藏启动器并在游戏结束后重新打开 -advancedsettings.game_dir.default=默认(.minecraft/) -advancedsettings.game_dir.independent=各版本独立(.minecraft/versions/<版本名>/,除assets,libraries) -advancedsettings.no_jvm_args=不添加默认的JVM参数(使用Java9时必勾) -advancedsettings.no_common=不使用公共路径 -advancedsettings.java_args_default=启动器默认添加的参数(请不要重复添加):-XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode -XX:-UseAdaptiveSizePolicy -XX:MaxPermSize=???m -Xmx???m -Dfml.ignoreInvalidMinecraftCertificates=true -Dfml.ignorePatchDiscrepancies=true -advancedsettings.wrapper_launcher=前置指令(不必填写,如optirun) -advancedsettings.precall_command=启动前执行命令(不必填写,将在游戏启动前调用) -advancedsettings.server_ip=直入服务器ip地址(不必填写,启动游戏后直接进入对应服务器) -advancedsettings.cancel_wrapper_launcher=取消包裹启动器(出现奇怪问题时可尝试使用,与调试模式冲突) -advancedsettings.dont_check_game_completeness=不检查游戏完整性 - -mainwindow.show_log=查看日志 -mainwindow.make_launch_script=生成启动脚本 -mainwindow.make_launch_script_failed=生成启动脚本失败 -mainwindow.enter_script_name=输入要生成脚本的文件名 -mainwindow.make_launch_succeed=启动脚本已生成完毕: -mainwindow.no_version=未找到任何版本,是否进入游戏下载? - -launcher.about=默认背景图感谢gamerteam提供。
    关于作者:
    百度ID:huanghongxun20
    mcbbs:huanghongxun
    Minecraft Forum ID: klkl6523
    欢迎提交Bug哦
    Copyright (c) 2013-2017 huangyuhui.
    免责声明:Minecraft软件版权归Mojang AB所有,使用本软件产生的版权问题本软件制作方概不负责。
    本启动器在GPLv3协议下开源:https://github.com/huanghongxun/HMCL/ ,感谢issues和pull requests贡献者
    本软件使用了基于Apache License 2.0的Gson项目,感谢贡献者。 -launcher.download_source=下载源 -launcher.background_location=背景地址 -launcher.common_location=公共文件夹 -launcher.exit_failed=强制退出失败,可能是Forge 1.7.10及更高版本导致的,无法解决。 -launcher.versions_json_not_matched=版本%s格式不规范!该版本文件夹下有json:%s,是否更名这个文件来规范格式? -launcher.versions_json_not_matched_cannot_auto_completion=版本%s缺失必要的版本信息文件,是否删除该版本? -launcher.versions_json_not_formatted=版本%s信息文件格式错误,是否重新下载? -launcher.choose_bgpath=选择背景路径 -launcher.choose_commonpath=选择公共路径 -launcher.commpath_tooltip=启动器将所有游戏资源及依赖库文件放于此集中管理,如果游戏文件夹内有现成的将不会使用公共库文件 -launcher.background_tooltip=启动器默认使用自带的背景
    如果当前目录有background.png,则会使用该文件作为背景
    如果当前目录有bg子目录,则会随机使用里面的一张图作为背景
    如果该背景地址被修改,则会使用背景地址里的一张图作为背景
    背景地址允许有多个地址,使用半角分号";"(不包含双引号)分隔 -launcher.update_launcher=检查更新 -launcher.enable_shadow=启用窗口阴影 -launcher.enable_animation=启用动态效果 -launcher.enable_blur=启用主界面模糊 -launcher.theme=主题 -launcher.proxy=代理 -launcher.decorated=启用窗口边框(Linux下可解决程序界面全灰问题) -launcher.modpack=整合包作者帮助 -launcher.lang=语言 -launcher.restart=本界面选项需要重启本启动器生效 -launcher.log_font=日志字体 -launcher.tab.general=通用 -launcher.tab.ui=界面 -launcher.tab.about=关于 - -launcher.title.game=游戏设置 -launcher.title.main=主页 -launcher.title.launcher=启动器设置 - -versions.release=稳定版 -versions.snapshot=快照版 -versions.old_beta=测试版 -versions.old_alpha=远古版 - -versions.manage.rename=重命名该版本 -versions.manage.rename.message=请输入要改成的名字 -versions.manage.remove=删除该版本 -versions.manage.remove.confirm=真的要删除版本 -versions.manage.redownload_json=重新下载版本配置(minecraft.json) -versions.manage.redownload_assets_index=重新下载资源配置(assets_index.json) -versions.mamage.remove_libraries=删除所有库文件 - -advice.os64butjdk32=您的系统是64位的但是Java是32位的,推荐您安装64位Java. -advice.java8=检测到您未使用Java 8及更新版本,Java 8能使游戏更流畅而且Minecraft 1.12及更新版本和很多Mod强制需要需要Java 8。 - -assets.download_all=下载资源文件 -assets.not_refreshed=资源列表未刷新,请刷新一次。 -assets.failed=获取列表失败,请刷新重试。 -assets.list.1_7_3_after=1.7.3及以后 -assets.list.1_6=1.6(BMCLAPI) -assets.unkown_type_select_one=无法解析游戏版本:%s,请选择一种资源类型下载。 -assets.type=资源类型 -assets.download=下载资源 -assets.no_assets=资源文件不完整,是否补全? -assets.failed_download=下载资源文件失败,可能导致没有中文和声音。 - -gamedownload.not_refreshed=游戏下载列表未刷新,请再刷新一次。 - -taskwindow.title=任务 -taskwindow.single_progress=单项进度 -taskwindow.total_progress=总进度 -taskwindow.cancel=取消 -taskwindow.no_more_instance=可能同时打开了多个任务窗口,请不要多次打开! -taskwindow.file_name=任务 -taskwindow.download_progress=进度 - -setupwindow.include_minecraft=导入游戏文件夹 -setupwindow.find_in_configurations=导入完成,快到配置下拉框中找新游戏路径吧! -setupwindow.give_a_name=给新游戏路径起个名字吧 -setupwindow.new=新建 -setupwindow.no_empty_name=名字不可为空 -setupwindow.clean=清理游戏文件 - -update.no_browser=无法打开浏览器,网址已经复制到剪贴板了,您可以手动粘贴网址打开页面 -update.should_open_link=是否更新? -update.newest_version=最新版本为: -update.failed=检查更新失败 -update.found=(发现更新!) - -logwindow.terminate_game=结束游戏进程 -logwindow.title=日志 -logwindow.contact=联系我们 -logwindow.show_lines=显示行数 -logwindow.search=查找 - -selector.choose=选择 - -serverlistview.title=选择服务器 -serverlistview.name=名称 -serverlistview.type=类型 -serverlistview.version=版本 -serverlistview.info=信息 - -minecraft.invalid=无效的 -minecraft.invalid_jar=无效的jar包 -minecraft.not_a_file=不是文件 -minecraft.not_found=找不到minecraft.jar -minecraft.not_readable=minecraft.jar不可读 -minecraft.modified=(修改的!) - -color.red=红色 -color.blue=蓝色 -color.green=绿色 -color.orange=橙色 -color.dark_blue=深蓝色 -color.purple=紫色 - -wizard.next_>=下一步 > -wizard.next_mnemonic=下 -wizard.<_prev=< 上一步 -wizard.prev_mnemonic=上 -wizard.finish=完成 -wizard.finish_mnemonic=完 -wizard.cancel=取消 -wizard.cancel_mnemonic=取 -wizard.help=帮助 -wizard.help_mnemonic=帮 -wizard.close=关闭 -wizard.close_mnemonic=关 -wizard.summary=概要 -wizard.failed=失败 -wizard.steps=步骤 - -lang=简体中文 -lang.default=跟随系统语言 diff --git a/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_zh_CN.properties b/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_zh_CN.properties deleted file mode 100644 index f29e92004..000000000 --- a/HMCLCore/src/main/resources/org/jackhuang/hmcl/lang/I18N_zh_CN.properties +++ /dev/null @@ -1,440 +0,0 @@ -# Hello Minecraft! Launcher. -# Copyright (C) 2013 huangyuhui -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see {http://www.gnu.org/licenses/}. -# -#author: huangyuhui -launch.failed=\u542f\u52a8\u5931\u8d25 -launch.failed_creating_process=\u542f\u52a8\u5931\u8d25\uff0c\u5728\u521b\u5efa\u65b0\u8fdb\u7a0b\u65f6\u53d1\u751f\u9519\u8bef\uff0c\u53ef\u80fd\u662fJava\u8def\u5f84\u9519\u8bef\u3002 -launch.failed_sh_permission=\u4e3a\u542f\u52a8\u6587\u4ef6\u6dfb\u52a0\u6743\u9650\u65f6\u53d1\u751f\u9519\u8bef -launch.failed_packing_jar=\u5728\u6253\u5305jar\u65f6\u53d1\u751f\u9519\u8bef -launch.unsupported_launcher_version=\u5bf9\u4e0d\u8d77\uff0c\u672c\u542f\u52a8\u5668\u73b0\u5728\u53ef\u80fd\u4e0d\u80fd\u542f\u52a8\u8fd9\u4e2a\u7248\u672c\u7684Minecraft\uff0c\u4f46\u542f\u52a8\u5668\u8fd8\u662f\u4f1a\u5c1d\u8bd5\u542f\u52a8\uff0c\u8bf7\u5c3d\u5feb\u5c06\u6b64\u95ee\u9898\u62a5\u544a\u7ed9\u4f5c\u8005\u3002 -launch.too_big_memory_alloc_64bit=\u60a8\u8bbe\u7f6e\u7684\u5185\u5b58\u5927\u5c0f\u8fc7\u5927\uff0c\u7531\u4e8e\u53ef\u80fd\u8d85\u8fc7\u4e8632\u4f4dJava\u7684\u5185\u5b58\u5206\u914d\u9650\u5236\uff0c\u6240\u4ee5\u53ef\u80fd\u65e0\u6cd5\u542f\u52a8\u6e38\u620f\uff0c\u8bf7\u5c06\u5185\u5b58\u8c03\u81f31024MB\u6216\u66f4\u5c0f\uff0c\u542f\u52a8\u5668\u4ecd\u4f1a\u5c1d\u8bd5\u542f\u52a8\u3002 -launch.too_big_memory_alloc_free_space_too_low=\u60a8\u8bbe\u7f6e\u7684\u5185\u5b58\u5927\u5c0f\u8fc7\u5927\uff0c\u7531\u4e8e\u8d85\u8fc7\u4e86\u7cfb\u7edf\u5185\u5b58\u5927\u5c0f%dMB\uff0c\u6240\u4ee5\u53ef\u80fd\u5f71\u54cd\u6e38\u620f\u4f53\u9a8c\u6216\u65e0\u6cd5\u542f\u52a8\u6e38\u620f\uff0c\u542f\u52a8\u5668\u4ecd\u4f1a\u5c1d\u8bd5\u542f\u52a8\u3002 -launch.cannot_create_jvm=\u622a\u83b7\u5230\u65e0\u6cd5\u521b\u5efaJava\u865a\u62df\u673a\uff0c\u53ef\u80fd\u662fJava\u53c2\u6570\u6709\u95ee\u9898\uff0c\u53ef\u4ee5\u5728\u8bbe\u7f6e\u4e2d\u5f00\u542f\u65e0\u53c2\u6570\u6a21\u5f0f\u542f\u52a8 -launch.circular_dependency_versions=\u53d1\u73b0\u6e38\u620f\u7248\u672c\u5faa\u73af\u5f15\u7528\uff0c\u8bf7\u786e\u8ba4\u60a8\u7684\u5ba2\u6237\u7aef\u672a\u88ab\u4fee\u6539\u6216\u4fee\u6539\u5bfc\u81f4\u51fa\u73b0\u6b64\u95ee\u9898\u3002 -launch.not_finished_downloading_libraries=\u672a\u5b8c\u6210\u6e38\u620f\u4f9d\u8d56\u5e93\u7684\u4e0b\u8f7d\uff0c\u8fd8\u8981\u7ee7\u7eed\u542f\u52a8\u6e38\u620f\u5417\uff1f -launch.not_finished_decompressing_natives=\u672a\u80fd\u89e3\u538b\u6e38\u620f\u672c\u5730\u5e93\uff0c\u8fd8\u8981\u7ee7\u7eed\u542f\u52a8\u6e38\u620f\u5417\uff1f -launch.wrong_javadir=\u9519\u8bef\u7684Java\u8def\u5f84\uff0c\u5c06\u81ea\u52a8\u91cd\u7f6e\u4e3a\u9ed8\u8ba4Java\u8def\u5f84\u3002 -launch.exited_abnormally=\u6e38\u620f\u975e\u6b63\u5e38\u9000\u51fa\uff0c\u8bf7\u67e5\u770b\u65e5\u5fd7\u6587\u4ef6\uff0c\u6216\u8054\u7cfb\u4ed6\u4eba\u5bfb\u6c42\u5e2e\u52a9\u3002 - -launch.state.logging_in=\u767b\u5f55\u4e2d -launch.state.generating_launching_codes=\u6b63\u5728\u751f\u6210\u542f\u52a8\u4ee3\u7801 -launch.state.downloading_libraries=\u6b63\u5728\u4e0b\u8f7d\u5fc5\u8981\u6587\u4ef6 -launch.state.decompressing_natives=\u6b63\u5728\u91ca\u653e\u672c\u5730\u6587\u4ef6 -launch.state.waiting_launching=\u7b49\u5f85\u6e38\u620f\u542f\u52a8 - -install.no_version=\u672a\u627e\u5230\u8981\u5b89\u88c5\u7684\u5bf9\u5e94MC\u7248\u672c -install.no_version_if_intall=\u672a\u627e\u5230\u8981\u5b89\u88c5\u7684\u5bf9\u5e94MC\u7248\u672c\uff0c\u662f\u5426\u81ea\u52a8\u5b89\u88c5\u9700\u8981\u7684MC\u7248\u672c\uff1f -install.not_refreshed=\u672a\u5237\u65b0\u5217\u8868 -install.download_list=\u4e0b\u8f7d\u5217\u8868 - -install.liteloader.get_list=\u83b7\u53d6LiteLoader\u5217\u8868 -install.liteloader.install=\u5b89\u88c5LiteLoader - -install.forge.get_list=\u83b7\u53d6Forge\u5217\u8868 -install.forge.install=\u5b89\u88c5Forge -install.forge.get_changelogs=\u83b7\u53d6Forge\u66f4\u65b0\u8bb0\u5f55 - -install.optifine.install=\u5b89\u88c5OptiFine -install.optifine.get_list=\u83b7\u53d6OptiFine\u5217\u8868 -install.optifine.get_download_link=\u83b7\u53d6OptiFine\u4e0b\u8f7d\u5730\u5740 - -install.failed_forge=\u5b89\u88c5Forge\u5931\u8d25 -install.failed_optifine=\u5b89\u88c5OptiFine\u5931\u8d25 -install.failed_liteloader=\u5b89\u88c5LiteLoader\u5931\u8d25 -install.failed_download_forge=\u4e0b\u8f7dForge\u5931\u8d25 -install.failed_download_optifine=\u4e0b\u8f7dOptiFine\u5931\u8d25 -install.failed=\u5b89\u88c5\u5931\u8d25 -install.success=\u5b89\u88c5\u6210\u529f -install.no_forge=\u6ca1\u6709\u5b89\u88c5Forge -install.choose_forge=\u9009\u62e9\u4f60\u5b89\u88c5\u7684Forge\u7248\u672c -install.version=\u7248\u672c -install.mcversion=\u6e38\u620f\u7248\u672c -install.time=\u65f6\u95f4 -install.release_time=\u91ca\u653e\u65f6\u95f4 -install.type=\u7c7b\u578b -install.please_refresh=\u5982\u9700\u4f7f\u7528\u81ea\u52a8\u5b89\u88c5\u8bf7\u70b9\u51fb\u53f3\u4fa7\u5237\u65b0\u6309\u94ae - -crash.launcher=\u542f\u52a8\u5668\u5d29\u6e83\u4e86\uff01 -crash.minecraft=Minecraft\u5d29\u6e83\u4e86\uff01\u8bf7\u8ba4\u771f\u9605\u8bfb\u5efa\u8bae\u3002 - -login.choose_charactor=\u8bf7\u9009\u62e9\u60a8\u8981\u4f7f\u7528\u7684\u89d2\u8272 -login.no_charactor=\u8be5\u5e10\u53f7\u6ca1\u6709\u89d2\u8272 -login.your_password=\u60a8\u7684\u5bc6\u7801 -login.failed=\u767b\u5f55\u5931\u8d25\uff1a -login.no_Player007=\u4f60\u8fd8\u672a\u8bbe\u7f6e\u7528\u6237\u540d\uff01 -login.wrong_password=\u53ef\u80fd\u662f\u60a8\u7684\u7528\u6237\u540d\u6216\u5bc6\u7801\u9519\u8bef -login.invalid_username=\u65e0\u6548\u7684\u7528\u6237\u540d -login.invalid_uuid_and_username=\u65e0\u6548\u7684UUID\u548c\u7528\u6237\u540d -login.invalid_password=\u65e0\u6548\u7684\u5bc6\u7801 -login.invalid_access_token=\u65e0\u6548\u7684\u8bbf\u95ee\u4ee4\u724c -login.changed_client_token=\u670d\u52a1\u5668\u56de\u5e94\u5df2\u7ecf\u4fee\u6539\u5ba2\u6237\u7aef\u4ee4\u724c -login.not_email=\u7528\u6237\u540d\u5fc5\u987b\u662f\u90ae\u7bb1 -login.type=\u767b\u5f55 -login.username=\u540d\u5b57 -login.account=\u90ae\u7bb1 -login.invalid_token=\u8bf7\u5c1d\u8bd5\u767b\u51fa\u5e76\u91cd\u65b0\u8f93\u5165\u5bc6\u7801\u767b\u5f55 -login.no_valid_character=\u65e0\u6709\u6548\u7684\u89d2\u8272\uff0c\u81ea\u884c\u5230skinme.cc\u767b\u9646\u5e76\u521b\u5efa\u89d2\u8272 - -proxy.username=\u8d26\u6237 -proxy.password=\u5bc6\u7801 -proxy.host=\u4e3b\u673a -proxy.port=\u7aef\u53e3 - -login.failed.connect_authentication_server=\u65e0\u6cd5\u8fde\u63a5\u8ba4\u8bc1\u670d\u52a1\u5668,\u53ef\u80fd\u662f\u7f51\u7edc\u95ee\u9898 - -login.profile.not_logged_in=\u65e0\u6cd5\u4fee\u6539\u6e38\u620f\u8d44\u6599\u540c\u65f6\u672a\u767b\u5f55 -login.profile.selected=\u65e0\u6cd5\u4fee\u6539\u6e38\u620f\u8d44\u6599. \u4f60\u5fc5\u987b\u767b\u51fa\u518d\u8fd4\u56de. - -login.methods.yggdrasil=\u6b63\u7248\u767b\u5f55 -login.methods.offline=\u79bb\u7ebf\u6a21\u5f0f -login.methods.no_method=\u6ca1\u6709\u767b\u5165\u65b9\u5f0f... - -log.playername_null=\u73a9\u5bb6\u540d\u4e3a\u7a7a\uff0c\u8fd9\u4ee3\u8868\u7740\u767b\u5f55\u65b9\u6cd5\u51fa\u73b0\u95ee\u9898 - -minecraft.no_selected_version=\u6ca1\u6709\u9009\u62e9\u4efb\u4f55\u4e00\u4e2aMinecraft\u7248\u672c -minecraft.wrong_path=\u9519\u8bef\u7684Minecraft\u8def\u5f84\uff0c\u542f\u52a8\u5668\u672a\u627e\u5230\u8bbe\u5b9a\u7684Minecraft\u8def\u5f84\uff0c\u8bf7\u68c0\u67e5\u3002 - -operation.stopped=\u64cd\u4f5c\u88ab\u5f3a\u884c\u7ec8\u6b62 -operation.confirm_stop=\u771f\u7684\u8981\u7ec8\u6b62\u64cd\u4f5c\u5417\uff1f - -ui.login.password=\u5bc6\u7801 -ui.more=\u66f4\u591a - -crash.advice.UnsupportedClassVersionError=\u8fd9\u53ef\u80fd\u662f\u56e0\u4e3a\u60a8\u7684Java\u7248\u672c\u8fc7\u4e8e\u8001\u65e7\uff0c\u53ef\u4ee5\u5c1d\u8bd5\u66f4\u6362\u6700\u65b0Java\u5e76\u5728\u7248\u672c\u8bbe\u7f6e\u7684Java\u8def\u5f84\u4e2d\u8bbe\u7f6e. -crash.advice.ConcurrentModificationException=\u8fd9\u53ef\u80fd\u662f\u56e0\u4e3a\u60a8\u7684Java\u7248\u672c\u9ad8\u4e8eJava 1.8.0_11\u5bfc\u81f4\u7684,\u53ef\u4ee5\u5c1d\u8bd5\u5378\u8f7dJava8\u5b89\u88c5Java7\u3002 -crash.advice.ClassNotFoundException=Minecraft\u4e0d\u5b8c\u6574\u6216Mod\u51b2\u7a81\uff0c\u5982\u679c\u6709\u672a\u80fd\u4e0b\u8f7d\u7684\u6587\u4ef6\u8bf7\u4e0b\u8f7d\u6210\u529f\u540e\u91cd\u8bd5\u6216\u662f\u5ba2\u6237\u7aef\u635f\u574f\u8bf7\u91cd\u8bd5\u8bf7\u91cd\u65b0\u5236\u4f5c\u5ba2\u6237\u7aef\u6216\u4e0b\u8f7d\u6574\u5408\u5305\u89e3\u51b3\u95ee\u9898\uff0c\u53e6\u53ef\u5c1d\u8bd5\u6e38\u620f\u8bbe\u7f6e->\uff08\u7248\u672c\uff09\u7ba1\u7406->\u5220\u9664\u5e93\u6587\u4ef6\u89e3\u51b3\u95ee\u9898 -crash.advice.NoSuchFieldError=Minecraft\u4e0d\u5b8c\u6574\u6216Mod\u51b2\u7a81\uff0c\u5982\u679c\u6709\u672a\u80fd\u4e0b\u8f7d\u7684\u6587\u4ef6\u8bf7\u4e0b\u8f7d\u6210\u529f\u540e\u91cd\u8bd5\u6216\u662f\u5ba2\u6237\u7aef\u635f\u574f\u8bf7\u91cd\u8bd5\u8bf7\u91cd\u65b0\u5236\u4f5c\u5ba2\u6237\u7aef\u6216\u4e0b\u8f7d\u6574\u5408\u5305\u89e3\u51b3\u95ee\u9898\u3002 -crash.advice.LWJGLException=\u60a8\u7684\u7535\u8111\u4e0d\u6b63\u5e38\uff0c\u53ef\u80fd\u9700\u8981\u4f7f\u7528\u9a71\u52a8\u7cbe\u7075\u6216\u5176\u4ed6\u5b89\u88c5\u5668\u66f4\u65b0\u663e\u5361\u9a71\u52a8\u3002 -crash.advice.SecurityException=\u53ef\u80fd\u662f\u60a8\u4fee\u6539\u4e86minecraft.jar\u4f46\u672a\u5220\u9664META-INF\u6587\u4ef6\u5939\u7684\u539f\u56e0\u3002\u8bf7\u901a\u8fc7\u538b\u7f29\u8f6f\u4ef6\u5220\u9664jar\u4e2d\u7684META-INF\u6587\u4ef6\u5939\u3002 -crash.advice.OutOfMemoryError=\u5185\u5b58\u6ea2\u51fa\uff0c\u60a8\u8bbe\u7f6e\u7684Minecraft\u6700\u5927\u5185\u5b58\u8fc7\u5c0f\uff0c\u8bf7\u8c03\u5927\uff01 -crash.advice.otherwise=\u53ef\u80fd\u662fMod\u6216\u5176\u4ed6\u95ee\u9898\u3002 - -crash.advice.OpenGL=\u53ef\u80fd\u662f\u663e\u5361/\u58f0\u5361\u9a71\u52a8\u95ee\u9898\uff0c\u4e5f\u53ef\u80fd\u662fMod\u5bfc\u81f4\u7684\u95ee\u9898\u3002 -crash.advice.no_lwjgl=\u53ef\u80fd\u662f\u6e38\u620f\u4f9d\u8d56\u5e93\u4e0d\u5b8c\u6574\u6216\u89e3\u538b\u4f9d\u8d56\u5e93\u65f6\u51fa\u9519\u3002\u53ef\u4ee5\u901a\u8fc7\u4e0b\u8f7d\u6574\u5408\u5305\u89e3\u51b3\u95ee\u9898\u3002 - -crash.advice.no=\u65e0\u5efa\u8bae\u3002 - -crash.user_fault=\u60a8\u7684\u7cfb\u7edf\u6216Java\u73af\u5883\u53ef\u80fd\u5b89\u88c5\u4e0d\u5f53\u5bfc\u81f4\u672c\u8f6f\u4ef6\u5d29\u6e83\uff0c\u8bf7\u68c0\u67e5\u60a8\u7684Java\u73af\u5883\u6216\u60a8\u7684\u7535\u8111\uff01\u53ef\u4ee5\u5c1d\u8bd5\u91cd\u65b0\u5b89\u88c5Java\u3002 -crash.headless=\u5982\u679c\u60a8\u7684\u64cd\u4f5c\u7cfb\u7edf\u662fLinux\uff0c\u8bf7\u6ce8\u610f\u4e0d\u8981\u4f7f\u7528OpenJDK\uff0c\u52a1\u5fc5\u4f7f\u7528Oracle JDK\uff0c\u6216\u5c1d\u8bd5\u6dfb\u52a0-Djava.awt.headless=false\u53c2\u6570\uff0c\u6216\u68c0\u67e5\u60a8\u7684Xserver\u662f\u5426\u6b63\u5e38 -crash.NoClassDefFound=\u8bf7\u786e\u8ba4HMCL\u672c\u4f53\u662f\u5426\u5b8c\u6574 - -crash.error=\u60a8\u7684Minecraft\u5d29\u6e83\u4e86\u3002 -crash.main_class_not_found=\u627e\u4e0d\u5230\u4e3b\u7c7b\uff0c\u53ef\u80fd\u662f\u60a8\u7684JSON\u6587\u4ef6\u586b\u5199\u9519\u8bef\u3002\u65e0\u6cd5\u542f\u52a8\u6e38\u620f\u3002\u53ef\u4ee5\u901a\u8fc7\u4e0b\u8f7d\u6574\u5408\u5305\u89e3\u51b3\u95ee\u9898\u3002 -crash.class_path_wrong=\u89e3\u6790Class Path\u65f6\u51fa\u73b0\u9519\u8bef\uff0c\u6b64\u9519\u8bef\u672c\u4e0d\u5e94\u8be5\u53d1\u751f\u3002\u53ef\u80fd\u662f\u542f\u52a8\u811a\u672c\u9519\u8bef\uff0c\u8bf7\u4ed4\u7ec6\u68c0\u67e5\u542f\u52a8\u811a\u672c\u3002 - -ui.label.newProfileWindow.new_profile_name=\u65b0\u914d\u7f6e\u540d: -ui.label.newProfileWindow.copy_from=\u590d\u5236\u914d\u7f6e: -ui.newProfileWindow.title=\u65b0\u5efa\u914d\u7f6e - -ui.button.ok=\u786e\u8ba4 -ui.button.refresh=\u5237\u65b0 -ui.button.run=\u542f\u52a8Minecraft -ui.button.settings= -ui.button.about=\u5173\u4e8e -ui.button.others=\u5176\u4ed6 -ui.button.logout=\u767b\u51fa -ui.button.download=\u4e0b\u8f7d -ui.button.retry=\u91cd\u8bd5 -ui.button.delete=\u5220\u9664 -ui.button.install=\u5b89\u88c5 -ui.button.info=\u4fe1\u606f -ui.button.save=\u4fdd\u5b58 -ui.button.copy=\u590d\u5236 -ui.button.clear=\u6e05\u9664 -ui.button.close=\u5173\u95ed -ui.button.explore=\u6d4f\u89c8 -ui.button.test=\u6d4b\u8bd5 -ui.button.preview=\u9884\u89c8 -button.cancel=\u53d6\u6d88 -button.ok=\u786e\u5b9a -button.yes=\u662f -button.no=\u4e0d - -ui.label.version=\u7248\u672c -ui.label.password=\u5bc6\u7801 -ui.label.profile=\u914d\u7f6e - -ui.message.first_load=\u8bf7\u5728\u5de6\u8fb9\u8f93\u5165\u60a8\u7684\u8d26\u53f7 -ui.message.enter_password=\u8bf7\u5728\u5de6\u8fb9\u8f93\u5165\u60a8\u7684\u5bc6\u7801 -ui.message.launching=\u542f\u52a8\u4e2d -ui.message.making=\u751f\u6210\u4e2d -ui.message.sure_remove=\u771f\u7684\u8981\u5220\u9664\u914d\u7f6e%s\u5417\uff1f -ui.message.update_java=\u8bf7\u66f4\u65b0\u60a8\u7684Java -ui.message.open_jdk=\u6211\u4eec\u53d1\u73b0\u60a8\u6b63\u5728\u4f7f\u7528OpenJDK\uff0c\u8fd9\u4f1a\u5bfc\u81f4\u5f88\u591a\u754c\u9762\u95ee\u9898\uff0c\u6211\u4eec\u5efa\u8bae\u60a8\u66f4\u6362Oracle JDK\u3002 - -ui.label.settings=\u9009\u9879 -ui.label.crashing=Hello Minecraft!\u9047\u5230\u4e86\u65e0\u6cd5\u5904\u7406\u7684\u9519\u8bef\uff0c\u8bf7\u590d\u5236\u4e0b\u5217\u5185\u5bb9\u5e76\u901a\u8fc7mcbbs\u3001\u8d34\u5427\u3001Github\u6216Minecraft Forum\u53cd\u9988bug\u3002 -ui.label.crashing_out_dated=Hello Minecraft! Launcher\u9047\u5230\u4e86\u65e0\u6cd5\u5904\u7406\u7684\u9519\u8bef\uff0c\u5df2\u68c0\u6d4b\u5230\u60a8\u7684\u542f\u52a8\u5668\u4e0d\u662f\u6700\u65b0\u7248\u672c\uff0c\u8bf7\u66f4\u65b0\u540e\u518d\u8bd5\uff01 -ui.label.failed_set=\u8bbe\u7f6e\u5931\u8d25\uff1a - -download=\u4e0b\u8f7d -download.mojang=\u5b98\u65b9 -download.BMCL=BMCLAPI (bangbang93, http://bmclapi.bangbang93.com/) -download.rapid_data=RapidData (\u9510\u7f51\u4e91\u8ba1\u7b97, https://www.rapiddata.org/) -download.not_200=\u4e0b\u8f7d\u5931\u8d25\uff0c\u56de\u590d\u7801 -download.failed=\u4e0b\u8f7d\u5931\u8d25 -download.successfully=\u4e0b\u8f7d\u5b8c\u6210 -download.source=\u4e0b\u8f7d\u6e90 - -message.error=\u9519\u8bef -message.cannot_open_explorer=\u65e0\u6cd5\u6253\u5f00\u6587\u4ef6\u7ba1\u7406\u5668: -message.cancelled=\u5df2\u53d6\u6d88 -message.info=\u63d0\u793a -message.loading=\u52a0\u8f7d\u4e2d... - -folder.game=\u6e38\u620f\u6587\u4ef6\u5939 -folder.mod=MOD\u6587\u4ef6\u5939 -folder.coremod=\u6838\u5fc3MOD\u6587\u4ef6\u5939 -folder.config=\u914d\u7f6e\u6587\u4ef6\u5939 -folder.resourcepacks=\u8d44\u6e90\u5305\u6587\u4ef6\u5939 -folder.screenshots=\u622a\u56fe\u6587\u4ef6\u5939 -folder.saves=\u5b58\u6863\u6587\u4ef6\u5939 - -settings.tabs.game_download=\u6e38\u620f\u4e0b\u8f7d -settings.tabs.installers=\u81ea\u52a8\u5b89\u88c5 -settings.tabs.assets_downloads=\u8d44\u6e90\u4e0b\u8f7d - -settings=\u666e\u901a\u8bbe\u7f6e -settings.explore=\u6d4f\u89c8 -settings.manage=\u7ba1\u7406 -settings.cannot_remove_default_config=\u4e0d\u80fd\u5220\u9664\u9ed8\u8ba4\u914d\u7f6e -settings.max_memory=\u6700\u5927\u5185\u5b58/MB -settings.java_dir=Java\u8def\u5f84 -settings.game_directory=\u6e38\u620f\u8def\u5f84 -settings.dimension=\u6e38\u620f\u7a97\u53e3\u5206\u8fa8\u7387 -settings.fullscreen=\u5168\u5c4f -settings.update_version=\u66f4\u65b0\u7248\u672c\u6587\u4ef6 -settings.run_directory=\u8fd0\u884c\u8def\u5f84(\u7248\u672c\u9694\u79bb) -settings.physical_memory=\u7269\u7406\u5185\u5b58\u5927\u5c0f -settings.choose_javapath=\u9009\u62e9Java\u8def\u5f84 -settings.default=\u9ed8\u8ba4 -settings.custom=\u81ea\u5b9a\u4e49 -settings.choose_gamedir=\u9009\u62e9\u6e38\u620f\u8def\u5f84 -settings.failed_load=\u8bbe\u7f6e\u6587\u4ef6\u52a0\u8f7d\u5931\u8d25\uff0c\u53ef\u80fd\u662f\u5347\u7ea7\u4e86\u542f\u52a8\u5668\u6216\u88ab\u4eba\u5de5\u4fee\u6539\u9020\u6210\u9519\u8bef\uff0c\u662f\u5426\u6e05\u9664\uff1f -settings.test_game=\u6d4b\u8bd5\u6e38\u620f - -settings.type.none=\u7f3a\u5c11\u6e38\u620f\u7248\u672c\uff0c\u8bf7\u5207\u6362\u5230\u6e38\u620f\u4e0b\u8f7d\u9875\u4e0b\u8f7d\u6e38\u620f -settings.type.global=\u70b9\u51fb\u6b64\u5904\u5207\u6362\u4e3a\u7248\u672c\u7279\u5b9a\u8bbe\u7f6e\u3002\u8be5\u7248\u672c\u6b63\u5728\u4f7f\u7528\u5168\u5c40\u8bbe\u7f6e\uff0c\u4fee\u6539\u4ee5\u4e0b\u8bbe\u7f6e\u4f1a\u5f71\u54cd\u5230\u5176\u4ed6\u4f7f\u7528\u5168\u5c40\u8bbe\u7f6e\u7684\u7248\u672c -settings.type.special=\u70b9\u51fb\u6b64\u5904\u5207\u6362\u4e3a\u5168\u5c40\u8bbe\u7f6e\u3002\u8be5\u7248\u672c\u6b63\u5728\u4f7f\u7528\u7248\u672c\u7279\u5b9a\u8bbe\u7f6e\uff0c\u4fee\u6539\u4ee5\u4e0b\u8bbe\u7f6e\u4e0d\u4f1a\u5f71\u54cd\u5230\u5176\u4ed6\u7248\u672c\u8bbe\u7f6e - -modpack=\u6574\u5408\u5305 -modpack.choose=\u9009\u62e9\u8981\u5bfc\u5165\u7684\u6e38\u620f\u6574\u5408\u5305\u6587\u4ef6\uff0c\u5982\u679c\u60a8\u5e0c\u671b\u66f4\u65b0\u6574\u5408\u5305\uff0c\u8bf7\u8f93\u5165\u8981\u66f4\u65b0\u7684\u7248\u672c\u540d -modpack.export_error=\u5bfc\u51fa\u5931\u8d25\uff0c\u53ef\u80fd\u662f\u60a8\u7684\u6e38\u620f\u6587\u4ef6\u5939\u683c\u5f0f\u4e0d\u6b63\u786e\u6216\u64cd\u4f5c\u6587\u4ef6\u5931\u8d25 -modpack.export_finished=\u6574\u5408\u5305\u5bfc\u51fa\u5b8c\u6210\uff0c\u53c2\u89c1 -modpack.included_launcher=\u6574\u5408\u5305\u5df2\u5305\u542b\u542f\u52a8\u5668\uff0c\u53ef\u76f4\u63a5\u53d1\u5e03 -modpack.not_included_launcher=\u6574\u5408\u5305\u672a\u5305\u542b\u542f\u52a8\u5668\uff0c\u53ef\u4f7f\u7528\u672c\u8f6f\u4ef6\u7684\u5bfc\u5165\u6574\u5408\u5305\u529f\u80fd\u5bfc\u5165\u6574\u5408\u5305 -modpack.enter_name=\u7ed9\u6e38\u620f\u8d77\u4e2a\u4f60\u559c\u6b22\u7684\u540d\u5b57 - -modpack.task.save=\u5bfc\u51fa\u6574\u5408\u5305 -modpack.task.install=\u5bfc\u5165\u6574\u5408\u5305 -modpack.task.install.error=\u5b89\u88c5\u5931\u8d25\uff0c\u53ef\u80fd\u662f\u6574\u5408\u5305\u683c\u5f0f\u4e0d\u6b63\u786e\u6216\u64cd\u4f5c\u6587\u4ef6\u5931\u8d25 -modpack.task.install.will=\u5c06\u4f1a\u5b89\u88c5\u6574\u5408\u5305\uff1a - -modpack.wizard=\u5bfc\u51fa\u6574\u5408\u5305\u5411\u5bfc -modpack.wizard.step.1=\u57fa\u672c\u8bbe\u7f6e -modpack.wizard.step.1.title=\u8bbe\u7f6e\u6574\u5408\u5305\u7684\u4e3b\u8981\u4fe1\u606f -modpack.wizard.step.initialization.include_launcher=\u5305\u542b\u542f\u52a8\u5668 -modpack.wizard.step.initialization.exported_version=\u8981\u5bfc\u51fa\u7684\u6e38\u620f\u7248\u672c -modpack.wizard.step.initialization.save=\u9009\u62e9\u8981\u5bfc\u51fa\u5230\u7684\u6e38\u620f\u6574\u5408\u5305\u4f4d\u7f6e -modpack.wizard.step.initialization.warning=\u5728\u5236\u4f5c\u6574\u5408\u5305\u524d\uff0c\u8bf7\u60a8\u786e\u8ba4\u60a8\u9009\u62e9\u7684\u7248\u672c\u53ef\u4ee5\u6b63\u5e38\u542f\u52a8\uff0c
    \u5e76\u4fdd\u8bc1\u60a8\u7684Minecraft\u662f\u6b63\u5f0f\u7248\u800c\u975e\u5feb\u7167\u7248\uff0c
    \u800c\u4e14\u4e0d\u5e94\u5f53\u5c06\u4e0d\u5141\u8bb8\u975e\u5b98\u65b9\u9014\u5f84\u4f20\u64ad\u7684Mod\u3001\u6750\u8d28\u5305\u7b49\u7eb3\u5165\u6574\u5408\u5305\u3002
    \u6574\u5408\u5305\u4f1a\u4fdd\u5b58\u60a8\u76ee\u524d\u7684\u4e0b\u8f7d\u6e90\u8bbe\u7f6e -modpack.wizard.step.2=\u6587\u4ef6\u9009\u62e9 -modpack.wizard.step.2.title=\u9009\u4e2d\u4f60\u4e0d\u60f3\u52a0\u5230\u6574\u5408\u5305\u4e2d\u7684\u6587\u4ef6(\u5939) -modpack.wizard.step.3=\u6574\u5408\u5305\u63cf\u8ff0 -modpack.wizard.step.3.title=\u63cf\u8ff0\u4f60\u8981\u5236\u4f5c\u7684\u6574\u5408\u5305 - -modpack.desc=\u63cf\u8ff0\u4f60\u8981\u5236\u4f5c\u7684\u6574\u5408\u5305\uff0c\u6bd4\u5982\u6574\u5408\u5305\u6ce8\u610f\u4e8b\u9879\u548c\u66f4\u65b0\u8bb0\u5f55\uff0c\u652f\u6301Markdown(\u56fe\u7247\u8bf7\u7528\u7f51\u7edc\u56fe\u7247)\u3002 -modpack.incorrect_format.no_json=\u6574\u5408\u5305\u683c\u5f0f\u9519\u8bef\uff0cpack.json\u4e22\u5931 -modpack.incorrect_format.no_jar=\u6574\u5408\u5305\u683c\u5f0f\u9519\u8bef\uff0cpack.json\u4e22\u5931jar\u5b57\u6bb5 -modpack.cannot_read_version=\u8bfb\u53d6\u6e38\u620f\u7248\u672c\u5931\u8d25 -modpack.not_a_valid_location=\u4e0d\u662f\u4e00\u4e2a\u6709\u6548\u6574\u5408\u5305\u4f4d\u7f6e -modpack.name=\u6574\u5408\u5305\u540d\u79f0 -modpack.not_a_valid_name=\u4e0d\u662f\u4e00\u4e2a\u6709\u6548\u7684\u6574\u5408\u5305\u540d\u79f0 - -modpack.files.servers_dat=\u591a\u4eba\u6e38\u620f\u670d\u52a1\u5668\u5217\u8868 -modpack.files.saves=\u6e38\u620f\u5b58\u6863 -modpack.files.mods=Mod -modpack.files.config=Mod\u914d\u7f6e\u6587\u4ef6 -modpack.files.liteconfig=Mod\u914d\u7f6e\u6587\u4ef6 -modpack.files.resourcepacks=\u8d44\u6e90\u5305(\u6750\u8d28\u5305) -modpack.files.options_txt=\u6e38\u620f\u8bbe\u5b9a -modpack.files.optionsshaders_txt=\u5149\u5f71\u8bbe\u5b9a -modpack.files.mods.voxelmods=VoxelMods\u914d\u7f6e\uff0c\u5982\u5c0f\u5730\u56fe -modpack.files.dumps=NEI\u8c03\u8bd5\u8f93\u51fa -modpack.files.scripts=MineTweaker\u914d\u7f6e -modpack.files.blueprints=BuildCraft\u84dd\u56fe - -mods=Mod\u7ba1\u7406 -mods.choose_mod=\u9009\u62e9\u6a21\u7ec4 -mods.failed=\u6dfb\u52a0\u5931\u8d25 -mods.add=\u6dfb\u52a0 -mods.remove=\u5220\u9664 -mods.default_information=\u5b89\u88c5Mod\u524d\u4f60\u9700\u8981\u786e\u4fdd\u5df2\u5b89\u88c5Forge\u6216LiteLoader!
    \u60a8\u53ef\u4ee5\u4ece\u8d44\u6e90\u7ba1\u7406\u5668\u62d6\u52a8mod\u6587\u4ef6\u5230\u5217\u8868\u4e2d\u6765\u6dfb\u52a0mod\uff0c\u540c\u65f6\u4f7f\u7528\u5220\u9664\u952e\u53ef\u5feb\u901f\u5220\u9664\u9009\u4e2dmod
    \u70b9\u6389mod\u524d\u9762\u7684\u52fe\u53ef\u7981\u7528mod\uff0c\u4e0d\u4f1a\u52a0\u8f7d\uff1b\u9009\u62e9mod\u53ef\u4ee5\u83b7\u53d6mod\u4fe1\u606f
    - -advancedsettings=\u9ad8\u7ea7\u8bbe\u7f6e -advancedsettings.launcher_visible=\u542f\u52a8\u5668\u53ef\u89c1\u6027 -advancedsettings.debug_mode=\u8c03\u8bd5\u6a21\u5f0f -advancedsettings.java_permanent_generation_space=\u5185\u5b58\u6c38\u4e45\u4fdd\u5b58\u533a\u57df(\u4e0d\u5fc5\u586b\u5199,MB) -advancedsettings.jvm_args=Java\u865a\u62df\u673a\u53c2\u6570(\u4e0d\u5fc5\u586b\u5199) -advancedsettings.Minecraft_arguments=Minecraft\u989d\u5916\u53c2\u6570(\u4e0d\u5fc5\u586b\u5199) -advancedsettings.launcher_visibility.close=\u6e38\u620f\u542f\u52a8\u540e\u7ed3\u675f\u542f\u52a8\u5668 -advancedsettings.launcher_visibility.hide=\u6e38\u620f\u542f\u52a8\u540e\u9690\u85cf\u542f\u52a8\u5668 -advancedsettings.launcher_visibility.keep=\u4fdd\u6301\u542f\u52a8\u5668\u53ef\u89c1 -advancedsettings.launcher_visibility.hide_reopen=\u9690\u85cf\u542f\u52a8\u5668\u5e76\u5728\u6e38\u620f\u7ed3\u675f\u540e\u91cd\u65b0\u6253\u5f00 -advancedsettings.game_dir.default=\u9ed8\u8ba4(.minecraft/) -advancedsettings.game_dir.independent=\u5404\u7248\u672c\u72ec\u7acb(.minecraft/versions/<\u7248\u672c\u540d>/,\u9664assets,libraries) -advancedsettings.no_jvm_args=\u4e0d\u6dfb\u52a0\u9ed8\u8ba4\u7684JVM\u53c2\u6570(\u4f7f\u7528Java9\u65f6\u5fc5\u52fe) -advancedsettings.no_common=\u4e0d\u4f7f\u7528\u516c\u5171\u8def\u5f84 -advancedsettings.java_args_default=\u542f\u52a8\u5668\u9ed8\u8ba4\u6dfb\u52a0\u7684\u53c2\u6570\uff08\u8bf7\u4e0d\u8981\u91cd\u590d\u6dfb\u52a0\uff09\uff1a-XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode -XX:-UseAdaptiveSizePolicy -XX:MaxPermSize=???m -Xmx???m -Dfml.ignoreInvalidMinecraftCertificates=true -Dfml.ignorePatchDiscrepancies=true -advancedsettings.wrapper_launcher=\u524d\u7f6e\u6307\u4ee4(\u4e0d\u5fc5\u586b\u5199,\u5982optirun) -advancedsettings.precall_command=\u542f\u52a8\u524d\u6267\u884c\u547d\u4ee4(\u4e0d\u5fc5\u586b\u5199\uff0c\u5c06\u5728\u6e38\u620f\u542f\u52a8\u524d\u8c03\u7528) -advancedsettings.server_ip=\u76f4\u5165\u670d\u52a1\u5668ip\u5730\u5740(\u4e0d\u5fc5\u586b\u5199\uff0c\u542f\u52a8\u6e38\u620f\u540e\u76f4\u63a5\u8fdb\u5165\u5bf9\u5e94\u670d\u52a1\u5668) -advancedsettings.cancel_wrapper_launcher=\u53d6\u6d88\u5305\u88f9\u542f\u52a8\u5668\uff08\u51fa\u73b0\u5947\u602a\u95ee\u9898\u65f6\u53ef\u5c1d\u8bd5\u4f7f\u7528,\u4e0e\u8c03\u8bd5\u6a21\u5f0f\u51b2\u7a81\uff09 -advancedsettings.dont_check_game_completeness=\u4e0d\u68c0\u67e5\u6e38\u620f\u5b8c\u6574\u6027 - -mainwindow.show_log=\u67e5\u770b\u65e5\u5fd7 -mainwindow.make_launch_script=\u751f\u6210\u542f\u52a8\u811a\u672c -mainwindow.make_launch_script_failed=\u751f\u6210\u542f\u52a8\u811a\u672c\u5931\u8d25 -mainwindow.enter_script_name=\u8f93\u5165\u8981\u751f\u6210\u811a\u672c\u7684\u6587\u4ef6\u540d -mainwindow.make_launch_succeed=\u542f\u52a8\u811a\u672c\u5df2\u751f\u6210\u5b8c\u6bd5: -mainwindow.no_version=\u672a\u627e\u5230\u4efb\u4f55\u7248\u672c\uff0c\u662f\u5426\u8fdb\u5165\u6e38\u620f\u4e0b\u8f7d\uff1f - -launcher.about=\u9ed8\u8ba4\u80cc\u666f\u56fe\u611f\u8c22gamerteam\u63d0\u4f9b\u3002
    \u5173\u4e8e\u4f5c\u8005\uff1a
    \u767e\u5ea6ID\uff1ahuanghongxun20
    mcbbs\uff1ahuanghongxun
    Minecraft Forum ID: klkl6523
    \u6b22\u8fce\u63d0\u4ea4Bug\u54e6
    Copyright (c) 2013-2017 huangyuhui.
    \u514d\u8d23\u58f0\u660e\uff1aMinecraft\u8f6f\u4ef6\u7248\u6743\u5f52Mojang AB\u6240\u6709\uff0c\u4f7f\u7528\u672c\u8f6f\u4ef6\u4ea7\u751f\u7684\u7248\u6743\u95ee\u9898\u672c\u8f6f\u4ef6\u5236\u4f5c\u65b9\u6982\u4e0d\u8d1f\u8d23\u3002
    \u672c\u542f\u52a8\u5668\u5728GPLv3\u534f\u8bae\u4e0b\u5f00\u6e90:https://github.com/huanghongxun/HMCL/ ,\u611f\u8c22issues\u548cpull requests\u8d21\u732e\u8005
    \u672c\u8f6f\u4ef6\u4f7f\u7528\u4e86\u57fa\u4e8eApache License 2.0\u7684Gson\u9879\u76ee\uff0c\u611f\u8c22\u8d21\u732e\u8005\u3002 -launcher.download_source=\u4e0b\u8f7d\u6e90 -launcher.background_location=\u80cc\u666f\u5730\u5740 -launcher.common_location=\u516c\u5171\u6587\u4ef6\u5939 -launcher.exit_failed=\u5f3a\u5236\u9000\u51fa\u5931\u8d25\uff0c\u53ef\u80fd\u662fForge 1.7.10\u53ca\u66f4\u9ad8\u7248\u672c\u5bfc\u81f4\u7684\uff0c\u65e0\u6cd5\u89e3\u51b3\u3002 -launcher.versions_json_not_matched=\u7248\u672c%s\u683c\u5f0f\u4e0d\u89c4\u8303\uff01\u8be5\u7248\u672c\u6587\u4ef6\u5939\u4e0b\u6709json:%s\uff0c\u662f\u5426\u66f4\u540d\u8fd9\u4e2a\u6587\u4ef6\u6765\u89c4\u8303\u683c\u5f0f\uff1f -launcher.versions_json_not_matched_cannot_auto_completion=\u7248\u672c%s\u7f3a\u5931\u5fc5\u8981\u7684\u7248\u672c\u4fe1\u606f\u6587\u4ef6\uff0c\u662f\u5426\u5220\u9664\u8be5\u7248\u672c\uff1f -launcher.versions_json_not_formatted=\u7248\u672c%s\u4fe1\u606f\u6587\u4ef6\u683c\u5f0f\u9519\u8bef\uff0c\u662f\u5426\u91cd\u65b0\u4e0b\u8f7d\uff1f -launcher.choose_bgpath=\u9009\u62e9\u80cc\u666f\u8def\u5f84 -launcher.choose_commonpath=\u9009\u62e9\u516c\u5171\u8def\u5f84 -launcher.commpath_tooltip=\u542f\u52a8\u5668\u5c06\u6240\u6709\u6e38\u620f\u8d44\u6e90\u53ca\u4f9d\u8d56\u5e93\u6587\u4ef6\u653e\u4e8e\u6b64\u96c6\u4e2d\u7ba1\u7406\uff0c\u5982\u679c\u6e38\u620f\u6587\u4ef6\u5939\u5185\u6709\u73b0\u6210\u7684\u5c06\u4e0d\u4f1a\u4f7f\u7528\u516c\u5171\u5e93\u6587\u4ef6 -launcher.background_tooltip=\u542f\u52a8\u5668\u9ed8\u8ba4\u4f7f\u7528\u81ea\u5e26\u7684\u80cc\u666f
    \u5982\u679c\u5f53\u524d\u76ee\u5f55\u6709background.png\uff0c\u5219\u4f1a\u4f7f\u7528\u8be5\u6587\u4ef6\u4f5c\u4e3a\u80cc\u666f
    \u5982\u679c\u5f53\u524d\u76ee\u5f55\u6709bg\u5b50\u76ee\u5f55\uff0c\u5219\u4f1a\u968f\u673a\u4f7f\u7528\u91cc\u9762\u7684\u4e00\u5f20\u56fe\u4f5c\u4e3a\u80cc\u666f
    \u5982\u679c\u8be5\u80cc\u666f\u5730\u5740\u88ab\u4fee\u6539\uff0c\u5219\u4f1a\u4f7f\u7528\u80cc\u666f\u5730\u5740\u91cc\u7684\u4e00\u5f20\u56fe\u4f5c\u4e3a\u80cc\u666f
    \u80cc\u666f\u5730\u5740\u5141\u8bb8\u6709\u591a\u4e2a\u5730\u5740\uff0c\u4f7f\u7528\u534a\u89d2\u5206\u53f7";"(\u4e0d\u5305\u542b\u53cc\u5f15\u53f7)\u5206\u9694 -launcher.update_launcher=\u68c0\u67e5\u66f4\u65b0 -launcher.enable_shadow=\u542f\u7528\u7a97\u53e3\u9634\u5f71 -launcher.enable_animation=\u542f\u7528\u52a8\u6001\u6548\u679c -launcher.enable_blur=\u542f\u7528\u4e3b\u754c\u9762\u6a21\u7cca -launcher.theme=\u4e3b\u9898 -launcher.proxy=\u4ee3\u7406 -launcher.decorated=\u542f\u7528\u7a97\u53e3\u8fb9\u6846(Linux\u4e0b\u53ef\u89e3\u51b3\u7a0b\u5e8f\u754c\u9762\u5168\u7070\u95ee\u9898) -launcher.modpack=\u6574\u5408\u5305\u4f5c\u8005\u5e2e\u52a9 -launcher.lang=\u8bed\u8a00 -launcher.restart=\u672c\u754c\u9762\u9009\u9879\u9700\u8981\u91cd\u542f\u672c\u542f\u52a8\u5668\u751f\u6548 -launcher.log_font=\u65e5\u5fd7\u5b57\u4f53 -launcher.tab.general=\u901a\u7528 -launcher.tab.ui=\u754c\u9762 -launcher.tab.about=\u5173\u4e8e - -launcher.title.game=\u6e38\u620f\u8bbe\u7f6e -launcher.title.main=\u4e3b\u9875 -launcher.title.launcher=\u542f\u52a8\u5668\u8bbe\u7f6e - -versions.release=\u7a33\u5b9a\u7248 -versions.snapshot=\u5feb\u7167\u7248 -versions.old_beta=\u6d4b\u8bd5\u7248 -versions.old_alpha=\u8fdc\u53e4\u7248 - -versions.manage.rename=\u91cd\u547d\u540d\u8be5\u7248\u672c -versions.manage.rename.message=\u8bf7\u8f93\u5165\u8981\u6539\u6210\u7684\u540d\u5b57 -versions.manage.remove=\u5220\u9664\u8be5\u7248\u672c -versions.manage.remove.confirm=\u771f\u7684\u8981\u5220\u9664\u7248\u672c -versions.manage.redownload_json=\u91cd\u65b0\u4e0b\u8f7d\u7248\u672c\u914d\u7f6e(minecraft.json) -versions.manage.redownload_assets_index=\u91cd\u65b0\u4e0b\u8f7d\u8d44\u6e90\u914d\u7f6e(assets_index.json) -versions.mamage.remove_libraries=\u5220\u9664\u6240\u6709\u5e93\u6587\u4ef6 - -advice.os64butjdk32=\u60a8\u7684\u7cfb\u7edf\u662f64\u4f4d\u7684\u4f46\u662fJava\u662f32\u4f4d\u7684\uff0c\u63a8\u8350\u60a8\u5b89\u88c564\u4f4dJava. -advice.java8=\u68c0\u6d4b\u5230\u60a8\u672a\u4f7f\u7528Java 8\u53ca\u66f4\u65b0\u7248\u672c\uff0cJava 8\u80fd\u4f7f\u6e38\u620f\u66f4\u6d41\u7545\u800c\u4e14Minecraft 1.12\u53ca\u66f4\u65b0\u7248\u672c\u548c\u5f88\u591aMod\u5f3a\u5236\u9700\u8981\u9700\u8981Java 8\u3002 - -assets.download_all=\u4e0b\u8f7d\u8d44\u6e90\u6587\u4ef6 -assets.not_refreshed=\u8d44\u6e90\u5217\u8868\u672a\u5237\u65b0\uff0c\u8bf7\u5237\u65b0\u4e00\u6b21\u3002 -assets.failed=\u83b7\u53d6\u5217\u8868\u5931\u8d25\uff0c\u8bf7\u5237\u65b0\u91cd\u8bd5\u3002 -assets.list.1_7_3_after=1.7.3\u53ca\u4ee5\u540e -assets.list.1_6=1.6(BMCLAPI) -assets.unkown_type_select_one=\u65e0\u6cd5\u89e3\u6790\u6e38\u620f\u7248\u672c\uff1a%s\uff0c\u8bf7\u9009\u62e9\u4e00\u79cd\u8d44\u6e90\u7c7b\u578b\u4e0b\u8f7d\u3002 -assets.type=\u8d44\u6e90\u7c7b\u578b -assets.download=\u4e0b\u8f7d\u8d44\u6e90 -assets.no_assets=\u8d44\u6e90\u6587\u4ef6\u4e0d\u5b8c\u6574\uff0c\u662f\u5426\u8865\u5168\uff1f -assets.failed_download=\u4e0b\u8f7d\u8d44\u6e90\u6587\u4ef6\u5931\u8d25\uff0c\u53ef\u80fd\u5bfc\u81f4\u6ca1\u6709\u4e2d\u6587\u548c\u58f0\u97f3\u3002 - -gamedownload.not_refreshed=\u6e38\u620f\u4e0b\u8f7d\u5217\u8868\u672a\u5237\u65b0\uff0c\u8bf7\u518d\u5237\u65b0\u4e00\u6b21\u3002 - -taskwindow.title=\u4efb\u52a1 -taskwindow.single_progress=\u5355\u9879\u8fdb\u5ea6 -taskwindow.total_progress=\u603b\u8fdb\u5ea6 -taskwindow.cancel=\u53d6\u6d88 -taskwindow.no_more_instance=\u53ef\u80fd\u540c\u65f6\u6253\u5f00\u4e86\u591a\u4e2a\u4efb\u52a1\u7a97\u53e3\uff0c\u8bf7\u4e0d\u8981\u591a\u6b21\u6253\u5f00\uff01 -taskwindow.file_name=\u4efb\u52a1 -taskwindow.download_progress=\u8fdb\u5ea6 - -setupwindow.include_minecraft=\u5bfc\u5165\u6e38\u620f\u6587\u4ef6\u5939 -setupwindow.find_in_configurations=\u5bfc\u5165\u5b8c\u6210\uff0c\u5feb\u5230\u914d\u7f6e\u4e0b\u62c9\u6846\u4e2d\u627e\u65b0\u6e38\u620f\u8def\u5f84\u5427\uff01 -setupwindow.give_a_name=\u7ed9\u65b0\u6e38\u620f\u8def\u5f84\u8d77\u4e2a\u540d\u5b57\u5427 -setupwindow.new=\u65b0\u5efa -setupwindow.no_empty_name=\u540d\u5b57\u4e0d\u53ef\u4e3a\u7a7a -setupwindow.clean=\u6e05\u7406\u6e38\u620f\u6587\u4ef6 - -update.no_browser=\u65e0\u6cd5\u6253\u5f00\u6d4f\u89c8\u5668\uff0c\u7f51\u5740\u5df2\u7ecf\u590d\u5236\u5230\u526a\u8d34\u677f\u4e86\uff0c\u60a8\u53ef\u4ee5\u624b\u52a8\u7c98\u8d34\u7f51\u5740\u6253\u5f00\u9875\u9762 -update.should_open_link=\u662f\u5426\u66f4\u65b0\uff1f -update.newest_version=\u6700\u65b0\u7248\u672c\u4e3a\uff1a -update.failed=\u68c0\u67e5\u66f4\u65b0\u5931\u8d25 -update.found=(\u53d1\u73b0\u66f4\u65b0!) - -logwindow.terminate_game=\u7ed3\u675f\u6e38\u620f\u8fdb\u7a0b -logwindow.title=\u65e5\u5fd7 -logwindow.contact=\u8054\u7cfb\u6211\u4eec -logwindow.show_lines=\u663e\u793a\u884c\u6570 -logwindow.search=\u67e5\u627e - -selector.choose=\u9009\u62e9 - -serverlistview.title=\u9009\u62e9\u670d\u52a1\u5668 -serverlistview.name=\u540d\u79f0 -serverlistview.type=\u7c7b\u578b -serverlistview.version=\u7248\u672c -serverlistview.info=\u4fe1\u606f - -minecraft.invalid=\u65e0\u6548\u7684 -minecraft.invalid_jar=\u65e0\u6548\u7684jar\u5305 -minecraft.not_a_file=\u4e0d\u662f\u6587\u4ef6 -minecraft.not_found=\u627e\u4e0d\u5230minecraft.jar -minecraft.not_readable=minecraft.jar\u4e0d\u53ef\u8bfb -minecraft.modified=(\u4fee\u6539\u7684!) - -color.red=\u7ea2\u8272 -color.blue=\u84dd\u8272 -color.green=\u7eff\u8272 -color.orange=\u6a59\u8272 -color.dark_blue=\u6df1\u84dd\u8272 -color.purple=\u7d2b\u8272 - -wizard.next_>=\u4e0b\u4e00\u6b65 > -wizard.next_mnemonic=\u4e0b -wizard.<_prev=< \u4e0a\u4e00\u6b65 -wizard.prev_mnemonic=\u4e0a -wizard.finish=\u5b8c\u6210 -wizard.finish_mnemonic=\u5b8c -wizard.cancel=\u53d6\u6d88 -wizard.cancel_mnemonic=\u53d6 -wizard.help=\u5e2e\u52a9 -wizard.help_mnemonic=\u5e2e -wizard.close=\u5173\u95ed -wizard.close_mnemonic=\u5173 -wizard.summary=\u6982\u8981 -wizard.failed=\u5931\u8d25 -wizard.steps=\u6b65\u9aa4 - -lang=\u7b80\u4f53\u4e2d\u6587 -lang.default=\u8ddf\u968f\u7cfb\u7edf\u8bed\u8a00 diff --git a/HMCLCore/src/main/resources/org/jackhuang/hmcl/wizard.jpg b/HMCLCore/src/main/resources/org/jackhuang/hmcl/wizard.jpg deleted file mode 100644 index 755408592f0b93ea06c1a5d6f60857ac8e8a3eae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6041 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 N>~ANoTQu$s{|^K=a+?4E diff --git a/HMCLaF/build.gradle b/HMCLaF/build.gradle deleted file mode 100755 index b0510b21f..000000000 --- a/HMCLaF/build.gradle +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ - -plugins { - id "me.tatarka.retrolambda" version "3.5.0" - //id "org.jetbrains.kotlin.jvm" version "1.1.2-2" -} - -if (System.getenv("BUILD_NUMBER") != null) - version = System.getenv("BUILD_NUMBER") - -dependencies { - compile project(":HMCLCore") -} - -retrolambda { - javaVersion = JavaVersion.VERSION_1_7 -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/BeautyEyeLNFHelper.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/BeautyEyeLNFHelper.java deleted file mode 100644 index 1b071290a..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/BeautyEyeLNFHelper.java +++ /dev/null @@ -1,391 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BeautyEyeLNFHelper.java at 2015-2-1 20:25:40, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf; - -import java.awt.Color; - -import javax.swing.BorderFactory; -import javax.swing.LookAndFeel; -import javax.swing.UIManager; -import javax.swing.border.Border; - -import org.jackhuang.hmcl.laf.widget.border.BEShadowBorder; -import org.jackhuang.hmcl.laf.widget.border.BEShadowBorder3; -import org.jackhuang.hmcl.laf.widget.border.PlainGrayBorder; - -/** - *

    - * BeautyEye Swing外观实现方案 - L&F核心辅助类.
    - *

    - * 项目托管地址:https://github.com/JackJiang2011/beautyeye - * - * @author Jack Jiang(jb2011@163.com), 2012-05 - * @version 1.0 - */ -public class BeautyEyeLNFHelper { - - /** - * 开关量:用于开启/关闭BeautyEye LNF的调试信息输出. - *

    - * 默认false,即不开启调试信息输出. - * - * @since 3.2 - */ - public static boolean debug = false; - /** - * 开关量:用于开启/关闭当窗口(包括JFrame、JDialog)处于非活动 状态(inactivity)时的半透明视觉效果. - *

    - * 默认true,即表示默认开启半透明效果. - * - * @since 3.2 - */ - public static boolean translucencyAtFrameInactive = true; - - /** - * BeautyEye LNF 的窗口边框样式. - *

    - * 默认值:运行在java1.6.0_u10及以上版本时使用 - * {@link FrameBorderStyle#translucencyAppleLike}, - * 运行在java1.5版本时使用{@link FrameBorderStyle#generalNoTranslucencyShadow}. - * - *

    - * 注意:如需设置本参数,请确保它在UIManager.setLookAndFeel前被设置,否则将不会起效哦. - * - * @see FrameBorderStyle - */ - public static FrameBorderStyle frameBorderStyle = FrameBorderStyle.translucencyAppleLike; - - /** - * 颜色全局变量:正常情况下的窗口文本颜色. - *

    - * 你可设置本变量,也可直接通过{@code UIManager.put("activeCaptionText",new ColorUIResource(c))}和 - * {@code UIManager.put("inactiveCaptionText",new ColorUIResource(c))}来实现窗口文本颜色的改变. - *

    - * 窗体不活动(inactivite)时的颜色将据此自动计算出来,无需额外设置. 默认是黑色(new Color(0,0,0)). - */ - public static Color activeCaptionTextColor = new Color(0, 0, 0);//黑色 - - /** - * 颜色全局变量:多数组件的背景色. - *

    - * 你可设置本变量,也可直接通过各自的UIManager属性来改变它们. - *

    - * 默认是浅灰色(new Color(250,250,250)). - * - * @since 3.2 - */ - public static Color commonBackgroundColor = new Color(250, 250, 250);//240,240,240); //248,248,248);//255,255,255);// - /** - * 颜色全局变量:多数组件的前景色(文本颜色). - *

    - * 你可设置本变量,也可直接通过各自的UIManager属性来改变它们. - *

    - * 默认是深灰色(new Color(60,60,60)). - * - * @since 3.2 - */ - public static Color commonForegroundColor = new Color(60, 60, 60);//102,102,102); - /** - * 颜色全局变量:某些组件的焦点边框颜色. 当前主要用于按钮等焦点边框的绘制颜色. - *

    - * 你可设置本变量,也可直接通过各自的UIManager属性来改变它们. - *

    - * 默认是浅灰色(new Color(250,250,250)). - * - * @since 3.2 - */ - public static Color commonFocusedBorderColor = new Color(162, 162, 162); - /** - * 颜色全局变量:某些组件被禁用时的文本颜色. 当前主要用于菜单项中. - *

    - * 你可设置本变量,也可直接通过各自的UIManager属性来改变它们. - *

    - * 默认是浅灰色(new Color(172,168,153)). - * - * @since 3.2 - */ - public static Color commonDisabledForegroundColor = new Color(172, 168, 153); - /** - * 颜色全局变量:多数组件中文本被选中时的背景色.当前主要用于各文本组件等. - *

    - * 你可设置本变量,也可直接通过各自的UIManager属性来改变它们. - *

    - * 默认是深灰色(new Color(2,129,216)). - * - * @since 3.2 - */ - public static Color commonSelectionBackgroundColor = new Color(2, 129, 216);//78,155,193));//58,135,173));//235,217,147));//new Color(255,237,167)); - /** - * 颜色全局变量:多数组件中文本被选中时的前景色(文本颜色).当前主要用于各文本组件、菜单项等. - *

    - * 你可设置本变量,也可直接通过各自的UIManager属性来改变它们. - *

    - * 默认是深灰色(new Color(255,255,255)). - * - * @since 3.2 - */ - public static Color commonSelectionForegroundColor = new Color(255, 255, 255); - - /** - * 开关量:用于默认设置或不设置窗口(Frame及其子类)的设置此窗体的最大化边界. - *

    - * 此开关量是它是为了解决这样一个问题 :
    - * 当不使用操作系统的窗口装饰(即使用完全自定义的窗口标题、边框)时,在windows上最 大化窗口时将会全屏显示从而覆盖了下方的任务栏(task - * bar),这个问题 据说自2002年 就已存在,SUN一直未解决或者根本不认为是bug。目前的解决方案是当本变量是true时则 - * 默认为每一个窗体设置最大化边界,否则保持系统默认。不过这样设置并非完美方案:一旦 设置了最大边界,则此后无论Task Bar再怎么调 - * 整大小,比如被hide了,则窗体永远是设 置时的最大边界,不过目前也只能这么折中解决了,因为窗体最大化事件处理并非L&F中实现 - * ,暂未找到其它更好的方法。 - *

    - * 默认true,即表示默认开启此设置. - * - * @since 3.2 - * @see javax.swing.JFrame#setMaximizedBounds(java.awt.Rectangle) - */ - public static boolean setMaximizedBoundForFrame = true; - - /** - * BeautyEye LNF的外观实现核心方法. - *

    - * 本方法可以直接从外部调用,这意味着BeautyEye LNF的外观核心实现无需特定于LookAndFeel的实例. - *

    - * 也就是说任意外观都可应用本方法所作的外观实现(并保证跨平台),以使之可灵活应用. - * - * @see org.jb2011.lnf.beautyeye.titlepane.__UI__#uiImpl() - * @see org.jb2011.lnf.beautyeye.tab.__UI__#uiImpl() - * @see org.jb2011.lnf.beautyeye.button.__UI__#uiImpl() - * @see org.jb2011.lnf.beautyeye.separator.__UI__#uiImpl() - * @see org.jb2011.lnf.beautyeye.scroll.__UI__#uiImpl() - * @see org.jb2011.lnf.beautyeye.table.__UI__#uiImpl() - * @see org.jb2011.lnf.beautyeye.textcoms.__UI__#uiImpl() - * @see org.jb2011.lnf.beautyeye.popup.__UI__#uiImpl() - * @see org.jb2011.lnf.beautyeye.toolbar.__UI__#uiImpl() - * @see org.jb2011.lnf.beautyeye.menu.__UI__#uiImpl() - * @see org.jb2011.lnf.beautyeye.internalframe.__UI__#uiImpl() - * @see org.jb2011.lnf.beautyeye.progress.__UI__#uiImpl() - * @see org.jb2011.lnf.beautyeye.radio$cb_btn.__UI__#uiImpl() - * @see org.jb2011.lnf.beautyeye.combox.__UI__#uiImpl() - * @see org.jb2011.lnf.beautyeye.slider.__UI__#uiImpl() - * @see org.jb2011.lnf.beautyeye.tree.__UI__#uiImpl() - * @see org.jb2011.lnf.beautyeye.split.__UI__#uiImpl() - * @see org.jb2011.lnf.beautyeye.spinner.__UI__#uiImpl() - * @see org.jb2011.lnf.beautyeye.list.__UI__#uiImpl() - * @see org.jb2011.lnf.beautyeye.filechooser.__UI__#uiImpl_win() - */ - protected static void implLNF() { - //自定义窗口的L&F实现 - org.jackhuang.hmcl.laf.titlepane.__UI__.uiImpl(); - //自定义JTabbedPane的L&F实现 - org.jackhuang.hmcl.laf.tab.__UI__.uiImpl(); - //自定义按钮的L&F实现 - org.jackhuang.hmcl.laf.button.__UI__.uiImpl(); - //各种杂七杂八的设置 - org.jackhuang.hmcl.laf.separator.__UI__.uiImpl(); - //自定义滚动条的L&F实现 - org.jackhuang.hmcl.laf.scroll.__UI__.uiImpl(); - //自定义表格头的L&F实现 - org.jackhuang.hmcl.laf.table.__UI__.uiImpl(); - //自定义文本组件的L&F实现 - org.jackhuang.hmcl.laf.textcoms.__UI__.uiImpl(); - //自定义弹出组件(包括toolTip组件和弹出菜单等)的L&F实现 - org.jackhuang.hmcl.laf.popup.__UI__.uiImpl(); - //自定义ToggleButton的L&F实现 - org.jackhuang.hmcl.laf.toolbar.__UI__.uiImpl(); - //自定义菜单项的L&F实现 - org.jackhuang.hmcl.laf.menu.__UI__.uiImpl(); - //自定义DesktopPane及内部窗体的L&F实现 - org.jackhuang.hmcl.laf.internalframe.__UI__.uiImpl(); - //自定义进度条的L&F实现 - org.jackhuang.hmcl.laf.progress.__UI__.uiImpl(); - //自定义单选按钮的L&F实现 - org.jackhuang.hmcl.laf.radio$cb_btn.__UI__.uiImpl(); - //自定义下拉框的L&F实现 - org.jackhuang.hmcl.laf.combox.__UI__.uiImpl(); - //自定义JSlider的L&F实现 - org.jackhuang.hmcl.laf.slider.__UI__.uiImpl(); - //自定义Jtree的L&F实现 - org.jackhuang.hmcl.laf.tree.__UI__.uiImpl(); - //自定义JSplitPane的L&F实现 - org.jackhuang.hmcl.laf.split.__UI__.uiImpl(); - //自定义JSpinner的L&F实现 - org.jackhuang.hmcl.laf.spinner.__UI__.uiImpl(); - //自定义JList的L&F实现 - org.jackhuang.hmcl.laf.list.__UI__.uiImpl(); - //自定义JFileChooser的L&F实现 - org.jackhuang.hmcl.laf.filechooser.__UI__.uiImpl(); - } - - /** - * Gets the beauty eye lnf platform. - * - * @return {@code new BeautyEyeLookAndFeel()} - */ - public static LookAndFeel getBeautyEyeLNFPlatform() { - return new BeautyEyeLookAndFeel(); - } - - /** - * 实施BeautyEye外观.开发者使用BeautyEye L&F时应首选本方法. - *

    - * 本方法会据操作系统类型不同,来决定主类是使用BeautyEyeLookAndFeelWin还是BeautyEyeLookAndFeelWin. - * 使用BeautyEye外观时推荐使用本方法来设置外观.之所以有平台不同主类不同的区分,是为了 - * 在Windows上平台上能更好的使用与操作系统相同的字体等设置. - * - * @throws Exception {@link UIManager#setLookAndFeel(String)}过程中出现的任何异常 - * @see #getBeautyEyeLNFStrWindowsPlatform() - * @see #getBeautyEyeLNFPlatform() - * @see org.jb2011.lnf.beautyeye.utils.Platform - */ - public static void launchBeautyEyeLNF() throws Exception { - System.setProperty("sun.java2d.noddraw", "true"); - UIManager.setLookAndFeel(getBeautyEyeLNFPlatform()); - } - - /** - * 开发者无需关注本方法. - *

    - * true表示当前正在使用的窗口边框是不透明的,否则表示透明. 本方法目前作为BERootPaneUI中设置窗口是否透明的开关使用. - *

    - * #### 官方API中存的Bug: ####
    - * 在jdk1.6.0_u33下+win7平台下(其它版本是否也有这情况尚未完全验证),JFrame窗口 - * 被设置成透明后,该窗口内所有文本都会被反走样(不管你有没有要求反走样),真悲具。 - * 这应该是官方AWTUtilities.setWindowOpaque(..)bug导致的,1.7.0_u6同样存在该问题, - * 使用BeautyEye时,遇到这样的问题只能自行使用本方法中指定的不透明边框才行(这样 - * BERootPaneUI类的设置窗口透明的代码就不用执行,也就不用触发该bug了),但JDialog 不受此bug影响,诡异! - * - * @return true, if successful - * @since 3.2 - */ - public static boolean isFrameBorderOpaque() { - return frameBorderStyle == FrameBorderStyle.osLookAndFeelDecorated - || frameBorderStyle == FrameBorderStyle.generalNoTranslucencyShadow; - } - - /** - * 开发者无需关注本方法. - *

    - * 根据设置的frameBorderStyle来返回正确的窗口边框. - * - * @return - * 当frameBorderStyle=={@link FrameBorderStyle#defaultLookAndFeelDecorated} - * 时返回无意义的BorderFactory.createEmptyBorder(),否则返回指定边框对象 - */ - public static Border getFrameBorder() { - switch (frameBorderStyle) { - case osLookAndFeelDecorated: - return BorderFactory.createEmptyBorder(); - case translucencyAppleLike: - return new BEShadowBorder3(); - case translucencySmallShadow: - return new BEShadowBorder(); - case generalNoTranslucencyShadow: - default: - return new PlainGrayBorder(); - } - } -// /** -// * 开发者无需关注本方法. -// *

    -// * 根据设置的frameBorderStyle来返回正确的窗口边框边角的拖动区大小. -// *

    -// * 重要说明:本方法中的边框类型及其对应的边框类必须与方法 {@link #__getFrameBorder()} -// * 完全一致! -// * -// * @return 当frameBorderStyle=={@link FrameBorderStyle#defaultLookAndFeelDecorated} -// * 时返回null,否则返回指定边框对象 -// */ -// public static int __getFrameBorder_CORNER_DRAG_WIDTH() -// { -// switch(frameBorderStyle) -// { -// case osLookAndFeelDecorated: -// return 16; -// case translucencyAppleLike: -// return BEShadowBorder3.CORNER_DRAG_WIDTH(); -// case translucencySmallShadow: -// return new BEShadowBorder().CORNER_DRAG_WIDTH(); -// case generalNoTranslucencyShadow: -// default: -// return new PlainGrayBorder().CORNER_DRAG_WIDTH(); -// } -// } -// /** -// * 开发者无需关注本方法. -// *

    -// * 根据设置的frameBorderStyle来返回正确的窗口边框拖动区大小. -// *

    -// * 重要说明:本方法中的边框类型及其对应的边框类必须与方法 {@link #__getFrameBorder()} -// * 完全一致! -// * -// * @return 当frameBorderStyle=={@link FrameBorderStyle#defaultLookAndFeelDecorated} -// * 时返回null,否则返回指定边框对象 -// */ -// public static int __getFrameBorder_BORDER_DRAG_THICKNESS() -// { -// switch(frameBorderStyle) -// { -// case osLookAndFeelDecorated: -// return 5; -// case translucencyAppleLike: -// return BEShadowBorder3.BORDER_DRAG_THICKNESS(); -// case translucencySmallShadow: -// return new BEShadowBorder().BORDER_DRAG_THICKNESS(); -// case generalNoTranslucencyShadow: -// default: -// return new PlainGrayBorder().BORDER_DRAG_THICKNESS(); -// } -// } - - /** - * BeautyEye LNF 的窗口边框样式. - */ - public enum FrameBorderStyle { - - /** - * 使用本地系统的窗口装饰样式(本样式将能带来最佳性能,使用操作系统默认窗口样式). - */ - osLookAndFeelDecorated, - /** - * 使用类似于MacOSX的强烈立体感半透明阴影边框(本样式性能尚可,视觉效果最佳). - */ - translucencyAppleLike, - /** - * 使用不太强烈立体感半透明阴影边框(本样式性能尚可,视觉效果较soft). - */ - translucencySmallShadow, - /** - * 使用不透明的普通边框(这是本LNF在Java1.5版默认使用的样式,因为java1.5不支持窗口透明) - */ - generalNoTranslucencyShadow - } - - /** - * 开发者暂时无需关注此接口. - *

    - * 实现了此接口的UI类意味着用户可以通过自行设置诸如border等,来 取消默认的NainePatch图实现的边框填充、背景填充等,具体设置哪 - * 些东西可以取消默认的NinePatch图填充的方式详见各自的类注释。 - */ - public interface __UseParentPaintSurported { - - /** - * 是否使用父类的绘制实现方法,true表示是. - *

    - * 因为在BE LNF中,进度条和背景都是使用N9图,比如没法通过设置JProgressBar的背景色和前景 - * 色来控制进度条的颜色,本方法的目的就是当用户设置了进度条的Background或Foreground 时告之本实现类不使用BE - * LNF中默认的N9图填充绘制而改用父类中的方法(父类中的方法 - * 就可以支持颜色的设置罗,只是丑点,但总归是能适应用户的需求场景要求,其实用户完全可以 通过JProgressBar.setUI(new - * MetalProgressBar())方式来自定义进度的UI哦). - * - * @return true, if is use parent paint - */ - boolean isUseParentPaint(); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/BeautyEyeLookAndFeel.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/BeautyEyeLookAndFeel.java deleted file mode 100644 index 7ac4af719..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/BeautyEyeLookAndFeel.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BeautyEyeLookAndFeel.java at 2015-2-1 20:25:40, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf; - -import java.awt.Font; -import java.util.Enumeration; -import javax.swing.UIDefaults; -import javax.swing.UIManager; -import javax.swing.plaf.FontUIResource; -import javax.swing.plaf.metal.MetalLookAndFeel; - -/** - *

    - * BeautyEye Swing外观实现方案 - 跨平台通用外观实现主类.
    - *

    - * 本主题主类仅供跨平台时使用,它可用于Java支持的所有操作系统. - * - * 如果要继承BasicLookAndFeel实现跨平台lnf 则还需要做更多的工作,目前 - * 跨平台时干脆继承MetalLookAndFeel以便站在巨人的肩膀上,节省一些工作量 - * - * @author Jack Jiang(jb2011@163.com) - * @version 1.0 - */ -public class BeautyEyeLookAndFeel extends MetalLookAndFeel { - private static void initGlobalFont(Font font) { - FontUIResource fontRes = new FontUIResource(font); - for (Enumeration keys = UIManager.getDefaults().keys(); - keys.hasMoreElements(); ) { - Object key = keys.nextElement(); - Object value = UIManager.get(key); - if (value instanceof FontUIResource) { - UIManager.put(key, fontRes); - } - } - } - - public BeautyEyeLookAndFeel() { - super(); - -// //本属性仅对windows平台有效?! -> Jack Jiang最终证实没效果!!!!!!!!!!! -// UIManager.put("Application.useSystemFontSettings", Boolean.TRUE); - //取消Metal LNF中默认的粗体字 - UIManager.put("swing.boldMetal", Boolean.FALSE); - //此项如是true,则将会为TabbedPane的内容面板填充天蓝色背景 - UIManager.put("TabbedPane.contentOpaque", Boolean.FALSE); - //此项如是true,则将会为TabbedPane的标签填充天蓝色背景 - UIManager.put("TabbedPane.tabsOpaque", Boolean.FALSE); - initGlobalFont(new Font("微软雅黑", Font.PLAIN, 12)); - BeautyEyeLNFHelper.implLNF(); - } - - @Override - public String getName() { - return "BeautyEye"; - } - - @Override - public String getID() { - return "BeautyEye"; - } - - @Override - public String getDescription() { - return "BeautyEye L&F developed by Jack Jiang(jb2011@163.com)."; - } - - /** - * Gets the supports window decorations. - * - * @return the supports window decorations {@inheritDoc} - */ - @Override - public boolean getSupportsWindowDecorations() { - return true; - } - - @Override - public boolean isNativeLookAndFeel() { - return false; - } - - @Override - public boolean isSupportedLookAndFeel() { - return true; - } - - @Override - protected void initComponentDefaults(UIDefaults table) { - super.initComponentDefaults(table); - initOtherResourceBundle(table); - } - - /** - * Initialize the defaults table with the name of the other ResourceBundle - * used for getting localized defaults. - */ - protected void initOtherResourceBundle(UIDefaults table) { - table.addResourceBundle("org.jb2011.lnf.beautyeye.resources.beautyeye"); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/LAFTheme.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/LAFTheme.java deleted file mode 100755 index cda967bfb..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/LAFTheme.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.laf; - -import java.util.HashMap; -import org.jackhuang.hmcl.api.ui.Theme; -import org.jackhuang.hmcl.util.C; - -/** - * - * @author huangyuhui - */ -public final class LAFTheme { - public static final Theme BLUE = new Theme("blue", C.i18n("color.blue"), new HashMap() { - { - put("Customized.TabbedPaneTab.selected_foreground", "#106CA3"); - put("Customized.ComboBox.selected_background", "#A0D8F0"); - put("Customized.MainFrame.background", "#106CA3"); - put("TabbedPane.selectedForeground", "#106CA3"); - put("TextField.focused", "#106CA3"); - put("MenuItem.selectionBackground", "#106CA3"); - put("Customized.MainFrame.selected_background", "#0C5E91"); - put("Customized.MainFrame.background_image", "background.jpg"); - } - }); - public static final Theme GREEN = new Theme("green", C.i18n("color.green"), new HashMap() { - { - put("Customized.TabbedPaneTab.selected_foreground", "#1ABC9C"); - put("Customized.ComboBox.selected_background", "#1ABC9C"); - put("Customized.MainFrame.background", "#1ABC9C"); - put("TabbedPane.selectedForeground", "#1ABC9C"); - put("TextField.focused", "#1ABC9C"); - put("MenuItem.selectionBackground", "#1ABC9C"); - put("Customized.MainFrame.selected_background", "#16A085"); - put("Customized.MainFrame.background_image", "background.jpg"); - } - }); - public static final Theme PURPLE = new Theme("purple", C.i18n("color.purple"), new HashMap() { - { - put("Customized.TabbedPaneTab.selected_foreground", "#9B59B6"); - put("Customized.ComboBox.selected_background", "#9B59B6"); - put("Customized.MainFrame.background", "#9B59B6"); - put("TabbedPane.selectedForeground", "#9B59B6"); - put("TextField.focused", "#9B59B6"); - put("MenuItem.selectionBackground", "#9B59B6"); - put("Customized.MainFrame.selected_background", "#8E44AD"); - put("Customized.MainFrame.background_image", "background.jpg"); - } - }); - public static final Theme DARKER_BLUE = new Theme("darker_blue", C.i18n("color.dark_blue"), new HashMap() { - { - put("Customized.TabbedPaneTab.selected_foreground", "#34495E"); - put("Customized.ComboBox.selected_background", "#34495E"); - put("Customized.MainFrame.background", "#34495E"); - put("TabbedPane.selectedForeground", "#34495E"); - put("TextField.focused", "#34495E"); - put("MenuItem.selectionBackground", "#34495E"); - put("Customized.MainFrame.selected_background", "#2C3E50"); - put("Customized.MainFrame.background_image", "background.jpg"); - } - }); - public static final Theme ORANGE = new Theme("orange", C.i18n("color.orange"), new HashMap() { - { - put("Customized.TabbedPaneTab.selected_foreground", "#E67E22"); - put("Customized.ComboBox.selected_background", "#F39C12"); - put("Customized.MainFrame.background", "#E67E22"); - put("TabbedPane.selectedForeground", "#E67E22"); - put("TextField.focused", "#E67E22"); - put("MenuItem.selectionBackground", "#E67E22"); - put("Customized.MainFrame.selected_background", "#D35400"); - put("Customized.MainFrame.background_image", "background.jpg"); - } - }); - public static final Theme RED = new Theme("red", C.i18n("color.red"), new HashMap() { - { - put("Customized.TabbedPaneTab.selected_foreground", "#E74C3C"); - put("Customized.ComboBox.selected_background", "#E74C3C"); - put("Customized.MainFrame.background", "#E74C3C"); - put("TabbedPane.selectedForeground", "#E74C3C"); - put("TextField.focused", "#E74C3C"); - put("MenuItem.selectionBackground", "#E74C3C"); - put("Customized.MainFrame.selected_background", "#C0392B"); - put("Customized.MainFrame.background_image", "background.jpg"); - } - }); - public static final Theme[] THEMES = new Theme[] {BLUE, GREEN, PURPLE, DARKER_BLUE, ORANGE, RED}; -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/button/BEButtonUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/button/BEButtonUI.java deleted file mode 100644 index 4e4e67102..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/button/BEButtonUI.java +++ /dev/null @@ -1,363 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BEButtonUI.java at 2015-2-1 20:25:36, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.button; - -import java.awt.Color; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Insets; - -import javax.swing.AbstractButton; -import javax.swing.ButtonModel; -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JComponent; -import javax.swing.JRadioButton; -import javax.swing.JToolBar; -import javax.swing.LookAndFeel; -import javax.swing.UIManager; -import javax.swing.border.Border; -import javax.swing.border.CompoundBorder; -import javax.swing.border.EmptyBorder; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.InsetsUIResource; -import javax.swing.plaf.UIResource; -import javax.swing.plaf.basic.BasicButtonUI; -import javax.swing.text.JTextComponent; -import org.jackhuang.hmcl.laf.utils.AnimationController; - -import org.jackhuang.hmcl.laf.utils.Icon9Factory; -import org.jackhuang.hmcl.laf.utils.Skin; -import org.jackhuang.hmcl.laf.utils.TMSchema; -import org.jackhuang.hmcl.laf.utils.TMSchema.Part; -import org.jackhuang.hmcl.laf.utils.TMSchema.State; - -/** - * JButton的UI实现类. - * - * @author Jack Jiang(jb2011@163.com) - * @version 1.0 - * @see com.sun.java.swing.plaf.windows.WindowsButtonUI - */ -public class BEButtonUI extends BasicButtonUI implements Skin { - - private static final Icon9Factory ICON_9 = new Icon9Factory("button"); - - private final static BEButtonUI INSTANCE = new BEButtonUI(); - - /** - * The dashed rect gap x. - */ - protected int dashedRectGapX; - - /** - * The dashed rect gap y. - */ - protected int dashedRectGapY; - - /** - * The dashed rect gap width. - */ - protected int dashedRectGapWidth; - - /** - * The dashed rect gap height. - */ - protected int dashedRectGapHeight; - - /** - * The focus color. - */ - protected Color focusColor; - - /** - * The defaults_initialized. - */ - private boolean defaults_initialized = false; - - // ******************************** - // Create PLAF - // ******************************** - public static ComponentUI createUI(JComponent c) { - if (c instanceof CustomButton) - return new CustomButtonUI(); - return INSTANCE; - } - - // ******************************** - // Defaults - // ******************************** - @Override - protected void installDefaults(AbstractButton b) { - super.installDefaults(b); - LookAndFeel.installProperty(b, "opaque", Boolean.FALSE); - - if (!defaults_initialized) { - String pp = getPropertyPrefix(); - dashedRectGapX = UIManager.getInt(pp + "dashedRectGapX"); - dashedRectGapY = UIManager.getInt(pp + "dashedRectGapY"); - dashedRectGapWidth = UIManager.getInt(pp + "dashedRectGapWidth"); - dashedRectGapHeight = UIManager.getInt(pp + "dashedRectGapHeight"); - focusColor = UIManager.getColor(pp + "focus"); - defaults_initialized = true; - } - - { - LookAndFeel.installProperty(b, "rolloverEnabled", Boolean.TRUE); - } - } - - @Override - protected void uninstallDefaults(AbstractButton b) { - super.uninstallDefaults(b); - defaults_initialized = false; - } - - /** - * Gets the focus color. - * - * @return the focus color - */ - protected Color getFocusColor() { - return focusColor; - } - - // ******************************** - // Layout Methods - // ******************************** - @Override - public Dimension getPreferredSize(JComponent c) { - Dimension d = super.getPreferredSize(c); - - /* Ensure that the width and height of the button is odd, - * to allow for the focus line if focus is painted - */ - AbstractButton b = (AbstractButton) c; - if (d != null && b.isFocusPainted()) { - if (d.width % 2 == 0) - d.width += 1; - if (d.height % 2 == 0) - d.height += 1; - } - return d; - } - - - /* These rectangles/insets are allocated once for all - * ButtonUI.paint() calls. Re-using rectangles rather than - * allocating them in each paint call substantially reduced the time - * it took paint to run. Obviously, this method can't be re-entered. - */ -// private static Rectangle viewRect = new Rectangle(); - @Override - public void paint(Graphics g, JComponent c) { - paintXPButtonBackground(g, c); - super.paint(g, c); - } - - /** - * Paint xp button background. - * - * @param nomalColor the nomal color - * @param g the g - * @param c the c - */ - public static void paintXPButtonBackground(Graphics g, JComponent c) { - AbstractButton b = (AbstractButton) c; - boolean toolbar = b.getParent() instanceof JToolBar; - - if (b.isContentAreaFilled()) { - ButtonModel model = b.getModel(); - Dimension d = c.getSize(); - int dx = 0; - int dy = 0; - int dw = d.width; - int dh = d.height; - - Border border = c.getBorder(); - Insets insets; - if (border != null) - // Note: The border may be compound, containing an outer - // opaque border (supplied by the application), plus an - // inner transparent margin border. We want to size the - // background to fill the transparent part, but stay - // inside the opaque part. - insets = BEButtonUI.getOpaqueInsets(border, c); - else - insets = c.getInsets(); - if (insets != null) { - dx += insets.left; - dy += insets.top; - dw -= (insets.left + insets.right); - dh -= (insets.top + insets.bottom); - } - - AnimationController.paintSkin(c, INSTANCE, g, dx, dy, dw, dh, getXPButtonState(b)); - } - } - - @Override - public Part getPart(JComponent c) { - return getXPButtonType((AbstractButton) c); - } - - static Part getXPButtonType(AbstractButton b) { - if (b instanceof JCheckBox) - return Part.BP_CHECKBOX; - if (b instanceof JRadioButton) - return Part.BP_RADIOBUTTON; - boolean toolbar = (b.getParent() instanceof JToolBar); - return toolbar ? Part.TP_BUTTON : Part.BP_PUSHBUTTON; - } - - public static State getXPButtonState(AbstractButton b) { - Part part = getXPButtonType(b); - ButtonModel model = b.getModel(); - State state = State.NORMAL; - switch (part) { - case BP_RADIOBUTTON: - case BP_CHECKBOX: - if (!model.isEnabled()) - state = (model.isSelected()) ? State.CHECKEDDISABLED - : State.UNCHECKEDDISABLED; - else if (model.isPressed() && model.isArmed()) - state = (model.isSelected()) ? State.CHECKEDPRESSED - : State.UNCHECKEDPRESSED; - else if (model.isRollover()) - state = (model.isSelected()) ? State.CHECKEDHOT - : State.UNCHECKEDHOT; - else - state = (model.isSelected()) ? State.CHECKEDNORMAL - : State.UNCHECKEDNORMAL; - break; - case BP_PUSHBUTTON: - case TP_BUTTON: - boolean toolbar = (b.getParent() instanceof JToolBar); - if (toolbar) { - if (model.isArmed() && model.isPressed()) - state = State.PRESSED; - else if (!model.isEnabled()) - state = State.DISABLED; - else if (model.isSelected() && model.isRollover()) - state = State.ROLLOVERCHECKED; - else if (model.isSelected()) - state = State.CHECKED; - else if (model.isRollover()) - state = State.ROLLOVER; - else if (b.hasFocus()) - state = State.ROLLOVER; - } else - if ((model.isArmed() && model.isPressed()) - || model.isSelected()) - state = State.PRESSED; - else if (!model.isEnabled()) - state = State.DISABLED; - else if (model.isRollover() || model.isPressed()) - state = State.ROLLOVER; - else if (b instanceof JButton - && ((JButton) b).isDefaultButton()) - state = State.NORMAL; - break; - default: - state = State.NORMAL; - } - - return state; - } - - @Override - public void paintSkinRaw(Graphics g, int dx, int dy, int dw, int dh, TMSchema.State state) { - ICON_9.get(state.toString()).draw((Graphics2D) g, dx, dy, dw, dh); - } - - /** - * returns - b.getBorderInsets(c) if border is opaque - null if border is - * completely non-opaque - somewhere inbetween if border is compound and - * outside border is opaque and inside isn't - * - * @param b the b - * @param c the c - * @return the opaque insets - */ - private static Insets getOpaqueInsets(Border b, Component c) { - if (b == null) - return null; - if (b.isBorderOpaque()) - return b.getBorderInsets(c); - else if (b instanceof CompoundBorder) { - CompoundBorder cb = (CompoundBorder) b; - Insets iOut = getOpaqueInsets(cb.getOutsideBorder(), c); - if (iOut != null && iOut.equals(cb.getOutsideBorder().getBorderInsets(c))) { - // Outside border is opaque, keep looking - Insets iIn = getOpaqueInsets(cb.getInsideBorder(), c); - if (iIn == null) - // Inside is non-opaque, use outside insets - return iOut; - else - // Found non-opaque somewhere in the inside (which is - // also compound). - return new Insets(iOut.top + iIn.top, iOut.left + iIn.left, - iOut.bottom + iIn.bottom, iOut.right + iIn.right); - } else - // Outside is either all non-opaque or has non-opaque - // border inside another compound border - return iOut; - } else - return null; - } - - public static class BEEmptyBorder extends EmptyBorder implements UIResource { - - public BEEmptyBorder(Insets m) { - super(m.top + 2, m.left + 2, m.bottom + 2, m.right + 2); - } - - @Override - public Insets getBorderInsets(Component c) { - return getBorderInsets(c, getBorderInsets()); - } - - @Override - public Insets getBorderInsets(Component c, Insets insets) { - insets = super.getBorderInsets(c, insets); - - Insets margin = null; - if (c instanceof AbstractButton) { - Insets m = ((AbstractButton) c).getMargin(); - // if this is a toolbar button then ignore getMargin() - // and subtract the padding added by the constructor - if (c.getParent() instanceof JToolBar - && !(c instanceof JRadioButton) - && !(c instanceof JCheckBox) - && m instanceof InsetsUIResource) { - insets.top -= 2; - insets.left -= 2; - insets.bottom -= 2; - insets.right -= 2; - } else - margin = m; - } else if (c instanceof JToolBar) - margin = ((JToolBar) c).getMargin(); - else if (c instanceof JTextComponent) - margin = ((JTextComponent) c).getMargin(); - if (margin != null) { - insets.top = margin.top + 2; - insets.left = margin.left + 2; - insets.bottom = margin.bottom + 2; - insets.right = margin.right + 2; - } - return insets; - } - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/button/BEToggleButtonUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/button/BEToggleButtonUI.java deleted file mode 100644 index 38a97ff22..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/button/BEToggleButtonUI.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BEToggleButtonUI.java at 2015-2-1 20:25:40, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.button; - -import java.awt.FontMetrics; -import java.awt.Graphics; -import java.awt.Rectangle; - -import javax.swing.AbstractButton; -import javax.swing.ButtonModel; -import javax.swing.JComponent; -import javax.swing.LookAndFeel; -import javax.swing.UIManager; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicToggleButtonUI; - -import org.jackhuang.hmcl.laf.BEUtils; -import org.jackhuang.hmcl.laf.utils.Icon9Factory; -import org.jackhuang.hmcl.laf.utils.MySwingUtilities2; - -/** - * JToggleButton的UI实现类. - * - * @author Jack Jiang(jb2011@163.com) - * @see com.sun.java.swing.plaf.windows.WindowsToggleButtonUI - */ -public class BEToggleButtonUI extends BasicToggleButtonUI { - - protected static final Icon9Factory ICON_9 = new Icon9Factory("toggle_button"); - - private static final BEToggleButtonUI INSTANCE = new BEToggleButtonUI(); - - public static ComponentUI createUI(JComponent b) { - return INSTANCE; - } - - //* 由Jack Jiang于2012-10-12日加入:重写本方法的目的是使得JToggleButton不填充 - //* BasicToggleButtonUI里的白色距形区,否则在JToolBar上时会因该白色距形区的存 - //* 在而使得与BEToolBarUI的渐变背景不协调(丑陋的创可贴效果),实际上 - //* WindowsToolButtonUI里有同名方法里也是它样处理的,详情参见WindowsToolButtonUI - @Override - protected void installDefaults(AbstractButton b) { - super.installDefaults(b); - LookAndFeel.installProperty(b, "opaque", Boolean.FALSE); - } - - // ******************************** - // Paint Methods - // ******************************** - @Override - public void paint(Graphics g, JComponent c) { - BEButtonUI.paintXPButtonBackground(g, c); - super.paint(g, c); - } - - //修改的目的是让它在获得焦点(或说点中时)改变前景色,可惜父类中没有实现它,只能自已来解决了 - /** - * As of Java 2 platform v 1.4 this method should not be used or overriden. - * Use the paintText method which takes the AbstractButton argument. - * - * @param g the g - * @param c the c - * @param textRect the text rect - * @param text the text - * @see - * javax.swing.plaf.basic.BasicToggleButtonUI#paintText(java.awt.Graphics, - * javax.swing.JComponent, java.awt.Rectangle, java.lang.String) - */ - @Override - protected void paintText(Graphics g, JComponent c, Rectangle textRect, String text) { - AbstractButton b = (AbstractButton) c; - ButtonModel model = b.getModel(); - FontMetrics fm = MySwingUtilities2.getFontMetrics(c, g); - int mnemonicIndex = b.getDisplayedMnemonicIndex(); - - if (model.isEnabled()) { - if (model.isSelected()) - g.setColor(UIManager.getColor(getPropertyPrefix() + "focus")); - else - g.setColor(b.getForeground()); - - MySwingUtilities2.drawStringUnderlineCharAt(c, g, text, mnemonicIndex, - textRect.x + getTextShiftOffset(), - textRect.y + fm.getAscent() + getTextShiftOffset()); - } else { - g.setColor(b.getBackground().brighter()); - MySwingUtilities2.drawStringUnderlineCharAt(c, g, text, mnemonicIndex, - textRect.x, textRect.y + fm.getAscent()); - g.setColor(b.getBackground().darker()); - MySwingUtilities2.drawStringUnderlineCharAt(c, g, text, mnemonicIndex, - textRect.x - 1, textRect.y + fm.getAscent() - 1); - } - } - - /** - * {@inheritDoc} - * - * Method signature defined here overriden in subclasses. Perhaps this class - * should be abstract? - */ - @Override - protected void paintFocus(Graphics g, AbstractButton b, - Rectangle viewRect, Rectangle textRect, Rectangle iconRect) { - Rectangle bound = b.getVisibleRect(); - //决定焦点要制的位置(当前实现是往内缩3个像素,与当前按钮背景配合) - final int delta = 3; - int x = bound.x + delta, y = bound.y + delta, w = bound.width - delta * 2, h = bound.height - delta * 2; - - //绘制焦点虚线框 - g.setColor(UIManager.getColor("ToggleButton.focusLine"));//*~ 这是Jack Jiang自定义的属性哦 - BEUtils.drawDashedRect(g, x, y, w, h, 17, 17, 2, 2); - //再绘制焦点虚线框的立体高亮阴影,以便形成立体感 - g.setColor(UIManager.getColor("ToggleButton.focusLineHilight"));//*~ 这是Jack Jiang自定义的属性哦 - BEUtils.drawDashedRect(g, x + 1, y + 1, w, h, 17, 17, 2, 2); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/button/CustomButton.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/button/CustomButton.java deleted file mode 100755 index ca3285982..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/button/CustomButton.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2013 huangyuhui - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. - */ -package org.jackhuang.hmcl.laf.button; - -import java.awt.Color; -import org.jackhuang.hmcl.util.ui.GraphicsUtils; - -/** - * - * @author huangyuhui - */ -public class CustomButton extends javax.swing.JButton { - public Color normalFg = GraphicsUtils.getWebColorWithAlpha("DDDDDD6F"), normalBg = GraphicsUtils.getWebColorWithAlpha("DDDDDD6F"), - prelightFg = GraphicsUtils.getWebColorWithAlpha("FFFFFF7F"), prelightBg = GraphicsUtils.getWebColorWithAlpha("FFFFFF7F"), - activeFg = GraphicsUtils.getWebColorWithAlpha("EAEDF83F"), activeBg = GraphicsUtils.getWebColorWithAlpha("EAEDF83F"); - public int drawPercent = 0; - public int radix = 0; -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/button/CustomButtonUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/button/CustomButtonUI.java deleted file mode 100644 index 0cc0800f2..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/button/CustomButtonUI.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.laf.button; - -import java.awt.Color; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.RenderingHints; -import java.awt.geom.RoundRectangle2D; -import javax.swing.AbstractButton; -import javax.swing.ButtonModel; -import javax.swing.JComponent; -import javax.swing.LookAndFeel; -import javax.swing.Timer; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicButtonUI; -import org.jackhuang.hmcl.util.ui.GraphicsUtils; -import org.jackhuang.hmcl.laf.button.BEButtonUI; - -/** - * - * @author huang - */ -public class CustomButtonUI extends BasicButtonUI { - - private static final String DEFAULT_NORMAL = "D5D5D5"; - private static final Color[] DEFAULT_NORMAL_FG = new Color[] { - GraphicsUtils.getWebColor(DEFAULT_NORMAL), - GraphicsUtils.getWebColor(DEFAULT_NORMAL) - }; - private static final String DEFAULT_PRELIGHT = "A9A9A9"; - private static final Color[] DEFAULT_PRELIGHT_FG = new Color[] { - GraphicsUtils.getWebColor(DEFAULT_PRELIGHT), - GraphicsUtils.getWebColor(DEFAULT_PRELIGHT) - }; - private static final String DEFAULT_ACTIVE = "222222"; - private static final Color[] DEFAULT_ACTIVE_FG = new Color[] { - GraphicsUtils.getWebColor(DEFAULT_ACTIVE), - GraphicsUtils.getWebColor(DEFAULT_ACTIVE) - }; - - private static final Color[] DISABLED_BG = new Color[] { - GraphicsUtils.getWebColor("E3EFE9"), - GraphicsUtils.getMidWebColor("E3EFE9", "DFE2E6"), - GraphicsUtils.getWebColor("DFE2E6"), - GraphicsUtils.getMidWebColor("DFE2E6", "D6D9DF"), - GraphicsUtils.getWebColor("D6D9DF"), - GraphicsUtils.getWebColor("D6D9DF"), - GraphicsUtils.getMidWebColor("D6D9DF", "D8DBE1"), - GraphicsUtils.getWebColor("D8DBE1"), - GraphicsUtils.getWebColor("DADDE3") - }; - private static final Color[] DISABLED_FG = new Color[] { - GraphicsUtils.getWebColor("C9CCD2"), - GraphicsUtils.getWebColor("C9CCD2"), - GraphicsUtils.getWebColor("BCBFC5"), - GraphicsUtils.getWebColor("BCBFC5") - }; - - private static boolean processCustomButton(final CustomButton c, int add) { - if (c.drawPercent == 0 || c.drawPercent == 100) { - Timer t = new Timer(1, null); - t.addActionListener(x -> { - c.drawPercent += add; - if (c.drawPercent > 100 && add > 0) { - c.drawPercent = 100; - t.stop(); - } else if (c.drawPercent < 0 && add < 0) { - c.drawPercent = 0; - t.stop(); - } else - c.updateUI(); - }); - t.start(); - } - return true; - } - - @Override - protected void installDefaults(AbstractButton b) { - super.installDefaults(b); - LookAndFeel.installProperty(b, "opaque", Boolean.FALSE); - } - - @Override - public void paint(Graphics g, JComponent component) { - CustomButton c = (CustomButton) component; - ButtonModel model = c.getModel(); - Graphics2D g2 = (Graphics2D) g.create(); - g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - Color[] fg, bg; - if (model.isPressed()) { - fg = new Color[] { c.activeFg, c.activeFg }; - bg = new Color[] { c.activeFg, c.activeFg }; - } else if (!c.isEnabled()) - return; - else if (model.isRollover()) { - if (!processCustomButton(c, 1)) - return; - Color fgs = GraphicsUtils.getMidWebColor(c.normalFg, c.prelightFg, c.drawPercent); - Color bgs = GraphicsUtils.getMidWebColor(c.normalBg, c.prelightBg, c.drawPercent); - fg = new Color[] { fgs, fgs }; - bg = new Color[] { bgs, bgs }; - } else { - if (!processCustomButton(c, -1)) - return; - Color fgs = GraphicsUtils.getMidWebColor(c.normalFg, c.prelightFg, c.drawPercent); - Color bgs = GraphicsUtils.getMidWebColor(c.normalBg, c.prelightBg, c.drawPercent); - fg = new Color[] { fgs, fgs }; - bg = new Color[] { bgs, bgs }; - } - - int radix = c.radix; - int x = 0, y = 0, w = c.getWidth(), h = c.getHeight(); - - g2.setColor(fg[0]); - RoundRectangle2D fgshape = new RoundRectangle2D.Float(x, y, w, h, radix, radix); - g2.draw(fgshape); - g2.setColor(bg[0]); - RoundRectangle2D bgshape = new RoundRectangle2D.Float(x, y, w, h, radix, radix); - g2.fill(bgshape); - - super.paint(g, c); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/button/__UI__.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/button/__UI__.java deleted file mode 100644 index 6d9f192fd..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/button/__UI__.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * __UI__.java at 2015-2-1 20:25:40, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.button; - -import java.awt.Insets; - -import javax.swing.UIManager; -import javax.swing.plaf.basic.BasicBorders.MarginBorder; - -import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper; -import org.jackhuang.hmcl.laf.utils.UI; - -public class __UI__ extends UI { - - public static void uiImpl() { - //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> JButton相关ui属性设定 - put("Button.background", BeautyEyeLNFHelper.commonBackgroundColor); - //Button.foreground的设定不起效,这可能是LNF里的bug,因NLLookAndFeel - //是继承自它们所以暂时无能为力,就这么的吧,以后再说 - put("Button.foreground", BeautyEyeLNFHelper.commonForegroundColor); - - //以下属性将决定按钮获得焦点时的焦点虚线框的绘制偏移量哦 - put("Button.dashedRectGapX", 3); - put("Button.dashedRectGapY", 3); - put("Button.dashedRectGapWidth", 6); - put("Button.dashedRectGapHeight", 6); - - put("ButtonUI", BEButtonUI.class); - putInsets("Button.margin", 2, 5, 2, 5); - //此border可以与Button.margin连合使用,而者之和即查整个Button的内衬哦 - UIManager.put("Button.border", new BEButtonUI.BEEmptyBorder(new Insets(3, 3, 3, 3))); - //获得焦点时的虚线框颜色 - putColor("Button.focus", 130, 130, 130); - - //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> JToggleButton相关ui属性设定 - //注意:本属性不要与ToggleButton.border混用,因为没有它的优先级高, - //另本参数如用InsetsUIResource则不会有效果,具体原因待查(本属性也将决定toolbar的整体高度和宽度哦) - putInsets("ToggleButton.margin", 3, 11, 3, 11);//4, 8, 4, 8));////4, 12, 4, 12)); - put("ToggleButton.background", BeautyEyeLNFHelper.commonBackgroundColor); - put("ToggleButton.foreground", BeautyEyeLNFHelper.commonForegroundColor); - //用于ToggleButon被选中时的前景色 - //注:在原WindowsLookAndFeel中,本属性存在(值是Color(0,0,0,))但在UI里没有用到 - //,此处被jb2011定义为“选中时的前景色”,当然也可以自已定名称,参见 NLWindowsToggleButtonUI2.paintText(..) - put("ToggleButton.focus", BeautyEyeLNFHelper.commonForegroundColor);// Color.white - put("ToggleButtonUI", BEToggleButtonUI.class); - //以下设置对ToggleButton在不加入到JToolBar时是有效果的哦!!!!!!!!!!! -// UIManager.put("ToggleButton.margin",new InsetsUIResource(2, 30, 2, 30)); - put("ToggleButton.border", new MarginBorder()); - /* ~~注:这个属性是Jack Jiang为了更好的ui效果自已加的属性:焦点虚线的颜色 */ - put("ToggleButton.focusLine", BeautyEyeLNFHelper.commonFocusedBorderColor.darker()); - /* ~~注:这个属性是Jack Jiang为了更好的ui效果自已加的属性:焦点虚线的高亮立体阴影颜色 */ - putColor("ToggleButton.focusLineHilight", 240, 240, 240); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/combox/BEComboBoxRenderer.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/combox/BEComboBoxRenderer.java deleted file mode 100644 index 2855f6315..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/combox/BEComboBoxRenderer.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BEComboBoxRenderer.java at 2015-2-1 20:25:38, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.combox; - -import java.awt.Component; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Insets; - -import javax.swing.BorderFactory; -import javax.swing.JList; -import javax.swing.plaf.basic.BasicComboBoxRenderer; -import org.jackhuang.hmcl.laf.menu.BEMenuUI; -import org.jackhuang.hmcl.laf.BEUtils; - -/** - * JComboBox组件下拉选项的render默认实现类. - * - * @author Jack Jiang(jb2011@163.com), 2012-07-05 - * @see BEComboBoxUI - */ -public class BEComboBoxRenderer extends BasicComboBoxRenderer { - - /** - * 当前下拉框里的item是否被选中:用于是否要将背景填充选中样式时使用. - */ - private boolean selected = false; - - /** - * 记下本render对应的JComboBox的UI. - */ - private BEComboBoxUI comboBoxUI = null; - - public BEComboBoxRenderer(BEComboBoxUI ui) { - super(); - this.comboBoxUI = ui; - //设置成透明背景则意味着不需要背景填充,但本类中的应用场景有点特殊 - //——默认的render的UI里不需要绘制背景的情况下本类才可进行NinePatch图作为背景进行填充 - setOpaque(false); - //TODO 此border(render的内衬)可以作为一个UIManager的属性哦,方便以后设置 - //注:此内衬是决定列表单元间的上下左右空白的关键哦! - setBorder(BorderFactory.createEmptyBorder(5, 4, 5, 8));//此设置是与Combox.border UI属性配合哦 - } - - /** - * {@inheritDoc} - * - * @see - * javax.swing.plaf.basic.BasicComboBoxRenderer#getListCellRendererComponent - * (javax.swing.JList, java.lang.Object, int, boolean, boolean) - */ - @Override - public Component getListCellRendererComponent(JList list, - Object value, int index, boolean isSelected, boolean cellHasFocus) { - Component c = super.getListCellRendererComponent(list, - value, index, isSelected, cellHasFocus); - //add by jb2011:保存选中状态 - this.selected = isSelected; - return c; - } - - /** - * {@inheritDoc} - * - * 按理说本方法中的是否选中背景填充实现逻辑在Render的UI中实现最为合理,但由于 - * 本类就是处理于UI实现中,所以容易产生冲突,故而不适宜自定义Ui实现,干脆硬编码则更直接 - */ - @Override - public void paintComponent(Graphics g) { - //当下拉选项弹出时 且 该item是被选中时才需要把背景填充成选中样式 - if (comboBoxUI.isPopupVisible(null) && selected) - BEMenuUI.drawSelectedBackground(g, 0, 0, this.getWidth(), this.getHeight()); - //下拉选项未弹出时JComboBox的背景样式 - //按理说,本类已设置成透明而无须填充背景,但本应用场景中,只能在默认Ui不填充背景的情况下才 - //能完成自定义NinePatch背景的填充。见 ComponentUI.update(Graphics g, JComponent c)方法 - - //注意:本组件已经被设置成opaque=false即透明,否则本方法还会填充默认背景,那么选中时的 - //N9图背景因先绘将会被覆盖哦。所以要使用N9图作为选中时的背景则前提是本组件必须是透明 - super.paintComponent(g); - } - - //copy from BasicComboBoxRenderer and modified by jb2011 - /** - * A subclass of BasicComboBoxRenderer that implements UIResource. - * BasicComboBoxRenderer doesn't implement UIResource directly so that - * applications can safely override the cellRenderer property with - * BasicListCellRenderer subclasses. - *

    - * Warning: - * Serialized objects of this class will not be compatible with future Swing - * releases. The current serialization support is appropriate for short term - * storage or RMI between applications running the same version of Swing. As - * of 1.4, support for long term storage of all - * JavaBeansTM - * has been added to the java.beans package. Please see - * {@link java.beans.XMLEncoder}. - */ - public static class UIResource extends BEComboBoxRenderer implements javax.swing.plaf.UIResource { - - /** - * Instantiates a new uI resource. - * - * @param ui the ui - */ - public UIResource(BEComboBoxUI ui) { - super(ui); - } - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/combox/BEComboBoxUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/combox/BEComboBoxUI.java deleted file mode 100644 index de0381593..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/combox/BEComboBoxUI.java +++ /dev/null @@ -1,406 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BEComboBoxUI.java at 2015-2-1 20:25:38, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.combox; - -import java.awt.Component; -import java.awt.Container; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Insets; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; - -import javax.swing.ComboBoxEditor; -import javax.swing.JButton; -import javax.swing.JComboBox; -import javax.swing.JComponent; -import javax.swing.JScrollPane; -import javax.swing.ListCellRenderer; -import javax.swing.LookAndFeel; -import javax.swing.UIManager; -import javax.swing.border.Border; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; -import javax.swing.plaf.basic.BasicComboBoxEditor; -import javax.swing.plaf.basic.BasicComboBoxUI; -import javax.swing.plaf.basic.BasicComboPopup; -import javax.swing.plaf.basic.ComboPopup; -import org.jackhuang.hmcl.laf.utils.AnimationController; -import org.jackhuang.hmcl.laf.utils.Icon9Factory; -import org.jackhuang.hmcl.laf.utils.Skin; -import org.jackhuang.hmcl.laf.utils.TMSchema; -import org.jackhuang.hmcl.laf.utils.TMSchema.State; - -/** - * JComboBox的UI实现类. - * - * @author Jack Jiang(jb2011@163.com), 2012-06-30 - * @version 1.0 - * @see com.sun.java.swing.plaf.windows.WindowsComboBoxUI - */ -public class BEComboBoxUI extends BasicComboBoxUI - implements org.jackhuang.hmcl.laf.BeautyEyeLNFHelper.__UseParentPaintSurported, MouseListener, Skin { - - private static final Icon9Factory ICON_9 = new Icon9Factory("combo"); - private static final Dimension BTN_SIZE = new Dimension(17, 20); - private final Dimension btnSize = new Dimension(BTN_SIZE); - - public static ComponentUI createUI(JComponent c) { - return new BEComboBoxUI(); - } - - //* 本方法由Jack Jiang于2012-09-07日加入 - /** - * 是否使用父类的绘制实现方法,true表示是. - *

    - * 因为在BE LNF中,边框和背景等都是使用N9图,没法通过设置背景色和前景 - * 色来控制JComboBox的颜色和边框,本方法的目的就是当用户设置了进度条的border或背景色 时告之本实现类不使用BE - * LNF中默认的N9图填充绘制而改用父类中的方法(父类中的方法 就可以支持颜色的设置罗,只是丑点,但总归是能适应用户的需求场景要求,其实用户完全可以 - * 通过JComboBox.setUI(..)方式来自定义UI哦). - * - * @return true, if is use parent paint - */ - @Override - public boolean isUseParentPaint() { - return comboBox != null - && (!(comboBox.getBorder() instanceof UIResource) - || !(comboBox.getBackground() instanceof UIResource)); - } - - @Override - public void installUI(JComponent c) { - super.installUI(c); - - //2012-08-30*******************************************************【重要说明】 START 对应BEListUI中的【重要说明】 - //* 【重要说明】因BEListUI中为了使列表行单元高变的更高(在MyDefaultListCellRenderer.java中 - //* 像COmboxRender一样通过增到border不起效果,它可能是BasicListUI的设计缺陷,它要么取FixedCellHeight - //* 固定值,要么取getPreferSize()即自动计算高度——它似乎是不计入border的,所以render设置border不起效) - //* 所以只能为列表单元设置因定值:list.setFixedCellHeight(30),但它将影响Combox里的行高(也会变成30高) - //* 所以此处要把列表UI中强制设定的30高针对Combox还原成自动计算(API中规定FixedCellHeight==-1即表示自动计算) - popup.getList().setFixedCellHeight(-1); - //**************************************************************** 【重要说明】 END - - //* 以下代码由jb2011加入 -// comboBox.setMaximumRowCount(8);//这个最大行可以起效,但似乎它的行高指的是一个固定值而不是计算值,像本LNF里因cell本身行高就很高 - //即使设置了最大显示行,但是显示的并不是指定值,有待进一步研究 - //为下拉框的弹出弹加border,这样上下空白外一点好看一些 - // install the scrollpane border - Container parent = popup.getList().getParent(); // should be viewport - if (parent != null) { - parent = parent.getParent(); // should be the scrollpane - if (parent != null && parent instanceof JScrollPane) - LookAndFeel.installBorder((JScrollPane) parent, "ComboBox.scrollPaneBorder");//*~ 注:这个属性是Jack Jiang仿照JTabel里的实现自已加的属性 - } - } - - @Override - protected void installListeners() { - super.installListeners(); - comboBox.addMouseListener(this); - } - - @Override - protected void uninstallListeners() { - super.uninstallListeners(); - comboBox.removeMouseListener(this); - } - - /** - * Gets the combox. - * - * @return the combox - */ - public JComboBox getCombox() { - return this.comboBox; - } - - /** - * {@inheritDoc} - * - * 自定义下接框箭头按钮实现类 - */ - @Override - protected JButton createArrowButton() { - JButton button = new JButton() { - @Override - protected void paintComponent(Graphics g) { - if (comboBox.isEditable()) - ICON_9.getWithComboState("", comboBox.isEnabled(), mouseDown, mouseInside) - .draw((Graphics2D) g, 0, 0, getWidth(), getHeight()); - } - }; - button.addMouseListener(this); - button.setMinimumSize(BTN_SIZE); - button.setPreferredSize(BTN_SIZE); - button.setMargin(new Insets(0, 0, 0, 0)); - return button; - } - - @Override - public void paint(Graphics g, JComponent c) { - hasFocus = comboBox.hasFocus(); - ListCellRenderer renderer = comboBox.getRenderer(); - Rectangle r = new Rectangle(0, 0, comboBox.getWidth(), comboBox.getHeight()); - paintCurrentValueBackground(g, r, hasFocus); - if (!comboBox.isEditable()) - paintCurrentValue(g, rectangleForCurrentValue(), false); - } - - /** - * Paints the background of the currently selected item. - * - * @param g the g - * @param bounds the bounds - * @param hasFocus the has focus - * @see javax.swing.plaf.basic.BasicComboBoxUI#paintCurrentValueBackground(java.awt.Graphics, java.awt.Rectangle, boolean) - */ - @Override - public void paintCurrentValueBackground(Graphics g, Rectangle bounds, boolean hasFocus) { - AnimationController.paintSkin(comboBox, this, g, bounds.x, bounds.y, bounds.width, bounds.height, getXPComboBoxState(comboBox)); - } - - @Override - public TMSchema.Part getPart(JComponent c) { - return TMSchema.Part.CP_COMBOBOX; - } - - State getXPComboBoxState(JComponent c) { - State state = State.NORMAL; - if (!c.isEnabled()) { - state = State.DISABLED; - } else if (isPopupVisible(comboBox)) { - state = State.PRESSED; - } else if (mouseInside) { - state = State.ROLLOVER; - } - return state; - } - - @Override - public void paintSkinRaw(Graphics g, int x, int y, int w, int h, TMSchema.State state) { - String key; - switch (state) { - case PRESSED: - key = "pressed"; - break; - case DISABLED: - key = "disabled"; - break; - case ROLLOVER: - key = "rollover"; - break; - case NORMAL: - key = "normal"; - break; - default: - return; - } - ICON_9.get(key).draw((Graphics2D) g, x, y, w, h); - } - - - - //* copy from BasicComboBoxUI and modified by jb2011 - /** - * Creates the default renderer that will be used in a non-editiable combo - * box. A default renderer will used only if a renderer has not been - * explicitly set with setRenderer. - * - * @return a ListCellRender used for the combo box - * @see javax.swing.JComboBox#setRenderer - */ - @Override - protected ListCellRenderer createRenderer() { - return new BEComboBoxRenderer.UIResource(this); - } - - /** - * {@inheritDoc} - * - * 改变方法可见性 - */ - @Override - public Insets getInsets() { - return super.getInsets(); - } - - /** - * Creates the popup portion of the combo box. - * - * 目的是修正弹出popup窗口的x、y坐标,不像菜单UI里有 - * Menu.menuPopupOffsetX等4个属性可设置以备对坐标进行调整,BeautyEye LNF中由Jack Jiang - * 依照Menu中的实现自定义了2个属性,以便以后配置。参考自jdk1.6.0_u18源码. - * - * @return an instance of ComboPopup - * @see javax.swing.plaf.basic.BasicComboBoxUI#createPopup() - */ - @Override - protected ComboPopup createPopup() { - return new BasicComboPopup(comboBox) { - /** - * popupOffsetX是jb2011自定的属性,用于修正下拉框的弹出窗的X坐标 - */ - private final int popupOffsetX = UIManager.getInt("ComboBox.popupOffsetX"); - /** - * popupOffsetY是jb2011自定的属性,用于修正下拉框的弹出窗的Y坐标 - */ - private final int popupOffsetY = UIManager.getInt("ComboBox.popupOffsetY"); - - @Override - public void show() { - setListSelection(comboBox.getSelectedIndex()); - Point location = getPopupLocation(); - show(comboBox, //以下x、y坐标修正代码由Jack Jiang增加 - location.x + popupOffsetX, //*~ popupOffsetX是自定属性,用于修改弹出窗的X坐标 - location.y + popupOffsetY //*~ popupOffsetY是自定属性,用于修改弹出窗的Y坐标 - ); - } - - /** - * Sets the list selection index to the selectedIndex. This method - * is used to synchronize the list selection with the combo box - * selection. - * - * @param selectedIndex the index to set the list - * @see javax.swing.plaf.basic.BasicComboPopup#setListSelection(int) - */ - private void setListSelection(int selectedIndex) { - if (selectedIndex == -1) - list.clearSelection(); - else { - list.setSelectedIndex(selectedIndex); - list.ensureIndexIsVisible(selectedIndex); - } - } - - /** - * Calculates the upper left location of the Popup. - * - * @see javax.swing.plaf.basic.BasicComboPopup#getPopupLocation() - */ - private Point getPopupLocation() { - Dimension popupSize = comboBox.getSize(); - Insets insets = getInsets(); - - // reduce the width of the scrollpane by the insets so that the popup - // is the same width as the combo box. - popupSize.setSize(popupSize.width - (insets.right + insets.left), - getPopupHeightForRowCount(comboBox.getMaximumRowCount())); - Rectangle popupBounds = computePopupBounds(0, comboBox.getBounds().height, - popupSize.width, popupSize.height); - Dimension scrollSize = popupBounds.getSize(); - Point popupLocation = popupBounds.getLocation(); - - scroller.setMaximumSize(scrollSize); - scroller.setPreferredSize(scrollSize); - scroller.setMinimumSize(scrollSize); - - list.revalidate(); - - return popupLocation; - } - }; - } - - /** - * Creates the default editor that will be used in editable combo boxes. A - * default editor will be used only if an editor has not been explicitly set - * with setEditor. - * - * 重写父类方法的目的是使得默认的 - * Editor透明(即不填充默认背景),因为BE LNF中JTextField的LNF是用NP图 - * 实现的,此处不透明的话就会遮住NP背景图,从而使得外观难看。 - * - * Fixed Issue 49(https://code.google.com/p/beautyeye/issues/detail?id=49) - * - * @return a ComboBoxEditor used for the combo box - * @see javax.swing.JComboBox#setEditor - * @see com.sun.java.swing.plaf.windows.WindowsComboBoxUI.WindowsComboBoxEditor - */ - @Override - protected ComboBoxEditor createEditor() { - BasicComboBoxEditor.UIResource bcbe = new BasicComboBoxEditor.UIResource(); - Component c = bcbe.getEditorComponent(); - if (c != null) { - //把默认的Editor设置成透明(editor不透明的话就会遮住NP背景图,从而使得外观难看) - ((JComponent) c).setOpaque(false); - - //* 以下这段是为了给默认Editor加上border而加(没有它个border将使 - //* 得与不可编辑comboBox的内容组件看起来有差异哦), - //* 在WindowsComboBoxUI中,这段代码是放在WindowsComboBoxEditor - //* 中的方法createEditorComponent中实现,由于该 方法是1.6里才有的, - //* BE LNF因要兼容java1.5,所以不作类似实现就在本方法中实现也没有问题。 - //* 类似实现请参考WindowsComboBoxUI.WindowsComboBoxEditor类 -// JTextField editor = (JTextField)c; - Border border = (Border) UIManager.get("ComboBox.editorBorder"); - if (border != null) - ((JComponent) c).setBorder(border); - } - return bcbe; - } - - // ================================================================================================================= - // MouseListener Methods - private boolean mouseInside = false; - private boolean mouseDown = false; - - @Override - public void mouseClicked(MouseEvent e) { - } - - @Override - public void mouseEntered(MouseEvent e) { - if (comboBox.isEditable()) { - if (e.getComponent() == arrowButton) - mouseInside = true; - } else { - mouseInside = true; - comboBox.repaint(); - } - } - - @Override - public void mouseExited(MouseEvent e) { - if (comboBox.isEditable()) { - if (e.getComponent() == arrowButton) - mouseInside = false; - } else { - mouseInside = false; - comboBox.repaint(); - } - } - - @Override - public void mousePressed(MouseEvent e) { - if (comboBox.isEditable()) { - if (e.getComponent() == arrowButton) - mouseDown = true; - } else { - mouseDown = true; - comboBox.repaint(); - } - } - - @Override - public void mouseReleased(MouseEvent e) { - if (comboBox.isEditable()) { - if (e.getComponent() == arrowButton) - mouseDown = false; - } else { - mouseDown = false; - comboBox.repaint(); - } - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/combox/__UI__.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/combox/__UI__.java deleted file mode 100644 index 715025107..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/combox/__UI__.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * __UI__.java at 2015-2-1 20:25:37, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.combox; - -import java.awt.Color; - -import javax.swing.UIManager; - -import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper; -import org.jackhuang.hmcl.laf.utils.UI; - -public class __UI__ extends UI { - - public static void uiImpl() { - /* ~~注:这个属性是Jack Jiang仿照JTabel里的实现自已加的属性,目的是控制选择框的弹出列表的边框空白 */ - putBorder("ComboBox.scrollPaneBorder", 0, 0, 0, 0); - - // 不能设置alpha通道小于255的透明颜色,否则会出现无法重paint的问题 - putColor("ComboBox.background", 242, 242, 242); - put("ComboBox.disabledBackground", BeautyEyeLNFHelper.commonBackgroundColor); -// put("ComboBox.buttonBackground", BeautyEyeLNFHelper.commonBackgroundColor); - putColor("ComboBox.buttonBackground", 242, 242, 242); - put("ComboBox.selectionForeground", BeautyEyeLNFHelper.commonSelectionForegroundColor); - put("ComboBox.selectionBackground", BeautyEyeLNFHelper.commonSelectionBackgroundColor); - put("ComboBox.foreground", BeautyEyeLNFHelper.commonForegroundColor); - - //render之外的衬距,此设置将改变下拉框的整体占位大小 - putInsets("ComboBox.padding", 0, 0, 0, 0);//5,8,5,8)); - //true表示下拉箭头按钮的宽度无条件=高度,否则宽度不与高度保持等长(使用自身长度) - UIManager.put("ComboBox.squareButton", true); - - //此border将决定ArrowButton的外衬大小(即框内衬空白大小),此大小决定conbox的高度和宽度,另一种方法 - //是通过设置render的border也能达到调整combox的高度和宽度,而且对lnf来说通过设置render的border是最佳方案 - putBorder("ComboBox.border", 0, 4, 0, 0);//new BERoundBorder(0).setThickness(10)));//.setArcWidth(10).setLineColor(new Color(0,0,0,0))));//使用全透明色绘边框,目的就是要让它的背景显现出来(NipePatch图实现) - putBorder("ComboBox.editorBorder", 0, 4, 0, 0);//windows 外观下认是1,2,1,1))); - - put("ComboBoxUI", BEComboBoxUI.class); - /* ~~注:这个属性是Jack Jiang为了更好的ui效果和方便未来的设定自已加的属性 */ - //用于修正下拉框的弹出窗的X坐标 - put("ComboBox.popupOffsetX", 0); - /* ~~注:这个属性是Jack Jiang为了更好的ui效果和方便未来的设定自已加的属性 */ - //用于修正下拉框的弹出窗的Y坐标 - put("ComboBox.popupOffsetY", 0); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/filechooser/BEFileChooserUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/filechooser/BEFileChooserUI.java deleted file mode 100644 index 534a87d6b..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/filechooser/BEFileChooserUI.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BEFileChooserUI.java at 2015-2-1 20:25:39, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.filechooser; - -import java.awt.Component; -import java.awt.Graphics; - -import javax.swing.JComponent; -import javax.swing.JFileChooser; -import javax.swing.JList; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JViewport; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.metal.MetalFileChooserUI; - -/** - * BeautyEye L&F implementation of a FileChooser. - *

    - * 目前属通用跨平台专用UI实现类. - * - * @author Jack Jiang(jb2011@163.com), 2012-09-17 - * @version 1.0 - */ -public class BEFileChooserUI extends MetalFileChooserUI { - - public BEFileChooserUI(JFileChooser filechooser) { - super(filechooser); - } - - // - // ComponentUI Interface Implementation methods - // - - public static ComponentUI createUI(JComponent c) { - return new BEFileChooserUI((JFileChooser) c); - } - - /** - * {@inheritDoc} - * - * 注:目前仅发现Windows平台的WindowsFileChooserUI存在它个问题 ! 本方法由Jack - * Jiang实现,没有以下默认背景绘制则在BE LNF中因透明窗口而使得 - * 文件选择框内容面板的空白处出现全透明现的丑陋现象,注释掉本方法即可见之前的问题 - */ - @Override - public void paint(Graphics g, JComponent c) { - g.setColor(c.getBackground()); - g.fillRect(0, 0, c.getWidth(), c.getHeight()); - } - - /** - * 重写父类方法,以实现对文件查看列表的额外设置. - *

    - * 为什么要重写此方法,没有更好的方法吗?
    - * 答:因父类的封装结构不佳,filePane是private私有,子类中无法直接引用, - * 要想对filePane中的文列表额外设置,目前重写本方法是个没有办法的方法. - *

    - * sun.swing.FilePane源码可查看地址:Click - * here. - * - * @param fc the fc - * @return the j panel - */ - @Override - protected JPanel createList(JFileChooser fc) { - JPanel p = super.createList(fc); - - //* 以下代码的作用就是将文件列表JList对象引用给找回来(通过从它的父面板中层层向下搜索) - //* ,因无法从父类中直接获得列表对象的直接引用,只能用此笨办法了 - if (p.getComponentCount() > 0) { - Component scollPane = p.getComponent(0); - if (scollPane != null && scollPane instanceof JScrollPane) { - JViewport vp = ((JScrollPane) scollPane).getViewport(); - if (vp != null) { - Component fileListView = vp.getView(); - //终于找到了文件列表的实例引用 - if (fileListView != null && fileListView instanceof JList) - //把列表的行高改成-1(即自动计算列表每个单元的行高而不指定固定值) - //* 说明:在BeautyEye LNF中,为了便JList的UI更好看,在没有其它方法有前 - //* 提下就在JList的BEListUI中给它设置了默写行高32,而JFildChooser中的 - //* 文件列表将会因此而使得单元行高很大——从而导致文件列表很难看,此处就是恢复 - //* 文件列表单元行高的自动计算,而非指定固定行高。 - //* - //* 说明2:为什么不能利用list.getClientProperty("List.isFileList")从而在JList - //* 的ui中进行判断并区别对待是否是文件列表呢? - //* 答:因为"List.isFileList"是在BasicFileChooserUI中设置的,也就是说当为个属性被 - //* 设置的时候JFileChooser中的文件列表已经实例化完成(包括它的ui初始化),所以此时 - //* 如果在JList的ui中想区分是不可能的,因它还没有被调置,这个设置主要是供BasicListUI - //* 在被实例化完成后,来异步处理这个属性的(通过监听属性改变事件来实现的) - ((JList) fileListView).setFixedCellHeight(-1); - } - } - } - - return p; - } - -// // -// // Renderer for Types ComboBox -// // -// protected FilterComboBoxRenderer createFilterComboBoxRenderer() -// { -// return new BEFilterComboBoxRenderer(); -// } -// /** -// * Render different type sizes and styles. -// */ -// protected class BEFilterComboBoxRenderer extends FilterComboBoxRenderer -// { -// public BEFilterComboBoxRenderer() -// { -// super(); -// -//// //设置成透明背景则意味着不需要背景填充,但本类中的应用场景有点特殊 -//// //——默认的render的UI里不需要绘制背景的情况下本类才可进行NinePatch图作为背景进行填充 -//// setOpaque(false); -// //TODO 此border(render的内衬)可以作为一个UIManager的属性哦,方便以后设置 -// //注:此内衬是决定列表单元间的上下左右空白的关键哦! -//// setBorder(BorderFactory.createEmptyBorder(5, 8, 5, 8)); -// } -// -// //按理说本方法中的是否选中背景填充实现逻辑在Render的UI中实现最为合理,但由于 -// //本类就是处理于UI实现中,所以容易产生冲突,故而不适宜自定义Ui实现,干脆硬编码则更直接 -// public void paintComponent(Graphics g) -// { -// //** 本HACK是为了解决 Issue 30:因JFileChooser中的文件类型选择下拉框的render -// //** (即本render)是自定义的(不是使用的ComboxUI里由BE LNF定义好的render而 -// //** 导致的视觉效果不佳的问题 -// //##### HACK:强行把绘制坐标右移、下移——以便使得与左边的空折多一点,要不然就太难看了 -// g.translate(5, 1); -// -// //照常绘制(只是之前的坐标被移了一下而已) -// super.paintComponent(g); -// -// //##### HACK:恢复坐标 -// g.translate(-5, -1); -// } -// } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/filechooser/__UI__.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/filechooser/__UI__.java deleted file mode 100644 index 689c4dae3..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/filechooser/__UI__.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * __UI__.java at 2015-2-1 20:25:38, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.filechooser; - -import java.awt.Color; - -import javax.swing.UIManager; -import javax.swing.plaf.BorderUIResource; -import javax.swing.plaf.ColorUIResource; -import org.jackhuang.hmcl.laf.utils.IconFactory; -import org.jackhuang.hmcl.laf.utils.UI; - -/** - * The Class __UI__. - */ -public class __UI__ extends UI { - - private static final IconFactory ICON = new IconFactory("tree"); - - public static void uiImpl() { - //文件查看列表的边框实现 - put("FileChooser.listViewBorder", new org.jackhuang.hmcl.laf.scroll.ScrollPaneBorder()); - //此颜色将决定windows平台下文件选择面板的左边WindowsPlaceBar的背景色 - putColor("ToolBar.shadow", 249, 248, 243); - put("FileChooserUI", BEFileChooserUI.class); - - UIManager.put("FileView.directoryIcon", ICON.get("closed")); - UIManager.put("FileView.fileIcon", ICON.get("leaf")); - - /* - "FileView.directoryIcon", new SwingLazyValue("javax.swing.plaf.metal.MetalIconFactory", "getTreeFolderIcon"), - "FileView.fileIcon", new SwingLazyValue("javax.swing.plaf.metal.MetalIconFactory", "getTreeLeafIcon"), - "FileView.computerIcon", new SwingLazyValue("javax.swing.plaf.metal.MetalIconFactory", "getTreeComputerIcon"), - "FileView.hardDriveIcon", new SwingLazyValue("javax.swing.plaf.metal.MetalIconFactory", "getTreeHardDriveIcon"), - "FileView.floppyDriveIcon", new SwingLazyValue("javax.swing.plaf.metal.MetalIconFactory", "getTreeFloppyDriveIcon"), - - // File Chooser - "FileChooser.detailsViewIcon", new SwingLazyValue("javax.swing.plaf.metal.MetalIconFactory", "getFileChooserDetailViewIcon"), - "FileChooser.homeFolderIcon", new SwingLazyValue("javax.swing.plaf.metal.MetalIconFactory", "getFileChooserHomeFolderIcon"), - "FileChooser.listViewIcon", new SwingLazyValue("javax.swing.plaf.metal.MetalIconFactory", "getFileChooserListViewIcon"), - "FileChooser.newFolderIcon", new SwingLazyValue("javax.swing.plaf.metal.MetalIconFactory", "getFileChooserNewFolderIcon"), - "FileChooser.upFolderIcon", new SwingLazyValue("javax.swing.plaf.metal.MetalIconFactory", "getFileChooserUpFolderIcon"), - */ - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/internalframe/BEDesktopIconUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/internalframe/BEDesktopIconUI.java deleted file mode 100644 index 13d581d75..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/internalframe/BEDesktopIconUI.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BEDesktopIconUI.java at 2015-2-1 20:25:36, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.internalframe; - -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Insets; - -import javax.swing.JComponent; -import javax.swing.UIManager; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicDesktopIconUI; - -/** - * 内部窗体最小化时的图标ui实现类. - * - * @author Jack Jiang(jb2011@163.com) - * @see com.sun.java.swing.plaf.windows.WindowsDesktopIconUI - */ -public class BEDesktopIconUI extends BasicDesktopIconUI { - - private int width; - - public static ComponentUI createUI(JComponent c) { - return new BEDesktopIconUI(); - } - - /** - * {@inheritDoc} - * - * @see com.sun.java.swing.plaf.windows.WindowsDesktopIconUI#installDefaults - */ - @Override - public void installDefaults() { - super.installDefaults(); - width = UIManager.getInt("DesktopIcon.width"); - } - - @Override - public void installUI(JComponent c) { - super.installUI(c); - c.setOpaque(false); - } - - /** - * {@inheritDoc} - * - * @see com.sun.java.swing.plaf.windows.WindowsDesktopIconUI#uninstallUI - */ - @Override - public void uninstallUI(JComponent c) { - BEInternalFrameTitlePane thePane = (BEInternalFrameTitlePane) iconPane; - super.uninstallUI(c); - thePane.uninstallListeners(); - } - - @Override - protected void installComponents() { - iconPane = new BEInternalFrameTitlePane(frame) { - @Override - protected void paintTitlePaneImpl(Insets frameInsets, Graphics g, - int width, int height, boolean isSelected) { - //** Swing BUG补尝:重写父类的目的就是想用Insets(0,0,0,0)来调用paintTitlePaneImpl(否则因 - //** BasicInternalFrameTitlePane中的布局bug,将会导致填充错位) - Insets instes = new Insets(0, 0, 0, 0); - super.paintTitlePaneImpl(instes, g, width, height, isSelected); - } - }; - desktopIcon.setLayout(new BorderLayout()); - desktopIcon.add(iconPane, BorderLayout.CENTER); - desktopIcon.setBorder(UIManager.getBorder("InternalFrame.border")); - } - - /** - * {@inheritDoc} - * - * @see - * com.sun.java.swing.plaf.windows.WindowsDesktopIconUI#getPreferredSize(javax.swing.JComponent) - */ - @Override - public Dimension getPreferredSize(JComponent c) { - // Windows desktop icons can not be resized. Therefore, we should - // always return the minimum size of the desktop icon. See - // getMinimumSize(JComponent c). - return getMinimumSize(c); - } - - /** - * Windows desktop icons are restricted to a width of 160 pixels by default. - * This value is retrieved by the DesktopIcon.width property. - * - * @param c the c - * @return the minimum size - * @see - * com.sun.java.swing.plaf.windows.WindowsDesktopIconUI#getPreferredSize(javax.swing.JComponent) - */ - @Override - public Dimension getMinimumSize(JComponent c) { - //## Bug FIX:see Issue 60(https://code.google.com/p/beautyeye/issues/detail?id=60&can=1) - //## bug起源:此bug源自WindowsDesktopIconUI,BeautyEye因参考了它的实现因而也把该bug带了过来。 - //## 是否解决:已于2012-10-19日由Jack Jiang解决。 - //## bug描述:在某些情况下(比如在cpcns的定制be lnf项目中,它的内部窗口先最大化后再最小化时,该DesptopIcon - //## 的高度就变的较小(与正常状态下有差异),具体原因待深究。 - //## 解决方法:参考MetalDesktopIconUI里的实现,用现在的代码即可解决这个问题。 -// Dimension dim = super.getMinimumSize(c); -// dim.width = width; -// return dim; - return new Dimension(width, - desktopIcon.getLayout().minimumLayoutSize(desktopIcon).height); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/internalframe/BEInternalFrameTitlePane.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/internalframe/BEInternalFrameTitlePane.java deleted file mode 100644 index 05870a6d4..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/internalframe/BEInternalFrameTitlePane.java +++ /dev/null @@ -1,631 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BEInternalFrameTitlePane.java at 2015-2-1 20:25:36, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.internalframe; - -import java.awt.Color; -import java.awt.Component; -import java.awt.Container; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Graphics; -import java.awt.Insets; -import java.awt.LayoutManager; -import java.awt.Rectangle; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; - -import javax.swing.Icon; -import javax.swing.JInternalFrame; -import javax.swing.JMenu; -import javax.swing.JOptionPane; -import javax.swing.UIManager; -import javax.swing.border.Border; -import javax.swing.border.EmptyBorder; -import javax.swing.plaf.basic.BasicInternalFrameTitlePane; -import javax.swing.plaf.metal.MetalLookAndFeel; - -import org.jackhuang.hmcl.laf.titlepane.BETitlePane; -import org.jackhuang.hmcl.laf.utils.MySwingUtilities2; -import org.jackhuang.hmcl.laf.utils.WinUtils; - -/** - * 内部窗体的标题栏UI实现. - * - * BeautyEye外观实现中取消了isPalette的所有特殊处理,isPalette及相关属性在 - *该外观中将失去意义,请注意! - *虽然beautyEye是参考自MetalLookAndFeel,但因beautyEye使用了Insets很大的立体边框, - * 则如果还要像MetalLookAndFeel实现Palette类型的JInternalFrame则效果会很难看,干脆就就像 - * WindowsLookAndFeel一样,不去理会什么Palette,在当前的L&F下没有任何减分。 - * - * @see com.sun.java.swing.plaf.windows.WindowsInternalFrameTitlePane - * @author Jack Jiang - */ -public class BEInternalFrameTitlePane extends BasicInternalFrameTitlePane { -// protected boolean isPalette = false; -// protected Icon paletteCloseIcon; -// protected int paletteTitleHeight; - - /** - * The Constant handyEmptyBorder. - */ - private static final Border handyEmptyBorder = new EmptyBorder(0, 0, 0, 0); - - /** - * Key used to lookup Color from UIManager. If this is null, - * getWindowTitleBackground is used. - */ - private String selectedBackgroundKey; - /** - * Key used to lookup Color from UIManager. If this is null, - * getWindowTitleForeground is used. - */ - private String selectedForegroundKey; - /** - * Key used to lookup shadow color from UIManager. If this is null, - * getPrimaryControlDarkShadow is used. - */ - private String selectedShadowKey; - /** - * Boolean indicating the state of the JInternalFrames closable - * property at updateUI time. - */ - private boolean wasClosable; - - /** - * The buttons width. - */ - int buttonsWidth = 0; - - /** - * Instantiates a new bE internal frame title pane. - * - * @param f the f - */ - public BEInternalFrameTitlePane(JInternalFrame f) { - super(f); - } - - @Override - public void addNotify() { - super.addNotify(); - // This is done here instead of in installDefaults as I was worried - // that the BasicInternalFrameUI might not be fully initialized, and - // that if this resets the closable state the BasicInternalFrameUI - // Listeners that get notified might be in an odd/uninitialized state. - updateOptionPaneState(); - } - - @Override - protected void installDefaults() { - super.installDefaults(); - setFont(UIManager.getFont("InternalFrame.titleFont")); -// paletteTitleHeight = UIManager -// .getInt("InternalFrame.paletteTitleHeight"); -// paletteCloseIcon = UIManager.getIcon("InternalFrame.paletteCloseIcon"); - wasClosable = frame.isClosable(); - selectedForegroundKey = selectedBackgroundKey = null; - if (true) - setOpaque(false); - } - - @Override - protected void uninstallDefaults() { - super.uninstallDefaults(); - if (wasClosable != frame.isClosable()) - frame.setClosable(wasClosable); - } - - @Override - protected void createButtons() { - super.createButtons(); - - Boolean paintActive = frame.isSelected() ? Boolean.TRUE : Boolean.FALSE; - iconButton.putClientProperty("paintActive", paintActive); - iconButton.setBorder(handyEmptyBorder); - - maxButton.putClientProperty("paintActive", paintActive); - maxButton.setBorder(handyEmptyBorder); - - closeButton.putClientProperty("paintActive", paintActive); - closeButton.setBorder(handyEmptyBorder); - - // The palette close icon isn't opaque while the regular close icon is. - // This makes sure palette close buttons have the right background. - closeButton.setBackground(MetalLookAndFeel.getPrimaryControlShadow()); - - if (true) { - iconButton.setContentAreaFilled(false); - maxButton.setContentAreaFilled(false); - closeButton.setContentAreaFilled(false); - } - } - - /** - * Override the parent's method to do nothing. Metal frames do not have - * system menus. - */ - @Override - protected void assembleSystemMenu() { - } - - /** - * Override the parent's method to do nothing. Metal frames do not have - * system menus. - * - * @param systemMenu the system menu - */ - @Override - protected void addSystemMenuItems(JMenu systemMenu) { - } - - /** - * Override the parent's method to do nothing. Metal frames do not have - * system menus. - */ - @Override - protected void showSystemMenu() { - } - - /** - * Override the parent's method avoid creating a menu bar. Metal frames do - * not have system menus. - */ - @Override - protected void addSubComponents() { - add(iconButton); - add(maxButton); - add(closeButton); - } - - @Override - protected PropertyChangeListener createPropertyChangeListener() { - return new MetalPropertyChangeHandler(); - } - - @Override - protected LayoutManager createLayout() { - return new XMetalTitlePaneLayout(); - } - - class MetalPropertyChangeHandler extends - BasicInternalFrameTitlePane.PropertyChangeHandler { - - @Override - public void propertyChange(PropertyChangeEvent evt) { - String prop = (String) evt.getPropertyName(); - if (prop.equals(JInternalFrame.IS_SELECTED_PROPERTY)) { - Boolean b = (Boolean) evt.getNewValue(); - iconButton.putClientProperty("paintActive", b); - closeButton.putClientProperty("paintActive", b); - maxButton.putClientProperty("paintActive", b); - } else if ("JInternalFrame.messageType".equals(prop)) { - updateOptionPaneState(); - frame.repaint(); - } - super.propertyChange(evt); - } - } - - class XMetalTitlePaneLayout extends TitlePaneLayout { - - @Override - public void addLayoutComponent(String name, Component c) { - } - - @Override - public void removeLayoutComponent(Component c) { - } - - @Override - public Dimension preferredLayoutSize(Container c) { - return minimumLayoutSize(c); - } - - @Override - public Dimension minimumLayoutSize(Container c) { - // Compute width. - int width = 30; - if (frame.isClosable()) - width += 21; - if (frame.isMaximizable()) - width += 16 + (frame.isClosable() ? 10 : 4); - if (frame.isIconifiable()) - width += 16 + (frame.isMaximizable() ? 2 - : (frame.isClosable() ? 10 : 4)); - FontMetrics fm = frame.getFontMetrics(getFont()); - String frameTitle = frame.getTitle(); - int title_w = frameTitle != null ? MySwingUtilities2.stringWidth( - frame, fm, frameTitle) : 0; - int title_length = frameTitle != null ? frameTitle.length() : 0; - - if (title_length > 2) { - int subtitle_w = MySwingUtilities2.stringWidth(frame, fm, frame - .getTitle().substring(0, 2) - + "..."); - width += (title_w < subtitle_w) ? title_w : subtitle_w; - } else - width += title_w; - - // Compute height. - int height = 0; - -// if (isPalette) -// { -// height = paletteTitleHeight; -// } -// else - { - int fontHeight = fm.getHeight(); - fontHeight += 4;//默认是 +=7 - Icon icon = frame.getFrameIcon(); - int iconHeight = 0; - if (icon != null) - // SystemMenuBar forces the icon to be 16x16 or less. - iconHeight = Math.min(icon.getIconHeight(), 16); - iconHeight += 5; - height = Math.max(fontHeight, iconHeight) + 5;//默认是 +0,modified by jb2011 2012-06-18 - } - - return new Dimension(width, height); - } - - @Override - public void layoutContainer(Container c) { - boolean leftToRight = WinUtils.isLeftToRight(frame); - - int w = getWidth(); - int x = leftToRight ? w : 0; - int y = 5;//默认是0,modified by jb2011 - int spacing; - - // assumes all buttons have the same dimensions - // these dimensions include the borders - int buttonHeight = closeButton.getIcon().getIconHeight(); - int buttonWidth = closeButton.getIcon().getIconWidth(); - - if (frame.isClosable()) // if (isPalette) - // { - // spacing = 3; - // x += leftToRight ? -spacing - (buttonWidth + 2) : spacing; - // closeButton.setBounds(x, y, buttonWidth + 2, - // getHeight() - 4); - // if (!leftToRight) - // x += (buttonWidth + 2); - // } - // else - { - spacing = 4; - x += leftToRight ? -spacing - buttonWidth : spacing; - closeButton.setBounds(x, y, buttonWidth, buttonHeight); - if (!leftToRight) - x += buttonWidth; - } - - if (frame.isMaximizable())// && !isPalette) - { - spacing = frame.isClosable() ? 2 : 4; //10 : 40 - x += leftToRight ? -spacing - buttonWidth : spacing; - maxButton.setBounds(x, y, buttonWidth, buttonHeight); - if (!leftToRight) - x += buttonWidth; - } - - if (frame.isIconifiable())// && !isPalette) - { - spacing = frame.isMaximizable() ? 2 : (frame.isClosable() ? 10 - : 4); - x += leftToRight ? -spacing - buttonWidth : spacing; - iconButton.setBounds(x, y, buttonWidth, buttonHeight); - if (!leftToRight) - x += buttonWidth; - } - - buttonsWidth = leftToRight ? w - x : x; - } - } - -// public void paintPalette(Graphics g) -// { -// boolean leftToRight = WinUtils.isLeftToRight(frame); -// -// int width = getWidth(); -// int height = getHeight(); -// -// Color background = MetalLookAndFeel.getPrimaryControlShadow(); -// Color darkShadow = MetalLookAndFeel.getPrimaryControlDarkShadow(); -// -// NLTitlePane.paintTitlePane(g, 0, 0, width , height, false -// , background, darkShadow); -// } - - @Override - public void paintComponent(Graphics g) { -// if (isPalette) -// { -// paintPalette(g); -// return; -// } - - boolean leftToRight = WinUtils.isLeftToRight(frame); - boolean isSelected = frame.isSelected();//! 选中与否的判断方式,参见border部分的注释 - - int width = getWidth(); - int height = getHeight(); - - Color background = null; - Color foreground = null; - Color shadow = null; - - if (isSelected) { -// if (!true) -// { -// closeButton.setContentAreaFilled(true); -// maxButton.setContentAreaFilled(true); -// iconButton.setContentAreaFilled(true); -// } - if (selectedBackgroundKey != null) - background = UIManager.getColor(selectedBackgroundKey); - if (background == null) - background = UIManager.getColor("activeCaption"); - if (selectedForegroundKey != null) - foreground = UIManager.getColor(selectedForegroundKey); - if (selectedShadowKey != null) - shadow = UIManager.getColor(selectedShadowKey); - if (shadow == null) - shadow = UIManager.getColor("activeCaptionBorder"); - if (foreground == null) - foreground = UIManager.getColor("activeCaptionText"); - } else { - if (!true) { - closeButton.setContentAreaFilled(false); - maxButton.setContentAreaFilled(false); - iconButton.setContentAreaFilled(false); - } - background = UIManager.getColor("inactiveCaption"); - foreground = UIManager.getColor("inactiveCaptionText"); - shadow = UIManager.getColor("inactiveCaptionBorder"); - } - - //---------------------------------------------------绘制标题栏背景 -// Color topDarkShadow2 = LNFUtils.getColor( -// background, -40, -40, -40) -// ,topHightLight2 = LNFUtils.getColor(background, -// 60, 60, 60) -// ,topDarkHightLight2 = LNFUtils.getColor(background, -// 20, 20, 20); - /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 绘制标题栏背景START */ - /* - * ** bug修正 by js,2009-09-30(这因是JDK1.5的Swing底层BUG) - * - * BUG描述:当操作系统的主题切换时,JInternalFrame有时相同的方法this.getBounds()获得的结果是不一样的 - * ,这种差异主要在于有时this.getBounds()获得的结果并未包括它的border,主要表现就是结果 - * 的(x,y)的坐标是未包含border的坐标,因而这种情况下它的(x=0,y=0),而正确应该 - * (x=border.insets.left,y=border.insets.top),如果无视此bug,则titlePane - * 在填充时会变的丑陋。 - * - * 解决方法:当确知这个bug发生后,只能以人工方式弥补这种异相,如 强制修正其(x,y)的坐标,并相应地调整 - * titlePane的填充区域。 - */ -// Border b=frame.getBorder(); -// Insets is=b.getBorderInsets(frame); -// Rectangle bounds = this.getBounds(); -// int paintTitlePaneX = bounds.x,paintTitlePaneY = bounds.y; -//// boolean isBUG = false; -////// System.out.println("JInternalFrame的UI是否处于正常isBUG="+isBUG); -//// if(isBUG=(is.left!=bounds.x))//当is.left!=bounds.x即可认定已经产生了BUG -//// paintTitlePaneX = is.left; -//// if(isBUG=(is.top!=bounds.y))//当is.left!=bounds.x同样可认定已经产生了BUG -//// paintTitlePaneY = is.top; -//// if(isBUG)//有BUG时的填充 -//// { -//// //----------------------------- 以下代码是为了弥补因BUG而产生的填充异常 -//// //*以下(1),(2),(3)部分代码是用于弥补BUG下的border外观被titlePane覆盖的错误 -//// //*请参见JInternalFrameDialogBorder的边框填充代码(尽量在此处模拟出边框的TOP部分效果)> -//// //水平第一条线(1) -//// g.setColor(topDarkShadow2); -//// g.drawLine(0, 0, width, 0); -//// g.drawLine(0, 1, 0, height);//左坚线 -//// g.drawLine(width, 1, width, height);//右坚线 -//// //水平第二条线(2) -//// g.setColor(topHightLight2); -//// g.drawLine(1, 1, width-NLMetalBorders.InternalFrameDialogBorder.insets.left, 1); -//// //水平第三条线(3) -//// g.setColor(topDarkHightLight2); -//// g.drawLine(2, 2, width-NLMetalBorders.InternalFrameDialogBorder.insets.left, 2); -//// -//// NLTitlePane.paintTitlePane(g//左右空起的部分由Border绘制 -//// , paintTitlePaneX//ZCMetalBorders.InternalFrameDialogBorder.insets.left -//// , paintTitlePaneY//ZCMetalBorders.InternalFrameDialogBorder.insets.left -//// , width-is.left*2 //注意此处也因BUG而作了填充区域的调整 -//// , height, isSelected -//// , background, shadow); -//// //----------------------------- END -//// } -//// //正常无BUG时的填充 -//// else - { - Insets frameInsets = frame.getInsets(); - //** Swing BUG:按理说,此处是不需要传入frameInstes的,因父类BasicInternalFrameTitlePane的布局 - //是存在BUG(布计算时没有把BorderInstes算入到x、y的偏移中,导致UI中paint时只能自行 - //进行增益,否则填充的图璩形肯定就因没有算上borderInstes而错位,详见父类中的 - //BasicInternalFrameTitlePane中内部类Handler的layoutContainer方法里 - //getNorthPane().setBounds(..)这一段 -// NLTitlePane.paintTitlePane(g -// , frameInsets.left//0 -// , frameInsets.top//0 -// , width-frameInsets.left-frameInsets.right//-0 -// , height, isSelected -//// , background, shadow -// ); - paintTitlePaneImpl(frameInsets, g, width, height, isSelected); - } - /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 绘制标题栏背景END */ - - //----------------------------------------------------绘制标题及图标 - int titleLength = 0; - int xOffset = leftToRight ? 5 : width - 5; - String frameTitle = frame.getTitle(); - - Icon icon = frame.getFrameIcon(); - if (icon != null) { - if (!leftToRight) - xOffset -= icon.getIconWidth(); - int iconY = ((height / 2) - (icon.getIconHeight() / 2)); - icon.paintIcon(frame, g, xOffset + 2, iconY + 1);//默认是xOffset +0, iconY+0 - xOffset += leftToRight ? icon.getIconWidth() + 5 : -5; - } - - if (frameTitle != null) { - Font f = getFont(); - g.setFont(f); - FontMetrics fm = MySwingUtilities2.getFontMetrics(frame, g, f); - int fHeight = fm.getHeight(); - - int yOffset = ((height - fm.getHeight()) / 2) + fm.getAscent(); - - Rectangle rect = new Rectangle(0, 0, 0, 0); - if (frame.isIconifiable()) - rect = iconButton.getBounds(); - else if (frame.isMaximizable()) - rect = maxButton.getBounds(); - else if (frame.isClosable()) - rect = closeButton.getBounds(); - int titleW; - - if (leftToRight) { - if (rect.x == 0) - rect.x = frame.getWidth() - frame.getInsets().right - 2; - titleW = rect.x - xOffset - 4; - frameTitle = getTitle(frameTitle, fm, titleW); - } else { - titleW = xOffset - rect.x - rect.width - 4; - frameTitle = getTitle(frameTitle, fm, titleW); - xOffset -= MySwingUtilities2.stringWidth(frame, fm, frameTitle); - } - - titleLength = MySwingUtilities2.stringWidth(frame, fm, frameTitle); - -// g.setColor(Color.DARK_GRAY);// -// NLUtils.drawString(frame, g, frameTitle, xOffset+1, yOffset+1); - g.setColor(foreground); -// if(NLLookAndFeel.windowTitleAntialising) -// NLLookAndFeel.setAntiAliasing((Graphics2D) g,true); - MySwingUtilities2.drawString(frame, g, frameTitle, xOffset, yOffset); -// if(NLLookAndFeel.windowTitleAntialising) -// NLLookAndFeel.setAntiAliasing((Graphics2D) g,false); - xOffset += leftToRight ? titleLength + 5 : -5; - } - } - - /** - * Paint title pane impl. - * - * @param frameInsets the frame insets - * @param g the g - * @param width the width - * @param height the height - * @param isSelected the is selected - */ - protected void paintTitlePaneImpl(Insets frameInsets, Graphics g, - int width, int height, boolean isSelected) { - BETitlePane.paintTitlePane(g, - frameInsets.left//0 - , - frameInsets.top//0 - , - width - frameInsets.left - frameInsets.right//-0 - , - height, isSelected - // , background, shadow - ); - } - -// public void setPalette(boolean b) -// { -// isPalette = b; -// -// if (isPalette) -// { -// closeButton.setIcon(paletteCloseIcon); -// if (frame.isMaximizable()) -// remove(maxButton); -// if (frame.isIconifiable()) -// remove(iconButton); -// } -// else -// { -// closeButton.setIcon(closeIcon); -// if (frame.isMaximizable()) -// add(maxButton); -// if (frame.isIconifiable()) -// add(iconButton); -// } -// revalidate(); -// repaint(); -// } - /** - * Updates any state dependant upon the JInternalFrame being shown in a - * JOptionPane. - */ - private void updateOptionPaneState() { - int type = -2; - boolean closable = wasClosable; - Object obj = frame.getClientProperty("JInternalFrame.messageType"); - - if (obj == null) - // Don't change the closable state unless in an JOptionPane. - return; - if (obj instanceof Integer) - type = ((Integer) obj).intValue(); - switch (type) { - case JOptionPane.ERROR_MESSAGE: - selectedBackgroundKey = "OptionPane.errorDialog.titlePane.background"; - selectedForegroundKey = "OptionPane.errorDialog.titlePane.foreground"; - selectedShadowKey = "OptionPane.errorDialog.titlePane.shadow"; - closable = false; - break; - case JOptionPane.QUESTION_MESSAGE: - selectedBackgroundKey = "OptionPane.questionDialog.titlePane.background"; - selectedForegroundKey = "OptionPane.questionDialog.titlePane.foreground"; - selectedShadowKey = "OptionPane.questionDialog.titlePane.shadow"; - closable = false; - break; - case JOptionPane.WARNING_MESSAGE: - selectedBackgroundKey = "OptionPane.warningDialog.titlePane.background"; - selectedForegroundKey = "OptionPane.warningDialog.titlePane.foreground"; - selectedShadowKey = "OptionPane.warningDialog.titlePane.shadow"; - closable = false; - break; - case JOptionPane.INFORMATION_MESSAGE: - case JOptionPane.PLAIN_MESSAGE: - selectedBackgroundKey = selectedForegroundKey = selectedShadowKey = null; - closable = false; - break; - default: - selectedBackgroundKey = selectedForegroundKey = selectedShadowKey = null; - break; - } - if (closable != frame.isClosable()) - frame.setClosable(closable); - } - - /** - * {@inheritDoc} - * - * 改变父类的方法的可见性为public,方便外界调用,仅此而已. - */ - @Override - public void uninstallListeners() { - super.uninstallListeners(); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/internalframe/BEInternalFrameUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/internalframe/BEInternalFrameUI.java deleted file mode 100644 index e2ae2fdf9..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/internalframe/BEInternalFrameUI.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BEInternalFrameUI.java at 2015-2-1 20:25:37, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.internalframe; - -import java.awt.Container; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; - -import javax.swing.ActionMap; -import javax.swing.JComponent; -import javax.swing.JInternalFrame; -import javax.swing.LookAndFeel; -import javax.swing.SwingUtilities; -import javax.swing.border.Border; -import javax.swing.border.EmptyBorder; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; -import javax.swing.plaf.basic.BasicInternalFrameUI; - -/** - * 内部窗体UI实现类. - * - * BeautyEye外观实现中取消了isPalette的所有特殊处理,isPalette及相关属性在 - * 该外观中将失去意义,请注意。 - * - * @author Jack Jiang - */ -public class BEInternalFrameUI extends BasicInternalFrameUI { - - /** - * The title pane. - */ - private BEInternalFrameTitlePane titlePane; - - /** - * The Constant metalPropertyChangeListener. - */ - private static final PropertyChangeListener metalPropertyChangeListener = new XZCMetalPropertyChangeHandler(); - - /** - * The Constant handyEmptyBorder. - */ - private static final Border handyEmptyBorder = new EmptyBorder(0, 0, 0, 0); - -// protected static String IS_PALETTE = "JInternalFrame.isPalette"; - /** - * The FRAM e_ type. - */ - private static String FRAME_TYPE = "JInternalFrame.frameType"; - - /** - * The NORMA l_ frame. - */ - private static String NORMAL_FRAME = "normal"; -// private static String PALETTE_FRAME = "palette"; - /** - * The OPTIO n_ dialog. - */ - private static String OPTION_DIALOG = "optionDialog"; - - /** - * Instantiates a new bE internal frame ui. - * - * @param b the b - */ - public BEInternalFrameUI(JInternalFrame b) { - super(b); - } - - public static ComponentUI createUI(JComponent c) { - return new BEInternalFrameUI((JInternalFrame) c); - } - - @Override - public void installUI(JComponent c) { - super.installUI(c); - -// Object paletteProp = c.getClientProperty(IS_PALETTE); -// if (paletteProp != null) -// { -// setPalette(((Boolean) paletteProp).booleanValue()); -// } - Container content = frame.getContentPane(); - stripContentBorder(content); - //c.setOpaque(false); - - frame.setOpaque(false); - } - - @Override - public void uninstallUI(JComponent c) { - frame = (JInternalFrame) c; - - Container cont = ((JInternalFrame) (c)).getContentPane(); - if (cont instanceof JComponent) { - JComponent content = (JComponent) cont; - if (content.getBorder() == handyEmptyBorder) - content.setBorder(null); - } - super.uninstallUI(c); - } - - @Override - protected void installListeners() { - super.installListeners(); - frame.addPropertyChangeListener(metalPropertyChangeListener); - } - - @Override - protected void uninstallListeners() { - frame.removePropertyChangeListener(metalPropertyChangeListener); - super.uninstallListeners(); - } - - @Override - protected void installKeyboardActions() { - super.installKeyboardActions(); - ActionMap map = SwingUtilities.getUIActionMap(frame); - if (map != null) - // BasicInternalFrameUI creates an action with the same name, we override - // it as Metal frames do not have system menus. - map.remove("showSystemMenu"); - } - - @Override - protected void uninstallKeyboardActions() { - super.uninstallKeyboardActions(); - } - - @Override - protected void uninstallComponents() { - titlePane = null; - super.uninstallComponents(); - } - - /** - * Strip content border. - * - * @param c the c - */ - private void stripContentBorder(Object c) { - if (c instanceof JComponent) { - JComponent contentComp = (JComponent) c; - Border contentBorder = contentComp.getBorder(); - if (contentBorder == null || contentBorder instanceof UIResource) - contentComp.setBorder(handyEmptyBorder); - } - } - - @Override - protected JComponent createNorthPane(JInternalFrame w) { - titlePane = new BEInternalFrameTitlePane(w); - return titlePane; - } - - /** - * Sets the frame type. - * - * @param frameType the new frame type - */ - private void setFrameType(String frameType) { - if (frameType.equals(OPTION_DIALOG)) - LookAndFeel.installBorder(frame, "InternalFrame.optionDialogBorder"); // titlePane.setPalette(false); -// else if (frameType.equals(PALETTE_FRAME)) -// { -// LookAndFeel.installBorder(frame, "InternalFrame.paletteBorder"); -//// titlePane.setPalette(true); -// } - else - LookAndFeel.installBorder(frame, "InternalFrame.border"); // titlePane.setPalette(false); - } - -// // this should be deprecated - jcs -// public void setPalette(boolean isPalette) -// { -//// if (isPalette) -//// { -//// LookAndFeel.installBorder(frame, "InternalFrame.paletteBorder"); -//// } -//// else -// { -// LookAndFeel.installBorder(frame, "InternalFrame.border"); -// } -//// titlePane.setPalette(isPalette); -// } - private static class XZCMetalPropertyChangeHandler implements - PropertyChangeListener { - - @Override - public void propertyChange(PropertyChangeEvent e) { - String name = e.getPropertyName(); - JInternalFrame jif = (JInternalFrame) e.getSource(); - - if (!(jif.getUI() instanceof BEInternalFrameUI)) - return; - - BEInternalFrameUI ui = (BEInternalFrameUI) jif.getUI(); - if (name.equals(FRAME_TYPE)) { - if (e.getNewValue() instanceof String) - ui.setFrameType((String) e.getNewValue()); - } // else if (name.equals(IS_PALETTE)) - // { - // if (e.getNewValue() != null) - // { - // ui.setPalette(((Boolean) e.getNewValue()).booleanValue()); - // } - // else - // { - // ui.setPalette(false); - // } - // } - else if (name.equals(JInternalFrame.CONTENT_PANE_PROPERTY)) - ui.stripContentBorder(e.getNewValue()); - } - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/internalframe/__UI__.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/internalframe/__UI__.java deleted file mode 100644 index bf0043f3a..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/internalframe/__UI__.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * __UI__.java at 2015-2-1 20:25:41, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.internalframe; - -import javax.swing.UIManager; -import javax.swing.plaf.BorderUIResource; - -import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper; -import org.jackhuang.hmcl.laf.utils.IconFactory; -import org.jackhuang.hmcl.laf.utils.UI; -import org.jackhuang.hmcl.laf.widget.border.BEShadowBorder; - -public class __UI__ extends UI { - - private static final IconFactory ICON = new IconFactory("internal_frame"); - - public static void uiImpl() { - //内部窗体的边框颜色(BueaytyEye中无意义,原因是BeautyEye LNF中的border是使用NP图实现) - put("InternalFrame.borderColor", BeautyEyeLNFHelper.commonBackgroundColor); - put("InternalFrame.minimizeIconBackground", BeautyEyeLNFHelper.commonBackgroundColor); -// UIManager.put("InternalFrame.paletteCloseIcon", ICON.get("close")); //本属性在beautyEye中不会起效的 - UIManager.put("InternalFrame.icon", ICON.get("icon")); - UIManager.put("InternalFrame.iconifyIcon", ICON.get("iconify")); - UIManager.put("InternalFrame.minimizeIcon", ICON.get("min")); - UIManager.put("InternalFrame.maximizeIcon", ICON.get("max")); - UIManager.put("InternalFrame.closeIcon", ICON.get("close")); - put("InternalFrameUI", BEInternalFrameUI.class); -// put("InternalFrame.paletteTitleHeight", 40); //本属性在beautyEye中不会起效的 -// put("InternalFrame.titlePaneHeight", 38); //default is 25 -// put("InternalFrame.borderWidth", 10); - Object internalFrameBorder = new BorderUIResource(new BEShadowBorder()); - UIManager.put("InternalFrame.border", internalFrameBorder); - UIManager.put("InternalFrame.paletteBorder", internalFrameBorder); - UIManager.put("InternalFrame.optionDialogBorder", internalFrameBorder); - - //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> JDesktopPane相关ui属性设定 - //JDesktopPane的背景色 - put("Desktop.background", BeautyEyeLNFHelper.commonBackgroundColor); - //此属性暂无意义 -// putInsetc("Desktop.minOnScreenInsets", 10, 10, 10, 10);//default is 3,3,3,3 - //JDesktopPane中内部窗体最小化时的窗体组件宽度 - put("DesktopIcon.width", 180); //默认是160 - //BeautyEye LNF中内部窗体标题栏实现 - put("DesktopIconUI", BEDesktopIconUI.class); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/list/BEListUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/list/BEListUI.java deleted file mode 100644 index 1dffd6dbe..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/list/BEListUI.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BEListUI.java at 2015-2-1 20:25:40, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.list; - -import javax.swing.CellRendererPane; -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicListUI; - -/** - * JList的UI实现类. - * - * @author Jack Jiang(jb2011@163.com) - * @version 1.0 - */ -public class BEListUI extends BasicListUI { - - public static ComponentUI createUI(JComponent c) { - return new BEListUI(); - } - - /** - * Initialize JList properties, e.g. font, foreground, and background, and - * add the CellRendererPane. The font, foreground, and background properties - * are only set if their current value is either null or a UIResource, other - * properties are set if the current value is null. - * - * @see #uninstallDefaults - * @see #installUI - * @see CellRendererPane - */ - @Override - protected void installDefaults() { - super.installDefaults(); - - //2012-08-30*******************************************************【重要说明】 START 对应BEComboBoxUI中的【重要说明】 - //* 【重要说明】因BEListUI中为了使列表行单元高变的更高(在MyDefaultListCellRenderer.java中 - //* 像COmboxRender一样通过增到border不起效果,它可能是BasicListUI的设计缺陷,它要么取FixedCellHeight - //* 固定值,要么取getPreferSize()即自动计算高度——它似乎是不计入border的,所以render设置border不起效) - //* 所以只能为列表单元设置因定值:list.setFixedCellHeight(30),但它将影响Combox里的行高(也会变成30高) - //* 所以BEComboBoxUI中要把本列表UI中强制设定的30高针对Combox还原成自动计算(API中规定FixedCellHeight==-1即表示自动计算) - //*************************************************************** 【重要说明】 END - //* 则jb2011加入,表示列表单元固定高度,默认值=-1(即意味着行高自动计算) - //* 使用BE LNF的项目,如要恢复行高算动计算则显示设置列表的固定行高为-1即可! - list.setFixedCellHeight(27);//32//30);// TODO 此设置值作一个UIManager属性就可以方便以后设置了,-1是原系统默认值哦(即自动计算单元高) - - //* 不需要了,它样强制要求它为透明可能会影响以后用户的定制需求,干脆 - //* 设置它的背景为认白色,也能达到想到的N9白色背景 -// //此设置将取消列表背景的绘制(以便BE LNF中绘制N9背景图哦) -// list.setOpaque(false); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/list/MyDefaultListCellRenderer.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/list/MyDefaultListCellRenderer.java deleted file mode 100644 index fdfbe16a5..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/list/MyDefaultListCellRenderer.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * MyDefaultListCellRenderer.java at 2015-2-1 20:25:36, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.list; - -import java.awt.Component; -import java.awt.Graphics; -import java.awt.Graphics2D; - -import javax.swing.DefaultListCellRenderer; -import javax.swing.JList; -import org.jackhuang.hmcl.laf.utils.Icon9Factory; - -/** - * 列表单元的默认renderer实现类. - * - * @author Jack Jiang(jb2011@163.com), 2012-08-30 - * @version 1.0 - */ -public class MyDefaultListCellRenderer extends DefaultListCellRenderer { - - private static final Icon9Factory ICON_9 = new Icon9Factory("list"); - - /** - * The is selected. - */ - protected boolean isSelected = false; - - /** - * The is focuesed. - */ - protected boolean isFocuesed = false; - - /** - * Instantiates a new my default list cell renderer. - */ - public MyDefaultListCellRenderer() { - //设置成透明背景则意味着不需要背景填充,但本类中的应用场景有点特殊 - //——默认的render的UI里不需要绘制背景的情况下本类才可进行NinePatch图作为背景进行填充 - setOpaque(false); - - //** 要像Combox的render一样设置border没用,因为列表单元不获得焦点时的border由UIManager属性List.cellNoFocusBorder决定 -// //注:此内衬是决定列表单元间的上下左右空白的关键哦! -// setBorder(BorderFactory.createEmptyBorder(5, 8, 5, 8)); - } - - @Override - public void paintComponent(Graphics g) { - if (isSelected) - //注意:2012-09-03日用的该图片右边有一个像素的空白哦,其实它是可以通过List.border的UI属性来调整的 - //之所以没有用它调整就是为了日后可以使用N9图来自由调整而无需调整代码(List.border的代码没置) - ICON_9.get("selected_icon_bg") - .draw((Graphics2D) g, 0, 0, this.getWidth(), this.getHeight()); - else { -// g.setColor(this.getBackground()); -// //本Insets取this.getInsets()是符合Sun的设计初衷的,但是不合理(本身isPopupVisible==false -// //时的背景就是特殊情况,不能与下拉项同等视之),所以此处用自定义的Insets来处理则在UI展现上更为合理 。 -// //TODO 这个Instes可以作为UI属性“ComboBox.popupNoVisibleBgInstes”方便以后设置,暂时先硬编码吧,以后再说 -// Insets is = new Insets(2,3,2,3);//this.getInsets(); -//// g.fillRect(is.left, is.top -//// , this.getWidth()-is.left-is.right -//// , this.getHeight()-is.top-is.bottom); -// BEUtils.fillTextureRoundRec((Graphics2D)g, this.getBackground(), is.left, is.top -// , this.getWidth()-is.left-is.right -// , this.getHeight()-is.top-is.bottom,20,0);//20,20 - } -// else - //注意:本组件已经被设置成opaque=false即透明,否则本方法还会填充默认背景,那么选中时的 - //N9图背景因先绘将会被覆盖哦。所以要使用N9图作为选中时的背景则前提是本组件必须是透明 - super.paintComponent(g); - } - - @Override - public Component getListCellRendererComponent( - JList list, - Object value, - int index, - boolean isSelected, - boolean cellHasFocus) { - Component c = super.getListCellRendererComponent(list, - value, index, isSelected, cellHasFocus); - - this.isSelected = isSelected; - this.isFocuesed = cellHasFocus; - return c; - } - - /** - * A subclass of DefaultListCellRenderer that implements UIResource. - * DefaultListCellRenderer doesn't implement UIResource directly so that - * applications can safely override the cellRenderer property with - * DefaultListCellRenderer subclasses. - *

    - * Warning: - * Serialized objects of this class will not be compatible with future Swing - * releases. The current serialization support is appropriate for short term - * storage or RMI between applications running the same version of Swing. As - * of 1.4, support for long term storage of all - * JavaBeansTM - * has been added to the java.beans package. Please see - * {@link java.beans.XMLEncoder}. - */ - public static class UIResource extends MyDefaultListCellRenderer - implements javax.swing.plaf.UIResource { - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/list/__UI__.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/list/__UI__.java deleted file mode 100644 index beffd70d9..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/list/__UI__.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * __UI__.java at 2015-2-1 20:25:40, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.list; - -import java.awt.Color; -import java.awt.Component; -import java.awt.Graphics; -import java.awt.Insets; - -import javax.swing.UIManager; -import javax.swing.border.AbstractBorder; - -import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper; -import org.jackhuang.hmcl.laf.utils.UI; - -public class __UI__ extends UI { - - public static void uiImpl() { - //通过此border可以调整整个列表的上下左右的空白 - putBorder("List.border", 0, 0, 0, 0); - //本属性将决定已被选中的列表单元显示文本的上下左右空白哦 - putBorder("List.focusCellHighlightBorder", 1, 8, 5, 3); - /* ~~注:这个属性是jb2011为了更好的ui效果自已加的属性 */ - putColor("List.focusSelectedCellHighlightBorderColor", 252, 87, 84); //Color.red - /* ~~注:这个属性是jb2011为了更好的ui效果自已加的属性,目的是使List.focusSelectedCellHighlightBorderColor有点立体效果哦 */ - putColor("List.focusSelectedCellHighlightBorderHighlightColor", 255, 255, 255, 70);//注意:这个颜色是半透明的哦 - //列表单元获得焦点时的边框(windows主题下是一个距形虚线框)——之前老也想不通的与左边隔一个像素的白边问题就是没设置它造成的 - put("List.focusSelectedCellHighlightBorder", new FocusSelectedCellHighlightBorder()); - //将决定正状态下的列表单元显示文本的上下左右空白哦 - putBorder("List.cellNoFocusBorder", 1, 8, 5, 3); - - put("List.background", Color.white); - put("List.foreground", BeautyEyeLNFHelper.commonForegroundColor); - put("List.selectionForeground", Color.white);//fgColor); - put("List.selectionBackground", BeautyEyeLNFHelper.commonSelectionBackgroundColor); - - UIManager.put("List.cellRenderer", new MyDefaultListCellRenderer.UIResource()); - put("ListUI", BEListUI.class); - } - - /** - * 本border由Jack Jiang实现,它是列表单元获得焦点时的边框(windows外观 - * 下是一个距形虚线框),本border当前的样式是在在最左边画的一条红色竖线 - */ - static class FocusSelectedCellHighlightBorder extends AbstractBorder { - - @Override - public Insets getBorderInsets(Component c) { - //Insets跟List.focusCellHighlightBorder 一样即可,这样就能在视觉上保持一致罗(不一样则会有移位的难看效果)! - return UIManager.getBorder("List.focusCellHighlightBorder").getBorderInsets(c); - } - - @Override - public Insets getBorderInsets(Component c, Insets insets) { - return getBorderInsets(c); - } - - @Override - public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { - //在左边划一条2像素宽的竖线 - g.setColor(UIManager.getColor("List.focusSelectedCellHighlightBorderColor")); - g.fillRect(x, y + 0, 2, height - 1);//-2);//上下各空白一个像素,目的是为了与render的N9图片背景配合形成更好的视觉效果 - - //再在上面的竖线右边划一条1像素宽的亮色竖线,以便为上面的2像素竖线营造立体效果 - /* ~~注:这个属性是jb2011为了更好的ui效果自已加的属性,目的是使List.focusSelectedCellHighlightBorder有点立体效果哦 */ - g.setColor(UIManager.getColor("List.focusSelectedCellHighlightBorderHighlightColor")); - g.fillRect(x + 2, y + 0, 1, height - 1);//-2); - } - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/menu/BECheckBoxMenuItemUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/menu/BECheckBoxMenuItemUI.java deleted file mode 100644 index a395e1daf..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/menu/BECheckBoxMenuItemUI.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BECheckBoxMenuItemUI.java at 2015-2-1 20:25:39, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.menu; - -import java.awt.Color; -import java.awt.Component; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.io.Serializable; - -import javax.swing.AbstractButton; -import javax.swing.ButtonModel; -import javax.swing.Icon; -import javax.swing.JComponent; -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; -import javax.swing.plaf.basic.BasicCheckBoxMenuItemUI; -import org.jackhuang.hmcl.laf.utils.IconFactory; - -/** - * JCheckBoxMenuItem的UI实现类. - * - * @author Jack Jiang(jb2011@163.com) - */ -public class BECheckBoxMenuItemUI extends BasicCheckBoxMenuItemUI { - - private static final IconFactory ICON = new IconFactory("menu_check"); - - /** - * 是否强制单项透明(当强制不透明时,在普通状态下该item将不会被绘制背景). - */ - private static boolean enforceTransparent = true; - - public static ComponentUI createUI(JComponent b) { - return new BECheckBoxMenuItemUI(); - } - - @Override - protected void paintBackground(Graphics g, JMenuItem menuItem, - Color bgColor) { -// if (WindowsMenuItemUI.isVistaPainting()) { -// WindowsMenuItemUI.paintBackground(accessor, g, menuItem, bgColor); -// return; -// } -// super.paintBackground(g, menuItem, bgColor); - // see parent! - ButtonModel model = menuItem.getModel(); - Color oldColor = g.getColor(); - int menuWidth = menuItem.getWidth(); - int menuHeight = menuItem.getHeight(); - - Graphics2D g2 = (Graphics2D) g; - - if (model.isArmed() - || (menuItem instanceof JMenu && model.isSelected())) { - g.setColor(bgColor); - - BEMenuUI.drawSelectedBackground(g, 0, 0, menuWidth, menuHeight); - -// /****** 选中的背景样式现在是渐变加圆角填充了,impled by js */ -// NLLookAndFeel.setAntiAliasing(g2, true); -// //矩形填充 -// Paint oldpaint = g2.getPaint(); -// GradientPaint gp = new GradientPaint(0, 0 -// ,GraphicHandler.getColor(bgColor, 35, 35, 35) -// ,0, menuHeight,bgColor -// ); -// g2.setPaint(gp); -// g.fillRoundRect(0, 0, menuWidth, menuHeight,5,5); -// g2.setPaint(oldpaint); -// NLLookAndFeel.setAntiAliasing(g2, false); - } else if (!enforceTransparent) { - g.setColor(menuItem.getBackground()); - g.fillRect(0, 0, menuWidth, menuHeight); - } - g.setColor(oldColor); - } - - /** - * @see - * com.sun.java.swing.plaf.windows.WindowsIconFactory.CheckBoxMenuItemIcon - */ - public static class CheckBoxMenuItemIcon implements Icon, UIResource, Serializable { - - @Override - public void paintIcon(Component c, Graphics g, int x, int y) { - g.drawImage(ICON.get(((AbstractButton) c).getModel().isSelected() ? "checked" : "normal").getImage(), - x - 4, y - 3, null); - } - - @Override - public int getIconWidth() { - return 16; - }// default 9 - - @Override - public int getIconHeight() { - return 16; - }// default 9 - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/menu/BEMenuBarUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/menu/BEMenuBarUI.java deleted file mode 100644 index fcb8b847c..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/menu/BEMenuBarUI.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BEMenuBarUI.java at 2015-2-1 20:25:37, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.menu; - -import java.awt.Graphics; - -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicMenuBarUI; - -/** - * JMenuBar的UI实现类. - * - * @author Jack Jiang(jb2011@163.com) - * @see com.sun.java.swing.plaf.windows.WindowsMenuBarUI - */ -public class BEMenuBarUI extends BasicMenuBarUI { - - public static ComponentUI createUI(JComponent x) { - return new BEMenuBarUI(); - } - - @Override - public void paint(Graphics g, JComponent c) { - int width = c.getWidth(); - int height = c.getHeight(); - - //背景划一个灰色底线(方便与JMenuBar的顶层菜单项的底色融合) - g.setColor(BEMenuUI.MENU_UNSELECTED_UNDERLINE_COLOR); - g.fillRect(0, height - BEMenuUI.DECORATED_UNDERLINE_HEIGHT, width, height); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/menu/BEMenuItemUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/menu/BEMenuItemUI.java deleted file mode 100644 index ca364459d..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/menu/BEMenuItemUI.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BEMenuItemUI.java at 2015-2-1 20:25:38, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.menu; - -import java.awt.Color; -import java.awt.Graphics; -import java.awt.Graphics2D; - -import javax.swing.ButtonModel; -import javax.swing.JComponent; -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicMenuItemUI; - -/** - * JMenuItem的UI实现类. - * - * 特别注意:BasicMenuItemUI中针对Vista及后来的Windows版本预设了很多其它LNF不需要的属性, - * 预设的属性详见BasicMenuItemUI及WindowsLookAndFeel中的initVistaComponentDefaults(..)方法. - * 这些属性只能会在vista及更新的windows平台上过运行时才会起效,所以除此之外的windows测不出来, - * 容易出现ui视觉差异. - * - * @author Jack Jiang(jb2011@163.com) - */ -public class BEMenuItemUI extends BasicMenuItemUI { - - /** - * 是否强制单项透明(当强制不透明时,在普通状态下该item将不会被绘制背景). - */ - private static boolean enforceTransparent = true;// TODO 可以提炼成UI属性 - - public static ComponentUI createUI(JComponent c) { - return new BEMenuItemUI(); - } - - /** - * {@inheritDoc} - * - * @see com.sun.java.swing.plaf.windows.WindowsMenuItemUI#paintBackground(java.awt.Graphics, javax.swing.JMenuItem, java.awt.Color) - * @see javax.swing.plaf.basic.BasicMenuItemUI#paintBackground(java.awt.Graphics, javax.swing.JMenuItem, java.awt.Color) - */ - @Override - protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor) { - ButtonModel model = menuItem.getModel(); - Color oldColor = g.getColor(); - int menuWidth = menuItem.getWidth(); - int menuHeight = menuItem.getHeight(); - - Graphics2D g2 = (Graphics2D) g; - - if (model.isArmed() - || (menuItem instanceof JMenu && model.isSelected())) - //菜单项的样式绘制(用NinePatch图来填充) - BEMenuUI.drawSelectedBackground(g, 0, 0, menuWidth, menuHeight); - else if (!enforceTransparent) { - g.setColor(menuItem.getBackground()); - g.fillRect(0, 0, menuWidth, menuHeight); - } - g.setColor(oldColor); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/menu/BEMenuUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/menu/BEMenuUI.java deleted file mode 100644 index b9d98e42c..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/menu/BEMenuUI.java +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BEMenuUI.java at 2015-2-1 20:25:40, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.menu; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.event.MouseEvent; - -import javax.swing.ButtonModel; -import javax.swing.Icon; -import javax.swing.JComponent; -import javax.swing.JMenu; -import javax.swing.JMenuBar; -import javax.swing.JMenuItem; -import javax.swing.MenuElement; -import javax.swing.UIManager; -import javax.swing.event.MouseInputListener; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicMenuUI; - -import org.jackhuang.hmcl.laf.BEUtils; -import org.jackhuang.hmcl.laf.utils.Icon9Factory; -import org.jackhuang.hmcl.laf.utils.WinUtils; - -/** - * JMenuU的UI实现类. - * - * @author Jack Jiang(jb2011@163.com) - * @see com.sun.java.swing.plaf.windows.WindowsMenuUI - */ -public class BEMenuUI extends BasicMenuUI { - - //JMenuBar的顶层菜单项的装饰底线高度 - public final static int DECORATED_UNDERLINE_HEIGHT = 2;// TODO 可以提炼成Ui属性哦 - - //顶层菜单项被选中的颜色 - public final static Color MENU_SELECTED_UNDERLINE_COLOR = new Color(37, 147, 217);// TODO 可以提炼成Ui属性哦 - - //顶层菜单项未被选中的颜色 - public final static Color MENU_UNSELECTED_UNDERLINE_COLOR = new Color(226, 230, 232);// TODO 可以提炼成Ui属性哦 - - protected Integer menuBarHeight; - - protected boolean hotTrackingOn; - - public static ComponentUI createUI(JComponent x) { - return new BEMenuUI(); - } - - /** - * {@inheritDoc} - * - * @see com.sun.java.swing.plaf.windows.WindowsMenuUI#installDefaults() - */ - @Override - protected void installDefaults() { - super.installDefaults(); -// if (!WindowsLookAndFeel.isClassicWindows()) - { - menuItem.setRolloverEnabled(true); - } - - menuBarHeight = (Integer) UIManager.getInt("MenuBar.height"); - Object obj = UIManager.get("MenuBar.rolloverEnabled"); - hotTrackingOn = (obj instanceof Boolean) ? (Boolean) obj : true; - } - - /** - * Draws the background of the menu. - * - * @param g the g - * @param menuItem the menu item - * @param bgColor the bg color - * @since 1.4 - * - * @see com.sun.java.swing.plaf.windows.WindowsMenuUI#paintBackground(java.awt.Graphics, javax.swing.JMenuItem, java.awt.Color) - */ - @Override - protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor) { - JMenu menu = (JMenu) menuItem; - ButtonModel model = menu.getModel(); - - Color oldColor = g.getColor(); - int menuWidth = menu.getWidth(); - int menuHeight = menu.getHeight(); - -// UIDefaults table = UIManager.getLookAndFeelDefaults(); -// Color highlight = table.getColor("controlLtHighlight"); -// Color shadow = table.getColor("controlShadow"); - g.setColor(menu.getBackground()); - g.fillRect(0, 0, menuWidth, menuHeight); - - //给JMEnuBar的顶层菜单项中画一个灰色底线(看起来美观) - //位于菜单项里的MenuItem则不需要画这个底线(要不然不好看哦) - if (menu.isTopLevelMenu()) { - //未选中的装饰底线 - //只要放在MenuBar最顶层的JMenu才需要画哦(从而与底色融为一体) - g.setColor(MENU_UNSELECTED_UNDERLINE_COLOR); - g.fillRect(0, menuHeight - DECORATED_UNDERLINE_HEIGHT, menuWidth, menuHeight); - } - - //* >注意:官方是判断menu.isOpaque()==false时才进入此if-else分支, - //* >其实以下代码的意义是:当是顶级Menu(即直接放在MenuBar上的那层)时 - //* >才需要调用以下分支,而在win7下,以下分支是不会被调用的(WindowsLookAndfeel.initVistaComponentDefaults中 - //* >处理了如果是vista则"MenuItem.opaque", "Menu.opaque", "CheckBoxMenuItem.opaque", "RadioButtonMenuItem.opaque" - //* >默认都设置成了false,即默认透明(官方逻辑可能是透明体就意味着是顶级menu了)!) - //* >,那么win7下将会出现错误的表现:无法区分是不是顶级menu也就无法区别paint出不同的样子了. - //* >那么官方为何没收到bug报告呢?我分析可能还没有人面对到BeautyEye这样需要对Menu进行较复杂样式需求的场景 - //* >,即把顶级menu和内层menu分的很清。 - //* >目前BeautyEye的实现即menu.isTopLevelMenu()==true时即进入本分支 - //* >才是比较合理的,当然,有待实践检验,或许官方有其它考虑。 -- commet by Jack Jiang 2012-09-14 - if (menu.isTopLevelMenu())//menu.isOpaque()) - { - //JMebuBar的顶层菜单项被选中或鼠标停留时 - if (model.isArmed() || model.isSelected()) { - Color c = MENU_SELECTED_UNDERLINE_COLOR; - g.setColor(c); - - //先填充一个装饰3角形(用于在UI上提示用户它被选中了) - // x2,y2 - // - //x1,y1 x3,y3 - int tW = 7, tH = 3; - int x1 = menuWidth / 2 - tW / 2; - int y1 = menuHeight - DECORATED_UNDERLINE_HEIGHT; - int x2 = menuWidth / 2; - int y2 = menuHeight - DECORATED_UNDERLINE_HEIGHT - tH; - int x3 = menuWidth / 2 + tW / 2; - int y3 = menuHeight - DECORATED_UNDERLINE_HEIGHT; - //反走样 - BEUtils.setAntiAliasing((Graphics2D) g, true); - BEUtils.fillTriangle(g, x1, y1, x2, y2, x3, y3, c); - BEUtils.setAntiAliasing((Graphics2D) g, false); - - //再填充一个底线(用于装饰) - g.fillRect(0, menuHeight - DECORATED_UNDERLINE_HEIGHT, menuWidth, DECORATED_UNDERLINE_HEIGHT);//menuHeight); - } else if (model.isRollover() && model.isEnabled()) { - // Only paint rollover if no other menu on menubar is selected - boolean otherMenuSelected = false; - MenuElement[] menus = ((JMenuBar) menu.getParent()) - .getSubElements(); - for (MenuElement menu1 : menus) - if (((JMenuItem) menu1).isSelected()) { - otherMenuSelected = true; - break; - } - - if (!otherMenuSelected) { - g.setColor(MENU_SELECTED_UNDERLINE_COLOR);//selectionBackground);// Uses protected -// g.fillRect(0, 0, menuWidth, menuHeight); - //再填充一个底线(用于装饰) - g.fillRect(0, menuHeight - DECORATED_UNDERLINE_HEIGHT, menuWidth, DECORATED_UNDERLINE_HEIGHT);//menuHeight); - } - } - } // add by Jack Jiang,JMebuBar的内层父级菜单项的样式绘制 - else if (model.isArmed() || (menuItem instanceof JMenu - && model.isSelected())) { - //用NinePatch图来填充 - drawSelectedBackground(g, 0, 0, menuWidth, menuHeight); - } - g.setColor(oldColor); - } - - public static void drawSelectedBackground(Graphics g, int x, int y, int w, int h) { - g.setColor(UIManager.getColor("MenuItem.selectionBackground")); - g.fillRect(0, 0, w, h); - } - - /** - * Method which renders the text of the current menu item. - *

    - * @param g Graphics context - * @param menuItem Current menu item to render - * @param textRect Bounding rectangle to render the text. - * @param text String to render - * @since 1.4 - * - * @see com.sun.java.swing.plaf.windows.WindowsMenuUI#paintText(java.awt.Graphics, javax.swing.JMenuItem, java.awt.Rectangle, java.lang.String) - */ - @Override - protected void paintText(Graphics g, JMenuItem menuItem, - Rectangle textRect, String text) { - //================= commet by Jack Jiang START -// if (WindowsMenuItemUI.isVistaPainting()) { -// WindowsMenuItemUI.paintText(accessor, g, menuItem, textRect, text); -// return; -// } - //================= commet by Jack Jiang END - JMenu menu = (JMenu) menuItem; - ButtonModel model = menuItem.getModel(); - Color oldColor = g.getColor(); - - // Only paint rollover if no other menu on menubar is selected - boolean paintRollover = model.isRollover(); - if (paintRollover && menu.isTopLevelMenu()) { - MenuElement[] menus = ((JMenuBar) menu.getParent()).getSubElements(); - for (MenuElement menu1 : menus) - if (((JMenuItem) menu1).isSelected()) { - paintRollover = false; - break; - } - } - - if ((model.isSelected() - && ( // WindowsLookAndFeel.isClassicWindows() || - !menu.isTopLevelMenu())) - || ( // BEXPStyle.getXP() != null && - (paintRollover || model.isArmed() || model.isSelected()))) - g.setColor(selectionForeground); // Uses protected field. - - //================= add by Jack Jiang START - //特殊处理顶级菜单项(就是直接放在JMenuBar上的那一层),使之在被选中或rover等状态时保持黑色(或其它颜色) - //,目的是为了配合整个菜单项的L&F效果,并没有过多的用途,此颜色可提取作为UIManager的自定义属性哦 - if (menu.isTopLevelMenu()) - g.setColor(new Color(35, 35, 35));//用MaxOS X的经典黑 - //================= add by Jack Jiang END - -// WindowsGraphicsUtils.paintText(g, menuItem, textRect, text, 0); - WinUtils.paintText(g, menuItem, textRect, text, 0); - - g.setColor(oldColor); - } - - /** - * {@inheritDoc} - * - * @see - * com.sun.java.swing.plaf.windows.WindowsMenuUI#createMouseInputListener(javax.swing.JComponent) - */ - @Override - protected MouseInputListener createMouseInputListener(JComponent c) { - return new BEMouseInputHandler(); - } - - /** - * This class implements a mouse handler that sets the rollover flag to true - * when the mouse enters the menu and false when it exits. - * - * @since 1.4 - * @see com.sun.java.swing.plaf.windows.WindowsMenuUI.MouseInputHandler - */ - protected class BEMouseInputHandler extends BasicMenuUI.MouseInputHandler { - - @Override - public void mouseEntered(MouseEvent evt) { - super.mouseEntered(evt); - - JMenu menu = (JMenu) evt.getSource(); - if (hotTrackingOn && menu.isTopLevelMenu() && menu.isRolloverEnabled()) { - menu.getModel().setRollover(true); - menuItem.repaint(); - } - } - - @Override - public void mouseExited(MouseEvent evt) { - super.mouseExited(evt); - - JMenu menu = (JMenu) evt.getSource(); - ButtonModel model = menu.getModel(); - if (menu.isRolloverEnabled()) { - model.setRollover(false); - menuItem.repaint(); - } - } - } - - /** - * {@inheritDoc} - * - * @see - * com.sun.java.swing.plaf.windows.WindowsMenuUI#getPreferredMenuItemSize(javax.swing.JComponent, - * javax.swing.Icon, javax.swing.Icon, int) - */ - @Override - protected Dimension getPreferredMenuItemSize(JComponent c, - Icon checkIcon, - Icon arrowIcon, - int defaultTextIconGap) { - - Dimension d = super.getPreferredMenuItemSize(c, checkIcon, arrowIcon, - defaultTextIconGap); - - // Note: When toolbar containers (rebars) are implemented, only do - // this if the JMenuBar is not in a rebar (i.e. ignore the desktop - // property win.menu.height if in a rebar.) - if (c instanceof JMenu && ((JMenu) c).isTopLevelMenu() - && menuBarHeight != null && d.height < menuBarHeight) - - d.height = menuBarHeight; - - return d; - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/menu/BEPopupMenuSeparatorUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/menu/BEPopupMenuSeparatorUI.java deleted file mode 100644 index 37a59dba5..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/menu/BEPopupMenuSeparatorUI.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BEPopupMenuSeparatorUI.java at 2015-2-1 20:25:36, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.menu; - -import java.awt.BasicStroke; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Stroke; - -import javax.swing.JComponent; -import javax.swing.JSeparator; -import javax.swing.LookAndFeel; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.SeparatorUI; - -/** - * JPopupMenuSeparator的UI实现. - * - * @author Jack Jiang(jb2011@163.com) - * @version 1.0 - */ -public class BEPopupMenuSeparatorUI extends SeparatorUI { - - public static ComponentUI createUI(JComponent c) { - return new BEPopupMenuSeparatorUI(); - } - - @Override - public void installUI(JComponent c) { - installDefaults((JSeparator) c); - installListeners((JSeparator) c); - } - - @Override - public void uninstallUI(JComponent c) { - uninstallDefaults((JSeparator) c); - uninstallListeners((JSeparator) c); - } - - protected void installDefaults(JSeparator s) { - LookAndFeel.installColors(s, "Separator.background", "Separator.foreground"); - LookAndFeel.installProperty(s, "opaque", Boolean.FALSE); - } - - protected void uninstallDefaults(JSeparator s) { - } - - protected void installListeners(JSeparator s) { - } - - protected void uninstallListeners(JSeparator s) { - } - - @Override - public void paint(Graphics g, JComponent c) { - int w = c.getWidth(), h = c.getHeight(); - Graphics2D g2 = (Graphics2D) g; - - if (((JSeparator) c).getOrientation() == JSeparator.VERTICAL) { - //垂直坚线原始代码 - //TODO 垂直样式的竖线有时间再实现吧,垂直竖线默认用于JToolBar里 - g.setColor(c.getForeground()); - g.drawLine(0, 0, 0, c.getHeight()); - g.setColor(c.getBackground()); - g.drawLine(1, 0, 1, c.getHeight()); - } else // HORIZONTAL - - drawHorizonal(g2, c, w, h); - } - - /** - * 以水平方向绘制分隔线样式. - */ - private void drawHorizonal(Graphics2D g2, JComponent c, int w, int h) { - //** 绘制border的底线 - //虚线样式 - Stroke oldStroke = g2.getStroke(); - Stroke sroke = new BasicStroke(1, BasicStroke.CAP_BUTT, - BasicStroke.JOIN_BEVEL, 0, new float[] { 2, 2 }, 0);//实线,空白 - g2.setStroke(sroke); - //底边上(浅灰色) -// g2.setColor(new Color(180,180,180)); - g2.setColor(c.getForeground()); - g2.drawLine(0, h - 2, w - 1, h - 2); // draw bottom1 - //底边下(白色):绘制一条白色虚线的目的是与上面的灰线产生较强对比度从而形成立体效果 - //,本L&F实现中因与Panel的底色对比度不够强烈而立体感不明显(颜色越深的底色最终效果越明显) -// g2.setColor(Color.white); - g2.setColor(c.getBackground()); - g2.drawLine(0, h - 1, w - 1, h - 1);//draw bottom2 - - g2.setStroke(oldStroke); - } - - @Override - public Dimension getPreferredSize(JComponent c) { - if (((JSeparator) c).getOrientation() == JSeparator.VERTICAL) - return new Dimension(2, 0); - else - return new Dimension(0, 3); - } - - @Override - public Dimension getMinimumSize(JComponent c) { - return null; - } - - @Override - public Dimension getMaximumSize(JComponent c) { - return null; - } - -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/menu/BEPopupMenuUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/menu/BEPopupMenuUI.java deleted file mode 100644 index ebcf066b8..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/menu/BEPopupMenuUI.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BEPopupMenuUI.java at 2015-2-1 20:25:36, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.menu; - -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicPopupMenuUI; - -/** - * BeautyEye L&F的弹出菜单主类实现类. - * - * 兼容性说明:WindowsPopupMenuUI类在java1.6.0_u10(可能不仅限于1.6.0_u10,但java1.6.0中不存在这个问题) - * 中会判断,如果是在Vista或者说xp平台时(测试证明是在win7平台会有这些问题)会用windows系 - * 统实现进行背景填充,而在1.6.0_u18(可能不限于此版本中)取消了这样的判断,改为直接继续 - * BasicPopupMenuUI的实默认实现。因此而带来的差异使得BE LNF在不同的java版本里(u10)会 - * 错误地使用windows系统实现.本类的目的就是要去掉这种差异,仍然交由父类BasicPopupMenuUI 实现即可(类似的官方Metal - * LNF也是采用了BeautyEye一样的处理逻辑). - * - * @author Jack Jiang(jb2011@163.com), 2012-09-14 - * @version 1.0 - * @since 3.1 - * - * @see com.sun.java.swing.plaf.windows.WindowsPopupMenuUI - */ -public class BEPopupMenuUI extends BasicPopupMenuUI { - - public static ComponentUI createUI(JComponent c) { - return new BEPopupMenuUI(); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/menu/BERadioButtonMenuItemUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/menu/BERadioButtonMenuItemUI.java deleted file mode 100644 index 31b43ff57..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/menu/BERadioButtonMenuItemUI.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BERadioButtonMenuItemUI.java at 2015-2-1 20:25:37, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.menu; - -import java.awt.Color; -import java.awt.Component; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.io.Serializable; - -import javax.swing.AbstractButton; -import javax.swing.ButtonModel; -import javax.swing.Icon; -import javax.swing.JComponent; -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; -import javax.swing.plaf.basic.BasicRadioButtonMenuItemUI; -import org.jackhuang.hmcl.laf.utils.IconFactory; - -/** - * JRadioButtonMenuItem的UI实现. - * - * @author Jack Jiang(jb2011@163.com) - * @version 1.0 - */ -public class BERadioButtonMenuItemUI extends BasicRadioButtonMenuItemUI { - - private static final IconFactory ICON = new IconFactory("menu_radio"); - - public static ComponentUI createUI(JComponent b) { - return new BERadioButtonMenuItemUI(); - } - - /** - * Draws the background of the menu item. - * - * @param g the paint graphics - * @param menuItem menu item to be painted - * @param bgColor selection background color - * @since 1.4 - * @see - * javax.swing.plaf.basic.BasicMenuItemUI#paintBackground(java.awt.Graphics, - * javax.swing.JMenuItem, java.awt.Color) - */ - @Override - protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor) { - ButtonModel model = menuItem.getModel(); - Color oldColor = g.getColor(); - int menuWidth = menuItem.getWidth(); - int menuHeight = menuItem.getHeight(); - - if (menuItem.isOpaque()) { - if (model.isArmed() || (menuItem instanceof JMenu && model.isSelected())) { - g.setColor(bgColor); - g.fillRect(0, 0, menuWidth, menuHeight); - } else { - g.setColor(menuItem.getBackground()); - g.fillRect(0, 0, menuWidth, menuHeight); - } - g.setColor(oldColor); - } else if (model.isArmed() || (menuItem instanceof JMenu - && model.isSelected())) -// g.setColor(bgColor); -// g.fillRect(0,0, menuWidth, menuHeight); -// g.setColor(oldColor); - - //由jb2011改用NinePatch图来填充 - BEMenuUI.drawSelectedBackground(g, 0, 0, menuWidth, menuHeight); - } - - /** - * @see com.sun.java.swing.plaf.windows.WindowsIconFactory.RadioButtonMenuItemIcon - */ - public static class RadioButtonMenuItemIcon implements Icon, UIResource, Serializable { - - @Override - public void paintIcon(Component c, Graphics g, int x, int y) { - //* 注意:当用于windows平台专用主类且处于Vista及更高版win时要做不一样的处理哦 - g.drawImage(ICON.get(((AbstractButton) c).getModel().isSelected() ? "checked" : "normal").getImage(), - x - 4, y - 4, null); - } - - @Override - public int getIconWidth() { - return 16; - }//default 6 - - @Override - public int getIconHeight() { - return 16; - }//default 6 - - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/menu/__UI__.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/menu/__UI__.java deleted file mode 100644 index 67331cbf7..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/menu/__UI__.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * __UI__.java at 2015-2-1 20:25:36, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.menu; - -import java.awt.Color; - -import javax.swing.UIManager; - -import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper; -import org.jackhuang.hmcl.laf.utils.UI; - -public class __UI__ extends UI { - - public static void uiImpl() { - //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> margin和border设置 START -// UIManager.put("MenuBar.border",new org.jb2011.lnf.windows2.ch10.EWindowsMenuBarUI.MenuBarBorder(Color.red,Color.BLUE)); - //去掉菜单条下方的border(默认是一个2个像素高的横线,参见WindowsMenuBarUI.MenuBarBorder) - putBorder("MenuBar.border"); - - //提示:margin与border并存设置情况容易产生混知,其实官方实现是:当设置margin时,则Border就使用 - //marginBorder,该Border就是用的这个margin来作它的Insets的 - //BueatyEye LNF中推荐实践是:抛弃margin的概念(省的混淆),直接使用border(在其上直接给于insets)即可 - putInsets("CheckBoxMenuItem.margin", 0, 0, 0, 0); - putInsets("RadioButtonMenuItem.margin", 0, 0, 0, 0);//iuir); - putInsets("Menu.margin", 0, 0, 0, 0);//windows lnf中默认是2,2,2,2 - putInsets("MenuItem.margin", 0, 0, 0, 0);//windows lnf中默认是2,2,2,2 -// putInsets("MenuItem.margin", 10, 2, 10, 2);//top=2,left=2,bottom=2,right=2 - - //请注意:上面的margin已经全设为0了哦 - putBorder("Menu.border", 4, 3, 5, 3);//javax.swing.plaf.basic.BasicBorders.MarginBorder; - putBorder("MenuItem.border", 4, 3, 5, 3);// - putBorder("CheckBoxMenuItem.border", 4, 3, 5, 3);//javax.swing.plaf.basic.BasicBorders.MarginBorder; - putBorder("RadioButtonMenuItem.border", 4, 3, 5, 3);// -// putBorder("PopupMenu.border", 20, 10, 20, 10); // - //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> margin和border设置 END - - //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 颜色设置 START - put("MenuBar.foreground", BeautyEyeLNFHelper.commonForegroundColor); - put("RadioButtonMenuItem.foreground", BeautyEyeLNFHelper.commonForegroundColor); - put("Menu.foreground", BeautyEyeLNFHelper.commonForegroundColor); - put("PopupMenu.foreground", BeautyEyeLNFHelper.commonForegroundColor); - put("CheckBoxMenuItem.foreground", BeautyEyeLNFHelper.commonForegroundColor); - put("MenuItem.foreground", BeautyEyeLNFHelper.commonForegroundColor); - - put("MenuBar.background", BeautyEyeLNFHelper.commonBackgroundColor); - put("Menu.background", new Color(255, 255, 255, 0)); - put("PopupMenu.background", new Color(255, 255, 255, 0)); - - put("RadioButtonMenuItem.disabledForeground", BeautyEyeLNFHelper.commonDisabledForegroundColor); - put("MenuItem.disabledForeground", BeautyEyeLNFHelper.commonDisabledForegroundColor); - - put("Menu.selectionForeground", BeautyEyeLNFHelper.commonSelectionForegroundColor); - put("MenuItem.selectionForeground", BeautyEyeLNFHelper.commonSelectionForegroundColor); - put("CheckBoxMenuItem.selectionForeground", BeautyEyeLNFHelper.commonSelectionForegroundColor); - put("RadioButtonMenuItem.selectionForeground", BeautyEyeLNFHelper.commonSelectionForegroundColor); - - put("Menu.selectionBackground", BeautyEyeLNFHelper.commonSelectionBackgroundColor); - put("MenuItem.selectionBackground", BeautyEyeLNFHelper.commonSelectionBackgroundColor); - put("CheckBoxMenuItem.selectionBackground", BeautyEyeLNFHelper.commonSelectionBackgroundColor); - put("RadioButtonMenuItem.selectionBackground", BeautyEyeLNFHelper.commonSelectionBackgroundColor); - //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 颜色设置 END - - //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 杂项设置 START - //本值意味着弹出菜单X轴方向上的偏移量,因BE LNF中加了边框,所以要负偏移以便得弹出菜单主体能与菜单项对齐好看一些 - put("Menu.menuPopupOffsetX", -3);//win lnf中默认值是0 - //本值意味着弹出菜单Y轴方向上的偏移量,因BE LNF中加了边框,所以要负偏移以便得弹出菜单主体能与菜单项对齐好看一些 - put("Menu.menuPopupOffsetY", 2);///win lnf默认值是0 - //本值意味着弹出子菜单X轴方向上的偏移量,因BE LNF中加了边框,所以要负偏移以便得弹出菜单主体能与菜单项对齐好看一些 - put("Menu.submenuPopupOffsetX", -2);///win lnf默认值是-4 - //本值意味着弹出子菜单Y轴方向上的偏移量,因BE LNF中加了边框,所以要负偏移以便得弹出菜单主体能与菜单项对齐好看一些 - put("Menu.submenuPopupOffsetY", -5);///win lnf默认值是-3 - - //多选按钮式的菜单项选中与否的图标实现设定 - UIManager.put("CheckBoxMenuItem.checkIcon", new BECheckBoxMenuItemUI.CheckBoxMenuItemIcon()); - //单选按钮式的菜单项选中与否的图标实现设定 - UIManager.put("RadioButtonMenuItem.checkIcon", new BERadioButtonMenuItemUI.RadioButtonMenuItemIcon()); - - //加高菜单条,提升视觉体验 - put("MenuBar.height", 30);//default value is 19 - - //此属性true时表明禁用的菜单项将不能被rover,否则有rover效果(BE LNF中 - //因禁用状态rover时的字体色影响视觉效果,所以干脆禁用之,逻辑上也很合理) - put("MenuItem.disabledAreNavigable", false);// windows lnf中默认是true - //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 杂项设置 END - - //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> UI实现类设置 START - put("MenuBarUI", BEMenuBarUI.class); - put("MenuUI", BEMenuUI.class); - put("MenuItemUI", BEMenuItemUI.class); - put("RadioButtonMenuItemUI", BERadioButtonMenuItemUI.class); - put("CheckBoxMenuItemUI", BECheckBoxMenuItemUI.class); - put("PopupMenuSeparatorUI", BEPopupMenuSeparatorUI.class); - put("PopupMenuUI", BEPopupMenuUI.class); - //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> UI实现类设置 END - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/popup/TranslucentPopupFactory.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/popup/TranslucentPopupFactory.java deleted file mode 100644 index 0314b3c34..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/popup/TranslucentPopupFactory.java +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * TranslucentPopupFactory.java at 2015-2-1 20:25:38, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.popup; - -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.Frame; -import java.awt.Graphics; -import java.awt.GraphicsDevice; -import java.awt.GraphicsEnvironment; -import java.awt.Window; - -import javax.swing.BorderFactory; -import javax.swing.JComponent; -import javax.swing.JMenuItem; -import javax.swing.JPopupMenu; -import javax.swing.JScrollPane; -import javax.swing.JToolTip; -import javax.swing.JWindow; -import javax.swing.MenuElement; -import javax.swing.Popup; -import javax.swing.PopupFactory; -import javax.swing.SwingUtilities; -import javax.swing.plaf.basic.BasicComboPopup; -import org.jackhuang.hmcl.laf.scroll.BEScrollBarUI; -import org.jackhuang.hmcl.laf.utils.Icon9Factory; -import org.jackhuang.hmcl.laf.utils.WindowTranslucencyHelper; -import org.jackhuang.hmcl.laf.widget.ImageBgPanel; - -/** - * 自定义透明背景的弹出工厂实现类. - * - * 本类其实与Swing的UI机制关联不大,完全可以独立于L&F使用。 - * - * @author Jack Jiang(jb2011@163.com), 2012-05-18 - * @version 1.0 - */ -public class TranslucentPopupFactory extends PopupFactory { - - private static final Icon9Factory ICON_9 = new Icon9Factory("popup"); - - @Override - public Popup getPopup(Component owner, Component contents, int x, int y) - throws IllegalArgumentException { - // A more complete implementation would cache and reuse popups - return new TranslucentPopup(owner, contents, x, y); - } - - /** - * 透明背景的Popup实现类. - *

    - * 本类的大部分代码都是原封不动地参考自Popup父类(JDK版本是1.6_u18版的源码),因为Popup父 - * 类中的多数方法都是使用的包内可见性,所以没法直接继承,像这种不允许第3方自行扩展的情 - * 况在Swing标准包里比较少见,不知原作者是出于何种考虑,无疑这样的类实现是相当的欠缺远 见性,但这种情况在LNF里很常见。 - */ - protected class TranslucentPopup extends Popup { - //copy all from parent class - - /** - * The Component representing the Popup. - */ - private Component component; - - //copy all from parent class - /** - * Creates a Popup for the Component owner - * containing the Component contents. owner is - * used to determine which Window the new - * Popup will parent the Component the - * Popup creates to. A null owner implies - * there is no valid parent. x and y specify - * the preferred initial location to place the Popup at. - * Based on screen size, or other paramaters, the Popup may - * not display at x and y. - * - * @param owner Component mouse coordinates are relative to, may be null - * @param contents Contents of the Popup - * @param x Initial x screen coordinate - * @param y Initial y screen coordinate - */ - public TranslucentPopup(Component owner, Component contents, int x, - int y) { - this(); - if (contents == null) - throw new IllegalArgumentException("Contents must be non-null"); - - reset(owner, contents, x, y); - } - - /** - * Creates a Popup. This is provided for subclasses. - */ - public TranslucentPopup() { - } - - /** - *

    - * Makes the Popup visible. If the Popup is - * currently visible, this has no effect.
    - * - * 本方法的结构完全copy自父类方法,但添加了component.repaint();的调用. - *

    - */ - @Override - public void show() { - Component c = getComponent(); - - if (c != null) { - c.setVisible(true); - - //此行代码必须要有,否则可能是因为没有关闭双缓存(getRootPane(). - //setUseTrueDoubleBuffering(false),这个方法是包内可见,所以本类里没法调用 - //),而导致界面没有重绘:要不就是UI没有绘出来,要不就是出现空白的popup(没有内容组件) - c.repaint(); - } - } - - /** - * Hides and disposes of the Popup. Once a - * Popup has been disposed you should no longer invoke - * methods on it. A disposed Popup may be - * reclaimed and later used based on the PopupFactory. As - * such, if you invoke methods on a disposed - * Popup, indeterminate behavior will result. - */ - @Override - public void hide() { - Component c = getComponent(); - - if (c instanceof JWindow) { - c.hide(); - ((JWindow) c).getContentPane().removeAll(); - } - dispose(); - } - - /** - * Frees any resources the Popup may be holding onto. - */ - protected void dispose() { - Component c = getComponent(); - Window window = SwingUtilities.getWindowAncestor(c); - - if (c instanceof JWindow) - ((Window) c).dispose(); - // If our parent is a DefaultFrame, we need to dispose it, too. - if (window instanceof DefaultFrame) - window.dispose(); - } - - /** - *

    - * Resets the Popup to an initial state.
    - * - * 本方法的结构完全copy自父类方法,但进行中包括:窗口透明、用图片实现背景填充等在内的修改. - *

    - * - * @param owner the owner - * @param contents the contents - * @param ownerX the owner x - * @param ownerY the owner y - */ - protected void reset(Component owner, Component contents, int ownerX, int ownerY) { - if (getComponent() == null) - component = createComponent(owner); - - Component c = getComponent(); - if (c instanceof JWindow) { - JWindow w = (JWindow) getComponent(); - w.setLocation(ownerX, ownerY); - - boolean isTooltip = ((JComponent) contents instanceof JToolTip); - //如果contents是BasicComboPopup或其子类那当前就应该是用于下拉框的弹出列表罗 - boolean isComboBoxPopup = (contents instanceof BasicComboPopup); - - if (WindowTranslucencyHelper.isTranslucencySupported()) { - try { - //每像素透明 - WindowTranslucencyHelper.setWindowOpaque(w, false); - //内容组件半透明 - w.setOpacity(isTooltip ? 1.0f : isComboBoxPopup ? 0.95f : 0.95f);//0.85f : 0.95f);//0.8f : 0.95f); - } catch(Exception e) { - // ignore - } - } - -// component.getContentPane().add(contents, BorderLayout.CENTER); -// contents.invalidate(); -// if (component.isVisible()) -// { -// // Do not call pack() if window is not visible to -// // avoid early native peer creation -// pack(); -// } - //图片填充背景的内容面板 - ImageBgPanel imageContentPane = new ImageBgPanel().setN9( - isTooltip - ? ICON_9.get("tooltip") - : isComboBoxPopup - ?//是下拉框列表则使一个跟JScrollPane一样的背景图,好看! - BEScrollBarUI.ICON_9.get("scroll_pane_border") - : ICON_9.get("popup") - ); - imageContentPane.setLayout(new BorderLayout()); - imageContentPane.add(contents, BorderLayout.CENTER); - - //为每一个要显示的真正的内容组件加一个空border,目的 - //是使得父面板的背景图片显示的效果更好 - if (contents instanceof JComponent) { - ((JComponent) contents).setOpaque(false); - //* ######################################### Bug FIX START ############################################ - //* 关于Java Bug 6683775,地址:http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6683775,解决于java1.6.0_14 - //* - //* 【Bug说明】: - //* 在java1.6.0_14之前(当然是>=u10版),在设置窗口透明时,即调用方法 - //* AWTUtilities.setWindowOpaque(component, false)使得窗口透明后,再设置位于 - //* Windows上的第1层JPanel也为透明时(即JPanel.setOpaque(false)),则会出现类似 - //* 于很久以前给JPanel设置一个半透明色(即alpha小于255)时出现的不正确paint情况, - //* 直接导致下拉框的弹出列表ui刷新出现混乱(根本就不能即时刷新,ui一塌糊涂)的情况. - //* - //* 【java1.6.0_14版前如何解决】: - //* 该Bug 6683775在被官方解决前,怎么才能避免出现ui刷新 - //* 混乱呢?Bug 6683775上的官方回复给出了解决方案:JPanel.setDoubleBuffered(false)(官方认为 - //* 光设置JPanel.setOpaque(false)是不够的,还得取消双缓冲才行),不过好在官方在u14及以后的版本中 - //* 彻底解决了这个问题. - //* - //* 【目前BeautyEye L&F中如何解决?】: - //* 为了能在该Bug被解决前(即java小于java1.6.0_14版)BE LNF也能正常运行,只能稍微牺牲一点ui性能, - //* 按官方解决方法——“JPanel.setDoubleBuffered(false)”来解决吧. - ((JComponent) contents).setDoubleBuffered(false); - //* ######################################### Bug FIX END ############################################## - - ((JComponent) contents).setBorder( - isTooltip - ? BorderFactory.createEmptyBorder(6, 8, 12, 12)//6,8,12,8) - : isComboBoxPopup ? BorderFactory.createEmptyBorder(6, 4, 6, 4) - : BorderFactory.createEmptyBorder(5, 3, 6, 3));//10,2,10,4));//5,5,20,5)); - } - - //如果BasicComboPopup即表明它应该是ComboBox里的弹出菜单,为了使N9 - //背景能被完整展现出来则要把combox弹出列表所在的JScrollPane进行透明设置 - //,因为如果它不被透明设置则本pop的NP图背景就只能显示边缘,而且底边有一点被 - //挡住,不好看(另注:本JScrollPane在BEComboBoxUI中被设置了一个EmptyBorder,所以 - //没有在ScrollPaneUI中定认的那个ScrollBorder哦,没有那个border的目的就是为了在些使用 - //pop的背景撒) - if (isComboBoxPopup) { - Component[] cs = ((BasicComboPopup) contents).getComponents(); - //该JScrollPane就是contents的第一层子组件里 - if (cs != null && cs.length > 0) - //遍历并找出它 - for (Component com : cs) - if (com instanceof JScrollPane) - ((JScrollPane) com).setOpaque(false); - } //如果是菜单父宿主则所有JMenuItem也设置透明,jb2011 2009-08-29 - else if (contents instanceof JPopupMenu) { - MenuElement[] mes = ((JPopupMenu) contents).getSubElements(); - for (MenuElement me : mes) - if (me instanceof JMenuItem) - ((JMenuItem) me).setOpaque(false); - } - - // add the contents to the popup - w.setContentPane(imageContentPane); -// popupWindow.getContentPane().add(p, BorderLayout.CENTER); -// contents.invalidate(); - if (w.isVisible()) - // Do not call pack() if window is not visible to - // avoid early native peer creation - pack(); - } - } - - /** - * Causes the Popup to be sized to fit the preferred size - * of the Component it contains. - */ - protected void pack() { - Component c = getComponent(); - - if (c instanceof Window) - ((Window) c).pack(); - } - - /** - * Returns the Window to use as the parent of the - * Window created for the Popup. This creates - * a new DefaultFrame, if necessary. - * - * @param owner the owner - * @return the parent window - */ - protected Window getParentWindow(Component owner) { - Window window = null; - - if (owner instanceof Window) - window = (Window) owner; - else if (owner != null) - window = SwingUtilities.getWindowAncestor(owner); - if (window == null) - window = new DefaultFrame(); - return window; - } - - /** - * Creates the Component to use as the parent of the Popup. - * The default implementation creates a Window, subclasses - * should override. - * - * @param owner the owner - * @return the component - */ - protected Component createComponent(Component owner) { - if (GraphicsEnvironment.isHeadless()) - // Generally not useful, bail. - return null; - - return new HeavyWeightWindow(getParentWindow(owner)); - } - - /** - * Returns the Component returned from - * createComponent that will hold the Popup. - * - * @return the component - */ - protected Component getComponent() { - return component; - } - - /** - * Used if no valid Window ancestor of the supplied owner is found. - *

    - * PopupFactory uses this as a way to know when the Popup shouldn't be - * cached based on the Window. - */ - protected class DefaultFrame extends Frame { - } - - /** - * Component used to house window. - */ - protected class HeavyWeightWindow extends JWindow { - - /** - * Instantiates a new heavy weight window. - * - * @param parent the parent - */ - public HeavyWeightWindow(Window parent) { - super(parent); - // FIXME: 一个外国朋友用了后,在此项被设置成false的情况下,Popup里的JTextField不能编辑了! - setFocusableWindowState(true); - setName("###overrideRedirect###"); - // Popups are typically transient and most likely won't benefit - // from true double buffering. Turn it off here. -// getRootPane().setUseTrueDoubleBuffering(false);//本方法不能在包外被调用 - // Try to set "always-on-top" for the popup window. - // Applets usually don't have sufficient permissions to do it. - // In this case simply ignore the exception. - try { - setAlwaysOnTop(true); - } catch (SecurityException se) { - // setAlwaysOnTop is restricted, - // the exception is ignored - } - } - - @Override - public void update(Graphics g) { - paint(g); - } - - @Override - public void show() { - this.pack(); - super.show(); - } - } - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/popup/__UI__.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/popup/__UI__.java deleted file mode 100644 index d5ec5bc61..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/popup/__UI__.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * __UI__.java at 2015-2-1 20:25:40, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.popup; - -import javax.swing.PopupFactory; - -public class __UI__ { - - public static PopupFactory popupFactoryDIY = new TranslucentPopupFactory(); - - public static void uiImpl() { - PopupFactory.setSharedInstance(popupFactoryDIY); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/progress/BEProgressBarUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/progress/BEProgressBarUI.java deleted file mode 100644 index 202e1b10b..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/progress/BEProgressBarUI.java +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BEProgressBarUI.java at 2015-2-1 20:25:39, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.progress; - -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Insets; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.geom.AffineTransform; - -import javax.swing.JComponent; -import javax.swing.JProgressBar; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; -import javax.swing.plaf.basic.BasicProgressBarUI; -import org.jackhuang.hmcl.laf.utils.Icon9Factory; -import org.jackhuang.hmcl.laf.utils.MySwingUtilities2; -import org.jackhuang.hmcl.laf.utils.WinUtils; -import org.jb2011.ninepatch4j.NinePatch; - -/** - * 进度条的UI实现类. - * - * @author Jack Jiang(jb2011@163.com) - * @see com.sun.java.swing.plaf.windows.WindowsProgressBarUI - */ -public class BEProgressBarUI extends BasicProgressBarUI - implements org.jackhuang.hmcl.laf.BeautyEyeLNFHelper.__UseParentPaintSurported { - - private static final Icon9Factory ICON_9 = new Icon9Factory("progress_bar"); - - public static ComponentUI createUI(JComponent x) { - return new BEProgressBarUI(); - } - - /** - * 是否使用父类的绘制实现方法,true表示是. - *

    - * 因为在BE LNF中,进度条和背景都是使用N9图,没法通过设置JProgressBar的背景色和前景 - * 色来控制进度条的颜色,本方法的目的就是当用户设置了进度条的Background或Foreground 时告之本实现类不使用BE - * LNF中默认的N9图填充绘制而改用父类中的方法(父类中的方法 就可以支持颜色的设置罗,只是丑点,但总归是能适应用户的需求场景要求,其实用户完全可以 - * 通过JProgressBar.setUI(new MetalProgressBar())方式来自定义进度的UI哦). - * - * @return true, if is use parent paint - */ - @Override - public boolean isUseParentPaint() { - return progressBar != null - && (!(progressBar.getForeground() instanceof UIResource) - || !(progressBar.getBackground() instanceof UIResource)); - } - - /** - * 绘制普通进度条的方法. - * All purpose paint method that should do the right thing for almost all - * linear, determinate progress bars. By setting a few values in the - * defaults table, things should work just fine to paint your progress bar. - * Naturally, override this if you are making a circular or semi-circular - * progress bar. - * - * @param g the g - * @param c the c - * @see #paintIndeterminate - * @see javax.swing.plaf.basic.BasicProgressBarUI#paintDeterminate(java.awt.Graphics, javax.swing.JComponent) - * @since 1.4 - */ - @Override - protected void paintDeterminate(Graphics g, JComponent c) { - if (!(g instanceof Graphics2D)) - return; - - //* 如果用户作了自定义颜色设置则使用父类方法来实现绘制,否则BE LNF中没法支持这些设置哦 - if (isUseParentPaint()) { - super.paintDeterminate(g, c); - return; - } - - Insets b = progressBar.getInsets(); // area for border - int barRectWidth = progressBar.getWidth() - (b.right + b.left); - int barRectHeight = progressBar.getHeight() - (b.top + b.bottom); - - //* add by Jack Jiang 2012-06-20 START - //绘制进度条的背景 - paintProgressBarBgImpl(progressBar.getOrientation() == JProgressBar.HORIZONTAL, - g, b, barRectWidth, barRectHeight); - //* add by Jack Jiang 2012-06-20 END - - if (barRectWidth <= 0 || barRectHeight <= 0) - return; - - int amountFull = getAmountFull(b, barRectWidth, barRectHeight); - Graphics2D g2 = (Graphics2D) g; - g2.setColor(progressBar.getForeground());//在BE LNF中本属性设置目前没有意义哦,因为用的都是n9图 - - if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) - if (WinUtils.isLeftToRight(c)) - paintProgressBarContentImpl(true, g, b.left, b.top, - amountFull, barRectHeight, -1); - // TODO 以下代码未经测试 - else - paintProgressBarContentImpl(true, g, barRectWidth + b.left, b.top, - barRectWidth + b.left - amountFull, barRectHeight, -1); - else // VERTICAL - paintProgressBarContentImpl(false, g, b.left, b.top + barRectHeight - amountFull, - barRectWidth, amountFull, barRectHeight); - - // Deal with possible text painting - if (progressBar.isStringPainted()) - paintString(g, b.left, b.top, barRectWidth, barRectHeight, amountFull, b); - } - - //绘制无穷进度条的方法 - /** - * All purpose paint method that should do the right thing for all linear - * bouncing-box progress bars. Override this if you are making another kind - * of progress bar. - * - * @param g the g - * @param c the c - * @see #paintDeterminate - * @since 1.4 - * @see javax.swing.plaf.basic.BasicProgressBarUI#paintIndeterminate(java.awt.Graphics, javax.swing.JComponent) - */ - @Override - protected void paintIndeterminate(Graphics g, JComponent c) { - if (!(g instanceof Graphics2D)) - return; - - //* 如果用户作了自定义颜色设置则使用父类方法来实现绘制,否则BE LNF中没法支持这些设置哦 - if (isUseParentPaint()) { - super.paintIndeterminate(g, c); - return; - } - - Insets b = progressBar.getInsets(); // area for border - int barRectWidth = progressBar.getWidth() - (b.right + b.left); - int barRectHeight = progressBar.getHeight() - (b.top + b.bottom); - - if (barRectWidth <= 0 || barRectHeight <= 0) - return; - - //* add by Jack Jiang 2012-06-20 START - //绘制进度条的背景 - paintProgressBarBgImpl(progressBar.getOrientation() == JProgressBar.HORIZONTAL, g, b, barRectWidth, barRectHeight); - //* add by Jack Jiang 2012-06-20 END - - Graphics2D g2 = (Graphics2D) g; - - // Paint the bouncing box. - boxRect = getBox(boxRect); - if (boxRect != null) { - g2.setColor(progressBar.getForeground());//BE LNF中,目前本颜色设置无意义哦,因使用的都是N9图 - //由Jack Jiang修改 -// g2.fillRect(boxRect.x, boxRect.y, boxRect.width, boxRect.height); - paintProgressBarContentImpl(progressBar.getOrientation() == JProgressBar.HORIZONTAL, - g, boxRect.x, boxRect.y, boxRect.width, boxRect.height, boxRect.height);//水平时最后一个参数无意义哦 - } - - // Deal with possible text painting - if (progressBar.isStringPainted()) - if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) - paintString(g2, b.left, b.top, barRectWidth, barRectHeight, boxRect.x, boxRect.width, b); - else - paintString(g2, b.left, b.top, barRectWidth, barRectHeight, boxRect.y, boxRect.height, b); - } - - //* add by Jack Jiang - /** - * 进度条当前值的绘制实现方法. - * - * @param isHorizontal true表示水平进度条,否则表示垂直进度条 - * @param g the g - * @param x the x - * @param y the y - * @param amountFull the amount full - * @param barContentRectHeight the bar content rect height - * @param barSumHeightForVertival 本参数只在垂直进度条时有意义,目的是为了在当前值很 - * 小的情况下为了达到N9图最小绘制高度时,作修正时需要 - */ - protected void paintProgressBarContentImpl(boolean isHorizontal, - Graphics g, int x, int y, int amountFull, int barContentRectHeight, - int barSumHeightForVertival) { - NinePatch np; - - //当前的进度条内容.9.png图片的边缘非填充部分是17像素,如果要 - //填充的总宽度小于此则会出现NinePatch填充算法无法解决的填充, - //以下判断将在总宽度小于此值时强制设置成最小宽度 - final int n9min = 17;// TODO 14是相关于.9.png图片的最小填充宽度的,最好用常量实现 - if (isHorizontal) { - //如果最小填充长度小于n9图的最小长度最设定为最小长度,否则N9的填充会很难看哦 - if (amountFull > 0 && amountFull < n9min) - amountFull = n9min; - np = ICON_9.get("green"); - } else { - //如果最小填充长度小于n9图的最小长度最设定为最小长度,否则N9的填充会很难看哦 - if (barContentRectHeight > 0 && barContentRectHeight < n9min) { - y = barSumHeightForVertival - n9min; - barContentRectHeight = n9min; - } - np = ICON_9.get("blur_vertical"); - } - //开始绘制N9图 - np.draw((Graphics2D) g, x, y, amountFull, barContentRectHeight); - } - - //* add by Jack Jiang - /** - * 进度条背景填充实现方法. - * - * @param isHorizontal the is horizontal - * @param g the g - * @param b the b - * @param barRectWidth the bar rect width - * @param barRectHeight the bar rect height - */ - protected void paintProgressBarBgImpl(boolean isHorizontal, Graphics g, Insets b, int barRectWidth, int barRectHeight) { - ICON_9.getWithHorizontal("bg", isHorizontal) - .draw((Graphics2D) g, b.left, b.top, barRectWidth, barRectHeight); - } - - /** - * Paints the progress string. - * - * @param g Graphics used for drawing. - * @param x x location of bounding box - * @param y y location of bounding box - * @param width width of bounding box - * @param height height of bounding box - * @param fillStart start location, in x or y depending on orientation, of - * the filled portion of the progress bar. - * @param amountFull size of the fill region, either width or height - * depending upon orientation. - * @param b Insets of the progress bar. - */ - private void paintString(Graphics g, int x, int y, int width, int height, - int fillStart, int amountFull, Insets b) { - if (!(g instanceof Graphics2D)) - return; - - Graphics2D g2 = (Graphics2D) g; - String progressString = progressBar.getString(); - g2.setFont(progressBar.getFont()); - Point renderLocation = getStringPlacement(g2, progressString, - x, y, width, height); - Rectangle oldClip = g2.getClipBounds(); - - if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) { - g2.setColor(getSelectionBackground()); - MySwingUtilities2.drawString(progressBar, g2, progressString, - renderLocation.x, renderLocation.y); - g2.setColor(getSelectionForeground()); - g2.clipRect(fillStart, y, amountFull, height); - MySwingUtilities2.drawString(progressBar, g2, progressString, - renderLocation.x, renderLocation.y); - } else { // VERTICAL - g2.setColor(getSelectionBackground()); - AffineTransform rotate - = AffineTransform.getRotateInstance(Math.PI / 2); - g2.setFont(progressBar.getFont().deriveFont(rotate)); - renderLocation = getStringPlacement(g2, progressString, - x, y, width, height); - MySwingUtilities2.drawString(progressBar, g2, progressString, - renderLocation.x, renderLocation.y); - g2.setColor(getSelectionForeground()); - g2.clipRect(x, fillStart, width, amountFull); - MySwingUtilities2.drawString(progressBar, g2, progressString, - renderLocation.x, renderLocation.y); - } - g2.setClip(oldClip); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/progress/__UI__.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/progress/__UI__.java deleted file mode 100644 index a9ca47644..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/progress/__UI__.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * __UI__.java at 2015-2-1 20:25:36, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.progress; - -import javax.swing.BorderFactory; - -import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper; -import org.jackhuang.hmcl.laf.utils.UI; - -public class __UI__ extends UI { - - public static void uiImpl() { - put("ProgressBar.background", BeautyEyeLNFHelper.commonBackgroundColor); - put("ProgressBar.selectionForeground", BeautyEyeLNFHelper.commonBackgroundColor); - - // 此属性决定水平进度条的默认最小大小:15是相关于.9.png图片的最小填充 - // 高度或长度的(小于此高度则NinePatch算法无法解决而很难看) - putDim("ProgressBar.horizontalSize", 146, 15); // 默认是146,12 - putDim("ProgressBar.verticalSize", 15, 146); // 默认是12,146 - put("ProgressBar.border", BorderFactory.createEmptyBorder(0, 0, 0, 0)); - put("ProgressBarUI", BEProgressBarUI.class); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/radio$cb_btn/BECheckBoxUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/radio$cb_btn/BECheckBoxUI.java deleted file mode 100644 index 9f605a5b6..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/radio$cb_btn/BECheckBoxUI.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.laf.radio$cb_btn; - -import javax.swing.AbstractButton; -import javax.swing.JComponent; -import javax.swing.LookAndFeel; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.metal.MetalCheckBoxUI; - -/** - * - * @author huang - */ -public class BECheckBoxUI extends MetalCheckBoxUI { - - private static final BECheckBoxUI INSTANCE = new BECheckBoxUI(); - - public static ComponentUI createUI(JComponent b) { - return INSTANCE; - } - - @Override - public void installDefaults(AbstractButton b) { - super.installDefaults(b); - - LookAndFeel.installProperty(b, "opaque", false); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/radio$cb_btn/BERadioButtonUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/radio$cb_btn/BERadioButtonUI.java deleted file mode 100644 index 04a1fd9f0..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/radio$cb_btn/BERadioButtonUI.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.laf.radio$cb_btn; - -import javax.swing.AbstractButton; -import javax.swing.JComponent; -import javax.swing.LookAndFeel; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.metal.MetalRadioButtonUI; - -/** - * - * @author huang - */ -public class BERadioButtonUI extends MetalRadioButtonUI { - - private static final BERadioButtonUI INSTANCE = new BERadioButtonUI(); - - public static ComponentUI createUI(JComponent b) { - return INSTANCE; - } - - @Override - public void installDefaults(AbstractButton b) { - super.installDefaults(b); - - LookAndFeel.installProperty(b, "opaque", false); - } - -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/radio$cb_btn/__UI__.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/radio$cb_btn/__UI__.java deleted file mode 100644 index 041065baa..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/radio$cb_btn/__UI__.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * __UI__.java at 2015-2-1 20:25:36, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.radio$cb_btn; - -import java.awt.Component; -import java.awt.Graphics; -import java.io.Serializable; - -import javax.swing.ButtonModel; -import javax.swing.Icon; -import javax.swing.JToggleButton; -import javax.swing.UIManager; - -import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper; -import org.jackhuang.hmcl.laf.utils.IconFactory; -import org.jackhuang.hmcl.laf.utils.UI; - -public class __UI__ extends UI { - private static final IconFactory RADIO = new IconFactory("radio"); - private static final IconFactory CHECK = new IconFactory("check"); - - public static void uiImpl() { - - putInsets("CheckBox.margin", 4, 3, 4, 3); - put("CheckBox.foreground", BeautyEyeLNFHelper.commonForegroundColor); - put("CheckBox.background", BeautyEyeLNFHelper.commonBackgroundColor); - put("CheckBoxUI", BECheckBoxUI.class); - - putInsets("RadioButton.margin", 4, 3, 4, 3); // 2, 2, 2, 2 - put("RadioButton.foreground", BeautyEyeLNFHelper.commonForegroundColor); - put("RadioButton.background", BeautyEyeLNFHelper.commonBackgroundColor); - put("RadioButtonUI", BERadioButtonUI.class); - - UIManager.put("RadioButton.icon", new IconFactoryIcon(RADIO)); - UIManager.put("CheckBox.icon", new IconFactoryIcon(CHECK)); - - // 衬距设定 - putInsets("RadioButton.margin", 1, 1, 1, 1); // 2, 2, 2, 2 - putInsets("CheckBox.margin", 1, 1, 1, 1); // 2, 2, 2, 2 - } - - /** - * @see com.sun.java.swing.plaf.windows.WindowsIconFactory - * @see com.sun.java.swing.plaf.windows.WindowsIconFactory.CheckBoxIcon - * @see com.sun.java.swing.plaf.windows.WindowsIconFactory.RadioBoxIcon - */ - private static class IconFactoryIcon implements Icon, Serializable { - IconFactory icon; - - public IconFactoryIcon(IconFactory icon) { - this.icon = icon; - } - - @Override - public void paintIcon(Component c, Graphics g, int x, int y) { - JToggleButton cb = (JToggleButton) c; - ButtonModel model = cb.getModel(); - - g.drawImage(icon.get(model.isSelected() ? "" : "unchecked", - model.isEnabled() ? (model.isPressed() ? "pressed" : (model.isRollover() ? "over" : "normal")) : "disabled").getImage(), - x, y, null); - } - - @Override - public int getIconWidth() { - return 24; - } - - @Override - public int getIconHeight() { - return 24; - } - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/resources/beautyeye.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/resources/beautyeye.java deleted file mode 100644 index 0b7bf6804..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/resources/beautyeye.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * beautyeye.java at 2015-2-1 20:25:40, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.resources; - -import java.util.ListResourceBundle; - -public final class beautyeye extends ListResourceBundle -{ - protected final Object[][] getContents() - { - return new Object[][] { - { "BETitlePane.setupButtonText", "Setup " }, - { "BETitlePane.titleMenuToolTipText", "Window operation." }, - { "BETitlePane.closeButtonToolTipext", "Close" }, - { "BETitlePane.iconifyButtonToolTipText", "Minimize" }, - { "BETitlePane.toggleButtonToolTipText", "Maximize" }, - { "BETitlePane.iconifyButtonText", "Minimize(N)" }, - { "BETitlePane.restoreButtonText", "Restore(R)" }, - { "BETitlePane.maximizeButtonText", "Maximized(X)" }, - }; - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/resources/beautyeye_zh_CN.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/resources/beautyeye_zh_CN.java deleted file mode 100644 index c0d39955f..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/resources/beautyeye_zh_CN.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * beautyeye_zh_CN.java at 2015-2-1 20:25:41, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.resources; - -import java.util.ListResourceBundle; - -public final class beautyeye_zh_CN extends ListResourceBundle -{ - protected final Object[][] getContents() - { - return new Object[][] { - { "BETitlePane.setupButtonText", "\u8bbe\u7f6e " }, - { "BETitlePane.titleMenuToolTipText", "\u7a97\u53e3\u76f8\u5173\u64cd\u4f5c." }, - { "BETitlePane.closeButtonToolTipext", "\u5173\u95ed" }, - { "BETitlePane.iconifyButtonToolTipText", "\u6700\u5c0f\u5316" }, - { "BETitlePane.toggleButtonToolTipText", "\u6700\u5927\u5316" }, - { "BETitlePane.iconifyButtonText", "\u6700\u5c0f\u5316(N)" }, - { "BETitlePane.restoreButtonText", "\u8fd8\u539f(R)" }, - { "BETitlePane.maximizeButtonText", "\u6700\u5927\u5316(X)" }, - }; - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/scroll/BEScrollBarUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/scroll/BEScrollBarUI.java deleted file mode 100644 index c6cf2d12b..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/scroll/BEScrollBarUI.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BEScrollBarUI.java at 2015-2-1 20:25:36, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.scroll; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Rectangle; - -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.JScrollBar; -import javax.swing.UIManager; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicArrowButton; -import javax.swing.plaf.basic.BasicScrollBarUI; -import org.jackhuang.hmcl.laf.button.BEButtonUI; -import org.jackhuang.hmcl.laf.utils.AnimationController; - -import org.jackhuang.hmcl.laf.utils.Icon9Factory; -import org.jackhuang.hmcl.laf.utils.Skin; -import org.jackhuang.hmcl.laf.utils.TMSchema; -import org.jackhuang.hmcl.laf.utils.TMSchema.State; -import org.jackhuang.hmcl.util.ui.GraphicsUtils; - -/** - * 本类是滚动条的UI实现. - * - * 注:滚动条的两端箭头按钮参考自xp主题的实现,未作修改,因而这部分逻辑代码与WindowsScrollBarUI中是完全一样的. - * - * @author Jack Jiang(jb2011@163.com), 2009-09-01 - * @version 1.0 - * @see com.sun.java.swing.plaf.windows.WindowsScrollBarUI - */ -public class BEScrollBarUI extends BasicScrollBarUI implements Skin { - - public static final Icon9Factory ICON_9 = new Icon9Factory("scroll_bar"); - - public static ComponentUI createUI(JComponent c) { - return new BEScrollBarUI(); - } - - @Override - protected JButton createDecreaseButton(int orientation) { - return new BEArrowButton(orientation, - UIManager.getColor("ScrollBar.thumb"), - UIManager.getColor("ScrollBar.thumbShadow"), - UIManager.getColor("ScrollBar.thumbDarkShadow"), - UIManager.getColor("ScrollBar.thumbHighlight")); - } - - @Override - protected JButton createIncreaseButton(int orientation) { - return new BEArrowButton(orientation, - UIManager.getColor("ScrollBar.thumb"), - UIManager.getColor("ScrollBar.thumbShadow"), - UIManager.getColor("ScrollBar.thumbDarkShadow"), - UIManager.getColor("ScrollBar.thumbHighlight")); - } - - /** - * WindowsArrowButton is used for the buttons to position the document - * up/down. It differs from BasicArrowButton in that the preferred size is - * always a square. - */ - protected class BEArrowButton extends BasicArrowButton implements Skin { - - /** - * Instantiates a new windows arrow button. - * - * @param direction the direction - * @param background the background - * @param shadow the shadow - * @param darkShadow the dark shadow - * @param highlight the highlight - */ - public BEArrowButton(int direction, Color background, Color shadow, - Color darkShadow, Color highlight) { - super(direction, background, shadow, darkShadow, highlight); - } - - public BEArrowButton(int direction) { - super(direction); - } - - @Override - public void paint(Graphics g) { - Graphics2D g2 = (Graphics2D) g; - switch (direction) { - case NORTH: - break; - case SOUTH: - g2.translate(getWidth(), getHeight()); - g2.rotate(Math.PI); - break; - case WEST: - g2.translate(0, getHeight()); - g2.rotate(-Math.PI / 2); - break; - case EAST: - g2.translate(getWidth(), 0); - g2.rotate(Math.PI / 2); - break; - } - AnimationController.paintSkin(this, this, g, 0, 0, getWidth(), getHeight(), BEButtonUI.getXPButtonState(this)); - } - - @Override - public Dimension getPreferredSize() { - int size = 12; - if (scrollbar != null) { - switch (scrollbar.getOrientation()) { - case JScrollBar.VERTICAL: - size = scrollbar.getWidth(); - break; - case JScrollBar.HORIZONTAL: - size = scrollbar.getHeight(); - break; - } - size = Math.max(size, 5); - } - return new Dimension(size, size); - } - - @Override - public void paintSkinRaw(Graphics g, int x, int y, int w, int h, TMSchema.State state) { - ICON_9.get("arrow", state.toString()).draw((Graphics2D) g, x, y, w, h); - } - - @Override - public TMSchema.Part getPart(JComponent c) { - return TMSchema.Part.SBP_ARROWBTN; - } - } - //----------------------------------------------------------------------------------- END - - //----------------------------------------------------------------------------------- 本次改造的主体部分 - @Override - protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds) { - if (c == null || g == null) - return; - Color color = GraphicsUtils.getWebColor("#F2F2F2"); - g.setColor(color); - g.fillRect(trackBounds.x, trackBounds.y, trackBounds.width, trackBounds.height); - } - - /** - * 滚动条绘制. - */ - @Override - protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) { - if (thumbBounds.isEmpty() || !scrollbar.isEnabled()) - return; - AnimationController.paintSkin(c, this, g, thumbBounds.x, thumbBounds.y, thumbBounds.width, thumbBounds.height, isDragging ? State.PRESSED : isThumbRollover() ? State.ROLLOVER : State.NORMAL); - } - - @Override - public void paintSkinRaw(Graphics g, int x, int y, int w, int h, State state) { - Color color = GraphicsUtils.getWebColor(state == State.PRESSED ? "#616161" : state == State.ROLLOVER ? "#919191" : "#C2C2C2"); - g.setColor(color); - g.fillRect(x, y, w, h); - } - - @Override - public TMSchema.Part getPart(JComponent c) { - return TMSchema.Part.SBP_THUMBBTNHORZ; - } - - //----------------------------------------------------------------------------------- END - -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/scroll/BEScrollPaneUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/scroll/BEScrollPaneUI.java deleted file mode 100644 index 68cf9065a..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/scroll/BEScrollPaneUI.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BEScrollPaneUI.java at 2015-2-1 20:25:39, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.scroll; - -import javax.swing.JComponent; -import javax.swing.JScrollPane; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicScrollPaneUI; - -/** - * 滚动面板的UI实现类. - * - * @author Jack Jiang(jb2011@163.com - */ -public class BEScrollPaneUI extends BasicScrollPaneUI { - - public static ComponentUI createUI(JComponent x) { - return new BEScrollPaneUI(); - } - - @Override - protected void installDefaults(JScrollPane scrollpane) { - super.installDefaults(scrollpane); - -// /* ~~注:ScrollPane.opaque这个属性是jb2011自已加的,目的是控制滚动面板及其Viewport的透明性 */ -// scrollpane.setOpaque(UIManager.getBoolean("ScrollPane.opaque")); -// scrollpane.getViewport().setOpaque(UIManager.getBoolean("ScrollPane.opaque")); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/scroll/ScrollPaneBorder.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/scroll/ScrollPaneBorder.java deleted file mode 100644 index 7d98de7ab..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/scroll/ScrollPaneBorder.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * ScrollPaneBorder.java at 2015-2-1 20:25:41, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.scroll; - -import java.awt.Insets; - -import org.jackhuang.hmcl.laf.widget.border.NinePatchBorder; - -/** - * 滚动面板默认Border的实现类. - * - * @author Jack Jiang(jb2011@163.com) - */ -public class ScrollPaneBorder extends NinePatchBorder { - - public ScrollPaneBorder() { - super(new Insets(2, 2, 2, 2), - BEScrollBarUI.ICON_9.get("scroll_pane_border")); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/scroll/__UI__.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/scroll/__UI__.java deleted file mode 100644 index 34f57e3b0..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/scroll/__UI__.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * __UI__.java at 2015-2-1 20:25:36, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.scroll; - -import java.awt.Color; - -import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper; -import org.jackhuang.hmcl.laf.utils.UI; - -public class __UI__ extends UI { - - public static void uiImpl() { - //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 视口的相关ui值设定 - put("Viewport.background", BeautyEyeLNFHelper.commonBackgroundColor); - put("Viewport.foreground", BeautyEyeLNFHelper.commonForegroundColor); - - //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> JScrollPane的相关ui值设定 - put("ScrollPane.border", new ScrollPaneBorder()); // 0, 0, 0, 0 - // 不能设置alpha通道小于255的透明颜色,否则会出现无法重paint的问题 - put("ScrollPane.background", Color.white);//cc)); - put("ScrollPane.foreground", BeautyEyeLNFHelper.commonForegroundColor); - put("ScrollPaneUI", BEScrollPaneUI.class); - - //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> JScrollPane的滚动条相关ui值设定 - put("ScrollBar.thumb", BeautyEyeLNFHelper.commonBackgroundColor); - put("ScrollBar.foreground", BeautyEyeLNFHelper.commonForegroundColor); - putColor("ScrollBar.background", 250, 250, 250); - putColor("ScrollBar.trackForeground", 250, 250, 250); - putColor("scrollbar", 250, 250, 250); - put("ScrollBar.width", 12); - put("ScrollBarUI", BEScrollBarUI.class); - -// /* ~~注:这个属性是jb2011自已加的,目的是控制滚动面板及其Viewport的透明性 */ -// //设置成透明是为了让BE LNF中它的N9图实现的border能展现出图片背景来,好看一点 -// put("ScrollPane.opaque", false); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/separator/BEPanelUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/separator/BEPanelUI.java deleted file mode 100644 index 49e6313af..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/separator/BEPanelUI.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.laf.separator; - -import javax.swing.JComponent; -import javax.swing.JPanel; -import javax.swing.LookAndFeel; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.PanelUI; -import javax.swing.plaf.basic.BasicPanelUI; - -/** - * - * @author huang - */ -public class BEPanelUI extends BasicPanelUI { - - // Shared UI object - private static PanelUI panelUI; - - public static ComponentUI createUI(JComponent c) { - if (panelUI == null) - panelUI = new BEPanelUI(); - return panelUI; - } - - @Override - protected void installDefaults(JPanel p) { - LookAndFeel.installProperty(p, "opaque", false); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/separator/BESeparatorUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/separator/BESeparatorUI.java deleted file mode 100644 index 8286f18ae..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/separator/BESeparatorUI.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BESeparatorUI.java at 2015-2-1 20:25:39, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.separator; - -import java.awt.BasicStroke; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Stroke; - -import javax.swing.JComponent; -import javax.swing.JSeparator; -import javax.swing.LookAndFeel; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicSeparatorUI; - -/** - * Separator外观实现类. - *

    - * - * @author Jack Jiang(jb2011@163.com), 2012-11-05 - * @version 1.0 - */ -public class BESeparatorUI extends BasicSeparatorUI { - - public static ComponentUI createUI(JComponent c) { - return new BESeparatorUI(); - } - - @Override - protected void installDefaults(JSeparator s) { - LookAndFeel.installColors(s, "Separator.background", "Separator.foreground"); - LookAndFeel.installProperty(s, "opaque", Boolean.FALSE); - } - - @Override - public void paint(Graphics g, JComponent c) { - //** 绘制border的底线 - //虚线样式 - Stroke oldStroke = ((Graphics2D) g).getStroke(); - Stroke sroke = new BasicStroke(1, BasicStroke.CAP_BUTT, - BasicStroke.JOIN_BEVEL, 0, new float[] { 2, 2 }, 0);//实线,空白 - ((Graphics2D) g).setStroke(sroke);// -// super.paint(g, c); - - Dimension s = c.getSize(); - - if (((JSeparator) c).getOrientation() == JSeparator.VERTICAL) { -// System.out.println("c.getBackground()c.getBackground()c.getBackground()="+c.getBackground()); - g.setColor(c.getForeground()); - g.drawLine(0, 0, 0, s.height); - - g.setColor(c.getBackground()); - g.drawLine(1, 0, 1, s.height); - } else // HORIZONTAL - { - g.setColor(c.getForeground()); - g.drawLine(0, 0, s.width, 0); - - g.setColor(c.getBackground()); - g.drawLine(0, 1, s.width, 1); - } - - ((Graphics2D) g).setStroke(oldStroke); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/separator/__UI__.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/separator/__UI__.java deleted file mode 100644 index fa8bc46b4..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/separator/__UI__.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * __UI__.java at 2015-2-1 20:25:36, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.separator; - -import java.awt.Color; - -import javax.swing.UIManager; - -import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper; -import org.jackhuang.hmcl.laf.utils.IconFactory; -import org.jackhuang.hmcl.laf.utils.UI; -import org.jackhuang.hmcl.laf.widget.border.BEDashedRoundRecBorder; - -/** - * 各种未归类的UI属性设置实现类. 本类中的各种属性日后可能会移入相应的各独立组件的UI包. - * - * @author Jack Jiang - * @version 1.1 - */ -public class __UI__ extends UI { - - private static final IconFactory ICON = new IconFactory("option_pane"); - - public static void uiImpl() { - put("control", BeautyEyeLNFHelper.commonBackgroundColor); - put("Separator.foreground", new Color(180, 180, 180)); - put("ToolTip.foreground", BeautyEyeLNFHelper.commonForegroundColor); - - put("Separator.background", Color.white); - put("Panel.foreground", BeautyEyeLNFHelper.commonForegroundColor); - put("Panel.background", BeautyEyeLNFHelper.commonBackgroundColor); - put("PanelUI", BEPanelUI.class); - - put("Label.foreground", BeautyEyeLNFHelper.commonForegroundColor); - //put("Label.background", BeautyEyeLNFHelper.commonBackgroundColor); - - put("ColorChooser.foreground", BeautyEyeLNFHelper.commonForegroundColor); - put("ColorChooser.background", BeautyEyeLNFHelper.commonBackgroundColor); - put("ColorChooser.swatchesDefaultRecentColor", BeautyEyeLNFHelper.commonBackgroundColor); - - putColor("TitledBorder.titleColor", 58, 135, 173); // TitleBorder的标题颜色 - // TitledBorder的默认border实现(windows LNF中默认是圆色灰色实线距形) - put("TitledBorder.border", new BEDashedRoundRecBorder(BeautyEyeLNFHelper.commonFocusedBorderColor)); - -// UIManager.put("OptionPaneUI",org.jb2011.lnf.windows2.ch3.NLOptionPaneUI.class.getName()); - //** Ui里的实现逻辑:此属性为true时将导致JOptionPane里的各按钮按BasicOptionPaneUI里设定的Insets进行 - //** UI展现:当按钮数<=2时使用的Insets=new Instes(2,8,2,8),否则使用new Instes(2,4,2,4), - //** 这样的逻辑下,BeautyEye L&F实现里会使得按钮高度缩小而不好看,所以要关闭此属性 - put("OptionPane.setButtonMargin", false); - put("OptionPane.foreground", BeautyEyeLNFHelper.commonForegroundColor); - put("OptionPane.background", BeautyEyeLNFHelper.commonBackgroundColor); - UIManager.put("OptionPane.questionIcon", ICON.get("question")); - UIManager.put("OptionPane.warningIcon", ICON.get("warn")); - UIManager.put("OptionPane.informationIcon", ICON.get("info")); - UIManager.put("OptionPane.errorIcon", ICON.get("error")); - - put("SeparatorUI", BESeparatorUI.class); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/slider/BESliderUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/slider/BESliderUI.java deleted file mode 100644 index c53f88efb..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/slider/BESliderUI.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BESliderUI.java at 2015-2-1 20:25:38, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.slider; - -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Rectangle; - -import javax.swing.JComponent; -import javax.swing.JSlider; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicSliderUI; - -import org.jackhuang.hmcl.laf.BEUtils; -import org.jackhuang.hmcl.laf.utils.Icon9Factory; -import org.jackhuang.hmcl.laf.utils.IconFactory; - -/** - * JSlider的ui实现类. - * - * @author Jack Jiang(jb2011@163.com) - * @version 1.0 - * - * @see com.sun.java.swing.plaf.windows.WindowsComboBoxUI - */ -public class BESliderUI extends BasicSliderUI { - - private static final Icon9Factory ICON_9 = new Icon9Factory("slider_track"); - private static final IconFactory ICON = new IconFactory("slider"); - - /** - * 水平Slider的Thumb高度. - */ - protected final int THUMB_HEIGHT_HORIZONAL = 7;// TODO 此属性可提取为Ui属性,方便以后配置(大小应是NP图的最小高度,最大值得看JSlider的高度了) - - /** - * 垂直Slider的Thumb宽度. - */ - protected final int THUMB_WIDTH_VERTICAL = 7;// TODO 此属性可提取为Ui属性,方便以后配置(大小应是NP图的最小高度,最大值得看JSlider的高度了) - - public BESliderUI(JSlider b) { - super(b); - } - - public static ComponentUI createUI(JComponent b) { - return new BESliderUI((JSlider) b); - } - - @Override - public void paintTrack(Graphics g) { - Rectangle trackBounds = trackRect; - if (slider.getOrientation() == JSlider.HORIZONTAL) { - int cy = (trackBounds.height / 2) - 2; - int cw = trackBounds.width; - - g.translate(trackBounds.x, trackBounds.y + cy); - - //轨道背景 - ICON_9.getWithEnabled("", slider.isEnabled()) - .draw((Graphics2D) g, 0, 0, cw, THUMB_HEIGHT_HORIZONAL); - //轨道(填充到当前刻度值处) - ICON_9.getWithEnabled("foreground", slider.isEnabled()) - .draw((Graphics2D) g, 0, 0, thumbRect.x, THUMB_HEIGHT_HORIZONAL); - g.translate(-trackBounds.x, -(trackBounds.y + cy)); - } else { - int cx = (trackBounds.width / 2) - 2; - int ch = trackBounds.height; - - g.translate(trackBounds.x + cx, trackBounds.y); - - //轨道背景 - ICON_9.getWithEnabled("vertical", slider.isEnabled()) - .draw((Graphics2D) g, 0, 0, THUMB_WIDTH_VERTICAL, ch); - //轨道(填充到当前刻度值处) - // TODO BUG:当前有个bug,即在SwingSets2演示中,当thumb高度较小时,轨道半圆形被画出,这可能父类中thumbRect中计算有部碮同,有时间再研究吧,官方以后版本或许能解决哦 - ICON_9.getWithEnabled("vertical_foreground", slider.isEnabled()) - .draw((Graphics2D) g, 0, thumbRect.y, THUMB_WIDTH_VERTICAL, ch - thumbRect.y); - - g.translate(-(trackBounds.x + cx), -trackBounds.y); - } - } - - @Override - public void paintFocus(Graphics g) { - g.setColor(getFocusColor()); - BEUtils.drawDashedRect(g, focusRect.x, focusRect.y, - focusRect.width, focusRect.height); - } - - /** - * {@inheritDoc} - * - * @see javax.swing.plaf.basic.BasicSliderUI#paintThumb(java.awt.Graphics) - */ - @Override - public void paintThumb(Graphics g) { - Rectangle knobBounds = thumbRect; - int w = knobBounds.width; - int h = knobBounds.height; - - g.translate(knobBounds.x, knobBounds.y); - if (slider.isEnabled()) - g.setColor(slider.getBackground()); - else - g.setColor(slider.getBackground().darker()); - - g.drawImage(ICON.get(isPaintNoTriangleThumb() ? "notriangle" : "", - slider.getOrientation() == JSlider.HORIZONTAL ? "" : "vertical", - slider.isEnabled() ? "" : "disabled").getImage(), 0, 0, null); - - g.translate(-knobBounds.x, -knobBounds.y); - } - - /** - * Checks if is paint no triangle thumb. - * 该thumb是否是无3角箭头的样式,true表示无3解箭头(即圆形thumb),false表示有3角箭头样式 - * - * @return true, if is paint no trangle thumb - */ - protected boolean isPaintNoTriangleThumb() { - Boolean paintThumbArrowShape = (Boolean) slider - .getClientProperty("Slider.paintThumbArrowShape"); - - //不绘制有箭头标识的thumb样式(即普通圆形thumb) - return !slider.getPaintTicks() && paintThumbArrowShape == null - || Boolean.FALSE.equals(paintThumbArrowShape); - } - - /** - * {@inheritDoc} - * - * @see javax.swing.plaf.basic.BasicSliderUI#getThumbSize() - */ - @Override - protected Dimension getThumbSize() { - boolean isPaintNoTrangle = isPaintNoTriangleThumb(); - - Dimension size = new Dimension(); - if (slider.getOrientation() == JSlider.VERTICAL) { - size.width = 17;//20; - size.height = isPaintNoTrangle ? 16 : 12;//14; - } else { - size.width = isPaintNoTrangle ? 16 : 12;//14; - size.height = 17;//20; - } - return size; - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/slider/__UI__.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/slider/__UI__.java deleted file mode 100644 index 4d096eeac..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/slider/__UI__.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * __UI__.java at 2015-2-1 20:25:39, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.slider; - -import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper; -import org.jackhuang.hmcl.laf.utils.UI; - -public class __UI__ extends UI { - - public static void uiImpl() { - put("Slider.background", BeautyEyeLNFHelper.commonBackgroundColor); - //JSlider的刻度线绘制颜色 - putColor("Slider.tickColor", 154, 154, 154); - put("Slider.foreground", BeautyEyeLNFHelper.commonForegroundColor); - //获得焦点时的insets -// putInsets("Slider.focusInsets", 2, 2, 7, 7); //父类中默认是 2, 2, 2, 2 - //获得焦点时的焦点边框颜色 - put("Slider.focus", BeautyEyeLNFHelper.commonFocusedBorderColor); //[r=113,g=111,b=100] - put("SliderUI", BESliderUI.class); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/spinner/BESpinnerUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/spinner/BESpinnerUI.java deleted file mode 100644 index 8df3f975a..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/spinner/BESpinnerUI.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BESpinnerUI.java at 2015-2-1 20:25:39, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.spinner; - -import java.awt.Component; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Graphics2D; - -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.UIManager; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicSpinnerUI; - -import org.jackhuang.hmcl.laf.spinner.BESpinnerUI.GlyphButton.Type; -import org.jackhuang.hmcl.laf.BEUtils; -import org.jackhuang.hmcl.laf.utils.Icon9Factory; - -/** - * JSPinner的UI实现类. - * - * @author Jack Jiang(jb2011@163.com) - * @version 1.0 - * @see com.sun.java.swing.plaf.windows.WindowsSpinnerUI - */ -public class BESpinnerUI extends BasicSpinnerUI { - - private static final Icon9Factory ICON_9 = new Icon9Factory("spinner"); - - public static ComponentUI createUI(JComponent c) { - return new BESpinnerUI(); - } - - @Override - protected JComponent createEditor() { - JComponent e = super.createEditor(); - e.setOpaque(false); - - //参见JSpinner.NumberEditor,super.createEditor()返回值就是它的父类 - //(是一个JPanel实例),它是由一个FormatttedTextField及其父JPanel组成 - //的,所以设置完 e.setOpaque(false),还要把它的子FormatttedTextField - //设置成透明,其实它的子只有1个,它里为了适用未来的扩展假设它有很多子, - Component[] childs = e.getComponents(); - BEUtils.componentsOpaque(childs, false); - - return e; - } - - /** - * Paint. - * - * @param g the g - * @param c the c {@inheritDoc} - */ - @Override - public void paint(Graphics g, JComponent c) { - if (spinner != null) - ICON_9.getWithEnabled("", spinner.isEnabled()). - draw((Graphics2D) g, 0, 0, c.getWidth(), c.getHeight()); - super.paint(g, c); - } - - @Override - protected Component createPreviousButton() { - JButton xpButton = new GlyphButton(spinner, Type.down); - Dimension size = UIManager.getDimension("Spinner.arrowButtonSize"); - xpButton.setPreferredSize(size); - xpButton.setRequestFocusEnabled(false); - installPreviousButtonListeners(xpButton); - return xpButton; - } - - @Override - protected Component createNextButton() { - JButton xpButton = new GlyphButton(spinner, Type.up); - Dimension size = UIManager.getDimension("Spinner.arrowButtonSize"); - xpButton.setPreferredSize(size); - xpButton.setRequestFocusEnabled(false); - installNextButtonListeners(xpButton); - return xpButton; - } - - /** - * @see com.sun.java.swing.plaf.windows.XPStyle.GlyphButton - */ - static class GlyphButton extends JButton { - - private Type type = null; - - /** - * The Enum Type. - */ - public enum Type { - down, - up - } - - /** - * Instantiates a new glyph button. - * - * @param parent the parent - * @param type the type - */ - public GlyphButton(Component parent, Type type) { - this.type = type; - setBorder(null); - setContentAreaFilled(false); - setMinimumSize(new Dimension(5, 5)); - setPreferredSize(new Dimension(16, 16)); - setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE)); - } - - @Override - public boolean isFocusTraversable() { - return false; - } - - @Override - public void paintComponent(Graphics g) { - ICON_9.get("button_" + type.name(), !isEnabled() || getModel().isPressed() ? "pressed" : ""). - draw((Graphics2D) g, 0, 0, getWidth(), getHeight()); - } - - @Override - protected void paintBorder(Graphics g) { - } - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/spinner/__UI__.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/spinner/__UI__.java deleted file mode 100644 index 3a496f5ff..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/spinner/__UI__.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * __UI__.java at 2015-2-1 20:25:37, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.spinner; - -import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper; -import org.jackhuang.hmcl.laf.utils.UI; - -public class __UI__ extends UI { - - public static void uiImpl() { - put("Spinner.background", BeautyEyeLNFHelper.commonBackgroundColor); - put("Spinner.foreground", BeautyEyeLNFHelper.commonForegroundColor); - put("SpinnerUI", BESpinnerUI.class); - - //Spinner组件的边框 - putBorder("Spinner.border", 5, 5, 10, 5); // 3, 3, 3, 3 - //Spinner组件的2个箭头按钮的内衬距 - putInsets("Spinner.arrowButtonInsets", 1, 0, 2, 2); // 1, 1, 1, 1 - //Spinner组件的2个箭头按钮的默认大小 - putDim("Spinner.arrowButtonSize", 17, 9); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/split/BESplitPaneDivider.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/split/BESplitPaneDivider.java deleted file mode 100644 index e6719b924..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/split/BESplitPaneDivider.java +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BESplitPaneDivider.java at 2015-2-1 20:25:40, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.split; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Cursor; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Stroke; - -import javax.swing.JButton; -import javax.swing.JSplitPane; -import javax.swing.UIManager; -import javax.swing.border.Border; -import javax.swing.plaf.basic.BasicSplitPaneDivider; -import javax.swing.plaf.basic.BasicSplitPaneUI; - -import org.jackhuang.hmcl.laf.BEUtils; -import org.jackhuang.hmcl.laf.utils.Icon9Factory; - -/** - * 分栏面板上的分隔线实现类. - *

    - * TODO 两个Touch按钮的位置等都是可以定制的,目前没有更好的美化灵感,以后可以再深入优先。 - * - * @author Jack Jiang(jb2011@163.com), 2012-07-13 - * @version 1.0 - */ -public class BESplitPaneDivider extends BasicSplitPaneDivider { - - private static final Icon9Factory ICON_9 = new Icon9Factory("split_touch"); - - private final int oneTouchSize; - - /** - * TODO 本常量可以做成UIManager属性以便未来使用者进行配置哦. - */ - protected final Color TOUCH_BUTTON_COLOR = new Color(58, 135, 173); - - /** - * 在水平SplitePane状态下,中间触碰装饰区装饰按钮的宽度. - */ - protected final static int TOUCH_DECRATED_BUTTON_W = 5;//* TODO 本常量可以做成UIManager属性以便未来使用者进行配置哦 - - /** - * 在水平SplitePane状态下,中间触碰装饰区装饰按钮的高度. - */ - protected final static int TOUCH_DECRATED_BUTTON_H = 30;//* TODO 本常量可以做成UIManager属性以便未来使用者进行配置哦 - - /** - * 分隔条线直线的颜色. - */ - protected final static Color TOUCH_DECRATED_BUTTON_COLOR = new Color(180, 180, 180);//* TODO 本颜色常量可以做成UIManager属性以便未来使用者进行配置哦 - - /** - * 分隔条线直线的高亮颜色(用来形成高对比度的立体效果) . - */ - protected final static Color TOUCH_DECRATED_BUTTON_HILIGHT_COLOR = Color.white;//* TODO 本颜色常量可以做成UIManager属性以便未来使用者进行配置哦 - - public BESplitPaneDivider(BasicSplitPaneUI ui) { - super(ui); - oneTouchSize = UIManager.getInt("SplitPane.oneTouchButtonSize", ui.getSplitPane().getLocale()); - } - - @Override - public void paint(Graphics g) { - Color bgColor = (splitPane.hasFocus()) - ? UIManager.getColor("SplitPane.shadow") : getBackground(); - Dimension size = getSize(); - Graphics2D g2 = ((Graphics2D) g); - BEUtils.setAntiAliasing((Graphics2D) g, true); -// g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, -// RenderingHints.VALUE_ANTIALIAS_ON); - if (bgColor != null) { - int orient = this.splitPane.getOrientation(); - if (orient == JSplitPane.HORIZONTAL_SPLIT) { - int halfWidth = size.width / 2; - int halfHeight = size.height / 2; - - //------------------------先水平居中画隔条竖线 - //虚线样式 - Stroke oldStroke = ((Graphics2D) g).getStroke(); - Stroke sroke = new BasicStroke(1, BasicStroke.CAP_BUTT, - BasicStroke.JOIN_BEVEL, 0, new float[] { 2, 2 }, 0);//实线,空白 - ((Graphics2D) g).setStroke(sroke); - - g.setColor(TOUCH_DECRATED_BUTTON_COLOR);//bgColor); -// g.fillRect(0, 0, size.width, size.height); - g.drawLine(halfWidth + 0, 0, halfWidth + 0, size.height); - //在竖线右边再画一个高对比度的竖线从而形成立体效果 - g.setColor(TOUCH_DECRATED_BUTTON_HILIGHT_COLOR); - g.drawLine(halfWidth + 1, 0, halfWidth + 1, size.height); - - ((Graphics2D) g).setStroke(oldStroke); - - //------------------------再填充触碰装饰区 - int decratedButton_w = TOUCH_DECRATED_BUTTON_W; - int decratedButton_h = TOUCH_DECRATED_BUTTON_H;//18; - int diverTouchStartX = halfWidth - decratedButton_w / 2; - ICON_9.get("bg1") - .draw((Graphics2D) g, diverTouchStartX, halfHeight - decratedButton_h / 2, - decratedButton_w, decratedButton_h); - } else { - int halfHeight = size.height / 2; - int halfWidth = size.width / 2; - - //------------------------先垂直居中画分隔条横线 - //虚线样式 - Stroke oldStroke = ((Graphics2D) g).getStroke(); - Stroke sroke = new BasicStroke(1, BasicStroke.CAP_BUTT, - BasicStroke.JOIN_BEVEL, 0, new float[] { 2, 2 }, 0);//实线,空白 - ((Graphics2D) g).setStroke(sroke); - - g.setColor(TOUCH_DECRATED_BUTTON_COLOR);//bgColor); -// g.fillRect(0, 0, size.width, size.height); - g.drawLine(0, halfHeight + 0, size.width, halfHeight + 0); - //在竖线下边再画一个高对比度的横线从而形成立体效果 - g.setColor(TOUCH_DECRATED_BUTTON_HILIGHT_COLOR); - g.drawLine(0, halfHeight + 1, size.width, halfHeight + 1); - - ((Graphics2D) g).setStroke(oldStroke); - - //------------------------再填充触碰装饰区 - int decratedButton_w = TOUCH_DECRATED_BUTTON_W; - int decratedButton_h = TOUCH_DECRATED_BUTTON_H;//18; - int diverTouchStartY = halfHeight - decratedButton_w / 2; - ICON_9.get("bg1") - .draw((Graphics2D) g, halfWidth - decratedButton_h, diverTouchStartY, - decratedButton_h, decratedButton_w); - } -// g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, -// RenderingHints.VALUE_ANTIALIAS_OFF); - BEUtils.setAntiAliasing((Graphics2D) g, false); - } - - super.paint(g); - } - - /** - * Creates and return an instance of JButton that can be used to collapse - * the left component in the split pane. - * - * 因父类方法继承重用设计不佳,此处只能全部拷过来代码,再行修改。 - * 至2012-07-13:本方法只作了关于箭头按钮的填充颜色的改变。 - * - * @return the j button - * @see javax.swing.plaf.basic.BasicSplitPaneDivider#createLeftOneTouchButton() - */ - @Override - protected JButton createLeftOneTouchButton() { - JButton b = new JButton() { - @Override - public void setBorder(Border b) { - } - - @Override - public void paint(Graphics g) { - if (splitPane != null) { - int[] xs = new int[3]; - int[] ys = new int[3]; - int blockSize; - - // Fill the background first ... - g.setColor(this.getBackground()); - g.fillRect(0, 0, this.getWidth(), this.getHeight()); - - // ... then draw the arrow. - g.setColor(TOUCH_BUTTON_COLOR);//Color.black); - - //* 开启反走样 - BEUtils.setAntiAliasing((Graphics2D) g, true); - - if (orientation == JSplitPane.VERTICAL_SPLIT) { - blockSize = Math.min(getHeight(), oneTouchSize); - xs[0] = blockSize; - xs[1] = 0; - xs[2] = blockSize << 1; - ys[0] = 0; - ys[1] = ys[2] = blockSize; - g.drawPolygon(xs, ys, 3); // Little trick to make the - // arrows of equal size - } else { - blockSize = Math.min(getWidth(), oneTouchSize); - xs[0] = xs[2] = blockSize; - xs[1] = 0; - ys[0] = 0; - ys[1] = blockSize; - ys[2] = blockSize << 1; - } - g.fillPolygon(xs, ys, 3); - - //* 关闭反走样 - BEUtils.setAntiAliasing((Graphics2D) g, false); - } - } - - // Don't want the button to participate in focus traversable. - @Override - public boolean isFocusTraversable() { - return false; - } - }; - b.setMinimumSize(new Dimension(oneTouchSize, oneTouchSize)); - b.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - b.setFocusPainted(false); - b.setBorderPainted(false); - b.setRequestFocusEnabled(false); - return b; - } - - /** - * Creates and return an instance of JButton that can be used to collapse - * the right component in the split pane. - * - * 因父类方法继承重用设计不佳,此处只能全部拷过来代码,再行修改。 - * 至2012-07-13:本方法只作了关于箭头按钮的填充颜色的改变。 - * - * @return the j button - * @see javax.swing.plaf.basic.BasicSplitPaneDivider#createRightOneTouchButton() - */ - @Override - protected JButton createRightOneTouchButton() { - JButton b = new JButton() { - @Override - public void setBorder(Border border) { - } - - @Override - public void paint(Graphics g) { - if (splitPane != null) { - int[] xs = new int[3]; - int[] ys = new int[3]; - int blockSize; - - // Fill the background first ... - g.setColor(this.getBackground()); - g.fillRect(0, 0, this.getWidth(), - this.getHeight()); - - //* 开启反走样 - BEUtils.setAntiAliasing((Graphics2D) g, true); - - // ... then draw the arrow. - if (orientation == JSplitPane.VERTICAL_SPLIT) { - blockSize = Math.min(getHeight(), oneTouchSize); - xs[0] = blockSize; - xs[1] = blockSize << 1; - xs[2] = 0; - ys[0] = blockSize; - ys[1] = ys[2] = 0; - } else { - blockSize = Math.min(getWidth(), oneTouchSize); - xs[0] = xs[2] = 0; - xs[1] = blockSize; - ys[0] = 0; - ys[1] = blockSize; - ys[2] = blockSize << 1; - } - - g.setColor(TOUCH_BUTTON_COLOR);//Color.black); - - g.fillPolygon(xs, ys, 3); - - //* 关闭反走样 - BEUtils.setAntiAliasing((Graphics2D) g, false); - } - } - - // Don't want the button to participate in focus traversable. - @Override - public boolean isFocusTraversable() { - return false; - } - }; - b.setMinimumSize(new Dimension(oneTouchSize, oneTouchSize)); - b.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - b.setFocusPainted(false); - b.setBorderPainted(false); - b.setRequestFocusEnabled(false); - return b; - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/split/BESplitPaneUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/split/BESplitPaneUI.java deleted file mode 100644 index 9ea484fcd..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/split/BESplitPaneUI.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BESplitPaneUI.java at 2015-2-1 20:25:40, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.split; - -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicSplitPaneDivider; -import javax.swing.plaf.basic.BasicSplitPaneUI; - -/** - * 分栏面板的UI实现. - * - * @author Jack Jiang(jb2011@163.com), 2012-07-10 - * @version 1.0 - */ -public class BESplitPaneUI extends BasicSplitPaneUI { - - public BESplitPaneUI() { - super(); - } - - public static ComponentUI createUI(JComponent x) { - return new BESplitPaneUI(); - } - - @Override - public BasicSplitPaneDivider createDefaultDivider() { - return new BESplitPaneDivider(this); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/split/SplitPaneDividerBorder.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/split/SplitPaneDividerBorder.java deleted file mode 100644 index ea8baf499..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/split/SplitPaneDividerBorder.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * SplitPaneDividerBorder.java at 2015-2-1 20:25:41, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.split; - -import java.awt.Component; -import java.awt.Graphics; -import java.awt.Insets; - -import javax.swing.JSplitPane; -import javax.swing.border.Border; -import javax.swing.plaf.UIResource; -import javax.swing.plaf.basic.BasicSplitPaneDivider; -import javax.swing.plaf.basic.BasicSplitPaneUI; - -/** - * 分隔条的border实现类. - *

    - * Draws the border around the divider in a splitpane. To get the appropriate - * effect, this needs to be used with a SplitPaneBorder. - * - * 主要修改了UI填充实现部分 - * - * @author Jack Jiang(jb2011@163.com) - * @see javax.swing.plaf.basic.BasicBorders - */ -public class SplitPaneDividerBorder implements Border, UIResource { -// javax.swing.plaf.basic.BasicBorders.SplitPaneDividerBorder -// private Color highlight; -// private Color shadow; - -// public SplitPaneDividerBorder(Color highlight, Color shadow) -// { -// this.highlight = highlight; -// this.shadow = shadow; -// } - @Override - public void paintBorder(Component c, Graphics g, int x, int y, int width, - int height) { - //在目前的视觉效果下不需要这个border的绘制哦 -// Graphics2D g2d = (Graphics2D) g; -// Component child; -// Rectangle cBounds; -// JSplitPane splitPane = ((BasicSplitPaneDivider) c).getBasicSplitPaneUI().getSplitPane(); -// Dimension size = c.getSize(); -// -// child = splitPane.getLeftComponent(); -// // This is needed for the space between the divider and end of -// // splitpane. -// g.setColor(c.getBackground()); -// g.drawRect(x, y, width - 1, height - 1); -// -// if (splitPane.getOrientation() == JSplitPane.HORIZONTAL_SPLIT) -// { -//// if (child != null) -//// { -//// g.setColor(shadow);//highlight); -//// g.drawLine(0, 0, 0, size.height); -//// } -//// child = splitPane.getRightComponent(); -//// if (child != null) -//// { -//// g.setColor(shadow); -//// g.drawLine(size.width - 1, 0, size.width - 1, size.height); -//// } -// } -// else -// { -//// if (child != null) -//// { -//// g.setColor(shadow);//highlight); -//// g.drawLine(0, 0, size.width, 0); -//// } -//// child = splitPane.getRightComponent(); -//// if (child != null) -//// { -//// g.setColor(shadow); -//// g.drawLine(0, size.height - 1, size.width,size.height - 1); -//// -//// } -// } - } - - @Override - public Insets getBorderInsets(Component c) { - Insets insets = new Insets(0, 0, 0, 0); - if (c instanceof BasicSplitPaneDivider) { - BasicSplitPaneUI bspui = ((BasicSplitPaneDivider) c) - .getBasicSplitPaneUI(); - - if (bspui != null) { - JSplitPane splitPane = bspui.getSplitPane(); - - if (splitPane != null) { - if (splitPane.getOrientation() == JSplitPane.HORIZONTAL_SPLIT) { - insets.top = insets.bottom = 0; - insets.left = insets.right = 1; - return insets; - } - // VERTICAL_SPLIT - insets.top = insets.bottom = 1; - insets.left = insets.right = 0; - return insets; - } - } - } - insets.top = insets.bottom = insets.left = insets.right = 1; - return insets; - } - - @Override - public boolean isBorderOpaque() { - return true; - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/split/__UI__.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/split/__UI__.java deleted file mode 100644 index 677fb1174..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/split/__UI__.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * __UI__.java at 2015-2-1 20:25:39, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.split; - -import org.jackhuang.hmcl.laf.utils.UI; - -public class __UI__ extends UI { - - public static void uiImpl() { - putColor("SplitPane.shadow", 200, 200, 200); // 本属性在BE LNF中暂时没用到 - //JSplitePane的默认背景色 - putColor("SplitPane.background", 250, 250, 250); // 238, 241, 243 - //JSplitePane的边框实现 - put("SplitPane.border", new org.jackhuang.hmcl.laf.scroll.ScrollPaneBorder());// 0, 0, 0, 0 - put("SplitPaneUI", BESplitPaneUI.class); - - //分隔条拖动时的颜色(说明:此值可以设置alpha通道以便达到半透明效果哦) - putColor("SplitPaneDivider.draggingColor", 0, 0, 0, 50); - //触碰按钮的默认大小 - // see javax.swing.plaf.basic.BasicSplitPaneDivider.ONE_TOUCH_SIZE = 6 - put("SplitPane.oneTouchButtonSize", 4); - //分隔条的默认大小 - put("SplitPane.dividerSize", 7); //drfault is 5 - //分隔条的边框实现 - put("SplitPaneDivider.border", new SplitPaneDividerBorder()); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/tab/BETabbedPaneUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/tab/BETabbedPaneUI.java deleted file mode 100644 index 59cdae10f..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/tab/BETabbedPaneUI.java +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BETabbedPaneUI.java at 2015-2-1 20:25:36, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.tab; - -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Rectangle; - -import javax.swing.JComponent; -import javax.swing.UIManager; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicTabbedPaneUI; - -/** - * JTabbedPane的UI实现类. - * - * @author Jack Jiang(jb2011@163.com), 2012-01-12 - * @version 1.1 - * @see com.sun.java.swing.plaf.windows.WindowsTabbedPaneUI - */ -public class BETabbedPaneUI extends BasicTabbedPaneUI { - - public static ComponentUI createUI(JComponent c) { - return new BETabbedPaneUI(); - } - - /** - * 本方法的重写copy自 com.sun.java.swing.plaf.windows.WindowsTabbedPaneUI,基本未修改代码 - * 重写父类方法实现rover状态下的tab的ui重绘(父类方法只是实现了rolloverTab 的设置,不步及ui重绘制,因Basic - * LNF中没有实现rover状态的ui样式) - * - * @see javax.swing.plaf.basic.BasicTabbedPaneUI#setRolloverTab(int) - */ - @Override - protected void setRolloverTab(int index) { - int oldRolloverTab = getRolloverTab(); - super.setRolloverTab(index); - Rectangle r1 = null; - Rectangle r2 = null; - if ((oldRolloverTab >= 0) && (oldRolloverTab < tabPane.getTabCount())) - r1 = getTabBounds(tabPane, oldRolloverTab); - if (index >= 0) - r2 = getTabBounds(tabPane, index); - if (r1 != null) - if (r2 != null) - tabPane.repaint(r1.union(r2)); - else - tabPane.repaint(r1); - else if (r2 != null) - tabPane.repaint(r2); - } - - /** - * this function draws the border around each tab note that this function - * does now draw the background of the tab. that is done elsewhere. - * - * @param g the g - * @param tabPlacement the tab placement - * @param tabIndex the tab index - * @param x the x - * @param y the y - * @param w the w - * @param h the h - * @param isSelected the is selected - * @see javax.swing.plaf.basic.BasicTabbedPaneUI#paintTabBorder(java.awt.Graphics, int, int, int, int, int, int, boolean) - */ - @Override - protected void paintTabBorder(Graphics g, int tabPlacement, - int tabIndex, int x, int y, int w, int h, boolean isSelected) { -// g.setColor(lightHighlight); -// Graphics2D g2d = (Graphics2D)g; - Graphics2D g2d = (Graphics2D) g.create(); - g2d.translate(x, y); - - //* 由Jack Jiang添加:true表示该tab当前正处于鼠标rover其上的状态 - //* this.getRolloverTab()的返回值由父类方法 setRolloverTab()设定并实现ui重绘的 - boolean isRover = (this.getRolloverTab() == tabIndex); - //* 由Jack Jiang添加:true表示该tab处于可用状态,否则表示处于禁用状态 - boolean isEnableAt = this.tabPane.isEnabledAt(tabIndex); - - switch (tabPlacement) { - case LEFT: - g2d.scale(-1.0, 1.0); - g2d.rotate(Math.toRadians(90.0)); - paintTabBorderImpl(g2d, isEnableAt, isSelected, isRover, 0, 0, h, w); - break; - case RIGHT: - g2d.translate(w, 0); - g2d.rotate(Math.toRadians(90.0)); - paintTabBorderImpl(g2d, isEnableAt, isSelected, isRover, 0, 0, h, w); - break; - case BOTTOM: - g2d.translate(0, h); - g2d.scale(-1.0, 1.0); - g2d.rotate(Math.toRadians(180.0)); - paintTabBorderImpl(g2d, isEnableAt, isSelected, isRover, 0, 0, w, h); - break; - case TOP: - default: - paintTabBorderImpl(g2d, isEnableAt, isSelected, isRover, 0, 0, w, h); - break; - } - } - //* paintTabBorder的绘制实现方法,2012-01-12日 BY Jack Jiang - - /** - * Paint tab border impl. - * - * @param g2d the g2d - * @param isEnableAt the is enable at - * @param isSelected the is selected - * @param isRover the is rover - * @param x the x - * @param y the y - * @param w the w - * @param h the h - */ - private void paintTabBorderImpl(Graphics2D g2d, boolean isEnableAt, boolean isSelected, - boolean isRover, int x, int y, int w, int h) { - //** modified by jb2011 改为NinePatch图片实现,Y + 1 的目的是使得选中时的底线能往下画一个像素(这样好看点) - if (isSelected) { - g2d.setColor(UIManager.getColor("TabbedPane.selectedForeground")); - g2d.fillRect(x, y + h - 1, w, 2); - } - //ICON_9.get("", isSelected ? "selected" : (isEnableAt && isRover ? "normal_rollover" : "normal")) - // .draw(g2d, x, y + 1, w, h); - } - - /** - * 重写本方法的目的仅是把原来的默认实线变成虚线而已哦 - * - * @see - * javax.swing.plaf.basic.BasicTabbedPaneUI#paintContentBorder(java.awt.Graphics, - * int, int) - */ - @Override - protected void paintContentBorder(Graphics g, int tabPlacement, int selectedIndex) { - /*//*** add by jb2011 2012-08-23 START - //虚线样式 - Stroke oldStroke = ((Graphics2D) g).getStroke(); - Stroke sroke = new BasicStroke(1, BasicStroke.CAP_BUTT, - BasicStroke.JOIN_BEVEL, 0, new float[] { 2, 2 }, 0);//实线,空白 - ((Graphics2D) g).setStroke(sroke); - //*** add by jb2011 2012-08-23 END -*/ - //调用父类默认实现 - super.paintContentBorder(g, tabPlacement, selectedIndex); -/* - //*** add by jb2011 2012-08-23 START - ((Graphics2D) g).setStroke(oldStroke); - //*** add by jb2011 2012-08-23 END*/ - } - - // - /** - * JTabbedPaneUI 内容面板的上边框绘制方法(默认就是内容面板上方的那条灰色). - * - * @see - * javax.swing.plaf.basic.BasicTabbedPaneUI#paintContentBorderTopEdge(java.awt.Graphics, - * int, int, int, int, int, int) - */ - @Override - protected void paintContentBorderTopEdge(Graphics g, int tabPlacement, - int selectedIndex, - int x, int y, int w, int h) { - //此模式下不绘制其它3条边框,视觉上好看一些 - if (tabPlacement == TOP) - //调用父类默认实现 - super.paintContentBorderTopEdge(g, tabPlacement, selectedIndex, x, y, w, h); - } - - /** - * JTabbedPaneUI 内容面板的左边框绘制方法. - * - * @see - * javax.swing.plaf.basic.BasicTabbedPaneUI#paintContentBorderLeftEdge(java.awt.Graphics, - * int, int, int, int, int, int) - */ - @Override - protected void paintContentBorderLeftEdge(Graphics g, int tabPlacement, - int selectedIndex, - int x, int y, int w, int h) { - //此模式下不绘制其它3条边框,视觉上好看一些 - if (tabPlacement == LEFT) - //调用父类默认实现 - super.paintContentBorderLeftEdge(g, tabPlacement, selectedIndex, x, y, w, h); - } - - /** - * JTabbedPaneUI 内容面板的底边框绘制方法. - * - * @see - * javax.swing.plaf.basic.BasicTabbedPaneUI#paintContentBorderBottomEdge(java.awt.Graphics, - * int, int, int, int, int, int) - */ - @Override - protected void paintContentBorderBottomEdge(Graphics g, int tabPlacement, - int selectedIndex, - int x, int y, int w, int h) { - //此模式下不绘制其它3条边框,视觉上好看一些 - if (tabPlacement == BOTTOM) - //调用父类默认实现 - super.paintContentBorderBottomEdge(g, tabPlacement, selectedIndex, x, y, w, h); - } - - /** - * JTabbedPaneUI 内容面板的右边框绘制方法. - * - * @see - * javax.swing.plaf.basic.BasicTabbedPaneUI#paintContentBorderRightEdge(java.awt.Graphics, - * int, int, int, int, int, int) - */ - @Override - protected void paintContentBorderRightEdge(Graphics g, int tabPlacement, - int selectedIndex, - int x, int y, int w, int h) { - //此模式下不绘制其它3条边框,视觉上好看一些 - if (tabPlacement == RIGHT) - //调用父类默认实现 - super.paintContentBorderRightEdge(g, tabPlacement, selectedIndex, x, y, w, h); - } - - /** - * 获得焦点时的虚线框绘制方法 - * - * @see - * javax.swing.plaf.basic.BasicTabbedPaneUI#paintFocusIndicator(java.awt.Graphics, - * int, java.awt.Rectangle[], int, java.awt.Rectangle, java.awt.Rectangle, - * boolean) - */ - @Override - protected void paintFocusIndicator(Graphics g, int tabPlacement, - Rectangle[] rects, int tabIndex, - Rectangle iconRect, Rectangle textRect, - boolean isSelected) { - } - - /** - * 重写并修改本方法的目的是修正tab上的文本显示Y坐标方向上的偏移,以便与背景协调 - * @see javax.swing.plaf.basic.BasicTabbedPaneUI#getTabLabelShiftY(int, int, boolean) - */ - @Override - protected int getTabLabelShiftY(int tabPlacement, int tabIndex, boolean isSelected) { - return 0; - /* - switch (tabPlacement) { - case BOTTOM: - return isSelected ? 1 : -1; - case LEFT: - case RIGHT: - return rects[tabIndex].height % 2; - case TOP: - default: - //** 由jb2011 2012-08-24修改:目的是使得选中时和未选中时的文本(包括图标 - //** 默认实现中之所以要产生它个效果是为了营造立体效果,而BE LNF中并不需要 - //** )不要往上或往下偏移的太多(太多则相当难看) -// nudge = isSelected? -1 : 1;//本行是原父类中的默认实现哦 - return -2;//由jb2011修改,目的是让文本相对现在的背景往上偏移一点,好看一些 - }*/ - } - - @Override - protected int getTabLabelShiftX(int tabPlacement, int tabIndex, boolean isSelected) { - Rectangle tabRect = rects[tabIndex]; - String propKey = "labelShift"; - int nudge = UIManager.getInt("TabbedPane." + propKey); - - switch (tabPlacement) { - case LEFT: - return nudge; - case RIGHT: - return -nudge; - case BOTTOM: - case TOP: - default: - return tabRect.width % 2; - } - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/tab/__UI__.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/tab/__UI__.java deleted file mode 100644 index 122c1f274..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/tab/__UI__.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * __UI__.java at 2015-2-1 20:25:40, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.tab; - -import java.awt.Font; -import javax.swing.UIManager; -import javax.swing.plaf.FontUIResource; -import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper; -import org.jackhuang.hmcl.laf.utils.UI; - -public class __UI__ extends UI { - - public static void uiImpl() { - FontUIResource f = (FontUIResource) UIManager.get("TabbedPane.font"); - UIManager.put("TabbedPane.font", new FontUIResource(new Font(f.getName(), f.getStyle(), 14))); - put("TabbedPane.background", BeautyEyeLNFHelper.commonBackgroundColor); - put("TabbedPane.foreground", BeautyEyeLNFHelper.commonForegroundColor); - put("TabbedPane.opaque", false); -// put("TabbedPane.tabRunOverlay", 2);//本属性无效果 - //false表示tab在边框虑线之上而不是重叠效果 - put("TabbedPane.tabsOverlapBorder", true); - put("TabbedPaneUI", BETabbedPaneUI.class); - //此属性决定了整个JTabbedPane区域的内衬 - putInsets("TabbedPane.tabAreaInsets", 3, 20, 2, 20);// 3, 2, 2, 2 - //此属性决定了tab与内容面板间的空白 - putInsets("TabbedPane.contentBorderInsets", 2, 0, 3, 0);// 2, 2, 3, 3 - //此参数将决定选中时的tab与左右相邻tab的重合度,正值表示重合、负值表示间隔(空白) - //* 注意与NP图的边缘留白配合使用能达到更灵活的效果 - putInsets("TabbedPane.selectedTabPadInsets", 0, 1, 0, 2);// 2, 2, 2, 1 - //此属性决定了JTabbedPane的tab标签的内衬 - putInsets("TabbedPane.tabInsets", 7, 7, 7, 7); - //获得焦点时的虚线框颜色 - putColor("TabbedPane.focus", 130, 130, 130); - //在BE LNF中,此颜色将决定TabPlacement=TOP和LEFT二种类型TabbedPane的内容面板那条虚线的颜色 - putColor("TabbedPane.highlight", 228, 228, 231);//new Color(200,200,200))); - //在BE LNF中,此颜色将决定TabPlacement=RIGHT和BOTTOM二种类型TabbedPane的内容面板那条虚线的颜色 - put("TabbedPane.shadow", BeautyEyeLNFHelper.commonFocusedBorderColor);//192,192,192); - //在BE LNF中,因TabPlacement=RIGHT和BOTTOM二种类型时,父类方法会默认再多画一条深色立体线而使得在BE LNF中 - //不好看,此颜色设置的目的就是让此立体阴影线与背景色一致从而看不出它的效果,进而不影响内容面板那条虚线在BE LNF中的视觉效果 - put("TabbedPane.darkShadow", BeautyEyeLNFHelper.commonBackgroundColor); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/table/BETableHeaderUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/table/BETableHeaderUI.java deleted file mode 100644 index 02659e6ac..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/table/BETableHeaderUI.java +++ /dev/null @@ -1,479 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BETableHeaderUI.java at 2015-2-1 20:25:38, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.table; - -import java.awt.Color; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.FontMetrics; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Insets; -import java.awt.Point; -import java.awt.Rectangle; -import java.io.Serializable; - -import javax.swing.Icon; -import javax.swing.JComponent; -import javax.swing.JLabel; -import javax.swing.JTable; -import javax.swing.RowSorter; -import javax.swing.SortOrder; -import javax.swing.SwingUtilities; -import javax.swing.UIManager; -import javax.swing.border.Border; -import javax.swing.border.EmptyBorder; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; -import javax.swing.plaf.basic.BasicTableHeaderUI; -import javax.swing.table.DefaultTableCellRenderer; -import javax.swing.table.JTableHeader; -import javax.swing.table.TableCellRenderer; -import org.jackhuang.hmcl.laf.utils.Icon9Factory; - -/** - * 表格头UI实现类。 - *

    - * 本类代码只能用于JDK1.6及以上版本,因JDK1.5及以下版本没法兼容本类中的很大一部分关键代码。 - * - * @author Jack Jiang(jb2011@163.com), 2011-03-28 - * @see com.sun.java.swing.plaf.windows.WindowsTableHeaderUI - */ -public class BETableHeaderUI extends BasicTableHeaderUI { - - protected static final Icon9Factory ICON_9 = new Icon9Factory("table"); - - private TableCellRenderer originalHeaderRenderer; - - public static ComponentUI createUI(JComponent h) { - return new BETableHeaderUI(); - } - - @Override - public void installUI(JComponent c) { - super.installUI(c); - originalHeaderRenderer = header.getDefaultRenderer(); - if (originalHeaderRenderer instanceof UIResource) - header.setDefaultRenderer(new XPDefaultRenderer()); - } - - @Override - public void uninstallUI(JComponent c) { - if (header.getDefaultRenderer() instanceof XPDefaultRenderer) - header.setDefaultRenderer(originalHeaderRenderer); - super.uninstallUI(c); - } - - @Override - protected void rolloverColumnUpdated(int oldColumn, int newColumn) { - header.repaint(header.getHeaderRect(oldColumn)); - header.repaint(header.getHeaderRect(newColumn)); - } - - //绘制头Ui内容,本方法提取出来是为了在ELineNumTable里也可以用到(它是进行了自定义Ui头实现) - /** - * Paint head cell. - * - * @param g the g - * @param headCellSize the head cell size - */ - public static void paintHeadCell(Graphics g, Dimension headCellSize) { - int w = headCellSize.width, h = headCellSize.height - 1; - -// Graphics2D g2 = (Graphics2D)g; -// //渐变背景 -// Paint oldp= g2.getPaint(); -// GradientPaint gp = new GradientPaint(0, 0 -// , new Color(250,250,250) -// , 0, h,new Color(241,241,241)); -// g2.setPaint(gp); -// g.fillRect(0, 0, w, h); -// //矩形区下1/2处非渐变填充(为了产生立体效果) -// g2.setPaint(oldp); -// -// //上下线条,突出立体感 -// g.setColor(new Color(215,215,215)); -// g.drawLine(0, 0, w, 0); -// g.setColor(new Color(249,250,249)); -// g.drawLine(0, h-1, w, h-1); -// g.setColor(new Color(209,209,209)); -// g.drawLine(0, h, w, h); - ICON_9.get("header_cell") - .draw((Graphics2D) g, 0, 0, w, h);//表头背景 - ICON_9.get("header_cell_separator") - .draw((Graphics2D) g, w - 2, 0, 4, h - 1);//表头右边的分隔线,h-1是为了让分隔线往上移一个像素,好看一点 - } - - public class DefaultTableCellHeaderRenderer extends DefaultTableCellRenderer - implements UIResource { - - private boolean horizontalTextPositionSet; - private Icon sortArrow; - private final EmptyIcon emptyIcon = new EmptyIcon(); - - public DefaultTableCellHeaderRenderer() { - setHorizontalAlignment(JLabel.CENTER); - } - - @Override - public void setHorizontalTextPosition(int textPosition) { - horizontalTextPositionSet = true; - super.setHorizontalTextPosition(textPosition); - } - - @Override - public Component getTableCellRendererComponent(JTable table, Object value, - boolean isSelected, boolean hasFocus, int row, int column) { - Icon sortIcon = null; - - boolean isPaintingForPrint = false; - - if (table != null) { - JTableHeader header = table.getTableHeader(); - if (header != null) { - Color fgColor = null; - Color bgColor = null; - if (hasFocus) { - fgColor = UIManager.getColor("TableHeader.focusCellForeground", this.getLocale()); - bgColor = UIManager.getColor("TableHeader.focusCellBackground", this.getLocale()); - } - if (fgColor == null) - fgColor = header.getForeground(); - if (bgColor == null) - bgColor = header.getBackground(); - setForeground(fgColor); - setBackground(bgColor); - - setFont(header.getFont()); - - isPaintingForPrint = header.isPaintingForPrint(); - } - - if (!isPaintingForPrint && table.getRowSorter() != null) { - if (!horizontalTextPositionSet) - // There is a row sorter, and the developer hasn't - // set a text position, change to leading. - setHorizontalTextPosition(JLabel.LEADING); - SortOrder sortOrder = getColumnSortOrder(table, column); - if (sortOrder != null) - switch (sortOrder) { - case ASCENDING: - sortIcon = UIManager.getIcon("Table.ascendingSortIcon", this.getLocale()); - break; - case DESCENDING: - sortIcon = UIManager.getIcon("Table.descendingSortIcon", this.getLocale()); - break; - case UNSORTED: - sortIcon = UIManager.getIcon("Table.naturalSortIcon", this.getLocale()); - break; - } - } - } - - setText(value == null ? "" : value.toString()); - setIcon(sortIcon); - sortArrow = sortIcon; - - Border border = null; - if (hasFocus) - border = UIManager.getBorder("TableHeader.focusCellBorder", this.getLocale()); - if (border == null) - border = UIManager.getBorder("TableHeader.cellBorder", this.getLocale()); - setBorder(border); - - return this; - } - - public SortOrder getColumnSortOrder(JTable table, int column) { - SortOrder rv = null; - if (table == null || table.getRowSorter() == null) - return rv; - java.util.List sortKeys - = table.getRowSorter().getSortKeys(); - if (sortKeys.size() > 0 && sortKeys.get(0).getColumn() - == table.convertColumnIndexToModel(column)) - rv = sortKeys.get(0).getSortOrder(); - return rv; - } - - @Override - public void paintComponent(Graphics g) { - boolean b = UIManager.getBoolean("TableHeader.rightAlignSortArrow", this.getLocale()); - if (b && sortArrow != null) { - //emptyIcon is used so that if the text in the header is right - //aligned, or if the column is too narrow, then the text will - //be sized appropriately to make room for the icon that is about - //to be painted manually here. - emptyIcon.width = sortArrow.getIconWidth(); - emptyIcon.height = sortArrow.getIconHeight(); - setIcon(emptyIcon); - super.paintComponent(g); - Point position = computeIconPosition(g); - sortArrow.paintIcon(this, g, position.x, position.y); - } else - super.paintComponent(g); - } - - private Point computeIconPosition(Graphics g) { - FontMetrics fontMetrics = g.getFontMetrics(); - Rectangle viewR = new Rectangle(); - Rectangle textR = new Rectangle(); - Rectangle iconR = new Rectangle(); - Insets i = getInsets(); - viewR.x = i.left; - viewR.y = i.top; - viewR.width = getWidth() - (i.left + i.right); - viewR.height = getHeight() - (i.top + i.bottom); - SwingUtilities.layoutCompoundLabel( - this, - fontMetrics, - getText(), - sortArrow, - getVerticalAlignment(), - getHorizontalAlignment(), - getVerticalTextPosition(), - getHorizontalTextPosition(), - viewR, - iconR, - textR, - getIconTextGap()); - int x = getWidth() - i.right - sortArrow.getIconWidth(); - int y = iconR.y; - return new Point(x, y); - } - - private class EmptyIcon implements Icon, Serializable { - - int width = 0; - int height = 0; - - @Override - public void paintIcon(Component c, Graphics g, int x, int y) { - } - - @Override - public int getIconWidth() { - return width; - } - - @Override - public int getIconHeight() { - return height; - } - } - } - - private class XPDefaultRenderer extends DefaultTableCellHeaderRenderer { - - XPDefaultRenderer() { - setHorizontalAlignment(LEADING); - setVerticalAlignment(CENTER); - } - - @Override - public Component getTableCellRendererComponent(JTable table, Object value, - boolean isSelected, boolean hasFocus, int row, int column) { - - //** 本方法里可以有默认设置render字体和颜色的设置,所以即使在上面构造方法里设置自已的字体等都不起效 - //,在此方法调用之后调置是没有问题的 - super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); - -// this.isSelected = isSelected; -// this.hasFocus = hasFocus; -// this.column = column; -// this.hasRollover = (column == getRolloverColumn()); -// if (skin == null) -// { -// skin = BEXPStyle.getXP().getSkin(header, Part.HP_HEADERITEM); -// } - Insets margins = UIManager.getInsets("TableHeader.cellMargin");//skin.getContentMargin(); - Border border; - int contentTop = 0; - int contentLeft = 0; - int contentBottom = 0; - int contentRight = 0; - if (margins != null) { - contentTop = margins.top; - contentLeft = margins.left; - contentBottom = margins.bottom; - contentRight = margins.right; - } - /* idk: - * Both on Vista and XP there is some offset to the - * HP_HEADERITEM content. It does not seem to come from - * Prop.CONTENTMARGINS. Do not know where it is defined. - * using some hardcoded values. - */ - contentLeft += 5; - contentBottom += 4; - contentRight += 5; - - /* On Vista sortIcon is painted above the header's text. - * We use border to paint it. - */ - Icon sortIcon; - //原UI代码 -// if (ZCWindowsLookAndFeel.isOnVista()&& -// ((sortIcon = getIcon()) instanceof javax.swing.plaf.UIResource -// || sortIcon == null)) - //现代码:上面原Java源代码里有WindowsLookAndFeel.isOnVista()==true时才会进入下面的代码 - //逻辑是不对的,也就是只要不是vista,就不可能绘制排序图标,这估计是Jdk自带的Java源代码很可能不是最新的! - if ( //去掉vista判断 - // ZCWindowsLookAndFeel.isOnVista() - // && - ((sortIcon = getIcon()) instanceof javax.swing.plaf.UIResource || sortIcon == null)) { - //原UI代码:原代码里为了仿vista样式,标头高度很高,现注释掉! -// contentTop += 1; - - setIcon(null); - sortIcon = null; - - SortOrder sortOrder = getColumnSortOrder(table, column); - if (sortOrder != null) - switch (sortOrder) { - case ASCENDING: - sortIcon - = UIManager.getIcon("Table.ascendingSortIcon"); - break; - case DESCENDING: - sortIcon - = UIManager.getIcon("Table.descendingSortIcon"); - break; - } - - if (sortIcon != null) - //原UI代码:原代码里为了仿vista样式,标头高度很高,现注释掉! -// contentBottom = sortIcon.getIconHeight(); - border = new IconBorder(sortIcon, contentTop, contentLeft, - contentBottom, contentRight); - else { - sortIcon = UIManager.getIcon("Table.ascendingSortIcon"); - int sortIconHeight = (sortIcon != null) ? sortIcon.getIconHeight() : 0; - if (sortIconHeight != 0) { - //原UI代码:原代码里为了仿vista样式,标头高度很高,现注释掉! -// contentBottom = sortIconHeight; - } - border = new EmptyBorder( - //原UI代码:原代码里为了仿vista样式,标头高度很高,现注释掉! - // sortIconHeight + contentTop, contentLeft, contentBottom, contentRight); - // /现代码:border的top不要那么(原代码是为了仿vista的) - contentTop, contentLeft, contentBottom, contentRight); - } - } else { - contentTop += 3; - border = new EmptyBorder(contentTop, contentLeft, contentBottom, contentRight); - } - setBorder(border); - - //** jb2011设置字体颜色和加粗 -// this.setForeground(ColorHelper.DARK_GRAY1_LIKE_APPLE); -// this.setFont(this.getFont().deriveFont(Font.BOLD)); - return this; - } - - @Override - public void paint(Graphics g) { - Dimension size = getSize(); -// State state = State.NORMAL; -// TableColumn draggedColumn = header.getDraggedColumn(); -// if (draggedColumn != null && -// column == SwingUtilities2.convertColumnIndexToView( -// header.getColumnModel(), -// draggedColumn.getModelIndex())) -// { -// state = State.PRESSED; -// } -// else if (isSelected || hasFocus || hasRollover) -// { -// state = State.HOT; -// } - /* on Vista there are more states for sorted columns */ -// if (WinUtils.isOnVista()) -// { -// SortOrder sortOrder = getColumnSortOrder(header.getTable(), column); -// if (sortOrder != null) -// { -// switch(sortOrder) -// { -// case ASCENDING: -// /* falls through */ -// case DESCENDING: -// switch (state) -// { -// case NORMAL: -// state = State.SORTEDNORMAL; -// break; -// case PRESSED: -// state = State.SORTEDPRESSED; -// break; -// case HOT: -// state = State.SORTEDHOT; -// break; -// default: -// /* do nothing */ -// } -// default : -// /* do nothing */ -// } -// } -// } - - paintHeadCell(g, size); -// skin.paintSkin(g, 0, 0, size.width-1, size.height-1, state); - - super.paint(g); - } - } - - //* 由jb2011 修改自WindowsTableHeaderUI里的同名类. - /** - * A border with an Icon at the middle of the top side. Outer insets can be - * provided for this border. - */ - private static class IconBorder implements Border, UIResource { - - private final Icon icon; - - private final int top, left, bottom, right; - - public IconBorder(Icon icon, int top, int left, int bottom, int right) { - this.icon = icon; - this.top = top; - this.left = left; - this.bottom = bottom; - this.right = right; - } - - @Override - public Insets getBorderInsets(Component c) { - //原UI代码:原代码里为了仿vista样式,标头高度很高,现注释掉! -// return new Insets(icon.getIconHeight() + top, left, bottom, right); - //现代码 - return new Insets(top, left, bottom, right); - } - - @Override - public boolean isBorderOpaque() { - return false; - } - - @Override - public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { - icon.paintIcon(c, g, - //原UI代码:原代码里为了仿vista样式,标头高度很高且图标的位置是放在top中央,现注释掉! - // x + left + (width - left - right - icon.getIconWidth()) / 2, y + top); - - //现代码:图标放在右边利往左来2个像素的位置(好看一点) - x + left + width - right - icon.getIconWidth() - 2, y); - } - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/table/BETableUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/table/BETableUI.java deleted file mode 100644 index bf0ec03e0..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/table/BETableUI.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BETableUI.java at 2015-2-1 20:25:41, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.table; - -import java.awt.Dimension; - -import javax.swing.JComponent; -import javax.swing.LookAndFeel; -import javax.swing.UIDefaults; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicTableUI; - -/** - * JTable的UI实现类. - * - * @author Jack Jiang(jb2011@163.com) - */ -public class BETableUI extends BasicTableUI { - - UIDefaults defaultRenderersByColumnClass; - - public static ComponentUI createUI(JComponent c) { - return new BETableUI(); - } - - /** - * Initialize JTable properties, e.g. font, foreground, and background. The - * font, foreground, and background properties are only set if their current - * value is either null or a UIResource, other properties are set if the - * current value is null. - * - * @see #installUI - */ - @Override - protected void installDefaults() { - super.installDefaults(); - //行高设置为25看起来会舒服些 - table.setRowHeight(25); - //不显示垂直的网格线 - table.setShowVerticalLines(false); - //设置单元格间的空白(默认是1个像素宽和高) - //说明:设置本参数可以实现单元格间的间隔空制,间隔里通常是实现网格线的绘制,但 - //网格维绘制与否并不影响间隔的存在(如果间隔存在但网格线不绘的话它就是是透明的空 - //间),参数中width表示水平间隔,height表示垂直间隔,为0则表示没有间隔 - table.setIntercellSpacing(new Dimension(0, 1)); - LookAndFeel.installProperty(table, "opaque", Boolean.FALSE); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/table/FocusCellHighlightBorder.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/table/FocusCellHighlightBorder.java deleted file mode 100644 index aa2ebb414..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/table/FocusCellHighlightBorder.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * FocusCellHighlightBorder.java at 2015-2-1 20:25:40, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.table; - -import java.awt.Component; -import java.awt.Graphics; -import java.awt.Insets; - -import javax.swing.UIManager; -import javax.swing.border.AbstractBorder; - -import org.jackhuang.hmcl.laf.BEUtils; - -/** - * 表格单元获得焦点时的Border实现类. - * - * 本border由Jack Jiang实现,它是表格单元获得焦点时的边框(类似的功能在windows LNF下是一个距形虚线框) - * - * @author Jack Jiang(jb2011@163.com) - */ -class FocusCellHighlightBorder extends AbstractBorder { - - @Override - public Insets getBorderInsets(Component c) { -// return new Insets(0,3,0,1); - return new Insets(2, 2, 2, 2); // @since 3.5 - } - - @Override - public Insets getBorderInsets(Component c, Insets insets) { - return getBorderInsets(c); - } - - @Override - public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { - //* old impl -// //在左边划一条2像素宽的竖线 -// g.setColor(UIManager.getColor("Table.focusCellHighlightBorderColor")); -// g.fillRect(x, y, 2, height );//上下各空白一个像素,目的是为了与render的N9图片背景配合形成更好的视觉效果 -// -// //再在上面的竖线右边划一条1像素宽的亮色竖线,以便为上面的2像素竖线营造立体效果 -// /* ~~注:这个属性是jb2011为了更好的ui效果自已加的属性,目的是使Table.focusCellHighlightBorder有点立体效果哦 */ -// g.setColor(UIManager.getColor("Table.focusCellHighlightBorderHighlightColor")); -// g.fillRect(x+2, y, 1, height ); - - //* @since 3.5 - BEUtils.draw4RecCorner(g, x, y, width - 2, height - 2, 5, - UIManager.getColor("Table.focusCellHighlightBorderColor")); - BEUtils.draw4RecCorner(g, x + 1, y + 1, width - 2, height - 2, 5, - UIManager.getColor("Table.focusCellHighlightBorderHighlightColor")); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/table/TableScrollBorder.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/table/TableScrollBorder.java deleted file mode 100644 index 316419be1..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/table/TableScrollBorder.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * TableScrollBorder.java at 2015-2-1 20:25:36, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.table; - -import java.awt.Insets; - -import org.jackhuang.hmcl.laf.widget.border.NinePatchBorder; - -/** - * 表格UI所在滚动条的边框实现类. - * - * @author Jack Jiang(jb2011@163.com), 2012-08-30 - * @version 1.0 - */ -class TableScrollBorder extends NinePatchBorder { - - public TableScrollBorder() { - super(new Insets(3, 5, 10, 5), BETableHeaderUI.ICON_9.get("scroll_border")); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/table/__UI__.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/table/__UI__.java deleted file mode 100644 index c792eaebc..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/table/__UI__.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * __UI__.java at 2015-2-1 20:25:39, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.table; - -import java.awt.Color; -import java.awt.Component; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Insets; - -import javax.swing.UIManager; - -import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper; -import org.jackhuang.hmcl.laf.utils.IconFactory; -import org.jackhuang.hmcl.laf.utils.UI; - -public class __UI__ extends UI { - - private static final IconFactory ICON = new IconFactory("table"); - - public static void uiImpl() { - //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> JTable的相关ui属性设定 - //JTable所属的滚动面板的border实现(不像JList,JTable的UI自动为它配备的一个JScrollPane) - put("Table.scrollPaneBorder", new TableScrollBorder());//defaut is com.sun.java.swing.plaf.windows.XPStyle.XPFillBorder - put("Table.focusCellHighlightBorder", new FocusCellHighlightBorder());//new BEDashedBorder(new Color(0,160,0),1,0,true,false,true,false))); - /* ~~注:这个属性是jb2011为了更好的ui效果自已加的属性 */ - put("Table.focusCellHighlightBorderColor", Color.white);//new ColorUIResource(Color.red)); - /* ~~注:这个属性是jb2011为了更好的ui效果自已加的属性,目的是使Table.focusCellHighlightBorder有点立体效果哦 */ - putColor("Table.focusCellHighlightBorderHighlightColor", 255, 255, 255, 70);//注意:这个颜色是半透明的哦 - put("Table.background", Color.white); - //** 2011-03-16 add by jb2011 为了使JDK1.6及以上表格头在排序时能显示排序箭头(1.6里的排序图标是在UI里设定的) - UIManager.put("Table.descendingSortIcon", ICON.get("descending_sort")); - UIManager.put("Table.ascendingSortIcon", ICON.get("ascending_sort")); - put("Table.selectionForeground", BeautyEyeLNFHelper.commonSelectionForegroundColor); - putColor("Table.gridColor", 220, 220, 220); - put("Table.selectionBackground", BeautyEyeLNFHelper.commonSelectionBackgroundColor); - put("Table.foreground", BeautyEyeLNFHelper.commonForegroundColor); - put("TableUI", BETableUI.class); - - //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> JTable表头相关ui属性设定 -// UIManager.put("TableHeader.font",new Font("宋体",Font.PLAIN,12));//此属性将决定表头的字体 - put("TableHeader.background", BeautyEyeLNFHelper.commonBackgroundColor); - put("TableHeader.foreground", BeautyEyeLNFHelper.commonForegroundColor); - - //不建议完全定制表头ui,因为BasicTableHeaderUI里的关键方法都是private,无法继承重写,要实现自已 - //的绘制逻辑需要重写大段代码,而因JTable在不同jdk版本里的变动较大:比如1.6里才有的排序(及图标)及相关方法 - //在不同的版本里都不尽相同,而且调用了若干sun的非公开包里的api。虽存在兼容性问题,为了UI美观,还是自定义实现吧 - put("TableHeaderUI", BETableHeaderUI.class); - //** BE LNF的本属性只在Java版本高于1.5时起效 - //* 由jb2011自已加的属性,因原BasicTableHeaderUI里用TableHeader.cellBorder来设置 - //border,但WindowsTableHeaderUI的border则是自已实现的IconBorder,而BE LNF中则是仿 - //照Windows LNF实现,所以只能实现一个自已的属性来供以后的使用者灵活设定(否则只能像Windows LNF一样硬编码在代码里) - putInsets("TableHeader.cellMargin", 7, 0, 7, 0); - } - - /** - * Border for a Table Header. - * - * @see javax.swing.plaf.metal.TableHeaderBorder - */ - public static class TableHeaderBorder extends javax.swing.border.AbstractBorder { - - protected Insets editorBorderInsets = new Insets(7, 0, 7, 0);//默认是2, 2, 2, 0 ); - - @Override - public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { - g.translate(x, y); - -// g.setColor(MetalLookAndFeel.getControlDarkShadow() ); -// g.drawLine( w-1, 0, w-1, h-1 ); -// g.drawLine( 1, h-1, w-1, h-1 ); -// g.setColor( MetalLookAndFeel.getControlHighlight() ); -// g.drawLine( 0, 0, w-2, 0 ); -// g.drawLine( 0, 0, 0, h-2 ); - //* add by Jack Jiang START - //绘制表头单元的底部水平线(跟网格线颜色一样就可以了) - g.setColor(UIManager.getColor("Table.gridColor")); - g.drawLine(0, h - 1, w, h - 1); - - //绘制表头单元的右分隔竖线 - BETableHeaderUI.ICON_9.get("header_cell_separator") - .draw((Graphics2D) g, w - 4, 0, 4, h); - //* add by Jack Jiang END - - g.translate(-x, -y); - } - - @Override - public Insets getBorderInsets(Component c) { - return editorBorderInsets; - } - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/textcoms/BEEditorPaneUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/textcoms/BEEditorPaneUI.java deleted file mode 100644 index e606e5257..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/textcoms/BEEditorPaneUI.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BEEditorPaneUI.java at 2015-2-1 20:25:41, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.textcoms; - -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; -import javax.swing.plaf.basic.BasicEditorPaneUI; - -import org.jackhuang.hmcl.laf.textcoms.__UI__.BgSwitchable; - -/** - * 文本组件JEditorPane的UI实现类. - * - * @author Jack Jiang(jb2011@163.com), 2012-08-25 - * @see com.sun.java.swing.plaf.windows.WindowsEditorPaneUI - */ -public class BEEditorPaneUI extends BasicEditorPaneUI implements BgSwitchable, - org.jackhuang.hmcl.laf.BeautyEyeLNFHelper.__UseParentPaintSurported { - //默认是纯白色背景,因为JEditorPane肯定是要放在JScrollPane中的,而ScrollPane也是有边框的 - //如果JEditorPane再有边框就很难看了,所以JEditorPane在没有获得焦点时就已无边框效果出现会好看很多 - - public static ComponentUI createUI(JComponent c) { - BETextFieldUI.addOtherListener(c); - return new BEEditorPaneUI(); - } - - //* 本方法由Jack Jiang于2012-09-07日加入 - /** - * 是否使用父类的绘制实现方法,true表示是. - *

    - * 因为在BE LNF中,边框和背景等都是使用N9图,没法通过设置背景色和前景 - * 色来控制JEditorPane的颜色和边框,本方法的目的就是当用户设置了进度条的border或背景色 时告之本实现类不使用BE - * LNF中默认的N9图填充绘制而改用父类中的方法(父类中的方法 就可以支持颜色的设置罗,只是丑点,但总归是能适应用户的需求场景要求,其实用户完全可以 - * 通过JEditorPane.setUI(..)方式来自定义UI哦). - * - * @return true, if is use parent paint - */ - @Override - public boolean isUseParentPaint() { - return getComponent() != null - && (!(getComponent().getBorder() instanceof UIResource) - || !(getComponent().getBackground() instanceof UIResource)); - } - - @Override - public void switchBgToNormal() { - } - - @Override - public void switchBgToFocused() { - } - - @Override - public void switchBgToOver() { - } - -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/textcoms/BEFormattedTextFieldUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/textcoms/BEFormattedTextFieldUI.java deleted file mode 100644 index 46cdcedc6..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/textcoms/BEFormattedTextFieldUI.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BEPasswordFieldUI.java at 2015-2-1 20:25:36, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.textcoms; - -import java.awt.Graphics; - -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; -import javax.swing.plaf.basic.BasicFormattedTextFieldUI; -import javax.swing.text.JTextComponent; - -import org.jackhuang.hmcl.laf.textcoms.__UI__.BgSwitchable; -import org.jackhuang.hmcl.laf.utils.TMSchema; - -/** - * 文本组件JFormattedTextField的UI实现类. - * - * @author Jack Jiang(jb2011@163.com), 2015-11-13 - * @since 3.7 - */ -public class BEFormattedTextFieldUI extends BasicFormattedTextFieldUI implements BgSwitchable, - org.jackhuang.hmcl.laf.BeautyEyeLNFHelper.__UseParentPaintSurported { - - public static ComponentUI createUI(JComponent c) { - c.addFocusListener(FocusListenerImpl.getInstance()); - return new BEFormattedTextFieldUI(); - } - - //* 本方法由Jack Jiang于2012-09-07日加入 - /** - * 是否使用父类的绘制实现方法,true表示是. - *

    - * 因为在BE LNF中,边框和背景等都是使用N9图,没法通过设置背景色和前景 - * 色来控制JPasswordField的颜色和边框,本方法的目的就是当用户设置了进度条的border或背景色 时告之本实现类不使用BE - * LNF中默认的N9图填充绘制而改用父类中的方法(父类中的方法 就可以支持颜色的设置罗,只是丑点,但总归是能适应用户的需求场景要求,其实用户完全可以 - * 通过JPasswordField.setUI(..)方式来自定义UI哦). - * - * @return true, if is use parent paint - */ - @Override - public boolean isUseParentPaint() { - return getComponent() != null - && (!(getComponent().getBorder() instanceof UIResource) - || !(getComponent().getBackground() instanceof UIResource)); - } - - /** - * Paints a background for the view. This will only be called if isOpaque() - * on the associated component is true. The default is to paint the - * background color of the component. - * - * @param g the graphics context - */ - @Override - protected void paintBackground(Graphics g) { - //先调用父类方法把背景刷新下(比如本UI里使用的大圆角NP图如不先刷新背景则会因上下拉动滚动条 - //而致4个圆角位置得不到刷新,从而影响视觉效果(边角有前面的遗留),置于透明边角不被透明像素填 - //充的问题,它有可能是Android的NinePatch技术为了性能做作出的优化——一切全透明像素即意味着不需绘制) - super.paintBackground(g);// TODO 出于节约计算资源考生虑,本行代码换成父类中默认填充背景的代码即可 - - //* 如果用户作了自定义颜色设置则使用父类方法来实现绘制,否则BE LNF中没法支持这些设置哦 - if (!isUseParentPaint()) { - //用新的NP图实现真正的背景填充 - JTextComponent editor = this.getComponent(); - __UI__.TextSkin.paintBg(editor, g, 0, 0, editor.getWidth(), editor.getHeight(), state); - } - } - - @Override - public void switchBgToNormal() { - state = TMSchema.State.NORMAL; - } - - @Override - public void switchBgToFocused() { - state = TMSchema.State.FOCUSED; - } - - @Override - public void switchBgToOver() { - state = TMSchema.State.ROLLOVER; - } - - TMSchema.State state = TMSchema.State.NORMAL; - -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/textcoms/BEPasswordFieldUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/textcoms/BEPasswordFieldUI.java deleted file mode 100644 index 124a1e309..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/textcoms/BEPasswordFieldUI.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BEPasswordFieldUI.java at 2015-2-1 20:25:36, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.textcoms; - -import java.awt.Graphics; - -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; -import javax.swing.plaf.basic.BasicPasswordFieldUI; -import javax.swing.text.JTextComponent; - -import org.jackhuang.hmcl.laf.textcoms.__UI__.BgSwitchable; -import org.jackhuang.hmcl.laf.utils.TMSchema; - -/** - * 文本组件JPasswordField的UI实现类. - * - * @author Jack Jiang(jb2011@163.com) - */ -public class BEPasswordFieldUI extends BasicPasswordFieldUI implements BgSwitchable, - org.jackhuang.hmcl.laf.BeautyEyeLNFHelper.__UseParentPaintSurported { - - public static ComponentUI createUI(JComponent c) { - BETextFieldUI.addOtherListener(c); - return new BEPasswordFieldUI(); - } - - //* 本方法由Jack Jiang于2012-09-07日加入 - /** - * 是否使用父类的绘制实现方法,true表示是. - *

    - * 因为在BE LNF中,边框和背景等都是使用N9图,没法通过设置背景色和前景 - * 色来控制JPasswordField的颜色和边框,本方法的目的就是当用户设置了进度条的border或背景色 时告之本实现类不使用BE - * LNF中默认的N9图填充绘制而改用父类中的方法(父类中的方法 就可以支持颜色的设置罗,只是丑点,但总归是能适应用户的需求场景要求,其实用户完全可以 - * 通过JPasswordField.setUI(..)方式来自定义UI哦). - * - * @return true, if is use parent paint - */ - @Override - public boolean isUseParentPaint() { - return getComponent() != null - && (!(getComponent().getBorder() instanceof UIResource) - || !(getComponent().getBackground() instanceof UIResource)); - } - - /** - * Paints a background for the view. This will only be called if isOpaque() - * on the associated component is true. The default is to paint the - * background color of the component. - * - * @param g the graphics context - */ - @Override - protected void paintBackground(Graphics g) { - //先调用父类方法把背景刷新下(比如本UI里使用的大圆角NP图如不先刷新背景则会因上下拉动滚动条 - //而致4个圆角位置得不到刷新,从而影响视觉效果(边角有前面的遗留),置于透明边角不被透明像素填 - //充的问题,它有可能是Android的NinePatch技术为了性能做作出的优化——一切全透明像素即意味着不需绘制) - super.paintBackground(g);// TODO 出于节约计算资源考生虑,本行代码换成父类中默认填充背景的代码即可 - - //* 如果用户作了自定义颜色设置则使用父类方法来实现绘制,否则BE LNF中没法支持这些设置哦 - if (!isUseParentPaint()) { - //用新的NP图实现真正的背景填充 - JTextComponent editor = this.getComponent(); - __UI__.TextSkin.paintBg(editor, g, 0, 0, editor.getWidth(), editor.getHeight(), state); - } - } - - @Override - public void switchBgToNormal() { - state = TMSchema.State.NORMAL; - } - - @Override - public void switchBgToFocused() { - state = TMSchema.State.FOCUSED; - } - - @Override - public void switchBgToOver() { - state = TMSchema.State.ROLLOVER; - } - - TMSchema.State state = TMSchema.State.NORMAL; -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/textcoms/BETextAreaUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/textcoms/BETextAreaUI.java deleted file mode 100644 index c509e2780..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/textcoms/BETextAreaUI.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BETextAreaUI.java at 2015-2-1 20:25:41, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.textcoms; - -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; -import javax.swing.plaf.basic.BasicTextAreaUI; - -import org.jackhuang.hmcl.laf.textcoms.__UI__.BgSwitchable; - -/** - * 文本组件JTextArea的UI实现类. - * - * @author Jack Jiang(jb2011@163.com) - */ -public class BETextAreaUI extends BasicTextAreaUI implements BgSwitchable, - org.jackhuang.hmcl.laf.BeautyEyeLNFHelper.__UseParentPaintSurported { - //默认是纯白色背景,因为JTextArea肯定是要放在JScrollPane中的,而ScrollPane也是有边框的 - //如果JTextArea再有边框就很难看了,所以JTextArea在没有获得焦点时就已无边框效果出现会好看很多 - - public static ComponentUI createUI(JComponent c) { - BETextFieldUI.addOtherListener(c); - return new BETextAreaUI(); - } - - //* 本方法由Jack Jiang于2012-09-07日加入 - /** - * 是否使用父类的绘制实现方法,true表示是. - *

    - * 因为在BE LNF中,边框和背景等都是使用N9图,没法通过设置背景色和前景 - * 色来控制JTextField的颜色和边框,本方法的目的就是当用户设置了进度条的border或背景色 时告之本实现类不使用BE - * LNF中默认的N9图填充绘制而改用父类中的方法(父类中的方法 就可以支持颜色的设置罗,只是丑点,但总归是能适应用户的需求场景要求,其实用户完全可以 - * 通过JTextField.setUI(..)方式来自定义UI哦). - * - * @return true, if is use parent paint - */ - @Override - public boolean isUseParentPaint() { - return getComponent() != null - && (!(getComponent().getBorder() instanceof UIResource) - || !(getComponent().getBackground() instanceof UIResource)); - } - - @Override - public void switchBgToNormal() { - } - - @Override - public void switchBgToFocused() { - } - - @Override - public void switchBgToOver() { - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/textcoms/BETextFieldUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/textcoms/BETextFieldUI.java deleted file mode 100644 index 32b7fdd04..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/textcoms/BETextFieldUI.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BETextFieldUI.java at 2015-2-1 20:25:37, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.textcoms; - -import java.awt.Graphics; - -import javax.swing.JComponent; -import javax.swing.plaf.UIResource; -import javax.swing.plaf.basic.BasicTextFieldUI; -import javax.swing.text.JTextComponent; - -import org.jackhuang.hmcl.laf.textcoms.__UI__.BgSwitchable; -import org.jackhuang.hmcl.laf.utils.TMSchema; - -/** - * 文本组件JTextField的UI实现类. - * - * @author Jack Jiang(jb2011@163.com) - */ -public class BETextFieldUI extends BasicTextFieldUI implements BgSwitchable, - org.jackhuang.hmcl.laf.BeautyEyeLNFHelper.__UseParentPaintSurported { - - public static BETextFieldUI createUI(JComponent c) { - addOtherListener(c); - return new BETextFieldUI(); - } - - //* 本方法由Jack Jiang于2012-09-07日加入 - /** - * 是否使用父类的绘制实现方法,true表示是. - *

    - * 因为在BE LNF中,边框和背景等都是使用N9图,没法通过设置背景色和前景 - * 色来控制JTextField的颜色和边框,本方法的目的就是当用户设置了进度条的border或背景色 时告之本实现类不使用BE - * LNF中默认的N9图填充绘制而改用父类中的方法(父类中的方法 就可以支持颜色的设置罗,只是丑点,但总归是能适应用户的需求场景要求,其实用户完全可以 - * 通过JTextField.setUI(..)方式来自定义UI哦). - * - * @return true, if is use parent paint - */ - @Override - public boolean isUseParentPaint() { - return getComponent() != null - && (!(getComponent().getBorder() instanceof UIResource) - || !(getComponent().getBackground() instanceof UIResource)); - } - - /** - * Paints a background for the view. This will only be called if isOpaque() - * on the associated component is true. The default is to paint the - * background color of the component. - * - * @param g the graphics context - */ - @Override - protected void paintBackground(Graphics g) { - //先调用父类方法把背景刷新下(比如本UI里使用的大圆角NP图如不先刷新背景则会因上下拉动滚动条 - //而致4个圆角位置得不到刷新,从而影响视觉效果(边角有前面的遗留),置于透明边角不被透明像素填 - //充的问题,它有可能是Android的NinePatch技术为了性能做作出的优化——一切全透明像素即意味着不需绘制) - super.paintBackground(g);// TODO 出于节约计算资源考生虑,本行代码换成父类中默认填充背景的代码即可 - - //* 如果用户作了自定义颜色设置则使用父类方法来实现绘制,否则BE LNF中没法支持这些设置哦 - if (!isUseParentPaint()) { - //用新的NP图实现真正的背景填充 - JTextComponent editor = this.getComponent(); - __UI__.TextSkin.paintBg(editor, g, 0, 0, editor.getWidth(), editor.getHeight(), state); - } - } - - @Override - public void switchBgToNormal() { - state = TMSchema.State.NORMAL; - } - - @Override - public void switchBgToFocused() { - state = TMSchema.State.FOCUSED; - } - - @Override - public void switchBgToOver() { - state = TMSchema.State.ROLLOVER; - } - - TMSchema.State state = TMSchema.State.NORMAL; - - /** - * 为组件添加焦点监听器(获得/取消焦点时可以自动设置/取消一个彩色的边框效果,以体高UI体验) 、右键菜单监听器(有复制/粘贴等功能). - * - * @param c the c - */ - public static void addOtherListener(JComponent c) { - c.addFocusListener(FocusListenerImpl.getInstance()); - c.addMouseListener(FocusListenerImpl.getInstance()); - } - -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/textcoms/BETextPaneUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/textcoms/BETextPaneUI.java deleted file mode 100644 index b33658f8b..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/textcoms/BETextPaneUI.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BETextPaneUI.java at 2015-2-1 20:25:40, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.textcoms; - -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; -import javax.swing.plaf.basic.BasicTextPaneUI; - -import org.jackhuang.hmcl.laf.textcoms.__UI__.BgSwitchable; - -/** - * 文本组件JTextPane的UI实现类. - * - * @author Jack Jiang(jb2011@163.com), 2012-08-25 - * @see com.sun.java.swing.plaf.windows.WindowsTextPaneUI - */ -public class BETextPaneUI extends BasicTextPaneUI implements BgSwitchable, - org.jackhuang.hmcl.laf.BeautyEyeLNFHelper.__UseParentPaintSurported { - //默认是纯白色背景,因为JTextPane肯定是要放在JScrollPane中的,而ScrollPane也是有边框的 - //如果JTextPane再有边框就很难看了,所以JTextPane在没有获得焦点时就已无边框效果出现会好看很多 - - public static ComponentUI createUI(JComponent c) { - BETextFieldUI.addOtherListener(c); -// c.addMouseListener(new NLLookAndFeel.EditMenu()); - return new BETextPaneUI(); - } - - /** - * 是否使用父类的绘制实现方法,true表示是. - *

    - * 因为在BE LNF中,边框和背景等都是使用N9图,没法通过设置背景色和前景 - * 色来控制JTextPane的颜色和边框,本方法的目的就是当用户设置了进度条的border或背景色 时告之本实现类不使用BE - * LNF中默认的N9图填充绘制而改用父类中的方法(父类中的方法 就可以支持颜色的设置罗,只是丑点,但总归是能适应用户的需求场景要求,其实用户完全可以 - * 通过JTextPane.setUI(..)方式来自定义UI哦). - * - * @return true, if is use parent paint - */ - @Override - public boolean isUseParentPaint() { - return getComponent() != null - && (!(getComponent().getBorder() instanceof UIResource) - || !(getComponent().getBackground() instanceof UIResource)); - } - - @Override - public void switchBgToNormal() { - } - - @Override - public void switchBgToFocused() { - } - - @Override - public void switchBgToOver() { - } - -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/textcoms/FocusListenerImpl.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/textcoms/FocusListenerImpl.java deleted file mode 100644 index c990596d2..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/textcoms/FocusListenerImpl.java +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * FocusListenerImpl.java at 2015-2-1 20:25:40, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.textcoms; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.event.FocusEvent; -import java.awt.event.FocusListener; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; - -import javax.swing.JComboBox; -import javax.swing.JComponent; -import javax.swing.JTextField; -import javax.swing.UIManager; -import javax.swing.border.Border; -import javax.swing.plaf.ComponentUI; -import javax.swing.text.JTextComponent; - -import org.jackhuang.hmcl.laf.textcoms.__UI__.BgSwitchable; -import org.jackhuang.hmcl.laf.BEUtils; -import org.jackhuang.hmcl.laf.widget.border.BERoundBorder; - -/** - * 焦点改变时的监听器实现类. - *

    - * 目前主要用于各文本组件. - * - * @author Jack Jiang(jb2011@163.com) - */ -public class FocusListenerImpl implements FocusListener, MouseListener { - - /** - * 文本组件等获得焦点后的边框线条宽度. - */ - public static int defaultFocusedThikness = 2; - - /** - * Gets the single instance of FocusListenerImpl. - * - * @return single instance of FocusListenerImpl - */ - public static FocusListenerImpl getInstance() { -// return INSTANCE; - return new FocusListenerImpl(); - } - - /** - * The focused thikness. - */ - protected int focusedThikness = defaultFocusedThikness; - - /** - * Gets the focused thikness. - * - * @return the focused thikness - */ - public int getFocusedThikness() { - return focusedThikness; - } - - /** - * Sets the focused thikness. - * - * @param focusedThikness the focused thikness - * @return the focus listener impl - */ - public FocusListenerImpl setFocusedThikness(int focusedThikness) { - this.focusedThikness = focusedThikness; - return this; - } - - @Override - public void focusGained(FocusEvent e) { - if (e.getSource() instanceof JComponent) { - JComponent com = (JComponent) e.getSource(); - Border orignalBorder = com.getBorder(); - - if (orignalBorder != null) { - //决定获得焦点时的连框色调 - Color focusedColor = getTextFieldFocusedColor(); - - //JTextField获得焦点时特殊处理:自动切换它的背景图即可(用NinePatch图实现) - if (com instanceof JTextComponent) { - JTextComponent text = (JTextComponent) com; - ComponentUI ui = text.getUI(); - text.putClientProperty("BEFocused", true); - if (ui instanceof BgSwitchable) { - ((BgSwitchable) ui).switchBgToFocused(); - com.repaint(); - return; - } - } else if (com instanceof JComboBox) - focusedColor = getComboBoxFocusedColor(); - - //获得焦点后的新边框 - BERoundBorder cc; - if (orignalBorder instanceof BERoundBorder) - cc = (BERoundBorder) (((BERoundBorder) orignalBorder).clone()); - else - cc = new BERoundBorder(1).setArcWidth(0); - cc.setLineColor(focusedColor); - cc.setThickness(focusedThikness); - - //* !当组件是JPasswordField,它的反应会有bug,也就是在setBorder之后它的 - //* preferredSize会变的很小,这里针对其作的特殊处理就是为了使其size与setBorder前保持一致 - Dimension oldDm = null; - if (com instanceof JTextField) - oldDm = com.getSize(); - com.setBorder(cc); - if (com instanceof JTextField) - com.setPreferredSize(oldDm); - } - } - } - - @Override - public void focusLost(FocusEvent e) { - if (e.getSource() instanceof JComponent) { - JComponent com = (JComponent) e.getSource(); - - //JTextField获得焦点时特殊处理:自动切换它的背景图即可(用NinePatch图实现) - if (com instanceof JTextComponent) { - JTextComponent text = (JTextComponent) com; - ComponentUI ui = text.getUI(); - text.putClientProperty("BEFocused", false); - if (ui instanceof BgSwitchable) { - ((BgSwitchable) ui).switchBgToNormal(); - com.repaint(); - return; - } - } - - //失去焦点时还原边框样式 - Border orignalBorder = com.getBorder(); - if (orignalBorder != null) - if (orignalBorder instanceof BERoundBorder) { - BERoundBorder cc = (BERoundBorder) (((BERoundBorder) orignalBorder).clone()); - cc.setLineColor(BERoundBorder.defaultLineColor); - cc.setThickness(1); - com.setBorder(cc); - } - } - } - - /** - * Gets the text field focused color. - * - * @return the text field focused color - */ - public static Color getTextFieldFocusedColor() { - return BEUtils.getColor(UIManager.getColor("TextField.selectionBackground"), 30, 30, 30); - } - - /** - * Gets the combo box focused color. - * - * @return the combo box focused color - */ - public static Color getComboBoxFocusedColor() { - return BEUtils.getColor(UIManager.getColor("ComboBox.selectionBackground"), 30, 30, 30); - } -// public static Color getTextPaneFocusedColor() -// { -// return LNFUtils.getColor(UIManager.getColor("TextPane.selectionBackground"),30,30,30); -// } - - @Override - public void mouseClicked(MouseEvent e) { - } - - @Override - public void mousePressed(MouseEvent e) { - } - - @Override - public void mouseReleased(MouseEvent e) { - } - - @Override - public void mouseEntered(MouseEvent e) { - if (e.getSource() instanceof JComponent) { - JComponent com = (JComponent) e.getSource(); - - //JTextField获得焦点时特殊处理:自动切换它的背景图即可(用NinePatch图实现) - if (com instanceof JTextComponent) { - JTextComponent text = (JTextComponent) com; - ComponentUI ui = text.getUI(); - Object o = text.getClientProperty("BEFocused"); - if (o == null || o == Boolean.FALSE) - if (ui instanceof BgSwitchable) { - ((BgSwitchable) ui).switchBgToOver(); - com.repaint(); - return; - } - } - - //失去焦点时还原边框样式 - Border orignalBorder = com.getBorder(); - if (orignalBorder != null) - if (orignalBorder instanceof BERoundBorder) { - BERoundBorder cc = (BERoundBorder) (((BERoundBorder) orignalBorder).clone()); - cc.setLineColor(BERoundBorder.defaultLineColor); - cc.setThickness(1); - com.setBorder(cc); - } - } - } - - @Override - public void mouseExited(MouseEvent e) { - if (e.getSource() instanceof JComponent) { - JComponent com = (JComponent) e.getSource(); - - //JTextField获得焦点时特殊处理:自动切换它的背景图即可(用NinePatch图实现) - if (com instanceof JTextComponent) { - JTextComponent text = (JTextComponent) com; - ComponentUI ui = text.getUI(); - Object o = text.getClientProperty("BEFocused"); - if (o == null || o == Boolean.FALSE) - if (ui instanceof BgSwitchable) { - ((BgSwitchable) ui).switchBgToNormal(); - com.repaint(); - return; - } - } - - //失去焦点时还原边框样式 - Border orignalBorder = com.getBorder(); - if (orignalBorder != null) - if (orignalBorder instanceof BERoundBorder) { - BERoundBorder cc = (BERoundBorder) (((BERoundBorder) orignalBorder).clone()); - cc.setLineColor(BERoundBorder.defaultLineColor); - cc.setThickness(1); - com.setBorder(cc); - } - } - } - -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/textcoms/__UI__.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/textcoms/__UI__.java deleted file mode 100644 index b3c02db2f..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/textcoms/__UI__.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * __UI__.java at 2015-2-1 20:25:38, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.textcoms; - -import java.awt.Color; -import java.awt.Graphics; -import javax.swing.JComponent; - -import javax.swing.UIManager; -import javax.swing.plaf.InsetsUIResource; -import org.jackhuang.hmcl.util.ui.GraphicsUtils; - -import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper; -import org.jackhuang.hmcl.laf.utils.AnimationController; -import org.jackhuang.hmcl.laf.utils.Icon9Factory; -import org.jackhuang.hmcl.laf.utils.Skin; -import org.jackhuang.hmcl.laf.utils.TMSchema; -import org.jackhuang.hmcl.laf.utils.UI; -import org.jackhuang.hmcl.laf.widget.border.BERoundBorder; - -public class __UI__ extends UI { - - static final Color BORDER_NORMAL = GraphicsUtils.getWebColor("#999999"); - static final Color BORDER_DISABLED = GraphicsUtils.getWebColor("#E3E3E3"); - static final Color BORDER_OVER = GraphicsUtils.getWebColor("#666666"); - - static Color border_focused() { - return (Color) UIManager.get("TextField.focused"); - } - - public static final Icon9Factory ICON_9 = new Icon9Factory("text"); - - public static void uiImpl() { - final InsetsUIResource iuir = new InsetsUIResource(4, 7, 4, 7); - final BERoundBorder berb = new BERoundBorder().setLineColor(new Color(0, 0, 0, 0)); - - //使用全透明色绘边框(用什么边框无所谓,关键是读取它的margin并透明),目的就是要让它的背景显现出来(NinePatch图实现) - UIManager.put("TextField.margin", iuir); - put("TextField.border", berb); - put("TextField.selectionForeground", BeautyEyeLNFHelper.commonSelectionForegroundColor); - put("TextField.selectionBackground", BeautyEyeLNFHelper.commonSelectionBackgroundColor); - put("TextField.foreground", BeautyEyeLNFHelper.commonForegroundColor); - put("TextFieldUI", BETextFieldUI.class); - - UIManager.put("FormattedTextField.margin", iuir); - put("FormattedTextField.border", new BERoundBorder(1).setArcWidth(10).setLineColor(new Color(0, 0, 0, 0))); - put("FormattedTextField.foreground", BeautyEyeLNFHelper.commonForegroundColor); - put("FormattedTextField.inactiveBackground", BeautyEyeLNFHelper.commonBackgroundColor); - put("FormattedTextField.selectionForeground", BeautyEyeLNFHelper.commonSelectionForegroundColor); - put("FormattedTextField.selectionBackground", BeautyEyeLNFHelper.commonSelectionBackgroundColor); - put("FormattedTextFieldUI", BEFormattedTextFieldUI.class); - - UIManager.put("PasswordField.margin", iuir); - put("PasswordField.border", berb); - put("PasswordField.selectionForeground", BeautyEyeLNFHelper.commonSelectionForegroundColor); - put("PasswordField.selectionBackground", BeautyEyeLNFHelper.commonSelectionBackgroundColor); - put("PasswordField.foreground", BeautyEyeLNFHelper.commonForegroundColor); - put("PasswordFieldUI", BEPasswordFieldUI.class); - - UIManager.put("TextArea.margin", iuir); - put("TextArea.border", berb); - put("TextArea.selectionForeground", BeautyEyeLNFHelper.commonSelectionForegroundColor); - put("TextArea.selectionBackground", BeautyEyeLNFHelper.commonSelectionBackgroundColor); - put("TextArea.foreground", BeautyEyeLNFHelper.commonForegroundColor); - put("TextAreaUI", BETextAreaUI.class); - - put("TextPane.border", berb); - put("TextPane.selectionForeground", BeautyEyeLNFHelper.commonSelectionForegroundColor); - put("TextPane.selectionBackground", BeautyEyeLNFHelper.commonSelectionBackgroundColor); - put("TextPane.foreground", BeautyEyeLNFHelper.commonForegroundColor); - put("TextPaneUI", BETextPaneUI.class); - - put("EditorPane.border", berb); - put("EditorPane.selectionForeground", BeautyEyeLNFHelper.commonSelectionForegroundColor); - put("EditorPane.selectionBackground", BeautyEyeLNFHelper.commonSelectionBackgroundColor); - put("EditorPane.foreground", BeautyEyeLNFHelper.commonForegroundColor); - put("EditorPaneUI", BEEditorPaneUI.class); - } - - public interface BgSwitchable { - - void switchBgToNormal(); - - void switchBgToFocused(); - - void switchBgToOver(); - } - - public static class TextSkin implements Skin { - public static final TextSkin INSTANCE = new TextSkin(); - - @Override - public void paintSkinRaw(Graphics g, int x, int y, int w, int h, TMSchema.State state) { - Color border; - switch (state) { - case DISABLED: - border = __UI__.BORDER_DISABLED; - break; - case FOCUSED: - border = __UI__.border_focused(); - break; - case NORMAL: - border = __UI__.BORDER_NORMAL; - break; - case ROLLOVER: - border = __UI__.BORDER_OVER; - break; - default: - return; - } - g.setColor(border); - g.fillRect(x, y, w, h); - } - - public static void paintBg(JComponent c, Graphics g, int x, int y, int w, int h, TMSchema.State state) { - AnimationController.paintSkin(c, INSTANCE, g, x, y, w, h, state); - g.setColor(Color.white); - g.fillRect(x + 2, y + 2, w - 4, h - 4); - } - - @Override - public TMSchema.Part getPart(JComponent c) { - return TMSchema.Part.EP_EDITTEXT; - } - - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/titlepane/BERootPaneUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/titlepane/BERootPaneUI.java deleted file mode 100644 index 5b20f4f58..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/titlepane/BERootPaneUI.java +++ /dev/null @@ -1,1232 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BERootPaneUI.java at 2015-2-1 20:25:40, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.titlepane; - -import java.awt.Component; -import java.awt.Container; -import java.awt.Cursor; -import java.awt.Dialog; -import java.awt.Dimension; -import java.awt.Frame; -import java.awt.HeadlessException; -import java.awt.Insets; -import java.awt.LayoutManager; -import java.awt.LayoutManager2; -import java.awt.MouseInfo; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.Toolkit; -import java.awt.Window; -import java.awt.event.InputEvent; -import java.awt.event.MouseEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.awt.event.WindowListener; -import java.beans.PropertyChangeEvent; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; - -import javax.swing.JComponent; -import javax.swing.JLayeredPane; -import javax.swing.JRootPane; -import javax.swing.LookAndFeel; -import javax.swing.SwingUtilities; -import javax.swing.UIManager; -import javax.swing.border.Border; -import javax.swing.event.MouseInputListener; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; -import javax.swing.plaf.basic.BasicRootPaneUI; - -import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper; -import org.jackhuang.hmcl.laf.utils.WindowTranslucencyHelper; - -/** - * 窗体的UI实现. - * - * @author Jack Jiang(jb2011@163.com) - * @see javax.swing.plaf.metal.MetalRootPaneUI - */ -public class BERootPaneUI extends BasicRootPaneUI { - - /** - * Keys to lookup borders in defaults table. - */ - private static final String[] BORDER_KEYS = new String[] { - null, - "RootPane.frameBorder", - "RootPane.plainDialogBorder", - "RootPane.informationDialogBorder", - "RootPane.errorDialogBorder", - "RootPane.colorChooserDialogBorder", - "RootPane.fileChooserDialogBorder", - "RootPane.questionDialogBorder", - "RootPane.warningDialogBorder" - }; - - //* 2012-09-19 在BeautyEye v3.2中此常量被Jack Jiang取消了,因为 - //* v3.2中启用了相比原MetalRootPaneUI中更精确更好的边框拖放算法 -// /** -// * The amount of space (in pixels) that the cursor is changed on. -// */ -// //MetalLookAndFeel中默认是16 -// private static final int CORNER_DRAG_WIDTH = 16; -// //BeautyEyeLNFHelper.__getFrameBorder_CORNER_DRAG_WIDTH();//为了便 得用户的敏感触点区更大,提高用户体验,此值可加大 - /** - * Region from edges that dragging is active from. - */ - //窗口可拖动敏感触点区域大小要设置多大取决于你知定义border的insets,默认是 5; - private static final int BORDER_DRAG_THICKNESS = 5; - //BeautyEyeLNFHelper.__getFrameBorder_BORDER_DRAG_THICKNESS();//为了便 得用户的敏感触点区更大,提高用户体验,此值可加大 - - /** - * Window the JRootPane is in. - */ - private Window window; - - /** - * JComponent providing window decorations. This will be null - * if not providing window decorations. - */ - private JComponent titlePane; - - /** - * MouseInputListener that is added to the parent - * Window the JRootPane is contained in. - */ - private MouseInputListener mouseInputListener; - - /** - * The LayoutManager that is set on the JRootPane. - */ - private LayoutManager layoutManager; - - /** - * LayoutManager of the JRootPane before we - * replaced it. - */ - private LayoutManager savedOldLayout; - - /** - * JRootPane providing the look and feel for. - */ - private JRootPane root; - - /** - * Cursor used to track the cursor set by the user. This is - * initially Cursor.DEFAULT_CURSOR. - */ - private Cursor lastCursor - = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR); - - /** - * 用于在窗口被激活与不激活时自动设置它的透明度(不激活时设为半透明). - */ - private WindowListener windowsListener = null; - - public static ComponentUI createUI(JComponent c) { - return new BERootPaneUI(); - } - - /** - * Invokes supers implementation of installUI to install the - * necessary state onto the passed in JRootPane to render the - * metal look and feel implementation of RootPaneUI. If the - * windowDecorationStyle property of the JRootPane - * is other than JRootPane.NONE, this will add a custom - * Component to render the widgets to JRootPane, - * as well as installing a custom Border and - * LayoutManager on the JRootPane. - * - * @param c the JRootPane to install state onto - */ - @Override - public void installUI(JComponent c) { - super.installUI(c); - - root = (JRootPane) c; - int style = root.getWindowDecorationStyle(); - - if (style != JRootPane.NONE) - installClientDecorations(root); - } - - /** - * Invokes supers implementation to uninstall any of its state. This will - * also reset the LayoutManager of the JRootPane. - * If a Component has been added to the JRootPane - * to render the window decoration style, this method will remove it. - * Similarly, this will revert the Border and LayoutManager of the - * JRootPane to what it was before installUI was - * invoked. - * - * @param c the JRootPane to uninstall state from - */ - @Override - public void uninstallUI(JComponent c) { - super.uninstallUI(c); - uninstallClientDecorations(root); - - layoutManager = null; - mouseInputListener = null; - root = null; - } - - /** - * Installs the appropriate Border onto the - * JRootPane. - * - * @param root the root - */ - void installBorder(JRootPane root) { - int style = root.getWindowDecorationStyle(); - - if (style == JRootPane.NONE) - LookAndFeel.uninstallBorder(root); - else { - Border b = root.getBorder(); - if (b == null || b instanceof UIResource) { - root.setBorder(null); - root.setBorder(UIManager.getBorder(BORDER_KEYS[style])); - } - } - } - - /** - * Removes any border that may have been installed. - * - * @param root the root - */ - private void uninstallBorder(JRootPane root) { - LookAndFeel.uninstallBorder(root); - } - - /** - * Installs the necessary Listeners on the parent Window, if - * there is one. - *

    - * This takes the parent so that cleanup can be done from - * removeNotify, at which point the parent hasn't been reset - * yet. - * - * @param root the root - * @param parent The parent of the JRootPane - */ - private void installWindowListeners(JRootPane root, Component parent) { - if (parent instanceof Window) - window = (Window) parent; - else - window = SwingUtilities.getWindowAncestor(parent); - if (window != null) { - if (mouseInputListener == null) - mouseInputListener = createWindowMouseInputListener(root); - - window.addMouseListener(mouseInputListener); - window.addMouseMotionListener(mouseInputListener); - - //* add by JS 2011-12-27,给窗口增加监听器:在不活动时设置窗口半透明,活动时还原 - if (BeautyEyeLNFHelper.translucencyAtFrameInactive) { - if (windowsListener == null) - windowsListener = new WindowAdapter() { - @Override - public void windowActivated(WindowEvent e) { - if (window != null) - window.setOpacity(1); - } - - @Override - public void windowDeactivated(WindowEvent e) { - if (window != null) - window.setOpacity(0.94f); - } - }; - window.addWindowListener(windowsListener); - } - } - } - - /** - * Uninstalls the necessary Listeners on the Window the - * Listeners were last installed on. - * - * @param root the root - */ - private void uninstallWindowListeners(JRootPane root) { - if (window != null) { - window.removeMouseListener(mouseInputListener); - window.removeMouseMotionListener(mouseInputListener); - } - } - - /** - * Installs the appropriate LayoutManager on the JRootPane to - * render the window decorations. - * - * @param root the root - */ - private void installLayout(JRootPane root) { - if (layoutManager == null) - layoutManager = createLayoutManager(); - savedOldLayout = root.getLayout(); - root.setLayout(layoutManager); - } - - /** - * Uninstalls the previously installed LayoutManager. - * - * @param root the root - */ - private void uninstallLayout(JRootPane root) { - if (savedOldLayout != null) { - root.setLayout(savedOldLayout); - savedOldLayout = null; - } - } - - /** - * Installs the necessary state onto the JRootPane to render client - * decorations. This is ONLY invoked if the JRootPane has a - * decoration style other than JRootPane.NONE. - * - * @param root the root - */ - private void installClientDecorations(JRootPane root) { - installBorder(root); - - JComponent p = createTitlePane(root); - - setTitlePane(root, p); - installWindowListeners(root, root.getParent()); - installLayout(root); - - //只有在窗口边框是半透明的情况下,以下才需要设置窗口透明 - //* 注意:本类中的此处代码的目的就是为了实现半透明边框窗口的 - //* 正常显示,而且仅针对此目的。如果该边框不为透明,则此处也就不需要设置 - //* 窗口透明了,那么如果你的程序其它地方需要窗口透明的话,自行.setWindowOpaque(..) - //* 就行了,由开发者自先决定,此处就不承载过多的要求了 - if (!BeautyEyeLNFHelper.isFrameBorderOpaque() - && window != null && WindowTranslucencyHelper.isTranslucencySupported()) { - //** 20111222 by jb2011,让窗口全透明(用以实现窗口的透明边框效果) -// AWTUtilities.setWindowOpaque(window, false); - // TODO BUG:1)目前可知,在jdk1.7.0_u6下,JDialog的半透明边框的透明度比原设计深一倍 - // TODO BUG:2)目前可知,在jdk1.6.0_u33下+win7平台下,JFrame窗口被调置成透明后, - // 该窗口内所在文本都会被反走样(不管你要没有要求反走样),真悲具,这应该 - // 是官方AWTUtilities.setWindowOpaque(..)bug导致的,1.7.0_u6同样存在该问题, - // 使用BeautyEye时,遇到这样的问题只能自行使用__isFrameBorderOpaque中指定的 - // 不透明边框才行(这样此类的以下代码就不用执行,也就不用触发该bug了),但 - // JDialog不受此bug影响,诡异! - WindowTranslucencyHelper.setWindowOpaque(window, false); - root.revalidate(); - root.repaint(); - } - } - - /** - * Uninstalls any state that installClientDecorations has - * installed. - *

    - * NOTE: This may be called if you haven't installed client decorations yet - * (ie before installClientDecorations has been invoked). - * - * @param root the root - */ - private void uninstallClientDecorations(JRootPane root) { - uninstallBorder(root); - uninstallWindowListeners(root); - setTitlePane(root, null); - uninstallLayout(root); - // We have to revalidate/repaint root if the style is JRootPane.NONE - // only. When we needs to call revalidate/repaint with other styles - // the installClientDecorations is always called after this method - // imediatly and it will cause the revalidate/repaint at the proper - // time. - int style = root.getWindowDecorationStyle(); - if (style == JRootPane.NONE) { - root.repaint(); - root.revalidate(); - } - // Reset the cursor, as we may have changed it to a resize cursor - if (window != null) - window.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - window = null; - } - - /** - * Returns the JComponent to render the window decoration - * style. - * - * @param root the root - * @return the j component - */ - private JComponent createTitlePane(JRootPane root) { - return new BETitlePane(root, this); - } - - /** - * Returns a MouseListener that will be added to the - * Window containing the JRootPane. - * - * @param root the root - * @return the mouse input listener - */ - private MouseInputListener createWindowMouseInputListener(JRootPane root) { - return new MouseInputHandler(); - } - - /** - * Returns a LayoutManager that will be set on the - * JRootPane. - * - * @return the layout manager - */ - private LayoutManager createLayoutManager() { - return new XMetalRootLayout(); - } - - /** - * Sets the window title pane -- the JComponent used to provide a plaf a way - * to override the native operating system's window title pane with one - * whose look and feel are controlled by the plaf. The plaf creates and sets - * this value; the default is null, implying a native operating system - * window title pane. - * - * @param root the root - * @param titlePane the title pane - */ - private void setTitlePane(JRootPane root, JComponent titlePane) { - JLayeredPane layeredPane = root.getLayeredPane(); - JComponent oldTitlePane = getTitlePane(); - - if (oldTitlePane != null) { - oldTitlePane.setVisible(false); - layeredPane.remove(oldTitlePane); - } - if (titlePane != null) { - layeredPane.add(titlePane, JLayeredPane.FRAME_CONTENT_LAYER); - titlePane.setVisible(true); - } - this.titlePane = titlePane; - } - - /** - * Returns the JComponent rendering the title pane. If this - * returns null, it implies there is no need to render window decorations. - * - * @return the current window title pane, or null - * @see #setTitlePane - */ - private JComponent getTitlePane() { - return titlePane; - } - - /** - * Returns the JRootPane we're providing the look and feel for. - * - * @return the root pane - */ - private JRootPane getRootPane() { - return root; - } - - /** - * Invoked when a property changes. MetalRootPaneUI is - * primarily interested in events originating from the - * JRootPane it has been installed on identifying the property - * windowDecorationStyle. If the - * windowDecorationStyle has changed to a value other than - * JRootPane.NONE, this will add a Component to - * the JRootPane to render the window decorations, as well as - * installing a Border on the JRootPane. On the - * other hand, if the windowDecorationStyle has changed to - * JRootPane.NONE, this will remove the Component - * that has been added to the JRootPane as well resetting the - * Border to what it was before installUI was invoked. - * - * @param e A PropertyChangeEvent object describing the event source and the - * property that has changed. - */ - @Override - public void propertyChange(PropertyChangeEvent e) { - super.propertyChange(e); - - String propertyName = e.getPropertyName(); - if (propertyName == null) - return; - - if (propertyName.equals("windowDecorationStyle")) { - JRootPane r = (JRootPane) e.getSource(); - int style = r.getWindowDecorationStyle(); - - // This is potentially more than needs to be done, - // but it rarely happens and makes the install/uninstall process - // simpler. MetalTitlePane also assumes it will be recreated if - // the decoration style changes. - uninstallClientDecorations(r); - if (style != JRootPane.NONE) - installClientDecorations(r); - } else if (propertyName.equals("ancestor")) { - uninstallWindowListeners(root); - if (((JRootPane) e.getSource()).getWindowDecorationStyle() - != JRootPane.NONE) - installWindowListeners(root, root.getParent()); - } - } - - /** - * A custom layout manager that is responsible for the layout of - * layeredPane, glassPane, menuBar and titlePane, if one has been installed. - */ - // NOTE: Ideally this would extends JRootPane.RootLayout, but that - // would force this to be non-static. - private static class XMetalRootLayout implements LayoutManager2 { - - /** - * Returns the amount of space the layout would like to have. - * - * @param parent the parent - * @return a Dimension object containing the layout's preferred size - */ - @Override - public Dimension preferredLayoutSize(Container parent) { - Dimension cpd, mbd, tpd; - int cpWidth = 0; - int cpHeight = 0; - int mbWidth = 0; - int mbHeight = 0; - int tpWidth = 0; - int tpHeight = 0; - Insets i = parent.getInsets(); - JRootPane root = (JRootPane) parent; - - if (root.getContentPane() != null) - cpd = root.getContentPane().getPreferredSize(); - else - cpd = root.getSize(); - if (cpd != null) { - cpWidth = cpd.width; - cpHeight = cpd.height; - } - - if (root.getMenuBar() != null) { - mbd = root.getMenuBar().getPreferredSize(); - if (mbd != null) { - mbWidth = mbd.width; - mbHeight = mbd.height; - } - } - - if (root.getWindowDecorationStyle() != JRootPane.NONE - && (root.getUI() instanceof BERootPaneUI)) { - JComponent titlePane = ((BERootPaneUI) root.getUI()). - getTitlePane(); - if (titlePane != null) { - tpd = titlePane.getPreferredSize(); - if (tpd != null) { - tpWidth = tpd.width; - tpHeight = tpd.height; - } - } - } - - return new Dimension(Math.max(Math.max(cpWidth, mbWidth), tpWidth) + i.left + i.right, - cpHeight + mbHeight + tpWidth + i.top + i.bottom); - } - - /** - * Returns the minimum amount of space the layout needs. - * - * @param parent the parent - * @return a Dimension object containing the layout's minimum size - */ - @Override - public Dimension minimumLayoutSize(Container parent) { - Dimension cpd, mbd, tpd; - int cpWidth = 0; - int cpHeight = 0; - int mbWidth = 0; - int mbHeight = 0; - int tpWidth = 0; - int tpHeight = 0; - Insets i = parent.getInsets(); - JRootPane root = (JRootPane) parent; - - if (root.getContentPane() != null) - cpd = root.getContentPane().getMinimumSize(); - else - cpd = root.getSize(); - if (cpd != null) { - cpWidth = cpd.width; - cpHeight = cpd.height; - } - - if (root.getMenuBar() != null) { - mbd = root.getMenuBar().getMinimumSize(); - if (mbd != null) { - mbWidth = mbd.width; - mbHeight = mbd.height; - } - } - if (root.getWindowDecorationStyle() != JRootPane.NONE - && (root.getUI() instanceof BERootPaneUI)) { - JComponent titlePane = ((BERootPaneUI) root.getUI()). - getTitlePane(); - if (titlePane != null) { - tpd = titlePane.getMinimumSize(); - if (tpd != null) { - tpWidth = tpd.width; - tpHeight = tpd.height; - } - } - } - - return new Dimension(Math.max(Math.max(cpWidth, mbWidth), tpWidth) + i.left + i.right, - cpHeight + mbHeight + tpWidth + i.top + i.bottom); - } - - /** - * Returns the maximum amount of space the layout can use. - * - * @param target the target - * @return a Dimension object containing the layout's maximum size - */ - @Override - public Dimension maximumLayoutSize(Container target) { - Dimension cpd, mbd, tpd; - int cpWidth = Integer.MAX_VALUE; - int cpHeight = Integer.MAX_VALUE; - int mbWidth = Integer.MAX_VALUE; - int mbHeight = Integer.MAX_VALUE; - int tpWidth = Integer.MAX_VALUE; - int tpHeight = Integer.MAX_VALUE; - Insets i = target.getInsets(); - JRootPane root = (JRootPane) target; - - if (root.getContentPane() != null) { - cpd = root.getContentPane().getMaximumSize(); - if (cpd != null) { - cpWidth = cpd.width; - cpHeight = cpd.height; - } - } - - if (root.getMenuBar() != null) { - mbd = root.getMenuBar().getMaximumSize(); - if (mbd != null) { - mbWidth = mbd.width; - mbHeight = mbd.height; - } - } - - if (root.getWindowDecorationStyle() != JRootPane.NONE - && (root.getUI() instanceof BERootPaneUI)) { - JComponent titlePane = ((BERootPaneUI) root.getUI()). - getTitlePane(); - if (titlePane != null) { - tpd = titlePane.getMaximumSize(); - if (tpd != null) { - tpWidth = tpd.width; - tpHeight = tpd.height; - } - } - } - - int maxHeight = Math.max(Math.max(cpHeight, mbHeight), tpHeight); - // Only overflows if 3 real non-MAX_VALUE heights, sum to > MAX_VALUE - // Only will happen if sums to more than 2 billion units. Not likely. - if (maxHeight != Integer.MAX_VALUE) - maxHeight = cpHeight + mbHeight + tpHeight + i.top + i.bottom; - - int maxWidth = Math.max(Math.max(cpWidth, mbWidth), tpWidth); - // Similar overflow comment as above - if (maxWidth != Integer.MAX_VALUE) - maxWidth += i.left + i.right; - - return new Dimension(maxWidth, maxHeight); - } - - /** - * Instructs the layout manager to perform the layout for the specified - * container. - * - * @param parent the parent - */ - @Override - public void layoutContainer(Container parent) { - JRootPane root = (JRootPane) parent; - Rectangle b = root.getBounds(); - Insets i = root.getInsets(); - int nextY = 0; - int w = b.width - i.right - i.left; - int h = b.height - i.top - i.bottom; - - if (root.getLayeredPane() != null) - root.getLayeredPane().setBounds(i.left, i.top, w, h); - if (root.getGlassPane() != null) - root.getGlassPane().setBounds(i.left, i.top, w, h); - // Note: This is laying out the children in the layeredPane, - // technically, these are not our children. - if (root.getWindowDecorationStyle() != JRootPane.NONE - && (root.getUI() instanceof BERootPaneUI)) { - JComponent titlePane = ((BERootPaneUI) root.getUI()). - getTitlePane(); - if (titlePane != null) { - Dimension tpd = titlePane.getPreferredSize(); - if (tpd != null) { - int tpHeight = tpd.height; - titlePane.setBounds(0, 0, w, tpHeight); - nextY += tpHeight; - } - } - } - if (root.getJMenuBar() != null - //* 该 行代码由Jack Jiang于2012-10-20增加:目的是为解决当 - //* MebuBar被设置不可见时任然被错误地当作可视组件占据布局空间,这 - //* 在BE LNF中的表现就是当menuBar不可见,它占据的那块空间将会是全透明 - //* 的空白区。这个问题在Metal主题中仍然存在(就是设置JFrame.setDefaultLookAndFeelDecorated(true); - //* JDialog.setDefaultLookAndFeelDecorated(true);后的Metal主题状态), - //* 可能官方不认为这是个bug吧。 - //* 为什么无论什么外观当在使用系统窗口边框类型时不会出现这样的情况呢?它 - //* 可能是由于窗口外观的实现原理决定的吧(按理说是同一原理),有待深究!!! - && root.getJMenuBar().isVisible()) { - Dimension mbd = root.getJMenuBar().getPreferredSize(); - root.getJMenuBar().setBounds(0, nextY, w, mbd.height); - nextY += mbd.height; - } - if (root.getContentPane() != null - //* 该 行代码由Jack Jiang于2012-10-20增加:目的是为解决与menubar在设置可见性时遇难到的一样的问题 - && root.getContentPane().isVisible()) { - Dimension cpd = root.getContentPane().getPreferredSize(); - root.getContentPane().setBounds(0, nextY, w, - h < nextY ? 0 : h - nextY); - } - } - - @Override - public void addLayoutComponent(String name, Component comp) { - } - - @Override - public void removeLayoutComponent(Component comp) { - } - - @Override - public void addLayoutComponent(Component comp, Object constraints) { - } - - @Override - public float getLayoutAlignmentX(Container target) { - return 0.0f; - } - - @Override - public float getLayoutAlignmentY(Container target) { - return 0.0f; - } - - @Override - public void invalidateLayout(Container target) { - } - } - - /** - * Maps from positions to cursor type. Refer to calculateCorner and - * calculatePosition for details of this. - */ - private static final int[] cursorMapping = new int[] { Cursor.NW_RESIZE_CURSOR, - Cursor.NW_RESIZE_CURSOR, - Cursor.N_RESIZE_CURSOR, - Cursor.NE_RESIZE_CURSOR, - Cursor.NE_RESIZE_CURSOR, - Cursor.NW_RESIZE_CURSOR, - 0, - 0, - 0, - Cursor.NE_RESIZE_CURSOR, - Cursor.W_RESIZE_CURSOR, - 0, - 0, - 0, - Cursor.E_RESIZE_CURSOR, - Cursor.SW_RESIZE_CURSOR, - 0, - 0, - 0, - Cursor.SE_RESIZE_CURSOR, - Cursor.SW_RESIZE_CURSOR, - Cursor.SW_RESIZE_CURSOR, - Cursor.S_RESIZE_CURSOR, - Cursor.SE_RESIZE_CURSOR, - Cursor.SE_RESIZE_CURSOR - }; - - /** - * MouseInputHandler is responsible for handling resize/moving of the - * Window. It sets the cursor directly on the Window when then mouse moves - * over a hot spot. - */ - private class MouseInputHandler implements MouseInputListener { - - /** - * Set to true if the drag operation is moving the window. - */ - private boolean isMovingWindow; - - /** - * Used to determine the corner the resize is occuring from. - */ - private int dragCursor; - - /** - * X location the mouse went down on for a drag operation. - */ - private int dragOffsetX; - - /** - * Y location the mouse went down on for a drag operation. - */ - private int dragOffsetY; - - /** - * Width of the window when the drag started. - */ - private int dragWidth; - - /** - * Height of the window when the drag started. - */ - private int dragHeight; - - /* - * PrivilegedExceptionAction needed by mouseDragged method to - * obtain new location of window on screen during the drag. - */ - /** - * The get location action. - */ - private final PrivilegedExceptionAction getLocationAction = new PrivilegedExceptionAction() { - @Override - public Object run() throws HeadlessException { - return MouseInfo.getPointerInfo().getLocation(); - } - }; - - @Override - public void mousePressed(MouseEvent ev) { - JRootPane rootPane = getRootPane(); - - if (rootPane.getWindowDecorationStyle() == JRootPane.NONE) - return; - Point dragWindowOffset = ev.getPoint(); - Window w = (Window) ev.getSource(); - if (w != null) - w.toFront(); - Point convertedDragWindowOffset = SwingUtilities.convertPoint(w, - dragWindowOffset, getTitlePane()); - - Frame f = null; - Dialog d = null; - - if (w instanceof Frame) - f = (Frame) w; - else if (w instanceof Dialog) - d = (Dialog) w; - - int frameState = (f != null) ? f.getExtendedState() : 0; - - if (getTitlePane() != null - && getTitlePane().contains(convertedDragWindowOffset)) { - if ((f != null && ((frameState & Frame.MAXIMIZED_BOTH) == 0) || (d != null)) - && dragWindowOffset.y >= BORDER_DRAG_THICKNESS - && dragWindowOffset.x >= BORDER_DRAG_THICKNESS - && dragWindowOffset.x < w.getWidth() - - BORDER_DRAG_THICKNESS) { - isMovingWindow = true; - dragOffsetX = dragWindowOffset.x; - dragOffsetY = dragWindowOffset.y; - } - } else if (f != null && f.isResizable() - && ((frameState & Frame.MAXIMIZED_BOTH) == 0) - || (d != null && d.isResizable())) { -// System.out.println("dragOffsetX="+dragOffsetX+" dragOffsetY="+dragOffsetY); TODO - dragOffsetX = dragWindowOffset.x; - dragOffsetY = dragWindowOffset.y; - dragWidth = w.getWidth(); - dragHeight = w.getHeight(); - dragCursor - = // getCursor(calculateCorner(w, dragWindowOffset.x,dragWindowOffset.y)); // TODO TEST - getCursor_new(w, dragWindowOffset.x, dragWindowOffset.y); - } - } - - @Override - public void mouseReleased(MouseEvent ev) { - if (dragCursor != 0 && window != null && !window.isValid()) { - // Some Window systems validate as you resize, others won't, - // thus the check for validity before repainting. - window.validate(); - getRootPane().repaint(); - } - isMovingWindow = false; - dragCursor = 0; - } - - @Override - public void mouseMoved(MouseEvent ev) { - JRootPane root = getRootPane(); - - if (root.getWindowDecorationStyle() == JRootPane.NONE) - return; - - Window w = (Window) ev.getSource(); - - Frame f = null; - Dialog d = null; - - if (w instanceof Frame) - f = (Frame) w; - else if (w instanceof Dialog) - d = (Dialog) w; - - // Update the cursor - int cursor - = //接下来1)测试算法的正确性 2)测试极端情况:即border小于或部分小于BORDER_THINNESS,3)写注释、整理代码! - // getCursor(calculateCorner(w, ev.getX(), ev.getY()));// TODO Test!! - getCursor_new(w, ev.getX(), ev.getY()); - - if (cursor != 0 - && ((f != null && (f.isResizable() && (f.getExtendedState() & Frame.MAXIMIZED_BOTH) == 0)) || (d != null && d - .isResizable()))) - w.setCursor(Cursor.getPredefinedCursor(cursor)); - else - w.setCursor(lastCursor); - } - - /** - * Adjust. - * - * @param bounds the bounds - * @param min the min - * @param deltaX the delta x - * @param deltaY the delta y - * @param deltaWidth the delta width - * @param deltaHeight the delta height - */ - private void adjust(Rectangle bounds, Dimension min, int deltaX, - int deltaY, int deltaWidth, int deltaHeight) { - bounds.x += deltaX; - bounds.y += deltaY; - bounds.width += deltaWidth; - bounds.height += deltaHeight; - if (min != null) { - if (bounds.width < min.width) { - int correction = min.width - bounds.width; - if (deltaX != 0) - bounds.x -= correction; - bounds.width = min.width; - } - if (bounds.height < min.height) { - int correction = min.height - bounds.height; - if (deltaY != 0) - bounds.y -= correction; - bounds.height = min.height; - } - } - } - - @Override - public void mouseDragged(MouseEvent ev) { - Window w = (Window) ev.getSource(); - Point pt = ev.getPoint(); - - if (isMovingWindow) { - Point windowPt; - try { - windowPt = (Point) AccessController - .doPrivileged(getLocationAction); - windowPt.x = windowPt.x - dragOffsetX; - windowPt.y = windowPt.y - dragOffsetY; - w.setLocation(windowPt); - } catch (PrivilegedActionException e) { - } - } else if (dragCursor != 0) { - Rectangle r = w.getBounds(); - Rectangle startBounds = new Rectangle(r); - Dimension min = w.getMinimumSize(); - - switch (dragCursor) { - case Cursor.E_RESIZE_CURSOR: - adjust(r, min, 0, 0, pt.x + (dragWidth - dragOffsetX) - - r.width, 0); - break; - case Cursor.S_RESIZE_CURSOR: - adjust(r, min, 0, 0, 0, pt.y - + (dragHeight - dragOffsetY) - r.height); - break; - case Cursor.N_RESIZE_CURSOR: - adjust(r, min, 0, pt.y - dragOffsetY, 0, - -(pt.y - dragOffsetY)); - break; - case Cursor.W_RESIZE_CURSOR: - adjust(r, min, pt.x - dragOffsetX, 0, - -(pt.x - dragOffsetX), 0); - break; - case Cursor.NE_RESIZE_CURSOR: - adjust(r, min, 0, pt.y - dragOffsetY, pt.x - + (dragWidth - dragOffsetX) - r.width, - -(pt.y - dragOffsetY)); - break; - case Cursor.SE_RESIZE_CURSOR: - adjust(r, min, 0, 0, pt.x + (dragWidth - dragOffsetX) - - r.width, pt.y + (dragHeight - dragOffsetY) - - r.height); - break; - case Cursor.NW_RESIZE_CURSOR: - adjust(r, min, pt.x - dragOffsetX, pt.y - dragOffsetY, - -(pt.x - dragOffsetX), -(pt.y - dragOffsetY)); - break; - case Cursor.SW_RESIZE_CURSOR: - adjust(r, min, pt.x - dragOffsetX, 0, - -(pt.x - dragOffsetX), pt.y - + (dragHeight - dragOffsetY) - r.height); - break; - default: - break; - } - if (!r.equals(startBounds)) { - w.setBounds(r); - // Defer repaint/validate on mouseReleased unless dynamic - // layout is active. - if (Toolkit.getDefaultToolkit().isDynamicLayoutActive()) { - w.validate(); - getRootPane().repaint(); - } - } - } - } - - @Override - public void mouseEntered(MouseEvent ev) { - Window w = (Window) ev.getSource(); - lastCursor = w.getCursor(); - mouseMoved(ev); - } - - @Override - public void mouseExited(MouseEvent ev) { - Window w = (Window) ev.getSource(); - // TODO ###### Hack:因Swing鼠标事件问题,拖动过快的话很多时候没法正常地保留和设置lastCursor - // 从而导致经常性的退出拖动后,拖动时的鼠标样式还在,这样很不爽,这应该是swing - // 的鼠标事件不精确导致的或其它问题。目前不如干脃在退出拖动时强制还原到默认鼠标, - // 虽然在极少情况下可能回不到用户真正的lastCursor,但起码能解决目前在BueatyEye中 - // 因大border而频繁出现的这个问题了,先这么滴吧! -// w.setCursor(lastCursor); - w.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - } - - @Override - public void mouseClicked(MouseEvent ev) { - Window w = (Window) ev.getSource(); - Frame f; - - if (w instanceof Frame) - f = (Frame) w; - else - return; - - Point convertedPoint = SwingUtilities.convertPoint(w, - ev.getPoint(), getTitlePane()); - - int state = f.getExtendedState(); - if (getTitlePane() != null - && getTitlePane().contains(convertedPoint)) - if ((ev.getClickCount() % 2) == 0 - && ((ev.getModifiers() & InputEvent.BUTTON1_MASK) != 0)) - if (f.isResizable()) - if ((state & Frame.MAXIMIZED_BOTH) != 0) - f.setExtendedState(state & ~Frame.MAXIMIZED_BOTH); - else - f.setExtendedState(state | Frame.MAXIMIZED_BOTH); - } - - //*************************************************************** v3.2前参考自MetalRootPaneUI中的老边框拖放核心算法 START - //** 老算法说明:Metal中的算法是假设窗口边框的border是规划的,即上下左右的inset都是一样的,它假定可拖动范围是整个 - //** 窗体大小(包括border在内的大小)的BORDER_DRAG_THICKNESS常量范围内的上下左右区域,所以它的 算法在 - //** 此前题下通过较巧妙的方法简单实现没有问题。 - //** 老算法缺陷:当窗口的边框不规划,如FrameBorderStyle.translucencyAppleLik这种时(上=17,左=27,右=27,下=37), - //** 此情况下只能假定一个最小值了,以前是取的17作为统一边框范围距离,那么像下部原本是37的inset,现在拖动 - //** 范围是17,余下的原本是border里insets的10个像素也被算进窗口内容面板了,这样导致移动到下方时,明明 - //** 是在边缘位置,却不是处于拖动范围内(要再往下移10像素到达inset的第10~27像素范围内才行),这样就严重 - //** 影响了用户体验。 - //* 2012-09-19 在BeautyEye v3.2中的BERootPaneUI,Jack Jiang启用了相比 - //* 原MetalRootPaneUI中更精确更好的边框拖放算法,以下方法暂时弃用,以后可以删除了! START -// /** -// * Returns the corner that contains the point x, -// * y, or -1 if the position doesn't match a corner. -// */ -// private int calculateCorner(Window w, int x, int y) -// { -// Insets insets = w.getInsets(); -// int xPosition = calculatePosition(x - insets.left, w.getWidth() -// - insets.left - insets.right); -// int yPosition = calculatePosition(y - insets.top, w.getHeight() -// - insets.top - insets.bottom); -// -// if (xPosition == -1 || yPosition == -1) -// { -// return -1; -// } -// return yPosition * 5 + xPosition; -// } -// /** -// * Returns the Cursor to render for the specified corner. This returns -// * 0 if the corner doesn't map to a valid Cursor -// */ -// private int getCursor(int corner) -// { -// if (corner == -1) -// { -// return 0; -// } -// return cursorMapping[corner]; -// } -// /** -// * Returns an integer indicating the position of spot -// * in width. The return value will be: -// * 0 if < BORDER_DRAG_THICKNESS -// * 1 if < CORNER_DRAG_WIDTH -// * 2 if >= CORNER_DRAG_WIDTH && < width - BORDER_DRAG_THICKNESS -// * 3 if >= width - CORNER_DRAG_WIDTH -// * 4 if >= width - BORDER_DRAG_THICKNESS -// * 5 otherwise -// */ -// private int calculatePosition(int spot, int width) -// { -//// Insets iss = getRootPane().getInsets(); -//// System.out.println("ississ="+iss); //TODO -// -// if (spot < BORDER_DRAG_THICKNESS) -// { -// return 0; -// } -// if (spot < CORNER_DRAG_WIDTH) -// { -// return 1; -// } -// if (spot >= (width - BORDER_DRAG_THICKNESS)) -// { -// return 4; -// } -// if (spot >= (width - CORNER_DRAG_WIDTH)) -// { -// return 3; -// } -// return 2; -// }//********************************************************************* v3.2前的老边框拖放核心算法 END - //********************************************************************* v3.2版启用的新边框拖放核心算法 SART - //** 新算法说明:v3.2中启用的新算法的原理是把可拖动范围限定在内容区(即整个窗体大小减去Border后的真正工作区) - //** 往外的一个固定的BORDER_DRAG_THICKNESS区域内,即不管理你把窗口的border设置多么不规划,我的用户拖 - //** 动区永远是这一个范围内,这就保证用户体验,较好的解决了老算法的缺陷。 - /** - * Gets the cursor_new. - * - * @param w the w - * @param x the x - * @param y the y - * @return the cursor_new - */ - public int getCursor_new(Window w, int x, int y) { - Insets insets = w.getInsets(); - return getCursor_new(x - insets.left, y - insets.top, - w.getWidth() - insets.left - insets.right, - w.getHeight() - insets.top - insets.bottom); - } - - /** - * 新的窗口边框拖动算法的实现是把可拖动区分成8个距形区,当鼠标动到对应 - * 的区里就计算出是是向哪个方向拖动,比MetalRootPaneUI中的简易方法要明确和精确。 - *

    - * 可拖动判断区示意图:
    - * 红色到蓝色的整个区域是窗口的border范围,红色到灰色的区域是固定的可拖动区,红色到灰色的区域是固定的, - * 红色到蓝色的区域因border不同而不一样。
    - * 注意:算法中要注意一种极端情况,就是Border的一部分或全部都小于可拖动区的情况,以下算法应该也 - * 是没有问题的,无非算出的8可拖动距形区坐标有负的情况,初步测试过没影响,以后还是注意一下! - * - * - * - * - *
    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    R1R2R3
    R8可视工作区R4
    R7R6R5
    - *
    . - * - * @param x the x - * @param y the y - * @param w the w - * @param h the h - * @return the cursor_new - */ - public int getCursor_new(int x, int y, int w, int h) { - int B = BORDER_DRAG_THICKNESS; - - Insets iss = getRootPane().getInsets(); - int topI = iss.top, bottomI = iss.bottom, leftI = iss.left, rightI = iss.right; - - //8个拖动检测距形区 - Rectangle r1 = new Rectangle(leftI - B, topI - B, B, B); - Rectangle r2 = new Rectangle(leftI, topI - B, w - leftI - rightI, B); - Rectangle r3 = new Rectangle(w - rightI, topI - B, B, B); - Rectangle r4 = new Rectangle(w - rightI, topI, B, h - topI - bottomI); - Rectangle r5 = new Rectangle(w - rightI, h - bottomI, B, B); - Rectangle r6 = new Rectangle(leftI, h - bottomI, w - leftI - rightI, B); - Rectangle r7 = new Rectangle(leftI - B, h - bottomI, B, B); - Rectangle r8 = new Rectangle(leftI - B, topI, B, h - topI - bottomI); - - Point p = new Point(x, y); - int cc = 0; - - if (r1.contains(p)) - cc = Cursor.NW_RESIZE_CURSOR; - else if (r3.contains(p)) - cc = Cursor.NE_RESIZE_CURSOR; - else if (r5.contains(p)) - cc = Cursor.SE_RESIZE_CURSOR; - else if (r7.contains(p)) - cc = Cursor.SW_RESIZE_CURSOR; - else if (r2.contains(p)) - cc = Cursor.N_RESIZE_CURSOR; - else if (r4.contains(p)) - cc = Cursor.E_RESIZE_CURSOR; - else if (r6.contains(p)) - cc = Cursor.S_RESIZE_CURSOR; - else if (r8.contains(p)) - cc = Cursor.W_RESIZE_CURSOR; - - return cc; - } - }//********************************************************************* v3.2版启用的新边框拖放核心算法 END -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/titlepane/BETitlePane.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/titlepane/BETitlePane.java deleted file mode 100644 index aceac56c6..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/titlepane/BETitlePane.java +++ /dev/null @@ -1,1259 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BETitlePane.java at 2015-2-1 20:25:36, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.titlepane; - -import java.awt.Color; -import java.awt.Component; -import java.awt.Container; -import java.awt.Dialog; -import java.awt.Dimension; -import java.awt.FontMetrics; -import java.awt.Frame; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.GraphicsConfiguration; -import java.awt.Image; -import java.awt.Insets; -import java.awt.LayoutManager; -import java.awt.Paint; -import java.awt.Rectangle; -import java.awt.Toolkit; -import java.awt.Window; -import java.awt.event.ActionEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.awt.event.WindowListener; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.util.Locale; - -import javax.swing.AbstractAction; -import javax.swing.AbstractButton; -import javax.swing.Action; -import javax.swing.Icon; -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.JMenu; -import javax.swing.JMenuBar; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.JRootPane; -import javax.swing.JSeparator; -import javax.swing.SwingUtilities; -import javax.swing.UIManager; -import javax.swing.border.Border; -import javax.swing.border.EmptyBorder; -import javax.swing.plaf.UIResource; - -import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper; -import org.jackhuang.hmcl.laf.BEUtils; -import org.jackhuang.hmcl.laf.utils.MySwingUtilities2; - -/** - * 窗体的标题栏UI实现. - * - * @author Jack Jiang(jb2011@163.com) - * @see javax.swing.plaf.metal.MetalTitlePane//(Java 1.5) - */ -public class BETitlePane extends JComponent { -// MetalTitlePane - -// MetalLookAndFeel -// WindowsLookAndFeel - /** - * The Constant handyEmptyBorder. - */ - private static final Border handyEmptyBorder = new EmptyBorder(0, 0, 0, 0); - - /** - * The Constant IMAGE_HEIGHT. - */ - private static final int IMAGE_HEIGHT = 16; - - /** - * The Constant IMAGE_WIDTH. - */ - private static final int IMAGE_WIDTH = 16; - - /** - * PropertyChangeListener added to the JRootPane. - */ - private PropertyChangeListener propertyChangeListener; - - /** - * JMenuBar, typically renders the system menu items. - */ - private JMenuBar menuBar; - /** - * Action used to close the Window. - */ - private Action closeAction; - - /** - * Action used to iconify the Frame. - */ - private Action iconifyAction; - - /** - * Action to restore the Frame size. - */ - private Action restoreAction; - - /** - * Action to restore the Frame size. - */ - private Action maximizeAction; - - /** - * 设置action(功能暂未实现!). - */ - private Action setupAction; - - /** - * Button used to maximize or restore the Frame. - */ - private JButton toggleButton; - - /** - * Button used to maximize or restore the Frame. - */ - private JButton iconifyButton; - - /** - * Button used to maximize or restore the Frame. - */ - private JButton closeButton; - - /** - * Icon used for toggleButton when window is normal size. - */ - private Icon maximizeIcon; - private Icon maximizeIcon_rover; - private Icon maximizeIcon_pressed; - - /** - * Icon used for toggleButton when window is maximized. - */ - private Icon minimizeIcon; - private Icon minimizeIcon_rover; - private Icon minimizeIcon_pressed; - - /** - * 设置按钮(功能暂未实现!). - */ - private JButton setupButton; - - /** - * Listens for changes in the state of the Window listener to update the - * state of the widgets. - */ - private WindowListener windowListener; - - /** - * Window we're currently in. - */ - private Window window; - - /** - * JRootPane rendering for. - */ - private JRootPane rootPane; - - /** - * Room remaining in title for bumps. - */ - private int buttonsWidth; - - /** - * Buffered Frame.state property. As state isn't bound, this is kept to - * determine when to avoid updating widgets. - */ - private int state; - - /** - * MetalRootPaneUI that created us. - */ - private BERootPaneUI rootPaneUI; - - // Colors - /** - * The inactive background. - */ - private Color inactiveBackground = UIManager.getColor("inactiveCaption"); - - /** - * The inactive foreground. - */ - private Color inactiveForeground = UIManager.getColor("inactiveCaptionText"); - - /** - * The inactive shadow. - */ - private Color inactiveShadow = UIManager.getColor("inactiveCaptionBorder"); - - /** - * The active background. - */ - private Color activeBackground = null; - - /** - * The active foreground. - */ - private Color activeForeground = null; - - /** - * The active shadow. - */ - private Color activeShadow = null; - - /** - * Instantiates a new bE title pane. - * - * @param root the root - * @param ui the ui - */ - public BETitlePane(JRootPane root, BERootPaneUI ui) { - this.rootPane = root; - rootPaneUI = ui; - - state = -1; - - installSubcomponents(); - determineColors(); - installDefaults(); - - setLayout(createLayout()); - } - - /** - * Uninstalls the necessary state. - */ - private void uninstall() { - uninstallListeners(); - window = null; - removeAll(); - } - - /** - * Installs the necessary listeners. - */ - private void installListeners() { - if (window != null) { - windowListener = createWindowListener(); - window.addWindowListener(windowListener); - propertyChangeListener = createWindowPropertyChangeListener(); - window.addPropertyChangeListener(propertyChangeListener); - } - } - - /** - * Uninstalls the necessary listeners. - */ - private void uninstallListeners() { - if (window != null) { - window.removeWindowListener(windowListener); - window.removePropertyChangeListener(propertyChangeListener); - } - } - - /** - * Returns the WindowListener to add to the - * Window. - * - * @return the window listener - */ - private WindowListener createWindowListener() { - return new WindowHandler(); - } - - /** - * Returns the PropertyChangeListener to install on the - * Window. - * - * @return the property change listener - */ - private PropertyChangeListener createWindowPropertyChangeListener() { - return new PropertyChangeHandler(); - } - - /** - * Returns the JRootPane this was created for. - * - * @return the root pane - */ - @Override - public JRootPane getRootPane() { - return rootPane; - } - - /** - * Returns the decoration style of the JRootPane. - * - * @return the window decoration style - */ - private int getWindowDecorationStyle() { - return getRootPane().getWindowDecorationStyle(); - } - - @Override - public void addNotify() { - try { - super.addNotify(); - } catch (Exception e) { - } - uninstallListeners(); - - window = SwingUtilities.getWindowAncestor(this); - if (window != null) { - if (window instanceof Frame) { - setState(((Frame) window).getExtendedState()); - - //* 说明请见:BeautyEyeLNFHelper.setMaximizedBoundForFrame - if (BeautyEyeLNFHelper.setMaximizedBoundForFrame) - //* 此处设置窗口的最大边界是为了解决窗口最大化时覆盖 - //* 操作系统的task bar 的问题,它是sun一直没有解决的问题 - //* ,目前没有其它好方法,只能如此解决了 - setFrameMaxBound((Frame) window); - } else - setState(0); - setActive(window.isActive()); - installListeners(); - } - } - - /** - * 设置窗口的最大边界. - *

    - * 本方法由Jack Jiang 于2012-09-20添加的。 - * - * @param f the new frame max bound - * @see - * org.jb2011.lnf.beautyeye.BeautyEyeLNFHelper#setMaximizedBoundForFrame - * @since 3.2 - */ - private void setFrameMaxBound(Frame f) { - GraphicsConfiguration gc = f.getGraphicsConfiguration(); - Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets(gc); - Rectangle screenBounds = gc.getBounds(); - int x = Math.max(0, screenInsets.left); - int y = Math.max(0, screenInsets.top); - int w = screenBounds.width - (screenInsets.left + screenInsets.right); - int h = screenBounds.height - (screenInsets.top + screenInsets.bottom); - // Keep taskbar visible - f.setMaximizedBounds(new Rectangle(x, y, w, h)); - } - - @Override - public void removeNotify() { - super.removeNotify(); - - uninstallListeners(); - window = null; - } - - /** - * Adds any sub-Components contained in the MetalTitlePane. - */ - private void installSubcomponents() { - int decorationStyle = getWindowDecorationStyle(); - - if (decorationStyle == JRootPane.FRAME || decorationStyle == JRootPane.PLAIN_DIALOG) { - createActions(); - menuBar = createMenuBar(); - add(menuBar); - createButtons(); - - add(closeButton); - - //~* RootPane.setupButtonVisible是jb2011自定义的属性哦,目的是控制这个当前用于演示的设置按钮的可见性 - Object isSetupButtonVisibleObj = UIManager.get("RootPane.setupButtonVisible"); - //如果开发者没有设置此属性则默认认为是true(即显示该按钮) - boolean isSetupButtonVisible = (isSetupButtonVisibleObj == null ? true : (Boolean) isSetupButtonVisibleObj); - if (isSetupButtonVisible) - //加入设置按钮 - add(setupButton); - - if (decorationStyle != JRootPane.PLAIN_DIALOG)//! - { - add(iconifyButton); - add(toggleButton); - menuBar.setEnabled(false); - } - } else if ( // decorationStyle == JRootPane.PLAIN_DIALOG - // || - decorationStyle == JRootPane.INFORMATION_DIALOG - || decorationStyle == JRootPane.ERROR_DIALOG - || decorationStyle == JRootPane.COLOR_CHOOSER_DIALOG - || decorationStyle == JRootPane.FILE_CHOOSER_DIALOG - || decorationStyle == JRootPane.QUESTION_DIALOG - || decorationStyle == JRootPane.WARNING_DIALOG) { - createActions(); - createButtons(); - add(closeButton); - } - } - - /** - * Determines the Colors to draw with. - */ - private void determineColors() { - switch (getWindowDecorationStyle()) { - case JRootPane.FRAME: - activeBackground = UIManager.getColor("activeCaption"); - activeForeground = UIManager.getColor("activeCaptionText"); - activeShadow = UIManager.getColor("activeCaptionBorder"); - break; - case JRootPane.ERROR_DIALOG: - activeBackground = UIManager - .getColor("OptionPane.errorDialog.titlePane.background"); - activeForeground = UIManager - .getColor("OptionPane.errorDialog.titlePane.foreground"); - activeShadow = UIManager - .getColor("OptionPane.errorDialog.titlePane.shadow"); - break; - case JRootPane.QUESTION_DIALOG: - case JRootPane.COLOR_CHOOSER_DIALOG: - case JRootPane.FILE_CHOOSER_DIALOG: - activeBackground = UIManager - .getColor("OptionPane.questionDialog.titlePane.background"); - activeForeground = UIManager - .getColor("OptionPane.questionDialog.titlePane.foreground"); - activeShadow = UIManager - .getColor("OptionPane.questionDialog.titlePane.shadow"); - break; - case JRootPane.WARNING_DIALOG: - activeBackground = UIManager - .getColor("OptionPane.warningDialog.titlePane.background"); - activeForeground = UIManager - .getColor("OptionPane.warningDialog.titlePane.foreground"); - activeShadow = UIManager - .getColor("OptionPane.warningDialog.titlePane.shadow"); - break; - case JRootPane.PLAIN_DIALOG: - case JRootPane.INFORMATION_DIALOG: - default: - activeBackground = UIManager.getColor("activeCaption"); - activeForeground = UIManager.getColor("activeCaptionText"); - activeShadow = UIManager.getColor("activeCaptionBorder"); - break; - } - } - - /** - * Installs the fonts and necessary properties on the MetalTitlePane. - */ - private void installDefaults() { - setFont(UIManager.getFont("InternalFrame.titleFont", getLocale())); - } - - /** - * Uninstalls any previously installed UI values. - */ - private void uninstallDefaults() { - } - - /** - * Returns the JMenuBar displaying the appropriate system menu - * items. - * - * @return the j menu bar - */ - protected JMenuBar createMenuBar() { - menuBar = new SystemMenuBar(); - menuBar.setOpaque(false); - menuBar.setFocusable(false); - menuBar.setBorderPainted(true); - menuBar.add(createMenu()); - return menuBar; - } - - /** - * Closes the Window. - */ - private void close() { - Window w = getWindow(); - - if (w != null) - w.dispatchEvent(new WindowEvent(w, - WindowEvent.WINDOW_CLOSING)); - } - - /** - * Iconifies the Frame. - */ - private void iconify() { - Frame frame = getFrame(); - if (frame != null) - frame.setExtendedState(state | Frame.ICONIFIED); - } - - /** - * Maximizes the Frame. - */ - private void maximize() { - Frame frame = getFrame(); - if (frame != null) - frame.setExtendedState(state | Frame.MAXIMIZED_BOTH); - } - - /** - * Restores the Frame size. - */ - private void restore() { - Frame frame = getFrame(); - - if (frame == null) - return; - - if ((state & Frame.ICONIFIED) != 0) - frame.setExtendedState(state & ~Frame.ICONIFIED); - else - frame.setExtendedState(state & ~Frame.MAXIMIZED_BOTH); - } - - /** - * Create the Actions that get associated with the buttons and - * menu items. - */ - private void createActions() { - closeAction = new CloseAction(); - if (getWindowDecorationStyle() == JRootPane.FRAME) { - iconifyAction = new IconifyAction(); - restoreAction = new RestoreAction(); - maximizeAction = new MaximizeAction(); - - setupAction = new AbstractAction(UIManager.getString("BETitlePane.setupButtonText", getLocale())) { - @Override - public void actionPerformed(ActionEvent e) { - JOptionPane.showMessageDialog(rootPane, "This button just used for demo." - + "In the future,you can customize it.\n" - + "Now, you can set UIManager.put(\"RootPane.setupButtonVisible\", false) to hide it(detault is true).\n" - + "BeautyEye L&F developed by Jack Jiang, you can mail with jb2011@163.com."); - } - }; - } - } - - /** - * Returns the JMenu displaying the appropriate menu items for - * manipulating the Frame. - * - * @return the j menu - */ - private JMenu createMenu() { - JMenu menu = new JMenu(""); - menu.setOpaque(false);//本行一定要,否则将导致窗口图标区会绘制Menu的背景!这是Java Metal主题的Bug! -- jack,2009-09-11 - if (getWindowDecorationStyle() == JRootPane.FRAME - || getWindowDecorationStyle() == JRootPane.PLAIN_DIALOG//现在也给dialog加上菜单项(但只有关闭项) - ) - addMenuItems(menu); - return menu; - } - - /** - * Adds the necessary JMenuItems to the passed in menu. - * - * @param menu the menu - */ - private void addMenuItems(JMenu menu) { - Locale locale = getRootPane().getLocale(); - menu.setToolTipText(//"窗口相关操作."); - UIManager.getString("BETitlePane.titleMenuToolTipText", getLocale())); - - JMenuItem mi; - int mnemonic; - if (getWindowDecorationStyle() == JRootPane.FRAME)//! 只有frame才有这些菜单项 - { - mi = menu.add(restoreAction); - mnemonic = BEUtils.getInt("MetalTitlePane.restoreMnemonic", -1); - if (mnemonic != -1) - mi.setMnemonic(mnemonic); - - mi = menu.add(iconifyAction); - mnemonic = BEUtils.getInt("MetalTitlePane.iconifyMnemonic", -1); - if (mnemonic != -1) - mi.setMnemonic(mnemonic); - - if (Toolkit.getDefaultToolkit().isFrameStateSupported( - Frame.MAXIMIZED_BOTH)) { - mi = menu.add(maximizeAction); - mnemonic = BEUtils.getInt("MetalTitlePane.maximizeMnemonic", - -1); - if (mnemonic != -1) - mi.setMnemonic(mnemonic); - } - - menu.add(new JSeparator()); - } - - mi = menu.add(closeAction); - mnemonic = BEUtils.getInt("MetalTitlePane.closeMnemonic", -1); - if (mnemonic != -1) - mi.setMnemonic(mnemonic); - } - - /** - * Returns a JButton appropriate for placement on the - * TitlePane. - * - * @return the j button - */ - private JButton createTitleButton() { - JButton button = new JButton(); - - button.setFocusPainted(false); - button.setFocusable(false); - button.setOpaque(true); - return button; - } - - /** - * Creates the Buttons that will be placed on the TitlePane. - */ - private void createButtons() { - - setupButton = createTitleButton(); - setupButton.setAction(setupAction); -// setupButton.setText("设置 "); -// setupButton.putClientProperty("paintActive", Boolean.TRUE); - setupButton.setBorder(handyEmptyBorder); -// setupButton.getAccessibleContext().setAccessibleName("Close"); - setupButton.setIcon(UIManager.getIcon("Frame.setupIcon")); - setButtonIcon(setupButton, setupButton.getIcon());// @since 3.5:同时设置rover和pressed时的icon效果 - setupButton.setContentAreaFilled(false); -// setupButton.setToolTipText("设置"); - - closeButton = createTitleButton(); - closeButton.setAction(closeAction); - closeButton.setText(null); - closeButton.putClientProperty("paintActive", Boolean.TRUE); - closeButton.setBorder(handyEmptyBorder); - closeButton.getAccessibleContext().setAccessibleName("Close"); - closeButton.setIcon(UIManager.getIcon("Frame.closeIcon")); -// setButtonIcon(closeButton, closeButton.getIcon());// @since 3.5:同时设置rover和pressed时的icon效果 - closeButton.setRolloverIcon(UIManager.getIcon("Frame.closeIcon_rover")); - closeButton.setPressedIcon(UIManager.getIcon("Frame.closeIcon_pressed")); - closeButton.setContentAreaFilled(false); - closeButton.setToolTipText(//"关闭"); - UIManager.getString("BETitlePane.closeButtonToolTipext", getLocale())); - - if (getWindowDecorationStyle() == JRootPane.FRAME) { - maximizeIcon = UIManager.getIcon("Frame.maximizeIcon"); - maximizeIcon_rover = UIManager.getIcon("Frame.maximizeIcon_rover"); - maximizeIcon_pressed = UIManager.getIcon("Frame.maximizeIcon_pressed"); - - minimizeIcon = UIManager.getIcon("Frame.minimizeIcon"); - minimizeIcon_rover = UIManager.getIcon("Frame.minimizeIcon_rover"); - minimizeIcon_pressed = UIManager.getIcon("Frame.minimizeIcon_pressed"); - - iconifyButton = createTitleButton(); - iconifyButton.setAction(iconifyAction); - iconifyButton.setText(null); - iconifyButton.putClientProperty("paintActive", Boolean.TRUE); - iconifyButton.setBorder(handyEmptyBorder); - iconifyButton.getAccessibleContext().setAccessibleName("Iconify"); - iconifyButton.setIcon(UIManager.getIcon("Frame.iconifyIcon")); -// setButtonIcon(iconifyButton, iconifyButton.getIcon());// @since 3.5:同时设置rover和pressed时的icon效果 - iconifyButton.setRolloverIcon(UIManager.getIcon("Frame.iconifyIcon_rover")); - iconifyButton.setPressedIcon(UIManager.getIcon("Frame.iconifyIcon_pressed")); - iconifyButton.setContentAreaFilled(false); - iconifyButton.setToolTipText(//"最小化"); - UIManager.getString("BETitlePane.iconifyButtonToolTipText", getLocale())); - - toggleButton = createTitleButton(); - toggleButton.setAction(restoreAction); - toggleButton.putClientProperty("paintActive", Boolean.TRUE); - toggleButton.setBorder(handyEmptyBorder); - toggleButton.getAccessibleContext().setAccessibleName("Maximize"); - toggleButton.setIcon(maximizeIcon); -// setButtonIcon(toggleButton, toggleButton.getIcon());// @since 3.5:同时设置rover和pressed时的icon效果 - toggleButton.setRolloverIcon(maximizeIcon_rover); - toggleButton.setPressedIcon(maximizeIcon_pressed); - toggleButton.setContentAreaFilled(false); - toggleButton.setToolTipText(//"最大化"); - UIManager.getString("BETitlePane.toggleButtonToolTipText", getLocale())); - } - } - - /** - * 为按钮设置图标,并据原图icon自动调用方法 - * {@link #filterWithRescaleOp(ImageIcon, float, float, float, float)} - * 使用滤镜分别生成RolloverIcon、PressedIcon并设置之. - * - * @param btn - * @param ico - * @since 3.5 - * @deprecated since 3.6 - */ - public static void setButtonIcon(AbstractButton btn, Icon ico) { - //* 图片设定 - btn.setIcon(ico); - if (ico != null && ico instanceof ImageIcon) { - //rover时图片颜色变成红色 - btn.setRolloverIcon(BEUtils.filterWithRescaleOp((ImageIcon) ico, 2f, 1f, 1f, 1f)); - //press时图片颜色变成淡红色 - btn.setPressedIcon(BEUtils.filterWithRescaleOp((ImageIcon) ico, 2f, 1f, 1f, 0.5f)); - } - } - - /** - * Returns the LayoutManager that should be installed on the - * MetalTitlePane. - * - * @return the layout manager - */ - private LayoutManager createLayout() { - return new TitlePaneLayout(); - } - - /** - * Updates state dependant upon the Window's active state. - * - * @param isActive the new active - */ - private void setActive(boolean isActive) { - Boolean activeB = isActive ? Boolean.TRUE : Boolean.FALSE; - closeButton.putClientProperty("paintActive", activeB); - if (getWindowDecorationStyle() == JRootPane.FRAME) { - iconifyButton.putClientProperty("paintActive", activeB); - toggleButton.putClientProperty("paintActive", activeB); - } - // Repaint the whole thing as the Borders that are used have - // different colors for active vs inactive - getRootPane().repaint(); - } - - /** - * Sets the state of the Window. - * - * @param state the new state - */ - private void setState(int state) { - setState(state, false); - } - - /** - * Sets the state of the window. If updateRegardless is true - * and the state has not changed, this will update anyway. - * - * @param state the state - * @param updateRegardless the update regardless - */ - private void setState(int state, boolean updateRegardless) { - Window w = getWindow(); - - if (w != null && getWindowDecorationStyle() == JRootPane.FRAME) { - if (this.state == state && !updateRegardless) - return; - Frame frame = getFrame(); - - if (frame != null) { - JRootPane p = getRootPane(); - - if (((state & Frame.MAXIMIZED_BOTH) != 0) - && (p.getBorder() == null || (p - .getBorder() instanceof UIResource)) - && frame.isShowing()) - p.setBorder(null); - else if ((state & Frame.MAXIMIZED_BOTH) == 0) - // This is a croak, if state becomes bound, this can - // be nuked. - rootPaneUI.installBorder(p); - if (frame.isResizable()) { - if ((state & Frame.MAXIMIZED_BOTH) != 0) { - updateToggleButton(restoreAction, minimizeIcon, minimizeIcon_rover, minimizeIcon_pressed); - maximizeAction.setEnabled(false); - restoreAction.setEnabled(true); - } else { - updateToggleButton(maximizeAction, maximizeIcon, maximizeIcon_rover, maximizeIcon_pressed); - maximizeAction.setEnabled(true); - restoreAction.setEnabled(false); - } - if (toggleButton.getParent() == null - || iconifyButton.getParent() == null) { - add(toggleButton); - add(iconifyButton); - revalidate(); - repaint(); - } - toggleButton.setText(null); - } else { - maximizeAction.setEnabled(false); - restoreAction.setEnabled(false); - if (toggleButton.getParent() != null) { - remove(toggleButton); - revalidate(); - repaint(); - } - } - } else { - // Not contained in a Frame - maximizeAction.setEnabled(false); - restoreAction.setEnabled(false); - iconifyAction.setEnabled(false); - remove(toggleButton); - remove(iconifyButton); - revalidate(); - repaint(); - } - closeAction.setEnabled(true); - this.state = state; - } - } - - /** - * Updates the toggle button to contain the Icon icon, and - * Action action. - * - * @param action the action - * @param icon the icon - */ - private void updateToggleButton(Action action, Icon icon, - Icon iconRover, Icon iconPressed) { - toggleButton.setAction(action); - toggleButton.setIcon(icon); -// setButtonIcon(toggleButton, toggleButton.getIcon());// @since 3.5:同时设置rover和pressed时的icon效果:同时设置rover和pressed时的icon效果 - toggleButton.setRolloverIcon(iconRover); - toggleButton.setPressedIcon(iconPressed); - toggleButton.setText(null); - } - - /** - * Returns the Frame rendering in. This will return null if the - * JRootPane is not contained in a Frame. - * - * @return the frame - */ - private Frame getFrame() { - Window w = getWindow(); - - if (w instanceof Frame) - return (Frame) w; - return null; - } - - /** - * Returns the Window the JRootPane is contained - * in. This will return null if there is no parent ancestor of the - * JRootPane. - * - * @return the window - */ - private Window getWindow() { - return window; - } - - /** - * Returns the String to display as the title. - * - * @return the title - */ - private String getTitle() { - Window w = getWindow(); - - if (w instanceof Frame) - return ((Frame) w).getTitle(); - else if (w instanceof Dialog) - return ((Dialog) w).getTitle(); - return null; - } - - /** - * Renders the TitlePane. - * - * @param g the g - */ - @Override - public void paintComponent(Graphics g) { - // As state isn't bound, we need a convenience place to check - // if it has changed. Changing the state typically changes the - if (getFrame() != null) - setState(getFrame().getExtendedState()); - JRootPane p = getRootPane(); - Window w = getWindow(); - boolean leftToRight = (w == null) ? p - .getComponentOrientation().isLeftToRight() : w - .getComponentOrientation().isLeftToRight(); - boolean isSelected = (w == null) ? true : w.isActive(); - int width = getWidth(); - int height = getHeight(); - - Color background; - Color foreground; - Color darkShadow; - - if (isSelected) { - background = activeBackground; - foreground = activeForeground; - darkShadow = activeShadow; - } else { - background = inactiveBackground; - foreground = inactiveForeground; - darkShadow = inactiveShadow; -// bumps = inactiveBumps; - } - //----------------------------------------------- 标题背景 - paintTitlePane(g, 0, 0, width, height, isSelected); - - //----------------------------------------------- 标题文字和图片 - int xOffset = leftToRight ? 5 : width - 5; - - if (getWindowDecorationStyle() == JRootPane.FRAME || getWindowDecorationStyle() == JRootPane.PLAIN_DIALOG) - xOffset += leftToRight ? IMAGE_WIDTH + 5 : -IMAGE_WIDTH - 5; - - String theTitle = getTitle(); - if (theTitle != null) { - FontMetrics fm = MySwingUtilities2.getFontMetrics(p, g); - int yOffset = ((height - fm.getHeight()) / 2) + fm.getAscent(); - - Rectangle rect = new Rectangle(0, 0, 0, 0); - if (iconifyButton != null && iconifyButton.getParent() != null) - rect = iconifyButton.getBounds(); - int titleW; - - if (leftToRight) { - if (rect.x == 0) - rect.x = w.getWidth() - w.getInsets().right - 2; - titleW = rect.x - xOffset - 4; - theTitle = MySwingUtilities2.clipStringIfNecessary(p, fm, - theTitle, titleW); - } else { - titleW = xOffset - rect.x - rect.width - 4; - theTitle = MySwingUtilities2.clipStringIfNecessary(p, fm, - theTitle, titleW); - xOffset -= MySwingUtilities2.stringWidth(p, fm, theTitle); - } - - int titleLength = MySwingUtilities2.stringWidth(p, fm, theTitle); - g.setColor(foreground); - MySwingUtilities2.drawString(p, g, theTitle, xOffset, yOffset); - xOffset += leftToRight ? titleLength + 5 : -5; - } - } - - /** - * Paint title pane. - * - * @param g the g - * @param x the x - * @param y the y - * @param width the width - * @param height the height - * @param actived the actived - */ - public static void paintTitlePane(Graphics g, int x, int y, int width, - int height, boolean actived) { - Graphics2D g2 = (Graphics2D) g; - - //是用图形进行填充的 - Paint oldpaint = g2.getPaint(); - g2.setPaint(BEUtils.createTexturePaint( - __UI__.ICON.get("title", actived ? "active" : "inactive").getImage())); - g2.fillRect(x, y, width, height); - g2.setPaint(oldpaint); - } - - /** - * Actions used to close the Window. - */ - private class CloseAction extends AbstractAction { - - /** - * Instantiates a new close action. - */ - public CloseAction() { - super(UIManager.getString("BETitlePane.closeButtonToolTipext", getLocale())); - } - - @Override - public void actionPerformed(ActionEvent e) { - close(); - } - } - - /** - * Actions used to iconfiy the Frame. - */ - private class IconifyAction extends AbstractAction { - - /** - * Instantiates a new iconify action. - */ - public IconifyAction() { - super(UIManager.getString("BETitlePane.iconifyButtonText", getLocale())); - } - - @Override - public void actionPerformed(ActionEvent e) { - iconify(); - } - } - - /** - * Actions used to restore the Frame. - */ - private class RestoreAction extends AbstractAction { - - /** - * Instantiates a new restore action. - */ - public RestoreAction() { - super(UIManager.getString("BETitlePane.restoreButtonText", getLocale())); - } - - @Override - public void actionPerformed(ActionEvent e) { - restore(); - } - } - - /** - * Actions used to restore the Frame. - */ - private class MaximizeAction extends AbstractAction { - - public MaximizeAction() { - super(UIManager.getString("BETitlePane.maximizeButtonText", getLocale())); - } - - @Override - public void actionPerformed(ActionEvent e) { - maximize(); - } - } - - /** - * Class responsible for drawing the system menu. Looks up the image to draw - * from the Frame associated with the JRootPane. - */ - private class SystemMenuBar extends JMenuBar { - - @Override - public void paint(Graphics g) { - //## Bug FIX: Issue BELNF-10, 之前是用的MetalLNF中的代码( - //## 它设计为不显示Dialog及其子类的图标),此处就是要加上Dialog及其子类 - //## 窗口图标的处理 -// Frame frame = getFrame();// getFrame()方法意味只处理Frame及其子类图标(Dialog的就错误地跳过了) - Window frame = getWindow(); - - if (isOpaque()) { - g.setColor(getBackground()); - g.fillRect(0, 0, getWidth(), getHeight()); - } - - //## Bug FIX: Issue BELNF-10 -// Image image = (frame != null) ? frame.getIconImage() : null; - Image image = null; - if (frame != null) - // 如果是Frame及其子类则调用getIconImage取回最合适 - // 图标(跨平台时可能尺寸不一样,此方法返回最合适的) - if (frame instanceof Frame) - image = ((Frame) frame).getIconImage(); - // 其它情况那就Dialog及其子类了,因它们没有getIconImage方法, - // 那就只取frame.getIconImages()里的第1个图标吧(如蛤存在多个图标的话), - // 它样处理虽跨平台考虑不足但总比MetalTitlePane里不显示Dialog图标强 - else if (frame.getIconImages() != null && frame.getIconImages().size() > 0) - image = frame.getIconImages().get(0); - - if (image != null) - g.drawImage(image, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, null); - else { - Icon icon = UIManager.getIcon("Frame.icon");//"InternalFrame.icon"); - if (icon != null) - icon.paintIcon(this, g, 0, 0); - } - } - - @Override - public Dimension getMinimumSize() { - return getPreferredSize(); - } - - @Override - public Dimension getPreferredSize() { - Dimension size = super.getPreferredSize(); - - return new Dimension(Math.max(IMAGE_WIDTH, size.width), Math.max( - size.height, IMAGE_HEIGHT)); - } - } - - private class TitlePaneLayout implements LayoutManager { - - @Override - public void addLayoutComponent(String name, Component c) { - } - - @Override - public void removeLayoutComponent(Component c) { - } - - @Override - public Dimension preferredLayoutSize(Container c) { - int height = computeHeight(); - return new Dimension(height, height); - } - - @Override - public Dimension minimumLayoutSize(Container c) { - return preferredLayoutSize(c); - } - - /** - * Compute height. - * - * @return the int - */ - private int computeHeight() { - FontMetrics fm = rootPane.getFontMetrics(getFont()); - int fontHeight = fm.getHeight(); - fontHeight += 7; - int iconHeight = 0; - if (getWindowDecorationStyle() == JRootPane.FRAME) // ||getWindowDecorationStyle() == JRootPane.PLAIN_DIALOG)// - - iconHeight = IMAGE_HEIGHT; - - int finalHeight = Math.max(fontHeight, iconHeight); - return finalHeight + 2;//* 改变此处的返回结果将直接改变窗口标题的高度哦 - } - - @Override - public void layoutContainer(Container c) { - boolean leftToRight = (window == null) ? getRootPane() - .getComponentOrientation().isLeftToRight() : window - .getComponentOrientation().isLeftToRight(); - - int w = getWidth(); - int x; - int y = 3; - int spacing; - int buttonHeight; - int buttonWidth; - - if (closeButton != null && closeButton.getIcon() != null) { - buttonHeight = closeButton.getIcon().getIconHeight(); - buttonWidth = closeButton.getIcon().getIconWidth(); - } else { - buttonHeight = IMAGE_HEIGHT; - buttonWidth = IMAGE_WIDTH; - } - - // assumes all buttons have the same dimensions - // these dimensions include the borders - x = leftToRight ? w : 0; - - spacing = 5; - x = leftToRight ? spacing : w - buttonWidth - spacing; - if (menuBar != null) - //* js 2010-03-30 - //* 原MetalTitledPane的Bug:当存在关闭按钮时,窗口图标的大小是已关闭按钮的大小来决定的,这样不合理 - menuBar.setBounds(x, - y + 2//+2偏移量由Jack Jiang于2012-09-24日加上,目的是使得图标与文本保持在同一中心位置 - // TODO 目前BueautyEye和MetalLookAndFeel的标题图标位置算法都有优化的余地:y轴坐标自动按title高度居中会 - // 适用更多场景,现在的算法如果title高度变的很大,则这些位置都是固定。不过按MetalLNF的思路,这些高度 - // 是与整体美感一样,不应被随意改动的,也可以说不需要优化,目前就这么的吧,没有关系。 - , - IMAGE_HEIGHT, IMAGE_WIDTH);//buttonWidth, buttonHeight); - - x = leftToRight ? w : 0; - spacing = 4; - x += leftToRight ? -spacing - buttonWidth : spacing; - if (closeButton != null) - closeButton.setBounds(x, y, buttonWidth, buttonHeight); - - if (!leftToRight) - x += buttonWidth; - - if (getWindowDecorationStyle() == JRootPane.FRAME) { - if (Toolkit.getDefaultToolkit().isFrameStateSupported( - Frame.MAXIMIZED_BOTH)) - if (toggleButton.getParent() != null) { - spacing = 2;//10!!! - x += leftToRight ? -spacing - buttonWidth : spacing; - toggleButton.setBounds(x, y, buttonWidth, buttonHeight); - if (!leftToRight) - x += buttonWidth; - } - - if (iconifyButton != null && iconifyButton.getParent() != null) { - spacing = 2; - x += leftToRight ? -spacing - buttonWidth : spacing; - iconifyButton.setBounds(x, y, buttonWidth, buttonHeight); - if (!leftToRight) - x += buttonWidth; - } - - //“设置”按钮 - if (setupButton != null) { - spacing = 2; - int stringWidth = BEUtils.getStrPixWidth(setupButton.getFont(), setupButton.getText()); - x += leftToRight ? -spacing - buttonWidth - stringWidth : spacing; - setupButton.setBounds(x, y, buttonWidth + stringWidth, buttonHeight); - if (!leftToRight) - x += buttonWidth; - } - } - buttonsWidth = leftToRight ? w - x : x; - } - } - - /** - * PropertyChangeListener installed on the Window. Updates the necessary - * state as the state of the Window changes. - */ - private class PropertyChangeHandler implements PropertyChangeListener { - - @Override - public void propertyChange(PropertyChangeEvent pce) { - String name = pce.getPropertyName(); - - if (null != name) // Frame.state isn't currently bound. - switch (name) { - case "resizable": - case "state": - Frame frame = getFrame(); - if (frame != null) - setState(frame.getExtendedState(), true); - if ("resizable".equals(name)) - getRootPane().repaint(); - break; - case "title": - repaint(); - break; - case "componentOrientation": - case "iconImage": - revalidate(); - repaint(); - break; - default: - break; - } - } - } - - /** - * WindowListener installed on the Window, updates the state as necessary. - */ - private class WindowHandler extends WindowAdapter { - - @Override - public void windowActivated(WindowEvent ev) { - setActive(true); - } - - @Override - public void windowDeactivated(WindowEvent ev) { - setActive(false); - } - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/titlepane/__UI__.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/titlepane/__UI__.java deleted file mode 100644 index 3802c25b8..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/titlepane/__UI__.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * __UI__.java at 2015-2-1 20:25:39, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.titlepane; - -import javax.swing.UIManager; -import javax.swing.plaf.BorderUIResource; - -import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper; -import org.jackhuang.hmcl.laf.BEUtils; -import org.jackhuang.hmcl.laf.utils.IconFactory; -import org.jackhuang.hmcl.laf.utils.UI; - -public class __UI__ extends UI { - - protected static final IconFactory ICON = new IconFactory("frame"); - - public static void uiImpl() { - //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 窗体ui的各项属性设定 - //*~ 本属性是Jack Jiang自已设定的,Java的Metal主题默认对非Frame对象的窗口图标取的是InternalFrame.icon,这是不对的 - UIManager.put("Frame.icon", ICON.get("icon")); - - UIManager.put("Frame.iconifyIcon", ICON.get("iconify")); - UIManager.put("Frame.iconifyIcon_rover", ICON.get("iconify_over")); - UIManager.put("Frame.iconifyIcon_pressed", ICON.get("iconify_pressed")); - - UIManager.put("Frame.minimizeIcon", ICON.get("min")); - UIManager.put("Frame.minimizeIcon_rover", ICON.get("min_over")); - UIManager.put("Frame.minimizeIcon_pressed", ICON.get("min_pressed")); - - UIManager.put("Frame.maximizeIcon", ICON.get("max")); - UIManager.put("Frame.maximizeIcon_rover", ICON.get("max_over")); - UIManager.put("Frame.maximizeIcon_pressed", ICON.get("max_pressed")); - - UIManager.put("Frame.closeIcon", ICON.get("close")); - UIManager.put("Frame.closeIcon_rover", ICON.get("close_over")); - UIManager.put("Frame.closeIcon_pressed", ICON.get("close_pressed")); - - //设定用于演示之用的“设置”按钮图标 - UIManager.put("Frame.setupIcon", ICON.get("setup")); - -// put("activeCaption", Windows2LookAndFeel.activeCaption); - put("activeCaptionText", BeautyEyeLNFHelper.activeCaptionTextColor); -// put("activeCaptionBorder", Windows2LookAndFeel.activeCaptionBorder); -// put("inactiveCaption", GraphicHandler.getColor(activeCaption, 64, 42, 22)); - put("inactiveCaptionText", BEUtils.getColor(BeautyEyeLNFHelper.activeCaptionTextColor, -49, -27, -7)); -// put("inactiveCaptionBorder", GraphicHandler.getColor(activeCaptionBorder, 64, 42, 22)); - - //此属性即是BeautyEye LNF的窗口标题栏实现 - put("RootPaneUI", BERootPaneUI.class); - - // These bindings are only enabled when there is a default - // button set on the rootpane. - UIManager.put("RootPane.defaultButtonWindowKeyBindings", new Object[] { - "ENTER", "press", - "released ENTER", "release", - "ctrl ENTER", "press", - "ctrl released ENTER", "release" - }); - - //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> OptionPane的各项ui属性设定 - Object dialogBorder = new BorderUIResource(BeautyEyeLNFHelper.getFrameBorder());//BorderFactory.createLineBorder(new Color(181,181,181))); - UIManager.put("RootPane.frameBorder", dialogBorder); - UIManager.put("RootPane.plainDialogBorder", dialogBorder); - UIManager.put("RootPane.informationDialogBorder", dialogBorder); - UIManager.put("RootPane.errorDialogBorder", dialogBorder); - UIManager.put("RootPane.colorChooserDialogBorder", dialogBorder); - UIManager.put("RootPane.fileChooserDialogBorder", dialogBorder); - UIManager.put("RootPane.questionDialogBorder", dialogBorder); - UIManager.put("RootPane.warningDialogBorder", dialogBorder); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/toolbar/BEToolBarSeparatorUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/toolbar/BEToolBarSeparatorUI.java deleted file mode 100644 index f61e7216d..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/toolbar/BEToolBarSeparatorUI.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BEToolBarSeparatorUI.java at 2015-2-1 20:25:36, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.toolbar; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Stroke; - -import javax.swing.JComponent; -import javax.swing.JSeparator; -import javax.swing.JToolBar; -import javax.swing.SwingConstants; -import javax.swing.UIDefaults; -import javax.swing.UIManager; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicToolBarSeparatorUI; - -/** - * JToolBar的分隔条UI实现类. - * - * @author Jack Jiang(jb2011@163.com) - * @see com.sun.java.swing.plaf.windows.WindowsToolBarSeparatorUI - */ -public class BEToolBarSeparatorUI extends BasicToolBarSeparatorUI { - - public static ComponentUI createUI(JComponent c) { - return new BEToolBarSeparatorUI(); - } - - @Override - public Dimension getPreferredSize(JComponent c) { - Dimension size = ((JToolBar.Separator) c).getSeparatorSize(); - - if (size != null) - size = size.getSize(); - else { - size = new Dimension(6, 6); - - if (((JSeparator) c).getOrientation() == SwingConstants.VERTICAL) - size.height = 0; - else - size.width = 0; - } - return size; - } - - @Override - public Dimension getMaximumSize(JComponent c) { - Dimension pref = getPreferredSize(c); - if (((JSeparator) c).getOrientation() == SwingConstants.VERTICAL) - return new Dimension(pref.width, Short.MAX_VALUE); - else - return new Dimension(Short.MAX_VALUE, pref.height); - } - - @Override - public void paint(Graphics g, JComponent c) { - boolean vertical = ((JSeparator) c).getOrientation() == SwingConstants.VERTICAL; - Dimension size = c.getSize(); - - //虚线样式 - Stroke oldStroke = ((Graphics2D) g).getStroke(); - Stroke sroke = new BasicStroke(1, BasicStroke.CAP_BUTT, - BasicStroke.JOIN_BEVEL, 0, new float[] { 2, 2 }, 0);//实线,空白 - ((Graphics2D) g).setStroke(sroke);// - - Color temp = g.getColor(); - UIDefaults table = UIManager.getLookAndFeelDefaults(); - Color shadow = table.getColor("ToolBar.shadow"); - Color highlight = table.getColor("ToolBar.highlight"); - - // TODO BUG_001:不知何故,垂直分隔条并不能像水平分隔条一样,拥有默认设置的new Dimension(6, 6) - // 而只有new Dimension(1, ...),而当它floating时却能正常表现(只能绘出hilight而不能绘出shadow) - //,有待深入研究,垂直的分隔条则不会有此种情况 - if (vertical) { - int x = (size.width / 2) - 1; - - //* 当BUG_001存在时,暂时使用以下代码解决:把本该显示hilight的 - //* 线条用shadow颜色绘制,最大可能保证ui的正常展现 -// g.setColor(shadow); -// g.drawLine(x, 2, x, size.height - 2); - g.setColor(shadow);//highlight); - g.drawLine(x + 1, 2, x + 1, size.height - 2); - - //* 当BUG_001不存在时,应该使用以下代码 -// g.setColor(shadow); -// g.drawLine(x, 2, x, size.height - 2); -// g.setColor(highlight); -// g.drawLine(x + 1, 2, x + 1, size.height - 2); - } else { - int y = (size.height / 2) - 1; - g.setColor(shadow); - g.drawLine(2, y, size.width - 2, y); - - g.setColor(highlight); - g.drawLine(2, y + 1, size.width - 2, y + 1); - } - g.setColor(temp); - - ((Graphics2D) g).setStroke(oldStroke); - } - -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/toolbar/BEToolBarUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/toolbar/BEToolBarUI.java deleted file mode 100644 index 6b806bf25..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/toolbar/BEToolBarUI.java +++ /dev/null @@ -1,362 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BEToolBarUI.java at 2015-2-1 20:25:41, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.toolbar; - -import java.awt.BasicStroke; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.Container; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Insets; -import java.awt.LayoutManager; -import java.awt.Stroke; -import java.awt.event.ContainerEvent; -import java.awt.event.ContainerListener; - -import javax.swing.AbstractButton; -import javax.swing.JComponent; -import javax.swing.JToolBar; -import javax.swing.SwingConstants; -import javax.swing.UIManager; -import javax.swing.border.AbstractBorder; -import javax.swing.border.Border; -import javax.swing.border.EmptyBorder; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.UIResource; -import javax.swing.plaf.basic.BasicToolBarUI; - -import org.jackhuang.hmcl.laf.button.BEButtonUI; -import org.jackhuang.hmcl.laf.utils.Icon9Factory; -import org.jb2011.ninepatch4j.NinePatch; - -/** - * JToolBar的UI实现类。 - * - *

    - * Since v3.4:
    - * 可以使用"ToolBar.isPaintPlainBackground"来控制BEToolBarUI还是 - * 默认的渐变NinePatch图实现背景的填充(效果好,但是背景比较强烈,不适于组件密集的场景). - * 全局控制可以通过UIManager.put("ToolBar.isPaintPlainBackground", - * Boolean.FALSE)(UIManager中默认是false) - * 或者通过JToolBar.putClientProperty("ToolBar.isPaintPlainBackground", - * Boolean.FALSE) 独立控制,ClientProperty中的设置拥有最高优先级。 - * - * 特别说明:JToolBar比较特殊,加入到JToolBar中的组件,其UI(主要是Border)将由ToolBarUI额 - * 外控制而不受自身UI控制,比如放入到JToolBar中的JToggleButton,它的border就是受ToolBarUI - * 控制,这些JToggleButton将无论如何修改ToolgleButtonUI.border也不会起效。 - * - * @author Jack Jiang(jb2011@163.com) - * @see com.sun.java.swing.plaf.windows.WindowsToolBarUI - */ -public class BEToolBarUI extends BasicToolBarUI - implements org.jackhuang.hmcl.laf.BeautyEyeLNFHelper.__UseParentPaintSurported { - - private static final Icon9Factory ICON_9 = new Icon9Factory("toolbar"); - - public static ComponentUI createUI(JComponent c) { - return new BEToolBarUI(); - } - - @Override - protected void installDefaults() { - setRolloverBorders(true); - super.installDefaults(); - } - - //* 本方法由Jack Jiang于2012-09-07日加入 - /** - * 是否使用父类的绘制实现方法,true表示是. - *

    - * 因为在BE LNF中,工具条背景是使用N9图,没法通过设置背景色和前景 - * 色来控制工具条的颜色,本方法的目的就是当用户设置了工具条的Background 时告之本实现类不使用BE - * LNF中默认的N9图填充绘制而改用父类中的方法(父类中的方法 就可以支持颜色的设置罗,只是丑点,但总归是能适应用户的需求场景要求,其实用户完全可以 - * 通过JToolBar.setUI(new MetalToolBar())等方式来自定义UI哦). - * - * @return true, if is use parent paint - */ - @Override - public boolean isUseParentPaint() { - return toolBar != null - && (!(toolBar.getBackground() instanceof UIResource)); - } - - @Override - protected Border createRolloverBorder() { - return new EmptyBorder(3, 3, 3, 3); - } - - @Override - protected Border createNonRolloverBorder() { - return new EmptyBorder(3, 3, 3, 3); - } - - @Override - public void paint(Graphics g, JComponent c) { - //~* @since 3.4, add by Jack Jiang 2012-11-05 - //~* 【BeautyEye外观的特有定制属性】:true表示BEToolBarUI里,将使用其它典型外观 - //~* 一样的默认纯色填充背景(颜色由ToolBar.background属性指定), 否则将使用BeautyEye - //~* 默认的渐变NinePatch图实现背景的填充。另外,还可以使用 - //~* JToolBar.putClientProperty("ToolBar.isPaintPlainBackground", Boolean.TRUE);来进行 - //~* 独立控制背景的填充方法,ClientProperty相比UIManager中的本方法拥有最高优先级 - boolean isPaintPlainBackground = false; - String isPaintPlainBackgroundKey = "ToolBar.isPaintPlainBackground";//~* 【BeautyEye外观的特有定制属性】@since 3.4 - //首先看看有没有独立在ClientProperty中设置"ToolBar.isPaintPlainBackground"属性(ClientProperty中设置拥有最高优先级) - Object isPaintPlainBackgroundObj = c.getClientProperty(isPaintPlainBackgroundKey); - //如果ClientProperty中没有设置,则尝试取UIManager中的该属性默认值 - if (isPaintPlainBackgroundObj == null) - isPaintPlainBackgroundObj = UIManager.getBoolean(isPaintPlainBackgroundKey); - if (isPaintPlainBackgroundObj != null) - isPaintPlainBackground = (Boolean) isPaintPlainBackgroundObj; - - //* 如果用户作了自定义颜色设置则使用父类方法来实现绘制,否则BE LNF中没法支持这些设置哦 - if (isPaintPlainBackground || isUseParentPaint()) - super.paint(g, c); - else { - //* 根据工具条所放在父类的位置不同来决定它的背景该使用哪个图片(图片的差别在于方向不同,主要是边缘阴影的方向) - NinePatch np = ICON_9.get("north"); - //int orientation = toolBar.getOrientation(); - Container parent = toolBar.getParent(); - if (parent != null) { - LayoutManager lm = parent.getLayout(); - if (lm instanceof BorderLayout) { - Object cons = ((BorderLayout) lm).getConstraints(toolBar); - if (cons != null) - if (cons.equals(BorderLayout.NORTH)) - np = ICON_9.get("north"); - else if (cons.equals(BorderLayout.SOUTH)) - np = ICON_9.get("south"); - else if (cons.equals(BorderLayout.WEST)) - np = ICON_9.get("west"); - else if (cons.equals(BorderLayout.EAST)) - np = ICON_9.get("east"); - } - } - np.draw((Graphics2D) g, 0, 0, c.getWidth(), c.getHeight()); - } - } - - /** - * Gets the rollover border. - * - * @param b the b - * @return the rollover border {@inheritDoc} - */ - @Override - protected Border getRolloverBorder(AbstractButton b) { - return new BEButtonUI.BEEmptyBorder(new Insets(3, 3, 3, 3)); - } - - //* 由jb2011修改,只加了一行代码哦 - /** - * 重写父类方法实现自已的容器监听器. 自定义的目的就是为了把加入到其中的组件设置为透明,因为BE LNF的工具栏是有背景,否则 - * 因有子组件的背景存在而使得整体很难看. - * - * @return the container listener - */ - @Override - protected ContainerListener createToolBarContListener() { - return new ToolBarContListenerJb2011(); - } - //* 由jb2011修改自父类的Handler里的ContainerListener监听代码 - - /** - * The Class ToolBarContListenerJb2011. - */ - protected class ToolBarContListenerJb2011 implements ContainerListener { - // - // ContainerListener - // - - @Override - public void componentAdded(ContainerEvent evt) { - Component c = evt.getChild(); - - if (toolBarFocusListener != null) - c.addFocusListener(toolBarFocusListener); - - if (isRolloverBorders()) - setBorderToRollover(c); - else - setBorderToNonRollover(c); - - //## Bug FIX:Issue 51(https://code.google.com/p/beautyeye/issues/detail?id=51) - //* 由Jack Jiang201210-12日注释掉:它样做将导致各种放入的组 - //* 件(如文本框)等都将透明,从而不绘制该 组件的背景,那就错误了哦 - //* 其实以下代码原本是为了解决放入到JToggleButton的白色背景问题,现在它 - //* 已经在BEToolgleButtonUI里解决了,此处就不需要了,也不应该要! -// //* 只有它一行是由jb2011加的 -// if(c instanceof JComponent) -// ((JComponent)c).setOpaque(false); - } - - @Override - public void componentRemoved(ContainerEvent evt) { - Component c = evt.getChild(); - - if (toolBarFocusListener != null) - c.removeFocusListener(toolBarFocusListener); - - // Revert the button border - setBorderToNormal(c); - } - } - - //* 本类由Jack Jiang实现,参考了com.sun.java.swing.plaf.windows.WindowsBorders.getToolBarBorder - /** - * 工具条边框,左边(或右、或上方)有拖动触点的绘制,方便 告之用户它是可以拖动的 A border for the ToolBar. If the - * ToolBar is floatable then the handle grip is drawn - *

    - * @since 1.4 - */ - public static class ToolBarBorder extends AbstractBorder implements UIResource, SwingConstants { - - /** - * The shadow. - */ - protected Color shadow; - /** - * The highlight. - */ - protected Color highlight; - protected Insets insets; - - /** - * Instantiates a new tool bar border. - * - * @param shadow the shadow - * @param highlight the highlight - */ - public ToolBarBorder(Color shadow, Color highlight, Insets insets) { - this.highlight = highlight; - this.shadow = shadow; - this.insets = insets; - } - - @Override - public void paintBorder(Component c, Graphics g, int x, int y, - int width, int height) { - g.translate(x, y); - - //需要绘制拖动触点 - if (((JToolBar) c).isFloatable()) { - boolean vertical = ((JToolBar) c).getOrientation() == VERTICAL; - - //虚线样式 - Stroke oldStroke = ((Graphics2D) g).getStroke(); - Stroke sroke = new BasicStroke(1, BasicStroke.CAP_BUTT, - BasicStroke.JOIN_BEVEL, 0, new float[] { 1, 1 }, 0);//实线,空白 - ((Graphics2D) g).setStroke(sroke); -// int gap_top = 5,gap_bottom = 4; //!!10,-1 - if (!vertical) { - int gap_top = 8, gap_bottom = 8; - if (c.getComponentOrientation().isLeftToRight()) { - int drawX = 3; - drawTouchH(g, drawX, gap_top - 1, drawX, height - gap_bottom - 1); - } else { - int drawX = 3 - 1; - drawTouchH(g, width - drawX, gap_top - 1, width - drawX, height - gap_bottom - 1); - } - } else // Vertical - { - int gap_left = 8, gap_right = 8; - int drawY = 3; - drawTouchV(g, gap_left - 1, drawY, width - gap_right - 1, drawY); - } - - ((Graphics2D) g).setStroke(oldStroke); - } - - g.translate(-x, -y); - } - - //水平工具条的触点绘制方法 - private void drawTouchH(Graphics g, int x1, int y1, int x2, int y2) { - //第1条竖虚线(深色) - g.setColor(shadow); - g.drawLine(x1, y1, x1, y2 - 1); - //第2条竖虚线(与第1条形成立体效果的浅色,Y坐标相对第1条下偏一个像素) - g.setColor(highlight); - g.drawLine(x1 + 1, y1 + 1, x1 + 1, y2); - - //第3条竖虚线 - g.setColor(shadow); - g.drawLine(x1 + 2, y1, x1 + 2, y2 - 1); - //第4条竖虚线(与第3条形成立体效果的浅色,Y坐标相对第3条下偏一个像素) - g.setColor(highlight); - g.drawLine(x1 + 3, y1 + 1, x1 + 3, y2); - } - //垂直工具条的触点绘制方法 - - private void drawTouchV(Graphics g, int x1, int y1, int x2, int y2) { - //第1条横虚线(深色) - g.setColor(shadow); - g.drawLine(x1, y1, x2 - 1, y2); - //第2条横虚线(与第1条形成立体效果的浅色,X坐标相对第1条右偏一个像素) - g.setColor(highlight); - g.drawLine(x1 + 1, y1 + 1, x2, y2 + 1); - - //第3条横虚线 - g.setColor(shadow); - g.drawLine(x1, y1 + 2, x2 - 1, y2 + 2); - //第4条横虚线(与第3条形成立体效果的浅色,X坐标相对第3条右偏一个像素) - g.setColor(highlight); - g.drawLine(x1 + 1, y1 + 3, x2, y2 + 3); - } - - @Override - public Insets getBorderInsets(Component c) { - //** 根据toolbar所放面板的方位不同而设置不一样的border(参照的目标是水平toolbar时的insets)! - //tollbar上下设置的空白多一点看起来大气一些(它也将决定toolbar的整体高度和宽度哦) - final Insets DEFAILT_IS = insets;//8,0,9,0);//6, 0, 11, 0); - Insets is = DEFAILT_IS; - if (c instanceof JToolBar) { - Container parent = c.getParent(); - if (parent != null) { - LayoutManager lm = parent.getLayout(); - if (lm instanceof BorderLayout) { - Object cons = ((BorderLayout) lm).getConstraints((JToolBar) c); - if (cons != null) - if (cons.equals(BorderLayout.NORTH)) - is = DEFAILT_IS; - else if (cons.equals(BorderLayout.SOUTH)) - is = new Insets(DEFAILT_IS.bottom, 0, DEFAILT_IS.top, 0); - else if (cons.equals(BorderLayout.WEST)) - is = new Insets(0, DEFAILT_IS.top, 0, DEFAILT_IS.bottom); - else if (cons.equals(BorderLayout.EAST)) - is = new Insets(0, DEFAILT_IS.bottom, 0, DEFAILT_IS.top); - } - } - } - - return getBorderInsets(c, is);//5, 0, 10, 0));//默认是 1,1,1,1 - } - - @Override - public Insets getBorderInsets(Component c, Insets insets) { -// insets.top = insets.left = insets.bottom = insets.right = 1; - if (((JToolBar) c).isFloatable()) { -// int gripInset = (XPStyle.getXP() != null) ? 12 : 9;//原windows外观中默认的 - int gripInset = 9; - if (((JToolBar) c).getOrientation() == HORIZONTAL) - if (c.getComponentOrientation().isLeftToRight()) - insets.left = gripInset; - else - insets.right = gripInset; - else - insets.top = gripInset; - } - return insets; - } - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/toolbar/__UI__.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/toolbar/__UI__.java deleted file mode 100644 index 8e0375cac..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/toolbar/__UI__.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * __UI__.java at 2015-2-1 20:25:39, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.toolbar; - -import java.awt.Color; -import java.awt.Insets; - -import javax.swing.UIManager; - -import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper; -import org.jackhuang.hmcl.laf.utils.UI; - -public class __UI__ extends UI { - - public static void uiImpl() { - //~* @since 3.4, add by Jack Jiang 2012-11-05 - //~* 【BeautyEye外观的特有定制属性】:true表示BEToolBarUI里,将使用其它典型外观 - //~* 一样的默认纯色填充背景(颜色由ToolBar.background属性指定), 否则将使用BeautyEye - //~* 默认的渐变NinePatch图实现背景的填充。另外,还可以使用 - //~* JToolBar.putClientProperty("ToolBar.isPaintPlainBackground", Boolean.TRUE);来进行 - //~* 独立控制背景的填充方法,ClientProperty相比UIManager中的本方法拥有最高优先级 - put("ToolBar.isPaintPlainBackground", false); - //此属性目前用于ToolBar.border中表示触点的颜色 - putColor("ToolBar.shadow", 180, 183, 187); - //此属性目前用于ToolBar.border中表示触点的立体阴影效果颜色 - put("ToolBar.highlight", Color.white); - put("ToolBar.dockingBackground", BeautyEyeLNFHelper.commonBackgroundColor); - put("ToolBar.floatingBackground", BeautyEyeLNFHelper.commonBackgroundColor); - put("ToolBar.background", BeautyEyeLNFHelper.commonBackgroundColor); - put("ToolBar.foreground", BeautyEyeLNFHelper.commonForegroundColor); - //工具栏的border实现 - UIManager.put("ToolBar.border", - new BEToolBarUI.ToolBarBorder(UIManager.getColor("ToolBar.shadow"), - UIManager.getColor("ToolBar.highlight"), new Insets(6, 0, 11, 0))); -// BorderFactory.createEmptyBorder(5, 0, 8, 0)));//5, 5, 8, 5))); - //分隔条ui实现 - put("ToolBarSeparatorUI", BEToolBarSeparatorUI.class); - put("ToolBarUI", BEToolBarUI.class); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/tree/BETreeUI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/tree/BETreeUI.java deleted file mode 100644 index e74bd7ee6..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/tree/BETreeUI.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BETreeUI.java at 2015-2-1 20:25:36, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.tree; - -import javax.swing.JComponent; -import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicTreeUI; -import javax.swing.tree.DefaultTreeCellRenderer; -import javax.swing.tree.TreeCellRenderer; - -/** - * JTree的UI实现类. - * - * 目前,本类中暂未对UI方面代码进行修改,对Tree的UI修改主要是基于UIManager对应Tree - * 属性的配置,目前已经足够达到预期效果,如有必要可开放本类中的代码进行深入修改。 - * - * @author Jack Jiang(jb2011@163.com) - * @version 1.0 - * @see com.sun.java.swing.plaf.windows.WindowsTreeUI - */ -public class BETreeUI extends BasicTreeUI { - - public static ComponentUI createUI(JComponent c) { - return new BETreeUI(); - } - -// //copy from BasicTreeUI and modified by jb2011 -// // This method is slow -- revisit when Java2D is ready. -// // assumes x1 <= x2 -// /** -// * 绘制水平层次虚线. -// * Jack Jiang重写此方法的目的是加调整虚线的步进值. -// */ -// protected void drawDashedHorizontalLine(Graphics g, int y, int x1, int x2) -// { -// // Drawing only even coordinates helps join line segments so they -// // appear as one line. This can be defeated by translating the -// // Graphics by an odd amount. -//// x1 += (x1 % 2); -// x1 += (x1 % 6); -// -//// for (int x = x1; x <= x2; x+=2) -//// { -//// g.drawLine(x, y, x, y); -//// } -// for (int x = x1; x <= x2; x+=6) -// { -// g.drawLine(x, y, x, y); -// } -// } -// -// //copy from BasicTreeUI and modified by jb2011 -// // This method is slow -- revisit when Java2D is ready. -// // assumes y1 <= y2 -// /** -// * 绘制垂直层次虚线. -// * Jack Jiang重写此方法的目的是加调整虚线的步进值. -// */ -// protected void drawDashedVerticalLine(Graphics g, int x, int y1, int y2) -// { -// // Drawing only even coordinates helps join line segments so they -// // appear as one line. This can be defeated by translating the -// // Graphics by an odd amount. -//// y1 += (y1 % 2); -// y1 += (y1 % 6); -// -//// for (int y = y1; y <= y2; y+=2) { -//// g.drawLine(x, y, x, y); -//// } -// for (int y = y1; y <= y2; y+=6) { -// g.drawLine(x, y, x, y); -// } -// } -// static protected final int HALF_SIZE = 4; -// static protected final int SIZE = 9; - /** - * Returns the default cell renderer that is used to do the stamping of each - * node. - * - * @return the tree cell renderer - * @see - * com.sun.java.swing.plaf.windows.WindowsTreeUI#createDefaultCellRenderer() - */ - @Override - protected TreeCellRenderer createDefaultCellRenderer() { - return new WindowsTreeCellRenderer(); - } - -// /** -// * The minus sign button icon -// *

    -// * Warning: -// * Serialized objects of this class will not be compatible with -// * future Swing releases. The current serialization support is appropriate -// * for short term storage or RMI between applications running the same -// * version of Swing. A future release of Swing will provide support for -// * long term persistence. -// */ -// public static class ExpandedIcon implements Icon, Serializable -// { -// -// static public Icon createExpandedIcon() -// { -// return new ExpandedIcon(); -// } -// -//// Skin getSkin(Component c) -//// { -//// XPStyle xp = XPStyle.getXP(); -//// return (xp != null) ? xp.getSkin(c, Part.TVP_GLYPH) : null; -//// } -// -// public void paintIcon(Component c, Graphics g, int x, int y) -// { -//// Skin skin = getSkin(c); -//// if (skin != null) { -//// skin.paintSkin(g, x, y, State.OPENED); -//// return; -//// } -// -// Color backgroundColor = c.getBackground(); -// -// if(backgroundColor != null) -// g.setColor(backgroundColor); -// else -// g.setColor(Color.white); -// -// g.fillRect(x, y, SIZE-1, SIZE-1); -// g.setColor(Color.gray); -// g.drawRect(x, y, SIZE-1, SIZE-1); -// g.setColor(Color.black); -// g.drawLine(x + 2, y + HALF_SIZE, x + (SIZE - 3), y + HALF_SIZE); -// } -// -// public int getIconWidth() { -//// Skin skin = getSkin(null); -// return //(skin != null) ? skin.getWidth() : -// SIZE; -// } -// -// public int getIconHeight() -// { -//// Skin skin = getSkin(null); -// return //(skin != null) ? skin.getHeight() : -// SIZE; -// } -// } -// /** -// * The plus sign button icon -// *

    -// * Warning: -// * Serialized objects of this class will not be compatible with -// * future Swing releases. The current serialization support is appropriate -// * for short term storage or RMI between applications running the same -// * version of Swing. A future release of Swing will provide support for -// * long term persistence. -// */ -// public static class CollapsedIcon extends ExpandedIcon { -// static public Icon createCollapsedIcon() { -// return new CollapsedIcon(); -// } -// -// public void paintIcon(Component c, Graphics g, int x, int y) -// { -//// Skin skin = getSkin(c); -//// if (skin != null) -//// { -//// skin.paintSkin(g, x, y, State.CLOSED); -//// } -//// else -// { -// super.paintIcon(c, g, x, y); -// g.drawLine(x + HALF_SIZE, y + 2, x + HALF_SIZE, y + (SIZE - 3)); -// } -// } -// } - /** - * The Class WindowsTreeCellRenderer. - * - * @see - * com.sun.java.swing.plaf.windows.WindowsTreeUI.WindowsTreeCellRenderer - */ - public class WindowsTreeCellRenderer extends DefaultTreeCellRenderer {//目前没有定制内容,本来想让render绘制成圆角,但尝试后发现DefaultTreeCellRenderer类里 - //的代码设计欠佳,很难继承,要改的代码非常多,干脆作罢 -// /** -// * Configures the renderer based on the passed in components. -// * The value is set from messaging the tree with -// * convertValueToText, which ultimately invokes -// * toString on value. -// * The foreground color is set based on the selection and the icon -// * is set based on on leaf and expanded. -// */ -// public Component getTreeCellRendererComponent(JTree tree, Object value, -// boolean sel, -// boolean expanded, -// boolean leaf, int row, -// boolean hasFocus) { -// super.getTreeCellRendererComponent(tree, value, sel, -// expanded, leaf, row, -// hasFocus); -// // Windows displays the open icon when the tree item selected. -// if (!tree.isEnabled()) { -// setEnabled(false); -// if (leaf) { -// setDisabledIcon(getLeafIcon()); -// } else if (sel) { -// setDisabledIcon(getOpenIcon()); -// } else { -// setDisabledIcon(getClosedIcon()); -// } -// } -// else { -// setEnabled(true); -// if (leaf) { -// setIcon(getLeafIcon()); -// } else if (sel) { -// setIcon(getOpenIcon()); -// } else { -// setIcon(getClosedIcon()); -// } -// } -// return this; -// } - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/tree/__UI__.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/tree/__UI__.java deleted file mode 100644 index e80b28201..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/tree/__UI__.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * __UI__.java at 2015-2-1 20:25:36, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.tree; - -import java.awt.Color; - -import javax.swing.UIManager; - -import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper; -import org.jackhuang.hmcl.laf.utils.IconFactory; -import org.jackhuang.hmcl.laf.utils.UI; - -public class __UI__ extends UI { - - private static final IconFactory ICON = new IconFactory("tree"); - - public static void uiImpl() { - put("Tree.background", Color.white); - put("Tree.textBackground", Color.white); -// put("Tree.drawsFocusBorderAroundIcon", false); - put("Tree.selectionForeground", BeautyEyeLNFHelper.commonSelectionForegroundColor); - put("Tree.selectionBackground", BeautyEyeLNFHelper.commonSelectionBackgroundColor); - put("Tree.foreground", BeautyEyeLNFHelper.commonForegroundColor); - put("Tree.selectionBorderColor", BeautyEyeLNFHelper.commonFocusedBorderColor);//windows父类中默认是0,0,0 - - UIManager.put("Tree.openIcon", ICON.get("open")); - UIManager.put("Tree.closedIcon", ICON.get("closed")); - UIManager.put("Tree.leafIcon", ICON.get("leaf")); - UIManager.put("Tree.expandedIcon", ICON.get("expanded")); - UIManager.put("Tree.collapsedIcon", ICON.get("collapsed")); - - //不绘制层次线 - put("Tree.paintLines", false);//default is true - //行高 - put("Tree.rowHeight", 18);//default is 16 - //未选中时单元前景色(备选MacOSX黑 (35,35,35)) - putColor("Tree.textForeground", 70, 70, 70); - //处于编辑状态时的文本框边框,因BE LNF中文本框无边框(事实上它是用N9图实现的背景 - //边框视觉效果),所以此处要去掉,但加多点空白,与背景配合起来好看点 - putBorder("Tree.editorBorder", 1, 5, 1, 5);//Windows LNF中默认是LineBorderUIResource - - put("TreeUI", BETreeUI.class); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/AnimationController.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/AnimationController.java deleted file mode 100644 index cd6297269..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/AnimationController.java +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.laf.utils; - -import java.awt.AlphaComposite; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeEvent; -import java.util.ArrayList; -import java.util.EnumMap; -import java.util.Map; -import java.util.WeakHashMap; -import javax.swing.JComponent; -import javax.swing.SwingUtilities; -import javax.swing.Timer; -import javax.swing.UIManager; -import org.jackhuang.hmcl.laf.BeautyEyeLookAndFeel; - -import org.jackhuang.hmcl.laf.utils.TMSchema.State; -import static org.jackhuang.hmcl.laf.utils.TMSchema.State.*; -import org.jackhuang.hmcl.laf.utils.TMSchema.Part; - -/** - * A class to help mimic Vista theme animations. The only kind of - * animation it handles for now is 'transition' animation (this seems - * to be the only animation which Vista theme can do). This is when - * one picture fadein over another one in some period of time. - * According to - * https://connect.microsoft.com/feedback/ViewFeedback.aspx?FeedbackID=86852&SiteID=4 - * The animations are all linear. - * - * This class has a number of responsibilities. - *

      - *
    • It trigger rapaint for the UI components involved in the animation - *
    • It tracks the animation state for every UI component involved in the - * animation and paints {@code Skin} in new {@code State} over the - * {@code Skin} in last {@code State} using - * {@code AlphaComposite.SrcOver.derive(alpha)} where {code alpha} - * depends on the state of animation - *
    - * - * @author Igor Kushnirskiy - */ -public class AnimationController implements ActionListener, PropertyChangeListener { - - public static boolean ENABLE_ANIMATION = true; - - private static AnimationController INSTANCE = new AnimationController(); - private static final String ANIMATION_CONTROLLER_KEY = "BeautyEye.AnimationController"; - private final Map> animationStateMap - = new WeakHashMap<>(); - - //this timer is used to cause repaint on animated components - //30 repaints per second should give smooth animation affect - private final Timer timer = new Timer(1000 / 30, this); - - private static synchronized AnimationController getAnimationController(JComponent c) { - if (c.getClientProperty(ANIMATION_CONTROLLER_KEY) == null) - c.putClientProperty(ANIMATION_CONTROLLER_KEY, new AnimationController()); - return (AnimationController) c.getClientProperty(ANIMATION_CONTROLLER_KEY); - } - - private AnimationController() { - timer.setRepeats(true); - timer.setCoalesce(true); - //we need to dispose the controller on l&f change - UIManager.addPropertyChangeListener(this); - } - - private static void triggerAnimation(JComponent c, - Part part, State newState) { - if (c instanceof javax.swing.JTabbedPane - || part == Part.TP_BUTTON) - //idk: we can not handle tabs animation because - //the same (component,part) is used to handle all the tabs - //and we can not track the states - //Vista theme might have transition duration for toolbar buttons - //but native application does not seem to animate them - return; - AnimationController controller - = AnimationController.getAnimationController(c); - State oldState = controller.getState(c, part); - if (oldState != newState) { - controller.putState(c, part, newState); - if (newState == State.DEFAULT) - // it seems for DEFAULTED button state Vista does animation from - // HOT - oldState = State.ROLLOVER; - if (oldState != null) { - long duration; - //if (newState == State.DEFAULTED) { - //Only button might have DEFAULTED state - //idk: do not know how to get the value from Vista - //one second seems plausible value - duration = 500; - /*} else { - XPStyle xp = XPStyle.getXP(); - duration = (xp != null) - ? xp.getThemeTransitionDuration( - c, part, - normalizeState(oldState), - normalizeState(newState), - Prop.TRANSITIONDURATIONS) - : 1000; - }*/ - controller.startAnimation(c, part, oldState, newState, duration); - } - } - } - - // for scrollbar up, down, left and right button pictures are - // defined by states. It seems that theme has duration defined - // only for up button states thus we doing this translation here. - private static State normalizeState(State state) { - State rv; - switch (state) { - case DOWNPRESSED: - case LEFTPRESSED: - case RIGHTPRESSED: - rv = UPPRESSED; - break; - - case DOWNDISABLED: - case LEFTDISABLED: - case RIGHTDISABLED: - rv = UPDISABLED; - break; - - case DOWNHOT: - case LEFTHOT: - case RIGHTHOT: - rv = UPHOT; - break; - - case DOWNNORMAL: - case LEFTNORMAL: - case RIGHTNORMAL: - rv = UPNORMAL; - break; - - default: - rv = state; - break; - } - return rv; - } - - private synchronized State getState(JComponent component, Part part) { - State rv = null; - Object tmpObject - = component.getClientProperty(PartUIClientPropertyKey.getKey(part)); - if (tmpObject instanceof State) - rv = (State) tmpObject; - return rv; - } - - private synchronized void putState(JComponent component, Part part, - State state) { - component.putClientProperty(PartUIClientPropertyKey.getKey(part), - state); - } - - private synchronized void startAnimation(JComponent component, - Part part, - State startState, - State endState, - long millis) { - boolean isForwardAndReverse = false; - if (endState == State.DEFAULT) - isForwardAndReverse = true; - Map map = animationStateMap.get(component); - if (millis <= 0) { - if (map != null) { - map.remove(part); - if (map.isEmpty()) - animationStateMap.remove(component); - } - return; - } - if (map == null) { - map = new EnumMap<>(Part.class); - animationStateMap.put(component, map); - } - map.put(part, - new AnimationState(startState, millis, isForwardAndReverse)); - if (!timer.isRunning()) - timer.start(); - } - - public static void paintSkin(JComponent component, Skin skin, - Graphics g, int dx, int dy, int dw, int dh, State state) { - if (ENABLE_ANIMATION) - triggerAnimation(component, skin.getPart(component), state); - AnimationController controller = getAnimationController(component); - synchronized (controller) { - AnimationState animationState = null; - Map map - = controller.animationStateMap.get(component); - if (map != null) - animationState = map.get(skin.getPart(component)); - if (animationState != null) - animationState.paintSkin(skin, g, dx, dy, dw, dh, state); - else - skin.paintSkinRaw(g, dx, dy, dw, dh, state); - } - } - - @Override - public synchronized void propertyChange(PropertyChangeEvent e) { - if ("lookAndFeel".equals(e.getPropertyName()) - && !(e.getNewValue() instanceof BeautyEyeLookAndFeel)) - dispose(); - } - - @Override - public synchronized void actionPerformed(ActionEvent e) { - java.util.List componentsToRemove = null; - java.util.List partsToRemove = null; - for (JComponent component : animationStateMap.keySet()) { - component.repaint(); - if (partsToRemove != null) - partsToRemove.clear(); - Map map = animationStateMap.get(component); - if (!component.isShowing() - || map == null - || map.isEmpty()) { - if (componentsToRemove == null) - componentsToRemove = new ArrayList<>(); - componentsToRemove.add(component); - continue; - } - for (Part part : map.keySet()) - if (map.get(part).isDone()) { - if (partsToRemove == null) - partsToRemove = new ArrayList<>(); - partsToRemove.add(part); - } - if (partsToRemove != null) - if (partsToRemove.size() == map.size()) { - //animation is done for the component - if (componentsToRemove == null) - componentsToRemove = new ArrayList<>(); - componentsToRemove.add(component); - } else - for (Part part : partsToRemove) - map.remove(part); - } - if (componentsToRemove != null) - for (JComponent component : componentsToRemove) - animationStateMap.remove(component); - if (animationStateMap.isEmpty()) - timer.stop(); - } - - private synchronized void dispose() { - timer.stop(); - UIManager.removePropertyChangeListener(this); - INSTANCE = null; - } - - private static class AnimationState { - - private final State startState; - - //animation duration in nanoseconds - private final long duration; - - //animatin start time in nanoseconds - private long startTime; - - //direction the alpha value is changing - //forward - from 0 to 1 - //!forward - from 1 to 0 - private boolean isForward = true; - - //if isForwardAndReverse the animation continually goes - //forward and reverse. alpha value is changing from 0 to 1 then - //from 1 to 0 and so forth - private final boolean isForwardAndReverse; - - private float progress; - - AnimationState(final State startState, - final long milliseconds, - boolean isForwardAndReverse) { - assert startState != null && milliseconds > 0; - assert SwingUtilities.isEventDispatchThread(); - - this.startState = startState; - this.duration = milliseconds * 1000000; - this.startTime = System.nanoTime(); - this.isForwardAndReverse = isForwardAndReverse; - progress = 0f; - } - - private void updateProgress() { - assert SwingUtilities.isEventDispatchThread(); - - if (isDone()) - return; - long currentTime = System.nanoTime(); - - progress = ((float) (currentTime - startTime)) - / duration; - progress = Math.max(progress, 0); //in case time was reset - if (progress >= 1) { - progress = 1; - if (isForwardAndReverse) { - startTime = currentTime; - progress = 0; - isForward = !isForward; - } - } - } - - void paintSkin(Skin skin, Graphics _g, - int dx, int dy, int dw, int dh, State state) { - assert SwingUtilities.isEventDispatchThread(); - - updateProgress(); - if (!isDone()) { - Graphics2D g = (Graphics2D) _g.create(); - skin.paintSkinRaw(g, dx, dy, dw, dh, startState); - float alpha; - if (isForward) - alpha = progress; - else - alpha = 1 - progress; - g.setComposite(AlphaComposite.SrcOver.derive(alpha)); - skin.paintSkinRaw(g, dx, dy, dw, dh, state); - g.dispose(); - } else - skin.paintSkinRaw(_g, dx, dy, dw, dh, state); - } - - boolean isDone() { - assert SwingUtilities.isEventDispatchThread(); - - return progress >= 1; - } - } - - private static class PartUIClientPropertyKey { - - private static final Map MAP - = new EnumMap<>(Part.class); - - static synchronized PartUIClientPropertyKey getKey(Part part) { - PartUIClientPropertyKey rv = MAP.get(part); - if (rv == null) { - rv = new PartUIClientPropertyKey(part); - MAP.put(part, rv); - } - return rv; - } - - private final Part part; - - private PartUIClientPropertyKey(Part part) { - this.part = part; - } - - @Override - public String toString() { - return part.toString(); - } - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/BEUtils.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/BEUtils.java deleted file mode 100644 index ace5a6250..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/BEUtils.java +++ /dev/null @@ -1,448 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BEUtils.java at 2015-2-1 20:25:38, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Component; -import java.awt.Container; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.GradientPaint; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Image; -import java.awt.Paint; -import java.awt.Polygon; -import java.awt.Rectangle; -import java.awt.RenderingHints; -import java.awt.Stroke; -import java.awt.TexturePaint; -import java.awt.Toolkit; -import java.awt.image.BufferedImage; -import java.awt.image.RescaleOp; - -import javax.swing.ImageIcon; -import javax.swing.JComponent; -import javax.swing.UIManager; - -/** - * The Class BEUtils. - */ -public class BEUtils { - - /** - * 使用RescaleOp对图片进行滤镜处理. - * - * @param iconBottom 原图 - * @param redFilter 红色通道滤镜值,1.0f表示保持不变 - * @param greenFilter 绿色通道滤镜值,1.0f表示保持不变 - * @param blueFilter 蓝色通道滤镜值,1.0f表示保持不变 - * @param alphaFilter alpha通道滤镜值,1.0f表示保持不变 - * @return 处理后的图片新对象 - * @author Jack Jiang, 2013-04-05 - * @since 3.5 - */ - public static ImageIcon filterWithRescaleOp(ImageIcon iconBottom, - float redFilter, float greenFilter, float blueFilter, float alphaFilter) { - try { - int w = iconBottom.getIconWidth(), h = iconBottom.getIconHeight(); - - //原图 - BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); - Graphics2D gg = (Graphics2D) bi.getGraphics(); - gg.drawImage(iconBottom.getImage(), 0, 0, w, h, null); - - //设置滤镜效果 - float[] scales = { redFilter, greenFilter, blueFilter, alphaFilter }; - float[] offsets = new float[4]; - RescaleOp rop = new RescaleOp(scales, offsets, null); - - //执行 - // gg.drawImage(bi, rop, 0, 0);//用这一行代码没效果,用下一行代码即可! - rop.filter(bi, bi); - return new ImageIcon(bi); - - } catch (Exception e) { - LogHelper.error("filterWithRescaleOp出错了," + e.getMessage() + ",iconBottom=" + iconBottom); - return new ImageIcon(); - } - } - - /** - *
    -     * 给一个距形区域绘制4个角效果,形状和坐标如下:
    -     * A(x,y)----B(x+β)                  C(x+(w-β),y)---D(x+w,y)
    -     * |                                                |
    -     * |                                                |
    -     * |                                                |
    -     * E(x,y+β)                                     L(x+w,y+β)
    -     *
    -     *
    -     * F(x,y+(h-β))                               K(x+w,y+(h-β))
    -     * |                                                |
    -     * |                                                |
    -     * |                                                |
    -     * G(x,y+h)----H(x+β,y+h)         I(x+(w-β),y+h)----J(x+w,y+h)
    -     * 
    - * - * @param g - * @param x 距形区的X坐标 - * @param y 距形区的Y坐标 - * @param w 距形区的宽 - * @param h 距形区的高 - * @param β 每个角的角长 - * @author Jack Jiang, 2013-04-05 - * @since 3.5 - */ - public static void draw4RecCorner(Graphics g, int x, int y, int w, int h, int β, Color c) { - Color oldColor = g.getColor(); - - g.setColor(c); - //top(A~B,C~D) - g.drawLine(x, y, x + β, y); - g.drawLine(x + (w - β), y, x + w, y); - - //left(A~E,F~G) - g.drawLine(x, y, x, y + β); - g.drawLine(x, y + (h - β), x, y + h); - - //bottom(G~H,I~J) - g.drawLine(x, y + h, x + β, y + h); - g.drawLine(x + (w - β), y + h, x + w, y + h); - - //right(J~K,L~D) - g.drawLine(x + w, y + h, x + w, y + (h - β)); - g.drawLine(x + w, y + β, x + w, y); - g.setColor(oldColor); - } - - /** - * 设置对象集的透明性,如果该组件是Container及其子类则递归设 - * 置该组件内的所有子组件的透明性,直到组件中的任何组件都被设置完毕. - * - * @param comps 对象集 - * @param opaque true表示要设置成不透明,否则表示要设置成透明 - */ - public static void componentsOpaque(java.awt.Component[] comps, - boolean opaque) { - if (comps == null) - return; - for (Component c : comps) - //递归设置它的子组件 - if (c instanceof Container) { - if (c instanceof JComponent) - ((JComponent) c).setOpaque(opaque); - componentsOpaque(((Container) c).getComponents(), opaque); - } else - if (c instanceof JComponent) - ((JComponent) c).setOpaque(opaque); - } - - /** - * 图形绘制反走样设置. - * - * @param g2 the g2 - * @param antiAliasing 是否反走样 - */ - public static void setAntiAliasing(Graphics2D g2, boolean antiAliasing) { - if (antiAliasing) - g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, - RenderingHints.VALUE_ANTIALIAS_ON); - else - g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, - RenderingHints.VALUE_ANTIALIAS_OFF); - } - - /** - * 填充3角形区域. - * - * @param g the g - * @param x1 3个点之一的x坐标 - * @param y1 3个点之一的y坐标 - * @param x2 3个点之一的x坐标 - * @param y2 3个点之一的y坐标 - * @param x3 3个点之一的x坐标 - * @param y3 3个点之一的y坐标 - * @param c the c - */ - public static void fillTriangle(Graphics g, - int x1, int y1, int x2, int y2, - int x3, int y3, Color c) { - int[] x = new int[3], y = new int[3]; - // A simple triangle. - x[0] = x1; - x[1] = x2; - x[2] = x3; - y[0] = y1; - y[1] = y2; - y[2] = y3; - int n = 3; - - Polygon p = new Polygon(x, y, n); // This polygon represents a triangle with the above - // vertices. - g.setColor(c); - g.fillPolygon(p); // Fills the triangle above. - } - - /** - * 绘制虚线框(本方法适用于对4个边的可选绘制情况下,可能会有4舍5入的小误差 - * ,除了要可选绘制4个边外,一般不推荐使用).
    . - * - * @param g the g - * @param x the x - * @param y the y - * @param width the width - * @param height the height - */ - public static void drawDashedRect(Graphics g, int x, int y, int width, int height) { - drawDashedRect(g, x, y, width, height, 6, 6, 2, 2); - } - - /** - * 绘制虚线框(本方法适用于对4个边的可选绘制情况下,可能会有4舍5入的小误差 - * ,除了要可选绘制4个边外,一般不推荐使用). - * - * @param g the g - * @param x the x - * @param y the y - * @param width the width - * @param height the height - * @param arcWidth the arc width - * @param arcHeight the arc height - * @param separator_solid 虚线段实线长度 - * @param separator_space 虚线段空白长度 - * add by js,2009-08-30 - */ - public static void drawDashedRect(Graphics g, int x, int y, int width, int height, - int arcWidth, int arcHeight, int separator_solid, int separator_space) { -// drawDashedRect(g,x,y,width,height,step,true,true,true,true); - BEUtils.setAntiAliasing((Graphics2D) g, true); - - //虚线样式 - Stroke oldStroke = ((Graphics2D) g).getStroke(); - Stroke sroke = new BasicStroke(1, BasicStroke.CAP_BUTT, - BasicStroke.JOIN_BEVEL, 0, new float[] { separator_solid, separator_space }, 0);//实线,空白 - ((Graphics2D) g).setStroke(sroke); - - g.drawRoundRect(x, y, - width - 1, height - 1 //* 一个很诡异的问题:使用BasicStroke实现虚线绘制后,似乎绘制的距形 - //* 要比普通方法绘制实线距形往下偏移一个坐标,此处-1是为了修正这个问题,这难道是java的bug? - //* 难怪当初打印工具开发时也遇到了莫名其妙偏移一个像素的现象,具体有待进一步研究! - , - arcWidth, arcHeight); - - ((Graphics2D) g).setStroke(oldStroke); - BEUtils.setAntiAliasing((Graphics2D) g, false); - } - - /** - * Draw dashed rect. - * - * @param g the g - * @param x the x - * @param y the y - * @param width the width - * @param height the height - * @param step the step - * @param top the top - * @param left the left - * @param bottom the bottom - * @param right the right - */ - public static void drawDashedRect(Graphics g, int x, int y, int width, int height, int step//,boolean drawLeft$Right - , - boolean top, boolean left, boolean bottom, boolean right) { - int vx, vy; - - int drawStep = step == 0 ? 1 : 2 * step; - int drawLingStep = step == 0 ? 1 : step; - // draw upper and lower horizontal dashes - for (vx = x; vx < (x + width); vx += drawStep) { - if (top) - g.fillRect(vx, y, drawLingStep, 1); - if (bottom) - g.fillRect(vx, y + height - 1, drawLingStep, 1); - } - -// if(drawLeft$Right) - // draw left and right vertical dashes - for (vy = y; vy < (y + height); vy += drawStep) { - if (left) - g.fillRect(x, vy, 1, drawLingStep); - if (right) - g.fillRect(x + width - 1, vy, 1, drawLingStep); - } - } - - /** - * 对基准颜色的RGB通道进行加减后得到的新色调. - * - * @param basic 基准色调 - * @param r Red通道的增加值(可以是负) - * @param g Geen通道的增加值(可以是负) - * @param b Blue通道的增加值(可以是负) - * @return the color - */ - public static Color getColor(Color basic, int r, int g, int b) { - return new Color(getColorInt(basic.getRed() + r), - getColorInt(basic.getGreen() + g), - getColorInt(basic.getBlue() + b), - getColorInt(basic.getAlpha())); - } - - /** - * 对基准颜色的RGBA通道进行加减后得到的新色调. - * - * @param basic 基准色调 - * @param r Red通道的增加值(可以是负) - * @param g Geen通道的增加值(可以是负) - * @param b Blue通道的增加值(可以是负) - * @param a Alpha通道的增加值(可以是负) - * @return the color - */ - public static Color getColor(Color basic, int r, int g, int b, int a) { - return new Color(getColorInt(basic.getRed() + r), - getColorInt(basic.getGreen() + g), - getColorInt(basic.getBlue() + b), - getColorInt(basic.getAlpha() + a)); - } - - /** - * Gets the color int. - * - * @param rgb the rgb - * @return the color int - */ - public static int getColorInt(int rgb) { - return rgb < 0 ? 0 : (rgb > 255 ? 255 : rgb); - } - - /** - * 获得字符串的像素宽度. - * - * @param fm the fm - * @param str the str - * @return the str pix width - * @see FontMetrics#stringWidth(String) - */ - public static int getStrPixWidth(FontMetrics fm, String str) { - return fm.stringWidth(str + ""); - } - - /** - * 获得字符串的像素宽度. - * - * @param f the f - * @param str the str - * @return the str pix width - * @see #getStrPixWidth(FontMetrics, String) - */ - public static int getStrPixWidth(Font f, String str) { - return getStrPixWidth(Toolkit.getDefaultToolkit().getFontMetrics(f), str); - } - - /** - * 获得一个可按指定图片进行纹理填充方式的对象,利用此对象可实现图片填充背景效果。 - * - *
    -     * 示例如下(在这个例子里将实现一个以指定图片填充效果为背景的面板对象):
    -     * private FixedLayoutPane inputPane = new FixedLayoutPane() {
    -     * //给它弄一个图片平铺的背景
    -     * private TexturePaint paint = createTexturePaint(LaunchIconFactory.getInstance()
    -     * .getImage("/login_background.png").getImage());
    -     * //重写本方法实现图片平铺的背景
    -     * protected void paintComponent(Graphics g) {
    -     * super.paintComponent(g);
    -     * Graphics2D g2d = (Graphics2D) g;
    -     * g2d.setPaint(paint);
    -     * g2d.fillRect(0, 0, this.getWidth(), this.getHeight());
    -     * }
    -     * };
    -     * 
    - * - * @param image 填充图片,该图片一宽1像素高N像素(据这1像素宽进行重复填充即可达到目的) - * @return the texture paint - */ - public static TexturePaint createTexturePaint(Image image) { - int imageWidth = image.getWidth(null); - int imageHeight = image.getHeight(null); - BufferedImage bi = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_ARGB); - Graphics2D g2d = bi.createGraphics(); - g2d.drawImage(image, 0, 0, null); - g2d.dispose(); - return new TexturePaint(bi, new Rectangle(0, 0, imageWidth, imageHeight)); - } - - /** - * Gets the int. - * - * @param key the key - * @param defaultValue the default value - * @return the int - */ - public static int getInt(Object key, int defaultValue) { - Object value = UIManager.get(key); - - if (value instanceof Integer) - return (Integer) value; - if (value instanceof String) - try { - return Integer.parseInt((String) value); - } catch (NumberFormatException nfe) { - } - return defaultValue; - } - - /** - * 在指定的区域内填充出厚重质感立体效果. - * - * @param g2 the g2 - * @param baseColor the base color - * @param x the x - * @param y the y - * @param w the w - * @param h the h - * @param arc the arc - */ - public static void fillTextureRoundRec(Graphics2D g2, Color baseColor, - int x, int y, int w, int h, int arc) { - fillTextureRoundRec(g2, baseColor, - x, y, w, h, arc, 35); - } - - /** - * 在指定的区域内填充出厚重质感立体效果. - * - * @param g2 the g2 - * @param baseColor the base color - * @param x the x - * @param y the y - * @param w the w - * @param h the h - * @param arc the arc - * @param colorDelta 渐变起色(上)与渐变止色(下)的RGB色差(矢量),正表示变淡,负表示加深 - */ - public static void fillTextureRoundRec(Graphics2D g2, Color baseColor, - int x, int y, int w, int h, int arc, int colorDelta) { - setAntiAliasing(g2, true); - //矩形填充 - Paint oldpaint = g2.getPaint(); - GradientPaint gp = new GradientPaint(x, y, //渐变的起色比止色RGB浅35 - getColor(baseColor, colorDelta, colorDelta, colorDelta), - x, y + h, baseColor); - g2.setPaint(gp); - g2.fillRoundRect(x, y, w, h, arc, arc); - g2.setPaint(oldpaint); - setAntiAliasing(g2, false); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/Icon9Factory.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/Icon9Factory.java deleted file mode 100644 index 7bb58009e..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/Icon9Factory.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.jackhuang.hmcl.laf.utils; - -import java.awt.image.BufferedImage; -import java.util.HashMap; -import org.jb2011.ninepatch4j.NinePatch; - -/** - * - * @author huang - */ -public class Icon9Factory extends RawCache { - - private static final NinePatch EMPTY = NinePatch.load(new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB), false, true); - - /** - * 相对路径根(默认是相对于本类的相对物理路径). - */ - public final static String IMGS_ROOT = "imgs/np"; - - @Override - protected NinePatch getResource(String relativePath, Class baseClass) { - return NinePatchHelper.createNinePatch(baseClass.getResource(relativePath), false); - } - - public Icon9Factory(String namespace) { - ns = namespace; - init(); - } - - String ns; - - /** - * Gets the raw. - * - * @param relativePath the relative path - * @return the raw - */ - public NinePatch getRaw(String relativePath) { - return getRaw(relativePath, this.getClass()); - } - - HashMap icons = new HashMap<>(); - - protected void put(String namespace, String key, String filename) { - if (!ns.equals(namespace)) - return; - icons.put(namespace + ":" + key, getRaw(IMGS_ROOT + "/" + filename + ".9.png")); - } - - public NinePatch get(String key) { - NinePatch p = icons.get(ns + ":" + key); - if (p == null) { - System.err.println("Could not find 9patch: " + key); - icons.put(ns + ":" + key, EMPTY); - return EMPTY; - } - return p; - } - - public NinePatch get(String key, String state) { - return Icon9Factory.this.get(concat(key, state)); - } - - public NinePatch getWithEnabled(String key, boolean enabled) { - return get(key, enabled ? "" : "disabled"); - } - - public NinePatch getWithHorizontal(String key, boolean isHorizontal) { - return get(key, isHorizontal ? "" : "vertical"); - } - - public NinePatch getWithButtonState(String key, boolean enabled, boolean pressed) { - return get(key, (enabled ? (pressed ? "pressed" : "normal") : "disabled")); - } - - public NinePatch getWithScrollState(String key, boolean pressed, boolean over) { - return get(key, (pressed ? "pressed" : (over ? "rollover" : ""))); - } - - public NinePatch getWithComboState(String key, boolean enabled, boolean pressed, boolean over) { - return get(key, (enabled ? (pressed ? "pressed" : (over ? "rollover" : "normal")) : "disabled")); - } - - private String concat(String a, String b) { - if (a.isEmpty() && b.isEmpty()) - return ""; - else if (a.isEmpty()) - return b; - else if (b.isEmpty()) - return a; - else - return a + "_" + b; - } - - private void init() { - put("slider_track", "", "slider_track2"); - put("slider_track", "vertical", "slider_track2_v"); - put("slider_track", "disabled", "slider_track2_dark"); - put("slider_track", "vertical_disabled", "slider_track2_v_dark"); - put("slider_track", "foreground", "slider_track2_forgroud"); - put("slider_track", "foreground_disabled", "slider_track2_forgroud_disable"); - put("slider_track", "vertical_foreground", "slider_track2_forgroud_v"); - put("slider_track", "vertical_foreground_disabled", "slider_track2_forgroud_v_disable"); - - put("button_arrow", "normal", "button_arrow"); - put("button_arrow", "pressed", "button_arrow_pressed"); - put("button_arrow", "rollover", "button_arrow_rollover"); - put("button_arrow", "disabled", "button_arrow_disable"); - - put("progress_bar", "bg", "progress_bar_bg"); - put("progress_bar", "bg_vertical", "progress_bar_bg_v"); - put("progress_bar", "green", "progress_bar_green"); - put("progress_bar", "blue_vertical", "progress_bar_grean_v"); - - put("split_touch", "bg1", "split_touch_bg1"); - - put("list", "selected_icon_bg", "list_cell_selected_bg2"); - - put("spinner", "", "spinner1_bg"); - put("spinner", "button_up", "spinner1_btn_up_bg"); - put("spinner", "button_down", "spinner1_btn_down_bg"); - put("spinner", "button_up_pressed", "spinner1_btn_up_pressed_bg"); - put("spinner", "button_down_pressed", "spinner1_btn_down_pressed_bg"); - put("spinner", "disabled", "spinner1_disable_bg"); - - put("button", "normal", "btn_special_default"); - put("button", "disabled", "btn_special_disabled"); - put("button", "pressed", "btn_general_pressed"); - put("button", "rollover", "btn_general_rover"); - - put("toggle_button", "selected", "toggle_button_selected"); - put("toggle_button", "rollover", "toggle_button_rover"); - - put("scroll_bar", "arrow_normal", "arrow"); - put("scroll_bar", "arrow_rollover", "arrow_rover"); - put("scroll_bar", "arrow_pressed", "arrow_pressed"); - put("scroll_bar", "scroll_pane_border", "scroll_pane_bg1"); - - put("popup", "popup", "shadow_bg_popup"); - put("popup", "tooltip", "shadow_bg_tooltip2"); - - put("table", "scroll_border", "table_scrollborder1"); - put("table", "header_cell", "table_header_bg1"); - put("table", "header_cell_separator", "table_header_separator1"); - - put("toolbar", "north", "toolbar_bg1"); - put("toolbar", "south", "toolbar_bg1_SOUTH"); - put("toolbar", "west", "toolbar_bg1_WEST"); - put("toolbar", "east", "toolbar_bg1_EAST"); - - put("menu", "selected", "menu_bg"); - - put("widget", "panel", "query_item_bg_2"); - put("widget", "hint_light_blue", "hint_bg_lightblue"); - put("widget", "hint_light_gray", "hint_bg_lightblue_gray"); - put("widget", "tips", "tips_bg"); - put("widget", "orange_balloon", "orange_baloon1"); - put("widget", "border_shadow1", "shadow1"); - put("widget", "border_shadow2", "shadow2"); - put("widget", "border_plain_gray", "plain_gray1"); - put("widget", "border_shadow3", "frame_shadow_border4"); - - put("combo", "normal", "combo_normal"); - put("combo", "disabled", "combo_disabled"); - put("combo", "rollover", "combo_over"); - put("combo", "pressed", "combo_pressed"); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/IconFactory.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/IconFactory.java deleted file mode 100644 index 9283111f7..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/IconFactory.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.jackhuang.hmcl.laf.utils; - -import java.util.HashMap; -import javax.swing.ImageIcon; - -/** - * - * @author huang - */ -public class IconFactory extends RawCache { - - /** - * 相对路径根(默认是相对于本类的相对物理路径). - */ - public final static String IMGS_ROOT = "imgs"; - - public IconFactory(String namespace) { - ns = namespace; - init(); - } - - String ns; - - @Override - protected ImageIcon getResource(String relativePath, Class baseClass) { - return new ImageIcon(baseClass.getResource(relativePath)); - } - - /** - * Gets the image. - * - * @param relativePath the relative path - * @return the image - */ - protected ImageIcon getImage(String relativePath) { - return getRaw(relativePath, IconFactory.class); - } - - HashMap icons = new HashMap<>(); - - protected void put(String namespace, String key, String filename) { - if (!ns.equals(namespace)) - return; - icons.put(namespace + ":" + key, getImage(IMGS_ROOT + "/" + filename + ".png")); - } - - public ImageIcon get(String... states) { - String s = ""; - for (String k : states) - s = concat(s, k); - return icons.get(ns + ":" + s); - } - - public ImageIcon getWithButtonState(String key, boolean enabled, boolean pressed) { - return get(key, (enabled ? (pressed ? "pressed" : "normal") : "disabled")); - } - - private String concat(String a, String b) { - if (a.isEmpty() && b.isEmpty()) - return ""; - else if (a.isEmpty()) - return b; - else if (b.isEmpty()) - return a; - else - return a + "_" + b; - } - - void init() { - put("menu", "radio_check", "RadioButtonMenuItemCheckIcon2"); - put("menu", "radio_normal", "RadioButtonMenuItemCheckIcon_none"); - put("menu", "check_selected", "checkbox_menuitem_selected_normal"); - put("menu", "check_none", "checkbox_menuitem_none"); - - put("internal_frame", "close", "frame_close_over"); - put("internal_frame", "min", "frame_windowize_over"); - put("internal_frame", "max", "frame_maximize_over"); - put("internal_frame", "iconify", "frame_minimize_over"); - put("internal_frame", "icon", "ifi1"); - - put("radio", "disabled", "radio_btn_disabled_selected"); - put("radio", "normal", "radio_btn_selected"); - put("radio", "pressed", "radio_btn_selected_pressed"); - put("radio", "over", "radio_btn_selected_over"); - put("radio", "unchecked_disabled", "radio_btn_disabled_normal"); - put("radio", "unchecked_normal", "radio_btn"); - put("radio", "unchecked_pressed", "radio_btn_pressed"); - put("radio", "unchecked_over", "radio_btn_over"); - - put("check", "disabled", "checkbox_on_disabled"); - put("check", "normal", "checkbox_on"); - put("check", "pressed", "checkbox_on_pressed"); - put("check", "over", "checkbox_on_over"); - put("check", "unchecked_disabled", "checkbox_off_disabled"); - put("check", "unchecked_normal", "checkbox_off"); - put("check", "unchecked_pressed", "checkbox_off_pressed"); - put("check", "unchecked_over", "checkbox_off_over"); - - put("menu_radio", "checked", "RadioButtonMenuItemCheckIcon2"); - put("menu_radio", "normal", "RadioButtonMenuItemCheckIcon_none"); - put("menu_check", "checked", "checkbox_menuitem_selected_normal"); - put("menu_check", "normal", "checkbox_menuitem_none"); - - put("table", "descending_sort", "desc2"); - put("table", "ascending_sort", "asc2"); - - put("tree", "open", "treeDefaultOpen1"); - put("tree", "closed", "treeDefaultClosed1"); - put("tree", "leaf", "leaf1"); - put("tree", "expanded", "a"); - put("tree", "collapsed", "b"); - - put("option_pane", "warn", "warn"); - put("option_pane", "error", "error"); - put("option_pane", "info", "info"); - put("option_pane", "question", "question"); - - put("slider", "", "slider_tick1"); - put("slider", "disabled", "slider_tick1_dark"); - put("slider", "vertical", "slider_tick1_v"); - put("slider", "vertical_disabled", "slider_tick1_v_dark"); - put("slider", "notriangle", "slider_tick1_notrangle"); - put("slider", "notriangle_disabled", "slider_tick1_notrangle_dark"); - put("slider", "notriangle_vertical", "slider_tick1_notrangle_v"); - put("slider", "notriangle_vertical_disabled", "slider_tick1_notrangle_v_dark"); - - put("frame", "close", "frame_close_normal"); - put("frame", "close_over", "frame_close_rover"); - put("frame", "close_pressed", "frame_close_pressed"); - put("frame", "min", "frame_maxwin"); - put("frame", "min_over", "frame_maxwin_rover"); - put("frame", "min_pressed", "frame_maxwin_pressed"); - put("frame", "max", "frame_max_normal"); - put("frame", "max_over", "frame_max_rover"); - put("frame", "max_pressed", "frame_max_pressed"); - put("frame", "iconify", "frame_min_normal"); - put("frame", "iconify_over", "frame_min_rover"); - put("frame", "iconify_pressed", "frame_min_pressed"); - put("frame", "icon", "default_frame_icon"); - put("frame", "setup", "frame_setup_normal"); - put("frame", "title_active", "head_bg"); - put("frame", "title_inactive", "head_inactive"); - } - -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/LogHelper.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/LogHelper.java deleted file mode 100644 index d87b121d7..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/LogHelper.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * LogHelper.java at 2015-2-1 20:25:40, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf; - -import org.jackhuang.hmcl.laf.BeautyEyeLNFHelper; - -/** - * The Class LogHelper. - * - * @author Jack Jiang, 2013-04-05 - * @since 3.5 - * @see BeautyEyeLNFHelper#debug - */ -public class LogHelper -{ - /** - * Error. - * - * @param msg the msg - */ - public static void error(String msg) - { - if(BeautyEyeLNFHelper.debug) - System.err.println("[BE-ERROR] - "+msg); - } - - /** - * Debug. - * - * @param msg the msg - */ - public static void debug(String msg) - { - if(BeautyEyeLNFHelper.debug) - System.err.println("[BE-DEBUG] - "+msg); - } - - /** - * Info. - * - * @param msg the msg - */ - public static void info(String msg) - { - System.err.println("[BE-INFO] - "+msg); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/MySwingUtilities2.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/MySwingUtilities2.java deleted file mode 100644 index d24ab69b5..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/MySwingUtilities2.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * MySwingUtilities2.java at 2015-2-1 20:25:40, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.utils; - -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.RenderingHints; -import java.awt.Toolkit; - -import javax.swing.JComponent; - -/** - * 本类中的方法一一对应于SUN未公开的类SwingUtilities2中的方法. - * - * 部分代码摘自JDK 1.5. - * - * @author Jack Jiang(jb2011@163.com) - * @author huangyuhui - */ -public class MySwingUtilities2 { - - /** - * Returns the FontMetrics for the current Font of the passed in Graphics. - * This method is used when a Graphics is available, typically when - * painting. If a Graphics is not available the JComponent method of the - * same name should be used. - *

    - * Callers should pass in a non-null JComponent, the exception to this is if - * a JComponent is not readily available at the time of painting. - *

    - * This does not necessarily return the FontMetrics from the Graphics. - * - * @param c JComponent requesting FontMetrics, may be null - * @param g Graphics Graphics - * @return the font metrics - */ - public static FontMetrics getFontMetrics(JComponent c, Graphics g) { - return getFontMetrics(c, g, g.getFont()); - } - - /** - * Returns the FontMetrics for the specified Font. This method is used when - * a Graphics is available, typically when painting. If a Graphics is not - * available the JComponent method of the same name should be used. - *

    - * Callers should pass in a non-null JComonent, the exception to this is if - * a JComponent is not readily available at the time of painting. - *

    - * This does not necessarily return the FontMetrics from the Graphics. - * - * @param c Graphics Graphics - * @param g the g - * @param font Font to get FontMetrics for - * @return the font metrics - */ - public static FontMetrics getFontMetrics(JComponent c, Graphics g, - Font font) { - if (c != null) - // Note: We assume that we're using the FontMetrics - // from the widget to layout out text, otherwise we can get - // mismatches when printing. - return c.getFontMetrics(font); - return Toolkit.getDefaultToolkit().getFontMetrics(font); - } - - /** - * Returns the width of the passed in String. - * - * @param c JComponent that will display the string, may be null - * @param fm FontMetrics used to measure the String width - * @param string String to get the width of - * @return the int - */ - public static int stringWidth(JComponent c, FontMetrics fm, String string) { - return fm.stringWidth(string); - } - - /** - * Draws the string at the specified location. - * - * @param c JComponent that will display the string, may be null - * @param g Graphics to draw the text to - * @param text String to display - * @param x X coordinate to draw the text at - * @param y Y coordinate to draw the text at - */ - public static void drawString(JComponent c, Graphics g, String text, - int x, int y) { - Graphics2D g2d = (Graphics2D) g; - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g2d.drawString(text, x, y); - } - - /** - * Draws the string at the specified location underlining the specified - * character. - * - * @param c JComponent that will display the string, may be null - * @param g Graphics to draw the text to - * @param text String to display - * @param underlinedIndex Index of a character in the string to underline - * @param x X coordinate to draw the text at - * @param y Y coordinate to draw the text at - */ - public static void drawStringUnderlineCharAt(JComponent c, Graphics g, - String text, int underlinedIndex, int x, int y) { - drawString(c, g, text, x, y); - if (underlinedIndex >= 0 && underlinedIndex < text.length()) { - // PENDING: this needs to change. - FontMetrics fm = g.getFontMetrics(); - int underlineRectX = x + stringWidth(c, - fm, text.substring(0, underlinedIndex)); - int underlineRectY = y; - int underlineRectWidth = fm.charWidth(text. - charAt(underlinedIndex)); - int underlineRectHeight = 1; - g.fillRect(underlineRectX, underlineRectY + 1, - underlineRectWidth, underlineRectHeight); - } - } - - /** - * Clips the passed in String to the space provided. - * - * @param c JComponent that will display the string, may be null - * @param fm FontMetrics used to measure the String width - * @param string String to display - * @param availTextWidth Amount of space that the string can be drawn in - * @return Clipped string that can fit in the provided space. - */ - public static String clipStringIfNecessary(JComponent c, FontMetrics fm, - String string, int availTextWidth) { - if ((string == null) || (string.equals(""))) - return ""; - int textWidth = stringWidth(c, fm, string); - if (textWidth > availTextWidth) - return clipString(c, fm, string, availTextWidth); - return string; - } - - /** - * Clips the passed in String to the space provided. NOTE: this assumes the - * string does not fit in the available space. - * - * @param c JComponent that will display the string, may be null - * @param fm FontMetrics used to measure the String width - * @param string String to display - * @param availTextWidth Amount of space that the string can be drawn in - * @return Clipped string that can fit in the provided space. - */ - public static String clipString(JComponent c, FontMetrics fm, - String string, int availTextWidth) { - // c may be null here. - String clipString = "..."; - int width = stringWidth(c, fm, clipString); - // NOTE: This does NOT work for surrogate pairs and other fun - // stuff - int nChars = 0; - for (int max = string.length(); nChars < max; nChars++) { - width += fm.charWidth(string.charAt(nChars)); - if (width > availTextWidth) - break; - } - string = string.substring(0, nChars) + clipString; - return string; - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/NinePatchHelper.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/NinePatchHelper.java deleted file mode 100644 index 6c9f15421..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/NinePatchHelper.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * NinePatchHelper.java at 2015-2-1 20:25:36, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.utils; - -import java.awt.image.BufferedImage; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; - -import org.jb2011.ninepatch4j.NinePatch; - -/** - * NinePatch图辅助工厂类. - * - * @author Jack Jiang(jb2011@163.com), 2011-12-22 - * @version 1.0 - */ -public class NinePatchHelper { - - /** - * Creates the nine patch. - * - * @param fileUrl the file url - * @param convert the convert - * @return the nine patch - * @see NinePatch#load(URL, boolean) - */ - public static NinePatch createNinePatch(URL fileUrl, boolean convert) { - try { - return NinePatch.load(fileUrl, convert); - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - /** - * Creates the nine patch. - * - * @param stream the stream - * @param is9Patch the is9 patch - * @param convert the convert - * @return the nine patch - * @throws IOException Signals that an I/O exception has occurred. - * @see NinePatch#load(InputStream, boolean, boolean) - */ - public static NinePatch createNinePatch(InputStream stream, boolean is9Patch, boolean convert) throws IOException { - return NinePatch.load(stream, is9Patch, convert); - } - - /** - * Creates the nine patch. - * - * @param image the image - * @param is9Patch the is9 patch - * @param convert the convert - * @return the nine patch - * @see NinePatch#load(BufferedImage, boolean, boolean) - */ - public static NinePatch createNinePatch(BufferedImage image, boolean is9Patch, boolean convert) { - return NinePatch.load(image, is9Patch, convert); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/RawCache.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/RawCache.java deleted file mode 100644 index ac79ca077..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/RawCache.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * RawCache.java at 2015-2-1 20:25:40, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.utils; - -import java.util.HashMap; - -/** - * 本地磁盘资源文件缓存中心超类,子类可继承本类以实现磁盘资源的集中缓存. - * - * @param the generic type - * @author Jack Jiang(jb2011@163.com), 2010-09-11 - * @version 1.0 - */ -public abstract class RawCache { - - /** - * 本地磁盘资源缓存中心(key=path,value=image对象). - */ - private final HashMap rawCache = new HashMap<>(); - - /** - * 本地磁盘资源(如果缓存中已存在,则从中取之,否则从磁盘读取并缓存之). - * - * @param relativePath - * 本地磁盘资源相对于baseClass类的相对路径,比如它如果在/res/imgs/pic/下,baseClass在 - * /res下,则本地磁盘资源此处传过来的相对路径应该是/imgs/pic/some.png - * @param baseClass 基准类,指定此类则获取本地磁盘资源时会以此类为基准取本地磁盘资源的相对物理目录 - * @return T - */ - public T getRaw(String relativePath, Class baseClass) { - T ic = null; - - String key = relativePath + baseClass.getCanonicalName(); - if (rawCache.containsKey(key)) - ic = rawCache.get(key); - else - try { - ic = getResource(relativePath, baseClass); - rawCache.put(key, ic); - } catch (Exception e) { - System.out.println("取本地磁盘资源文件出错,path=" + key + "," + e.getMessage()); - e.printStackTrace(); - } - return ic; - } - - /** - * 本地资源获取方法实现. - * - * @param relativePath 相对路径 - * @param baseClass 基准类 - * @return the resource - */ - protected abstract T getResource(String relativePath, Class baseClass); -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/Skin.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/Skin.java deleted file mode 100644 index fab7bcffd..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/Skin.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.laf.utils; - -import java.awt.Graphics; -import javax.swing.JComponent; - -/** - * - * @author huang - */ -public interface Skin { - void paintSkinRaw(Graphics g, int x, int y, int w, int h, TMSchema.State state); - - TMSchema.Part getPart(JComponent c); -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/TMSchema.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/TMSchema.java deleted file mode 100644 index 49ff758a9..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/TMSchema.java +++ /dev/null @@ -1,457 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -package org.jackhuang.hmcl.laf.utils; - -/* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. - * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - */ - - /* - *

    These classes are designed to be used while the - * corresponding LookAndFeel class has been installed - * (UIManager.setLookAndFeel(new XXXLookAndFeel())). - * Using them while a different LookAndFeel is installed - * may produce unexpected results, including exceptions. - * Additionally, changing the LookAndFeel - * maintained by the UIManager without updating the - * corresponding ComponentUI of any - * JComponents may also produce unexpected results, - * such as the wrong colors showing up, and is generally not - * encouraged. - * - */ -import java.awt.*; -import java.util.*; - -import javax.swing.*; - -/** - * Implements Windows Parts and their States and Properties for the Windows Look and Feel. - * - * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/userex/topics/partsandstates.asp - * See tmschema.h (or vssym32.h & vsstyle.h for MS Vista) - * - * @author Leif Samuelsson - */ -public class TMSchema { - - /** - * An enumeration of the various Windows controls (also known as - * components, or top-level parts) - */ - public static enum Control { - BUTTON, - COMBOBOX, - EDIT, - HEADER, - LISTBOX, - LISTVIEW, - MENU, - PROGRESS, - REBAR, - SCROLLBAR, - SPIN, - TAB, - TOOLBAR, - TRACKBAR, - TREEVIEW, - WINDOW - } - - /** - * An enumeration of the Windows compoent parts - */ - public static enum Part { - MENU(Control.MENU, 0), // Special case, not in native - MP_BARBACKGROUND(Control.MENU, 7), - MP_BARITEM(Control.MENU, 8), - MP_POPUPBACKGROUND(Control.MENU, 9), - MP_POPUPBORDERS(Control.MENU, 10), - MP_POPUPCHECK(Control.MENU, 11), - MP_POPUPCHECKBACKGROUND(Control.MENU, 12), - MP_POPUPGUTTER(Control.MENU, 13), - MP_POPUPITEM(Control.MENU, 14), - MP_POPUPSEPARATOR(Control.MENU, 15), - MP_POPUPSUBMENU(Control.MENU, 16), - BP_PUSHBUTTON(Control.BUTTON, 1), - BP_RADIOBUTTON(Control.BUTTON, 2), - BP_CHECKBOX(Control.BUTTON, 3), - BP_GROUPBOX(Control.BUTTON, 4), - CP_COMBOBOX(Control.COMBOBOX, 0), - CP_DROPDOWNBUTTON(Control.COMBOBOX, 1), - CP_BACKGROUND(Control.COMBOBOX, 2), - CP_TRANSPARENTBACKGROUND(Control.COMBOBOX, 3), - CP_BORDER(Control.COMBOBOX, 4), - CP_READONLY(Control.COMBOBOX, 5), - CP_DROPDOWNBUTTONRIGHT(Control.COMBOBOX, 6), - CP_DROPDOWNBUTTONLEFT(Control.COMBOBOX, 7), - CP_CUEBANNER(Control.COMBOBOX, 8), - EP_EDIT(Control.EDIT, 0), - EP_EDITTEXT(Control.EDIT, 1), - HP_HEADERITEM(Control.HEADER, 1), - HP_HEADERSORTARROW(Control.HEADER, 4), - LBP_LISTBOX(Control.LISTBOX, 0), - LVP_LISTVIEW(Control.LISTVIEW, 0), - PP_PROGRESS(Control.PROGRESS, 0), - PP_BAR(Control.PROGRESS, 1), - PP_BARVERT(Control.PROGRESS, 2), - PP_CHUNK(Control.PROGRESS, 3), - PP_CHUNKVERT(Control.PROGRESS, 4), - RP_GRIPPER(Control.REBAR, 1), - RP_GRIPPERVERT(Control.REBAR, 2), - SBP_SCROLLBAR(Control.SCROLLBAR, 0), - SBP_ARROWBTN(Control.SCROLLBAR, 1), - SBP_THUMBBTNHORZ(Control.SCROLLBAR, 2), - SBP_THUMBBTNVERT(Control.SCROLLBAR, 3), - SBP_LOWERTRACKHORZ(Control.SCROLLBAR, 4), - SBP_UPPERTRACKHORZ(Control.SCROLLBAR, 5), - SBP_LOWERTRACKVERT(Control.SCROLLBAR, 6), - SBP_UPPERTRACKVERT(Control.SCROLLBAR, 7), - SBP_GRIPPERHORZ(Control.SCROLLBAR, 8), - SBP_GRIPPERVERT(Control.SCROLLBAR, 9), - SBP_SIZEBOX(Control.SCROLLBAR, 10), - SPNP_UP(Control.SPIN, 1), - SPNP_DOWN(Control.SPIN, 2), - TABP_TABITEM(Control.TAB, 1), - TABP_TABITEMLEFTEDGE(Control.TAB, 2), - TABP_TABITEMRIGHTEDGE(Control.TAB, 3), - TABP_PANE(Control.TAB, 9), - TP_TOOLBAR(Control.TOOLBAR, 0), - TP_BUTTON(Control.TOOLBAR, 1), - TP_SEPARATOR(Control.TOOLBAR, 5), - TP_SEPARATORVERT(Control.TOOLBAR, 6), - TKP_TRACK(Control.TRACKBAR, 1), - TKP_TRACKVERT(Control.TRACKBAR, 2), - TKP_THUMB(Control.TRACKBAR, 3), - TKP_THUMBBOTTOM(Control.TRACKBAR, 4), - TKP_THUMBTOP(Control.TRACKBAR, 5), - TKP_THUMBVERT(Control.TRACKBAR, 6), - TKP_THUMBLEFT(Control.TRACKBAR, 7), - TKP_THUMBRIGHT(Control.TRACKBAR, 8), - TKP_TICS(Control.TRACKBAR, 9), - TKP_TICSVERT(Control.TRACKBAR, 10), - TVP_TREEVIEW(Control.TREEVIEW, 0), - TVP_GLYPH(Control.TREEVIEW, 2), - WP_WINDOW(Control.WINDOW, 0), - WP_CAPTION(Control.WINDOW, 1), - WP_MINCAPTION(Control.WINDOW, 3), - WP_MAXCAPTION(Control.WINDOW, 5), - WP_FRAMELEFT(Control.WINDOW, 7), - WP_FRAMERIGHT(Control.WINDOW, 8), - WP_FRAMEBOTTOM(Control.WINDOW, 9), - WP_SYSBUTTON(Control.WINDOW, 13), - WP_MDISYSBUTTON(Control.WINDOW, 14), - WP_MINBUTTON(Control.WINDOW, 15), - WP_MDIMINBUTTON(Control.WINDOW, 16), - WP_MAXBUTTON(Control.WINDOW, 17), - WP_CLOSEBUTTON(Control.WINDOW, 18), - WP_MDICLOSEBUTTON(Control.WINDOW, 20), - WP_RESTOREBUTTON(Control.WINDOW, 21), - WP_MDIRESTOREBUTTON(Control.WINDOW, 22); - - private final Control control; - private final int value; - - private Part(Control control, int value) { - this.control = control; - this.value = value; - } - - public int getValue() { - return value; - } - - public String getControlName(Component component) { - String str = ""; - if (component instanceof JComponent) { - JComponent c = (JComponent) component; - String subAppName = (String) c.getClientProperty("XPStyle.subAppName"); - if (subAppName != null) - str = subAppName + "::"; - } - return str + control.toString(); - } - - @Override - public String toString() { - return control.toString() + "." + name(); - } - } - - /** - * An enumeration of the possible component states - */ - public static enum State { - ACTIVE, - ASSIST, - BITMAP, - CHECKED, - CHECKEDDISABLED, - CHECKEDHOT, - CHECKEDNORMAL, - CHECKEDPRESSED, - CHECKMARKNORMAL, - CHECKMARKDISABLED, - BULLETNORMAL, - BULLETDISABLED, - CLOSED, - DEFAULT, - DISABLED, - DISABLEDHOT, - DISABLEDPUSHED, - DOWNDISABLED, - DOWNHOT, - DOWNNORMAL, - DOWNPRESSED, - FOCUSED, - ROLLOVER, - ROLLOVERCHECKED, - ICONHOT, - ICONNORMAL, - ICONPRESSED, - ICONSORTEDHOT, - ICONSORTEDNORMAL, - ICONSORTEDPRESSED, - INACTIVE, - INACTIVENORMAL, // See note 1 - INACTIVEHOT, // See note 1 - INACTIVEPUSHED, // See note 1 - INACTIVEDISABLED, // See note 1 - LEFTDISABLED, - LEFTHOT, - LEFTNORMAL, - LEFTPRESSED, - MIXEDDISABLED, - MIXEDHOT, - MIXEDNORMAL, - MIXEDPRESSED, - NORMAL, - PRESSED, - OPENED, - PUSHED, - READONLY, - RIGHTDISABLED, - RIGHTHOT, - RIGHTNORMAL, - RIGHTPRESSED, - SELECTED, - UNCHECKEDDISABLED, - UNCHECKEDHOT, - UNCHECKEDNORMAL, - UNCHECKEDPRESSED, - UPDISABLED, - UPHOT, - UPNORMAL, - UPPRESSED, - HOVER, - UPHOVER, - DOWNHOVER, - LEFTHOVER, - RIGHTHOVER, - SORTEDDOWN, - SORTEDHOT, - SORTEDNORMAL, - SORTEDPRESSED, - SORTEDUP; - - /** - * A map of allowed states for each Part - */ - private static EnumMap stateMap; - - private static synchronized void initStates() { - stateMap = new EnumMap<>(Part.class); - - stateMap.put(Part.EP_EDITTEXT, - new State[] { - NORMAL, ROLLOVER, SELECTED, DISABLED, FOCUSED, READONLY, ASSIST - }); - - stateMap.put(Part.BP_PUSHBUTTON, - new State[] { NORMAL, ROLLOVER, PRESSED, DISABLED, DEFAULT }); - - stateMap.put(Part.BP_RADIOBUTTON, - new State[] { - UNCHECKEDNORMAL, UNCHECKEDHOT, UNCHECKEDPRESSED, UNCHECKEDDISABLED, - CHECKEDNORMAL, CHECKEDHOT, CHECKEDPRESSED, CHECKEDDISABLED - }); - - stateMap.put(Part.BP_CHECKBOX, - new State[] { - UNCHECKEDNORMAL, UNCHECKEDHOT, UNCHECKEDPRESSED, UNCHECKEDDISABLED, - CHECKEDNORMAL, CHECKEDHOT, CHECKEDPRESSED, CHECKEDDISABLED, - MIXEDNORMAL, MIXEDHOT, MIXEDPRESSED, MIXEDDISABLED - }); - - State[] comboBoxStates = new State[] { NORMAL, ROLLOVER, PRESSED, DISABLED }; - stateMap.put(Part.CP_COMBOBOX, comboBoxStates); - stateMap.put(Part.CP_DROPDOWNBUTTON, comboBoxStates); - stateMap.put(Part.CP_BACKGROUND, comboBoxStates); - stateMap.put(Part.CP_TRANSPARENTBACKGROUND, comboBoxStates); - stateMap.put(Part.CP_BORDER, comboBoxStates); - stateMap.put(Part.CP_READONLY, comboBoxStates); - stateMap.put(Part.CP_DROPDOWNBUTTONRIGHT, comboBoxStates); - stateMap.put(Part.CP_DROPDOWNBUTTONLEFT, comboBoxStates); - stateMap.put(Part.CP_CUEBANNER, comboBoxStates); - - stateMap.put(Part.HP_HEADERITEM, new State[] { NORMAL, ROLLOVER, PRESSED, - SORTEDNORMAL, SORTEDHOT, SORTEDPRESSED, - ICONNORMAL, ICONHOT, ICONPRESSED, - ICONSORTEDNORMAL, ICONSORTEDHOT, ICONSORTEDPRESSED }); - - stateMap.put(Part.HP_HEADERSORTARROW, - new State[] { SORTEDDOWN, SORTEDUP }); - - State[] scrollBarStates = new State[] { NORMAL, ROLLOVER, PRESSED, DISABLED, HOVER }; - stateMap.put(Part.SBP_SCROLLBAR, scrollBarStates); - stateMap.put(Part.SBP_THUMBBTNVERT, scrollBarStates); - stateMap.put(Part.SBP_THUMBBTNHORZ, scrollBarStates); - stateMap.put(Part.SBP_GRIPPERVERT, scrollBarStates); - stateMap.put(Part.SBP_GRIPPERHORZ, scrollBarStates); - - stateMap.put(Part.SBP_ARROWBTN, - new State[] { - UPNORMAL, UPHOT, UPPRESSED, UPDISABLED, - DOWNNORMAL, DOWNHOT, DOWNPRESSED, DOWNDISABLED, - LEFTNORMAL, LEFTHOT, LEFTPRESSED, LEFTDISABLED, - RIGHTNORMAL, RIGHTHOT, RIGHTPRESSED, RIGHTDISABLED, - UPHOVER, DOWNHOVER, LEFTHOVER, RIGHTHOVER - }); - - State[] spinnerStates = new State[] { NORMAL, ROLLOVER, PRESSED, DISABLED }; - stateMap.put(Part.SPNP_UP, spinnerStates); - stateMap.put(Part.SPNP_DOWN, spinnerStates); - - stateMap.put(Part.TVP_GLYPH, new State[] { CLOSED, OPENED }); - - State[] frameButtonStates = new State[] { - NORMAL, ROLLOVER, PUSHED, DISABLED, // See note 1 - INACTIVENORMAL, INACTIVEHOT, INACTIVEPUSHED, INACTIVEDISABLED, }; - // Note 1: The INACTIVE frame button states apply when the frame - // is inactive. They are not defined in tmschema.h - - // Fix for 6316538: Vista has five frame button states - /*if (ThemeReader.getInt(Control.WINDOW.toString(), - Part.WP_CLOSEBUTTON.getValue(), 1, - Prop.IMAGECOUNT.getValue()) == 10) { - frameButtonStates = new State[] { - NORMAL, HOT, PUSHED, DISABLED, null, - INACTIVENORMAL, INACTIVEHOT, INACTIVEPUSHED, INACTIVEDISABLED, null - }; - }*/ - stateMap.put(Part.WP_MINBUTTON, frameButtonStates); - stateMap.put(Part.WP_MAXBUTTON, frameButtonStates); - stateMap.put(Part.WP_RESTOREBUTTON, frameButtonStates); - stateMap.put(Part.WP_CLOSEBUTTON, frameButtonStates); - - // States for Slider (trackbar) - stateMap.put(Part.TKP_TRACK, new State[] { NORMAL }); - stateMap.put(Part.TKP_TRACKVERT, new State[] { NORMAL }); - - State[] sliderThumbStates - = new State[] { NORMAL, ROLLOVER, PRESSED, FOCUSED, DISABLED }; - stateMap.put(Part.TKP_THUMB, sliderThumbStates); - stateMap.put(Part.TKP_THUMBBOTTOM, sliderThumbStates); - stateMap.put(Part.TKP_THUMBTOP, sliderThumbStates); - stateMap.put(Part.TKP_THUMBVERT, sliderThumbStates); - stateMap.put(Part.TKP_THUMBRIGHT, sliderThumbStates); - - // States for Tabs - State[] tabStates = new State[] { NORMAL, ROLLOVER, SELECTED, DISABLED, FOCUSED }; - stateMap.put(Part.TABP_TABITEM, tabStates); - stateMap.put(Part.TABP_TABITEMLEFTEDGE, tabStates); - stateMap.put(Part.TABP_TABITEMRIGHTEDGE, tabStates); - - stateMap.put(Part.TP_BUTTON, - new State[] { - NORMAL, ROLLOVER, PRESSED, DISABLED, CHECKED, ROLLOVERCHECKED - }); - - State[] frameStates = new State[] { ACTIVE, INACTIVE }; - stateMap.put(Part.WP_WINDOW, frameStates); - stateMap.put(Part.WP_FRAMELEFT, frameStates); - stateMap.put(Part.WP_FRAMERIGHT, frameStates); - stateMap.put(Part.WP_FRAMEBOTTOM, frameStates); - - State[] captionStates = new State[] { ACTIVE, INACTIVE, DISABLED }; - stateMap.put(Part.WP_CAPTION, captionStates); - stateMap.put(Part.WP_MINCAPTION, captionStates); - stateMap.put(Part.WP_MAXCAPTION, captionStates); - - stateMap.put(Part.MP_BARBACKGROUND, - new State[] { ACTIVE, INACTIVE }); - stateMap.put(Part.MP_BARITEM, - new State[] { NORMAL, ROLLOVER, PUSHED, - DISABLED, DISABLEDHOT, DISABLEDPUSHED }); - stateMap.put(Part.MP_POPUPCHECK, - new State[] { CHECKMARKNORMAL, CHECKMARKDISABLED, - BULLETNORMAL, BULLETDISABLED }); - stateMap.put(Part.MP_POPUPCHECKBACKGROUND, - new State[] { DISABLEDPUSHED, NORMAL, BITMAP }); - stateMap.put(Part.MP_POPUPITEM, - new State[] { NORMAL, ROLLOVER, DISABLED, DISABLEDHOT }); - stateMap.put(Part.MP_POPUPSUBMENU, - new State[] { NORMAL, DISABLED }); - - } - - public static synchronized int getValue(Part part, State state) { - if (stateMap == null) - initStates(); - - Enum[] states = stateMap.get(part); - if (states != null) - for (int i = 0; i < states.length; i++) - if (state == states[i]) - return i + 1; - - if (state == null || state == State.NORMAL) - return 1; - - return 0; - } - - @Override - public String toString() { - return name().toLowerCase(); - } - - } - -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/UI.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/UI.java deleted file mode 100644 index 711350ec4..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/UI.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.jackhuang.hmcl.laf.utils; - -import java.awt.Color; -import javax.swing.BorderFactory; -import javax.swing.UIManager; -import javax.swing.border.Border; -import javax.swing.plaf.BorderUIResource; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.DimensionUIResource; -import javax.swing.plaf.InsetsUIResource; - -/** - * - * @author huang - */ -public class UI { - - protected static void put(String key, int i) { - UIManager.put(key, i); - } - - protected static void put(String key, boolean b) { - UIManager.put(key, b); - } - - protected static void put(String key, Color c) { - UIManager.put(key, new ColorUIResource(c)); - } - - protected static void put(String key, Border b) { - UIManager.put(key, new BorderUIResource(b)); - } - - protected static void putDim(String key, int w, int h) { - UIManager.put(key, new DimensionUIResource(h, h)); - } - - protected static void putInsets(String key, int top, int left, int bottom, int right) { - UIManager.put(key, new InsetsUIResource(top, left, bottom, right)); - } - - protected static void putBorder(String key) { - UIManager.put(key, BorderFactory.createEmptyBorder()); - } - - protected static void putBorder(String key, int top, int left, int bottom, int right) { - UIManager.put(key, new BorderUIResource(BorderFactory.createEmptyBorder(top, left, bottom, right))); - } - - protected static void putColor(String key, int r, int g, int b) { - put(key, new Color(r, g, b)); - } - - protected static void putColor(String key, int r, int g, int b, int a) { - put(key, new Color(r, g, b, a)); - } - - protected static void put(String key, Class c) { - UIManager.put(key, c.getName()); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/WinUtils.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/WinUtils.java deleted file mode 100644 index 7519b3f8f..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/WinUtils.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * WinUtils.java at 2015-2-1 20:25:37, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.utils; - -import java.awt.Color; -import java.awt.Component; -import java.awt.FontMetrics; -import java.awt.Graphics; -import java.awt.Rectangle; - -import javax.swing.AbstractButton; -import javax.swing.ButtonModel; -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import javax.swing.UIManager; - -/** - * The Class WinUtils. - * - * @see com.sun.java.swing.plaf.windows.WindowsGraphicsUtils - */ -public class WinUtils { - //* copy from WindowsLookAndFeel START 未做修改 - // Toggle flag for drawing the mnemonic state - - /** - * The is mnemonic hidden. - */ - private static boolean isMnemonicHidden = true; - - /** - * Gets the state of the hide mnemonic flag. This only has meaning if this - * feature is supported by the underlying OS. - * - * @return true if mnemonics are hidden, otherwise, false - * @see #setMnemonicHidden - * @since 1.4 - */ - public static boolean isMnemonicHidden() { - if (UIManager.getBoolean("Button.showMnemonics") == true) - // Do not hide mnemonics if the UI defaults do not support this - isMnemonicHidden = false; - return isMnemonicHidden; - } - //* copy from WindowsLookAndFeel END - - //* copy from WindowsGraphicsUtils START (modified by jack jiang) - /** - * Renders a text String in Windows without the mnemonic. This is here - * because the WindowsUI hiearchy doesn't match the Component heirarchy. All - * the overriden paintText methods of the ButtonUI delegates will call this - * static method. - *

    - * - * @param g Graphics context - * @param b Current button to render - * @param textRect Bounding rectangle to render the text. - * @param text String to render - * @param textShiftOffset the text shift offset - */ - public static void paintText(Graphics g, AbstractButton b, - Rectangle textRect, String text, - int textShiftOffset) { - FontMetrics fm = MySwingUtilities2.getFontMetrics(b, g); - - int mnemIndex = b.getDisplayedMnemonicIndex(); - // W2K Feature: Check to see if the Underscore should be rendered. - if (isMnemonicHidden() == true) - mnemIndex = -1; - paintClassicText(b, g, textRect.x + textShiftOffset, - textRect.y + fm.getAscent() + textShiftOffset, - text, mnemIndex); - } - - /** - * Paint classic text. - * - * @param b the b - * @param g the g - * @param x the x - * @param y the y - * @param text the text - * @param mnemIndex the mnem index - */ - static void paintClassicText(AbstractButton b, Graphics g, int x, int y, - String text, int mnemIndex) { - ButtonModel model = b.getModel(); - - /* Draw the Text */ - Color color = b.getForeground(); - if (model.isEnabled()) { - /** - * * paint the text normally - */ - if (!(b instanceof JMenuItem && model.isArmed()) - && !(b instanceof JMenu && (model.isSelected() || model.isRollover()))) - /* We shall not set foreground color for selected menu or - * armed menuitem. Foreground must be set in appropriate - * Windows* class because these colors passes from - * BasicMenuItemUI as protected fields and we can't - * reach them from this class */ - g.setColor(b.getForeground()); - MySwingUtilities2.drawStringUnderlineCharAt(b, g, text, mnemIndex, x, y); - } else { - /** - * * paint the text disabled ** - */ - color = UIManager.getColor("Button.shadow"); - Color shadow = UIManager.getColor("Button.disabledShadow"); - if (model.isArmed()) - color = UIManager.getColor("Button.disabledForeground"); - else { - if (shadow == null) - shadow = b.getBackground().darker(); - g.setColor(shadow); - MySwingUtilities2.drawStringUnderlineCharAt(b, g, text, mnemIndex, x + 1, y + 1); - } - if (color == null) - color = b.getBackground().brighter(); - g.setColor(color); - MySwingUtilities2.drawStringUnderlineCharAt(b, g, text, mnemIndex, x, y); - - } - } - //* copy from WindowsGraphicsUtils END (modified by jack jiang) - - //* copy from WindowsGraphicsUtils START - /** - * 是否组件的排列方向是从左到右. - * - * @param c the c - * @return true, if is left to right - */ - public static boolean isLeftToRight(Component c) { - return c.getComponentOrientation().isLeftToRight(); - } - //* copy from WindowsGraphicsUtils END -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/WindowTranslucencyHelper.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/WindowTranslucencyHelper.java deleted file mode 100644 index 311aa663b..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/WindowTranslucencyHelper.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * WindowTranslucencyHelper.java at 2015-2-1 20:25:40, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.utils; - -import java.awt.Color; -import java.awt.GraphicsDevice; -import java.awt.GraphicsEnvironment; -import java.awt.Window; - -/** - * 关于java支持窗口透明的详细信息请见:http://docs.oracle.com/javase/tutorial/uiswing/misc/trans_shaped_windows.html#uniform - */ -public class WindowTranslucencyHelper { - - /** - * Checks if is translucency supported. - * - * @return true, if is translucency supported - */ - public static boolean isTranslucencySupported() { - GraphicsDevice device = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); - return device.isWindowTranslucencySupported(GraphicsDevice.WindowTranslucency.TRANSLUCENT) && - device.isWindowTranslucencySupported(GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSLUCENT); - } - - /** - * Sets the window opaque. - * - * @param w the w - * @param opaque the opaque - */ - public static void setWindowOpaque(Window w, boolean opaque) { - Color bgc = w.getBackground(); - /* - * 在群友机器上(win7+java1.7.0.1)的生产系统下 - * 下使用BeautyEye有时w.getBackground()返回值是null,但为什么返回是null,Jack 没 - * 有测出来(Jack测试都是正常的),暂且认为是其系统代码有问题吧,在此容错一下 - */ - if (bgc == null) - bgc = Color.black;//暂不知道用此黑色作为容错值合不合适 - Color newBgn = new Color(bgc.getRed(), bgc.getGreen(), bgc.getBlue(), opaque ? 255 : 0); - w.setBackground(newBgn); - } - -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/ImageBgPanel.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/ImageBgPanel.java deleted file mode 100644 index d8cc53c45..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/ImageBgPanel.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * ImageBgPanel.java at 2015-2-1 20:25:38, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.widget; - -import java.awt.Component; -import java.awt.Graphics; -import java.awt.Graphics2D; - -import javax.swing.JComponent; -import javax.swing.JPanel; - -import org.jb2011.ninepatch4j.NinePatch; - -/** - * 一个使用NinePatch图作为背景的面板实现类. - * - * @author Jack Jiang(jb2011@163.com) - */ -public class ImageBgPanel extends JPanel { - - private boolean drawBg = true; - - private NinePatch n9 = null; - - public ImageBgPanel() { - this.setOpaque(false); - } - - @Override - public void paintChildren(Graphics g) { - if (drawBg && n9 != null) - n9.draw((Graphics2D) g, 0, 0, this.getWidth(), this.getHeight()); - super.paintChildren(g); - } - - /** - * 重写父类方法,以实现添加到它的所有子组件的透明性是按字段childOpaque指明的方式呈现. - * - * @param comp the comp - * @param constraints the constraints - * @param index the index - */ - @Override - protected void addImpl(Component comp, Object constraints, int index) { - if (comp != null && comp instanceof JComponent) - ((JComponent) comp).setOpaque(false); - super.addImpl(comp, constraints, index); - } - - /** - * Checks if is draw bg. - * - * @return true, if is draw bg - */ - public boolean isDrawBg() { - return drawBg; - } - - /** - * Sets the draw bg. - * - * @param drawBg the draw bg - * @return the image bg panel - */ - public ImageBgPanel setDrawBg(boolean drawBg) { - this.drawBg = drawBg; - return this; - } - - /** - * Gets the n9. - * - * @return the n9 - */ - public NinePatch getN9() { - return n9; - } - - /** - * Sets the n9. - * - * @param n9 the n9 - * @return the image bg panel - */ - public ImageBgPanel setN9(NinePatch n9) { - this.n9 = n9; - return this; - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/N9ComponentFactory.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/N9ComponentFactory.java deleted file mode 100644 index 806462c0a..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/N9ComponentFactory.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * N9ComponentFactory.java at 2015-2-1 20:25:36, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.widget; - -import java.awt.Color; -import java.awt.Font; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Insets; - -import javax.swing.BorderFactory; -import javax.swing.JLabel; -import org.jackhuang.hmcl.laf.utils.Icon9Factory; - -import org.jb2011.ninepatch4j.NinePatch; - -/** - * 使用NinePatch作为背景的一些可重用组件工厂类. - *

    - * 目前这些组件主要用于SwingSets2的演示代码,以便改造官方的SwingSets2使 得它们的美感与BeautyEye形成较好的搭配。 - * - * @author Jack Jiang(jb2011@163.com) - */ -public class N9ComponentFactory extends JLabel { - - public static final Icon9Factory ICON_9 = new Icon9Factory("widget"); - - /** - * Creates a new N9Component object. - * - * @param text the text - * @param n9 the n9 - * @param is the is - * @param foregroundColor the foreground color - * @param f the f - * @return the j label - */ - public static JLabel createLabel_root(String text, - final NinePatch n9, Insets is, - Color foregroundColor, Font f) { - JLabel l = new JLabel(text) { - @Override - public void paintComponent(Graphics g) { - n9.draw((Graphics2D) g, 0, 0, this.getWidth(), this.getHeight()); - super.paintComponent(g); - } - }; - if (is != null) - l.setBorder(BorderFactory.createEmptyBorder(is.top, is.left, is.bottom, is.right)); - if (foregroundColor != null) - l.setForeground(foregroundColor); - if (f != null) - l.setFont(f); - - return l; - } - - /** - * Creates a new N9Component object. - * - * @param txt the txt - * @return the j label - */ - public static JLabel createLabel_style1(String txt) { - return createLabel_root(txt, ICON_9.get("hint_light_blue"), - new Insets(1, 6, 1, 6), Color.white, new Font("宋体", Font.BOLD, 12)); - } - - /** - * Creates a new N9Component object. - * - * @param txt the txt - * @return the j label - */ - public static JLabel createLabel_style2(String txt) { - return createLabel_root(txt, ICON_9.get("tips"), - new Insets(15, 3, 28, 3), new Color(139, 119, 75), - null); - } - - /** - * Creates a new N9Component object. - * - * @param txt the txt - * @return the j label - */ - public static JLabel createLabel_style3(String txt) { - return createLabel_root(txt, ICON_9.get("orange_balloon"), - new Insets(4, 9, 9, 9)//3, 9, 8, 9) - , - new Color(255, 255, 255), - null); - } - - /** - * Creates a new N9Component object. - * - * @param txt the txt - * @return the j label - */ - public static JLabel createLabel_style4(String txt) { - return createLabel_root(txt, ICON_9.get("hint_light_gray"), - new Insets(2, 8, 2, 8), Color.white, new Font("宋体", Font.PLAIN, 12)); - } - - /** - * Creates a new N9Component object. - * - * @return the image bg panel - */ - public static ImageBgPanel createPanel_style1() { - return createPanel_style1(new Insets(8, 0, 26, 10)); - } - - /** - * Creates a new N9Component object. - * - * @param is the is - * @return the image bg panel - */ - public static ImageBgPanel createPanel_style1(Insets is) { - ImageBgPanel p = new ImageBgPanel().setN9(ICON_9.get("panel")); - if (is != null) - p.setBorder(BorderFactory.createEmptyBorder(is.top, is.left, is.bottom, is.right)); - return p; - } - -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/border/BEDashedBorder.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/border/BEDashedBorder.java deleted file mode 100644 index df6bbc8a3..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/border/BEDashedBorder.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BEDashedBorder.java at 2015-2-1 20:25:41, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.widget.border; - -import java.awt.Color; -import java.awt.Component; -import java.awt.Graphics; - -import javax.swing.border.LineBorder; -import javax.swing.plaf.UIResource; - -import org.jackhuang.hmcl.laf.BEUtils; - -/** - * 虚线边框Border. - * - * @author Jack Jiang(jb2011@163.com) - */ -public class BEDashedBorder extends LineBorder implements UIResource { - - /** - * 虚线段绘制步进. - */ - private int step = 3; - - private boolean top = true, left = true, bottom = true, right = true; - - public BEDashedBorder(Color color, boolean top, boolean left, boolean bottom, boolean right) { - super(color); - this.top = top; - this.left = left; - this.bottom = bottom; - this.right = right; - } - - /** - * 构造方法. - * - * @param color 虚线颜色 - * @param thickness 线框宽度 - * @param step 步进 - * @param top the top - * @param left the left - * @param bottom the bottom - * @param right the right - */ - public BEDashedBorder(Color color, int thickness, int step, - boolean top, boolean left, boolean bottom, boolean right) { - super(color, thickness); - this.step = step; - this.top = top; - this.left = left; - this.bottom = bottom; - this.right = right; - } - - @Override - public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { - Color oldColor = g.getColor(); - int i; - - g.setColor(lineColor); - for (i = 0; i < thickness; i++) - BEUtils.drawDashedRect(g, x + i, y + i, width - i - i, height - i - i, step, top, left, bottom, right); - g.setColor(oldColor); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/border/BEDashedRoundRecBorder.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/border/BEDashedRoundRecBorder.java deleted file mode 100644 index 10f09c07c..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/border/BEDashedRoundRecBorder.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BEDashedRoundRecBorder.java at 2015-2-1 20:25:39, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.widget.border; - -import java.awt.Color; -import java.awt.Component; -import java.awt.Graphics; - -import javax.swing.border.LineBorder; -import javax.swing.plaf.UIResource; - -import org.jackhuang.hmcl.laf.BEUtils; - -/** - * 虚线圆角边框Border. - *

    - * TODO 目前圆角大小和虚线间隔等目前都是固定的,进一步重构后可以进行重用哦. - * - * @author Jack Jiang(jb2011@163.com) - */ -public class BEDashedRoundRecBorder extends LineBorder implements UIResource { - - /** - * The separator space. - */ - private int arcWidth = 6, arcHeight = 6, separatorSolid = 2, separatorSpace = 2; - - /** - * 构造方法. - * - * @param color 虚线颜色 - */ - public BEDashedRoundRecBorder(Color color) { - super(color); - } - - @Override - public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { - Color oldColor = g.getColor(); - g.setColor(lineColor); - BEUtils.drawDashedRect(g, x, y, width, height, arcWidth, arcHeight, separatorSolid, separatorSpace); - g.setColor(oldColor); - } - - /** - * Gets the arc width. - * - * @return the arc width - */ - public int getArcWidth() { - return arcWidth; - } - - /** - * Sets the arc width. - * - * @param arcWidth the arc width - * @return the bE dashed round rec border - */ - public BEDashedRoundRecBorder setArcWidth(int arcWidth) { - this.arcWidth = arcWidth; - return this; - } - - /** - * Gets the arc height. - * - * @return the arc height - */ - public int getArcHeight() { - return arcHeight; - } - - /** - * Sets the arc height. - * - * @param arcHeight the arc height - * @return the bE dashed round rec border - */ - public BEDashedRoundRecBorder setArcHeight(int arcHeight) { - this.arcHeight = arcHeight; - return this; - } - - /** - * Gets the separator solid. - * - * @return the separator solid - */ - public int getSeparatorSolid() { - return separatorSolid; - } - - /** - * Sets the separator solid. - * - * @param separatorSolid the separator solid - * @return the bE dashed round rec border - */ - public BEDashedRoundRecBorder setSeparatorSolid(int separatorSolid) { - this.separatorSolid = separatorSolid; - return this; - } - - /** - * Gets the separator space. - * - * @return the separator space - */ - public int getSeparatorSpace() { - return separatorSpace; - } - - /** - * Sets the separator space. - * - * @param separatorSpace the separator space - * @return the bE dashed round rec border - */ - public BEDashedRoundRecBorder setSeparatorSpace(int separatorSpace) { - this.separatorSpace = separatorSpace; - return this; - } - -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/border/BERoundBorder.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/border/BERoundBorder.java deleted file mode 100644 index a19f772b2..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/border/BERoundBorder.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BERoundBorder.java at 2015-2-1 20:25:39, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.widget.border; - -import java.awt.Color; -import java.awt.Component; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Insets; - -import javax.swing.AbstractButton; -import javax.swing.JToolBar; -import javax.swing.border.LineBorder; -import javax.swing.plaf.UIResource; -import javax.swing.text.JTextComponent; - -import org.jackhuang.hmcl.laf.BEUtils; - -/** - * 圆角实线边框Border. - * - * @author Jack Jiang(jb2011@163.com) - */ -public class BERoundBorder extends LineBorder implements UIResource { - - /** - * 默认绘制的色调. - */ - public final static Color defaultLineColor = new Color(188, 188, 188);//154,154,155);// new Color(171,168,163); - - /** - * 圆角的半径. - */ - protected int arcWidth = 0;//6 - - /** - * Instantiates a new bE round border. - */ - public BERoundBorder() { - this(defaultLineColor, 1); - } - - /** - * Instantiates a new bE round border. - * - * @param color the color - */ - public BERoundBorder(Color color) { - this(color, 1); - } - - /** - * Instantiates a new bE round border. - * - * @param thickness the thickness - */ - public BERoundBorder(int thickness) { - this(defaultLineColor, thickness); - } - - /** - * Instantiates a new bE round border. - * - * @param color the color - * @param thickness the thickness - */ - public BERoundBorder(Color color, int thickness) { - super(color, thickness); - } - - @Override - public Insets getBorderInsets(Component c) { - return getBorderInsets(c, new Insets(0, 0, 0, 0)); - } - - @Override - public Insets getBorderInsets(Component c, Insets insets) { - Insets margin = null; - - if (c instanceof AbstractButton) - margin = ((AbstractButton) c).getMargin(); - else if (c instanceof JToolBar) - margin = ((JToolBar) c).getMargin(); - else if (c instanceof JTextComponent) - margin = ((JTextComponent) c).getMargin(); - insets.top = (margin != null ? margin.top : 0) + thickness; - insets.left = (margin != null ? margin.left : 0) + thickness; - insets.bottom = (margin != null ? margin.bottom : 0) + thickness; - insets.right = (margin != null ? margin.right : 0) + thickness; - - return insets; - } - - @Override - public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { - Color oldColor = g.getColor(); - - BEUtils.setAntiAliasing((Graphics2D) g, true); -// ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, -// RenderingHints.VALUE_ANTIALIAS_ON); - Component cp = c.getParent(); - if (cp != null) { - //** 因java的textField边框默认是直角的,为了在LNF级别使加上圆连框后自然些,就得给这原始的直角先做隐藏处理(不要看见它) - // Color parentBackground=c.getParent().getBackground(); - // g.setColor(parentBackground); - // g.drawRect(x, y, width-1, height-1); - } - - //据thickness画出边框(当前是圆角的) - g.setColor(lineColor); - int i; - for (i = 0; i < thickness; i++) { - g.drawRoundRect(x + i, y + i, width - i - i - 1, height - i - i - 1, this.arcWidth, this.arcWidth); - if (thickness > 1) - g.setColor(BEUtils.getColor(g.getColor(), 70, 70, 70, -50)); - } - - g.setColor(oldColor); -// ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, -// RenderingHints.VALUE_ANTIALIAS_OFF); - BEUtils.setAntiAliasing((Graphics2D) g, false); - } - - /** - * Sets the line color. - * - * @param c the c - * @return the bE round border - */ - public BERoundBorder setLineColor(Color c) { - lineColor = c; - return this; - } - - @Override - public Color getLineColor() { - return lineColor; - } - - /** - * Sets the thickness. - * - * @param t the t - * @return the bE round border - */ - public BERoundBorder setThickness(int t) { - thickness = t; - return this; - } - - @Override - public Object clone() { - BERoundBorder bb = new BERoundBorder(this.getLineColor(), this.getThickness()); - return bb; - } - - /** - * Gets the arc width. - * - * @return the arc width - */ - public int getArcWidth() { - return arcWidth; - } - - /** - * Sets the arc width. - * - * @param arcWidth the arc width - * @return the bE round border - */ - public BERoundBorder setArcWidth(int arcWidth) { - this.arcWidth = arcWidth; - return this; - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/border/BEShadowBorder.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/border/BEShadowBorder.java deleted file mode 100644 index ad47367e4..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/border/BEShadowBorder.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BEShadowBorder.java at 2015-2-1 20:25:39, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.widget.border; - -import java.awt.Insets; -import org.jackhuang.hmcl.laf.widget.N9ComponentFactory; - -/** - * 一个用9格图实现的边框阴影效果,目前用于内部窗口的边框(阴影效果是半透明的). - * - * @author Jack Jiang(jb2011@163.com) - * @see - * org.jb2011.lnf.beautyeye.BeautyEyeLNFHelper.FrameBorderStyle#translucencySmallShadow - */ -public class BEShadowBorder extends NinePatchBorder { - - private final static int TOP = 5, LEFT = 5, RIGHT = 5, BOTTOM = 6; - - public BEShadowBorder() { - super(new Insets(TOP, LEFT, BOTTOM, RIGHT), - N9ComponentFactory.ICON_9.get("border_shadow1")); - } - - //* 2012-09-19 在BeautyEye v3.2中的BERootPaneUI,Jack Jiang启用了相比 - //* 原MetalRootPaneUI中更精确更好的边框拖放算法,以下方法暂时弃用,以后可以删除了! -// //当用本border作边框时,窗口可拖动敏感触点区大小值 -// public static int BORDER_DRAG_THICKNESS() -// { -// return Math.min(Math.min(Math.min(TOP, LEFT),RIGHT),BOTTOM); -// } -// -// //当用本border作边框时,窗口边角可拖动敏感触点区大小值 -// public static int CORNER_DRAG_WIDTH() -// { -// return Math.max(Math.max(Math.max(TOP, LEFT),RIGHT),BOTTOM); -// } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/border/BEShadowBorder3.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/border/BEShadowBorder3.java deleted file mode 100644 index 7b5e98a76..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/border/BEShadowBorder3.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * BEShadowBorder3.java at 2015-2-1 20:25:39, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.widget.border; - -import java.awt.Insets; -import org.jackhuang.hmcl.laf.widget.N9ComponentFactory; - -/** - * 一个用9格图实现的边框阴影效果,目前主要用于窗口的边框(阴影效果是半透明的). - * - * @author Jack Jiang(jb201@163.com) - * @see - * org.jb2011.lnf.beautyeye.BeautyEyeLNFHelper.FrameBorderStyle#translucencyAppleLike - */ -public class BEShadowBorder3 extends NinePatchBorder { - - private final static int TOP = 17, LEFT = 27, RIGHT = 27, BOTTOM = 37; - - public BEShadowBorder3() { - super(new Insets(TOP, LEFT, BOTTOM, RIGHT), - N9ComponentFactory.ICON_9.get("border_shadow3")); - } - - //* 2012-09-19 在BeautyEye v3.2中的BERootPaneUI,Jack Jiang启用了相比 - //* 原MetalRootPaneUI中更精确更好的边框拖放算法,以下方法暂时弃用,以后可以删除了! -// //当用本border作边框时,窗口可拖动敏感触点区大小值 -// public static int BORDER_DRAG_THICKNESS() -// { -// return Math.min(Math.min(Math.min(TOP, LEFT),RIGHT),BOTTOM); -// } -// //当用本border作边框时,窗口边角可拖动敏感触点区大小值 -// public static int CORNER_DRAG_WIDTH() -// { -// return Math.max(Math.max(Math.max(TOP, LEFT),RIGHT),BOTTOM); -// } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/border/NinePatchBorder.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/border/NinePatchBorder.java deleted file mode 100644 index 548d94621..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/border/NinePatchBorder.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * NinePatchBorder.java at 2015-2-1 20:25:36, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.widget.border; - -import java.awt.Component; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Insets; - -import javax.swing.border.AbstractBorder; - -import org.jb2011.ninepatch4j.NinePatch; - -/** - * 一个利用NinePatch图实现边框的border实现类. - *

    - * 本类可以很好地被重用于NinePatch图作为border实现的场景哦. - * - * @author Jack Jiang(jb2011@163.com), 2012-09-04 - * @version 1.0 - */ -public class NinePatchBorder extends AbstractBorder { - - /** - * The insets. - */ - private Insets insets = null; - - /** - * The np. - */ - private NinePatch np = null; - - /** - * Instantiates a new nine patch border. - * - * @param insets the insets - * @param np the np - */ - public NinePatchBorder(Insets insets, NinePatch np) { - this.insets = insets; - this.np = np; - } - - @Override - public Insets getBorderInsets(Component c) { - return insets; - } - - @Override - public Insets getBorderInsets(Component c, Insets insets) { - return insets; - } - - @Override - public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { - this.np.draw((Graphics2D) g, x, y, width, height); - } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/border/PlainGrayBorder.java b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/border/PlainGrayBorder.java deleted file mode 100644 index ff5d14098..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/border/PlainGrayBorder.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2015 Jack Jiang(cngeeker.com) The BeautyEye Project. - * All rights reserved. - * Project URL:https://github.com/JackJiang2011/beautyeye - * Version 3.6 - * - * Jack Jiang PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. - * - * PlainGrayBorder.java at 2015-2-1 20:25:38, original version by Jack Jiang. - * You can contact author with jb2011@163.com. - */ -package org.jackhuang.hmcl.laf.widget.border; - -import java.awt.Insets; -import org.jackhuang.hmcl.laf.widget.N9ComponentFactory; - -/** - * 一个NinePatch图实现的不透明边框border. - *

    - * 目前主要用于jdk1.5及以下版本的窗口边框(因为该版本下java不支持窗口透明). - * - * @author Jack Jiang(jb2011@163.com), 2012-09-04 - * @version 1.0 - * @see - * org.jb2011.lnf.beautyeye.BeautyEyeLNFHelper.FrameBorderStyle#generalNoTranslucencyShadow - */ -public class PlainGrayBorder extends NinePatchBorder { - - private final static int IS = 5; - - public PlainGrayBorder() { - super(new Insets(IS, IS, IS, IS), - N9ComponentFactory.ICON_9.get("border_plain_gray")); - } - - //* 2012-09-19 在BeautyEye v3.2中的BERootPaneUI,Jack Jiang启用了相比 - //* 原MetalRootPaneUI中更精确更好的边框拖放算法,以下方法暂时弃用,以后可以删除了! -// //当用本border作边框时,窗口可拖动敏感触点区大小值 -// public static int BORDER_DRAG_THICKNESS() -// { -// return IS; -// } -// //当用本border作边框时,窗口边角可拖动敏感触点区大小值 -// public static int CORNER_DRAG_WIDTH() -// { -// return 16;//使用MetalLookAndFeel的默认值比较合适哦 -// } -} diff --git a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/border/package.html b/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/border/package.html deleted file mode 100644 index 1664d615f..000000000 --- a/HMCLaF/src/main/java/org/jackhuang/hmcl/laf/widget/border/package.html +++ /dev/null @@ -1,7 +0,0 @@ - - - - - 本包内包含了各种自定义border实现类。 - - \ No newline at end of file diff --git a/HMCLaF/src/main/java/org/jb2011/ninepatch4j/GraphicsUtilities.java b/HMCLaF/src/main/java/org/jb2011/ninepatch4j/GraphicsUtilities.java deleted file mode 100644 index 80fca2b27..000000000 --- a/HMCLaF/src/main/java/org/jb2011/ninepatch4j/GraphicsUtilities.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Decompiled with CFR 0_118. - */ -package org.jb2011.ninepatch4j; - -import java.awt.Graphics; -import java.awt.GraphicsConfiguration; -import java.awt.GraphicsEnvironment; -import java.awt.image.BufferedImage; -import java.awt.image.WritableRaster; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import javax.imageio.ImageIO; - -public class GraphicsUtilities { - - public static BufferedImage loadCompatibleImage(URL resource) throws IOException { - return GraphicsUtilities.toCompatibleImage(ImageIO.read(resource)); - } - - public static BufferedImage loadCompatibleImage(InputStream stream) throws IOException { - return GraphicsUtilities.toCompatibleImage(ImageIO.read(stream)); - } - - public static BufferedImage createCompatibleImage(int width, int height) { - return GraphicsUtilities.getGraphicsConfiguration().createCompatibleImage(width, height); - } - - public static BufferedImage toCompatibleImage(BufferedImage image) { - if (GraphicsUtilities.isHeadless()) - return image; - if (image.getColorModel().equals(GraphicsUtilities.getGraphicsConfiguration().getColorModel())) - return image; - BufferedImage compatibleImage = GraphicsUtilities.getGraphicsConfiguration().createCompatibleImage(image.getWidth(), image.getHeight(), image.getTransparency()); - Graphics g = compatibleImage.getGraphics(); - g.drawImage(image, 0, 0, null); - g.dispose(); - return compatibleImage; - } - - public static BufferedImage createCompatibleImage(BufferedImage image, int width, int height) { - return GraphicsUtilities.getGraphicsConfiguration().createCompatibleImage(width, height, image.getTransparency()); - } - - private static GraphicsConfiguration getGraphicsConfiguration() { - GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment(); - return environment.getDefaultScreenDevice().getDefaultConfiguration(); - } - - private static boolean isHeadless() { - return GraphicsEnvironment.isHeadless(); - } - - public static BufferedImage createTranslucentCompatibleImage(int width, int height) { - return GraphicsUtilities.getGraphicsConfiguration().createCompatibleImage(width, height, 3); - } - - public static int[] getPixels(BufferedImage img, int x, int y, int w, int h, int[] pixels) { - if (w == 0 || h == 0) - return new int[0]; - if (pixels == null) - pixels = new int[w * h]; - else if (pixels.length < w * h) - throw new IllegalArgumentException("Pixels array must have a length >= w * h"); - int imageType = img.getType(); - if (imageType == 2 || imageType == 1) { - WritableRaster raster = img.getRaster(); - return (int[]) raster.getDataElements(x, y, w, h, pixels); - } - return img.getRGB(x, y, w, h, pixels, 0, w); - } -} diff --git a/HMCLaF/src/main/java/org/jb2011/ninepatch4j/NinePatch.java b/HMCLaF/src/main/java/org/jb2011/ninepatch4j/NinePatch.java deleted file mode 100644 index b2c6c6e16..000000000 --- a/HMCLaF/src/main/java/org/jb2011/ninepatch4j/NinePatch.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Decompiled with CFR 0_118. - */ -package org.jb2011.ninepatch4j; - -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.image.BufferedImage; -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; - -public class NinePatch { - - public static final String EXTENSION_9PATCH = ".9.png"; - private final BufferedImage mImage; - private final NinePatchChunk mChunk; - - public BufferedImage getImage() { - return this.mImage; - } - - public NinePatchChunk getChunk() { - return this.mChunk; - } - - public static NinePatch load(URL fileUrl, boolean convert) throws IOException { - try { - boolean is9Patch = fileUrl.getPath().toLowerCase().endsWith(".9.png"); - return NinePatch.load(GraphicsUtilities.loadCompatibleImage(fileUrl), is9Patch, convert); - } catch (MalformedURLException e) { - return null; - } - } - - public static NinePatch load(InputStream stream, boolean is9Patch, boolean convert) throws IOException { - try { - return NinePatch.load(GraphicsUtilities.loadCompatibleImage(stream), is9Patch, convert); - } catch (MalformedURLException e) { - return null; - } - } - - /* - * Enabled force condition propagation - * Lifted jumps to return sites - */ - public static NinePatch load(BufferedImage image, boolean is9Patch, boolean convert) { - if (!is9Patch) { - if (!convert) - return null; - image = NinePatch.convertTo9Patch(image); - return new NinePatch(image); - } else - NinePatch.ensure9Patch(image); - return new NinePatch(image); - } - - public int getWidth() { - return this.mImage.getWidth(); - } - - public int getHeight() { - return this.mImage.getHeight(); - } - - public boolean getPadding(int[] padding) { - this.mChunk.getPadding(padding); - return true; - } - - public void draw(Graphics2D graphics2D, int x, int y, int scaledWidth, int scaledHeight) { - this.mChunk.draw(this.mImage, graphics2D, x, y, scaledWidth, scaledHeight, 0, 0); - } - - private NinePatch(BufferedImage image) { - this.mChunk = NinePatchChunk.create(image); - this.mImage = this.extractBitmapContent(image); - } - - private static void ensure9Patch(BufferedImage image) { - int pixel; - int width = image.getWidth(); - int height = image.getHeight(); - int i = 0; - while (i < width) { - pixel = image.getRGB(i, 0); - if (pixel != 0 && pixel != -16777216) - image.setRGB(i, 0, 0); - if ((pixel = image.getRGB(i, height - 1)) != 0 && pixel != -16777216) - image.setRGB(i, height - 1, 0); - ++i; - } - i = 0; - while (i < height) { - pixel = image.getRGB(0, i); - if (pixel != 0 && pixel != -16777216) - image.setRGB(0, i, 0); - if ((pixel = image.getRGB(width - 1, i)) != 0 && pixel != -16777216) - image.setRGB(width - 1, i, 0); - ++i; - } - } - - private static BufferedImage convertTo9Patch(BufferedImage image) { - BufferedImage buffer = GraphicsUtilities.createTranslucentCompatibleImage(image.getWidth() + 2, image.getHeight() + 2); - Graphics2D g2 = buffer.createGraphics(); - g2.drawImage(image, 1, 1, null); - g2.setColor(Color.black); - g2.fillRect(0, 1, 1, 1); - g2.fillRect(1, 0, 1, 1); - g2.fillRect(1, image.getHeight() + 1, 1, 1); - g2.fillRect(image.getWidth() + 1, 1, 1, 1); - g2.dispose(); - return buffer; - } - - private BufferedImage extractBitmapContent(BufferedImage image) { - return image.getSubimage(1, 1, image.getWidth() - 2, image.getHeight() - 2); - } -} diff --git a/HMCLaF/src/main/java/org/jb2011/ninepatch4j/NinePatchChunk.java b/HMCLaF/src/main/java/org/jb2011/ninepatch4j/NinePatchChunk.java deleted file mode 100644 index 505f0e3dd..000000000 --- a/HMCLaF/src/main/java/org/jb2011/ninepatch4j/NinePatchChunk.java +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Decompiled with CFR 0_118. - */ -package org.jb2011.ninepatch4j; - -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.RenderingHints; -import java.awt.image.BufferedImage; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - -/* - * This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6. - */ -public class NinePatchChunk implements Serializable { - - private static final long serialVersionUID = -7353439224505296217L; - private static final int[] sPaddingRect = new int[4]; - private boolean mVerticalStartWithPatch; - private boolean mHorizontalStartWithPatch; - private List mFixed; - private List mPatches; - private List mHorizontalPatches; - private List mVerticalPatches; - private Pair mHorizontalPadding; - private Pair mVerticalPadding; - - public static NinePatchChunk create(BufferedImage image) { - NinePatchChunk chunk = new NinePatchChunk(); - chunk.findPatches(image); - return chunk; - } - - public void draw(BufferedImage image, Graphics2D graphics2D, int x, int y, int scaledWidth, int scaledHeight, int destDensity, int srcDensity) { - boolean scaling; - boolean bl = scaling = destDensity != srcDensity && destDensity != 0 && srcDensity != 0; - if (scaling) - try { - graphics2D = (Graphics2D) graphics2D.create(); - float densityScale = (float) destDensity / (float) srcDensity; - graphics2D.translate(x, y); - graphics2D.scale(densityScale, densityScale); - scaledWidth = (int) ((float) scaledWidth / densityScale); - scaledHeight = (int) ((float) scaledHeight / densityScale); - y = 0; - x = 0; - this.draw(image, graphics2D, x, y, scaledWidth, scaledHeight); - } finally { - graphics2D.dispose(); - } - else - this.draw(image, graphics2D, x, y, scaledWidth, scaledHeight); - } - - private void draw(BufferedImage image, Graphics2D graphics2D, int x, int y, int scaledWidth, int scaledHeight) { - if (scaledWidth <= 1 || scaledHeight <= 1) - return; - Graphics2D g = (Graphics2D) graphics2D.create(); - g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); - try { - if (this.mPatches.isEmpty()) { - g.drawImage(image, x, y, scaledWidth, scaledHeight, null); - return; - } - g.translate(x, y); - y = 0; - x = 0; - DrawingData data = this.computePatches(scaledWidth, scaledHeight); - int fixedIndex = 0; - int horizontalIndex = 0; - int verticalIndex = 0; - int patchIndex = 0; - float vWeightSum = 1.0f; - float vRemainder = data.mRemainderVertical; - boolean vStretch = this.mVerticalStartWithPatch; - while (y < scaledHeight - 1) { - boolean hStretch = this.mHorizontalStartWithPatch; - int height = 0; - float vExtra = 0.0f; - float hWeightSum = 1.0f; - float hRemainder = data.mRemainderHorizontal; - while (x < scaledWidth - 1) { - float extra; - int width; - Rectangle r; - if (!vStretch) { - if (hStretch) { - r = this.mHorizontalPatches.get(horizontalIndex++); - extra = (float) r.width / data.mHorizontalPatchesSum; - width = (int) (extra * hRemainder / hWeightSum); - hWeightSum -= extra; - hRemainder -= (float) width; - g.drawImage(image, x, y, x + width, y + r.height, r.x, r.y, r.x + r.width, r.y + r.height, null); - x += width; - } else { - r = this.mFixed.get(fixedIndex++); - g.drawImage(image, x, y, x + r.width, y + r.height, r.x, r.y, r.x + r.width, r.y + r.height, null); - x += r.width; - } - height = r.height; - } else if (hStretch) { - r = this.mPatches.get(patchIndex++); - vExtra = (float) r.height / data.mVerticalPatchesSum; - height = (int) (vExtra * vRemainder / vWeightSum); - extra = (float) r.width / data.mHorizontalPatchesSum; - width = (int) (extra * hRemainder / hWeightSum); - hWeightSum -= extra; - hRemainder -= (float) width; - g.drawImage(image, x, y, x + width, y + height, r.x, r.y, r.x + r.width, r.y + r.height, null); - x += width; - } else { - r = this.mVerticalPatches.get(verticalIndex++); - vExtra = (float) r.height / data.mVerticalPatchesSum; - height = (int) (vExtra * vRemainder / vWeightSum); - g.drawImage(image, x, y, x + r.width, y + height, r.x, r.y, r.x + r.width, r.y + r.height, null); - x += r.width; - } - boolean bl = hStretch = !hStretch; - } - x = 0; - y += height; - if (vStretch) { - vWeightSum -= vExtra; - vRemainder -= (float) height; - } - boolean bl = vStretch = !vStretch; - } - } finally { - g.dispose(); - } - } - - public void getPadding(int[] padding) { - padding[0] = this.mHorizontalPadding.mFirst; - padding[2] = this.mHorizontalPadding.mSecond; - padding[1] = this.mVerticalPadding.mFirst; - padding[3] = this.mVerticalPadding.mSecond; - } - - public int[] getPadding() { - this.getPadding(sPaddingRect); - return sPaddingRect; - } - - private DrawingData computePatches(int scaledWidth, int scaledHeight) { - int start; - DrawingData data = new DrawingData(); - boolean measuredWidth = false; - boolean endRow = true; - int remainderHorizontal = 0; - int remainderVertical = 0; - if (this.mFixed.size() > 0) { - start = this.mFixed.get((int) 0).y; - for (Rectangle rect : this.mFixed) { - if (rect.y > start) { - endRow = true; - measuredWidth = true; - } - if (!measuredWidth) - remainderHorizontal += rect.width; - if (!endRow) - continue; - remainderVertical += rect.height; - endRow = false; - start = rect.y; - } - } - data.mRemainderHorizontal = scaledWidth - remainderHorizontal; - data.mRemainderVertical = scaledHeight - remainderVertical; - data.mHorizontalPatchesSum = 0.0f; - if (this.mHorizontalPatches.size() > 0) { - start = -1; - for (Rectangle rect : this.mHorizontalPatches) { - if (rect.x <= start) - continue; - DrawingData drawingData = data; - drawingData.mHorizontalPatchesSum = drawingData.mHorizontalPatchesSum + (float) rect.width; - start = rect.x; - } - } else { - start = -1; - for (Rectangle rect : this.mPatches) { - if (rect.x <= start) - continue; - DrawingData drawingData = data; - drawingData.mHorizontalPatchesSum = drawingData.mHorizontalPatchesSum + (float) rect.width; - start = rect.x; - } - } - data.mVerticalPatchesSum = 0.0f; - if (this.mVerticalPatches.size() > 0) { - start = -1; - for (Rectangle rect : this.mVerticalPatches) { - if (rect.y <= start) - continue; - DrawingData drawingData = data; - drawingData.mVerticalPatchesSum = drawingData.mVerticalPatchesSum + (float) rect.height; - start = rect.y; - } - } else { - start = -1; - for (Rectangle rect : this.mPatches) { - if (rect.y <= start) - continue; - DrawingData drawingData = data; - drawingData.mVerticalPatchesSum = drawingData.mVerticalPatchesSum + (float) rect.height; - start = rect.y; - } - } - return data; - } - - private void findPatches(BufferedImage image) { - int width = image.getWidth() - 2; - int height = image.getHeight() - 2; - int[] row = null; - int[] column = null; - row = GraphicsUtilities.getPixels(image, 1, 0, width, 1, row); - column = GraphicsUtilities.getPixels(image, 0, 1, 1, height, column); - boolean[] result = new boolean[1]; - Pair>> left = this.getPatches(column, result); - this.mVerticalStartWithPatch = result[0]; - result = new boolean[1]; - Pair>> top = this.getPatches(row, result); - this.mHorizontalStartWithPatch = result[0]; - this.mFixed = this.getRectangles((List) left.mFirst, (List) top.mFirst); - this.mPatches = this.getRectangles((List) left.mSecond, (List) top.mSecond); - if (this.mFixed.size() > 0) { - this.mHorizontalPatches = this.getRectangles((List) left.mFirst, (List) top.mSecond); - this.mVerticalPatches = this.getRectangles((List) left.mSecond, (List) top.mFirst); - } else if (((List) top.mFirst).size() > 0) { - this.mHorizontalPatches = new ArrayList<>(0); - this.mVerticalPatches = this.getVerticalRectangles(height, (List) top.mFirst); - } else if (((List) left.mFirst).size() > 0) { - this.mHorizontalPatches = this.getHorizontalRectangles(width, (List) left.mFirst); - this.mVerticalPatches = new ArrayList<>(0); - } else { - this.mVerticalPatches = new ArrayList<>(0); - this.mHorizontalPatches = this.mVerticalPatches; - } - row = GraphicsUtilities.getPixels(image, 1, height + 1, width, 1, row); - column = GraphicsUtilities.getPixels(image, width + 1, 1, 1, height, column); - top = this.getPatches(row, result); - this.mHorizontalPadding = this.getPadding((List) top.mFirst); - left = this.getPatches(column, result); - this.mVerticalPadding = this.getPadding((List) left.mFirst); - } - - private List getVerticalRectangles(int imageHeight, List> topPairs) { - ArrayList rectangles = new ArrayList<>(); - for (Pair top : topPairs) { - int x = top.mFirst; - int width = top.mSecond - top.mFirst; - rectangles.add(new Rectangle(x, 0, width, imageHeight)); - } - return rectangles; - } - - private List getHorizontalRectangles(int imageWidth, List> leftPairs) { - ArrayList rectangles = new ArrayList<>(); - for (Pair left : leftPairs) { - int y = left.mFirst; - int height = left.mSecond - left.mFirst; - rectangles.add(new Rectangle(0, y, imageWidth, height)); - } - return rectangles; - } - - private Pair getPadding(List> pairs) { - if (pairs.isEmpty()) - return new Pair<>(0, 0); - if (pairs.size() == 1) { - if (pairs.get((int) 0).mFirst == 0) - return new Pair<>(pairs.get((int) 0).mSecond - pairs.get((int) 0).mFirst, 0); - return new Pair<>(0, pairs.get((int) 0).mSecond - pairs.get((int) 0).mFirst); - } - int index = pairs.size() - 1; - return new Pair<>(pairs.get((int) 0).mSecond - pairs.get((int) 0).mFirst, pairs.get((int) index).mSecond - pairs.get((int) index).mFirst); - } - - private List getRectangles(List> leftPairs, List> topPairs) { - ArrayList rectangles = new ArrayList<>(); - for (Pair left : leftPairs) { - int y = left.mFirst; - int height = left.mSecond - left.mFirst; - for (Pair top : topPairs) { - int x = top.mFirst; - int width = top.mSecond - top.mFirst; - rectangles.add(new Rectangle(x, y, width, height)); - } - } - return rectangles; - } - - private Pair>> getPatches(int[] pixels, boolean[] startWithPatch) { - int lastIndex = 0; - int lastPixel = pixels[0]; - boolean first = true; - List> fixed = new ArrayList<>(); - List> patches = new ArrayList<>(); - int i = 0; - while (i < pixels.length) { - int pixel = pixels[i]; - if (pixel != lastPixel) { - if (lastPixel == -16777216) { - if (first) - startWithPatch[0] = true; - patches.add(new Pair<>(lastIndex, i)); - } else - fixed.add(new Pair<>(lastIndex, i)); - first = false; - lastIndex = i; - lastPixel = pixel; - } - ++i; - } - if (lastPixel == -16777216) { - if (first) - startWithPatch[0] = true; - patches.add(new Pair<>(lastIndex, pixels.length)); - } else - fixed.add(new Pair<>(lastIndex, pixels.length)); - if (patches.isEmpty()) { - patches.add(new Pair<>(1, pixels.length)); - startWithPatch[0] = true; - fixed.clear(); - } - return new Pair<>(fixed, patches); - } - - static final class DrawingData { - - int mRemainderHorizontal; - int mRemainderVertical; - float mHorizontalPatchesSum; - float mVerticalPatchesSum; - } - - static class Pair implements Serializable { - - private static final long serialVersionUID = -2204108979541762418L; - E mFirst; - E mSecond; - - Pair(E first, E second) { - this.mFirst = first; - this.mSecond = second; - } - - @Override - public String toString() { - return "Pair[" + this.mFirst + ", " + this.mSecond + "]"; - } - } - -} diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/RadioButtonMenuItemCheckIcon2.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/RadioButtonMenuItemCheckIcon2.png deleted file mode 100644 index 0164f3ba3861a0853f733146b2d60e17d0185816..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 812 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 diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/asc2.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/asc2.png deleted file mode 100644 index f44526e4fe2c20b39ce7ea6ab935ac231b1287cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2848 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 diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/checkbox_menuitem_none.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/checkbox_menuitem_none.png deleted file mode 100644 index 6a49a7343d8ffa7754741e758b3b4a10e72ed210..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 350 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjoCO|{#S9GG!XV7ZFl!D-g+j7N zkS_y6l_~>6Lo)-z&;LOBB?CjL0RzLU1O^7H84L{K`IF+0x&hTb@pN$vskrqf)RF6u zfxw*H>P+sBDxx(VKPK5Z2-Gz33(S8Y{j2@XQT8W{wjA#kPMKHrx=OUiH>7BT#RPA& znKM(Jrn#^v3Mv}Z#Vc&g4GZ1Muz|_o^OKhhF{d`|spNc8xzF=*iMxxpe3{_RZ?*MI z1sg=?PrJ4&E$t(#ard=d+X_|neNw$NO?;aZC5}1wC}}KZQ22cA!N*OXr&^rr;W|>t zqr{~yu!mWxsO-TiYt|UP{bB_NXI@OP-|gSlQjzZ9l6$@M^CFEsGiFM6%2b r$+0!Icjq&{S)2A>x%d~;cSeRAz6}m3j6IS-|1x;G`njxgN@xNA@HBx6 diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/checkbox_menuitem_none_1.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/checkbox_menuitem_none_1.png deleted file mode 100644 index 6a49a7343d8ffa7754741e758b3b4a10e72ed210..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 350 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjoCO|{#S9GG!XV7ZFl!D-g+j7N zkS_y6l_~>6Lo)-z&;LOBB?CjL0RzLU1O^7H84L{K`IF+0x&hTb@pN$vskrqf)RF6u zfxw*H>P+sBDxx(VKPK5Z2-Gz33(S8Y{j2@XQT8W{wjA#kPMKHrx=OUiH>7BT#RPA& znKM(Jrn#^v3Mv}Z#Vc&g4GZ1Muz|_o^OKhhF{d`|spNc8xzF=*iMxxpe3{_RZ?*MI z1sg=?PrJ4&E$t(#ard=d+X_|neNw$NO?;aZC5}1wC}}KZQ22cA!N*OXr&^rr;W|>t zqr{~yu!mWxsO-TiYt|UP{bB_NXI@OP-|gSlQjzZ9l6$@M^CFEsGiFM6%2b r$+0!Icjq&{S)2A>x%d~;cSeRAz6}m3j6IS-|1x;G`njxgN@xNA@HBx6 diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/checkbox_menuitem_selected_normal.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/checkbox_menuitem_selected_normal.png deleted file mode 100644 index cf4fe6d8c6c748118c7e1133af0593524c13d46a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 519 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjoCO|{#S9GG!XV7ZFl!D-g+j7N zkS_y6l_~>6Lo)-z&;LOBB?CjL0RzLU1O^7H84L{K`IF+0x-l>?_IkQFhE&{2`t$$4 zJ+m&OFmvz06|BzpnabGM*wUgR57@sx!MxtqJnprjfx(BzK}S5&>>kW6{W0(E-|zdw z_Sbytah&sVb$<1%_l|6AZTGKyVEq1!+y9DO%@5Pxx3}lZ^yl5Zad+OcYQEVIk3<|e zcHn>l$5KfN35gr|Hop}rKb^c@S^xj<^c|HiA3a`V&|U;IWBrq3jOCBN-M;*6e#IM* zh66yb`Ol%%ob~_yUf)~(`dYkc;k_7r?zQSXJUsR%JDI=D>CE0+_pxKGu#o8A)2GiF zy|q7Fzf9l$f7<@~-_stR?A4Bqw!VBDXsz9Z*aV9dTSE;m1084=IEnw??U&m2vtp$L|Nr>bdzJs)ox}tn*ircM5_>#% zFOy*1yX!zF{O5>t@G(kFPDprAra$l6pZ=-J(LJ+OOEYutXeGt)7e4#{|40Im_|Kj4 zZ52$SuHNz@Wwa;QhPsH=e*qWbkzLb6Mw< G&;$TXdhUAw diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/checkbox_menuitem_selected_normal_1.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/checkbox_menuitem_selected_normal_1.png deleted file mode 100644 index cf4fe6d8c6c748118c7e1133af0593524c13d46a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 519 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjoCO|{#S9GG!XV7ZFl!D-g+j7N zkS_y6l_~>6Lo)-z&;LOBB?CjL0RzLU1O^7H84L{K`IF+0x-l>?_IkQFhE&{2`t$$4 zJ+m&OFmvz06|BzpnabGM*wUgR57@sx!MxtqJnprjfx(BzK}S5&>>kW6{W0(E-|zdw z_Sbytah&sVb$<1%_l|6AZTGKyVEq1!+y9DO%@5Pxx3}lZ^yl5Zad+OcYQEVIk3<|e zcHn>l$5KfN35gr|Hop}rKb^c@S^xj<^c|HiA3a`V&|U;IWBrq3jOCBN-M;*6e#IM* zh66yb`Ol%%ob~_yUf)~(`dYkc;k_7r?zQSXJUsR%JDI=D>CE0+_pxKGu#o8A)2GiF zy|q7Fzf9l$f7<@~-_stR?A4Bqw!VBDXsz9Z*aV9dTSE;m1084=IEnw??U&m2vtp$L|Nr>bdzJs)ox}tn*ircM5_>#% zFOy*1yX!zF{O5>t@G(kFPDprAra$l6pZ=-J(LJ+OOEYutXeGt)7e4#{|40Im_|Kj4 zZ52$SuHNz@Wwa;QhPsH=e*qWbkzLb6Mw< G&;$TXdhUAw diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/checkbox_off.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/checkbox_off.png deleted file mode 100644 index 9a7056633d8bab9a0255fb9b6f89e54765e29478..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 205 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjEX7WqAsj$Z!;#Vf4nJ z@RfitW46lXYd}Hy64!{5;QX|b^2DN42H(WwqWs*{l*~j0x6Go{^8BLgVg-w>8J8-6 zN?kl%978-hlmGnxZ_ljDDD3OIyq#6&#GJM^wpA_R&d$urVcZKQO_Az5B>$_>AnV`? r*2Q8yQ3gsn3#w`x_$1u5Yn^~LSM#l(U3T~*&^!iDS3j3^P64nJ z@RfitW46lXYd}Hy64!{5;QX|b^2DN42H(WwqWs*{l*~j0x6Go{^8BLgVg-w>8J8-6 zO1(T?978-hlmGnxZ_ljDDD3OIyq#6&#GI?E!-G}#I5|5@Zj54>y5z(Mpupk}?R7Fe yQ3hEDSFkP?>*3%wc*XqX)106K7Ev#SnHbJ|4nJ z@RfitW46lXYd}Hy64!{5;QX|b^2DN42H(WwqWs*{l*~j0x6Go{^8BLgVg-w>8J8-6 zO1(T?978-hlmGnxZ_ljDDD3OIyq#6&gp9DT@T!*UGmXuTC?N9hLVt50 xx0|lS)`Tlff{Bc7wGDCeg1IEzwQHRi81`=EJ*~v^x&UY@gQu&X%Q~loCIFI!K2HDu diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/checkbox_off_pressed.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/checkbox_off_pressed.png deleted file mode 100644 index 6575fff11d9bbe9695bd502a848ec9c173cfb43c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 211 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjEX7WqAsj$Z!;#Vf4nJ z@RfitW46lXYd}Hy64!{5;QX|b^2DN42H(WwqWs*{l*~j0x6Go{^8BLgVg-w>8J8-6 zO1(T?978-hlmGnxZ_ljDDD3OIyq#6&gv`07pCO#<-wO*#Zj54>y5vLwP(b6)LV5PZ yVm(m?SqE3JDj#C%`Ngo;X1Rz#U)Zk}28I$hKKFYEJ^6vAGI+ZBxvXXU^U8t`Kqa5*|IhVEI;<+yD?GTx6ku@ zp7-l{KA)cFk;P&$aw&OE-G2g*_cjm&;aln@2!bpj;AQfw=I`Ra--9m!+}~12_ zXwsZdJ&-Do7+`p13x6;~FdSjsYD$=w)d~E;5QEE3{J{_ahMKaZxfuf@(I^8;E<9oY zfT5OJCQS{Q1Mb6*bS-SKxO?($d~9`xy)zMjrb-RAenZL)CGCOLzKz@K!|nBP=D%a6 zrNcYD-k{vC;N=EQUHs=4k=15a&cU zdaW9xu7bI~Hp%87@uF!}3J#}xGctbF?|zG<=-dB;kCOd=`swrp_(yG;!g;Tq00000 LNkvXXu0mjf-B0E# diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/checkbox_on_disabled.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/checkbox_on_disabled.png deleted file mode 100644 index e5542d0c30a56a66115ba652feb05ae04489e056..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 518 zcmV+h0{Q)kP){Tj3c2*=a-gJH@N zSN%f`R0b+B&Z za26$W8wWtwsbbS*qpL&N9AMct#LYv7^iz?;i#sl3NutR|0F;V0Hk{KKwOx|tAd#Xm zV>e#69fMj0P&EfwpR+J&GSoGf1OS-z8oX{hCY`1lTbLNYY3Y|`UKdb-Y%kg|>orW7 zdRTLe%Qgp@4^6LDvAZ(cka0!7yBEpPhZMc<=dDWd|LND$GwGUac~gCfpa1{>07*qo IM6N<$f)v5ny#N3J diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/checkbox_on_over.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/checkbox_on_over.png deleted file mode 100644 index b50a34bc62171bb3e41ad3803ecd7e3f4057374b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 525 zcmV+o0`mQdP)I^i3&t z(Bwpj8;i?I%E{TqNm_2gWs&~?wW;}0Y6mL^t5FWjS55h`Y+0KFTbOcS`-O?mq#@c^wFX@Fn$fyWOe}0WXtTnG1sOCjR?9$O_={T{3ES z5s5}q<|Oq%sl3t+!zj^B)rukNycDgn?`p~u!Q%5ErS4=nZ_Ts}W8pP$pf z9Wy=6%x-yDbDscERFKcQ#e_C5_j7rly2RL6TRkIUog(wJfH=f4 z(T&kiNPBHLbA7Ff%|YQsGw3uNPWNVH9M|uDi8 zG&vFCHj9hW%E{TqNo%=@UDmY!z|^SuQObdGuo~sSeAU#jOxEUr<=4LZ&Jg8&`#jI* zdB2|L^XYjWSt^y{J0<^C_n!b1ybKg}*O%1m)?t->2zZ*z%Uof1y^8;S5Ap&8Lg$RS z10<5kj5+UmAXPyj%7|;7NGwk5E`ir(`Y`WPCy2!23@!PI#Nq%L>MAnk<_t(AlMF7d z5fq{T47cg9o0@V5+}z#MJ-@=j*5Rx1anB~(#{vK?)f$`w2GI>=?19a_K_C<+5DIe~ zxn`!fmD$yOmUoW;C@m?*Ycr!PD*PN^%G}J($pymIEsnJV)`Ms4pI$yLlFRW}yQtA9 zMa@B^MD4ZZ_$Dl9RSJN#Ie>G(fKgwW)m#(+(4bZ0o3NlOQ>DkoIvcSX>LrvAO7!+U&sVblPd}R;0A3+&GV6lj Qr~m)}07*qoM6N<$f|pn6Pyhe` diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/default_frame_icon.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/default_frame_icon.png deleted file mode 100644 index 5237cb89122c04ebd82a50ce31e0b8b1a8ff3d05..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 569 zcmV-90>=G`P)Px#1ZP1_K>z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUzw@E}nR5(wKQ$0%qK@dH~D1O8sc7h02>W|O}7J^OUN3y$#okj$; zFy!_Q(Zr8Ju(1;?{0Fvzwjx;i2Q+nJrBN{^d+WR-3DM+?2gBUW&b)a$^Ug3l9&HQl zb>6*qut84G@yVww*8 z`DEl69^Z)n20$?w{)khc9Yth;if{MmjJ$3#pL26I zrj^Yeon*YX$*O8wxrm2`%C^WlQcN~%MoE6IEPkcaOMTVD`pzgW+5DOWb=FjkI+5_X zAd)>1qt!x^4{wEo1GuwGn>wRdr>A}h$G!INUH?xHJX2F5byZF})(>ixAoPHh!Z-Xt z$`Yr`erIbjB>MiGcpbt<6rm&nL|2t_0-|(00000NkvXX Hu0mjfs(tky diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/desc2.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/desc2.png deleted file mode 100644 index ee05a9c31aaaf2405bde72bcee0997c1142da247..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2826 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 diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/error.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/error.png deleted file mode 100644 index b4605fecd9ee2e783ce8765c3f1e811fa6eb2421..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3155 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 diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/frame_close_pressed.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/frame_close_pressed.png deleted file mode 100644 index 7ad8a17e0029bccc98244edba08e95b95b73800b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3202 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 R9IyZY002ovPDHLkV1l`z3FQC) diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/frame_max_pressed.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/frame_max_pressed.png deleted file mode 100644 index 65439c76ba41beb357dae33fcc2de4e51ecb5e7d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3212 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 Rxo-df002ovPDHLkV1m(OISBv& diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/frame_maxwin_pressed.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/frame_maxwin_pressed.png deleted file mode 100644 index f8eaa6198424c6d0e60fa6f751976e85c1671bc0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3231 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 R2#x>%002ovPDHLkV1lkZAJzZ> diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/frame_maxwin_rover.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/frame_maxwin_rover.png deleted file mode 100644 index ba0993572ca88877beff869be2d729161ebd5512..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3275 zcmV;+3^enJP)KLZ*U+5Lu!Sk^o_Z5E4Meg@_7P6crJiNL9pw)e1;Xm069{HJUZAPk55R%$-RIA z6-eL&AQ0xu!e<4=008gy@A0LT~suv4>S3ILP<0Bm`DLLvaF4FK%)Nj?Pt*r}7;7Xa9z9H|HZjR63e zC`Tj$K)V27Re@400>HumpsYY5E(E}?0f1SyGDiY{y#)Yvj#!WnKwtoXnL;eg03bL5 z07D)V%>y7z1E4U{zu>7~aD})?0RX_umCct+(lZpemCzb@^6=o|A>zVpu|i=NDG+7} zl4`aK{0#b-!z=TL9Wt0BGO&T{GJWpjryhdijfaIQ&2!o}p04JRKYg3k&Tf zVxhe-O!X z{f;To;xw^bEES6JSc$k$B2CA6xl)ltA<32E66t?3@gJ7`36pmX0IY^jz)rRYwaaY4 ze(nJRiw;=Qb^t(r^DT@T3y}a2XEZW-_W%Hszxj_qD**t_m!#tW0KDiJT&R>6OvVTR z07RgHDzHHZ48atvzz&?j9lXF70$~P3Knx_nJP<+#`N z#-MZ2bTkiLfR>_b(HgWKJ%F~Nr_oF3b#wrIijHG|(J>BYjM-sajE6;FiC7vY#};Gd zST$CUHDeuEH+B^pz@B062qXfFfD`NpUW5?BY=V%GM_5c)L#QR}BeW8_2v-S%gfYS= zB9o|3v?Y2H`NVi)In3rTB8+ej^> zQ=~r95NVuDChL%G$=>7$vVg20myx%S50Foi`^m%Pw-h?Xh~i8Mq9jtJloCocWk2Nv zrJpiFnV_ms&8eQ$2&#xWpIS+6pmtC%Q-`S&GF4Q#^mhymh7E(qNMa}%YZ-ePrx>>xFPTiH1=E+A$W$=bG8>s^ zm=Bn5Rah$aDtr}@$`X}2l~$F0mFKEdRdZE8)p@E5RI61Ft6o-prbbn>P~)iy)E2AN zsU20jsWz_8Qg>31P|s0cqrPALg8E|(vWA65poU1JRAaZs8I2(p#xiB`SVGovRs-uS zYnV-9TeA7=Om+qP8+I>yOjAR1s%ETak!GFdam@h^# z)@rS0t$wXH+Irf)+G6c;?H29p+V6F6oj{!|o%K3xI`?%6x;DB|x`n#ibhIR?(H}Q3Gzd138Ei2)WAMz7W9Vy`X}HnwgyEn!VS)>mv$8&{hQn>w4zwy3R}t;BYlZQm5)6pty=DfLrs+A-|>>;~;Q z_F?uV_HFjh9n2gO9o9Q^JA86v({H5aB!kjoO6 zc9$1ZZKsN-Zl8L~mE{`ly3)1N^`o1+o7}D0ZPeY&J;i;i`%NyJ8_8Y6J?}yE@b_5a zam?eLr<8@mESk|3$_SkmS{wQ>%qC18))9_|&j{ZT zes8AvOzF(F2#DZEY>2oYX&IRp`F#{ADl)1r>QS^)ba8a|EY_^#S^HO&t^Rgqwv=MZThqqEWH8 zxJo>d=ABlR_Bh=;eM9Tw|Ih34~oTE|= zX_mAr*D$vzw@+p(E0Yc6dFE}(8oqt`+R{gE3x4zjX+Sb3_cYE^= zgB=w+-tUy`ytONMS8KgRef4hA?t0j zufM;t32jm~jUGrkaOInTZ`zyfns>EuS}G30LFK_G-==(f<51|K&cocp&EJ`SxAh3? zNO>#LI=^+SEu(FqJ)ynt=!~PC9bO$rzPJB=?=j6w@a-(u02P7 zaQ)#(uUl{HW%tYNS3ItC^iAtK(eKlL`f9+{bJzISE?u8_z3;~C8@FyI-5j_jy7l;W z_U#vU3hqqYU3!mrul&B+{ptt$59)uk{;_4iZQ%G|z+lhASr6|H35TBkl>gI*;nGLU zN7W-nBaM%pA0HbH8olyl&XeJ%vZoWz%6?Y=dFykl=imL}`%BMQ{Mhgd`HRoLu6e2R za__6DuR6yg#~-}Tc|Gx_{H@O0eebyMy5GmWADJlpK>kqk(fVV@r_fLLKIeS?{4e)} z^ZO;zpECde03c&XQcVB=dL;k=fP(-4`Tqa_faw4Lbua(`>RI+y?e7jKeZ#YO-C z0r*KoK~#9!q?6BXQc)1bf2a3c%Aea3P!=W@;{t*d5?5U`-Besic!0hE24dn?c>v`J zO7sOxAE0GLz}TppZlpz8SF&*-*hp_dE|(q`K)oQl&g9#CnfcC_nK?o!#Z6*q0p|jq z0X1MSL2bgh=8MIggRHIWH|2Jf>aUN~FTMhhTzSBDaFg`yZKRM-fwzkUa-HG%ZsA*z zW3$On*(jwLbo;pdUUVTz7%^T&UT{kfBuHs5{XUM7iW)fl@m zVwB>qkwPv5)^rBha=S|7@{Exh&A{$ieBZCr@0yI%h{oj^<#rVy>m1@vrE@s8J(mD> z&!Sa6#xnmfR5q2)A;6APVB^F*WzkA~cLM+n%>k{0I)jToC*~=@27q)H54wF?2X*Y8 z1%UUCpKv-cyEX(;NC3;};3#H9aQnT4(+Q+!yzbtQ-~TxhLJ;xY2dFy*_8tef(1m2# z?`18$j^@^{Uv#D}B&pyQz@Af}lnJGX`=V$KLZ*U+5Lu!Sk^o_Z5E4Meg@_7P6crJiNL9pw)e1;Xm069{HJUZAPk55R%$-RIA z6-eL&AQ0xu!e<4=008gy@A0LT~suv4>S3ILP<0Bm`DLLvaF4FK%)Nj?Pt*r}7;7Xa9z9H|HZjR63e zC`Tj$K)V27Re@400>HumpsYY5E(E}?0f1SyGDiY{y#)Yvj#!WnKwtoXnL;eg03bL5 z07D)V%>y7z1E4U{zu>7~aD})?0RX_umCct+(lZpemCzb@^6=o|A>zVpu|i=NDG+7} zl4`aK{0#b-!z=TL9Wt0BGO&T{GJWpjryhdijfaIQ&2!o}p04JRKYg3k&Tf zVxhe-O!X z{f;To;xw^bEES6JSc$k$B2CA6xl)ltA<32E66t?3@gJ7`36pmX0IY^jz)rRYwaaY4 ze(nJRiw;=Qb^t(r^DT@T3y}a2XEZW-_W%Hszxj_qD**t_m!#tW0KDiJT&R>6OvVTR z07RgHDzHHZ48atvzz&?j9lXF70$~P3Knx_nJP<+#`N z#-MZ2bTkiLfR>_b(HgWKJ%F~Nr_oF3b#wrIijHG|(J>BYjM-sajE6;FiC7vY#};Gd zST$CUHDeuEH+B^pz@B062qXfFfD`NpUW5?BY=V%GM_5c)L#QR}BeW8_2v-S%gfYS= zB9o|3v?Y2H`NVi)In3rTB8+ej^> zQ=~r95NVuDChL%G$=>7$vVg20myx%S50Foi`^m%Pw-h?Xh~i8Mq9jtJloCocWk2Nv zrJpiFnV_ms&8eQ$2&#xWpIS+6pmtC%Q-`S&GF4Q#^mhymh7E(qNMa}%YZ-ePrx>>xFPTiH1=E+A$W$=bG8>s^ zm=Bn5Rah$aDtr}@$`X}2l~$F0mFKEdRdZE8)p@E5RI61Ft6o-prbbn>P~)iy)E2AN zsU20jsWz_8Qg>31P|s0cqrPALg8E|(vWA65poU1JRAaZs8I2(p#xiB`SVGovRs-uS zYnV-9TeA7=Om+qP8+I>yOjAR1s%ETak!GFdam@h^# z)@rS0t$wXH+Irf)+G6c;?H29p+V6F6oj{!|o%K3xI`?%6x;DB|x`n#ibhIR?(H}Q3Gzd138Ei2)WAMz7W9Vy`X}HnwgyEn!VS)>mv$8&{hQn>w4zwy3R}t;BYlZQm5)6pty=DfLrs+A-|>>;~;Q z_F?uV_HFjh9n2gO9o9Q^JA86v({H5aB!kjoO6 zc9$1ZZKsN-Zl8L~mE{`ly3)1N^`o1+o7}D0ZPeY&J;i;i`%NyJ8_8Y6J?}yE@b_5a zam?eLr<8@mESk|3$_SkmS{wQ>%qC18))9_|&j{ZT zes8AvOzF(F2#DZEY>2oYX&IRp`F#{ADl)1r>QS^)ba8a|EY_^#S^HO&t^Rgqwv=MZThqqEWH8 zxJo>d=ABlR_Bh=;eM9Tw|Ih34~oTE|= zX_mAr*D$vzw@+p(E0Yc6dFE}(8oqt`+R{gE3x4zjX+Sb3_cYE^= zgB=w+-tUy`ytONMS8KgRef4hA?t0j zufM;t32jm~jUGrkaOInTZ`zyfns>EuS}G30LFK_G-==(f<51|K&cocp&EJ`SxAh3? zNO>#LI=^+SEu(FqJ)ynt=!~PC9bO$rzPJB=?=j6w@a-(u02P7 zaQ)#(uUl{HW%tYNS3ItC^iAtK(eKlL`f9+{bJzISE?u8_z3;~C8@FyI-5j_jy7l;W z_U#vU3hqqYU3!mrul&B+{ptt$59)uk{;_4iZQ%G|z+lhASr6|H35TBkl>gI*;nGLU zN7W-nBaM%pA0HbH8olyl&XeJ%vZoWz%6?Y=dFykl=imL}`%BMQ{Mhgd`HRoLu6e2R za__6DuR6yg#~-}Tc|Gx_{H@O0eebyMy5GmWADJlpK>kqk(fVV@r_fLLKIeS?{4e)} z^ZO;zpECde03c&XQcVB=dL;k=fP(-4`Tqa_faw4Lbua(`>RI+y?e7jKeZ#YO-C z0Z~arK~#9!tdqe?0#Ou(zcV){gos&`K0upDkyfrmqL=Uu3?*n=_yF|;O1*(E5raj$ zKq}@PL?K-|GILto5r;u7umcw^|GoduIsbpJs4BaZvj%g4YrqHQ$?_A-&0dyF2Te43 z)RB))USaxWQLl^~)sW%^h`9ou)(Nx-r`(+yTvfeMRbN;2l3;H3zU=y)e+B?PVzlr^Ong890000KLZ*U+5Lu!Sk^o_Z5E4Meg@_7P6crJiNL9pw)e1;Xm069{HJUZAPk55R%$-RIA z6-eL&AQ0xu!e<4=008gy@A0LT~suv4>S3ILP<0Bm`DLLvaF4FK%)Nj?Pt*r}7;7Xa9z9H|HZjR63e zC`Tj$K)V27Re@400>HumpsYY5E(E}?0f1SyGDiY{y#)Yvj#!WnKwtoXnL;eg03bL5 z07D)V%>y7z1E4U{zu>7~aD})?0RX_umCct+(lZpemCzb@^6=o|A>zVpu|i=NDG+7} zl4`aK{0#b-!z=TL9Wt0BGO&T{GJWpjryhdijfaIQ&2!o}p04JRKYg3k&Tf zVxhe-O!X z{f;To;xw^bEES6JSc$k$B2CA6xl)ltA<32E66t?3@gJ7`36pmX0IY^jz)rRYwaaY4 ze(nJRiw;=Qb^t(r^DT@T3y}a2XEZW-_W%Hszxj_qD**t_m!#tW0KDiJT&R>6OvVTR z07RgHDzHHZ48atvzz&?j9lXF70$~P3Knx_nJP<+#`N z#-MZ2bTkiLfR>_b(HgWKJ%F~Nr_oF3b#wrIijHG|(J>BYjM-sajE6;FiC7vY#};Gd zST$CUHDeuEH+B^pz@B062qXfFfD`NpUW5?BY=V%GM_5c)L#QR}BeW8_2v-S%gfYS= zB9o|3v?Y2H`NVi)In3rTB8+ej^> zQ=~r95NVuDChL%G$=>7$vVg20myx%S50Foi`^m%Pw-h?Xh~i8Mq9jtJloCocWk2Nv zrJpiFnV_ms&8eQ$2&#xWpIS+6pmtC%Q-`S&GF4Q#^mhymh7E(qNMa}%YZ-ePrx>>xFPTiH1=E+A$W$=bG8>s^ zm=Bn5Rah$aDtr}@$`X}2l~$F0mFKEdRdZE8)p@E5RI61Ft6o-prbbn>P~)iy)E2AN zsU20jsWz_8Qg>31P|s0cqrPALg8E|(vWA65poU1JRAaZs8I2(p#xiB`SVGovRs-uS zYnV-9TeA7=Om+qP8+I>yOjAR1s%ETak!GFdam@h^# z)@rS0t$wXH+Irf)+G6c;?H29p+V6F6oj{!|o%K3xI`?%6x;DB|x`n#ibhIR?(H}Q3Gzd138Ei2)WAMz7W9Vy`X}HnwgyEn!VS)>mv$8&{hQn>w4zwy3R}t;BYlZQm5)6pty=DfLrs+A-|>>;~;Q z_F?uV_HFjh9n2gO9o9Q^JA86v({H5aB!kjoO6 zc9$1ZZKsN-Zl8L~mE{`ly3)1N^`o1+o7}D0ZPeY&J;i;i`%NyJ8_8Y6J?}yE@b_5a zam?eLr<8@mESk|3$_SkmS{wQ>%qC18))9_|&j{ZT zes8AvOzF(F2#DZEY>2oYX&IRp`F#{ADl)1r>QS^)ba8a|EY_^#S^HO&t^Rgqwv=MZThqqEWH8 zxJo>d=ABlR_Bh=;eM9Tw|Ih34~oTE|= zX_mAr*D$vzw@+p(E0Yc6dFE}(8oqt`+R{gE3x4zjX+Sb3_cYE^= zgB=w+-tUy`ytONMS8KgRef4hA?t0j zufM;t32jm~jUGrkaOInTZ`zyfns>EuS}G30LFK_G-==(f<51|K&cocp&EJ`SxAh3? zNO>#LI=^+SEu(FqJ)ynt=!~PC9bO$rzPJB=?=j6w@a-(u02P7 zaQ)#(uUl{HW%tYNS3ItC^iAtK(eKlL`f9+{bJzISE?u8_z3;~C8@FyI-5j_jy7l;W z_U#vU3hqqYU3!mrul&B+{ptt$59)uk{;_4iZQ%G|z+lhASr6|H35TBkl>gI*;nGLU zN7W-nBaM%pA0HbH8olyl&XeJ%vZoWz%6?Y=dFykl=imL}`%BMQ{Mhgd`HRoLu6e2R za__6DuR6yg#~-}Tc|Gx_{H@O0eebyMy5GmWADJlpK>kqk(fVV@r_fLLKIeS?{4e)} z^ZO;zpECde03c&XQcVB=dL;k=fP(-4`Tqa_faw4Lbua(`>RI+y?e7jKeZ#YO-C z0bEH$K~#9!tdq@40#Ovje=|1YLaWU*kZlubkxmdod!cO-A=KVbqW+fEM@aL(o2bKjGM5X@4t1EvB;KpyB=owqR6PL^yA z;)8zg%&g>SRB!pLl>t~-4zlEr;9K8Cb}5Izxzm6|r&Ujvua9Xpo*eCZmjVQLPH}tn zB#;>$pbq-I&co#a?PhiC&K}Lr=Kck;OK}6;VFq!tlA9<7Xg8~vl^j5PG{ji_`DW_m zEp7~8&cec9Z;t?!N=*udx}(rAG{RvWiyQvyj1x{61$4D3%iG3fWwX8DT7%N_5p zMF198HqiYMe8Ih;IP;?rLfBgsLYxR8^5VDdEljoZrCGo8_W+!;wg1BVU=aWS002ov JPDHLkV1gz8_PqcA diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/frame_min_rover.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/frame_min_rover.png deleted file mode 100644 index 20e47f8bbd4242a53aeefa9aba02eb2610f2bcdf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3130 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 diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/head_bg.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/head_bg.png deleted file mode 100644 index 27e0ee39712512274c54441408ba664eab1964d5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 969 zcmV;)12+7LP)X1ONa4NlwfF00009a7bBm000XU z000XU0RWnu7ytkR8EHd9P*7-ZbZ>KLZ*U+lnSp_Ufq@}0xwybFAi#%#fq@|}KQEO51AM#2z{tSB zz;IdD(Z$J?fi%FHTu@ZPz`$^Tfq}s&CAB!2fq~%*0|P^Pc}YPD0|R3W0|SFdQg%TJ z0|R3L0|SFdc1Vyj0|R3V0|OIJNoqw20|NttbACZ(QD%BZiGrb}rKN&nN`6wRLU3hq zNosDff@fZGeo;YwQDRAI3IhWJ)D8v)1_oZ2{1OHC#LPSeLsL}-Dual~C?)grM$+xhxmf|p7B=;2nnnfbQ63e)F`Yd zd{`u1lvi}CSe!Vg_*RJ&Nny#OQWes=(obaO$cD-Z%AJ+(QSedZRlJ}yML9}EN#(Wb zR<%ZTKMh%px0?I3CTgeZSnCSuzS29QKi{CnFv`f%Skm~n$vxA{#r++CO)=?RdfInDbtjt*-0cR=O|sSme3TYk~JdpT)k*{8ss|57-*GH|SXK z`H)+o&%(Y$FhvSRDMcH{xWz`r<;Axo%ud{#bT;{UDpQ(Vx=lt@W>wa#>^(X6@|g0~ z3w#QTi)I%eE_qufQSMSvSUIoiZ1vw-y}J1NNe#yue>WSnq_@s%yWSz#>D|@deYlsQ z&%VEI!oG?BCp%7QoqA$A?~LG?vt~V-qcyi=-o6D~3&R#IUi@*X!?Fp>AFecB)w=rT zTHSR`>u+u}*wnH4!B(qnQ@4NE>AP#y9*(`~`;H$_KiGNb^%1|Ln~#g1s6F}QwD*}U z=VZ^fU-)z>?((Ut7T1>D5WU%Y>+7BLyEpIqJUH;k^zrJaiqB@g5PaG7n)yxL+n?`C zKYaRB@cG@>yl?M*RI+y?e7jKeZ#YO-C04hmDK~#9!V*LM~0S&NxWWW&mPmB-~ r1DP5}&7#;WmdhAI00000|NjF3G*A@@!nm>c00000NkvXXu0mjfZcxAs diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/head_inactive.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/head_inactive.png deleted file mode 100644 index 74480a4cd3316b37fcabd9a584c82edeffc23d05..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2836 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 diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/info.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/info.png deleted file mode 100644 index 76d4706a14df20d15ca3910d713b38b172fc47f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1994 zcmV;*2Q~PKP)Px#1ZP1_K>z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBU(NJ&INR9Hu)Rt=0CWf|V>U5`=`YeNxjYl|QuL_L9OL$n+wH6=mP zw70Xnw?8-k-^_e7v-7`yge+A=NsJY-ks~D`Ay85pBZMe~5(Bxt zsOFjBT|V{ed#GO1CEz>7{;k0KSg^_kr$Lr`QPl9u4l=v>Xvh)va#Vyy}aZUp)_k zrtVkvk+6Ep%$i=r(bs5nD?xBI@%<~$RYENb@Ui!~ZZr&Ej}L31m=MlvzxM=<_S_8My! z<+E$Gbs*Y{;NzNGo*-T&>a=$7KS1CMOpLKfoaiaV3a*|LAZfVOFQ{JirD>na`>I>! z*)q=)!PZpu%30!6PQzhbbIL!uP||kU%bvGZb;_qe%7|O0I+eqU6Ml68CMjWCg7=Rt zKd1bHT&jI#o{tm+n`9^YC7h-}`l4J4=Q}K-f{9kV=mo`znyM2`DQIHa8px#M|`uTPwtlXj*?h+`fM1u(ae+4dP z#+%;XMLS4!5&(|X5b*OBj(WdqEgi2px8Wh?4fow5b$7NS5vj8kJ`ah8yIrJiS}?qm z3^!xP1=IU-Cjsn`8Z_L!EsW{?xuD~a<2Ca(p1Sd%;Xr`Br~vjwlZd-Tr2aQKQu)*% zbq?~>nVi9m4N`Z1tD!ny5K!97aJ=D63n*w_Z&7!q26gu&CJP-nl11X|F6!>P$ONL@ z822BDhS%3Qb|O(I1fMACrH5Kry)?Z9dBxsP&`QHa&H1RH*|nuI86f0}0x3OQ(4BFJ zMsS!`dgkUuzK)9t%1LxnQL_&*9C*-#{F=l7@j+_;Hc#wkj#!VTM0;JkY>I}pJ+Ik+ zg5a1LFcZMu&Ki`RfPH;^-Ah#>N1R*p#CmfYZ`WGekd-B;+CKnUoKvkg@`|->F%qa< zh50f>o@2hu3aa&cj-!_iNaig$V(KYI*yds)bHp~0z(`)T|HG1LRh#_`DCUlwVvT_O z3=6_UE#%2)+U5b(d;;@KXv^}lc~3#JdUJ~TSXQwHF8a#NAt@^6b%^nF3#(X13NpQR zb~+>Y8?(eZga9$byq+cImW2X}c$Zb_(U#AQWfk+)oI;OeRg-5&db{jd^?*@;KLh@8 z;9Pbl%=&ZO!LF=gr!jFlE7OULN`JOX*XR8aNz2wZFnD^jjX}(L*mpUeUbUP(zR-s?U0SqyIoWs_ z0^+o645uV|?@qS$mbj8>N&OZCJjY4KCcpBpaI|XB7M~*m-lUb2&O^Mp$oM?QU67@+=)Q`jN!w2BbOwqiKHPr&5B+IN{ zB3n3K6Vj6Y82tauf^&lY9w%ZsHEn&z;By^P*d{4KZ$Q8akj0#!olgnc3D~oE-Uor- z$6SE1jJds7zDJPtD|r4V6AkP*#+NxkU2=ykDJq}0FGu;dgXlp7{u?ZwHC`LX{cuVk zAI*C&>ZARF_GXGFQCd)M>U27Gt_lvSlqjy_c;#l8fPfG83*;z*zJoyL`g!s%JRigJ z^ZkN;f4``IXE#r-XD8%ETdi}nB|Va8upU+wCg@IC{!D66Tfa+HKf9}-U&*#9J3*H^ c4HskoFKBPXs~S&{9RL6T07*qoM6N<$g1ywig#Z8m diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/leaf1.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/leaf1.png deleted file mode 100644 index 78cc00f86a92a34ca11bb026e15ffb51ae887400..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 326 zcmV-M0lEH(P)h($07*qoM6N<$g5MvGod5s; diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/arrow.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/arrow.9.png deleted file mode 100644 index a9ef7c14e50c40e68b70c5b40dd389a1e0640c4a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 248 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xamSQK*5Dp-y;YjHK@;M7UB8wRq zxITa|qthCb86dSKt`Q}{`DrEPiAAXlzKO|2`MIennTZN+nMJAP`9;~q3Km;4E>!@P z=6kw0hGW9}LxAVf zwUp-6D>Xuqa!s*J8pjLYw>)8AyvzDdtycR7jU+@ l_Y0@CFgbW!tFE3U6*jNi*eiPe6BnS>44$rjF6*2UngHP!@P z=6bp~hG{E(s4)T;6@Vl`nC3RV^SjGB;b=9qd@_%22 j#yK-8sCeJqx2#<@jZd>w$ufH<&|(HpS3j3^P6!@P zmUy~2hGsfC7(;`rYa#nWA%(Ha}x13qE@6i}ynQ7KfS?rLLI^9XHLIsi62R zML4_cCrhLp*WBxi7*;%gTe~DWM4fUkX=R diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/btn_general_default.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/btn_general_default.9.png deleted file mode 100644 index 8d1c7608ee5dd61f6ac5cb7382b71ea9b22ad711..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2940 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 diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/btn_general_rover.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/btn_general_rover.9.png deleted file mode 100644 index d11cfa1633dfda59548f60081cb094547da1a6db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 241 zcmeAS@N?(olHy`uVBq!ia0vp^LO?9X!3HE1dHi&M6icy_X9x!n)NrJ90QsB+9+AZi z3|t>Tn9*sC$qb;Ne2HsBNpOBzNqJ&XDuZuga#4P6YD#9Jf?H-$YI%N9cCmuR){ILP zK&2U;E{-7{oyjQ&`2IZ>XlHa=!xS1C+G6sEH8(f6$7hN}15d;ROGigXmCU&9d9rhS zO~nlj1^6Ns@h;+$FwMBKATjeoeU_xl-cLZbV7`FcT2DTQmDeY{)(m32y2owJ_J9BX e|Ce7M#W3rhfUDs2Hzhzj89ZJ6T-G@yGywn@B~5hz diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/btn_special_default.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/btn_special_default.9.png deleted file mode 100644 index be66964f9ca8935388d316f7749f0eae7d01403d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 263 zcmeAS@N?(olHy`uVBq!ia0vp^!9Xm>!3HD)N|ZJMDVAa<&kznEsNqQI0P;BtJR*x3 z7`Q%wFr(8NlNmrk`4ZQNlHmNblJdl&R0iL~|zCrtr?dp zfJ*B;T^vI)8sFaB$a%nkhruz@IP*W}mdU}(3THi0RQabJJJUU3gWH<3-Nkc{eOj=) z_j^ESZ_RI^`XrwThK`bUW)kYcDIn%C7D-fw<>eVN|BXFS#HVbGSoT^DqQm_2%)S2@ Y+b?lgxTja{0=k63)78&qol`;+0DMnY_5c6? diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/btn_special_disabled.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/btn_special_disabled.9.png deleted file mode 100644 index d94e767b7fd755dffa727f24dbe0b7b2f3d2f28e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 217 zcmeAS@N?(olHy`uVBq!ia0vp^+(2x_!3HGLx)$pJDVAa<&kznEsNqQI0P;BtJR*x3 z7`Q%wFr(8NlNmrk`4ZQNlHmNblJdl&R0iL~|zCrtr?dp zfJy^AT^vI^I^SN|&C8&`!4goQ_HBN{+;h`Bcs70zE)I9BI2yX*iNYDJ$B*7kP)b|2 z*2%EC@aA_P-lU{Q{Dxs4y!$84nDImJT2StK!_^E7FRw9P;pWa)nXNP#Xf}hVtDnm{ Hr-UW|ecDI; diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/combo_disabled.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/combo_disabled.9.png deleted file mode 100644 index 7d4ae68b6a74f5f656c73d5bdba359c4b46ac08f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 347 zcmeAS@N?(olHy`uVBq!ia0vp^@<1%Z!3HE}TBS?}QY^(zo*^7SP{WbZ0pxQQctjR6 zFz}UtFk`mL=4(Jf`4ZQNlHmNblJdl&R0iL~|zCrtr?dp zfJ!fUx;Tb-bUvMK&3{;dr{#Ru(Gy1|DE|LHJvHH5OT?W{4%Muv=TF1-YPz(%Kc{5l z5xP-C@T`95)G%2;p_N+8GNY__L_D?-y3hOe>kH|_1~GhREYF``cXH?anDVZUE9N`3 z|D5{&L-!8%pXdU?#*R7H&d=F%ZI|VSjs@3#U5rqx=n+(Gna(C<(b6FCc;^RQ<}iZ| z5w~^Oq}E7oXli8Myf<{gl%}9A$r_G(JO;)yZt}2|P1_spmHB=9|D8*j?wyQ%7#F>2 pRo%sxTkRw7DPDi_q%yXO=`w%D{JHB60z-s>!PC{xWt~$(69CL`j0yk% diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/combo_normal.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/combo_normal.9.png deleted file mode 100644 index 26201421708f72eda8398b5854ae958087576e85..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 349 zcmeAS@N?(olHy`uVBq!ia0vp^@<1%Z!3HE}TBS?}QY^(zo*^7SP{WbZ0pxQQctjR6 zFz}UtFk`mL=4(Jf`4ZQNlHmNblJdl&R0iL~|zCrtr?dp zfJ(1;x;Tb-bY7i)m$%t~r{(;L_c@ZCyhcpYE~hl)ly(~&{K_fPcuT|n!MAxHDPQIa zmdPk~ZgzQcLq&6XgQL)-4#POvJ37zj`1m^)@BP$T{H`pa=VOK0*_u=J>(o`1ww%2q zQkO0({xIx8){kwu&dIAED6*``GV}`-bduoyeouMnm#Yn{l$Nr*{~J+p(t&pe=f9H< zx)K&&zeO>>-X-@s%HTp|)^G6)MrPTW@1v%%ezq~+d;4xm)WL>_E7|@8SIhEkx4P6${JKv{0eby33o;N`MF?hQAxvX|zCrtr?dp zfJ!fVx;Tb-be^4lnzzM($K`m&`zewa9laJbYpmVT@x_UCvw8r_E!Urk&s>xin>QEO zISHkAo-p(b(qo;gqVjOgZYzm35{rHOor`NfIrbD4s8+mb!hK*56!=(3s!k(9<07EUYEXrC5H8X>H-m- zIoG}gF~8m=_c+Ml!i}uo;wu=Lc~6$>o^Gm~xB6agTuRo#*ax~sw}Tj8KUr3=T6gM` nZolgTe~DWM4fl)!~# diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/combo_pressed.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/combo_pressed.9.png deleted file mode 100644 index 9d2739a79420f452bd71efef1dd5c3858bcaa9d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 350 zcmeAS@N?(olHy`uVBq!ia0vp^@<1%Z!3HE}TBS?}QY^(zo*^7SP{WbZ0pxQQctjR6 zFz}UtFk`mL=4(Jf`4ZQNlHmNblJdl&R0iL~|zCrtr?dp zfJ(1=x;Tb-be^5Qo43V4z$N`+Yl*YA$b*hW9U2E(bDZ8e%{lL?z+KY*r!iG2N4Ltj zYk@oE|}P&@~qO%dPn4C6VLA^CRf#Ec@7s?7sOuwd()(H`o9=|FPDtj zcSP#a<>L>nJ#h1bMDpcZIy=70t*VM#zUsrh?XA|&1)P3lJA?{4H59MY{d3BJZwJS} z(++wP7Hi(_WSf?H^Z3q$1)HvJ(+^-`)0&hobzHFazWCngy(gwL%|4KwvTZ5TwUfRN r!=klLiqDO^Jo%}xk+0sg>r3?=gEBmH{ZHHkdXT}>)z4*}Q$iB}H!Fz~ diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/frame_shadow_border4.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/frame_shadow_border4.9.png deleted file mode 100644 index e39216016c32842a136f1105c295b83c9da8dce4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5157 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 LmU4w6BJ6(vJ_5MD diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/hint_bg_lightblue.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/hint_bg_lightblue.9.png deleted file mode 100644 index b871cea83277e7a4c6f16782e665cfddbf46f4d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 272 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 O0000|zCrtr?dp zfJ&Emx;TbZ%z1m;kc-JspzY$#2dp}_y>B{gy4^pSh{-7?UJqiGUj5^6b?7NgJEq1n zLHgAP|3}&JUB4Z>!DYuBfA870EPuSV91+wljH+x9Jm%{yb5Y10%y)q>m)vyqma6AJ zp&a$7W17Vx)xL~QB|zCrtr?dp zfJ&Emx;TbZ%z1m;kc-JspzY$#2dp}_y>B{gy4^pSh{-7?UJqiGUj5^6b?7NgJEq1n zLHgAP|3}&JUB4Z>!DYuBfA870EPuSV91+wljH+x9Jm%{yb5Y10%y)q>m)vyqma6AJ zp&a$7W17Vx)xL~QBl*U-)48VqUw%Bp^e{*eq~Po0WB>oX zJvyW@$Pf4THKWEXh;#S+rvLZ%cY+oDK9@D5F~|?-p8OB<sL*9chJhDA`du!qU z|7X&M1s?U}aPj1o?S7;+J&li!7#`V#}2N?94P>|dVtY; z=FAzY;v)yQf-S}7K~RW;97An8LH+Mwe2ElyoZ{D zOUNDtc@UJOU>>CVKo+e4vPYMd>Y{j%VK@O;NP|2&EIo)V3k()F4Vw{k02vKyh)Apl QQUCw|07*qoM6N<$f_#6F!$q5H|{{=UEobl`b z|NZ6f@BOX*^TY6};fa_DKMPJbF#T^7GC8d9`QfySmy{&rWTw5nw|90@&*@G7Z|Ed1 zVCac5%euKD^~AKl^1R0uW=h6#KT3?5e{pLhL(YUh%cr&~6gxIdVsW3A#&GVhFW>0~ Sftf&y89ZJ6T-G@yGywoP-$rEs diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/progress_bar_bg.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/progress_bar_bg.9.png deleted file mode 100644 index bb2391fa344419fb8c653f3cc557c6a371867986..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 509 zcmVA4pa3MSMg}d_O=?XexT06LP0xYDJTD z;6O}f&i65iNhET8P>8vGXqpyJrBX=|ON7Mlz(J4Omqh=c@Or)eASS$|)9LSQHcPo& zjtYgsS&GHt&GD{9A9~RbP9l+r{*n+E-!Z9FDp9psrCO~<&1Ta{tJU%y?m!=U(eKK< zoe5+znJ3s*Divp8r_-TcuSflU-^pMw@Ez_zA9~RbPClO}aHT}KT>gNiuIpqNh6E3X zLno$b`VM!n5c>5E$-kj^D4p$6;p6d`CXU#94GT=2DjiZ$4cDs(D3P;IoHj|mp=XXb4&r&P{p5PwkJ49TtVaNh1bg@_j zjw;0>F7Hb|6PwNE6DL&xEM6{`p@n5w1Uztm-pxeMn83F{l~}D-f#a0`2gl&55>eZ> zb@l#xcfv3H(oP`YfqVX?B6{5K_d6``N(9{nRRYK0fOq+mNfbXE4(4{drS*C(AFQCy z0)jsDq92^=-)^Fq$g4=3!X0h5Hx~JaK|u>now-^Q&8r=l00000NkvXXu0mjfY>DO~ diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/progress_bar_bg_v.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/progress_bar_bg_v.9.png deleted file mode 100644 index 3f6235849d28b0060416df294848420d51251f2f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 538 zcmV+#0_FXQP)Px#1ZP1_K>z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUzm`OxIR7gwRmRo89K@dd+Aq&Vpge)K%$y&08{DmyS>>yu?iVq|z z_+sLF#`gmR1DS~4)NSab$1pm?`H2JdH+8smtGlWrk<%aK7e??8Kvd#xy5mrA9VbUJ-|lqShHuIpN}*$j^3s2B_e=yW=;EQ=uI^LeCFsV4zn{elS~ zw%u;ur_(7WlL^M-F+>T5!y#RI62FvspqM6QYt?jv0iQYG^XOX*3$jV1fL!U&`@7mdmAr5qu0Ho_HZl(#d`h zc8Mj?Tq^N}5MV;IFWTHtA%#NWd?gnS;W1I?LU$%ecP`wM$p7}_=mj)y^Wi8sd5g`V z^yhgJ#$*d+#)dNO&)+*7`)6-Jy*q;J;#@Ar?e`du$D_WB{oqybA+Lgcy%`KdH?_b diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/progress_bar_grean_v.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/progress_bar_grean_v.9.png deleted file mode 100644 index 35a39f8bbafec0e4d5054bebe72f9591edca113b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2982 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 diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/progress_bar_green.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/progress_bar_green.9.png deleted file mode 100644 index f4b176d45bd589310983c2b015e4db305c5fc76d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3038 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 diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/query_item_bg_2.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/query_item_bg_2.9.png deleted file mode 100644 index f52b415673a34a27fa347071919eedf7450eb8af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4076 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 UM}NrV<%0^eAL!q&(y)K|KhqJ#DF6Tf diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/scroll_pane_bg1.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/scroll_pane_bg1.9.png deleted file mode 100644 index 010fb17ca587fbd4e8cfa0d19f03e8e9db196100..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 247 zcmeAS@N?(olHy`uVBq!ia0vp^azHH2!3HF=|Jn-zDVAa<&kznEsNqQI0P;BtJR*x3 z7`Q%wFr(8NlNmrk`4ZQNlHmNblJdl&R0iL~|zCrtr?dp zfJ*Z`T^vI^I+Ifrc>W15WRp%%(XcFj=2OJ0&b?&$a$}>5mz`1$G@a?}=~=Qe_4IW8 z_RZ{Pjx%Q&#tMsVI?BxCrYpB~M%aV@4v{tmsb5cQk;rfL_3mb8>4~z*GCa%RmCV1> k&@I~_!EPB#z?Cp&2F=~P+DkeffV{=v>FVdQ&MBb@04hRGS^xk5 diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/shadow1.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/shadow1.9.png deleted file mode 100644 index c2c135c46718781b54ecd0d90fa413387fc98c55..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3086 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 diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/shadow2.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/shadow2.9.png deleted file mode 100644 index 304cf82c23dc43817e3a77465daf655778fb0df1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3984 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 diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/slider_track2.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/slider_track2.9.png deleted file mode 100644 index 10c0902732926d8f369a001c65cdbd7843af422e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 238 zcmVCy{$gbq1@W^i#4jU*6F$leQdauHtN2W>hy)%W1P1o8_p7R7N$ z*m0Cnm!@fMZQDMz)+7lAESUL#uIui7-_tmbWUUni0~XBuNrqu~Ip=6ySBf!;f&mL= zKEN2WdGE#eH&`(9o1~QNJkPW&3xyC)!`KT07Mm`=!M^VmFT`n@Hoh83f&q)o>+ioL oD!GcQxrea&W0l2;p?^2L0e$x!#EWQK0ssI207*qoM6N<$g00wMQ2+n{ diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/slider_track2_dark.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/slider_track2_dark.9.png deleted file mode 100644 index bc63449af6cc5ad39e5fc55cb1176a69c4e26111..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 240 zcmVCy{$gbtp-IJmfoA0(hAxc35`T!g3Z12r8S+xLb4k|Dnkk|a3~ zlsivR6qm9rZ^oEsRaMZ81}&QL0Cip8o2Eh6b+Fc|MuQg3c;#)|zMOMdmIWaM)o9S7 z84oZF!!}KmI(|fp=J6)5uB#o#5%WC5d#?s_ZyL13bny-B`<}@{==*+?tAS=TXo-3K q{yQL*GAWlH%HbhDX5mONh7w*U42O;_HLjoS~r{vW#Z z(I$|2$icwwzvRjLu6%;#w+sMb& zK2SOE%so8^^AA@ZWy&m7P$-;ebOqpxD@E(&bC`Gw=Q< z7X$TQPzbIxhXxBGLV=hMh-HCT6^PZyz^YLFe8>@sYyl_KOT1)Y9;kk11~S2aQWOIK Xoj+&uUZAbo00000NkvXXu0mjf;!}i6 diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/slider_track2_forgroud_disable.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/slider_track2_forgroud_disable.9.png deleted file mode 100644 index 65cf89d1ea4552d6361b8b88996447d3a9dd91df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3003 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 diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/slider_track2_forgroud_v_disable.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/slider_track2_forgroud_v_disable.9.png deleted file mode 100644 index ecd9fc6b4bc30b0392d3eb6941b556bb7f8e0cac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2947 zcmV-}3w-p6P)004&%004{+008|`004nN004b?008NW002DY000@xb3BE2000U( zX+uL$P-t&-Z*ypGa3D!TLm+T+Z)Rz1WdHz3$DNjUR8-d%htIutdZEoQ(iwV_E---f zE+8EQQ5a?h7|H;{3{7l^s6a#!5dlSzpnw6Rp-8NVVj(D~U=K(TP+~BOsHkK{)=GSN zdGF=r_s6~8+Gp=`_t|@&wJrc8PaiHX1(pIJnJ3@}dN|Wpg-6h_{Qw4dfB~ieFj?uT zzCrH6KqN0W7kawL3H*!R3;{^|zGdj?Pp5H0=h0sk8Wyh&7ga7GLtw0fuTQ>mB{3?=`JbBsZ3rr0E=h-EE#ca>7pWA znp#_08k!lIeo?6Zy7)IG?(HJI3i#YJh}QRq?XUb&>HuKOifXg#4_nNB06Mk;Ab0-{ zo8}<^Bt?B|zwyO+XySQ^7YI^qjEyrhGmW?$mXWxizw3WG{0)8aJtOgUzn6#Z%86wP zlLT~e-B>9}DMCIyJ(bDg&<+1Q#Q!+(uk%&0*raG}W_n!s* z`>t?__>spaFD&Aut10z!o?HH?RWufnX30 z)&drY2g!gBGC?lb3<^LI*ah~2N>BspK_h4ZCqM@{4K9Go;5xVo?tlki1dM~{UdPU)xj{ZqAQTQoLvauf5<ZgZNI6o6v>;tbFLDbRL8g&+C=7~%qN5B^ zwkS_j2#SSDLv276qbgBHQSGQ6)GgE~Y6kTQO-3uB4bV1dFZ3#O96A$SfG$Tjpxe-w z(09<|=rSYbRd;g|%>I!rO<0Hzgl9y5R$!^~o_Sb3}g)(-23Wnu-`0_=Y5 zG3+_)Aa)%47DvRX;>>XFxCk5%mxn9IHQ~!?W?(_!4|Qz6*Z? zKaQU#NE37jc7$L;0%0?ug3v;^M0iMeMI;i{iPppbBA2*{SV25ayh0o$z9Y$y^hqwH zNRp7WlXQf1o^+4&icBVJlO4$sWC3|6xsiO4{FwY!f+Arg;U&SA*eFpY(JnD4@j?SR-`K0DzX#{6;CMMSAv!Fl>(L4DIHeoQ<_y) zQT9+yRo<_BQF&U0rsAlQpi-uCR%J?+qH3?oRV`CJr}~U8OLw9t(JSaZ^cgiJHBU96 zTCG~Y+Pu1sdWd?SdaL>)4T1(kBUYnKqg!J}Q&rPfGgq@&^S%~di=h>-wNI;8Yff87 zJ4}0Dt zz%@8vFt8N8)OsmzY2DIcLz1DBVTNI|;iwVK$j2zpsKe-mv8Hi^@owW@<4-0QCP^ms zCJ#(yOjnrZnRc1}YNl_-GOIGXZB90KH{WR9Y5sDV!7|RWgUjw(P%L~cwpnyre6+N( zHrY-t*ICY4 zUcY?IPTh`aS8F$7Pq&Y@KV(1Rpyt4IsB?JYsNu+VY;c@#(sN31I_C7k*~FRe+~z#z zV&k&j<-9B6>fu`G+V3Xg7UEXv_SjwBJ8G6!a$8Ik+VFL5OaMFr+(FGBh%@F?24>HLNsjWR>x%^{cLj zD}-~yJ0q|Wp%D!cv#Z@!?_E6}X%SfvIkZM+P1c&LYZcZetvwSZ8O4k`8I6t(i*Abk z!1QC*F=u1EVya_iST3x6tmkY;b{Tt$W5+4wOvKv7mc~xT*~RUNn~HacFOQ$*x^OGG zFB3cyY7*uW{SuEPE+mB|wI<_|qmxhZWO#|Zo)ndotdxONgVci5ku;mMy=gOiZ+=5M zl)fgtQ$Q8{O!WzMgPUHd;& z##i2{a;|EvR;u1nJ$Hb8VDO;h!Im23nxdNbhq#CC)_T;o*J;<4AI2QcIQ+Cew7&Oi z#@CGv3JpaKACK^kj2sO-+S6#&*x01hRMHGL3!A5oMIO8Pjq5j^Eru<%t+dvnoA$o+&v?IGcZV;atwS+4HIAr!T}^80(JeesFQs#oIjrJ^h!wFI~Cpe)(drQ}4Me zc2`bcwYhrg8sl2Wb<6AReHMLfKUnZUby9Y>+)@{ z+t=@`yfZKqGIV!1a(Lt}`|jkuqXC)@%*Rcr{xo>6OEH*lc%TLr*1x5{cQYs>ht;Of}f>-u708W z;=5lQf9ac9H8cK_|8n8i;#cyoj=Wy>x_j1t_VJtKH}i9aZ{^<}eaCp$`#$Xb#C+xl z?1zevdLO$!d4GDiki4+)8~23s`{L#u!T(R5(v#U_b@`fm{&A3z&eitU$~T z#UM6F3;`xjo-8tZ_U!Cgvt~^LfzHm(d>?NgMW6}}6vYb`EGXN#bLUJDUbk-D%z5+X z&1`RPuLUX+gxUf&_5Y$pi)LQ9aAD@=&6~jrSFT(+v#+mjCQwcc>I{Mk#i7=ZOoiZR z#TSkvGk8!^4+AJY?%1(o=JxH|XRcYZ29_S{(9Q>IMm@95~r t@%HwX$4KGOOaaOtEO_$_Que`_3juj5H%^7(>{I{%002ovPDHLkV1hm)nn3^n diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/slider_track2_v.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/slider_track2_v.9.png deleted file mode 100644 index f4c1aa5a1983e69131011d8aa7a7d331e007624c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 303 zcmeAS@N?(olHy`uVBq!ia0vp^oIotW!3HEXq_67%DaPU;cPEB*=VV?2IV|apzK#qG z8~eHcB(ehe3dtTpz6=aiY77hwEes65fID^w3zopr00b~;tpET3 diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/slider_track2_v_dark.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/slider_track2_v_dark.9.png deleted file mode 100644 index 5d2eef8e51f7b8673ad74af69baa168454be8650..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 313 zcmeAS@N?(olHy`uVBq!ia0vp^oItF=!3HD`7zMopQjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{17O!f%!WnidMV_;}#VPNKSzVyl0`?tsT`9%4d2l&?HzT6u@#SazdtlW2ix zP(|YGr<@1hoiW&^tCH69w6gBmock>T>z8G^z2D2L7{f5<8oO&?%J%DkaLgs)U800Tym0gJ@C-Ko7x%*jzHYVr zP`G==XZcg+shZo4&&ip7R=6=y!(dbYfr{=~kz(HKA9FsL_I$IkuGc}J7Z^NU{an^L HB{Ts55l?d1 diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/spinner1_bg.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/spinner1_bg.9.png deleted file mode 100644 index a3c00dace862667a1a3f5c7d0a719feb2b58b135..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 295 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBI!3HG#&i#1_q*#ibJVQ8upoSx*1IXtr@Q5sC zVBi)4Va7{$>;3=*EalY(fD?jHD7~*$bkbDVHUzMV&;$AEpD}3_j?pFTb%84QI)aU`!J>bd~3H} zwXgD8Yns1>#pRfrI*^F&pA|yNAesJ!{?T9f~UnEe+l=0zd5A%X2ymG&^4Qhcd OW$<+Mb6Mw<&;$VHv|@Gu diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/spinner1_btn_down_bg.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/spinner1_btn_down_bg.9.png deleted file mode 100644 index 6b46f36e93fb1cb60f77ed1e365c2dbf2e626ba6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 322 zcmeAS@N?(olHy`uVBq!ia0vp^B0wz2!3HGny7cS=QY^(zo*^7SP{WbZ0pxQQctjR6 zFmQbUVMeDlCNqG7@+GbjCBgY=CFO}lsSLh}$wm3OsVSL>3T~N2spa`a*~JPLTQe?I z0G00aba4!^=zTkRH*d3n2*Z0tE{zp;1x^aLbWQ7dz_*EYVnCMx(B9}F2ky>4vo_%4&9o(dKHs`(vgO~#~rVt`mgq~x-Vk*srv8W`Ocm8 z-B&%oO`n%JOF%GWYEryGO#65L8}p*pY<;p@CR_LJ&fAx+N}C+JAR~RrxAb OVDNPHb6Mw<&;$Ve8hLR5 diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/spinner1_btn_down_pressed_bg.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/spinner1_btn_down_pressed_bg.9.png deleted file mode 100644 index b80631648fef07e94ab52adac34ff9aa0ec2c00e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 366 zcmeAS@N?(olHy`uVBq!ia0vp^B0wz2!3HGny7cS=QY^(zo*^7SP{WbZ0pxQQctjR6 zFmQbUVMeDlCNqG7@+GbjCBgY=CFO}lsSLh}$wm3OsVSL>3T~N2spa`a*~JPLTQe?I z0F^%Vba4!^=zTlIF{{Nvz%{;;_nyOx+O)@cMU3Wt?+g+-cr2%`K2uxrR@SC*!H4vT z76}=-&YRA}i>-Grzy*@s5-4rB0dnhJ=cm&gN}iubnBF zE79h=cxG&`4fE>DKGPm9YP-+>X2Ju0acj>>7tFWct?hru>k|B0!}Q?+pobYeUHx3v IIVCg!0PtIpu>b%7 diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/spinner1_btn_up_bg.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/spinner1_btn_up_bg.9.png deleted file mode 100644 index 90e1b21c0586fd634b021ff634facee98990381d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 309 zcmeAS@N?(olHy`uVBq!ia0vp^B0wz4!3HGVuAW-~q*#ibJVQ8upoSx*1IXtr@Q5sC zVBq=y!i-L9OlANDEak-(ff9?FV`Uhf!6ySDZ-mpm7h_4PyA)^b6YqQ6vG0B08?KVr_C$$ik0yzRwR0Vluy~%Z*0pxc^GDaeX2y4&lJ)=N z#(%Z7yKAr8ic@7$P8?cJyRNFss|X36T=$&GXzG?32{|7x0^QBv>FVdQ&MBb@0CR|S AasU7T diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/spinner1_btn_up_pressed_bg.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/spinner1_btn_up_pressed_bg.9.png deleted file mode 100644 index 2a72c92bf2d82889b565d7b6fab165cd3a462e3a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 315 zcmeAS@N?(olHy`uVBq!ia0vp^B0wz4!3HGVuAW-~q*#ibJVQ8upoSx*1IXtr@Q5sC zVBq=y!i-L9OlANDEak-(ff9aBVUt&fa`w&gGqWH^lW+K8jLqi-+O|0L+W+zg1)x5JA#_UqP9p2 z-_N@AXOHKs`HD7)I~0%K&YqU$9DCh+lW$0<>&x2NQ;gb#Jw;B(OT@l-byNE6N=~sV z$uA9sG7G2vi?i?*o)V-BG%oD&VAW|M?5OyHRt3=5Mf>w(mp_ z%W3zA%5{s|FSa@!y{FW3YO&d|85&MWeA&E$hQ`(VpR=WE=(v4eTA2@YJ%gvKpUXO@ GgeCx=4R)*m diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/spinner1_disable_bg.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/spinner1_disable_bg.9.png deleted file mode 100644 index c8c1f57362475cf7cab7519c9162a848432fd9d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3260 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 Hu0mjfUyf|C diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/table_header_bg1.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/table_header_bg1.9.png deleted file mode 100644 index 878f78235df75f210829b0821fa90a97f0c0d88a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^+(4|t!3HGb!wwt;Qk9-Ajv*Dd-d?ukI$*%#5_tcA z&c4>@=I>hrxrCP*`Y3s<;;38NZlzhu+bA}x_)y)Rqscroc)s6DG`bVje6nDzsM_JB zA`*}17{94$*j*9pr+F~N;uyzohIWC3p1t2U@NX#Q`(_swmF;9`c1)ma^ diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/table_header_separator1.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/table_header_separator1.9.png deleted file mode 100644 index a2d19c6e8a5a595f932f2931c71e255d2a7f5a99..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2869 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 TZVDS400000NkvXXu0mjf&UtcO diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/table_scrollborder1.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/table_scrollborder1.9.png deleted file mode 100644 index db0ef88720a97fdc46d4dc75fffdcbd477433aa8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 319 zcmV-F0l@x=P)X1^@s6zs*Ol00037Nkl8Md1B3IpXb?{Dx@Db8E9?w-PvCJT}q5trd}- zj^l^{mVpMY>$)5SL6M?Q3QQ7{#3a!qk>|M)2_hP;1P>|!?%yj>DVxF3LDwE?O58K78c}ONj zrc0;DEN(Z8uCmb3x>JTm4S7gPw@EAA;oLvI-|zdJ@8^8p=k@-c&o_@qIE2tP(S|@E z2ro}}AJr*TtrJ?Bs=f643>pI20D8F}@TCpUO9M%P$B~(!)<*Uw+v}{zC$nGnd{dL1 zm*42<GV{+u7L!2yNx)Uh9om$jqX{syiatwqV8ERDzpop#t0Y;CP)$WpTXQC3<;V(6E-7M>_v2kVF%!O3xRPVD^oH`r0DZ5+w5 zJ4~H)PMb1fG_Y?)o+8^#ObBZY7lyxJXr|K!g}ljr?^vppcn;%7Ua2^oG8eNXXc^ok zcOqs@E#g;}uHH?iO!VGPyJ8?i(Mx@zB+Q8R?r^_YUOdsf4R=}=&@vgOpg^zpf!&Ov zVey55A)tO6-kwi2)iT(xcc-aJaym!t2Ke|4)L{3il< zn@m-UcBYGa$p`$A4LNEW+NYfdLk-6?By7%-4z~(WbxyAXDx@}87+31ZjB-Uh0V)K8 zmsEn2G6v9#tIE4NpwZnTJ+5&sT%Cbi7)HRY6kkhGK$RM*phgd9K)ySswiapne93c zZu`R{&G8F{!o{<$h&n*?>pm4lzDSUP^c#y<=V5_CP)QtIzL!r^U!%|53f88Mg|F4Q zAs1*;hCI^*x5{1Km1)QV1r)=JtKLd_(X2UqdK-RWv(R{z!C9^=3?zTV{vX-&zCQ8+ zKO}i7?a}lA<7f4H@q(cTbd|v2UQT?k4O(+Ou!7aV?CJnQvp>;L==B3AUIyq8$KqH} zFwxm)g2@|ds>qjL zb=F(Lu{zxQ&dlZ-Ahf5S^jFuihN-4OnPKtbUJn8}qYXIdamoA2Eam>*M0sGMj|nyf zH;4O#Q?_1sHU(H0R)nOVId2QTH~FVzj0V#=Kjczs!J%;CIcGU3oV1aL7_ih7RKCV2 zj*rY-E_qeR&+DgurYYypirDD8lmYucg0dfsnyn9rg5oQ2BDU{>TWt?THNmQ!SjYk6 zLxpd*bi;%NX~BJZByLrzj*+sDU575H#JufwoCr`>*wrspDAPsik2EB2LVbHm=;8x}v`6Qy3>@p3stf03`c z_RvS=%OmI6o8OOpccfzSUu>!we}-bX7~foo>iCc-_$^6k+_$)hn2aJ7o_)AtcSIi*Ajhuwv^=+7Y0kqsOMdE1{Ji7cho&6@%VXm) bi}ufBL%a|<=L%GRF2w6sf_vk^Q(6B3*z&Ry diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/toggle_button_rover.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/toggle_button_rover.9.png deleted file mode 100644 index 85aef0fc6a235b7c766c2cdeb85c9ef7ef92b121..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3658 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 DUe#SG diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/toolbar_bg1_SOUTH.9.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/np/toolbar_bg1_SOUTH.9.png deleted file mode 100644 index 707e93e8d23caf845070553dabdc4a44dc63b700..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2898 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 diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/question.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/question.png deleted file mode 100644 index 8d76136f5e0a3b83e5fcdbff2114d59839a0e6cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3393 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 XC{KM)lRHY500000NkvXXu0mjfzyoTd diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/radio_btn.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/radio_btn.png deleted file mode 100644 index 0555fd6c010e7ae714809bc07ec244ad0399e877..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 772 zcmV+f1N;1mP)$$L0&@v2S3d2i+Se&Z~EOXfZ}SR8h1jSu5ftPfc>{AG6B}YuXfB z=3u{Le#!UqJbB13#Bm(FW%=GT{a*l_S0j~50RSXP+GULGFvh~RZF2w+2m~6G(x0JF zD5GiGx7IVsWU?cNxX+*!tSHJ>rBc~53`0mH5{Sp+pp@d}nJm_%pm%EM_B-2w7cS#n8}D*InASja)8=`}=!mZf@>_s;UQWpyLb_McKN% zyv(kxt&xq54bSl3uL_%+n^;;}BE@1ct0>C*)*?NDN~N+Fi9|>=8ubiz*ZllEL{TK= za(Um~YXc-n+I@b07FJePUL6hqKA#Wk>+7gitAZ@cUp;|pwfadEMGOxQ_XPj|$8ngM znE_*L#}hCNV@i^wzQbE3iXsfdnDPWH%i=~xMg|7P#>UY4R=NTJ&}cLU1_&V?*V+I< z5E@TUPXhywkBrN~d+d4TpIdtFSIj$EM z7vGi3j7-OFq zV^fx8aR9*ce1lS|2ZO=P+1XjTTX0X{Z`S|+)Bgp!<_QmwJ$9u40000z-D(;^7>3`eBDls;A}9(j{*ZM;45;M5 z8%f0*u+Wq?w^H#S?F~qpJMnNaxGRBOH70Q-L1)e8Ae(GYD#XX0RVy^95cp_48us7rs)L$j^nIgFsOw>p@yO;-{*6x)#?(5 zIPYK%7Dch5>-vdd7~yO-i)=OvN-1pH24f7eEaU3x3LM8xqS5FlS(bmTk}L>b!c|pm z@;pxpg#x_Z)f+WU6Ott1`uf^VrBYQ{mQS66r8^Ksv7%{Ovsf&WgM$NC_@ARfxm?EH z-X2j^wJD0?$N3^%1-h=E@H|h_>9i}@nVp>-B$G*^>-rC8Z9yOi!trc23-9mmzZnhy zgbCcl1*@_k2m}Jw-QC^Bu-n^Pa2#j33Mi#&zu(_j zaCvzNN~!vqpfMN>U|AN{jcJ+~4u_zWHe3aYqSXC<|3s1`JU>6LC1|(X*xK5fD2h^d z6#zgq8m(!XW}ly*zX@zv79>f+a5%JMu~^MnUurb6ET4&@h>MGh(}#x#lF#SCaokGy z-BJR za|250Bo>R+=I~eBwNnBBxm@lmW9$oKEdBDsp_Hn@V6f5ccI&IauL}NV{{K(^H-01t U>;5(UYXATM07*qoM6N<$g0_80SpWb4 diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/radio_btn_disabled_selected.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/radio_btn_disabled_selected.png deleted file mode 100644 index d6b2a45e6515038ad1b0d6993b6d64e122d2d052..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 843 zcmV-R1GM~!P)z%TC)s6o&tSz``gKH;8bNuwo({M}XuY z7Cb`ts6}}JDwV3`0lMS`T4h1|0udls^9%>T`t<1<4X$HCv!z+ZL$7l26EM4?as04R#G!8u8^omtg7m&VHjJcX^N>-3aL~Ilu|g31I{^gUB~tHH3UIuB@&5u zx~}g8K{^0_bH-Rfk|d&O8X}S4gIbn_qoX6-+}t?HWHP7g`gS*h6}&CLDc{C z^2bP$1kSnapYH%zmKBM`V&2%FmN5BaMn^~C_DUcC0G^+pUo`z4bpS?2M(jqT;f>wD zq@VmTcXxLX1i=mkP)gaw#f3Ls(K^x@D1Xe=)fFhE9fj)#D!oHk++Rqw&grUG#KvB9T~QjBO7M z4H38DG7};`zs?4p!nSQ3A0MMytva$SulZ{j2+(zXS5;Mv ztASG58Xq5DbIto+*WC~RNT<^uIp-fZ=d%C7p_H;{G@3s>J^dPF+!ydC_5VNmKLD$+ VM)jKE3|asH002ovPDHLkV1iHdbgBRV diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/radio_btn_over.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/radio_btn_over.png deleted file mode 100644 index e61b940bc493d60521ae8b5d8750d12fabd72f8b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 785 zcmV+s1Md8ZP)z&r2d<7{|XO(kmdk|{6R;(gdQx!AjF`9m*{;v#NK}f%WxuNRouNw>L1x5Rb=EEEZw0 zSn3N43t!^#cxtGGbN+kCvJ6?4p{lCi<#Kfo4-a{>+2lsiG>z}??{l}?-Bnf9FUxWd zk8?gKP*v6McDuWoOvVu0pHwQvT`pHQ91i>XB?C36R4P$LQG~U%wNdMc&CN|bJUj^H za``8Kl;IT}9UbkhuCDS%qcQU7^|aeg;Hrv>O`T2S1-^x${0JPifu?2!4 z49xWiEEY?rTCI*PxWB)LD2g3Jfh0+fxm<2+L7`9pA>`3eKnRKC^Leydtq;RBO~cjI z6$l{_LqQ^u2#cavkHunmeSQ6q;N;{4R;#t1NF>6B0syev?K|0QmY<%Ujs$MCT8KuY zxW2yTi;Igp{p$m*;{5zPy}iASi;Ih7tyU94p%7+fW`@F>%_a^G4sd&W%RL^C|Lp86 z-M`1MT?d0fZ@FBKJwHEBIUEiwFE3+mZVo1s33qpQxV*f?&CLx6A@!xDr5zpK->wG) z?WCHv97OVg`We>FJInNsm^mHIh!J!^6OT6#UKn|3Cd-AT778YKi*{ P00000NkvXXu0mjfRxM_m diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/radio_btn_pressed.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/radio_btn_pressed.png deleted file mode 100644 index 59ef38126bd6176ab4e639124d58addd3d52eca4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 796 zcmV+%1LOROP)zZ%7ki9LK+Bg93G%rDrwgTGI{JKMJ9e zl%f~;PI^(JUQ}3UXr&oN7$Wtq7rk%{(}*xAhgnFH3I%4)VX}}4-STWLb%|cVc56$` zb5AegKzE+Zl|f&)7x(<`KA-3KaleNmgkU8Tx1#iaA&^NG~#vw>DvZrfZn!aIRmCq*18vIheA{QfN_yL+;ZVL4^tUOi6i&V-&; zfDaQ4vmDG_gLv-pLY`!-X8)p#j4Nw2}g^FC@!OPl;KuOPvhi zUs+TD0CRsZo8l-+yf*(PeQg5YAm<7)UMxm$Wo}~nq z&Y^Lz-=~%h_xeI;9~^@rRcVnF)OI_~>ZAmJbz48C`MG5YZoYU2U9#L?+wC+<3IHHy zGhNi-93$7;`lAB>_{rl&dp|myUXq)!z9_OT5?Ee2n~!JfOpR~cI*6l8aAR}y9PVe$%vzX-cKx^ zy!D`y8Hb)$`13M06bbOiaV;qjQj%x9z_8pohUK&i4xALZCnH5+sqb-_7XvRT_?!9v a5B*z%TC)s6o!98fCVvlSO5Zqg0Mss5RMU- z1rV`7B0NBg`T|rcQOh2d@Bl?#(7pfy9)Oeu3)p}VIEF<4StNp3+=OO?y&{2hQR2o) z98{@P>eLjzfyZq?Q4|1xBuTTB(iuvr&$28J0C>IL3?U>* z2vIam`!}g1~va%9BpAVGM znR0@T-rn9kfa(e_l_QEGD5V{)0@E}-4Gj%;dpmDg+#)}xsi_IMyHZjB0GUkYRp_6D zLr_;&m$|#Uv)j2-QZDjyZfw6xu~=+97!2b0_;}T_EN)<606fo^gg-t$Vry#)sZ=T(2n41M4-eN1 zb6lV6zP`S9sZ{E_X_`WNdpkNiJJHzK2#(`$b#;Zavol;?UV;$9+S=NtbMUgyb)f_R zBuV;ADUC43I!x2_007VP89@*df*>eIM@LJgz-0x0Gyead{!eN?LEX`CzC{24002ov JPDHLkV1n*UgR}qu diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/radio_btn_selected_over.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/radio_btn_selected_over.png deleted file mode 100644 index 869f434935fb4050393ce65841fb2dd9d855e8dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 893 zcmV-@1A_dCP)zPe>wB9LK+7;xT3~mPE`Gx@3ot4jNWa z2g{&>0hOY&3tO$xrAsH#?uv(YZ$T0&9V?d(fkq_6I6-)_^d-U6!Ho`eF=r3u?D%Ku zvb(Tfn8SPTH{Z|v-uu1ZFtRM;Z%X%9-TwtZueD&e+W`O`k7t!qxwIXgRR@nM?Jpl-adu;3L%ajRG?vOLdYc6JsV$KmDW1(Z_6VlkYa zp2B1@Jy@;Q&#_o6(H0`ha>HY@*$@tgy-ugI76=67$HzxmOOhnXfj~fZxm>kyIPA6A zY%PA8=6id4n#RpaBoeaI>8wQ}5l=Iu5WC{`{qlXBl zasYsijt;D?t)W~lvtF;)uL-!hx%uL7IKZ;3^5vnF*qo%IP)bDl4QwzN;BYuVDP7V8 zlu9M@+}xbXAg5{GE@on40;N*PtO<}LNk1?!pp4V1ZPAiC#$vIceplK80H9W@eQ2sB zhGAOf8UQAfsVWG9GOkz2ds4?-US7gzG*&eM9LE)pkB^n{#+3C#fI23fPJ<9q)C3Sh zqSr8w1^};hA57(x z108z!Rc6Ks;zhBAZ$Fi$!7SGSm*xug8 z$;pX4Jw5Hq=kpEgEr8wK-Q@iIJofkZFH@}{`B;OP$-1+^K*G-X2!d- zvy*I&X=&HM>sBo;F1iIl_2$cbxWLiT5wh7V2q6zcLqop0 zd2_qg1k~kryT6vpzUr19?9LK-crjgdRuuV-%r_*NSpNT1H zN|2yI_7WyV^-^l6l$3#iM8zU{Oh#$ZLl}e;Bq(tPQEW9=4y z_TYB8bN9|3GUx~Q;hgik-_QB|&hPvVLDMu=)52C&{a*kCd<$_G?gIc$7AP8qomAb3 z)15R$c?1BkSrq9_kqF1qq$2g5mxDL_|4d&y8l*!kKLfw;siO2sqt($$I^E)9d8s(E zQx3UA2=5||5hsOPdJCQoO(H=Y<=Q2Sskx;$Yq%f*0JeBX-{^w_nTf>3eL0AX;0|<( z^5FUt6P|sXq7N!%hgRinG1 zXLteRth=^6BN3u?5zNl7YE7K^2Y{~fbl33$h8>jb#I9{Dfqq_b zE}!y@M34?j#tWEqEeN*7h?%jDl@>l@`(!6X!+%#e0RZsr=dTq-`HUclpt%6RmW}JZ z?c|L$A78_lWlU!}G z%>}Fn0oq@vq;1;#`*zdeTlG&P}PjsWW#j_u*~V zwZ+>j45Kr*C*~K#d(z^tf5%p2#Ycl62)rJ1;NiP5=!T~umx^44$uZS_@sRC$IRpTz z3KgeGr@NkXx@A+;g73kJ@}@|H)|5>f)OQU-EnLDO0e{o}|408f?Qn(60F&PM00000 LNkvXXu0mjfIFzu^ diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/slider_tick1.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/slider_tick1.png deleted file mode 100644 index 5517c7dba3566534548c60af0d74c4b084b10ec8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3235 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 diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/slider_tick1_notrangle_dark.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/slider_tick1_notrangle_dark.png deleted file mode 100644 index 230f576e39aae7d3f0f75d11a1ac1fab01822ac8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3363 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 diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/slider_tick1_notrangle_v.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/slider_tick1_notrangle_v.png deleted file mode 100644 index d875bbe464e19075a47ae2bae8feb4292e5c7fde..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3179 zcmV-x43zVUP)004&%004{+008|`004nN004b?008NW002DY000@xb3BE2000U( zX+uL$P-t&-Z*ypGa3D!TLm+T+Z)Rz1WdHz3$DNjUR8-d%htIutdZEoQ(iwV_E---f zE+8EQQ5a?h7|H;{3{7l^s6a#!5dlSzpnw6Rp-8NVVj(D~U=K(TP+~BOsHkK{)=GSN zdGF=r_s6~8+Gp=`_t|@&wJrc8PaiHX1(pIJnJ3@}dN|Wpg-6h_{Qw4dfB~ieFj?uT zzCrH6KqN0W7kawL3H*!R3;{^|zGdj?Pp5H0=h0sk8Wyh&7ga7GLtw0fuTQ>mB{3?=`JbBsZ3rr0E=h-EE#ca>7pWA znp#_08k!lIeo?6Zy7)IG?(HJI3i#YJh}QRq?XUb&>HuKOifXg#4_nNB06Mk;Ab0-{ zo8}<^Bt?B|zwyO+XySQ^7YI^qjEyrhGmW?$mXWxizw3WG{0)8aJtOgUzn6#Z%86wP zlLT~e-B>9}DMCIyJ(bDg&<+1Q#Q!+(uk%&0*raG}W_n!s* z`>t?__>spaFD&Aut10z!o?HH?RWufnX30 z)&drY2g!gBGC?lb3<^LI*ah~2N>BspK_h4ZCqM@{4K9Go;5xVo?tlki1dM~{UdPU)xj{ZqAQTQoLvauf5<ZgZNI6o6v>;tbFLDbRL8g&+C=7~%qN5B^ zwkS_j2#SSDLv276qbgBHQSGQ6)GgE~Y6kTQO-3uB4bV1dFZ3#O96A$SfG$Tjpxe-w z(09<|=rSYbRd;g|%>I!rO<0Hzgl9y5R$!^~o_Sb3}g)(-23Wnu-`0_=Y5 zG3+_)Aa)%47DvRX;>>XFxCk5%mxn9IHQ~!?W?(_!4|Qz6*Z? zKaQU#NE37jc7$L;0%0?ug3v;^M0iMeMI;i{iPppbBA2*{SV25ayh0o$z9Y$y^hqwH zNRp7WlXQf1o^+4&icBVJlO4$sWC3|6xsiO4{FwY!f+Arg;U&SA*eFpY(JnD4@j?SR-`K0DzX#{6;CMMSAv!Fl>(L4DIHeoQ<_y) zQT9+yRo<_BQF&U0rsAlQpi-uCR%J?+qH3?oRV`CJr}~U8OLw9t(JSaZ^cgiJHBU96 zTCG~Y+Pu1sdWd?SdaL>)4T1(kBUYnKqg!J}Q&rPfGgq@&^S%~di=h>-wNI;8Yff87 zJ4}0Dt zz%@8vFt8N8)OsmzY2DIcLz1DBVTNI|;iwVK$j2zpsKe-mv8Hi^@owW@<4-0QCP^ms zCJ#(yOjnrZnRc1}YNl_-GOIGXZB90KH{WR9Y5sDV!7|RWgUjw(P%L~cwpnyre6+N( zHrY-t*ICY4 zUcY?IPTh`aS8F$7Pq&Y@KV(1Rpyt4IsB?JYsNu+VY;c@#(sN31I_C7k*~FRe+~z#z zV&k&j<-9B6>fu`G+V3Xg7UEXv_SjwBJ8G6!a$8Ik+VFL5OaMFr+(FGBh%@F?24>HLNsjWR>x%^{cLj zD}-~yJ0q|Wp%D!cv#Z@!?_E6}X%SfvIkZM+P1c&LYZcZetvwSZ8O4k`8I6t(i*Abk z!1QC*F=u1EVya_iST3x6tmkY;b{Tt$W5+4wOvKv7mc~xT*~RUNn~HacFOQ$*x^OGG zFB3cyY7*uW{SuEPE+mB|wI<_|qmxhZWO#|Zo)ndotdxONgVci5ku;mMy=gOiZ+=5M zl)fgtQ$Q8{O!WzMgPUHd;& z##i2{a;|EvR;u1nJ$Hb8VDO;h!Im23nxdNbhq#CC)_T;o*J;<4AI2QcIQ+Cew7&Oi z#@CGv3JpaKACK^kj2sO-+S6#&*x01hRMHGL3!A5oMIO8Pjq5j^Eru<%t+dvnoA$o+&v?IGcZV;atwS+4HIAr!T}^80(JeesFQs#oIjrJ^h!wFI~Cpe)(drQ}4Me zc2`bcwYhrg8sl2Wb<6AReHMLfKUnZUby9Y>+)@{ z+t=@`yfZKqGIV!1a(Lt}`|jkuqXC)@%*Rcr{xo>6OEH*lc%TLr*1x5{cQYs>ht;Of}f>-u708W z;=5lQf9ac9H8cK_|8n8i;#cyoj=Wy>x_j1t_VJtKH}i9aZ{^<}eaCp$`#$Xb#C+xl z?1zevdLO$!d4GDiki4+)8~23s`{L#u!TTi(#gRZ4p2Y*4wY^8&U&f=_d5tmR0C17w6u}Ov!3L*|Q;0LxSs39cy6;IDejRuvX z;Dwiy+}u3(oZRz<0RRufFrJlhfcJ+eiX8m;t8G~pP!|6|a3fF@ zr5%sQUl4F%XG0Lo;uX_22;e}lGzbQR5DJB$TrS&XQ6>bb*Xu?qmEsU^h4R`ES(X)y zGdCm}jRMQEwg^Vg97wm@g>*XoiGXX=$^IaFDQ7Pqc9$cr)oO!{M@((MZL?wNwQx9m zzt(JX@2s`GX__p{ RkOKe!002ovPDHLkV1ge+1NZ;{ diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/slider_tick1_notrangle_v_dark.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/slider_tick1_notrangle_v_dark.png deleted file mode 100644 index dc1b41cdf3f5bd999d340bac820321c9d2858c78..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3189 zcmV-*42tuKP)004&%004{+008|`004nN004b?008NW002DY000@xb3BE2000U( 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 bn9lzNkmyI)%As)p00000NkvXXu0mjf(02$X diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/slider_tick1_v.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/slider_tick1_v.png deleted file mode 100644 index 554fcdcd0637bcadc3bb33837e49fbc9c5a411e8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3132 zcmV-C48!w@P)004&%004{+008|`004nN004b?008NW002DY000@xb3BE2000U( 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 diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/treeDefaultOpen1.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/treeDefaultOpen1.png deleted file mode 100644 index 661a77ca582d03c312736207938c43ee6ffaa7fb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 506 zcmVCW1RtyLP9qchwA+&DUIR7}8GDH}fzh|)|w2m5+c~wPL zQ4mcwAd^wBa$P5|a2LZ8&m$MpLaaTyI&Pb$E6GF@ak(%&#@q=%jmc$9O9p1!^{hns6KRmuKMHUx#MctPzm7Q`!r+#^?Txp-BF_&hG*Y0QC*5x^$bGn*aa+07*qoM6N<$f^>J+00000 diff --git a/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/warn.png b/HMCLaF/src/main/resources/org/jackhuang/hmcl/laf/utils/imgs/warn.png deleted file mode 100644 index ad841c16351793b0b7f57b3fa996b50b02fee3c3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3110 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 and add your jar to classpath. -* You'd better only access `org.jackhuang.hmcl.api.*`, and other classes may change in different versions. diff --git a/build.gradle b/build.gradle index e38604c34..e027060be 100755 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ /* * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui + * Copyright (C) 2017 huangyuhui * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,27 +15,52 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see {http://www.gnu.org/licenses/}. */ -import org.gradle.api.artifacts.* -apply plugin: 'base' // To add "clean" task to the root project. +group 'org.jackhuang' +version '3.0' -subprojects { - apply from: rootProject.file('common.gradle') -} +buildscript { + ext.kotlin_version = '1.1.3-2' -task mergedJavadoc(type: Javadoc, description: 'Creates Javadoc from all the projects.') { - title = 'All modules' - destinationDir = new File(project.buildDir, 'merged-javadoc') - - // Note: The closures below are executed lazily. - source { - subprojects*.sourceSets*.main*.allSource + repositories { + mavenCentral() } - classpath.from { - subprojects*.configurations*.compile*.copyRecursive({ !(it instanceof ProjectDependency); })*.resolve() + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } -task wrapper(type: Wrapper, description: 'Creates and deploys the Gradle wrapper to the current directory.') { - gradleVersion = '1.11' -} \ No newline at end of file +repositories { + mavenCentral() +} + +allprojects { + group 'org.jackhuang' + version '3.0' + + apply plugin: 'java' + apply plugin: 'kotlin' + apply plugin: 'idea' + + repositories { + mavenCentral() + jcenter() + } + + sourceCompatibility = 1.8 + + compileKotlin { + kotlinOptions.jvmTarget = "1.8" + } + + compileTestKotlin { + kotlinOptions.jvmTarget = "1.8" + } + + dependencies { + compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version" + compile "com.google.code.gson:gson:2.8.1" + testCompile group: 'junit', name: 'junit', version: '4.12' + } + +} diff --git a/common.gradle b/common.gradle deleted file mode 100755 index f35b30b9c..000000000 --- a/common.gradle +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ - -repositories { - mavenCentral(); -} - -apply plugin: 'java' -apply plugin: 'maven' - -[compileJava, compileTestJava]*.options*.encoding = 'UTF-8' - -dependencies { - compile 'com.google.code.gson:gson:2.2.4' // Apache License 2.0 - //compile "org.jetbrains.kotlin:kotlin-stdlib:1.1.2" -} - -task sourcesJar(type: Jar, dependsOn: classes, description: 'Creates a jar from the source files.') { - classifier = 'sources' - from sourceSets.main.allSource -} - -artifacts { - archives jar - archives sourcesJar -} - -task createFolders(description: 'Creates the source folders if they do not exist.') doLast { - sourceSets*.allSource*.srcDirs*.each { File srcDir -> - if (!srcDir.isDirectory()) { - println "Creating source folder: ${srcDir}" - srcDir.mkdirs() - } - } -} \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 30d399d8d2bf522ff5de94bf434a7cc43a9a74b5..6a461dda3d5d30134b4c47e32db77746293fab4c 100644 GIT binary patch delta 26093 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 P&kbh+t%BIDo7DdS3>n*L delta 23692 zcmZ6yb8sd=mpvTYw(-QaZ5tEYcJjoT*tTukwllG9Co{?XX7~H5cHix)R(1FN>r~%! zPu~u$0k6*hM^csphkyeCfq?-bP&k)NL?TA|pV<&t+jb(K7VkyoqsxN}D9C^A1^HLN z{;T;{ApTWH7fUAa|Fb7?h7|69>?OX@{I6NE8Pq2B|16H~hOJ@zv*+~BmUyx=6fscE z+ttn7UfIRb$=t=w+T8Wu$je*A-Ob9}!Ohy#*v-*}(bUe^)wNX3-Vsd%B>)Q$F}`?M zX;hoKx#pvO66LsPga;cN3Cp5Tr64b4Zwzi(=V|7c_*nlOZO{Gy{azf?ESyRLihegd zcg_Da!_U|Kc67FW2QuYlLlzqh3xtORx24(UY>bP=;8fFIyCp=|>#!w58Xss2@}uPt1hk#GM(jX77Z;#fX*Y&wM*o>MY(cm z1{hdv^C-XN6%llFlS4?x&2?*y!R++OvxSj9P&;K+Vo&->zjqaL^h^g8H^+EX4V^9! zPRk=*OltH4wBrU49Ac&fsPXZwjh9=G!(qu8HuVN)LG9fWfbd$Ao5!UpBbXT-ider^ znEn&4XV==URsUeR^{s?dHr!$=!|OH)W{mSt<)<8J#5Knyp?|qHUsbDsyabEsjTi z5w->_W*cW!mP9wOnnXlawqh>3E05i76;I7gO|C7QC-6AcDgJxE_ zJGwZeDpeE8UE`gNEo!%1JF6r8r-83_ajN!Ii%VlpshK+mrvuGLkIm>Nli9P02)-I0 z`w#nRvlY=oIhK?h8`KIVXBf22A_syjTyz(P+gdAIA9_{Ehr$he)JPXl%>7 zBM8@%Ys-%3mJc!+=7({Wwyq^(qhm7OVU@(uuGeW{EoEJ+-*)#6Yl;CpvJwp` z;&wNv1@jBZ;xY{+H8?+*5z^TBXttVR7)=9AVs09NTJtdzIM|^8#)*u9=zt!IBl8|I z<7HWi^!>&$bN!L(0R5x~JcIPa0kwc0(jx`=Cd1p0TN*qQzq2ONLe`r&*Aap!7y?J< zXR@>^v+z|rGyO$7lURgIO|!aA^4lBl&}m9MZ8&q~%dMTpT6^Gb;h<|#8Ti{U3ky!rQz zW|6dADZT2&>cT9wZ5K%t*V=8P*f?l}yu3-PHNoKDGr<);)NpOQQ{hYsApphnva2k* znR37cGg>owpFL-iM!4Tq71&I)y+TRO*-a1-vo@8e!&`WH_!{-Js;8iu_UbB@2t9FC zBDvbUDtvzn3ck#sWfeV2U^KDzaa#9Y5PB5fLq59bt5J{yC&tqun%NJOpWdm>e`I=rj~Y$wH`*yEf~a^!iI>tc)@ugmwsbkIpQ z@VkLqnw0qgE@nib_#hhf&|v*CWgf)N?#OK#_1v^W0~&(>#MN0r8X_3zJ}GFX*1j>O zgG_b7FN9gP3S29=+RU-d4zBB5QGfxEsO*wg>hpHqn6@6-w^O;)?h%huzmJdnntisw zqX2@WB{45-lEw}$%$urcw%Mp{d)t-J9qka)xM=$lhk|OH>R`terS6@KNZ)|Ui_L&X zso{}|?SrSxIXbf|Y%kZJIADnI?7O`=ohP&Zr%zpX#v8zOV?druwFwqF;~@mdU;55f zOZ@x8@e&mwkvDieL5gi}B%~u$Q~nS|pmk9T%&?enuK;}S5D+l1{Jb7%Xmx<)-9Gs{ zq(^A-cXSWm@t0U$g$puRi(g3IYjZF(i5E1Sa52Y8_M4J9QLi&J=l^o*46DT+={IdDO_3>l8X-hSK|Nl7pC<= zT}J=>0ZOu<4hJx4%VAj&k?-Hs5L`5Tolb}RcMN}^`drBte zigqLMCU8V8NIY}|5_v$3)M8yRn;t(Betu?dPUy+|dJh=z4Hn4DuPhv-ixk6?5%NM{ zrwokGQm~P?X)~*scFGUjbR7mb@eNPB2!Ms1X1+|a3IO?7k@f2HPymX%Ld~Mt!aQ{s zdU>X84|A^XUG17~vclhoNG6c6hx#5{FWXiT!n*Z@s1w&80zKCyV3~JC6i4L<% z=yUj6zKj=I^Sj-m>54S$RT(j-lm`)et!{3)@TntiB(IK72Cu^5o|H+Lg?2faHDCorJ_b z)eNkINUVbwUgDpqLOF(tLkTSLMj_;A#U*(TSs2tH{W%h12P5JTDMCSH2G8+=OQH+r zq6d?7B0>ZwqB%;ULv)O4Lo^RULq*~lO2UfV!~oGr2bJiZP+svX7gSYNcr8QnFZ_SP zPsN|m`s5!K#{EY)m_d?F)!BhpuIL&Vf9m1SkaV8E^MM`s^{z9_7*pXTCWbD_o-Fd`Jt|jDc{L ztb>)AlXX!HiK`@;v-QGXUb+^A-yIyq(jV$h>Y--hqb|L(Wo9OqQ5~iaRnM~(fwRUe zi<*W56Du?ClEP${>MF;0kK1Y%9Smn#Mney~j&Yj9W5adX9J?+_%w#1{%bS+Z&*prB z^BK3J#+2h3vy&V-B_s!?qbt%kW_U`xwwONcXORJy8UP-LaGd3#dUP5MY^)x?IxI%y z`8Z81#Cy8k=sPT^I313yu-R)vuVBclNz_aEY);@DWW+hbf?AoTrKlsYlgQ4p+9Y(I zFdG4`4<)$6vZGcOx-?NMH3wA7LpmO}JJ&x`wD-UAq{oc7D@B2t+77MhlbO?G7pl8v zeFa8xVIeA7+~KxzTQ8j_Zssdy>XtPHr8SKcq2{PIs0%Kbf%dg1^&m8ClemnIt$5}x zT@+DrPgTK;r+HZJ1)rORJ`I;VQWs7?hU9g^^_bz>|gpw%Du>` z5q685bJcFUE=>T-z0;%Ucv+2>?W{x7gX1h)lAf(D8WNYCH9mK@3(7Iv>L3Ejj5;ke z)nWK-nt3&u*_xXsJ&^h0ZbHwNhu|#jOw*d~W!;BeV@`e|L3_*S6GG}IgU-@zWEh4Y zm;g(JHfv2p#>oU1oC%4m-lfOKI|>ic3G;(>{KDtm2?l`Jw0$eiYA$_4>$H7~4-9?F z4*~(o&T`}N?=m88H^`YmE3f@vy=Zbs*v;D)1dQ0)Ih%C};8IleMq5!8j~sG{KvvVU zQa0Q;iJd-a|7N%K#wqD>+vjN}caE|iv1h~zSkZP$2w!47p-C=$r6RyF*A$Rdy5+M>(PV(jq}(f40q!1*uA_eq!- zCXw8-vwd+#L)5GH`kfHL^W^M=yGemi>a+qSroz~j8GLZ~Xz6+$X4s?8!F{;am zpWBSGZ>VuZU`z8aC_dJh5;-|f$NFSd>leTWDxo$9=k1*_k?m2r4y9RW?&~04=nvx+ z#c9D^EGg_8lkFWzYKFI`#+dMCs~u3aL_MA3Il zG47#5{lm94l^$7OeJZ^6l22~8sX=1AtLM-b;$P_hybMddnY%Qb6Qx7{cSttpautOM z4FckT1Oh_!Um;o26e95dQv^~qKTPqpP`}sKFujwxqg*#yLrkb+>3?C#r~zcq?^nfZ z>py7~H#=-?$sK9$y1J`J!d=h-Z~hQqDZinxb!kRgKm(5B!TNsv&}*YzeueJky0hM$ z;bPm%ZvXo||HTEGGuD5|9W_LhGpb4erBE9#Kgk)T5w= z(mGWoP}xqo(POQVY{VKD@uP@~p8{Gws3H(YA09dTf#t^>s5$%LN^}v9o|%37 z5scqAAsGHVj8^fZ31=E#467fx*HHP+LNLV6-b1;_X7Q6dbsWFX#p%Nzf4lb|bfyj` z9=R9e@urRfcEcgXXh-WhPdMpsX#+aL&1scg%PO}*Bxar6qy`h^lE1{rho9KghLfMt z$E709%FC!-P17+bBps}{TJ2QW;D6EJF~gr>UK6&+kFUymYSN{-LH?$q8qX&n%Gu>@ ztv9m$C=xt6e>Jz&VfSMTPxT)HT(YBjZ!;sl6$Ot0)!%A@7Yb6#H@{JbSH@+h;kyKC z88F-*nD#9>wi4VMa9z?7if#!SuSM59Q+v&A>FBz0a~HNt10-AJ6|&=yN<6x-9Dl=i zb+ZvaRr<8$Jy=Tm?f_Ek6x`-L`)k+H9c4O>?VP(YA>C(J+$%`h3V1#)_DlXOp`c zv4Ok$^1~7VYwtB+COpY>E_muU&lN&Kc2_nqH*@9&t*OLyjL{*{OD%g$OWOm|8IRB? ztmoSEHZPX;x0tFjQBITWYY}6%*(Vax%Oor&wv)=JH$Ty6ygI_sIBniA2d1l+?x-5h zk;JZp&ZyFTR1_rrqwIPS4ghzw$D#VY^862ikfmf3Z2)OC{CjDXVdS%IPtpENw`B)# z<6QxxUxOv6T&F8p@s&buU0;Hw&q>VCt@u4RYVQcS=e<}gUh+W-6F8KwQFEk$2^=)U zZ1IvxyI|xq!f+|8#)f#YEph^_hd*oz4sp*YD5&k?(_#H#scqhBxM80*BP=y)$W6M6AcI}Pn^C49~S;vTLc_UddHuVnezAgN_yUevs|zSh#{1A zl~PK|(s|F8b~;^N28!cNLhq7Q=JdM)Qmf%Pf83c@+{!ckT4V6G?S3kssHpy_gENto-23$IG`4~3+#KH+{XSZ)ToZLA~FM^ZFE zj4<1OaQ>B3QkiRC&Sb@-gNZHkrG<$v^<~2pp9|we$xZGz!My$@>{k~|Rky!U`2jwOju@L#)(Unwfj&+iiHcjPcNnWHff|+lwM**cU93R_| zlO2OV(VY0w$cDxkF-!s?IRe=Jpkmk9%*syXyA^?!y7iP>b~%qRvD8;3$3osyQe}Rb zdk$r`AZKKakRHpRy>5PL>fdPgZ}$s;>8Op0u!6lXtwH}D^> zk?1vxlhAo5NAw!EFWU9 z751<`1^qU}_DBpNL6>Y-u!>sE(2&!eFGYX<2xYs<9D8L|UG1UhvC1=vm9+9s=_Gpl zL;cmPN2KdC`h)^39n;{yTFlNT4PwgPG%1h$I48P6Jm;dYdgB)4hCP7fHOi-$RT|2}(ha~PY zjBrzwH`GrVbcYW}c=x0|9+BGWhcWf{|LF9E?E*U3$RHs0q#z(9|1EC{GeRfpalipF z*1i7<-mp}!k{F3dNAqAM2)B>e!{h23Q90nFk!Mb1Ji9DE%O~$TEU!gwl_>yw@52A|XYQ=Z>LNVG=kNMH?Y{N> z_S$=Fy#s!5kZsOk2V<0TnZ3K>ev1Ob9aBx-<#4}c1^@C&8~dmgI{N zX2AWXk_O5Fu}kij_Mk6dKcR8^$`^#7XvF_g6#T7O=ucVfU+SlMz61S44*O=4c7HY$ zsVe!K_VpKb;qTNRAlw%)fpaNaq^jU<+6f#SeJ*1VG96-roX;T4AMQ7J4Fork1iw_I z>ZAa{Ttw45bLd3Grj!f3hk&gfB_p*74$>R5Ub92=fCEeiw}h{gR@#@R=6;i;75<^u zPbzTzAY^?SMb%3zf!DiuD3QedX$-^>?*0_S5!QucJ>^kz7b>WObHJT-9ljL`7Z1|` zZpqjot*|sk&$}Ce4`Ua%M1%^6>jAs(5cUS>;gY6?;2iUu3hNd>ZX>xn^7ybre%$FX z6ue8+=pK4w4eRzrazl6}5?CfA&MAqjoV(MJ}59ISp1$uG9@!UAoRQGAq2D zBTXgGFxOIuW7NXu%c!oJC9syLcy%NOJJ{2?5jGsg+|i<$PoQYFG*w*0m)G8F@(Jh%1KsLDYgKf5P}#;?Ryj6bWW#E-HS_7^v2P zzSRrgp1ESh3X2DeI28isv7_3#8l4bWK*sNmubG$5qoNU!jxGt5?JE@Rh{#K_wGQjf z(2TwGAZ;QqgWYLco0Dqhw!*4xX;Nm`@$uPURjvEE+hHuyf_aOWL#^ur8qH^W+C8LB zdxn$<*>Lkzd6PaN*FgsEY6jZw9!=vdMR3uZWv($CN{#Jur*JMq;FMB1GEn3;fTLjJ zF}8$FXG;1>HlqP7b?>%RC7#XIU<65#_2UEt-i75^ z%xOP9i*T)~BK#R>9c$Zm1LB4LlXYJPk<=6e=c>V6_K&AUOlWkZ8uNz<2+!iv`Jm{t z@~+bB$?U=QPb!h6sS-N@0~jw5`ct%%0eK|59M^%Thu0KgAJH!dz#gQah zCc3Jx&6T3CFxyW3M;gwr4zJ(SVp%p7Gp1d4k~jehb=BFFE!PS#GGnsi)Nr-r#zW(uWy)VQ!nku{HD}r zEH_?RzzJv3fjsfkM+)(Nk=aFmcUxOJHOIy0?CDiGMPkb2T2{Ms<8gw@8__DSviU^X ztnMdB-UzD*5*tI_q9L%n;nt_M4u{MHmktluy0TK>J}-->cf0;>yO|h9cbxQCX-gRIbK_wU1<}R0lqL`g3Ta zoB(ZRimG*vvL>i=4{s9t4U7S9n*{~At_z$|nxI{F z5@;5=Kr)Tr`NL0pNy!8_^3M`ZJL)pBttTh7SwN=iGcscCXxkLHpE?e)`UeiNC9k_0 zRa46{iLvC^9xgPk&;ZNvD$m_b1HHYhzV--BcGwrNZ(*j)RBdzhV^Ha==U75?soMH0#lf9W{N zk%B|ZpPamG6-&iC1~GLWj74Zh431iz$kL6-HVWH_9Ycb()VItfN#THra+v(dEtLtl zK&uxsbX_a6PB9vML9p>hw7QAG2!FS4jdj&CGgExqx#5{XT;i5LXQ7pyU?gS&U5}qM z1STU2hdhyn4LwtMom?;hG)ACIs_B~@C+s(kMHf$GQ;n14iIlhKflO-od(Kq+!x49$ zQ*_7F-N9Sc9|)n!$KNBMv{7k{0BKd=5Jy1&5V7({5BDtehZs*QQ&lsq5G9t6E_0op zRi@YzoRfy}I~Gx-N**e{zjmo%k)h_hPO8w*4jfSZ+7K`XV zUu4!5Me^K^;)b zmzzZ{b(IW{%ATU2RBZ$oaCfsW06J`YS*#@l{7OwbM5#oN;>rvnZ2MUb2{a`_F>AKO zM)&lGK>O1wmG`oGId81&K*0Em_ua!37HRRh9vF8Y<5qyDVj;zvbob zWX_K!P@OuPN(8Mfg|LCV-hybD=gT+NUq{H@{ehup@;w!lwlwNvJswXMeJx!$jNSs2 z@{6}sWbFlj2kJ^5YCZ|aKG=6C_9HTp~cI*8XXUQ+bY3cE7dfs8rS{Mq(uizE>*L?ZEup!F z;mR)z4Dr?)W>0-v?U$c!(B9o+SD@SM!O?2_Xs8VLZ^npPjqo>iJVL0=DqA%yjAAhw^kM2H&Z#Yf@eiC6 zOKW|96RGigCf$Aj`=${t;+nE~&`>3a{C$OQF|oDhmb%7_S6!u36%$s~vkoA5Vn^x` zwY5BtyW;)<4G!e>?Fl$&JfpP-6xN96f%)&nKfo}Qg96VTP#y`28GQG&P+3(myEjP9pCMH8ORv$d!F%J|EV~_5egS->8cxiM^vU6{nm5(ofUoD%P)u77{0KEySX<0)vS*H zWLVslL9H%?@)V8-WzsihZ9|YzSjOqN!KW~5-v?}P%+k#(XK<4KOW!K0vn9q?W=##^ zX`EHIv)poqMwn6B+o;pUMs@EwtGtD9V>=w?q2JN1fckP1-wJ6^KGlHMHU1LjWMq_e zD-duo);>JN{*MF~aWMX3q@Uh4R{}0yscT9984x{m!RbPdo=)fuHYmw2RkZv@bGH;b zVFzlM5QMxUT3s9KhV9n~Yu}1DS&4O>i&xu6PGg? zeNl$aVTR7q7t}5PK1YOD@HE10w2zu{s?HRY5JIXIio|$8e@-rVXRn2>LtWU3bbH4A zq|xp~41(O?dM6R9~#eyPAd-<*04q3EOa=xN5~g2SIZ4foD-F!VmC7mAo%niS{%nT^1wUH<=m&*Vh`xCUh?>IB=Ep?wKVOQy8^jGq9ks;5+N#De3~N}oB9s;nY{UEM8V6G1 zjb(eTb*@GDuUjVxr1%^A4CMXd)uxx~0j^G#dt+%qoO7Mq>M-4c#y~f#?gdU&&8({T zhd9-WF&_pmI9kBcKI`e^0-m>2?E@b@&pn#~dd$JC8X&?@+SvXPTLF$$)>>+as^ z{`k;+1BdDGzP-w+QOEAWoB8QOPjk>b$0cHnVYLKC2jqF;C1Ud%86m??%JgV5AK#Ox zVNBiI_zR^dmdR1)y-=C!?@I8$mJ{1aka8$QdlF@mp8Erf$p0s>-WiaO9QpT*mkRq| zSw+bTpoBoZElm`Gp(e;Gv;jL72q!R%>`_HES^NTa*suniB%?ImlIR8|N%6D_di3)& zM(f}BpPT7@oJ`^MehPcPnLby5iyn1mAzY8E$o~ispX=OAuj$vvydx86PY|*ByR()g zlLbW&ld+~G-Kp93a8JxX@z7W%9GV4pTKi!5%LmB6pA_+;or;pqOi_$#i?(KNXQVa+ z{UYte760Ba8ZrLzt~@67u02HkqWs~aCyAYerV8e#mR0y`8H~U1J{-h(Or8ZamSxt6 zu5*U7d2Pi$m*P7kQ~d>Tb?Lp21morh104wgTdfzgZ8H=Qw z^lTQvxbt7~mvBh+4|N97e0Ica!cDfWtl2Snj!|hGCncPjxVri=S@l0o;mUkuptF>X zgs8}~FVi!-95fNRlu%e(i#khjUA#?pOiIA*#Q+xX+Ej<~@UqUcU&9nz?HtP!viqeQ zi!ti*v$&H#EO^X(L@~Xq%ouO26y4RQFR7vRG<S(;6+acWa6L>*oDeo*o)jY#%tk*S0U>24$IeBn+WrQo0 z*PQU1-Sp?GFj)Rj*mpHh9K`@d>lC29J>R$h1T=J02rA_KgFwV1 z(4woe7|XHn9>s6e;Ok+rn5C%S1Y)5b(d=&rQ2wc2lUnEwhYC%2bO|2rj)@LA z6l5~HR7}rG$`d;*63>f0Zc%F^4gEJbH{Nda@jW@OG12xWZ}aDb*65BdRo?m!(2wVT zVEY2!*3XLWr~84qMReu|{kjx>!MCQ*f1EXgJmBEr&`Wjzs68TA&Qk*Ayb8u45T3yk zUe1}9|Fluwb@}5x%GwCQz`7#=-AIC69oe)T@%!LCkHhT`}eg2IQtr{zV7{?dKKUiaHB7jVx@ zDd2h%nh4CP4h`;TjoAQmu)4Tn&~~VUAxf7ZMs&~?Xny8y+#?vw75Xp+a2O|4Svi;k zVC@^>I7XSEBCRDp&a(DMgtt%Ka~|}`g?EP?-=Ox0oqA5qbst|TL)@i(2(b2W1;0)H z3BVOZ8H6_fPC$ql?w}4vj-HE$x$9MNJN&85!C=Vt=xzw{7Cnj_%0kDEJTaO3__D}M z6m#eYB#7B3%_NT7H%0a150)Z(7l+7?*;i}wXOEF8-T;{8r+u)o68s1pzt>58>|_=s zmSE~5k?q47O}{s1xuH|>!!(ROyn2^}*i&!lDQDu~U0QE7Z*jD88c$37CLAUg8}219 zHia|!>TcQ5wbYzea4WN$o=~XKYG~M+!L(xlS~{*aN&Fa$f&=}Lt=cOHE7$&pcqbi; z6#J~1uik{{h}X-XQF}>|)jreX@GIOvxnZQW-U|QM+`*EdeGQYEJ!cbp({3sIjG|67 zwl6!KR77}`N1s)?I8U9!)Y*%^B)%uiS^4a?qN(U$R={%Bc}_!%yyo4usWn9tZ+oXJ zuw6{8g?)?J)y!tYT9@4_J+I9dA-dT5M$JjWwiI)aR;i@ivp$be6-OhqYZie}Z^iNW zdGK(h!yy)~8)8=8_E&9|`NZZH#sTWavQBO zpk~r@yPK=_Ou$X_wPf(TR**+3{g^=jSg+#~uVMrjhb=LIHLdIP*=CKPPY9a5WT)3ItH>j5 zm$y|G+$FE0?Z39dI@~92&qKow+5R)pwDe+AT?XCz(`81*)7Kwo&tiqzZ7UucIJmDU zfkkU&>(5JrzeYF_xua35MX2{ClJr@EY}OoP`J>EwS&%`fAW|xe5)c_eI-5m8h6u`Q z6?zb*zTig|28TBeeoS0039eu)*r*3)cAC-&3)kpAM&6 zeZFJ9r00>cRTahFC$=gQNpHEAN?LsA`z{z=eSI&@Vu`QjQ;CP!;>$TYJ#@rpE#Gre zBPz#l>XONJ)6tjyu{$WvG>wOso`yAsto{c@2rW#=qB7TPs(K@?T0O=D7#&r+QFizX zN6omnVrYO7Q)p1BlKzOUiLthz`W=@@>%nEa;_$4fF4#o7nOftIC?J3);<8mzP$I)U z{YA^={wfMQ{fNuuUXRBL<~$>`VvF8_4GCdM=g=1nrFn)1x)Evcz>`+q`S6YG9r?XD zN@#LDzcIR(Ty0Uh`EWJ}*eQOGR~FTiz*wueQdg8XD_s~Ct?3c!UV6y%PS@>kiHYVQ z0Fd!H-rKFxgB&lW{NA~(8GGKf{<*IVU8wTF#V-ggXLu6Oxayl%%HYh9Udd0Rx3z>yoVx<=;}@SeJ2w6T>?l>r?5=Du%Ib`J zcha=nI2sMM%zEZDU?sFXp)kycIl2qp6;j_OduMvVE~-C}s|+on4Asf|KfcJ>yf{ZLiy(5elN2KTA_JLeQF)RD;v z`Qlh*s9w>>iQTR#h!I*d> z1jc$!PD$jk#6hOsT-j-a^Q@@nz#8%`qg~TK^C!lgCIV*Lkp60T%#lTo|^eVtv zA;>X`M~NvCl@k!PrY`-^+!5{QKIhe!1V3#?MLf z>AQ^W_PH6l^-OPcR|DzX`9aso2mU%JmVEtzC>?-la|N#4$muKzd-P@_?u=u$$a@31 zC-nHoF{tjnU!0siqg5Qz2O2{SSWLPZJ`A7wQ~cO2!rxn)cVcRX21N5llk91{`HkkR3Z@?jn({~Lp7pMt#}%i@ zurdZpLN<1gJffZ`BUO+5V56SiXSr~tU=70kfG%xW9WAfuH5~CKoyjC`MaForx6Jy5 z)-A*ibmR1=R#%0u1{EDK7aM2MTQ>7ix@8Zm6H8Gvb)q@0{9JNf^=_{qB3xKKfzpRhE9HF;3`b7FForM@TDla;@D< zlS0Bo+GXrgRNdc<9inm>u^90;8UyM z=_c9}d}LL$Oq!$|TV!kZX1zAHY#W2+rqESh)wM56<97V0mrNx{DZ%L!f1+8s7@OIdGbIC|V3O@8uz|VS&|VnhnBUNfo69yD z+^{9XDd6xc33Gw5jRPn;Xe0?J1r|Z}Jvmqx_ZOPmH!6o|CgmHE%hHX>+yaV+7&+Y3 zzoHbbF{l+ieePy2dig#qJ>7YC7(@;GkY{gtyuW(A?+}#)pYDr6)}mu++YT5p@$XqX zd-NIWmG5OSA%ST6fm$@&N8{CBUa{M~|L!%XcH+192OmgBWfiK%se4IpulgvigIT!U zqM{|xevMJ29)(B0Zv9=-bkC{|7_G~Dge#fS8EeRXyHiw@aY0Iqf!HtW>Q%82r^GG=!i1DRXJ6yTsAh z?#c!#`C>V7B(ACqThTbwv$*>0kAiu;SSrXh4`60w;=QyeaUAYJGOWMfwsffH=9Y-% zdacwE`xMuhVGyNz#G^u6=~X1^WA!~Zmhz9e?w3&E$`DkJVZI`kkn++a*yIS!6=~U@ zfl15?)dI5HL(T$;?C*`ddh^oscn)miW6$pm>>l~CVv-W5YyrVB6oclS5WVHeX)J9_ zruiR!@lBWT=JTHhc{9dx*gUVLHCFWe;OQQ`J)f1=jIJ>rSYtDZ zsFl|e1}f)G$TC`|qP&W@i7Do2{bTSzC(blC-|@; zCIqos#|7(WV=jr+3T-iuUHt4K2GfK_+rWmQFKAw0rE!KYbxGsHcT;)2k6amCY>loZ zOg1BmBu>ebmYAGsuOShqTW}2-92vIMpE$KLhd7@Z1BWpVxepI1CxJ3mgfbGQ!_YB5 zQ3=~wtvG+%F>tN?;8u8?*%M?c>U0skX`OYtolfe3-=c@K>3~|d!5L)0a~M;=ivu1| zX%@r(pg`;&S$5N?+zhK{s)@H#H|8G29 z#lhQqNVw3U65Myq!9Tv1Y;!7lvy@!C^Vt#Je{hHQ?-Qhr^dS;r`GXxI)~)(I6XM@7 zAViu^N4?tGiFOS3+)=|0KW=>HCo|AC(A7nC_{ll@`H-!7hf|?Zsa;YpS;jO5lY{i( zdpe9!xEA_RqsCe$8Xq^`K(0L&QP*LLVTM$SCn7<=IwGNJxTlg;8EJ0PInc%_K*UwM&>-R&!-6WBn2{$R zx7=JP~OL#U8pS_qT9jVfRrYO_vZn{8QYJ)dYQIkGeY*QhFsU~Q6$fsL@m z)k$-pf1)F(%fM)1^_E47PYFCO3N5RK(2yRDpebFdF0n0=tXUk_{Ta-z2ZHX-lI-hXJnc`zCRz$iNMXswP z*lVMw?{iAjq`w_u@gDSyimN&%+>m0iDZP$6{(QoFmgkDi>iYa(-vx>;ufDm=KNull z2`sz2#Wk%Qu`&^@Cf7zLu4JILGnVLv*XO{-NlK~08q{!jn{(~q{Cb4Dt~Bji^NNGi zG4oh7rNd*XxvtX|*lB!(h8)c`g{aGtDxNqTn(8POv}B5?NLi(=HYi}kP9Ll5y9bDv zdt*bp@^!1#diW}$v;i+_N8*vEy_dVQPn77JZ)PuiJ{s?dB(P7AXhMH*QJdClvg{!7 zD_Lp;=mnZ=XfBXO^fZmBg)YbP&-ZkNF`OMfb@NR_A`;QNcHc2lDa#{CV9w0ID}{e} zn_ITz?c2Mt76O{n8CDuzFI~)5(8j#v(~D)vCPQZ3pWuqunSok-LaJGYoZ$A!HzSRS zYdUr)HSjlOPgyzw{?N%WKgeuykw zb>COpCP$6TY%*t`$t`XMPuzNXwBZXG&g0to%fB<0VfUi` zCECMA=yLOi`Gcf*c>C|tJ)V>2oX?I&<|$&O^H|}n(H9Uz(-^!B^q%zRzZ6FCzN~IY zz+nKuw%!HEY->35RaoOsLlf$^=F}UPzY$j60o$PSc-*7faqoIBuR|~>Q#pC zf_`f>kxrdW)fPr=_Q+`6m4Z#?FmtiNA{zQLJZ+Z9RCE{x<5lGap`cat4lg*4<5sHJ zR<^V|$-pZ-ULOYg+S1`ml`trJDRRb9-fK~|SKzX}mZ?B*Gb&VJc>`>_37dlyyg_g+ zcL?1Bj;{S(EFTfst_q)D{38#KY&_NhsrUz_*dqyXTCuh?&)X5y$j?^dah7oI-T;AK zha@>t9(_40FgWv8X8>VX{u1ZIVj5XH+sYM$A}d+B9S_*fpVR6&M7Pi$to!z~z8ujT zWuRDr1K3M)K}fZ}vMH9;7-^|Gf|V2`?|Bkon~EHPW=Epzz&Ec2e(4l;6Wu*4S98>4 z-QtHQCv`t>^JDeKEBwUaDMGX+cKwtlcdYv#TR3*;A!~ispqI|;uI3F5^Noj>+otaH zx@4cbx`A+Z&N63fy!6sW>v?~`Mb^-1A#e;<-#Ly|7ff$y!w0#FlG&;B4%H4{cVmGs z@&?^&jYlhU4OZWMEloplPyg1YDVR0TUA~#o>A|6z{3AAKj@`qv9+*A0 zLC&&vbE2ZP{0qxFqAR%1)%Uu&x942oY{H+iZDDX}(*BjHA$M|b_HO63-t_-9aurZf zbsoEqI-j)dt-vT@lGUs zS`W|5#JLYFU0U;|X>z9hkbg)3z42Xo;(3+o7!0;c{(Dcmq9`@m_`M083H{+Yi4&)y z;ad_z`KpH0dL?B_65*pZCo{Da-8O7pT$ma?UIx{qBd#Mmug7lG zWsR5LTDKZSKip_eB~-t=JCXr>pKtuIHFsm-#;5Lu=d*+rj3%p(7{90PO1!rl+ft%F zE-(8ogf&7w;N@{KO7!-U_;75%4sl$Z#Hs*YST77HqMExK_~_#jv)Ga)`P15!4zCRB zSj%v3=2GjA68hoY)=AtX=^A}eHuiA=USm-P^5-@>mf6Z!bt@)WIBjl@g%rvM%!D`) z9&|)n=BDeboX_K{b!iZ);PSR$F>X&|S@Eq>Wckopoj3Qy6dxURO<0pveLBr)*X&zf z{G*x0`Ar=O?^hvaPYW(Q6tXqj@tnP6+W_aNOjN#D)1Ik1X6%#s*-T2Qs*c#_n7zS3 zx1nni*_BuPTs5huW_sK2+814U{0MJyrks3xzK^$QQlV=sAQOcoH-h1N7upmVr$0FX z2zeO~-6^t11V89Ov$)N379j>whdGd1_7e=tok@<;_?m1g$PA9nY9q}`?WoBJ`VXPb zXVyMZ7{&0t8l+K@NlLjbtK8!%NuwWOl1tEt z)YYb;Hxw()_t15O$PaXpsQ!TT>8;mSB9lw#&Xn2fZUt_)MC)55?%*lxzUF1&T&82m zUXogggLS4{(SD(re3VCowY^x%SDkuG% zC4#k8;(VV=)}~@kA+mA|6fM&o*mz8CQ++z9ciu8$P9EpxF!L8wa<)OA4SOpb7R2h~ zc`-P3DV1^Bm`kbL?W{=fWU#HjRu=Ca;{v`{*CzW~^MSP&36w)&p;f+IPHTeZb0sfB z5}EnnMt~1m`1D9KbLyucldG%-&%C?q(G!okT+XQPtgqggV5CzW2#^P2n$}UnUtFh4 z>dPdNG47WxJzy+RTcCgAOa2VCd0+0DL&ewA{MKutpD`y3OYpx^sohd#dGH`D7Vh?3 zu%hT8XZ_fjmobMFjjaJI8_itVN|iP19~4clKdjv^(MKx)n%#DK8h(%Yd&90?4QCtp zOfD(KlrsLMJ~$@*aF1?qI>lkZjGX zFEf3+XYJ7P`{%-m zn1owj&IIS1c6~&hIGLP?@g74iQ>t0EHI4WhHc)$K%%P{Vl_Z0UMQO{Z9TSA|K3o=j z7yoLY$_W2?+nk{pb#9uiVdB^^Hi2m_hJ3pElEbm{&lw#THn@bmcKc1_G)*3zDUo$_ zF37+4#fvKcu|}Wr{ga+z`5#+;k~)bPc#2wbCeykp-k!0hlfD=l>6?NKOhg7`$ufK^hxfoZaJ{y2h;G!Ih@hYoy4m#{?)w=U9G-uJ=aYs1)PTytcz3LLBXCsGC}tZX>B>I-#^}4F;-Z z1KY3Tq#XL-vkYUYY=fP^n-{v6cKAl+;W-=K^fyhrOt$Nz%Z2vSA_w=c!{&#T8}E1& z1>i3j?jSM@D-5(+5YZX52?nHDhTH5!3r5@Mb3_X!+XO_qz59!q;E!N4YE@3AW2G83%W61wAt@~oSCt-kZJo;7Dn80ic&mL0gf653*|P8`QM8TX#RbWV$^^NO5Z!83$K zjT@$d-OtC%1v5~8<3zM_`SP;awJBtS{fT|GGWt207zZsop6B8&FOTm|monW?ny8X& z$fWs{FtRn|kkYOFnQg0vaj-PMka>?nqaU5opZBS@Qlf311fJ7gl^`Uj{*o4P%mKdH zx@%ZU?~H*n_g|$D(=ye~ckOtzg_$W+=0?f7V??IiODB^aZpvjzdE1W0@6eG9_Pg5^ zxV$XLLdgfpHMVcdO0#~7wV^7Ep?x=S;Cjnl=k^CV`S$w*2knX6?H+y8#%9Vg&Tr9S z`j=Kj&1ybA39a>(2Lfdt_@`c1vU=!y{#s|i)KmapzZS3Howt-$;UCISKT=G~I8Ms; z-Zb`)dH+^`uQbMQGB+N1yKh&&E1ac6i{weUkPcE4k(5vRN~BPIS!t!LB>mV5lP!HfW`VB>io~QR0f%hWI2nvs7AqI3gfw;}%DtL*AM+1jktytmEC-bC+V#i2w+p}Zg z=1Zd_B<8ukLUzqA6Z&=Y#ys1kM&@77mhYDq#V&42uk7ATX7aT&YAcyuogOLv+I@qs zebQ}Ha47wOM__&r5!0q7%C%d#EFzgA5t$cy+oiJBP|(=fLUVV4&a?>RA2=ZG~ zuU3w!pc(DyQcrz@k(ssfij-3_2ACg#j2}rwU#-2qbjbRmhtSAKjpReIgrWKAsR^1Y z##ff?RLWFwK3&cN*Q{IWtIwv^5#jfLnn9W;jvcH;)0J2Zt*td@kG>$uMQRG>hai^BXeq_9<5%QD&?$xZheE1(^s{smSdLOVRWeeP5MA}r!CLz zV=e9iy7q|fqGnUe`_Z;TPnmo;Z2U8M**L6Bnb+ndXM6UR{aWVc@4-%6%N#qyvD7#c zVSeU$nRCl=o1LIVSrLU(mgm<#<84ky1-W+1UVAn*d@E>=Hg7YlYTI`&OGOFozhJsA zNSd)zI@jh$aK}}~YtKHkf+)tZ8?IVS$zBf#&#B1WT@>9aYncBe7RXBzJj{BJ87{lh z{e-@adDV7m#&etPO}}FkjE@_^?L+C@b%WO*FY~6iNB&gNs=n}Al035hINdD5Rp(mW z%Y_N^)?)nXkhycsnwOi$ET{(2pS@>SQ(eT06RAePVGb3sHtnHcR5vmd^urE1lh4gnJ|osVI#pI3Ij+4695v38=h6eJ{X``a-1+4B0u z(`}tZHa?T+8Kr*a$r``V5ju~KB@BE7(Cx)jP(It|n%*Zi_$pu{t6?v%;x4ZwmCXke z(_5BDm0$7;dpad>BjjlvNjMCl7FV*(Z0~vhAUa`qZ!AtrY^yL^i7+6ekxDX>`fbFv zLZ1%_7m0shRL_#S*O$4KBMTyflPK9< zudx}l>7Mf)pYL+D!Cz^PQWbpS5zc$QEc&&;A%3;Aa*=AvyaHoZ=>tnn#wJ;Ix2O7^!P$_Yd@o^bQO! zU!v62*54Ky)EBSN6R)V2I8`AbZRF`kL8&h;Aujb+NT6>RsVyp4t1X7q>eZOk9_oD~ zBs3`8JD^?j79VGsB?;&ZAJgeD2s(q~!C>G^AegPMlj~K4H_8s>RcyfvEa1&`asDm28@sZg~qjYm}}Di|N94K(>K;WVpMqxW&UtInk@LE77{(RjG{6QRt+xNW%vW&+&y z?QAJXd&Ogb2)F-A(kF;Lr<$STxczFaeUN^?;5>+)mYhelxOj!@Ymk1k2h)(YjAJ<= zF8)IE0i<6&?meU(?rx0ts}>+Od`hE?D{BNW*iAA(FPa}P8D_1z6|@N%A!~atM6qC| zHpF6)Uo-(7_)ZcmtckT~o-k#u1}3Hou-9?YYSV`7I zM=rWJ;Ua&EhE$P+m^@B=L?U3}`it~$Au{km9|A&Rr#vDt_jBUvhE|UHk5C=lLw$sA z=;Oh~9~D=@9%it-CFg%|Fj(Iij_~E`Dko^4 z5wP#2!Nvc#Wd6_b%8MQ8(Z+)VR2YaJ$l6ng4^62fj+6z%UxEE|*}!jJb?}735y`EG z4ObZCY3pw=_+1@5q;WJ5#$GxyoGb)}d$IYzt_Mbh2hi1I{!0PmUv7v+{!2#+^f1H# zSvT2l6_D#Hi06fH&}M)LiVx!Cf4esR=2QpMm;>6Ka3|a>#S*Z9-_ss^7Vzr_JBjHn z{+af_Cb6BX6XXnlCExGaO_m4Q24FUw`ppHutAmv+fJXx?fce0`*^0$WSfSzy!2WmO zM*xB!vIG=^c!3Sy^@g*vK|m9U&f$aQzMtwzH{JTOuA*5CSSV2eH^>dxTdU zBL~XH7=9nBBZHd*Sc63<5Woh&-I)H0;&~>=!)~zJPy~2#f?8E@II=1|!i}qf&4saY z5LEFBoV79#71kcVR2&0tj6zi)#<42ycpm{=$9ZuL@?7sVO8|$IN&%KTf*5S|1zHFH zopRXWWVl)k7lOA!1>iMI7J^N_@vrmOqm0lH961Mq0NrLDKxBdp(wQ-VRpt@~)K6T% zRVCqSQi}wKNeC)CN}ONbs)Nr*9C<1X{yQVX@~fE~z!NgI6j!h((Va zFjX(&Vu8#ih9=NE7dTE42v(pF44CL&a%)>FuBCv4V(|Dw^F_4ymzZM!^(ZSO%G!fi zwcKSOfDNc{r~1q4e>WyDm^?&A@Dq@v@D~Aq$)(-|GvNS~at1=^dJ1q&Dni^39tA6< z`bZ!7I5a(UhOpYUYL7ZSt`hi9OuO(p(z(EH$qn;)a7!d5K;S`LT L1_mQ(#J2ti&^Jf& diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1b4d429ac..f67fc4b3a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Mon Sep 14 12:28:28 PDT 2015 +#Wed Jul 19 17:02:19 CST 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https://services.gradle.org/distributions/gradle-3.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.0.1-all.zip diff --git a/gradlew b/gradlew index 91a7e269e..d9116bf59 100644 --- a/gradlew +++ b/gradlew @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh ############################################################################## ## @@ -6,12 +6,30 @@ ## ############################################################################## -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" @@ -30,6 +48,7 @@ die ( ) { cygwin=false msys=false darwin=false +nonstop=false case "`uname`" in CYGWIN* ) cygwin=true @@ -40,31 +59,11 @@ case "`uname`" in MINGW* ) msys=true ;; + NONSTOP* ) + nonstop=true + ;; esac -# For Cygwin, ensure paths are in UNIX format before anything is touched. -if $cygwin ; then - [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` -fi - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >&- -APP_HOME="`pwd -P`" -cd "$SAVED" >&- - CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -90,7 +89,7 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then @@ -114,6 +113,7 @@ fi if $cygwin ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` @@ -154,11 +154,19 @@ if $cygwin ; then esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") +# Escape application args +save ( ) { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " } -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" +APP_ARGS=$(save "$@") -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +# 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" + +# by default we should be in the correct project dir, but when execute from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 576495fc9..f74b6cd90 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -5,17 +5,17 @@ @rem @rem ########################################################################## -@rem Set local scope for the variables with windows NT shell +@rem Set local scope for the variables then windows NT shell if "%OS%"=="Windows_NT" setlocal -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Dhttp.proxyHost=127.0.0.1 -Dhttp.proxyPort=1080 -Dhttps.proxyHost=127.0.0.1 -Dhttps.proxyPort=1080" - set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome @@ -46,10 +46,9 @@ echo location of your Java installation. goto fail :init -@rem Get command-line arguments, handling Windowz variants +@rem Get command-line arguments, handling Windows variants if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args :win9xME_args @rem Slurp the command line arguments. @@ -60,11 +59,6 @@ set _SKIP=2 if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ :execute @rem Setup the command line @@ -75,7 +69,7 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% :end -@rem End local scope for the variables with windows NT shell +@rem End local scope for the variables then windows NT shell if "%ERRORLEVEL%"=="0" goto mainEnd :fail diff --git a/license-header.txt b/license-header.txt deleted file mode 100755 index 15cd12760..000000000 --- a/license-header.txt +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index ba5f82c9c..a15d5837b 100755 --- a/settings.gradle +++ b/settings.gradle @@ -1,37 +1,4 @@ -/* - * Hello Minecraft! Launcher. - * Copyright (C) 2013 huangyuhui - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see {http://www.gnu.org/licenses/}. - */ -rootProject.name = 'Hello Minecraft!' +rootProject.name = 'HMCLKotlin' +include 'HMCL' +include 'HMCLCore' -// Find the directories containing a "build.gradle" file in the root directory -// of the project. That is, every directory containing a "build.gradle" will -// be automatically the subproject of this project. -def subDirs = rootDir.listFiles(new FileFilter() { - public boolean accept(File file) { - if (!file.isDirectory()) { - return false - } - if (file.name == 'buildSrc') { - return false - } - return new File(file, 'build.gradle').isFile() - } -}); - -subDirs.each { File dir -> - include dir.name -}