From 53c5ebd2949675bc156f1747edcf3e157ed8d105 Mon Sep 17 00:00:00 2001 From: Olyutorskii Date: Sat, 4 Feb 2012 11:01:53 +0900 Subject: [PATCH] =?utf8?q?main=E3=82=A8=E3=83=B3=E3=83=88=E3=83=AA?= =?utf8?q?=E3=81=AE=E3=83=91=E3=83=83=E3=82=B1=E3=83=BC=E3=82=B8=E3=82=92?= =?utf8?q?=E5=A4=89=E6=9B=B4=E3=80=82=20=E6=A9=9F=E8=83=BD=E3=81=94?= =?utf8?q?=E3=81=A8=E3=81=AB=E3=82=B5=E3=83=96=E3=83=91=E3=83=83=E3=82=B1?= =?utf8?q?=E3=83=BC=E3=82=B8=E3=81=AB=E5=88=86=E9=A1=9E=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- CHANGELOG.txt | 1 + pom.xml | 14 +- .../{sourceforge => sfjp}/jindolf/Controller.java | 220 ++++-- src/main/java/jp/sfjp/jindolf/Jindolf.java | 39 + src/main/java/jp/sfjp/jindolf/JindolfGuiJp.java | 68 ++ src/main/java/jp/sfjp/jindolf/JindolfJre15.java | 171 +++++ src/main/java/jp/sfjp/jindolf/JindolfOld.java | 452 ++++++++++++ src/main/java/jp/sfjp/jindolf/JreChecker.java | 277 +++++++ src/main/java/jp/sfjp/jindolf/ResourceManager.java | 303 ++++++++ src/main/java/jp/sfjp/jindolf/VerInfo.java | 178 +++++ .../jindolf/config}/AppSetting.java | 163 ++-- .../jindolf => sfjp/jindolf/config}/CmdOption.java | 130 ++-- .../jindolf/config}/ConfigFile.java | 374 ++-------- .../java/jp/sfjp/jindolf/config/ConfigStore.java | 391 ++++++++++ .../jindolf => sfjp/jindolf/config}/EnvInfo.java | 27 +- .../jindolf => sfjp/jindolf/config}/FileUtils.java | 20 +- .../jindolf/config}/InterVMLock.java | 2 +- .../java/jp/sfjp/jindolf/config/OptionInfo.java | 340 +++++++++ .../java/jp/sfjp/jindolf/config/package-info.java | 14 + .../jindolf => sfjp/jindolf/data}/Anchor.java | 3 +- .../jindolf => sfjp/jindolf/data}/Avatar.java | 3 +- .../jindolf => sfjp/jindolf/data}/DialogPref.java | 2 +- .../jindolf => sfjp/jindolf/data}/Land.java | 17 +- .../jindolf => sfjp/jindolf/data}/LandsModel.java | 14 +- .../jindolf => sfjp/jindolf/data}/Period.java | 10 +- .../jindolf => sfjp/jindolf/data}/Player.java | 2 +- .../jindolf/data}/RegexPattern.java | 2 +- .../jindolf => sfjp/jindolf/data}/SysEvent.java | 2 +- .../jindolf => sfjp/jindolf/data}/Talk.java | 2 +- .../jindolf => sfjp/jindolf/data}/Topic.java | 2 +- .../jindolf => sfjp/jindolf/data}/Village.java | 12 +- .../jindolf/dxchg}/ClipboardAction.java | 2 +- .../jindolf/dxchg}/CsvExporter.java | 8 +- .../jindolf/dxchg}/FaceIconSet.java | 3 +- .../jindolf => sfjp/jindolf/dxchg}/TextPopup.java | 2 +- .../jindolf/dxchg}/UriExporter.java | 2 +- .../jindolf => sfjp/jindolf/dxchg}/WebButton.java | 4 +- .../jindolf => sfjp/jindolf/dxchg}/WebIPC.java | 2 +- .../jindolf/dxchg}/WebIPCDialog.java | 29 +- .../jindolf => sfjp/jindolf/dxchg}/WolfBBS.java | 43 +- .../jindolf/dxchg}/XmlResourceResolver.java | 2 +- .../jindolf => sfjp/jindolf/dxchg}/XmlUtils.java | 2 +- .../java/jp/sfjp/jindolf/dxchg/package-info.java | 14 + .../jindolf/editor}/BalloonBorder.java | 2 +- .../jindolf => sfjp/jindolf/editor}/EditArray.java | 2 +- .../jindolf/editor}/TalkEditor.java | 4 +- .../jindolf/editor}/TalkPreview.java | 77 +- .../jindolf/editor}/TextEditor.java | 3 +- .../java/jp/sfjp/jindolf/editor/package-info.java | 14 + .../jindolf/glyph}/AbstractTextRow.java | 2 +- .../jindolf => sfjp/jindolf/glyph}/AnchorDraw.java | 7 +- .../jindolf/glyph}/AnchorHitEvent.java | 3 +- .../jindolf/glyph}/AnchorHitListener.java | 2 +- .../jindolf => sfjp/jindolf/glyph}/Discussion.java | 15 +- .../jindolf/glyph}/FontChooser.java | 503 +++++-------- .../jindolf => sfjp/jindolf/glyph}/FontInfo.java | 180 +++-- .../java/jp/sfjp/jindolf/glyph/FontListModel.java | 138 ++++ .../java/jp/sfjp/jindolf/glyph/FontPreviewer.java | 94 +++ .../java/jp/sfjp/jindolf/glyph/FontSelectList.java | 133 ++++ .../jindolf => sfjp/jindolf/glyph}/FontUtils.java | 82 ++- .../jindolf => sfjp/jindolf/glyph}/GlyphDraw.java | 4 +- .../jindolf/glyph}/ImtblAffineTx.java | 2 +- .../jindolf => sfjp/jindolf/glyph}/Selectable.java | 2 +- .../jindolf/glyph}/SequenceCharacterIterator.java | 2 +- .../jindolf/glyph}/SysEventDraw.java | 4 +- .../jindolf => sfjp/jindolf/glyph}/TalkDraw.java | 9 +- .../jindolf => sfjp/jindolf/glyph}/TextRow.java | 2 +- .../java/jp/sfjp/jindolf/glyph/package-info.java | 14 + .../jindolf => sfjp/jindolf/log}/LogFrame.java | 129 ++-- src/main/java/jp/sfjp/jindolf/log/LogUtils.java | 117 +++ .../jindolf => sfjp/jindolf/log}/LogWrapper.java | 11 +- .../jp/sfjp/jindolf/log/LoggingDispatcher.java | 78 ++ .../jindolf => sfjp/jindolf/log}/PileHandler.java | 48 +- .../java/jp/sfjp/jindolf/log/SwingDocHandler.java | 101 +++ .../java/jp/sfjp/jindolf/log/package-info.java | 14 + .../jindolf/net}/AccountCookie.java | 2 +- .../jindolf => sfjp/jindolf/net}/HtmlSequence.java | 2 +- .../jindolf => sfjp/jindolf/net}/HttpUtils.java | 6 +- .../jindolf => sfjp/jindolf/net}/ProxyChooser.java | 5 +- .../jindolf => sfjp/jindolf/net}/ProxyInfo.java | 2 +- .../jindolf => sfjp/jindolf/net}/ServerAccess.java | 15 +- .../jindolf/net}/TallyInputStream.java | 7 +- .../jindolf/net}/TallyOutputStream.java | 7 +- .../java/jp/sfjp/jindolf/net/package-info.java | 14 + .../jindolf/package-info.java | 11 +- .../jindolf/summary}/DaySummary.java | 14 +- .../jindolf/summary}/GameSummary.java | 53 +- .../jindolf/summary}/VillageDigest.java | 18 +- .../java/jp/sfjp/jindolf/summary/package-info.java | 14 + .../jindolf => sfjp/jindolf/util}/GUIUtils.java | 92 +-- .../jindolf => sfjp/jindolf/util}/Monodizer.java | 2 +- .../jindolf => sfjp/jindolf/util}/StringUtils.java | 2 +- .../java/jp/sfjp/jindolf/util/package-info.java | 14 + .../jindolf/view}/AccountPanel.java | 28 +- .../jindolf/view}/ActionManager.java | 35 +- .../jindolf/view}/DialogPrefPanel.java | 4 +- .../jindolf => sfjp/jindolf/view}/FilterPanel.java | 12 +- .../jindolf => sfjp/jindolf/view}/FindPanel.java | 82 ++- .../jindolf => sfjp/jindolf/view}/HelpFrame.java | 38 +- .../jindolf/view}/LandInfoPanel.java | 5 +- .../jindolf => sfjp/jindolf/view}/LandsTree.java | 22 +- .../java/jp/sfjp/jindolf/view/LockErrorPane.java | 178 +++++ .../jindolf => sfjp/jindolf/view}/OptionPanel.java | 13 +- .../jindolf => sfjp/jindolf/view}/PeriodView.java | 11 +- .../jindolf => sfjp/jindolf/view}/TabBrowser.java | 8 +- .../jindolf => sfjp/jindolf/view}/TopView.java | 15 +- .../jindolf => sfjp/jindolf/view}/TopicFilter.java | 14 +- .../jindolf/view}/VillageIconRenderer.java | 26 +- .../jindolf/view}/VillageInfoPanel.java | 3 +- .../java/jp/sfjp/jindolf/view/package-info.java | 14 + src/main/java/jp/sourceforge/jindolf/Jindolf.java | 817 --------------------- .../java/jp/sourceforge/jindolf/OptionInfo.java | 295 -------- .../jindolf/resources/font}/preview.txt | 0 .../jindolf/resources/help.txt | 0 .../jindolf/resources/html/help.css | 0 .../jindolf/resources/html/help.html | 0 .../jindolf/resources/html/keyassign.html | 0 .../jindolf/resources/html/license.html | 0 .../jindolf/resources/html/options.html | 0 .../jindolf/resources/image/logo.png | Bin .../jindolf/resources/image/noimage.png | Bin .../jindolf/resources/image/tb_ascend.png} | Bin .../jindolf/resources/image/tb_descend.png} | Bin .../jindolf/resources/image/tb_editor.png} | Bin .../jindolf/resources/image/tb_filter.png} | Bin .../jindolf/resources/image/tb_find.png} | Bin .../jindolf/resources/image/tb_findnext.png} | Bin .../jindolf/resources/image/tb_findprev.png} | Bin .../jindolf/resources/image/tb_reload.png} | Bin .../jindolf/resources/image/vs_cross.png} | Bin .../jindolf/resources/image/vs_epilogue.png} | Bin .../jindolf/resources/image/vs_gameover.png} | Bin .../jindolf/resources/image/vs_progress.png} | Bin .../jindolf/resources/image/vs_prologue.png} | Bin .../jindolf/resources/image/winicon.png | Bin .../jindolf/resources/image/www.png | Bin .../jp/sfjp/jindolf/resources/version.properties | 12 + .../resources/wolfbbs}/faceIconSet.properties | 0 .../jindolf/resources/version.properties | 12 - .../java/jp/sfjp/jindolf/config/CmdOptionTest.java | 237 ++++++ .../jp/sfjp/jindolf/config/OptionInfoTest.java | 378 ++++++++++ .../jindolf => sfjp/jindolf/data}/AvatarTest.java | 2 +- .../jindolf/net}/HttpUtilsTest.java | 2 +- .../jindolf/util}/StringUtilsTest.java | 2 +- 144 files changed, 5151 insertions(+), 2560 deletions(-) rename src/main/java/jp/{sourceforge => sfjp}/jindolf/Controller.java (89%) create mode 100644 src/main/java/jp/sfjp/jindolf/Jindolf.java create mode 100644 src/main/java/jp/sfjp/jindolf/JindolfGuiJp.java create mode 100644 src/main/java/jp/sfjp/jindolf/JindolfJre15.java create mode 100644 src/main/java/jp/sfjp/jindolf/JindolfOld.java create mode 100644 src/main/java/jp/sfjp/jindolf/JreChecker.java create mode 100644 src/main/java/jp/sfjp/jindolf/ResourceManager.java create mode 100644 src/main/java/jp/sfjp/jindolf/VerInfo.java rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/config}/AppSetting.java (71%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/config}/CmdOption.java (56%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/config}/ConfigFile.java (61%) create mode 100644 src/main/java/jp/sfjp/jindolf/config/ConfigStore.java rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/config}/EnvInfo.java (88%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/config}/FileUtils.java (95%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/config}/InterVMLock.java (99%) create mode 100644 src/main/java/jp/sfjp/jindolf/config/OptionInfo.java create mode 100644 src/main/java/jp/sfjp/jindolf/config/package-info.java rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/data}/Anchor.java (99%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/data}/Avatar.java (99%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/data}/DialogPref.java (99%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/data}/Land.java (96%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/data}/LandsModel.java (97%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/data}/Period.java (99%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/data}/Player.java (99%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/data}/RegexPattern.java (99%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/data}/SysEvent.java (99%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/data}/Talk.java (99%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/data}/Topic.java (91%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/data}/Village.java (98%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/dxchg}/ClipboardAction.java (99%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/dxchg}/CsvExporter.java (98%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/dxchg}/FaceIconSet.java (96%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/dxchg}/TextPopup.java (99%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/dxchg}/UriExporter.java (98%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/dxchg}/WebButton.java (97%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/dxchg}/WebIPC.java (99%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/dxchg}/WebIPCDialog.java (95%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/dxchg}/WolfBBS.java (93%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/dxchg}/XmlResourceResolver.java (99%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/dxchg}/XmlUtils.java (99%) create mode 100644 src/main/java/jp/sfjp/jindolf/dxchg/package-info.java rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/editor}/BalloonBorder.java (99%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/editor}/EditArray.java (99%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/editor}/TalkEditor.java (99%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/editor}/TalkPreview.java (91%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/editor}/TextEditor.java (99%) create mode 100644 src/main/java/jp/sfjp/jindolf/editor/package-info.java rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/glyph}/AbstractTextRow.java (99%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/glyph}/AnchorDraw.java (97%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/glyph}/AnchorHitEvent.java (95%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/glyph}/AnchorHitListener.java (93%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/glyph}/Discussion.java (98%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/glyph}/FontChooser.java (52%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/glyph}/FontInfo.java (56%) create mode 100644 src/main/java/jp/sfjp/jindolf/glyph/FontListModel.java create mode 100644 src/main/java/jp/sfjp/jindolf/glyph/FontPreviewer.java create mode 100644 src/main/java/jp/sfjp/jindolf/glyph/FontSelectList.java rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/glyph}/FontUtils.java (61%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/glyph}/GlyphDraw.java (99%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/glyph}/ImtblAffineTx.java (99%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/glyph}/Selectable.java (96%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/glyph}/SequenceCharacterIterator.java (99%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/glyph}/SysEventDraw.java (98%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/glyph}/TalkDraw.java (98%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/glyph}/TextRow.java (98%) create mode 100644 src/main/java/jp/sfjp/jindolf/glyph/package-info.java rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/log}/LogFrame.java (73%) create mode 100644 src/main/java/jp/sfjp/jindolf/log/LogUtils.java rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/log}/LogWrapper.java (94%) create mode 100644 src/main/java/jp/sfjp/jindolf/log/LoggingDispatcher.java rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/log}/PileHandler.java (51%) create mode 100644 src/main/java/jp/sfjp/jindolf/log/SwingDocHandler.java create mode 100644 src/main/java/jp/sfjp/jindolf/log/package-info.java rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/net}/AccountCookie.java (99%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/net}/HtmlSequence.java (98%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/net}/HttpUtils.java (97%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/net}/ProxyChooser.java (98%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/net}/ProxyInfo.java (99%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/net}/ServerAccess.java (98%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/net}/TallyInputStream.java (96%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/net}/TallyOutputStream.java (95%) create mode 100644 src/main/java/jp/sfjp/jindolf/net/package-info.java rename src/main/java/jp/{sourceforge => sfjp}/jindolf/package-info.java (82%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/summary}/DaySummary.java (97%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/summary}/GameSummary.java (95%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/summary}/VillageDigest.java (98%) create mode 100644 src/main/java/jp/sfjp/jindolf/summary/package-info.java rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/util}/GUIUtils.java (78%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/util}/Monodizer.java (99%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/util}/StringUtils.java (99%) create mode 100644 src/main/java/jp/sfjp/jindolf/util/package-info.java rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/view}/AccountPanel.java (95%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/view}/ActionManager.java (95%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/view}/DialogPrefPanel.java (98%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/view}/FilterPanel.java (98%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/view}/FindPanel.java (94%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/view}/HelpFrame.java (81%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/view}/LandInfoPanel.java (97%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/view}/LandsTree.java (92%) create mode 100644 src/main/java/jp/sfjp/jindolf/view/LockErrorPane.java rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/view}/OptionPanel.java (95%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/view}/PeriodView.java (96%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/view}/TabBrowser.java (97%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/view}/TopView.java (95%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/view}/TopicFilter.java (93%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/view}/VillageIconRenderer.java (78%) rename src/main/java/jp/{sourceforge/jindolf => sfjp/jindolf/view}/VillageInfoPanel.java (98%) create mode 100644 src/main/java/jp/sfjp/jindolf/view/package-info.java delete mode 100644 src/main/java/jp/sourceforge/jindolf/Jindolf.java delete mode 100644 src/main/java/jp/sourceforge/jindolf/OptionInfo.java rename src/main/resources/jp/{sourceforge/jindolf/resources => sfjp/jindolf/resources/font}/preview.txt (100%) rename src/main/resources/jp/{sourceforge => sfjp}/jindolf/resources/help.txt (100%) rename src/main/resources/jp/{sourceforge => sfjp}/jindolf/resources/html/help.css (100%) rename src/main/resources/jp/{sourceforge => sfjp}/jindolf/resources/html/help.html (100%) rename src/main/resources/jp/{sourceforge => sfjp}/jindolf/resources/html/keyassign.html (100%) rename src/main/resources/jp/{sourceforge => sfjp}/jindolf/resources/html/license.html (100%) rename src/main/resources/jp/{sourceforge => sfjp}/jindolf/resources/html/options.html (100%) rename src/main/resources/jp/{sourceforge => sfjp}/jindolf/resources/image/logo.png (100%) rename src/main/resources/jp/{sourceforge => sfjp}/jindolf/resources/image/noimage.png (100%) rename src/main/resources/jp/{sourceforge/jindolf/resources/image/ascend.png => sfjp/jindolf/resources/image/tb_ascend.png} (100%) rename src/main/resources/jp/{sourceforge/jindolf/resources/image/descend.png => sfjp/jindolf/resources/image/tb_descend.png} (100%) rename src/main/resources/jp/{sourceforge/jindolf/resources/image/editor.png => sfjp/jindolf/resources/image/tb_editor.png} (100%) rename src/main/resources/jp/{sourceforge/jindolf/resources/image/filter.png => sfjp/jindolf/resources/image/tb_filter.png} (100%) rename src/main/resources/jp/{sourceforge/jindolf/resources/image/find.png => sfjp/jindolf/resources/image/tb_find.png} (100%) rename src/main/resources/jp/{sourceforge/jindolf/resources/image/findnext.png => sfjp/jindolf/resources/image/tb_findnext.png} (100%) rename src/main/resources/jp/{sourceforge/jindolf/resources/image/findprev.png => sfjp/jindolf/resources/image/tb_findprev.png} (100%) rename src/main/resources/jp/{sourceforge/jindolf/resources/image/reload.png => sfjp/jindolf/resources/image/tb_reload.png} (100%) rename src/main/resources/jp/{sourceforge/jindolf/resources/image/cross.png => sfjp/jindolf/resources/image/vs_cross.png} (100%) rename src/main/resources/jp/{sourceforge/jindolf/resources/image/epilogue.png => sfjp/jindolf/resources/image/vs_epilogue.png} (100%) rename src/main/resources/jp/{sourceforge/jindolf/resources/image/gameover.png => sfjp/jindolf/resources/image/vs_gameover.png} (100%) rename src/main/resources/jp/{sourceforge/jindolf/resources/image/progress.png => sfjp/jindolf/resources/image/vs_progress.png} (100%) rename src/main/resources/jp/{sourceforge/jindolf/resources/image/prologue.png => sfjp/jindolf/resources/image/vs_prologue.png} (100%) rename src/main/resources/jp/{sourceforge => sfjp}/jindolf/resources/image/winicon.png (100%) rename src/main/resources/jp/{sourceforge => sfjp}/jindolf/resources/image/www.png (100%) create mode 100644 src/main/resources/jp/sfjp/jindolf/resources/version.properties rename src/main/resources/jp/{sourceforge/jindolf/resources => sfjp/jindolf/resources/wolfbbs}/faceIconSet.properties (100%) delete mode 100644 src/main/resources/jp/sourceforge/jindolf/resources/version.properties create mode 100644 src/test/java/jp/sfjp/jindolf/config/CmdOptionTest.java create mode 100644 src/test/java/jp/sfjp/jindolf/config/OptionInfoTest.java rename src/test/java/jp/{sourceforge/jindolf => sfjp/jindolf/data}/AvatarTest.java (99%) rename src/test/java/jp/{sourceforge/jindolf => sfjp/jindolf/net}/HttpUtilsTest.java (98%) rename src/test/java/jp/{sourceforge/jindolf => sfjp/jindolf/util}/StringUtilsTest.java (99%) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 5bb6363..0a2d842 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -10,6 +10,7 @@ Jindolf 変更履歴 ・ninjin氏の連絡先を http://ninjinix.com へ変更。 ・UIの各種文言を修正。 ・L&Fを「MacOSX」から変更する際の例外に対処。(バグ報告#26564) + ・パッケージ構成の整理。 3.206.4 (2011-05-10) ・10億をこえる発言番号へのアンカー参照を抑止。(バグ報告#24477,#24946) diff --git a/pom.xml b/pom.xml index f05d6f1..69dac4b 100644 --- a/pom.xml +++ b/pom.xml @@ -95,8 +95,8 @@ ${project.mainconf}/checks.xml false - jp.sourceforge.jindolf.Jindolf - jp/sourceforge/jindolf/resources/image/logo.png + jp.sfjp.jindolf.Jindolf + jp/sfjp/jindolf/resources/image/logo.png @@ -191,7 +191,7 @@ org.apache.maven.plugins maven-jar-plugin - 2.3.2 + 2.4 @@ -234,7 +234,7 @@ org.apache.maven.plugins maven-assembly-plugin - 2.2.1 + 2.3 src/main/assembly/descriptor.xml @@ -410,7 +410,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.8 + 2.8.1 false true @@ -439,7 +439,7 @@ org.apache.maven.plugins maven-surefire-report-plugin - 2.10 + 2.12 false @@ -502,7 +502,7 @@ org.codehaus.mojo findbugs-maven-plugin - 2.3.2 + 2.4.0 true Max diff --git a/src/main/java/jp/sourceforge/jindolf/Controller.java b/src/main/java/jp/sfjp/jindolf/Controller.java similarity index 89% rename from src/main/java/jp/sourceforge/jindolf/Controller.java rename to src/main/java/jp/sfjp/jindolf/Controller.java index 6781c54..b089feb 100644 --- a/src/main/java/jp/sourceforge/jindolf/Controller.java +++ b/src/main/java/jp/sfjp/jindolf/Controller.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf; import java.awt.BorderLayout; import java.awt.Component; @@ -55,8 +55,47 @@ import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.event.TreeWillExpandListener; import javax.swing.tree.TreePath; +import jp.sfjp.jindolf.config.AppSetting; +import jp.sfjp.jindolf.config.ConfigStore; +import jp.sfjp.jindolf.config.OptionInfo; +import jp.sfjp.jindolf.data.Anchor; +import jp.sfjp.jindolf.data.DialogPref; +import jp.sfjp.jindolf.data.Land; +import jp.sfjp.jindolf.data.LandsModel; +import jp.sfjp.jindolf.data.Period; +import jp.sfjp.jindolf.data.RegexPattern; +import jp.sfjp.jindolf.data.Talk; +import jp.sfjp.jindolf.data.Village; +import jp.sfjp.jindolf.dxchg.CsvExporter; +import jp.sfjp.jindolf.dxchg.WebIPCDialog; +import jp.sfjp.jindolf.editor.TalkPreview; +import jp.sfjp.jindolf.glyph.AnchorHitEvent; +import jp.sfjp.jindolf.glyph.AnchorHitListener; +import jp.sfjp.jindolf.glyph.Discussion; +import jp.sfjp.jindolf.glyph.FontInfo; +import jp.sfjp.jindolf.glyph.TalkDraw; +import jp.sfjp.jindolf.log.LogFrame; +import jp.sfjp.jindolf.log.LogUtils; +import jp.sfjp.jindolf.log.LogWrapper; +import jp.sfjp.jindolf.net.ProxyInfo; +import jp.sfjp.jindolf.net.ServerAccess; +import jp.sfjp.jindolf.summary.DaySummary; +import jp.sfjp.jindolf.summary.VillageDigest; +import jp.sfjp.jindolf.util.GUIUtils; +import jp.sfjp.jindolf.util.StringUtils; +import jp.sfjp.jindolf.view.AccountPanel; +import jp.sfjp.jindolf.view.ActionManager; +import jp.sfjp.jindolf.view.FilterPanel; +import jp.sfjp.jindolf.view.FindPanel; +import jp.sfjp.jindolf.view.HelpFrame; +import jp.sfjp.jindolf.view.LandsTree; +import jp.sfjp.jindolf.view.OptionPanel; +import jp.sfjp.jindolf.view.PeriodView; +import jp.sfjp.jindolf.view.TabBrowser; +import jp.sfjp.jindolf.view.TopView; import jp.sourceforge.jindolf.corelib.LandDef; import jp.sourceforge.jindolf.corelib.VillageState; +import jp.sourceforge.jovsonz.JsObject; /** * いわゆるMVCでいうとこのコントローラ。 @@ -68,6 +107,29 @@ public class Controller ChangeListener, AnchorHitListener { + private static final String TITLE_LOGGER = + VerInfo.getFrameTitle("ログ表示"); + private static final String TITLE_FILTER = + VerInfo.getFrameTitle("発言フィルタ"); + private static final String TITLE_EDITOR = + VerInfo.getFrameTitle("発言エディタ"); + private static final String TITLE_OPTION = + VerInfo.getFrameTitle("オプション設定"); + private static final String TITLE_FIND = + VerInfo.getFrameTitle("発言検索"); + private static final String TITLE_ACCOUNT = + VerInfo.getFrameTitle("アカウント管理"); + private static final String TITLE_DIGEST = + VerInfo.getFrameTitle("村のダイジェスト"); + private static final String TITLE_DAYSUMMARY = + VerInfo.getFrameTitle("発言集計"); + private static final String TITLE_HELP = + VerInfo.getFrameTitle("ヘルプ"); + + private static final LogWrapper LOGGER = new LogWrapper(); + + + private final AppSetting appSetting; private final ActionManager actionManager; private final TopView topView; private final LandsModel model; @@ -90,15 +152,19 @@ public class Controller /** * コントローラの生成。 + * @param setting アプリ設定 * @param actionManager アクション管理 * @param topView 最上位ビュー * @param model 最上位データモデル */ - public Controller(ActionManager actionManager, + @SuppressWarnings("LeakingThisInConstructor") + public Controller(AppSetting setting, + ActionManager actionManager, TopView topView, LandsModel model){ super(); + this.appSetting = setting; this.actionManager = actionManager; this.topView = topView; this.model = model; @@ -124,43 +190,37 @@ public class Controller reloadVillageListButton.setEnabled(false); this.filterFrame = new FilterPanel(this.topFrame); + this.filterFrame.setTitle(TITLE_FILTER); this.filterFrame.addChangeListener(this); this.filterFrame.pack(); this.filterFrame.setVisible(false); this.showlogFrame = new LogFrame(this.topFrame); + this.showlogFrame.setTitle(TITLE_LOGGER); this.showlogFrame.pack(); this.showlogFrame.setSize(600, 500); this.showlogFrame.setLocationByPlatform(true); this.showlogFrame.setVisible(false); - if(Jindolf.hasLoggingPermission()){ - Handler newHandler = this.showlogFrame.getHandler(); - Logger jre14Logger = Jindolf.logger().getJre14Logger(); - jre14Logger.addHandler(newHandler); - Handler[] handlers = jre14Logger.getHandlers(); - for(Handler handler : handlers){ - if( ! (handler instanceof PileHandler) ) continue; - PileHandler pile = (PileHandler) handler; - pile.delegate(newHandler); - pile.close(); - } - } + Logger rootLogger = Logger.getLogger(""); + Handler newHandler = this.showlogFrame.getHandler(); + LogUtils.switchHandler(rootLogger, newHandler); this.talkPreview = new TalkPreview(); + this.talkPreview.setTitle(TITLE_EDITOR); this.talkPreview.pack(); this.talkPreview.setSize(700, 500); this.talkPreview.setVisible(false); - this.talkPreview.loadDraft(); this.optionPanel = new OptionPanel(this.topFrame); + this.optionPanel.setTitle(TITLE_OPTION); this.optionPanel.pack(); this.optionPanel.setSize(450, 500); this.optionPanel.setVisible(false); this.findPanel = new FindPanel(this.topFrame); + this.findPanel.setTitle(TITLE_FIND); this.findPanel.pack(); this.findPanel.setVisible(false); - this.findPanel.loadHistory(); this.windowMap.put(this.filterFrame, true); this.windowMap.put(this.showlogFrame, false); @@ -168,17 +228,23 @@ public class Controller this.windowMap.put(this.optionPanel, false); this.windowMap.put(this.findPanel, true); - AppSetting setting = Jindolf.getAppSetting(); + ConfigStore config = this.appSetting.getConfigStore(); + + JsObject draft = config.loadDraftConfig(); + this.talkPreview.putJson(draft); - FontInfo fontInfo = setting.getFontInfo(); + JsObject history = config.loadHistoryConfig(); + this.findPanel.putJson(history); + + FontInfo fontInfo = this.appSetting.getFontInfo(); this.topView.getTabBrowser().setFontInfo(fontInfo); this.talkPreview.setFontInfo(fontInfo); this.optionPanel.getFontChooser().setFontInfo(fontInfo); - ProxyInfo proxyInfo = setting.getProxyInfo(); + ProxyInfo proxyInfo = this.appSetting.getProxyInfo(); this.optionPanel.getProxyChooser().setProxyInfo(proxyInfo); - DialogPref pref = setting.getDialogPref(); + DialogPref pref = this.appSetting.getDialogPref(); this.topView.getTabBrowser().setDialogPref(pref); this.optionPanel.getDialogPrefPanel().setDialogPref(pref); @@ -224,24 +290,14 @@ public class Controller * About画面を表示する。 */ private void actionAbout(){ - String message = - Jindolf.TITLE - + " Version " + Jindolf.VERSION + "\n" - + Jindolf.COPYRIGHT + "\n" - + "ライセンス: " + Jindolf.LICENSE + "\n" - + "連絡先: " + Jindolf.CONTACT; - - if(Jindolf.COMMENT.length() > 0){ - message += "\n" + Jindolf.COMMENT; - } - + String message = VerInfo.getAboutMessage(); JOptionPane pane = new JOptionPane(message, JOptionPane.INFORMATION_MESSAGE, JOptionPane.DEFAULT_OPTION, GUIUtils.getLogoIcon()); JDialog dialog = pane.createDialog(this.topFrame, - Jindolf.TITLE + "について"); + VerInfo.TITLE + "について"); dialog.pack(); dialog.setVisible(true); @@ -267,7 +323,11 @@ public class Controller return; } - this.helpFrame = new HelpFrame(); + OptionInfo optInfo = this.appSetting.getOptionInfo(); + ConfigStore configStore = this.appSetting.getConfigStore(); + + this.helpFrame = new HelpFrame(optInfo, configStore); + this.helpFrame.setTitle(TITLE_HELP); this.helpFrame.pack(); this.helpFrame.setSize(450, 450); @@ -420,7 +480,7 @@ public class Controller * ポータルサイトをWebブラウザで表示する。 */ private void actionShowPortal(){ - WebIPCDialog.showDialog(this.topFrame, Jindolf.CONTACT); + WebIPCDialog.showDialog(this.topFrame, VerInfo.CONTACT); return; } @@ -431,11 +491,11 @@ public class Controller * @param e 例外 */ private void warnDialog(String title, String message, Throwable e){ - Jindolf.logger().warn(message, e); + LOGGER.warn(message, e); JOptionPane.showMessageDialog( this.topFrame, message, - title + " - " + Jindolf.TITLE, + VerInfo.getFrameTitle(title), JOptionPane.WARNING_MESSAGE ); return; } @@ -481,7 +541,7 @@ public class Controller return; } - Jindolf.logger().info( + LOGGER.info( "Look&Feelが[" +lnf.getName() +"]に変更されました。"); @@ -510,10 +570,10 @@ public class Controller try{ SwingUtilities.invokeAndWait(updateUITask); }catch(InvocationTargetException e){ - Jindolf.logger().warn( + LOGGER.warn( "Look&Feelの更新に失敗しました。", e); }catch(InterruptedException e){ - Jindolf.logger().warn( + LOGGER.warn( "Look&Feelの更新に失敗しました。", e); }finally{ updateStatusBar("Look&Feelが更新されました"); @@ -544,6 +604,7 @@ public class Controller } this.accountFrame = new AccountPanel(this.topFrame, this.model); + this.accountFrame.setTitle(TITLE_ACCOUNT); this.accountFrame.pack(); this.accountFrame.setVisible(true); @@ -572,15 +633,13 @@ public class Controller * オプション設定画面を表示する。 */ private void actionOption(){ - AppSetting setting = Jindolf.getAppSetting(); - - FontInfo fontInfo = setting.getFontInfo(); + FontInfo fontInfo = this.appSetting.getFontInfo(); this.optionPanel.getFontChooser().setFontInfo(fontInfo); - ProxyInfo proxyInfo = setting.getProxyInfo(); + ProxyInfo proxyInfo = this.appSetting.getProxyInfo(); this.optionPanel.getProxyChooser().setProxyInfo(proxyInfo); - DialogPref dialogPref = setting.getDialogPref(); + DialogPref dialogPref = this.appSetting.getDialogPref(); this.optionPanel.getDialogPrefPanel().setDialogPref(dialogPref); this.optionPanel.setVisible(true); @@ -603,11 +662,10 @@ public class Controller * @param newFontInfo 新フォント設定 */ private void updateFontInfo(final FontInfo newFontInfo){ - AppSetting setting = Jindolf.getAppSetting(); - FontInfo oldInfo = setting.getFontInfo(); + FontInfo oldInfo = this.appSetting.getFontInfo(); if(newFontInfo.equals(oldInfo)) return; - setting.setFontInfo(newFontInfo); + this.appSetting.setFontInfo(newFontInfo); this.topView.getTabBrowser().setFontInfo(newFontInfo); this.talkPreview.setFontInfo(newFontInfo); @@ -621,11 +679,10 @@ public class Controller * @param newProxyInfo 新プロクシ設定 */ private void updateProxyInfo(ProxyInfo newProxyInfo){ - AppSetting setting = Jindolf.getAppSetting(); - ProxyInfo oldProxyInfo = setting.getProxyInfo(); + ProxyInfo oldProxyInfo = this.appSetting.getProxyInfo(); if(newProxyInfo.equals(oldProxyInfo)) return; - setting.setProxyInfo(newProxyInfo); + this.appSetting.setProxyInfo(newProxyInfo); for(Land land : this.model.getLandList()){ ServerAccess server = land.getServerAccess(); @@ -640,11 +697,10 @@ public class Controller * @param newDialogPref 表示設定 */ private void updateDialogPref(DialogPref newDialogPref){ - AppSetting setting = Jindolf.getAppSetting(); - DialogPref oldDialogPref = setting.getDialogPref(); + DialogPref oldDialogPref = this.appSetting.getDialogPref(); if(newDialogPref.equals(oldDialogPref)) return; - setting.setDialogPref(newDialogPref); + this.appSetting.setDialogPref(newDialogPref); this.topView.getTabBrowser().setDialogPref(newDialogPref); @@ -665,7 +721,7 @@ public class Controller ) || ! village.isValid() ){ String message = "エピローグを正常に迎えていない村は\n" +"ダイジェスト機能を利用できません"; - String title = "ダイジェスト不可 - " + Jindolf.TITLE; + String title = VerInfo.getFrameTitle("ダイジェスト不可"); JOptionPane pane = new JOptionPane(message, JOptionPane.WARNING_MESSAGE, JOptionPane.DEFAULT_OPTION ); @@ -678,6 +734,7 @@ public class Controller if(this.digestPanel == null){ this.digestPanel = new VillageDigest(this.topFrame); + this.digestPanel.setTitle(TITLE_DIGEST); this.digestPanel.pack(); this.digestPanel.setSize(600, 550); this.windowMap.put(this.digestPanel, false); @@ -774,7 +831,7 @@ public class Controller } } loginfo += hitMessage; - Jindolf.logger().info(loginfo); + LOGGER.info(loginfo); return; } @@ -825,7 +882,7 @@ public class Controller } } loginfo += hitMessage; - Jindolf.logger().info(loginfo); + LOGGER.info(loginfo); return; } @@ -853,6 +910,7 @@ public class Controller if(this.daySummaryPanel == null){ this.daySummaryPanel = new DaySummary(this.topFrame); + this.daySummaryPanel.setTitle(TITLE_DAYSUMMARY); this.daySummaryPanel.pack(); this.daySummaryPanel.setSize(400, 500); } @@ -1205,10 +1263,10 @@ public class Controller } }); }catch(InvocationTargetException e){ - Jindolf.logger().fatal( + LOGGER.fatal( "タブ操作で致命的な障害が発生しました", e); }catch(InterruptedException e){ - Jindolf.logger().fatal( + LOGGER.fatal( "タブ操作で致命的な障害が発生しました", e); } updateStatusBar("村情報を読み直しました…"); @@ -1227,10 +1285,10 @@ public class Controller } }); }catch(InvocationTargetException e){ - Jindolf.logger().fatal( + LOGGER.fatal( "ブラウザ表示で致命的な障害が発生しました", e); }catch(InterruptedException e){ - Jindolf.logger().fatal( + LOGGER.fatal( "ブラウザ表示で致命的な障害が発生しました", e); } EventQueue.invokeLater(new Runnable(){ @@ -1342,7 +1400,7 @@ public class Controller * @param e ネットワークエラー */ public void showNetworkError(Land land, IOException e){ - Jindolf.logger().warn("ネットワークで障害が発生しました", e); + LOGGER.warn("ネットワークで障害が発生しました", e); ServerAccess server = land.getServerAccess(); String message = @@ -1357,8 +1415,8 @@ public class Controller JOptionPane.WARNING_MESSAGE, JOptionPane.DEFAULT_OPTION ); - JDialog dialog = pane.createDialog(this.topFrame, - "通信異常発生 - " + Jindolf.TITLE); + String title = VerInfo.getFrameTitle("通信異常発生"); + JDialog dialog = pane.createDialog(this.topFrame, title); dialog.pack(); dialog.setVisible(true); @@ -1642,9 +1700,9 @@ public class Controller try{ SwingUtilities.invokeAndWait(microJob); }catch(InvocationTargetException e){ - Jindolf.logger().fatal("ビジー処理で失敗", e); + LOGGER.fatal("ビジー処理で失敗", e); }catch(InterruptedException e){ - Jindolf.logger().fatal("ビジー処理で失敗", e); + LOGGER.fatal("ビジー処理で失敗", e); } } @@ -1664,15 +1722,9 @@ public class Controller * タイトルは指定された国or村名 + " - Jindolf" * @param name 国or村名 */ - private void setFrameTitle(CharSequence name){ - String title = Jindolf.TITLE; - - if(name != null && name.length() > 0){ - title = name + " - " + title; - } - + private void setFrameTitle(String name){ + String title = VerInfo.getFrameTitle(name); this.topFrame.setTitle(title); - return; } @@ -1680,10 +1732,24 @@ public class Controller * アプリ正常終了処理。 */ private void shutdown(){ - this.findPanel.saveHistory(); - this.talkPreview.saveDraft(); - Jindolf.getAppSetting().saveConfig(); - Jindolf.exit(0); + ConfigStore configStore = this.appSetting.getConfigStore(); + + JsObject findConf = this.findPanel.getJson(); + if( ! this.findPanel.hasConfChanged(findConf) ){ + configStore.saveHistoryConfig(findConf); + } + + JsObject draftConf = this.talkPreview.getJson(); + if( ! this.talkPreview.hasConfChanged(draftConf) ){ + configStore.saveDraftConfig(draftConf); + } + + this.appSetting.saveConfig(); + + LOGGER.info("VMごとアプリケーションを終了します。"); + System.exit(0); // invoke shutdown hooks... BYE ! + + assert false; return; } diff --git a/src/main/java/jp/sfjp/jindolf/Jindolf.java b/src/main/java/jp/sfjp/jindolf/Jindolf.java new file mode 100644 index 0000000..ecfa30f --- /dev/null +++ b/src/main/java/jp/sfjp/jindolf/Jindolf.java @@ -0,0 +1,39 @@ +/* + * Jindolf main class + * + * License : The MIT License + * Copyright(c) 2011 olyutorskii + */ + +package jp.sfjp.jindolf; + +/** + * Jindolf スタートアップクラス。 + *

JRE実行系の互換性検査を主目的とする。 + *

このクラスではJRE1.0互換なランタイムライブラリのみが利用できる。 + *

このクラスはJRE1.0でもコンパイルできなければならない。 + * アプリ開始はstaticメソッド{@link #main(String[])}呼び出しから。 + */ +public final class Jindolf { + + /** + * 隠しコンストラクタ。 + */ + private Jindolf(){ + super(); + return; + } + + /** + * Jindolf のスタートアップエントリ。 + * @param args コマンドライン引数 + */ + public static void main(String[] args){ + JreChecker.checkJre(); + + JindolfJre15.main(args); + + return; + } + +} diff --git a/src/main/java/jp/sfjp/jindolf/JindolfGuiJp.java b/src/main/java/jp/sfjp/jindolf/JindolfGuiJp.java new file mode 100644 index 0000000..e4c1f57 --- /dev/null +++ b/src/main/java/jp/sfjp/jindolf/JindolfGuiJp.java @@ -0,0 +1,68 @@ +/* + * Jindolf main class + * + * License : The MIT License + * Copyright(c) 2011 olyutorskii + */ + +package jp.sfjp.jindolf; + +import java.util.concurrent.atomic.AtomicBoolean; +import javax.swing.JOptionPane; + +/** + * GUIとUnicode出力とリソースアクセスが解禁された + * Jindolf スタートアップクラス。 + *

Jindolf_jre15の下請け。 + */ +public final class JindolfGuiJp { + + private static final String TITLE_INVOKEDBL = "多重起動"; + private static final String MSG_INVOKEDBL = + "ERROR : 二度目以降の起動がキャンセルされました。"; + + /** 多重起動防止用セマフォ。 */ + private static final AtomicBoolean INVOKE_FLAG = + new AtomicBoolean(false); + + + /** + * 隠しコンストラクタ。 + */ + private JindolfGuiJp(){ + super(); + assert false; + return; + } + + /** + * JVM内で多重起動していないかチェックする。 + *

多重起動を確認した場合は、GUIにダイアログを出力する。 + * @return 多重起動していたらtrue + */ + private static boolean hasInvokedCheck(){ + boolean successed = INVOKE_FLAG.compareAndSet(false, true); + if(successed) return false; + + JOptionPane.showMessageDialog(null, + MSG_INVOKEDBL, + TITLE_INVOKEDBL, + JOptionPane.ERROR_MESSAGE); + + return true; + } + + /** + * Jindolf のスタートアップエントリ。 + *

ここからGUIとUnicode出力とリソースアクセスが解禁される。 + * @param args コマンドライン引数 + */ + static void main(String... args){ + if(hasInvokedCheck()) return; + + JindolfOld.main(args); + + return; + } + +} diff --git a/src/main/java/jp/sfjp/jindolf/JindolfJre15.java b/src/main/java/jp/sfjp/jindolf/JindolfJre15.java new file mode 100644 index 0000000..7e58b81 --- /dev/null +++ b/src/main/java/jp/sfjp/jindolf/JindolfJre15.java @@ -0,0 +1,171 @@ +/* + * Jindolf main class + * + * License : The MIT License + * Copyright(c) 2011 olyutorskii + */ + +package jp.sfjp.jindolf; + +import java.awt.GraphicsEnvironment; +import javax.swing.JOptionPane; + +/** + * JRE1.5の利用が解禁されたJindolfエントリ。 + *

起動クラスJindolfの下請けとしての機能が想定される。 + *

必ずしも必要ないが、異常系切り分けに有用な、 + * 実行環境やビルドの成否に関する各種診断を行う。 + */ +public final class JindolfJre15 { + + /** exit code. */ + public static final int EXIT_CODE_HEADLESS = 1; + /** exit code. */ + public static final int EXIT_CODE_BUILDENCO = 1; + /** exit code. */ + public static final int EXIT_CODE_INVMANIFEST = 1; + + + /** + * 隠しコンストラクタ。 + */ + private JindolfJre15(){ + super(); + assert false; + return; + } + + + /** + * GUI環境の有無をチェックする。 + * GUI環境に接続できなければJVMを終了させる。 + */ + private static void checkGuiEnv(){ + if( ! GraphicsEnvironment.isHeadless() ) return; + + String dispEnv; + try{ + dispEnv = System.getenv("DISPLAY"); + }catch(SecurityException e){ + dispEnv = null; + } + + StringBuilder message = new StringBuilder(); + + message.append("ERROR : GUI session failed."); + + if(dispEnv != null){ + message.append('\n') + .append("Environment DISPLAY [") + .append(dispEnv) + .append("]"); + } + + System.err.println(message); + System.err.flush(); + + System.exit(EXIT_CODE_HEADLESS); + + assert false; + return; + } + + /** + * エラーダイアログの出力。 + * @param errmsg エラーメッセージ + * @param title タイトル + */ + private static void showErrorDialog(String errmsg, String title){ + JOptionPane.showMessageDialog(null, + errmsg, + title, + JOptionPane.ERROR_MESSAGE); + return; + } + + /** + * ビルド時のエンコーディングミスを判定する。 + * ※ 非Unicode系の開発環境を使いたい人は適当に無視してね。 + */ + private static void checkBuildError(){ + if( '狼' == 0x72fc + && ' ' == 0x3000 + && '~' == 0x007e + && '\\' == 0x005c // バックスラッシュ + && '¥' == 0x00a5 // 半角円通貨 + && '~' == 0xff5e + && '�' == 0xfffd // Unicode専用特殊文字 + ){ + return; + } + + String errmsg = + "ERROR : Invalid source-code encoding detected.\n" + +"Let's check encoding with compiler & source-file."; + + showErrorDialog(errmsg, "Build failed"); + + System.exit(EXIT_CODE_BUILDENCO); + + assert false; + return; + } + + /** + * MANIFEST.MFパッケージ定義エラーの検出。 + */ + private static void checkPackageDefinition(){ + Package rootPkg = ResourceManager.DEF_ROOT_PACKAGE; + String implTitle = rootPkg.getImplementationTitle(); + String implVersion = rootPkg.getImplementationVersion(); + String implVendor = rootPkg.getImplementationVendor(); + + String title = "ビルドエラー"; + + if(implTitle != null && ! VerInfo.TITLE.equals(implTitle) ){ + String errmsg = "パッケージ定義とタイトルが一致しません。" + +"["+ implTitle +"]≠["+ VerInfo.TITLE +"]"; + showErrorDialog(errmsg, title); + System.exit(EXIT_CODE_INVMANIFEST); + assert false; + } + + if(implVersion != null && ! VerInfo.VERSION.equals(implVersion) ){ + String errmsg = "パッケージ定義とバージョン番号が一致しません。" + +"["+ implVersion +"]≠["+ VerInfo.VERSION +"]"; + showErrorDialog(errmsg, title); + System.exit(EXIT_CODE_INVMANIFEST); + assert false; + } + + if(implVendor != null && ! VerInfo.AUTHOR.equals(implVendor) ){ + String errmsg = "パッケージ定義とベンダが一致しません。" + +"["+ implVendor +"]≠["+ VerInfo.AUTHOR +"]"; + showErrorDialog(errmsg, title); + System.exit(EXIT_CODE_INVMANIFEST); + assert false; + } + + return; + } + + /** + * Jindolf のスタートアップエントリ。 + *

ここからJRE1.5の利用が解禁される。 + * @param args コマンドライン引数 + */ + static void main(String... args){ + checkGuiEnv(); + // ここから異常系でのSwingGUI解禁 + + checkBuildError(); + // ここからUnicode出力解禁。 + + checkPackageDefinition(); + + JindolfGuiJp.main(args); + + return; + } + +} diff --git a/src/main/java/jp/sfjp/jindolf/JindolfOld.java b/src/main/java/jp/sfjp/jindolf/JindolfOld.java new file mode 100644 index 0000000..f0b1cf8 --- /dev/null +++ b/src/main/java/jp/sfjp/jindolf/JindolfOld.java @@ -0,0 +1,452 @@ +/* + * Jindolf main class + * + * License : The MIT License + * Copyright(c) 2008 olyutorskii + */ + +package jp.sfjp.jindolf; + +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Window; +import java.lang.reflect.InvocationTargetException; +import java.text.DateFormat; +import java.text.NumberFormat; +import java.util.Date; +import javax.swing.ImageIcon; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JWindow; +import javax.swing.UIManager; +import jp.sfjp.jindolf.config.AppSetting; +import jp.sfjp.jindolf.config.CmdOption; +import jp.sfjp.jindolf.config.ConfigFile; +import jp.sfjp.jindolf.config.ConfigStore; +import jp.sfjp.jindolf.config.EnvInfo; +import jp.sfjp.jindolf.config.OptionInfo; +import jp.sfjp.jindolf.data.LandsModel; +import jp.sfjp.jindolf.glyph.Discussion; +import jp.sfjp.jindolf.glyph.GlyphDraw; +import jp.sfjp.jindolf.log.LogUtils; +import jp.sfjp.jindolf.log.LogWrapper; +import jp.sfjp.jindolf.log.LoggingDispatcher; +import jp.sfjp.jindolf.util.GUIUtils; +import jp.sfjp.jindolf.view.ActionManager; +import jp.sfjp.jindolf.view.TabBrowser; +import jp.sfjp.jindolf.view.TopView; + +/** + * Jindolf スタートアップクラス。 + * + * コンストラクタは無いよ。 + * アプリ開始はstaticメソッド{@link #main(String[])}呼び出しから。 + */ +public final class JindolfOld { + + /** このClass。 */ + public static final Class SELF_KLASS; + /** クラスローダ。 */ + public static final ClassLoader LOADER; + + + /** クラスロード時のナノカウント。 */ + public static final long NANOCT_LOADED; + /** クラスロード時刻(エポックmsec)。 */ + public static final long EPOCHMS_LOADED; + + + /** ロガー。 */ + private static final LogWrapper LOGGER = new LogWrapper(); + + /** スプラッシュロゴ。 */ + private static final String RES_LOGOICON = + "resources/image/logo.png"; + + static{ + SELF_KLASS = JindolfOld.class; + + ClassLoader thisLoader; + try{ + thisLoader = SELF_KLASS.getClassLoader(); + }catch(SecurityException e){ + thisLoader = null; + } + LOADER = thisLoader; + + NANOCT_LOADED = System.nanoTime(); + EPOCHMS_LOADED = System.currentTimeMillis(); + + new JindolfOld().hashCode(); + } + + + /** + * 隠れコンストラクタ。 + */ + private JindolfOld(){ + super(); + assert this.getClass() == SELF_KLASS; + return; + } + + + /** + * 標準出力端末にヘルプメッセージ(オプションの説明)を表示する。 + */ + private static void showHelpMessage(){ + System.out.flush(); + System.err.flush(); + + CharSequence helpText = CmdOption.getHelpText(); + System.out.print(helpText); + + System.out.flush(); + System.err.flush(); + + return; + } + + /** + * スプラッシュウィンドウを表示する。 + *

JRE1.6以降では何も表示しない。 + * @return スプラッシュウィンドウ。JRE1.6以降ならnullを返す。 + */ + @SuppressWarnings("CallToThreadYield") + private static Window showSplash(){ + if(JreChecker.has16Runtime()) return null; + + Window splashWindow = new JWindow(); + + ImageIcon logo = ResourceManager.getImageIcon(RES_LOGOICON); + JLabel splashLabel = new JLabel(logo); + splashWindow.add(splashLabel); + + splashWindow.pack(); + splashWindow.setLocationRelativeTo(null); // locate center + splashWindow.setVisible(true); + + Thread.yield(); + + return splashWindow; + } + + /** + * スプラッシュウィンドウを隠す。 + * @param splashWindow スプラッシュウィンドウ。nullならなにもしない。 + */ + @SuppressWarnings("CallToThreadYield") + private static void hideSplash(Window splashWindow){ + if(splashWindow == null) return; + + splashWindow.setVisible(false); + splashWindow.dispose(); + + Thread.yield(); + + return; + } + + /** + * 起動時の諸々の情報をログ出力する。 + * @param optinfo コマンドライン情報 + * @param configStore 設定ディレクトリ情報 + */ + private static void dumpBootInfo(OptionInfo optinfo, + ConfigStore configStore ){ + DateFormat dform = DateFormat.getDateTimeInstance(); + NumberFormat nform = NumberFormat.getNumberInstance(); + + LOGGER.info( + VerInfo.ID + " は " + + dform.format(new Date(EPOCHMS_LOADED)) + + " にVM上のクラス " + + SELF_KLASS.getName() + " としてロードされました。 " ); + + LOGGER.info("Initial Nano-Count : " + nform.format(NANOCT_LOADED)); + + Runtime runtime = Runtime.getRuntime(); + LOGGER.info( + "Max-heap : " + + nform.format(runtime.maxMemory()) + " Byte" + + " Total-heap : " + + nform.format(runtime.totalMemory()) + " Byte"); + + StringBuilder bootArgs = new StringBuilder(); + bootArgs.append("\n\n").append("起動時引数:\n"); + for(String arg : optinfo.getInvokeArgList()){ + bootArgs.append("\u0020\u0020").append(arg).append('\n'); + } + bootArgs.append('\n'); + bootArgs.append(EnvInfo.getVMInfo()); + LOGGER.info(bootArgs); + + if(configStore.useStoreFile()){ + LOGGER.info("設定格納ディレクトリに[ " + + configStore.getConfigPath().getPath() + + " ]が指定されました。"); + }else{ + LOGGER.info("設定格納ディレクトリは使いません。"); + } + + if( JreChecker.has16Runtime() + && optinfo.hasOption(CmdOption.OPT_NOSPLASH) ){ + LOGGER.warn( + "JRE1.6以降では、" + +"Jindolfの-nosplashオプションは無効です。" + + "Java実行系の方でスプラッシュ画面の非表示を" + + "指示してください(おそらく空の-splash:オプション)" ); + } + + if(LOADER == null){ + LOGGER.warn( + "セキュリティ設定により、" + +"クラスローダを取得できませんでした"); + } + + return; + } + + /** + * 任意のクラス群に対して一括ロード/初期化を単一スレッドで順に行う。 + * どーしてもクラス初期化の順序に依存する障害が発生する場合や + * クラス初期化のオーバーヘッドでGUIの操作性が損なわれるときなどにどうぞ。 + * + * @throws java.lang.LinkageError クラス間リンケージエラー。 + * @throws java.lang.ExceptionInInitializerError クラス初期化で異常 + */ + private static void preInitClass() + throws LinkageError, + ExceptionInInitializerError { + Object[] classes = { // Class型 または String型 + "java.lang.Object", + TabBrowser.class, + Discussion.class, + GlyphDraw.class, + java.net.HttpURLConnection.class, + java.text.SimpleDateFormat.class, + Void.class, + }; + + for(Object obj : classes){ + String className; + if(obj instanceof Class){ + className = ((Class)obj).getName(); + }else if(obj instanceof String){ + className = obj.toString(); + }else{ + continue; + } + + try{ + if(LOADER != null){ + Class.forName(className, true, LOADER); + }else{ + Class.forName(className); + } + }catch(ClassNotFoundException e){ + LOGGER.warn("クラスの明示的ロードに失敗しました", e); + continue; + } + } + + return; + } + + /** + * JindolfOld のスタートアップエントリ。 + * + * @param args コマンドライン引数 + */ + static void main(String... args){ + OptionInfo optinfo; + + try{ + optinfo = OptionInfo.parseOptions(args); + }catch(IllegalArgumentException e){ + String message = e.getLocalizedMessage(); + System.err.println(message); + System.err.println( + "起動オプション一覧は、" + + "起動オプションに「" + + CmdOption.OPT_HELP.toString() + + "」を指定すると確認できます。" ); + System.exit(1); + assert false; + return; + } + + main(optinfo); + + return; + } + + /** + * JindolfOld のスタートアップエントリ。 + * + * @param optinfo コマンドライン引数情報 + */ + static void main(OptionInfo optinfo){ + if(optinfo.hasOption(CmdOption.OPT_HELP)){ + showHelpMessage(); + System.exit(0); + assert false; + return; + } + + if(optinfo.hasOption(CmdOption.OPT_VERSION)){ + System.out.println(VerInfo.ID); + System.exit(0); + assert false; + return; + } + + // ここ以降、アプリウィンドウの生成と表示に向けてまっしぐら。 + + // あらゆるSwing文字列表示処理より前に必要。 + // システムプロパティ swing.boldMetal は無視される。 + Boolean boldFlag; + if(optinfo.hasOption(CmdOption.OPT_BOLDMETAL)){ + // もの凄く日本語表示が汚くなるかもよ!注意 + boldFlag = Boolean.TRUE; + }else{ + boldFlag = Boolean.FALSE; + } + UIManager.put("swing.boldMetal", boldFlag); + + // JRE1.5用スプラッシュウィンドウ + Window splashWindow = null; + if( ! optinfo.hasOption(CmdOption.OPT_NOSPLASH) ){ + splashWindow = showSplash(); + } + + boolean hasError = false; + try{ + hasError = splashedMain(optinfo); + }finally{ + hideSplash(splashWindow); + } + + if(hasError) System.exit(1); + + return; + } + + /** + * JindolfOld のスタートアップエントリ。 + *

スプラッシュウィンドウが出ている状態。 + * @param optinfo コマンドライン引数情報 + * @return エラーがあればtrue + */ + static boolean splashedMain(OptionInfo optinfo){ + final AppSetting appSetting = new AppSetting(); + appSetting.applyOptionInfo(optinfo); + + if(optinfo.hasOption(CmdOption.OPT_VMINFO)){ + System.out.println(EnvInfo.getVMInfo()); + } + + LogUtils.initRootLogger(optinfo.hasOption(CmdOption.OPT_CONSOLELOG)); + // ここからロギング解禁 + + ConfigStore configStore = appSetting.getConfigStore(); + dumpBootInfo(optinfo, configStore); + + ConfigFile.setupConfigDirectory(configStore); + ConfigFile.setupLockFile(configStore); + // ここから設定格納ディレクトリ解禁 + + appSetting.loadConfig(); + + final Runtime runtime = Runtime.getRuntime(); + runtime.addShutdownHook(new Thread(){ + @Override + @SuppressWarnings("CallToThreadYield") + public void run(){ + LOGGER.info("シャットダウン処理に入ります…"); + System.out.flush(); + System.err.flush(); + runtime.gc(); + Thread.yield(); + runtime.runFinalization(); // 危険? + Thread.yield(); + return; + } + }); + + preInitClass(); + + LoggingDispatcher.replaceEventQueue(); + + boolean hasError = false; + try{ + EventQueue.invokeAndWait(new Runnable(){ + public void run(){ + startGUI(appSetting); + return; + } + }); + }catch(InvocationTargetException e){ + LOGGER.fatal("アプリケーション初期化に失敗しました", e); + e.printStackTrace(System.err); + hasError = true; + }catch(InterruptedException e){ + LOGGER.fatal("アプリケーション初期化に失敗しました", e); + e.printStackTrace(System.err); + hasError = true; + } + + return hasError; + } + + /** + * AWTイベントディスパッチスレッド版スタートアップエントリ。 + * @param appSetting アプリ設定 + */ + private static void startGUI(AppSetting appSetting){ + LandsModel model = new LandsModel(); + model.loadLandList(); + + JFrame topFrame = buildMVC(appSetting, model); + + GUIUtils.modifyWindowAttributes(topFrame, true, false, true); + + topFrame.pack(); + + Dimension initGeometry = + new Dimension(appSetting.initialFrameWidth(), + appSetting.initialFrameHeight()); + topFrame.setSize(initGeometry); + + if( appSetting.initialFrameXpos() <= Integer.MIN_VALUE + || appSetting.initialFrameYpos() <= Integer.MIN_VALUE ){ + topFrame.setLocationByPlatform(true); + }else{ + topFrame.setLocation(appSetting.initialFrameXpos(), + appSetting.initialFrameYpos() ); + } + + topFrame.setVisible(true); + + return; + } + + /** + * モデル・ビュー・コントローラの結合。 + * @param appSetting アプリ設定 + * @param model 最上位のデータモデル + * @return アプリケーションのトップフレーム + */ + private static JFrame buildMVC(AppSetting appSetting, LandsModel model){ + ActionManager actionManager = new ActionManager(); + TopView topView = new TopView(); + + Controller controller = + new Controller(appSetting, actionManager, topView, model); + + JFrame topFrame = controller.createTopFrame(); + + return topFrame; + } + +} diff --git a/src/main/java/jp/sfjp/jindolf/JreChecker.java b/src/main/java/jp/sfjp/jindolf/JreChecker.java new file mode 100644 index 0000000..a23ea9f --- /dev/null +++ b/src/main/java/jp/sfjp/jindolf/JreChecker.java @@ -0,0 +1,277 @@ +/* + * JRE checker + * + * License : The MIT License + * Copyright(c) 2011 olyutorskii + */ + +package jp.sfjp.jindolf; + +import javax.swing.JOptionPane; + +/** + * JRE互換性のチェックを行う。 + *

JREのバージョンと、 + * JREに含まれるjava.langパッケージ仕様のバージョンは互換性があるものとする。 + *

なるべく昔のJREでも動くように。 + * 少なくとも1.2以降。できれば1.0以降。 + * 原則、1.3以降の新設ライブラリは利用禁止。 + *

なるべく昔のコンパイラでもコンパイルできるように。 + * 少なくとも1.2以降。できれば1.0以降。 + * 原則、assert文、総称ジェネリクス、アノテーションは禁止。 + *

できればBasic-Latinに入らない文字(日本語)の出力も禁止。 + *

ランタイム存在検査用のクラスは、ロードや初期化が軽いほうが望ましい。 + * そしていずれJindolfの実行に必要なものであるのが望ましい。 + * もしそうでない場合でも、 + * Jindolfに関係ないクラスの連鎖ロードが起きにくいほうが望ましい。 + */ +public final class JreChecker { + + /** required JRE version. */ + public static final String REQUIRED_JRE_VER = "1.5"; + + /** exit code. */ + public static final int EXIT_CODE_INCOMPAT_JRE = 1; + + private static final String DIALOG_TITLE = + "JRE Incompatibility detected..."; + + private static final int MAX_LINE = 40; + + + /** + * 隠しコンストラクタ。 + */ + private JreChecker(){ + super(); + return; + } + + + /** + * クラス名に相当するクラスがロードできるか判定する。 + * @param klassName FQDNなクラス名 + * @return ロードできたらtrue + */ + private static boolean hasClass(String klassName){ + boolean result = false; + + try{ + Class.forName(klassName); // 1.2Laterな3引数版メソッドは利用禁止 + result = true; + }catch(ClassNotFoundException e){ + result = false; + }catch(LinkageError e){ + throw e; + } + + return result; + } + + /** + * JRE 1.1 相当のランタイムライブラリが提供されているか判定する。 + * @return 提供されているならtrue + */ + public static boolean has11Runtime(){ + boolean result = hasClass("java.io.Serializable"); + return result; + } + + /** + * JRE 1.2 相当のランタイムライブラリが提供されているか判定する。 + * @return 提供されているならtrue + */ + public static boolean has12Runtime(){ + boolean result; + if(has11Runtime()) result = hasClass("java.util.Iterator"); + else result = false; + return result; + } + + /** + * JRE 1.3 相当のランタイムライブラリが提供されているか判定する。 + * @return 提供されているならtrue + */ + public static boolean has13Runtime(){ + boolean result; + if(has12Runtime()) result = hasClass("java.util.TimerTask"); + else result = false; + return result; + } + + /** + * JRE 1.4 相当のランタイムライブラリが提供されているか判定する。 + * @return 提供されているならtrue + */ + public static boolean has14Runtime(){ + boolean result; + if(has13Runtime()) result = hasClass("java.lang.CharSequence"); + else result = false; + return result; + } + + /** + * JRE 1.5 相当のランタイムライブラリが提供されているか判定する。 + * @return 提供されているならtrue + */ + public static boolean has15Runtime(){ + boolean result; + if(has14Runtime()) result = hasClass("java.lang.Appendable"); + else result = false; + return result; + } + + /** + * JRE 1.6 相当のランタイムライブラリが提供されているか判定する。 + * @return 提供されているならtrue + */ + public static boolean has16Runtime(){ + boolean result; + if(has15Runtime()) result = hasClass("java.util.Deque"); + else result = false; + return result; + } + + /** + * JREもしくはjava.langパッケージの仕様バージョンを返す。 + * @return 仕様バージョン文字列。不明ならnull + */ + public static String getLangPkgSpec(){ + String result; + + try{ + result = System.getProperty("java.specification.version"); + }catch(SecurityException e){ + result = null; + } + if(result != null) return result; + + try{ + result = System.getProperty("java.version"); + }catch(SecurityException e){ + result = null; + } + if(result != null) return result; + + Package javaLangPkg = java.lang.Object.class.getPackage(); + if(javaLangPkg == null) return null; + + result = javaLangPkg.getSpecificationVersion(); + return result; + } + + /** + * JREのインストール情報を返す。 + * @return インストール情報。不明ならnull + */ + public static String getJreHome(){ + String result; + + try{ + result = System.getProperty("java.home"); + }catch(SecurityException e){ + result = null; + } + if(result != null) return result; + + return result; + } + + /** + * 非互換エラーメッセージを組み立てる。 + * @return エラーメッセージ + */ + public static String buildErrMessage(){ + StringBuffer message = new StringBuffer(); + + message.append("ERROR : Java JRE ") + .append(REQUIRED_JRE_VER) + .append(" compatible or later required."); + + String specVer = getLangPkgSpec(); + if(specVer != null){ + message.append('\n') + .append("but").append('\u0020') + .append(specVer) + .append('\u0020').append("detected."); + } + + String jreHome = getJreHome(); + if(jreHome != null){ + message.append(" [ ") + .append(jreHome) + .append(" ]"); + } + + return message.toString(); + } + + /** + * 指定された文字数で行の長さを揃える。 + *

サロゲートペアは無視される。 + * @param text 文字列 + * @param limit 行ごとの最大文字数 + * @return 改行済みの文字列 + */ + public static String alignLine(String text, int limit){ + StringBuffer message = new StringBuffer(); + + int lineLength = 0; + + int textLength = text.length(); + for(int idx = 0; idx < textLength; idx++){ + if(lineLength >= limit){ + message.append('\n'); + lineLength = 0; + } + + char ch = text.charAt(idx); + message.append(ch); + + if(ch == '\n') lineLength = 0; + else lineLength++; + } + + String result = message.toString(); + return result; + } + + /** + * Swingダイアログでエラーを報告する。 + *

ボタンを押すまでの間、実行はブロックされる。 + *

JRE1.2環境が用意されていなければ何もしない。 + *

GUIに接続できなければ何か例外を投げるかもしれない。 + * @param text エラー文面 + */ + public static void showErrorDialog(String text){ + if( ! has12Runtime() ) return; + String aligned = alignLine(text, MAX_LINE); + JOptionPane.showMessageDialog( + null, + aligned, DIALOG_TITLE, + JOptionPane.ERROR_MESSAGE ); + return; + } + + /** + * JRE環境をチェックする。(JRE1.5) + *

もしJREの非互換性が検出されたらエラーメッセージを報告し、 + * 所定の終了コードでJVMを終了させる。 + */ + public static void checkJre(){ + if(has15Runtime()) return; + + // 以降、JVM終了へ向けて一直線。 + try{ + String message = buildErrMessage(); + System.err.println(message); + System.err.flush(); + showErrorDialog(message); + }finally{ + System.exit(EXIT_CODE_INCOMPAT_JRE); + } + + return; + } + +} diff --git a/src/main/java/jp/sfjp/jindolf/ResourceManager.java b/src/main/java/jp/sfjp/jindolf/ResourceManager.java new file mode 100644 index 0000000..e9d3144 --- /dev/null +++ b/src/main/java/jp/sfjp/jindolf/ResourceManager.java @@ -0,0 +1,303 @@ +/* + * resource manager + * + * License : The MIT License + * Copyright(c) 2011 olyutorskii + */ + +package jp.sfjp.jindolf; + +import java.awt.image.BufferedImage; +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.LineNumberReader; +import java.io.Reader; +import java.net.URL; +import java.nio.charset.Charset; +import java.util.Properties; +import javax.imageio.ImageIO; +import javax.swing.ImageIcon; + +/** + * 各種リソースファイルの管理。 + *

{@link Class}用と{@link ClassLoader}用とでは + * 微妙に絶対リソース名の形式が異なることに留意せよ。 + *

基本的に、リソースファイルへのアクセスにおける異常系は + * リカバリの対象外とする。ビルド工程の不手際扱い。 + * @see java.lang.Class#getResource + */ +public final class ResourceManager { + + /** リソース名セパレータ文字。 */ + public static final char RES_SEPCHAR = '/'; + /** パッケージ名セパレータ文字。 */ + public static final char PKG_SEPCHAR = '.'; + + /** リソース名セパレータ文字列。 */ + public static final String RES_SEPARATOR = + Character.toString(RES_SEPCHAR); + /** パッケージ名セパレータ文字列。 */ + public static final String PKG_SEPARATOR = + Character.toString(PKG_SEPCHAR); + + /** デフォルトで用いられるルートパッケージ。 */ + public static final Package DEF_ROOT_PACKAGE; + /** デフォルトで用いられるクラスローダ。 */ + public static final ClassLoader DEF_LOADER; + + private static final Charset CS_UTF8 = Charset.forName("UTF-8"); + + static{ + Class rootKlass = Jindolf.class; + + DEF_ROOT_PACKAGE = rootKlass.getPackage(); + DEF_LOADER = rootKlass.getClassLoader(); + } + + + /** + * 隠しコンストラクタ。 + */ + private ResourceManager(){ + super(); + assert false; + return; + } + + + /** + * リソース名が絶対パスか否か判定する。 + *

リソース名が「/」で始まる場合絶対パスとみなされる。 + *

このリソース名は{@link Class}用であって + * {@link ClassLoader}用ではない。 + * @param resPath リソース名 + * @return 絶対パスならtrueを返す。 + * @see java.lang.Class#getResource + */ + public static boolean isAbsoluteResourcePath(String resPath){ + if (resPath.startsWith(RES_SEPARATOR)) return true; + return false; + } + + /** + * パッケージ情報を反映するリソース名前置詞を返す。 + *

パッケージ名のセパレータ「.」は「/」に置き換えられる。 + * 無名パッケージの場合は長さゼロの空文字列を返す。 + * 無名パッケージを除き、リソース名前置詞は必ず「/」で終わる。 + *

この前置詞は{@link ClassLoader}用であって + * {@link Class}用ではないので、 + * 頭に「/」が付かない。 + * @param pkg パッケージ設定。nullは無名パッケージと認識される。 + * @return リソース名前置詞。無名パッケージの場合は空文字列が返る。 + * @see java.lang.Class#getResource + */ + public static String getResourcePrefix(Package pkg){ + if(pkg == null) return ""; // 無名パッケージ + + String pkgName = pkg.getName(); + String result = pkgName.replace(PKG_SEPCHAR, RES_SEPCHAR); + if( ! result.isEmpty() ){ + result += RES_SEPARATOR; + } + + return result; + } + + /** + * リソース名を用いて、 + * デフォルトのクラスローダとデフォルトのルートパッケージから + * リソースのURLを取得する。 + * @param resPath リソース名 + * @return リソースのURL。リソースが見つからなければnull。 + */ + public static URL getResource(String resPath){ + return getResource(DEF_ROOT_PACKAGE, resPath); + } + + /** + * 任意のルートパッケージと相対リソース名を用いて、 + * デフォルトのクラスローダからリソースのURLを取得する。 + * @param rootPkg ルートパッケージ情報。 + * 「/」で始まる絶対リソース名が指定された場合は無視される。 + * @param resPath リソース名 + * @return リソースのURL。リソースが見つからなければnull。 + */ + public static URL getResource(Package rootPkg, String resPath){ + return getResource(DEF_LOADER, rootPkg, resPath); + } + + /** + * 任意のルートパッケージと相対リソース名を用いて、 + * 任意のクラスローダからリソースのURLを取得する。 + * @param loader クラスローダ + * @param rootPkg ルートパッケージ情報。 + * 「/」で始まる絶対リソース名が指定された場合は無視される。 + * @param resPath リソース名 + * @return リソースのURL。リソースが見つからなければnull。 + */ + public static URL getResource(ClassLoader loader, + Package rootPkg, + String resPath ){ + String fullName; + if(isAbsoluteResourcePath(resPath)){ + fullName = resPath.substring(1); // chop '/' heading + }else{ + String pfx = getResourcePrefix(rootPkg); + fullName = pfx + resPath; + } + + URL result = loader.getResource(fullName); + + return result; + } + + /** + * リソース名を用いて、 + * デフォルトのクラスローダとデフォルトのルートパッケージから + * リソースの入力ストリームを取得する。 + * @param resPath リソース名 + * @return リソースの入力ストリーム。リソースが見つからなければnull。 + */ + public static InputStream getResourceAsStream(String resPath){ + return getResourceAsStream(DEF_ROOT_PACKAGE, resPath); + } + + /** + * 任意のルートパッケージと相対リソース名を用いて、 + * デフォルトのクラスローダからリソースの入力ストリームを取得する。 + * @param rootPkg ルートパッケージ情報。 + * 「/」で始まる絶対リソース名が指定された場合は無視される。 + * @param resPath リソース名 + * @return リソースの入力ストリーム。リソースが見つからなければnull。 + */ + public static InputStream getResourceAsStream(Package rootPkg, + String resPath ){ + return getResourceAsStream(DEF_LOADER, rootPkg, resPath); + } + + /** + * 任意のルートパッケージと相対リソース名を用いて、 + * 任意のクラスローダからリソースの入力ストリームを取得する。 + * @param loader クラスローダ + * @param rootPkg ルートパッケージ情報。 + * 「/」で始まる絶対リソース名が指定された場合は無視される。 + * @param resPath リソース名 + * @return リソースの入力ストリーム。リソースが見つからなければnull。 + */ + public static InputStream getResourceAsStream(ClassLoader loader, + Package rootPkg, + String resPath ){ + URL url = getResource(loader, rootPkg, resPath); + if(url == null) return null; + + InputStream result; + try{ + result = url.openStream(); + }catch (IOException e){ + result = null; + } + + return result; + } + + /** + * リソース名を用いてイメージ画像を取得する。 + * @param resPath 画像リソース名 + * @return イメージ画像。リソースが見つからなければnull。 + */ + public static BufferedImage getBufferedImage(String resPath){ + URL url = getResource(resPath); + if(url == null) return null; + + BufferedImage result; + try{ + result = ImageIO.read(url); + }catch(IOException e){ + result = null; + } + + return result; + } + + /** + * リソース名を用いてアイコン画像を取得する。 + * @param resPath アイコン画像リソース名 + * @return アイコン画像。リソースが見つからなければnull。 + */ + public static ImageIcon getImageIcon(String resPath){ + URL url = getResource(resPath); + if(url == null) return null; + + ImageIcon result = new ImageIcon(url); + + return result; + } + + /** + * リソース名を用いてプロパティを取得する。 + * @param resPath プロパティファイルのリソース名 + * @return プロパティ。リソースが読み込めなければnull。 + */ + public static Properties getProperties(String resPath){ + InputStream is = getResourceAsStream(resPath); + if(is == null) return null; + is = new BufferedInputStream(is); + + Properties properties = new Properties(); + + try{ + properties.load(is); + }catch(IOException e){ + properties = null; + } + + try{ + is.close(); + }catch(IOException e){ + properties = null; + } + + return properties; + } + + /** + * リソース名を用いてUTF-8テキストファイルの内容を取得する。 + *

「#」で始まる行はコメント行として無視される。 + * @param resPath テキストファイルのリソース名 + * @return テキスト。リソースが読み込めなければnull。 + */ + public static CharSequence getTextFile(String resPath){ + InputStream is = getResourceAsStream(resPath); + if(is == null) return null; + is = new BufferedInputStream(is); + + Reader reader = new InputStreamReader(is, CS_UTF8); + LineNumberReader lineReader = new LineNumberReader(reader); + + StringBuilder result = new StringBuilder(); + + for(;;){ + String line; + try{ + line = lineReader.readLine(); + }catch(IOException e){ + result = null; + break; + } + if(line == null) break; + if(line.startsWith("#")) continue; + result.append(line).append('\n'); + } + + try{ + lineReader.close(); + }catch(IOException e){ + result = null; + } + + return result; + } + +} diff --git a/src/main/java/jp/sfjp/jindolf/VerInfo.java b/src/main/java/jp/sfjp/jindolf/VerInfo.java new file mode 100644 index 0000000..7abd857 --- /dev/null +++ b/src/main/java/jp/sfjp/jindolf/VerInfo.java @@ -0,0 +1,178 @@ +/* + * version information + * + * License : The MIT License + * Copyright(c) 2011 olyutorskii + */ + +package jp.sfjp.jindolf; + +import java.util.Properties; + +/** + * バージョンその他アプリに関する各種情報。 + */ +public final class VerInfo { + + /** タイトル。 */ + public static final String TITLE; + /** バージョン。 */ + public static final String VERSION; + /** 作者名。 */ + public static final String AUTHOR; + /** 著作権表記。 */ + public static final String COPYRIGHT; + /** ライセンス表記。 */ + public static final String LICENSE; + /** 連絡先。 */ + public static final String CONTACT; + /** 初出。 */ + public static final String INCEPTION; + /** その他、何でも書きたいこと。 */ + public static final String COMMENT; + /** クレジット。 */ + public static final String ID; + + private static final String RES_VERDEF = "resources/version.properties"; + + private static final String PFX_TITLE = "pkg-title."; + private static final String PFX_VERSION = "pkg-version."; + private static final String PFX_AUTHOR = "pkg-author."; + private static final String PFX_LICENSE = "pkg-license."; + private static final String PFX_CONTACT = "pkg-contact."; + private static final String PFX_INCEPTION = "pkg-inception."; + private static final String PFX_COMMENT = "pkg-comment."; + + static{ + Properties verProp = ResourceManager.getProperties(RES_VERDEF); + if(verProp == null) verProp = new Properties(); + + TITLE = getPackageInfo(verProp, PFX_TITLE, "Jindolf"); + VERSION = getPackageInfo(verProp, PFX_VERSION, "0.0.1"); + AUTHOR = getPackageInfo(verProp, PFX_AUTHOR, "nobody"); + LICENSE = getPackageInfo(verProp, PFX_LICENSE, "Unknown"); + CONTACT = getPackageInfo(verProp, PFX_CONTACT, "Unknown"); + INCEPTION = getPackageInfo(verProp, PFX_INCEPTION, "2008"); + COMMENT = getPackageInfo(verProp, PFX_COMMENT, ""); + + COPYRIGHT = "Copyright(c)" +"\u0020"+ INCEPTION +"\u0020"+ AUTHOR; + + ID = TITLE + +"\u0020"+ "Ver." + VERSION + +"\u0020"+ COPYRIGHT + +"\u0020"+ "("+ LICENSE +")"; + } + + /** + * 隠しコンストラクタ。 + */ + private VerInfo(){ + super(); + assert false; + return; + } + + + /** + * プロパティからルートパッケージのパッケージ情報を取得する。 + * @param prop プロパティ + * @param prefix 接頭辞 + * @param defValue 見つからなかった場合のデフォルト値 + * @return パッケージ情報 + */ + static String getPackageInfo(Properties prop, + String prefix, + String defValue ){ + String result = getPackageInfo(prop, prefix, + ResourceManager.DEF_ROOT_PACKAGE, + defValue ); + return result; + } + + /** + * プロパティからパッケージに紐づけられたパッケージ情報を取得する。 + * @param prop プロパティ + * @param prefix 接頭辞 + * @param pkg 任意のパッケージ + * @param defValue 見つからなかった場合のデフォルト値 + * @return パッケージ情報 + */ + static String getPackageInfo(Properties prop, + String prefix, + Package pkg, + String defValue ){ + String propKeyName = prefix + pkg.getName(); + String result = prop.getProperty(propKeyName, defValue); + + // ignore Maven macro filtering + if(isMavenMacro(result)){ + result = defValue; + } + + return result; + } + + /** + * 文字列がMavenのマクロフィルタ置換子でありうるか判定する。 + *

「${」で始まり「}」で終わる文字列を置換子とみなす。 + *

マクロ展開結果がさらに偶然引っかかった場合はあきらめる。 + * @param text 文字列 + * @return 置換子でありうるならtrue + */ + public static boolean isMavenMacro(String text){ + if(text.startsWith("$" + "{") && text.endsWith("}")){ + return true; + } + return false; + } + + /** + * ウィンドウタイトル名を生成する。 + *

各ウィンドウタイトルには、他のアプリとの区別のため + * アプリ名が付加される。 + * @param base タイトル基本部 + * @return アプリ名が付加されたウィンドウタイトル。 + */ + public static String getFrameTitle(String base){ + StringBuilder result = new StringBuilder(); + + if(base != null){ + result.append(base).append("\u0020-\u0020"); + } + result.append(TITLE); + + String message = result.toString(); + return message; + } + + /** + * About画面用メッセージを生成する。 + * @return About画面用メッセージ + */ + public static String getAboutMessage(){ + StringBuilder result = new StringBuilder(); + + result.append(TITLE) + .append("\u0020\u0020\u0020") + .append("Version") + .append('\u0020') + .append(VERSION) + .append('\n'); + result.append(COPYRIGHT) + .append('\n'); + result.append("ライセンス:\u0020") + .append(LICENSE) + .append('\n'); + result.append("連絡先:\u0020") + .append(CONTACT); + + if(COMMENT.length() > 0){ + result.append('\n') + .append(COMMENT); + } + + String message = result.toString(); + return message; + } + +} diff --git a/src/main/java/jp/sourceforge/jindolf/AppSetting.java b/src/main/java/jp/sfjp/jindolf/config/AppSetting.java similarity index 71% rename from src/main/java/jp/sourceforge/jindolf/AppSetting.java rename to src/main/java/jp/sfjp/jindolf/config/AppSetting.java index f69b5d5..39ebe77 100644 --- a/src/main/java/jp/sourceforge/jindolf/AppSetting.java +++ b/src/main/java/jp/sfjp/jindolf/config/AppSetting.java @@ -5,11 +5,13 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.config; import java.awt.Font; -import java.awt.font.FontRenderContext; import java.io.File; +import jp.sfjp.jindolf.data.DialogPref; +import jp.sfjp.jindolf.glyph.FontInfo; +import jp.sfjp.jindolf.net.ProxyInfo; import jp.sourceforge.jovsonz.JsBoolean; import jp.sourceforge.jovsonz.JsObject; import jp.sourceforge.jovsonz.JsPair; @@ -20,10 +22,8 @@ import jp.sourceforge.jovsonz.JsValue; */ public class AppSetting{ - private static final String NETCONFIG_FILE = "netconfig.json"; private static final String HASH_PROXY = "proxy"; - private static final String TALKCONFIG_FILE = "talkconfig.json"; private static final String HASH_FONT = "font"; private static final String HASH_USEBODYICON = "useBodyIcon"; private static final String HASH_USEMONOTOMB = "useMonoTomb"; @@ -31,10 +31,7 @@ public class AppSetting{ private static final String HASH_ALIGNBALOON = "alignBaloonWidth"; private OptionInfo optInfo; - - private boolean useConfigPath; - private File configPath; - + private ConfigStore configStore; private FontInfo fontInfo = FontInfo.DEFAULT_FONTINFO; private int frameWidth = 800; @@ -58,37 +55,45 @@ public class AppSetting{ } /** - * コマンドラインオプションからアプリ設定を展開する。 - * @param optionInfo オプション情報 + * 設定格納ディレクトリ関係の解析。 + * @param optionInfo コマンドライン情報 + * @return 設定ディレクトリ情報 */ - public void applyOptionInfo(OptionInfo optionInfo){ - this.optInfo = optionInfo; - applyConfigPathSetting(); - applyFontSetting(); - applyGeometrySetting(); - return; - } + private static ConfigStore parseConfigStore(OptionInfo optionInfo){ + CmdOption opt = + optionInfo.getExclusiveOption(CmdOption.OPT_CONFDIR, + CmdOption.OPT_NOCONF ); + + boolean useConfig; + File configPath; - /** - * 設定格納ディレクトリ関係の設定。 - */ - private void applyConfigPathSetting(){ - CmdOption opt = this.optInfo - .getExclusiveOption(CmdOption.OPT_CONFDIR, - CmdOption.OPT_NOCONF ); if(opt == CmdOption.OPT_NOCONF){ - this.useConfigPath = false; - this.configPath = null; + useConfig = false; + configPath = null; }else if(opt == CmdOption.OPT_CONFDIR){ - this.useConfigPath = true; - String path = this.optInfo.getStringArg(CmdOption.OPT_CONFDIR); - this.configPath = FileUtils.supplyFullPath(new File(path)); + String path = optionInfo.getStringArg(CmdOption.OPT_CONFDIR); + useConfig = true; + configPath = FileUtils.supplyFullPath(new File(path)); }else{ - this.useConfigPath = true; + useConfig = true; File path = ConfigFile.getImplicitConfigDirectory(); - this.configPath = path; + configPath = path; } + ConfigStore result = new ConfigStore(useConfig, configPath); + + return result; + } + + /** + * コマンドラインオプションからアプリ設定を展開する。 + * @param optionInfo オプション情報 + */ + public void applyOptionInfo(OptionInfo optionInfo){ + this.optInfo = optionInfo; + this.configStore = parseConfigStore(optionInfo); + applyFontSetting(); + applyGeometrySetting(); return; } @@ -97,33 +102,27 @@ public class AppSetting{ */ private void applyFontSetting(){ String fontName = this.optInfo.getStringArg(CmdOption.OPT_INITFONT); + Boolean useAntiAlias = this.optInfo.getBooleanArg(CmdOption.OPT_ANTIALIAS); + if(useAntiAlias == null){ + useAntiAlias = this.fontInfo.isAntiAliased(); + } + Boolean useFractional = this.optInfo.getBooleanArg(CmdOption.OPT_FRACTIONAL); + if(useFractional == null){ + useFractional = this.fontInfo.usesFractionalMetrics(); + } if(fontName != null){ Font font = Font.decode(fontName); this.fontInfo = this.fontInfo.deriveFont(font); } - if(useAntiAlias != null){ - FontRenderContext context = this.fontInfo.getFontRenderContext(); - FontRenderContext newContext = - new FontRenderContext(context.getTransform(), - useAntiAlias.booleanValue(), - context.usesFractionalMetrics() ); - this.fontInfo = this.fontInfo.deriveRenderContext(newContext); - } - - if(useFractional != null){ - FontRenderContext context = this.fontInfo.getFontRenderContext(); - FontRenderContext newContext = - new FontRenderContext(context.getTransform(), - context.isAntiAliased(), - useFractional.booleanValue() ); - this.fontInfo = this.fontInfo.deriveRenderContext(newContext); - } + this.fontInfo = + this.fontInfo.deriveRenderContext(useAntiAlias, + useFractional ); return; } @@ -150,37 +149,19 @@ public class AppSetting{ } /** - * 設定格納ディレクトリを返す。 - * @return 設定格納ディレクトリ。 - */ - public File getConfigPath(){ - return this.configPath; - } - - /** - * 設定格納ディレクトリを設定する。 - * @param path 設定格納ディレクトリ + * コマンドラインオプション情報を返す。 + * @return コマンドラインオプション情報 */ - public void setConfigPath(File path){ - this.configPath = path; - return; + public OptionInfo getOptionInfo(){ + return this.optInfo; } /** - * 設定格納ディレクトリを使うか否かを返す。 - * @return 使うならtrue + * 設定格納情報を返す。 + * @return 設定格納情報 */ - public boolean useConfigPath(){ - return this.useConfigPath; - } - - /** - * 設定格納ディレクトリを使うか否か設定する。 - * @param need 使うならtrue - */ - public void setUseConfigPath(boolean need){ - this.useConfigPath = need; - return; + public ConfigStore getConfigStore(){ + return this.configStore; } /** @@ -274,16 +255,11 @@ public class AppSetting{ * ネットワーク設定をロードする。 */ private void loadNetConfig(){ - if( ! useConfigPath() ) return; - - JsValue value = ConfigFile.loadJson(new File(NETCONFIG_FILE)); - if(value == null) return; - this.loadedNetConfig = value; + JsObject root = this.configStore.loadNetConfig(); + if(root == null) return; + this.loadedNetConfig = root; - if( ! (value instanceof JsObject) ) return; - JsObject root = (JsObject) value; - - value = root.getValue(HASH_PROXY); + JsValue value = root.getValue(HASH_PROXY); if( ! (value instanceof JsObject) ) return; JsObject proxy = (JsObject) value; @@ -298,16 +274,11 @@ public class AppSetting{ * 会話表示設定をロードする。 */ private void loadTalkConfig(){ - if( ! useConfigPath() ) return; - - JsValue value = ConfigFile.loadJson(new File(TALKCONFIG_FILE)); - if(value == null) return; - this.loadedTalkConfig = value; - - if( ! (value instanceof JsObject) ) return; - JsObject root = (JsObject) value; + JsObject root = this.configStore.loadTalkConfig(); + if(root == null) return; + this.loadedTalkConfig = root; - value = root.getValue(HASH_FONT); + JsValue value = root.getValue(HASH_FONT); if(value instanceof JsObject){ JsObject font = (JsObject) value; FontInfo info = FontInfo.decodeJson(font); @@ -346,7 +317,7 @@ public class AppSetting{ * ネットワーク設定をセーブする。 */ private void saveNetConfig(){ - if( ! useConfigPath() ) return; + if( ! getConfigStore().useStoreFile() ) return; JsObject root = new JsObject(); JsObject proxy = ProxyInfo.buildJson(getProxyInfo()); @@ -356,7 +327,7 @@ public class AppSetting{ if(this.loadedNetConfig.equals(root)) return; } - ConfigFile.saveJson(new File(NETCONFIG_FILE), root); + this.configStore.saveNetConfig(root); return; } @@ -365,7 +336,7 @@ public class AppSetting{ * 会話表示設定をセーブする。 */ private void saveTalkConfig(){ - if( ! useConfigPath() ) return; + if( ! getConfigStore().useStoreFile() ) return; JsObject root = new JsObject(); @@ -390,7 +361,7 @@ public class AppSetting{ if(this.loadedTalkConfig.equals(root)) return; } - ConfigFile.saveJson(new File(TALKCONFIG_FILE), root); + this.configStore.saveTalkConfig(root); return; } diff --git a/src/main/java/jp/sourceforge/jindolf/CmdOption.java b/src/main/java/jp/sfjp/jindolf/config/CmdOption.java similarity index 56% rename from src/main/java/jp/sourceforge/jindolf/CmdOption.java rename to src/main/java/jp/sfjp/jindolf/config/CmdOption.java index 933d142..1a3a7b8 100644 --- a/src/main/java/jp/sourceforge/jindolf/CmdOption.java +++ b/src/main/java/jp/sfjp/jindolf/config/CmdOption.java @@ -5,83 +5,103 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.config; -import java.io.IOException; -import java.util.LinkedList; +import java.util.Arrays; import java.util.List; +import jp.sfjp.jindolf.ResourceManager; /** * コマンドラインオプションの列挙。 */ -public enum CmdOption{ +public enum CmdOption { /** ヘルプ。 */ - OPT_HELP("help", "h", "-help", "?"), + OPT_HELP("-help", "-h", "--help", "-?"), /** 版数表示。 */ - OPT_VERSION("version"), + OPT_VERSION("-version"), /** UI文字制御。 */ - OPT_BOLDMETAL("boldMetal"), + OPT_BOLDMETAL("-boldMetal"), /** スプラッシュ制御。 */ - OPT_NOSPLASH("nosplash"), + OPT_NOSPLASH("-nosplash"), /** ウィンドウ位置指定。 */ - OPT_GEOMETRY("geometry"), + OPT_GEOMETRY("-geometry"), /** 実行環境出力。 */ - OPT_VMINFO("vminfo"), + OPT_VMINFO("-vminfo"), /** コンソールログ。 */ - OPT_CONSOLELOG("consolelog"), + OPT_CONSOLELOG("-consolelog"), /** フォント指定。 */ - OPT_INITFONT("initfont"), + OPT_INITFONT("-initfont"), /** アンチエイリアス。 */ - OPT_ANTIALIAS("antialias"), + OPT_ANTIALIAS("-antialias"), /** サブピクセル制御。 */ - OPT_FRACTIONAL("fractional"), + OPT_FRACTIONAL("-fractional"), /** 設定格納ディレクトリ指定。 */ - OPT_CONFDIR("confdir"), + OPT_CONFDIR("-confdir"), /** 設定格納ディレクトリ不使用。 */ - OPT_NOCONF("noconfdir"), + OPT_NOCONF("-noconfdir"), ; - private final List nameList = new LinkedList(); + private static final String RES_HELPTEXT = "resources/help.txt"; + + + private final List nameList; /** * コンストラクタ。 * @param names 頭のハイフンを除いたオプション名の一覧 */ - private CmdOption(CharSequence ... names){ - if(names == null) throw new NullPointerException(); - if(names.length <= 0) throw new IllegalArgumentException(); - - for(CharSequence name : names){ - if(name == null) throw new NullPointerException(); - this.nameList.add(name.toString().intern()); - } - + private CmdOption(String ... names){ + assert names.length > 0; + this.nameList = Arrays.asList(names); return; } /** + * ヘルプメッセージ(オプションの説明)を返す。 + * @return ヘルプメッセージ + */ + public static CharSequence getHelpText(){ + CharSequence helpText = + ResourceManager.getTextFile(RES_HELPTEXT); + + return helpText; + } + + /** * オプション名に合致するEnumを返す。 - * @param seq ハイフン付きオプション名 + * @param arg 個別のコマンドライン引数 * @return 合致したEnum。どれとも合致しなければnull */ - public static CmdOption parseCmdOption(CharSequence seq){ + public static CmdOption parseCmdOption(String arg){ for(CmdOption option : values()){ - if(option.matchHyphened(seq)) return option; + if(option.matches(arg)) return option; } return null; } /** + * 任意のオプション文字列がこのオプションに合致するか判定する。 + * @param option ハイフンの付いたオプション文字列 + * @return 合致すればtrue + */ + public boolean matches(String option){ + for(String name : this.nameList){ + if(option.equals(name)) return true; + } + + return false; + } + + /** * 単体で意味をなすオプションか判定する。 - * @param option オプション * @return 単体で意味をなすならtrue */ - public static boolean isIndepOption(CmdOption option){ - switch(option){ + public boolean isIndepOption(){ + switch(this){ case OPT_HELP: case OPT_VERSION: case OPT_VMINFO: @@ -99,11 +119,10 @@ public enum CmdOption{ /** * 真偽指定を一つ必要とするオプションか判定する。 - * @param option オプション * @return 真偽指定を一つ必要とするオプションならtrue */ - public static boolean isBooleanOption(CmdOption option){ - switch(option){ + public boolean isBooleanOption(){ + switch(this){ case OPT_ANTIALIAS: case OPT_FRACTIONAL: return true; @@ -115,22 +134,6 @@ public enum CmdOption{ } /** - * ヘルプメッセージ(オプションの説明)を返す。 - * @return ヘルプメッセージ - */ - public static CharSequence getHelpText(){ - CharSequence helpText; - - try{ - helpText = Jindolf.loadResourceText("resources/help.txt"); - }catch(IOException e){ - helpText = ""; - } - - return helpText; - } - - /** * 頭のハイフンを除いたオプション名を返す。 * オプション名が複数指定されていた場合は最初のオプション名 * @return オプション名 @@ -140,29 +143,4 @@ public enum CmdOption{ return this.nameList.get(0); } - /** - * 頭のハイフンが付いたオプション名を返す。 - * オプション名が複数指定されていた場合は最初のオプション名 - * @return オプション名 - */ - public String toHyphened(){ - return "-" + toString(); - } - - /** - * 任意のオプション文字列がこのオプションに合致するか判定する。 - * @param option ハイフンの付いたオプション文字列 - * @return 合致すればtrue - */ - public boolean matchHyphened(CharSequence option){ - if(option == null) return false; - - for(String name : this.nameList){ - String hyphened = "-" + name; - if(hyphened.equals(option.toString())) return true; - } - - return false; - } - } diff --git a/src/main/java/jp/sourceforge/jindolf/ConfigFile.java b/src/main/java/jp/sfjp/jindolf/config/ConfigFile.java similarity index 61% rename from src/main/java/jp/sourceforge/jindolf/ConfigFile.java rename to src/main/java/jp/sfjp/jindolf/config/ConfigFile.java index efd80f2..9fc38af 100644 --- a/src/main/java/jp/sourceforge/jindolf/ConfigFile.java +++ b/src/main/java/jp/sfjp/jindolf/config/ConfigFile.java @@ -5,36 +5,21 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; - -import java.awt.Component; -import java.awt.HeadlessException; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; +package jp.sfjp.jindolf.config; + import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; -import java.io.Reader; import java.io.Writer; import java.nio.charset.Charset; -import javax.swing.ButtonGroup; -import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JOptionPane; -import javax.swing.JRadioButton; -import jp.sourceforge.jovsonz.JsComposition; -import jp.sourceforge.jovsonz.JsParseException; -import jp.sourceforge.jovsonz.JsVisitException; -import jp.sourceforge.jovsonz.Json; +import jp.sfjp.jindolf.VerInfo; +import jp.sfjp.jindolf.log.LogWrapper; +import jp.sfjp.jindolf.view.LockErrorPane; /** * Jindolf設定格納ディレクトリに関するあれこれ。 @@ -42,7 +27,7 @@ import jp.sourceforge.jovsonz.Json; public final class ConfigFile{ private static final String TITLE_BUILDCONF = - Jindolf.TITLE + "設定格納ディレクトリの設定"; + VerInfo.TITLE + "設定格納ディレクトリの設定"; private static final String JINCONF = "Jindolf"; private static final String JINCONF_DOT = ".jindolf"; @@ -52,14 +37,16 @@ public final class ConfigFile{ private static final String MSG_POST = "

    " - + "
  • " + CmdOption.OPT_CONFDIR.toHyphened() + "" + + "
  • " + CmdOption.OPT_CONFDIR + "" + " ã‚ªãƒ—ション指定により、
    " + "任意の設定格納ディレクトリを指定することができます。
    " - + "
  • " + CmdOption.OPT_NOCONF.toHyphened() + "" + + "
  • " + CmdOption.OPT_NOCONF + "" + " ã‚ªãƒ—ション指定により、
    " + "設定格納ディレクトリを使わずに起動することができます。
    " + "
"; + private static final LogWrapper LOGGER = new LogWrapper(); + /** * 隠れコンストラクタ。 @@ -72,19 +59,19 @@ public final class ConfigFile{ /** * 設定格納ディレクトリのセットアップ。 + * @param configStore 設定ディレクトリ * @return 設定格納ディレクトリ */ - public static File setupConfigDirectory(){ - AppSetting setting = Jindolf.getAppSetting(); + public static File setupConfigDirectory(ConfigStore configStore){ File configPath; - if( ! setting.useConfigPath() ){ + if( ! configStore.useStoreFile() ){ configPath = null; }else{ String optName; - if(setting.getConfigPath() != null){ - configPath = setting.getConfigPath(); - optName = CmdOption.OPT_CONFDIR.toHyphened(); + if(configStore.getConfigPath() != null){ + configPath = configStore.getConfigPath(); + optName = CmdOption.OPT_CONFDIR.toString(); }else{ configPath = ConfigFile.getImplicitConfigDirectory(); optName = null; @@ -96,19 +83,18 @@ public final class ConfigFile{ ConfigFile.checkAccessibility(configPath); } - setting.setConfigPath(configPath); + configStore.setConfigPath(configPath); return configPath; } /** * ロックファイルのセットアップ。 + * @param configStore 設定ディレクトリ * @return ロックオブジェクト */ - public static InterVMLock setupLockFile(){ - AppSetting setting = Jindolf.getAppSetting(); - - File configPath = setting.getConfigPath(); + public static InterVMLock setupLockFile(ConfigStore configStore){ + File configPath = configStore.getConfigPath(); if(configPath == null) return null; File lockFile = new File(configPath, "lock"); @@ -119,8 +105,8 @@ public final class ConfigFile{ if( ! lock.isFileOwner() ){ confirmLockError(lock); if( ! lock.isFileOwner() ){ - setting.setConfigPath(null); - setting.setUseConfigPath(false); + configStore.setConfigPath(null); + configStore.setUseStoreFile(false); } } @@ -143,7 +129,7 @@ public final class ConfigFile{ public static File getImplicitConfigDirectory(){ File result; - File jarParent = FileUtils.getJarDirectory(Jindolf.class); + File jarParent = FileUtils.getJarDirectory(); if(jarParent != null && FileUtils.isAccessibleDirectory(jarParent)){ result = new File(jarParent, JINCONF); if(FileUtils.isAccessibleDirectory(result)){ @@ -284,6 +270,15 @@ public final class ConfigFile{ } /** + * VMを異常終了させる。 + */ + private static void abort(){ + System.exit(1); + assert false; + return; + } + + /** * 設定ディレクトリのルートファイルシステムもしくはドライブレターに * アクセスできないエラーをダイアログに提示し、VM終了する。 * @param path 設定ディレクトリ @@ -299,7 +294,7 @@ public final class ConfigFile{ + "起動を中止します。
" + MSG_POST + "" ); - Jindolf.exit(1); + abort(); return; } @@ -320,7 +315,7 @@ public final class ConfigFile{ + "起動を中止します。
" + MSG_POST + "" ); - Jindolf.exit(1); + abort(); return; } @@ -369,7 +364,7 @@ public final class ConfigFile{ + "設定ディレクトリの作成をせずに起動を中止します。
" + MSG_POST + "" ); - Jindolf.exit(1); + abort(); return; } @@ -387,7 +382,7 @@ public final class ConfigFile{ + "起動を中止します。
" + MSG_POST + "" ); - Jindolf.exit(1); + abort(); return; } @@ -407,7 +402,7 @@ public final class ConfigFile{ + "読み書きできるようにしてください。
" + MSG_POST + "" ); - Jindolf.exit(1); + abort(); return; } @@ -423,7 +418,7 @@ public final class ConfigFile{ + "への書き込みができません。" + "起動を中止します。
" + "" ); - Jindolf.exit(1); + abort(); return; } @@ -520,7 +515,7 @@ public final class ConfigFile{ dialog.dispose(); if(pane.isAborted() || pane.getValue() == null){ - Jindolf.exit(1); + abort(); break; }else if(pane.isRadioRetry()){ lock.tryLock(); @@ -531,7 +526,7 @@ public final class ConfigFile{ + "設定ディレクトリを使わずに起動を続行します。
" + "今回、各種設定の読み込み・保存はできません。
" + "" - + CmdOption.OPT_NOCONF.toHyphened() + + CmdOption.OPT_NOCONF + " オプション" + "を使うとこの警告は出なくなります。" + ""); @@ -549,7 +544,7 @@ public final class ConfigFile{ + "を削除してください。
" + "起動を中止します。" + ""); - Jindolf.exit(1); + abort(); break; } lock.tryLock(); @@ -561,7 +556,7 @@ public final class ConfigFile{ + "を確保することができません。
" + "起動を中止します。" + ""); - Jindolf.exit(1); + abort(); break; } } @@ -569,289 +564,4 @@ public final class ConfigFile{ return; } - /** - * 設定ディレクトリ上のJSONファイルを読み込む。 - * @param file JSONファイルの相対パス - * @return JSON objectまたはarray。 - * 設定ディレクトリを使わない設定、 - * もしくはJSONファイルが存在しない、 - * もしくは入力エラーがあればnull - */ - public static JsComposition loadJson(File file){ - AppSetting setting = Jindolf.getAppSetting(); - if( ! setting.useConfigPath() ) return null; - - File absFile; - if(file.isAbsolute()){ - absFile = file; - }else{ - File configPath = setting.getConfigPath(); - if(configPath == null) return null; - absFile = new File(configPath, file.getPath()); - if( ! absFile.exists() ) return null; - if( ! absFile.isAbsolute() ) return null; - } - - InputStream istream; - try{ - istream = new FileInputStream(absFile); - }catch(FileNotFoundException e){ - assert false; - return null; - } - istream = new BufferedInputStream(istream); - - Reader reader = new InputStreamReader(istream, CHARSET_JSON); - - JsComposition root; - try{ - root = Json.parseJson(reader); - }catch(IOException e){ - Jindolf.logger().fatal( - "JSONファイル[" - + absFile.getPath() - + "]の読み込み時に支障がありました。", e); - return null; - }catch(JsParseException e){ - Jindolf.logger().fatal( - "JSONファイル[" - + absFile.getPath() - + "]の内容に不備があります。", e); - return null; - }finally{ - try{ - reader.close(); - }catch(IOException e){ - Jindolf.logger().fatal( - "JSONファイル[" - + absFile.getPath() - + "]を閉じることができません。", e); - return null; - } - } - - return root; - } - - /** - * 設定ディレクトリ上のJSONファイルに書き込む。 - * @param file JSONファイルの相対パス - * @param root JSON objectまたはarray - * @return 正しくセーブが行われればtrue。 - * 何らかの理由でセーブが完了できなければfalse - */ - public static boolean saveJson(File file, JsComposition root){ - AppSetting setting = Jindolf.getAppSetting(); - if( ! setting.useConfigPath() ) return false; - File configPath = setting.getConfigPath(); - if(configPath == null) return false; - - // TODO テンポラリファイルを用いたより安全なファイル更新 - File absFile = new File(configPath, file.getPath()); - absFile.delete(); - try{ - if(absFile.createNewFile() != true) return false; - }catch(IOException e){ - Jindolf.logger().fatal( - "JSONファイル[" - + absFile.getPath() - + "]の新規生成ができません。", e); - return false; - } - - OutputStream ostream; - try{ - ostream = new FileOutputStream(absFile); - }catch(FileNotFoundException e){ - assert false; - return false; - } - ostream = new BufferedOutputStream(ostream); - Writer writer = new OutputStreamWriter(ostream, CHARSET_JSON); - - try{ - Json.dumpJson(writer, root); - }catch(JsVisitException e){ - Jindolf.logger().fatal( - "JSONファイル[" - + absFile.getPath() - + "]の出力処理で支障がありました。", e); - return false; - }catch(IOException e){ - Jindolf.logger().fatal( - "JSONファイル[" - + absFile.getPath() - + "]の書き込み時に支障がありました。", e); - return false; - }finally{ - try{ - writer.close(); - }catch(IOException e){ - Jindolf.logger().fatal( - "JSONファイル[" - + absFile.getPath() - + "]を閉じることができません。", e); - return false; - } - } - - return true; - } - - /** - * ロックエラー用ダイアログ。 - *
    - *
  • 強制解除 - *
  • リトライ - *
  • 設定ディレクトリを無視 - *
  • 起動中止 - *
- * の選択を利用者に求める。 - */ - @SuppressWarnings("serial") - private static class LockErrorPane - extends JOptionPane - implements ActionListener{ - - private final InterVMLock lock; - - private final JRadioButton continueButton = - new JRadioButton("設定ディレクトリを使わずに起動を続行"); - private final JRadioButton retryButton = - new JRadioButton("再度ロック取得を試す"); - private final JRadioButton forceButton = - new JRadioButton( - "" - + "ロックを強制解除
" - + " (※他のJindolfと設定ファイル書き込みが衝突するかも…)" - + ""); - - private final JButton okButton = new JButton("OK"); - private final JButton abortButton = new JButton("起動中止"); - - private boolean aborted = false; - - /** - * コンストラクタ。 - * @param lock 失敗したロック - */ - public LockErrorPane(InterVMLock lock){ - super(); - - this.lock = lock; - - String htmlMessage = - "" - + "設定ディレクトリのロックファイル
" - + getCenteredFileName(this.lock.getLockFile()) - + "のロックに失敗しました。
" - + "考えられる原因としては、
" - + "
    " - + "
  • 前回起動したJindolfの終了が正しく行われなかった" - + "
  • 今どこかで他のJindolfが動いている" - + "
" - + "などが考えられます。
" - + "
" - + ""; - - ButtonGroup bgrp = new ButtonGroup(); - bgrp.add(this.continueButton); - bgrp.add(this.retryButton); - bgrp.add(this.forceButton); - this.continueButton.setSelected(true); - - Object[] msg = { - htmlMessage, - this.continueButton, - this.retryButton, - this.forceButton, - }; - setMessage(msg); - - Object[] opts = { - this.okButton, - this.abortButton, - }; - setOptions(opts); - - setMessageType(JOptionPane.ERROR_MESSAGE); - - this.okButton .addActionListener(this); - this.abortButton.addActionListener(this); - - return; - } - - /** - * 「設定ディレクトリを無視して続行」が選択されたか判定する。 - * @return 「無視して続行」が選択されていればtrue - */ - public boolean isRadioContinue(){ - return this.continueButton.isSelected(); - } - - /** - * 「リトライ」が選択されたか判定する。 - * @return 「リトライ」が選択されていればtrue - */ - public boolean isRadioRetry(){ - return this.retryButton.isSelected(); - } - - /** - * 「強制解除」が選択されたか判定する。 - * @return 「強制解除」が選択されていればtrue - */ - public boolean isRadioForce(){ - return this.forceButton.isSelected(); - } - - /** - * 「起動中止」が選択されたか判定する。 - * @return 「起動中止」が押されていたならtrue - */ - public boolean isAborted(){ - return this.aborted; - } - - /** - * {@inheritDoc} - * @param parentComponent {@inheritDoc} - * @param title {@inheritDoc} - * @return {@inheritDoc} - * @throws HeadlessException {@inheritDoc} - */ - @Override - public JDialog createDialog(Component parentComponent, - String title) - throws HeadlessException{ - final JDialog dialog = - super.createDialog(parentComponent, title); - - ActionListener listener = new ActionListener(){ - public void actionPerformed(ActionEvent event){ - dialog.setVisible(false); - return; - } - }; - - this.okButton .addActionListener(listener); - this.abortButton.addActionListener(listener); - - return dialog; - } - - /** - * ボタン押下を受信する。 - * @param event イベント - */ - public void actionPerformed(ActionEvent event){ - Object source = event.getSource(); - if(source == this.okButton) this.aborted = false; - else this.aborted = true; - return; - } - - } - } diff --git a/src/main/java/jp/sfjp/jindolf/config/ConfigStore.java b/src/main/java/jp/sfjp/jindolf/config/ConfigStore.java new file mode 100644 index 0000000..beecf80 --- /dev/null +++ b/src/main/java/jp/sfjp/jindolf/config/ConfigStore.java @@ -0,0 +1,391 @@ +/* + * config store + * + * License : The MIT License + * Copyright(c) 2012 olyutorskii + */ + +package jp.sfjp.jindolf.config; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.Writer; +import java.nio.charset.Charset; +import jp.sfjp.jindolf.log.LogWrapper; +import jp.sourceforge.jovsonz.JsComposition; +import jp.sourceforge.jovsonz.JsObject; +import jp.sourceforge.jovsonz.JsParseException; +import jp.sourceforge.jovsonz.JsTypes; +import jp.sourceforge.jovsonz.JsVisitException; +import jp.sourceforge.jovsonz.Json; + +/** + * 各種設定の永続化関連。 + */ +public class ConfigStore { + + /** 検索履歴ファイル。 */ + public static final File HIST_FILE = new File("searchHistory.json"); + /** 原稿ファイル。 */ + public static final File DRAFT_FILE = new File("draft.json"); + /** ネットワーク設定ファイル。 */ + public static final File NETCONFIG_FILE = new File("netconfig.json"); + /** 台詞表示設定ファイル。 */ + public static final File TALKCONFIG_FILE = new File("talkconfig.json"); + + private static final Charset CHARSET_JSON = Charset.forName("UTF-8"); + + private static final LogWrapper LOGGER = new LogWrapper(); + + + private boolean useStoreFile; + private File configPath; + + + /** + * コンストラクタ。 + * @param useStoreFile 設定ディレクトリへの永続化機能を使うならtrue + * @param configPath 設定ディレクトリ。 + * 設定ディレクトリを使わない場合は無視され、nullとして扱われる。 + */ + public ConfigStore(boolean useStoreFile, File configPath){ + super(); + + this.useStoreFile = useStoreFile; + + File path = null; + if(this.useStoreFile) path = configPath; + this.configPath = path; + + return; + } + + /** + * 設定ディレクトリを使うか否か判定する。 + * @return 設定ディレクトリを使うならtrue。 + */ + public boolean useStoreFile(){ + return this.useStoreFile; + } + + /** + * 設定ディレクトリ利用の有無を変更する。 + * @param sw 利用するならtrue + */ + public void setUseStoreFile(boolean sw){ + this.useStoreFile = sw; + if( ! this.useStoreFile ){ + this.configPath = null; + } + return; + } + + /** + * 設定ディレクトリを返す。 + * @return 設定ディレクトリ。設定ディレクトリを使わない場合はnull + */ + public File getConfigPath(){ + File result; + if(this.useStoreFile) result = this.configPath; + else result = null; + return result; + } + + /** + * 設定ディレクトリを変更する。 + * @param path 設定ディレクトリ + */ + public void setConfigPath(File path){ + this.configPath = path; + return; + } + + /** + * 設定ディレクトリ上のOBJECT型JSONファイルを読み込む。 + * @param file JSONファイルの相対パス。 + * @return JSON object。 + * 設定ディレクトリを使わない設定、 + * もしくはJSONファイルが存在しない、 + * もしくはOBJECT型でなかった、 + * もしくは入力エラーがあればnull + */ + public JsObject loadJsObject(File file){ + JsComposition root = loadJson(file); + if(root == null || root.getJsTypes() != JsTypes.OBJECT) return null; + JsObject result = (JsObject) root; + return result; + } + + /** + * 設定ディレクトリ上のJSONファイルを読み込む。 + * @param file JSONファイルの相対パス + * @return JSON objectまたはarray。 + * 設定ディレクトリを使わない設定、 + * もしくはJSONファイルが存在しない、 + * もしくは入力エラーがあればnull + */ + public JsComposition loadJson(File file){ + if( ! this.useStoreFile ) return null; + + File absFile; + if(file.isAbsolute()){ + absFile = file; + }else{ + if(this.configPath == null) return null; + absFile = new File(this.configPath, file.getPath()); + if( ! absFile.exists() ) return null; + if( ! absFile.isAbsolute() ) return null; + } + String absPath = absFile.getPath(); + + InputStream istream; + try{ + istream = new FileInputStream(absFile); + }catch(FileNotFoundException e){ + assert false; + return null; + } + istream = new BufferedInputStream(istream); + + JsComposition root; + try{ + root = loadJson(istream); + }catch(IOException e){ + LOGGER.fatal( + "JSONファイル[" + + absPath + + "]の読み込み時に支障がありました。", e); + return null; + }catch(JsParseException e){ + LOGGER.fatal( + "JSONファイル[" + + absPath + + "]の内容に不備があります。", e); + return null; + }finally{ + try{ + istream.close(); + }catch(IOException e){ + LOGGER.fatal( + "JSONファイル[" + + absPath + + "]を閉じることができません。", e); + return null; + } + } + + return root; + } + + /** + * バイトストリーム上のJSONデータを読み込む。 + *

バイトストリームはUTF-8と解釈される。 + * @param is バイトストリーム + * @return JSON objectまたはarray。 + * @throws IOException 入力エラー + * @throws JsParseException 構文エラー + */ + protected JsComposition loadJson(InputStream is) + throws IOException, JsParseException { + Reader reader = new InputStreamReader(is, CHARSET_JSON); + reader = new BufferedReader(reader); + JsComposition root = loadJson(reader); + return root; + } + + /** + * 文字ストリーム上のJSONデータを読み込む。 + * @param reader 文字ストリーム + * @return JSON objectまたはarray。 + * @throws IOException 入力エラー + * @throws JsParseException 構文エラー + */ + protected JsComposition loadJson(Reader reader) + throws IOException, JsParseException { + JsComposition root = Json.parseJson(reader); + return root; + } + + /** + * 設定ディレクトリ上のJSONファイルに書き込む。 + * @param file JSONファイルの相対パス + * @param root JSON objectまたはarray + * @return 正しくセーブが行われればtrue。 + * 何らかの理由でセーブが完了できなければfalse + */ + public boolean saveJson(File file, JsComposition root){ + if( ! this.useStoreFile ) return false; + + // TODO テンポラリファイルを用いたより安全なファイル更新 + File absFile = new File(this.configPath, file.getPath()); + String absPath = absFile.getPath(); + + absFile.delete(); + try{ + if(absFile.createNewFile() != true) return false; + }catch(IOException e){ + LOGGER.fatal( + "JSONファイル[" + + absPath + + "]の新規生成ができません。", e); + return false; + } + + OutputStream ostream; + try{ + ostream = new FileOutputStream(absFile); + }catch(FileNotFoundException e){ + assert false; + return false; + } + ostream = new BufferedOutputStream(ostream); + + try{ + saveJson(ostream, root); + }catch(JsVisitException e){ + LOGGER.fatal( + "JSONファイル[" + + absPath + + "]の出力処理で支障がありました。", e); + return false; + }catch(IOException e){ + LOGGER.fatal( + "JSONファイル[" + + absPath + + "]の書き込み時に支障がありました。", e); + return false; + }finally{ + try{ + ostream.close(); + }catch(IOException e){ + LOGGER.fatal( + "JSONファイル[" + + absPath + + "]を閉じることができません。", e); + return false; + } + } + + return true; + } + + /** + * バイトストリームにJSONデータを書き込む。 + *

バイトストリームはUTF-8と解釈される。 + * @param os バイトストリーム出力 + * @param root JSON objectまたはarray + * @throws IOException 出力エラー + * @throws JsVisitException 構造エラー + */ + protected void saveJson(OutputStream os, JsComposition root) + throws IOException, JsVisitException { + Writer writer = new OutputStreamWriter(os, CHARSET_JSON); + writer = new BufferedWriter(writer); + saveJson(writer, root); + return; + } + + /** + * 文字ストリームにJSONデータを書き込む。 + * @param writer 文字ストリーム出力 + * @param root JSON objectまたはarray + * @throws IOException 出力エラー + * @throws JsVisitException 構造エラー + */ + protected void saveJson(Writer writer, JsComposition root) + throws IOException, JsVisitException { + Json.dumpJson(writer, root); + return; + } + + /** + * 検索履歴ファイルを読み込む。 + * @return 履歴データ。履歴を読まないもしくは読めない場合はnull + */ + public JsObject loadHistoryConfig(){ + JsObject result = loadJsObject(HIST_FILE); + return result; + } + + /** + * 原稿ファイルを読み込む。 + * @return 原稿データ。原稿を読まないもしくは読めない場合はnull + */ + public JsObject loadDraftConfig(){ + JsObject result = loadJsObject(DRAFT_FILE); + return result; + } + + /** + * ネットワーク設定ファイルを読み込む。 + * @return ネットワーク設定データ。 + * 設定を読まないもしくは読めない場合はnull + */ + public JsObject loadNetConfig(){ + JsObject result = loadJsObject(NETCONFIG_FILE); + return result; + } + + /** + * 台詞表示設定ファイルを読み込む。 + * @return 台詞表示設定データ。 + * 設定を読まないもしくは読めない場合はnull + */ + public JsObject loadTalkConfig(){ + JsObject result = loadJsObject(TALKCONFIG_FILE); + return result; + } + + /** + * 検索履歴ファイルに書き込む。 + * @param root 履歴データ + * @return 書き込まなかったもしくは書き込めなかった場合はfalse + */ + public boolean saveHistoryConfig(JsComposition root){ + boolean result = saveJson(HIST_FILE, root); + return result; + } + + /** + * 原稿ファイルに書き込む。 + * @param root 原稿データ + * @return 書き込まなかったもしくは書き込めなかった場合はfalse + */ + public boolean saveDraftConfig(JsComposition root){ + boolean result = saveJson(DRAFT_FILE, root); + return result; + } + + /** + * ネットワーク設定ファイルに書き込む。 + * @param root ネットワーク設定 + * @return 書き込まなかったもしくは書き込めなかった場合はfalse + */ + public boolean saveNetConfig(JsComposition root){ + boolean result = saveJson(NETCONFIG_FILE, root); + return result; + } + + /** + * 台詞表示設定ファイルに書き込む。 + * @param root 台詞表示設定 + * @return 書き込まなかったもしくは書き込めなかった場合はfalse + */ + public boolean saveTalkConfig(JsComposition root){ + boolean result = saveJson(TALKCONFIG_FILE, root); + return result; + } + +} diff --git a/src/main/java/jp/sourceforge/jindolf/EnvInfo.java b/src/main/java/jp/sfjp/jindolf/config/EnvInfo.java similarity index 88% rename from src/main/java/jp/sourceforge/jindolf/EnvInfo.java rename to src/main/java/jp/sfjp/jindolf/config/EnvInfo.java index 0cb6d21..d728546 100644 --- a/src/main/java/jp/sourceforge/jindolf/EnvInfo.java +++ b/src/main/java/jp/sfjp/jindolf/config/EnvInfo.java @@ -5,7 +5,7 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.config; import java.io.File; import java.text.NumberFormat; @@ -29,6 +29,9 @@ public final class EnvInfo{ /** Java実行形バージョン。 */ public static final String JAVA_VERSION; + /** 最大ヒープメモリ。 */ + public static final long MAX_MEMORY; + private static final SortedMap propertyMap = new TreeMap(); @@ -47,12 +50,18 @@ public final class EnvInfo{ getSecureEnvironment("LANG"); getSecureEnvironment("DISPLAY"); + Runtime runtime = Runtime.getRuntime(); + MAX_MEMORY = runtime.maxMemory(); + String classpath = getSecureProperty("java.class.path"); + String[] pathVec; if(classpath != null){ - classpaths = classpath.split(File.pathSeparator); + pathVec = classpath.split(File.pathSeparator); }else{ - classpaths = new String[0]; + pathVec = new String[0]; } + classpaths = pathVec; + } @@ -104,15 +113,9 @@ public final class EnvInfo{ StringBuilder result = new StringBuilder(); NumberFormat nform = NumberFormat.getNumberInstance(); - result.append("最大ヒープメモリ量: " - + nform.format(Jindolf.RUNTIME.maxMemory()) + " bytes\n"); - - result.append("\n"); - - result.append("起動時引数:\n"); - for(String arg : Jindolf.getOptionInfo().getInvokeArgList()){ - result.append(" ").append(arg).append("\n"); - } + result.append("最大ヒープメモリ量: ") + .append(nform.format(MAX_MEMORY)) + .append(" bytes\n"); result.append("\n"); diff --git a/src/main/java/jp/sourceforge/jindolf/FileUtils.java b/src/main/java/jp/sfjp/jindolf/config/FileUtils.java similarity index 95% rename from src/main/java/jp/sourceforge/jindolf/FileUtils.java rename to src/main/java/jp/sfjp/jindolf/config/FileUtils.java index d90e41e..7d523aa 100644 --- a/src/main/java/jp/sourceforge/jindolf/FileUtils.java +++ b/src/main/java/jp/sfjp/jindolf/config/FileUtils.java @@ -5,7 +5,7 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.config; import java.io.File; import java.lang.reflect.InvocationTargetException; @@ -24,6 +24,8 @@ import java.util.Locale; */ public final class FileUtils{ + private static final Class THISKLASS = FileUtils.class; + private static final String SCHEME_FILE = "file"; /** JRE1.6のjava.io.File#setReadableに相当。 */ @@ -66,6 +68,7 @@ public final class FileUtils{ METHOD_SETWRITABLE = method; assert ! ( isMacOSXFs() && isWindowsOSFs() ); + new FileUtils().hashCode(); } @@ -73,8 +76,9 @@ public final class FileUtils{ * 隠しコンストラクタ。 */ private FileUtils(){ - assert false; - throw new AssertionError(); + super(); + assert this.getClass() == THISKLASS; + return; } @@ -284,6 +288,16 @@ public final class FileUtils{ } /** + * このクラスがローカルJARファイルからロードされたのであれば + * その格納ディレクトリを返す。 + * @return ロード元JARファイルの格納ディレクトリ。 + * JARが見つからない、もしくはロード元がJARファイルでなければnull。 + */ + public static File getJarDirectory(){ + return getJarDirectory(THISKLASS); + } + + /** * ホームディレクトリを得る。 * システムプロパティuser.homeで示されたホームディレクトリを返す。 * @return ホームディレクトリ。何らかの事情でnullを返す場合もあり。 diff --git a/src/main/java/jp/sourceforge/jindolf/InterVMLock.java b/src/main/java/jp/sfjp/jindolf/config/InterVMLock.java similarity index 99% rename from src/main/java/jp/sourceforge/jindolf/InterVMLock.java rename to src/main/java/jp/sfjp/jindolf/config/InterVMLock.java index c3324b9..a45efb6 100644 --- a/src/main/java/jp/sourceforge/jindolf/InterVMLock.java +++ b/src/main/java/jp/sfjp/jindolf/config/InterVMLock.java @@ -5,7 +5,7 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.config; import java.io.File; import java.io.FileNotFoundException; diff --git a/src/main/java/jp/sfjp/jindolf/config/OptionInfo.java b/src/main/java/jp/sfjp/jindolf/config/OptionInfo.java new file mode 100644 index 0000000..cf9211b --- /dev/null +++ b/src/main/java/jp/sfjp/jindolf/config/OptionInfo.java @@ -0,0 +1,340 @@ +/* + * option argument information + * + * License : The MIT License + * Copyright(c) 2009 olyutorskii + */ + +package jp.sfjp.jindolf.config; + +import java.text.MessageFormat; +import java.util.Collections; +import java.util.EnumMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * コマンドラインオプション情報。 + * public static void main()の引数から展開される。 + */ +public class OptionInfo{ + + private static final Pattern PATTERN_GEOMETRY = + Pattern.compile( + "([1-9][0-9]*)x([1-9][0-9]*)" + +"(?:(\\+|\\-)([1-9][0-9]*)(\\+|\\-)([1-9][0-9]*))?" + ); + + private static final String ERRFORM_UKNOWN = + "未定義の起動オプション[{0}]が指定されました。"; + private static final String ERRFORM_NOARG = + "起動オプション[{0}]に引数がありません。"; + private static final String ERRFORM_GEOM = + "起動オプション[{0}]のジオメトリ指定[{1}]が不正です。" + + "WIDTHxHEIGHT[(+|-)XPOS(+|-)YPOS]の形式で指定してください"; + private static final String ERRFORM_BOOL = + "起動オプション[{0}]の真偽指定[{1}]が不正です。" + + "on, off, yes, no, true, falseのいずれかを指定してください。"; + private static final String ERRFORM_NONBOOL = + "起動オプション[{0}]は真偽を指定するオプションではありません。"; + + + private Integer frameWidth = null; + private Integer frameHeight = null; + private Integer frameXpos = null; + private Integer frameYpos = null; + + private final List invokeArgs = new LinkedList(); + private final List optionList = new LinkedList(); + private final Map boolOptionMap = + new EnumMap(CmdOption.class); + private final Map stringOptionMap = + new EnumMap(CmdOption.class); + + + /** + * コンストラクタ。 + */ + protected OptionInfo(){ + super(); + return; + } + + + /** + * 文字列が可変引数のいずれかと英字大小無視で等しいか判定する。 + *

※ JRE1.6のString#equalsIgnoreCase の代替も兼ねる。 + * @param text 文字列 + * @param names 文字列の可変引数 + * @return 等しい物があればtrue + */ + private static boolean equalsIgnoreCase(String text, String ... names){ + for(String name : names){ + if(text.compareToIgnoreCase(name) == 0) return true; + } + return false; + } + + /** + * 真偽二値をとるオプション解析の下請け。 + * @param info オプション情報格納先 + * @param option オプション種別 + * @param optTxt オプション名文字列 + * @param onoff オプション引数 + * @throws IllegalArgumentException 構文エラー + */ + private static void parseBooleanSwitch(OptionInfo info, + CmdOption option, + String optTxt, + String onoff ) + throws IllegalArgumentException{ + Boolean flag; + + if(equalsIgnoreCase(onoff, "on", "yes", "true")){ + flag = Boolean.TRUE; + }else if(equalsIgnoreCase(onoff, "off", "no", "false")){ + flag = Boolean.FALSE; + }else{ + String errmsg = + MessageFormat.format(ERRFORM_BOOL, optTxt, onoff); + throw new IllegalArgumentException(errmsg); + } + + info.boolOptionMap.put(option, flag); + + return; + } + + /** + * 文字列がマイナス記号で始まるか判定する。 + * @param txt 文字列 + * @return マイナス記号で始まればtrue + */ + private static boolean isMinus(String txt){ + if(txt.length() >= 1 && txt.charAt(0) == '-'){ + return true; + } + return false; + } + + /** + * ウィンドウジオメトリオプション解析。 + *

例) WIDTHxHEIGHT+XPOS+YPOS + * @param info オプション情報格納先 + * @param optTxt オプション名文字列 + * @param geometry オプション引数 + * @throws IllegalArgumentException 構文エラー + */ + private static void parseGeometry(OptionInfo info, + String optTxt, + String geometry ) + throws IllegalArgumentException{ + Matcher matcher = PATTERN_GEOMETRY.matcher(geometry); + if( ! matcher.matches() ){ + String errmsg = MessageFormat.format(ERRFORM_GEOM, + optTxt, geometry); + throw new IllegalArgumentException(errmsg); + } + + int gpos = 1; + String width = matcher.group(gpos++); + String height = matcher.group(gpos++); + String xSign = matcher.group(gpos++); + String xPos = matcher.group(gpos++); + String ySign = matcher.group(gpos++); + String yPos = matcher.group(gpos++); + + info.frameWidth = Integer.parseInt(width); + info.frameHeight = Integer.parseInt(height); + + if(xPos != null){ + info.frameXpos = Integer.parseInt(xPos); + if(isMinus(xSign)){ + info.frameXpos = -info.frameXpos; + } + } + + if(yPos != null){ + info.frameYpos = Integer.parseInt(yPos); + if(isMinus(ySign)){ + info.frameYpos = -info.frameYpos; + } + } + + return; + } + + /** + * オプション引数を解析する。 + * @param result オプション情報 + * @param optTxt オプション文字列 + * @param option オプション種別 + * @param iterator オプション並び + * @return 引数と同じオプション情報 + * @throws IllegalArgumentException 構文エラー + */ + private static OptionInfo parseOptionArg(OptionInfo result, + String optTxt, + CmdOption option, + Iterator iterator ) + throws IllegalArgumentException { + String nextArg; + if(iterator.hasNext()){ + nextArg = iterator.next(); + }else{ + String errMsg = MessageFormat.format(ERRFORM_NOARG, optTxt); + throw new IllegalArgumentException(errMsg); + } + + if(option == CmdOption.OPT_GEOMETRY){ + parseGeometry(result, optTxt, nextArg); + }else if(option.isBooleanOption()){ + parseBooleanSwitch(result, option, optTxt, nextArg); + }else if( option == CmdOption.OPT_INITFONT + || option == CmdOption.OPT_CONFDIR ){ + result.stringOptionMap.put(option, nextArg); + }else{ + assert false; + } + + return result; + } + + /** + * オプション文字列を解析する。 + * @param args main()に渡されるオプション文字列 + * @return 解析済みのオプション情報。 + * @throws IllegalArgumentException 構文エラー + */ + public static OptionInfo parseOptions(String ... args) + throws IllegalArgumentException{ + OptionInfo result = new OptionInfo(); + + for(String arg : args){ + if(arg == null) continue; + result.invokeArgs.add(arg); + } + Iterator iterator = result.invokeArgs.iterator(); + + while(iterator.hasNext()){ + String arg = iterator.next(); + + CmdOption option = CmdOption.parseCmdOption(arg); + if(option == null){ + String errmsg = MessageFormat.format(ERRFORM_UKNOWN, arg); + throw new IllegalArgumentException(errmsg); + } + result.optionList.add(option); + + if( ! option.isIndepOption() ){ + parseOptionArg(result, arg, option, iterator); + } + } + + return result; + } + + + /** + * 全引数のリストを返す。 + * @return 全引数のリスト + */ + public List getInvokeArgList(){ + return Collections.unmodifiableList(this.invokeArgs); + } + + /** + * オプションが指定されていたか否か判定する。 + * @param option オプション + * @return 指定されていたらtrue + */ + public boolean hasOption(CmdOption option){ + if(this.optionList.contains(option)) return true; + return false; + } + + /** + * 真偽値をとるオプション値を返す。 + * 複数回指定された場合は最後の値。 + * @param option オプション + * @return 真偽値。オプション指定がなかった場合はnull + * @throws IllegalArgumentException 真偽値を取るオプションではない。 + */ + public Boolean getBooleanArg(CmdOption option) + throws IllegalArgumentException{ + if( ! option.isBooleanOption() ){ + String errMsg = + MessageFormat.format(ERRFORM_NONBOOL, option.toString()); + throw new IllegalArgumentException(errMsg); + } + Boolean result = this.boolOptionMap.get(option); + return result; + } + + /** + * 文字列引数をとるオプション値を返す。 + * 複数回指定された場合は最後の値。 + * @param option オプション + * @return 文字列。オプション指定がなかった場合はnull + */ + public String getStringArg(CmdOption option){ + String result = this.stringOptionMap.get(option); + return result; + } + + /** + * 排他的オプションのいずれかが指定されたか判定する。 + * 後から指定された方が有効となる。 + * @param options 排他的オプション群 + * @return いずれかのオプション。どれも指定されなければnull + */ + public CmdOption getExclusiveOption(CmdOption... options){ + CmdOption result = null; + for(CmdOption option : this.optionList){ + for(CmdOption excOption : options){ + if(option == excOption){ + result = option; + break; + } + } + } + return result; + } + + /** + * 初期のフレーム幅を返す。 + * @return 初期のフレーム幅。オプション指定されてなければnull + */ + public Integer initialFrameWidth(){ + return this.frameWidth; + } + + /** + * 初期のフレーム高を返す。 + * @return 初期のフレーム高。オプション指定されてなければnull + */ + public Integer initialFrameHeight(){ + return this.frameHeight; + } + + /** + * 初期のフレーム位置のX座標を返す。 + * @return 初期のフレーム位置のX座標。オプション指定されてなければnull + */ + public Integer initialFrameXpos(){ + return this.frameXpos; + } + + /** + * 初期のフレーム位置のY座標を返す。 + * @return 初期のフレーム位置のY座標。オプション指定されてなければnull + */ + public Integer initialFrameYpos(){ + return this.frameYpos; + } + +} diff --git a/src/main/java/jp/sfjp/jindolf/config/package-info.java b/src/main/java/jp/sfjp/jindolf/config/package-info.java new file mode 100644 index 0000000..fc15f1f --- /dev/null +++ b/src/main/java/jp/sfjp/jindolf/config/package-info.java @@ -0,0 +1,14 @@ +/* + * パッケージ情報 + * + * License : The MIT License + * Copyright(c) 2011 olyutorskii + */ + +/** + * 各種アプリ設定や実行環境に関する一連のクラス。 + */ + +package jp.sfjp.jindolf.config; + +/* EOF */ diff --git a/src/main/java/jp/sourceforge/jindolf/Anchor.java b/src/main/java/jp/sfjp/jindolf/data/Anchor.java similarity index 99% rename from src/main/java/jp/sourceforge/jindolf/Anchor.java rename to src/main/java/jp/sfjp/jindolf/data/Anchor.java index 7171090..ad07a22 100644 --- a/src/main/java/jp/sourceforge/jindolf/Anchor.java +++ b/src/main/java/jp/sfjp/jindolf/data/Anchor.java @@ -5,12 +5,13 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.data; import java.util.LinkedList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; +import jp.sfjp.jindolf.util.StringUtils; /** * 発言アンカー。 diff --git a/src/main/java/jp/sourceforge/jindolf/Avatar.java b/src/main/java/jp/sfjp/jindolf/data/Avatar.java similarity index 99% rename from src/main/java/jp/sourceforge/jindolf/Avatar.java rename to src/main/java/jp/sfjp/jindolf/data/Avatar.java index 0d483f2..eee0726 100644 --- a/src/main/java/jp/sourceforge/jindolf/Avatar.java +++ b/src/main/java/jp/sfjp/jindolf/data/Avatar.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.data; import java.io.IOException; import java.net.URISyntaxException; @@ -19,6 +19,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.ParserConfigurationException; +import jp.sfjp.jindolf.dxchg.XmlUtils; import jp.sourceforge.jindolf.corelib.PreDefAvatar; import org.xml.sax.SAXException; diff --git a/src/main/java/jp/sourceforge/jindolf/DialogPref.java b/src/main/java/jp/sfjp/jindolf/data/DialogPref.java similarity index 99% rename from src/main/java/jp/sourceforge/jindolf/DialogPref.java rename to src/main/java/jp/sfjp/jindolf/data/DialogPref.java index 84b17e3..c34843f 100644 --- a/src/main/java/jp/sourceforge/jindolf/DialogPref.java +++ b/src/main/java/jp/sfjp/jindolf/data/DialogPref.java @@ -5,7 +5,7 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.data; /** * 発言表示設定。 diff --git a/src/main/java/jp/sourceforge/jindolf/Land.java b/src/main/java/jp/sfjp/jindolf/data/Land.java similarity index 96% rename from src/main/java/jp/sourceforge/jindolf/Land.java rename to src/main/java/jp/sfjp/jindolf/data/Land.java index c0d4fc1..8840f4a 100644 --- a/src/main/java/jp/sourceforge/jindolf/Land.java +++ b/src/main/java/jp/sfjp/jindolf/data/Land.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.data; import java.awt.image.BufferedImage; import java.io.IOException; @@ -18,6 +18,9 @@ import java.util.LinkedList; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; +import jp.sfjp.jindolf.log.LogWrapper; +import jp.sfjp.jindolf.net.HtmlSequence; +import jp.sfjp.jindolf.net.ServerAccess; import jp.sourceforge.jindolf.corelib.LandDef; import jp.sourceforge.jindolf.corelib.LandState; import jp.sourceforge.jindolf.corelib.VillageState; @@ -36,6 +39,8 @@ public class Land { // 古国ID private static final String ID_VANILLAWOLF = "wolf"; + private static final LogWrapper LOGGER = new LogWrapper(); + private final LandDef landDef; private final ServerAccess serverAccess; @@ -117,7 +122,7 @@ public class Land { try{ uri = new URI(pureHREF); }catch(URISyntaxException e){ - Jindolf.logger().warn( + LOGGER.warn( "不正なURI[" + hrefValue + "]を検出しました"); @@ -204,7 +209,7 @@ public class Land { try{ image = server.downloadImage(imageURL); }catch(IOException e){ - Jindolf.logger().warn( + LOGGER.warn( "イメージ[" + imageURL + "]" + "のダウンロードに失敗しました", e ); @@ -258,7 +263,7 @@ public class Land { try{ this.parser.parseAutomatic(content); }catch(HtmlParseException e){ - Jindolf.logger().warn("トップページを認識できない", e); + LOGGER.warn("トップページを認識できない", e); } List list = this.handler.getVillageList(); if(list != null){ @@ -273,7 +278,7 @@ public class Land { try{ this.parser.parseAutomatic(content); }catch(HtmlParseException e){ - Jindolf.logger().warn("村一覧ページを認識できない", e); + LOGGER.warn("村一覧ページを認識できない", e); } List list = this.handler.getVillageList(); if(list != null){ @@ -396,7 +401,7 @@ public class Land { String villageID = getVillageIDFromHREF(href); if( villageID == null || villageID.length() <= 0 ){ - Jindolf.logger().warn( + LOGGER.warn( "認識できないURL[" + href + "]に遭遇しました。"); return; } diff --git a/src/main/java/jp/sourceforge/jindolf/LandsModel.java b/src/main/java/jp/sfjp/jindolf/data/LandsModel.java similarity index 97% rename from src/main/java/jp/sourceforge/jindolf/LandsModel.java rename to src/main/java/jp/sfjp/jindolf/data/LandsModel.java index d5380f3..39a54d2 100644 --- a/src/main/java/jp/sourceforge/jindolf/LandsModel.java +++ b/src/main/java/jp/sfjp/jindolf/data/LandsModel.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.data; import java.io.IOException; import java.net.URISyntaxException; @@ -21,6 +21,8 @@ import javax.swing.tree.TreeModel; import javax.swing.tree.TreePath; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.ParserConfigurationException; +import jp.sfjp.jindolf.dxchg.XmlUtils; +import jp.sfjp.jindolf.log.LogWrapper; import jp.sourceforge.jindolf.corelib.LandDef; import org.xml.sax.SAXException; @@ -34,6 +36,8 @@ public class LandsModel implements TreeModel{ // ComboBoxModelも付けるか? private static final String ROOT = "ROOT"; private static final int SECTION_INTERVAL = 100; + private static final LogWrapper LOGGER = new LogWrapper(); + private final List landList = new LinkedList(); private final List unmodList = @@ -98,16 +102,16 @@ public class LandsModel implements TreeModel{ // ComboBoxModelも付けるか? DocumentBuilder builder = XmlUtils.createDocumentBuilder(); landDefList = LandDef.buildLandDefList(builder); }catch(IOException e){ - Jindolf.logger().fatal("failed to load land list", e); + LOGGER.fatal("failed to load land list", e); return; }catch(SAXException e){ - Jindolf.logger().fatal("failed to load land list", e); + LOGGER.fatal("failed to load land list", e); return; }catch(URISyntaxException e){ - Jindolf.logger().fatal("failed to load land list", e); + LOGGER.fatal("failed to load land list", e); return; }catch(ParserConfigurationException e){ - Jindolf.logger().fatal("failed to load land list", e); + LOGGER.fatal("failed to load land list", e); return; } diff --git a/src/main/java/jp/sourceforge/jindolf/Period.java b/src/main/java/jp/sfjp/jindolf/data/Period.java similarity index 99% rename from src/main/java/jp/sourceforge/jindolf/Period.java rename to src/main/java/jp/sfjp/jindolf/data/Period.java index 9bce811..a120970 100644 --- a/src/main/java/jp/sourceforge/jindolf/Period.java +++ b/src/main/java/jp/sfjp/jindolf/data/Period.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.data; import java.io.IOException; import java.util.Collections; @@ -15,6 +15,10 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; +import jp.sfjp.jindolf.log.LogWrapper; +import jp.sfjp.jindolf.net.HtmlSequence; +import jp.sfjp.jindolf.net.ServerAccess; +import jp.sfjp.jindolf.util.StringUtils; import jp.sourceforge.jindolf.corelib.EventFamily; import jp.sourceforge.jindolf.corelib.GameRole; import jp.sourceforge.jindolf.corelib.LandDef; @@ -46,6 +50,8 @@ public class Period{ private static final PeriodHandler HANDLER = new PeriodHandler(); + private static final LogWrapper LOGGER = new LogWrapper(); + static{ PARSER.setBasicHandler (HANDLER); PARSER.setSysEventHandler(HANDLER); @@ -170,7 +176,7 @@ public class Period{ try{ PARSER.parseAutomatic(content); }catch(HtmlParseException e){ - Jindolf.logger().warn("発言抽出に失敗", e); + LOGGER.warn("発言抽出に失敗", e); } if(wasHot && ! period.isHot() ){ diff --git a/src/main/java/jp/sourceforge/jindolf/Player.java b/src/main/java/jp/sfjp/jindolf/data/Player.java similarity index 99% rename from src/main/java/jp/sourceforge/jindolf/Player.java rename to src/main/java/jp/sfjp/jindolf/data/Player.java index 9b1380d..b7cc11e 100644 --- a/src/main/java/jp/sourceforge/jindolf/Player.java +++ b/src/main/java/jp/sfjp/jindolf/data/Player.java @@ -5,7 +5,7 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.data; import jp.sourceforge.jindolf.corelib.Destiny; import jp.sourceforge.jindolf.corelib.GameRole; diff --git a/src/main/java/jp/sourceforge/jindolf/RegexPattern.java b/src/main/java/jp/sfjp/jindolf/data/RegexPattern.java similarity index 99% rename from src/main/java/jp/sourceforge/jindolf/RegexPattern.java rename to src/main/java/jp/sfjp/jindolf/data/RegexPattern.java index 9e76af5..92bc75b 100644 --- a/src/main/java/jp/sourceforge/jindolf/RegexPattern.java +++ b/src/main/java/jp/sfjp/jindolf/data/RegexPattern.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.data; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; diff --git a/src/main/java/jp/sourceforge/jindolf/SysEvent.java b/src/main/java/jp/sfjp/jindolf/data/SysEvent.java similarity index 99% rename from src/main/java/jp/sourceforge/jindolf/SysEvent.java rename to src/main/java/jp/sfjp/jindolf/data/SysEvent.java index 8faa8fc..4450c95 100644 --- a/src/main/java/jp/sourceforge/jindolf/SysEvent.java +++ b/src/main/java/jp/sfjp/jindolf/data/SysEvent.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.data; import java.util.Collections; import java.util.HashSet; diff --git a/src/main/java/jp/sourceforge/jindolf/Talk.java b/src/main/java/jp/sfjp/jindolf/data/Talk.java similarity index 99% rename from src/main/java/jp/sourceforge/jindolf/Talk.java rename to src/main/java/jp/sfjp/jindolf/data/Talk.java index 2d01cf3..1998dcf 100644 --- a/src/main/java/jp/sourceforge/jindolf/Talk.java +++ b/src/main/java/jp/sfjp/jindolf/data/Talk.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.data; import jp.sourceforge.jindolf.corelib.TalkType; diff --git a/src/main/java/jp/sourceforge/jindolf/Topic.java b/src/main/java/jp/sfjp/jindolf/data/Topic.java similarity index 91% rename from src/main/java/jp/sourceforge/jindolf/Topic.java rename to src/main/java/jp/sfjp/jindolf/data/Topic.java index 9278190..d615921 100644 --- a/src/main/java/jp/sourceforge/jindolf/Topic.java +++ b/src/main/java/jp/sfjp/jindolf/data/Topic.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.data; /** * プレイヤーの発言及びゲームシステムからのメッセージのスーパーインタフェース。 diff --git a/src/main/java/jp/sourceforge/jindolf/Village.java b/src/main/java/jp/sfjp/jindolf/data/Village.java similarity index 98% rename from src/main/java/jp/sourceforge/jindolf/Village.java rename to src/main/java/jp/sfjp/jindolf/data/Village.java index a212a5b..1345dc7 100644 --- a/src/main/java/jp/sourceforge/jindolf/Village.java +++ b/src/main/java/jp/sfjp/jindolf/data/Village.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.data; import java.awt.image.BufferedImage; import java.io.IOException; @@ -16,6 +16,10 @@ import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; +import jp.sfjp.jindolf.log.LogWrapper; +import jp.sfjp.jindolf.net.HtmlSequence; +import jp.sfjp.jindolf.net.ServerAccess; +import jp.sfjp.jindolf.util.GUIUtils; import jp.sourceforge.jindolf.corelib.LandDef; import jp.sourceforge.jindolf.corelib.LandState; import jp.sourceforge.jindolf.corelib.PeriodType; @@ -73,6 +77,8 @@ public class Village implements Comparable { private static final VillageHeadHandler HANDLER = new VillageHeadHandler(); + private static final LogWrapper LOGGER = new LogWrapper(); + static{ PARSER.setBasicHandler (HANDLER); PARSER.setSysEventHandler(HANDLER); @@ -163,7 +169,7 @@ public class Village implements Comparable { try{ PARSER.parseAutomatic(content); }catch(HtmlParseException e){ - Jindolf.logger().warn("村の状態が不明", e); + LOGGER.warn("村の状態が不明", e); } return; @@ -794,7 +800,7 @@ public class Village implements Comparable { if(villageState == VillageState.UNKNOWN){ this.village.setState(villageState); this.village.periodList.clear(); - Jindolf.logger().warn("村の状況を読み取れません"); + LOGGER.warn("村の状況を読み取れません"); return; } diff --git a/src/main/java/jp/sourceforge/jindolf/ClipboardAction.java b/src/main/java/jp/sfjp/jindolf/dxchg/ClipboardAction.java similarity index 99% rename from src/main/java/jp/sourceforge/jindolf/ClipboardAction.java rename to src/main/java/jp/sfjp/jindolf/dxchg/ClipboardAction.java index b1e23f9..c97a3d1 100644 --- a/src/main/java/jp/sourceforge/jindolf/ClipboardAction.java +++ b/src/main/java/jp/sfjp/jindolf/dxchg/ClipboardAction.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.dxchg; import java.awt.Toolkit; import java.awt.datatransfer.Clipboard; diff --git a/src/main/java/jp/sourceforge/jindolf/CsvExporter.java b/src/main/java/jp/sfjp/jindolf/dxchg/CsvExporter.java similarity index 98% rename from src/main/java/jp/sourceforge/jindolf/CsvExporter.java rename to src/main/java/jp/sfjp/jindolf/dxchg/CsvExporter.java index 064b1e5..0cd254f 100644 --- a/src/main/java/jp/sourceforge/jindolf/CsvExporter.java +++ b/src/main/java/jp/sfjp/jindolf/dxchg/CsvExporter.java @@ -5,7 +5,7 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.dxchg; import java.awt.Component; import java.awt.GridBagConstraints; @@ -31,6 +31,12 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.border.Border; import javax.swing.filechooser.FileFilter; +import jp.sfjp.jindolf.data.Avatar; +import jp.sfjp.jindolf.data.Period; +import jp.sfjp.jindolf.data.Talk; +import jp.sfjp.jindolf.data.Topic; +import jp.sfjp.jindolf.data.Village; +import jp.sfjp.jindolf.view.TopicFilter; import jp.sourceforge.jindolf.corelib.TalkType; /** diff --git a/src/main/java/jp/sourceforge/jindolf/FaceIconSet.java b/src/main/java/jp/sfjp/jindolf/dxchg/FaceIconSet.java similarity index 96% rename from src/main/java/jp/sourceforge/jindolf/FaceIconSet.java rename to src/main/java/jp/sfjp/jindolf/dxchg/FaceIconSet.java index e5ccb06..ea4e195 100644 --- a/src/main/java/jp/sourceforge/jindolf/FaceIconSet.java +++ b/src/main/java/jp/sfjp/jindolf/dxchg/FaceIconSet.java @@ -5,10 +5,11 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.dxchg; import java.util.HashMap; import java.util.Map; +import jp.sfjp.jindolf.data.Avatar; /** * 顔アイコンWiki表記のセット。 diff --git a/src/main/java/jp/sourceforge/jindolf/TextPopup.java b/src/main/java/jp/sfjp/jindolf/dxchg/TextPopup.java similarity index 99% rename from src/main/java/jp/sourceforge/jindolf/TextPopup.java rename to src/main/java/jp/sfjp/jindolf/dxchg/TextPopup.java index c912e29..606190e 100644 --- a/src/main/java/jp/sourceforge/jindolf/TextPopup.java +++ b/src/main/java/jp/sfjp/jindolf/dxchg/TextPopup.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.dxchg; import java.awt.Component; import java.beans.PropertyChangeEvent; diff --git a/src/main/java/jp/sourceforge/jindolf/UriExporter.java b/src/main/java/jp/sfjp/jindolf/dxchg/UriExporter.java similarity index 98% rename from src/main/java/jp/sourceforge/jindolf/UriExporter.java rename to src/main/java/jp/sfjp/jindolf/dxchg/UriExporter.java index 6ca0c6c..6e6bb3f 100644 --- a/src/main/java/jp/sourceforge/jindolf/UriExporter.java +++ b/src/main/java/jp/sfjp/jindolf/dxchg/UriExporter.java @@ -5,7 +5,7 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.dxchg; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; diff --git a/src/main/java/jp/sourceforge/jindolf/WebButton.java b/src/main/java/jp/sfjp/jindolf/dxchg/WebButton.java similarity index 97% rename from src/main/java/jp/sourceforge/jindolf/WebButton.java rename to src/main/java/jp/sfjp/jindolf/dxchg/WebButton.java index 27fbba7..1cf72aa 100644 --- a/src/main/java/jp/sourceforge/jindolf/WebButton.java +++ b/src/main/java/jp/sfjp/jindolf/dxchg/WebButton.java @@ -5,7 +5,7 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.dxchg; import java.awt.Frame; import java.awt.GridBagConstraints; @@ -21,6 +21,8 @@ import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.SwingUtilities; +import jp.sfjp.jindolf.util.GUIUtils; +import jp.sfjp.jindolf.util.Monodizer; /** * Webブラウザ起動ボタン。 diff --git a/src/main/java/jp/sourceforge/jindolf/WebIPC.java b/src/main/java/jp/sfjp/jindolf/dxchg/WebIPC.java similarity index 99% rename from src/main/java/jp/sourceforge/jindolf/WebIPC.java rename to src/main/java/jp/sfjp/jindolf/dxchg/WebIPC.java index fda6d26..e1b7e29 100644 --- a/src/main/java/jp/sourceforge/jindolf/WebIPC.java +++ b/src/main/java/jp/sfjp/jindolf/dxchg/WebIPC.java @@ -5,7 +5,7 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.dxchg; import java.awt.GraphicsEnvironment; import java.awt.HeadlessException; diff --git a/src/main/java/jp/sourceforge/jindolf/WebIPCDialog.java b/src/main/java/jp/sfjp/jindolf/dxchg/WebIPCDialog.java similarity index 95% rename from src/main/java/jp/sourceforge/jindolf/WebIPCDialog.java rename to src/main/java/jp/sfjp/jindolf/dxchg/WebIPCDialog.java index 14ee499..9e1e390 100644 --- a/src/main/java/jp/sourceforge/jindolf/WebIPCDialog.java +++ b/src/main/java/jp/sfjp/jindolf/dxchg/WebIPCDialog.java @@ -5,7 +5,7 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.dxchg; import java.awt.Container; import java.awt.Frame; @@ -35,6 +35,11 @@ import javax.swing.SwingConstants; import javax.swing.TransferHandler; import javax.swing.border.Border; import javax.swing.border.EtchedBorder; +import jp.sfjp.jindolf.JreChecker; +import jp.sfjp.jindolf.VerInfo; +import jp.sfjp.jindolf.log.LogWrapper; +import jp.sfjp.jindolf.util.GUIUtils; +import jp.sfjp.jindolf.util.Monodizer; /** * Webブラウザ起動用の専用ダイアログ。 @@ -44,8 +49,11 @@ public class WebIPCDialog extends JDialog implements ActionListener { - private static final String FRAMETITLE = - "URLへのアクセス確認 - " + Jindolf.TITLE; + private static final String TITLE_WWW = + VerInfo.getFrameTitle("URLへのアクセス確認"); + + + private static final LogWrapper LOGGER = new LogWrapper(); private final String warnMessage; @@ -73,7 +81,8 @@ public class WebIPCDialog * @param owner オーナーフレーム */ public WebIPCDialog(Frame owner){ - super(owner, FRAMETITLE, true); + super(owner); + setModal(true); GUIUtils.modifyWindowAttributes(this, true, false, true); @@ -87,7 +96,7 @@ public class WebIPCDialog this.ipc = webipc; if(this.ipc == null){ - if( ! Jindolf.JRE_PACKAGE.isCompatibleWith("1.6") ){ + if( ! JreChecker.has16Runtime() ){ this.warnMessage = "この機能を利用するには、JRE1.6以上が必要です"; }else{ @@ -141,7 +150,6 @@ public class WebIPCDialog return; } - /** * Webブラウザ起動用のモーダルダイアログを表示する。 * @param owner オーナーフレーム @@ -150,6 +158,7 @@ public class WebIPCDialog public static void showDialog(Frame owner, String url){ WebIPCDialog dialog = new WebIPCDialog(owner); + dialog.setTitle(TITLE_WWW); dialog.setUrlText(url); dialog.pack(); dialog.setLocationRelativeTo(owner); @@ -285,7 +294,7 @@ public class WebIPCDialog if(this.ipc == null){ String title; - if( ! Jindolf.JRE_PACKAGE.isCompatibleWith("1.6") ){ + if( ! JreChecker.has16Runtime() ){ title = "新しいJavaを入手しましょう"; }else{ title = "報告"; @@ -314,7 +323,7 @@ public class WebIPCDialog String logmsg = "URL " + this.uri.toASCIIString() + " へのアクセスをWebブラウザに指示しました"; - Jindolf.logger().info(logmsg); + LOGGER.info(logmsg); }finally{ close(); } @@ -338,7 +347,7 @@ public class WebIPCDialog String logmsg = "文字列「" + uristring + "」をクリップボードにコピーしました"; - Jindolf.logger().info(logmsg); + LOGGER.info(logmsg); }finally{ close(); } @@ -415,7 +424,7 @@ public class WebIPCDialog String logmsg = "URL " + WebIPCDialog.this.uri.toASCIIString() + " がどこかへドラッグ&ドロップされました"; - Jindolf.logger().info(logmsg); + LOGGER.info(logmsg); close(); diff --git a/src/main/java/jp/sourceforge/jindolf/WolfBBS.java b/src/main/java/jp/sfjp/jindolf/dxchg/WolfBBS.java similarity index 93% rename from src/main/java/jp/sourceforge/jindolf/WolfBBS.java rename to src/main/java/jp/sfjp/jindolf/dxchg/WolfBBS.java index 5088bfa..b78f7c8 100644 --- a/src/main/java/jp/sourceforge/jindolf/WolfBBS.java +++ b/src/main/java/jp/sfjp/jindolf/dxchg/WolfBBS.java @@ -5,10 +5,10 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.dxchg; +import java.io.FileNotFoundException; import java.io.IOException; -import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.CharacterCodingException; @@ -24,6 +24,9 @@ import java.util.SortedSet; import java.util.TreeSet; import java.util.regex.Matcher; import java.util.regex.Pattern; +import jp.sfjp.jindolf.ResourceManager; +import jp.sfjp.jindolf.data.Avatar; +import jp.sfjp.jindolf.log.LogWrapper; import jp.sourceforge.jindolf.corelib.Destiny; import jp.sourceforge.jindolf.corelib.GameRole; @@ -43,7 +46,7 @@ public final class WolfBBS{ Pattern.compile("[A-Z][a-z]+([A-Z])[a-z]+"); private static final String FACEICONSET = - "resources/faceIconSet.properties"; + "resources/wolfbbs/faceIconSet.properties"; private static final String ORDER_PREFIX = "iconset.order."; private static final List FACEICONSET_LIST = new LinkedList(); @@ -52,8 +55,14 @@ public final class WolfBBS{ private static final String WOLFBBS_URL = "http://wolfbbs.jp/"; + private static final LogWrapper LOGGER = new LogWrapper(); + static{ - loadFaceIconSet(); + try{ + loadFaceIconSet(); + }catch(FileNotFoundException e){ + throw new ExceptionInInitializerError(e); + } StringBuilder wikicomment = new StringBuilder(); wikicomment.append("// "); @@ -76,17 +85,13 @@ public final class WolfBBS{ /** * アイコンセットのロード。 + * @throws FileNotFoundException リソースが不明 */ - private static void loadFaceIconSet(){ - InputStream is = Jindolf.getResourceAsStream(FACEICONSET); - Properties properties = new Properties(); - try{ - properties.load(is); - is.close(); - }catch(IOException e){ - Jindolf.logger().fatal( - "顔アイコンセットの読み込みに失敗しました", e); - Jindolf.exit(1); + private static void loadFaceIconSet() throws FileNotFoundException { + Properties properties = ResourceManager.getProperties(FACEICONSET); + if(properties == null){ + LOGGER.fatal("顔アイコンセットの読み込みに失敗しました"); + throw new FileNotFoundException(); } loadFaceIconSet(properties); @@ -97,18 +102,19 @@ public final class WolfBBS{ /** * アイコンセットのロード。 * @param properties プロパティ + * @throws FileNotFoundException リソースが不明 */ - private static void loadFaceIconSet(Properties properties){ + private static void loadFaceIconSet(Properties properties) + throws FileNotFoundException { String codeCheck = properties.getProperty("codeCheck"); if( codeCheck == null || codeCheck.length() != 1 || codeCheck.charAt(0) != '\u72fc'){ // 「狼」 - Jindolf.logger().fatal( + LOGGER.fatal( "顔アイコンセットプロパティファイルの" +"文字コードがおかしいようです。" +"native2ascii は正しく適用しましたか?"); - Jindolf.exit(1); - return; + throw new FileNotFoundException(); } Set keySet = properties.keySet(); @@ -285,7 +291,6 @@ public final class WolfBBS{ int resultLength; - resultLength = result.length(); while(result.length() > 0 && result.charAt(0) == '/'){ result.deleteCharAt(0); } diff --git a/src/main/java/jp/sourceforge/jindolf/XmlResourceResolver.java b/src/main/java/jp/sfjp/jindolf/dxchg/XmlResourceResolver.java similarity index 99% rename from src/main/java/jp/sourceforge/jindolf/XmlResourceResolver.java rename to src/main/java/jp/sfjp/jindolf/dxchg/XmlResourceResolver.java index b528a68..b96d0eb 100644 --- a/src/main/java/jp/sourceforge/jindolf/XmlResourceResolver.java +++ b/src/main/java/jp/sfjp/jindolf/dxchg/XmlResourceResolver.java @@ -5,7 +5,7 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.dxchg; import java.io.IOException; import java.io.InputStream; diff --git a/src/main/java/jp/sourceforge/jindolf/XmlUtils.java b/src/main/java/jp/sfjp/jindolf/dxchg/XmlUtils.java similarity index 99% rename from src/main/java/jp/sourceforge/jindolf/XmlUtils.java rename to src/main/java/jp/sfjp/jindolf/dxchg/XmlUtils.java index 70533ab..97c41f1 100644 --- a/src/main/java/jp/sourceforge/jindolf/XmlUtils.java +++ b/src/main/java/jp/sfjp/jindolf/dxchg/XmlUtils.java @@ -5,7 +5,7 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.dxchg; import java.io.IOException; import java.io.InputStream; diff --git a/src/main/java/jp/sfjp/jindolf/dxchg/package-info.java b/src/main/java/jp/sfjp/jindolf/dxchg/package-info.java new file mode 100644 index 0000000..8307f4d --- /dev/null +++ b/src/main/java/jp/sfjp/jindolf/dxchg/package-info.java @@ -0,0 +1,14 @@ +/* + * パッケージ情報 + * + * License : The MIT License + * Copyright(c) 2011 olyutorskii + */ + +/** + * 他アプリやサービスとのデータ交換関連の一連のクラス。 + */ + +package jp.sfjp.jindolf.dxchg; + +/* EOF */ diff --git a/src/main/java/jp/sourceforge/jindolf/BalloonBorder.java b/src/main/java/jp/sfjp/jindolf/editor/BalloonBorder.java similarity index 99% rename from src/main/java/jp/sourceforge/jindolf/BalloonBorder.java rename to src/main/java/jp/sfjp/jindolf/editor/BalloonBorder.java index cd7465f..13601e7 100644 --- a/src/main/java/jp/sourceforge/jindolf/BalloonBorder.java +++ b/src/main/java/jp/sfjp/jindolf/editor/BalloonBorder.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.editor; import java.awt.BorderLayout; import java.awt.Color; diff --git a/src/main/java/jp/sourceforge/jindolf/EditArray.java b/src/main/java/jp/sfjp/jindolf/editor/EditArray.java similarity index 99% rename from src/main/java/jp/sourceforge/jindolf/EditArray.java rename to src/main/java/jp/sfjp/jindolf/editor/EditArray.java index 1fc6cd3..1500bdb 100644 --- a/src/main/java/jp/sourceforge/jindolf/EditArray.java +++ b/src/main/java/jp/sfjp/jindolf/editor/EditArray.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.editor; import java.awt.Dimension; import java.awt.EventQueue; diff --git a/src/main/java/jp/sourceforge/jindolf/TalkEditor.java b/src/main/java/jp/sfjp/jindolf/editor/TalkEditor.java similarity index 99% rename from src/main/java/jp/sourceforge/jindolf/TalkEditor.java rename to src/main/java/jp/sfjp/jindolf/editor/TalkEditor.java index 2a1280f..17caa8f 100644 --- a/src/main/java/jp/sourceforge/jindolf/TalkEditor.java +++ b/src/main/java/jp/sfjp/jindolf/editor/TalkEditor.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.editor; import java.awt.Color; import java.awt.Dimension; @@ -29,6 +29,7 @@ import javax.swing.text.Document; import javax.swing.text.NavigationFilter; import javax.swing.text.PlainDocument; import javax.swing.text.Segment; +import jp.sfjp.jindolf.dxchg.TextPopup; /** * 原稿作成支援エディタ。 @@ -74,6 +75,7 @@ public class TalkEditor * コンストラクタ。 * @param seqNumber 通し番号 */ + @SuppressWarnings("LeakingThisInConstructor") private TalkEditor(int seqNumber){ super(); diff --git a/src/main/java/jp/sourceforge/jindolf/TalkPreview.java b/src/main/java/jp/sfjp/jindolf/editor/TalkPreview.java similarity index 91% rename from src/main/java/jp/sourceforge/jindolf/TalkPreview.java rename to src/main/java/jp/sfjp/jindolf/editor/TalkPreview.java index fae79c1..c95d4a0 100644 --- a/src/main/java/jp/sourceforge/jindolf/TalkPreview.java +++ b/src/main/java/jp/sfjp/jindolf/editor/TalkPreview.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.editor; import java.awt.BorderLayout; import java.awt.Color; @@ -35,9 +35,15 @@ import javax.swing.border.TitledBorder; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.text.JTextComponent; +import jp.sfjp.jindolf.dxchg.ClipboardAction; +import jp.sfjp.jindolf.dxchg.TextPopup; +import jp.sfjp.jindolf.glyph.FontInfo; +import jp.sfjp.jindolf.util.GUIUtils; import jp.sourceforge.jovsonz.JsArray; +import jp.sourceforge.jovsonz.JsComposition; import jp.sourceforge.jovsonz.JsObject; import jp.sourceforge.jovsonz.JsString; +import jp.sourceforge.jovsonz.JsTypes; import jp.sourceforge.jovsonz.JsValue; /** @@ -47,9 +53,10 @@ import jp.sourceforge.jovsonz.JsValue; public class TalkPreview extends JFrame implements ActionListener, ChangeListener{ - private static final String FRAMETITLE = "発言エディタ - " + Jindolf.TITLE; + /** 原稿ファイル。 */ + public static final File DRAFT_FILE = new File("draft.json"); + private static final Color COLOR_EDITORBACK = Color.BLACK; - private static final String DRAFT_FILE = "draft.json"; private final JTextComponent freeMemo = new TextEditor(); @@ -74,8 +81,9 @@ public class TalkPreview extends JFrame /** * コンストラクタ。 */ + @SuppressWarnings("LeakingThisInConstructor") public TalkPreview(){ - super(FRAMETITLE); + super(); GUIUtils.modifyWindowAttributes(this, true, false, true); @@ -338,28 +346,44 @@ public class TalkPreview extends JFrame } /** - * 原稿のロード。 + * JSON形式の原稿情報を返す。 + * @return JSON形式の原稿情報 + */ + public JsObject getJson(){ + JsObject result = new JsObject(); + JsString memo = new JsString(this.freeMemo.getText()); + result.putValue("freeMemo", memo); + + JsArray array = new JsArray(); + JsString text = new JsString(this.editArray.getAllText()); + array.add(text); + result.putValue("drafts", array); + + return result; + } + + /** + * JSON形式の原稿情報を反映させる。 + * @param root JSON形式の原稿情報。nullが来たら何もしない */ - public void loadDraft(){ - JsValue value = ConfigFile.loadJson(new File(DRAFT_FILE)); - if(value == null) return; + public void putJson(JsObject root){ + if(root == null) return; - if( ! (value instanceof JsObject) ) return; - JsObject root = (JsObject) value; + JsValue value; value = root.getValue("freeMemo"); - if(value instanceof JsString){ + if(value.getJsTypes() == JsTypes.STRING){ JsString memo = (JsString) value; this.freeMemo.setText(memo.toRawString()); } value = root.getValue("drafts"); - if( ! (value instanceof JsArray) ) return; + if(value.getJsTypes() != JsTypes.ARRAY) return; JsArray array = (JsArray) value; StringBuilder draftAll = new StringBuilder(); for(JsValue elem : array){ - if( ! (elem instanceof JsString) ) continue; + if(elem.getJsTypes() != JsTypes.STRING) continue; JsString draft = (JsString) elem; draftAll.append(draft.toRawString()); } @@ -372,30 +396,15 @@ public class TalkPreview extends JFrame } /** - * 原稿のセーブ。 + * 起動時の原稿と等価か判定する。 + * @param conf 比較対象 + * @return 等価ならtrue */ - public void saveDraft(){ - AppSetting setting = Jindolf.getAppSetting(); - if( ! setting.useConfigPath() ) return; - File configPath = setting.getConfigPath(); - if(configPath == null) return; - - JsObject root = new JsObject(); - JsString memo = new JsString(this.freeMemo.getText()); - root.putValue("freeMemo", memo); - - JsArray array = new JsArray(); - JsString text = new JsString(this.editArray.getAllText()); - array.add(text); - root.putValue("drafts", array); - + public boolean hasConfChanged(JsComposition conf){ if(this.loadedDraft != null){ - if(this.loadedDraft.equals(root)) return; + if(this.loadedDraft.equals(conf)) return true; } - - ConfigFile.saveJson(new File(DRAFT_FILE), root); - - return; + return false; } /** diff --git a/src/main/java/jp/sourceforge/jindolf/TextEditor.java b/src/main/java/jp/sfjp/jindolf/editor/TextEditor.java similarity index 99% rename from src/main/java/jp/sourceforge/jindolf/TextEditor.java rename to src/main/java/jp/sfjp/jindolf/editor/TextEditor.java index 28ba523..6ada0d2 100644 --- a/src/main/java/jp/sourceforge/jindolf/TextEditor.java +++ b/src/main/java/jp/sfjp/jindolf/editor/TextEditor.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.editor; import java.awt.Rectangle; import java.awt.event.InputMethodEvent; @@ -37,6 +37,7 @@ public class TextEditor extends JTextArea /** * コンストラクタ。 */ + @SuppressWarnings("LeakingThisInConstructor") public TextEditor(){ super(); diff --git a/src/main/java/jp/sfjp/jindolf/editor/package-info.java b/src/main/java/jp/sfjp/jindolf/editor/package-info.java new file mode 100644 index 0000000..0ba1728 --- /dev/null +++ b/src/main/java/jp/sfjp/jindolf/editor/package-info.java @@ -0,0 +1,14 @@ +/* + * パッケージ情報 + * + * License : The MIT License + * Copyright(c) 2011 olyutorskii + */ + +/** + * 発言エディタ関連の一連のクラス。 + */ + +package jp.sfjp.jindolf.editor; + +/* EOF */ diff --git a/src/main/java/jp/sourceforge/jindolf/AbstractTextRow.java b/src/main/java/jp/sfjp/jindolf/glyph/AbstractTextRow.java similarity index 99% rename from src/main/java/jp/sourceforge/jindolf/AbstractTextRow.java rename to src/main/java/jp/sfjp/jindolf/glyph/AbstractTextRow.java index fe42f33..e3c7192 100644 --- a/src/main/java/jp/sourceforge/jindolf/AbstractTextRow.java +++ b/src/main/java/jp/sfjp/jindolf/glyph/AbstractTextRow.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.glyph; import java.awt.Rectangle; import java.awt.font.GlyphVector; diff --git a/src/main/java/jp/sourceforge/jindolf/AnchorDraw.java b/src/main/java/jp/sfjp/jindolf/glyph/AnchorDraw.java similarity index 97% rename from src/main/java/jp/sourceforge/jindolf/AnchorDraw.java rename to src/main/java/jp/sfjp/jindolf/glyph/AnchorDraw.java index 67a4bfe..309cf46 100644 --- a/src/main/java/jp/sourceforge/jindolf/AnchorDraw.java +++ b/src/main/java/jp/sfjp/jindolf/glyph/AnchorDraw.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.glyph; import java.awt.BasicStroke; import java.awt.Color; @@ -16,6 +16,11 @@ import java.awt.Stroke; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.regex.Pattern; +import jp.sfjp.jindolf.data.Avatar; +import jp.sfjp.jindolf.data.DialogPref; +import jp.sfjp.jindolf.data.Period; +import jp.sfjp.jindolf.data.Talk; +import jp.sfjp.jindolf.data.Village; /** * アンカー描画。 diff --git a/src/main/java/jp/sourceforge/jindolf/AnchorHitEvent.java b/src/main/java/jp/sfjp/jindolf/glyph/AnchorHitEvent.java similarity index 95% rename from src/main/java/jp/sourceforge/jindolf/AnchorHitEvent.java rename to src/main/java/jp/sfjp/jindolf/glyph/AnchorHitEvent.java index 9dd4b33..557700e 100644 --- a/src/main/java/jp/sourceforge/jindolf/AnchorHitEvent.java +++ b/src/main/java/jp/sfjp/jindolf/glyph/AnchorHitEvent.java @@ -5,10 +5,11 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.glyph; import java.awt.Point; import java.util.EventObject; +import jp.sfjp.jindolf.data.Anchor; /** * 発言アンカーがクリックされたときのイベント。 diff --git a/src/main/java/jp/sourceforge/jindolf/AnchorHitListener.java b/src/main/java/jp/sfjp/jindolf/glyph/AnchorHitListener.java similarity index 93% rename from src/main/java/jp/sourceforge/jindolf/AnchorHitListener.java rename to src/main/java/jp/sfjp/jindolf/glyph/AnchorHitListener.java index c65f8d4..094d699 100644 --- a/src/main/java/jp/sourceforge/jindolf/AnchorHitListener.java +++ b/src/main/java/jp/sfjp/jindolf/glyph/AnchorHitListener.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.glyph; import java.util.EventListener; diff --git a/src/main/java/jp/sourceforge/jindolf/Discussion.java b/src/main/java/jp/sfjp/jindolf/glyph/Discussion.java similarity index 98% rename from src/main/java/jp/sourceforge/jindolf/Discussion.java rename to src/main/java/jp/sfjp/jindolf/glyph/Discussion.java index 890ec86..54538ae 100644 --- a/src/main/java/jp/sourceforge/jindolf/Discussion.java +++ b/src/main/java/jp/sfjp/jindolf/glyph/Discussion.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.glyph; import java.awt.Color; import java.awt.Component; @@ -42,6 +42,18 @@ import javax.swing.SwingConstants; import javax.swing.event.EventListenerList; import javax.swing.event.MouseInputListener; import javax.swing.text.DefaultEditorKit; +import jp.sfjp.jindolf.data.Anchor; +import jp.sfjp.jindolf.data.Avatar; +import jp.sfjp.jindolf.data.DialogPref; +import jp.sfjp.jindolf.data.Period; +import jp.sfjp.jindolf.data.RegexPattern; +import jp.sfjp.jindolf.data.SysEvent; +import jp.sfjp.jindolf.data.Talk; +import jp.sfjp.jindolf.data.Topic; +import jp.sfjp.jindolf.dxchg.ClipboardAction; +import jp.sfjp.jindolf.util.GUIUtils; +import jp.sfjp.jindolf.view.ActionManager; +import jp.sfjp.jindolf.view.TopicFilter; /** * 発言表示画面。 @@ -89,6 +101,7 @@ public class Discussion extends JComponent /** * 発言表示画面を作成する。 */ + @SuppressWarnings("LeakingThisInConstructor") public Discussion(){ super(); diff --git a/src/main/java/jp/sourceforge/jindolf/FontChooser.java b/src/main/java/jp/sfjp/jindolf/glyph/FontChooser.java similarity index 52% rename from src/main/java/jp/sourceforge/jindolf/FontChooser.java rename to src/main/java/jp/sfjp/jindolf/glyph/FontChooser.java index 8b099ef..76fe2e2 100644 --- a/src/main/java/jp/sourceforge/jindolf/FontChooser.java +++ b/src/main/java/jp/sfjp/jindolf/glyph/FontChooser.java @@ -5,15 +5,11 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.glyph; import java.awt.BorderLayout; -import java.awt.Color; import java.awt.Container; -import java.awt.Dimension; import java.awt.Font; -import java.awt.Graphics; -import java.awt.Graphics2D; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; @@ -22,24 +18,22 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; -import java.awt.font.FontRenderContext; -import java.awt.geom.AffineTransform; -import java.awt.geom.Rectangle2D; -import java.io.IOException; +import java.text.MessageFormat; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; -import javax.swing.JComponent; import javax.swing.JLabel; -import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; -import javax.swing.ListSelectionModel; import javax.swing.border.Border; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; +import jp.sfjp.jindolf.ResourceManager; +import jp.sfjp.jindolf.dxchg.TextPopup; +import jp.sfjp.jindolf.log.LogWrapper; +import jp.sfjp.jindolf.util.Monodizer; /** * 発言表示フォント選択パネル。 @@ -48,27 +42,25 @@ import javax.swing.event.ListSelectionListener; public class FontChooser extends JPanel implements ListSelectionListener, ActionListener, - ItemListener{ + ItemListener { - private static final Integer[] POINT_SIZES = { + private static final int[] POINT_SIZES = { 8, 10, 12, 16, 18, 24, 32, 36, 48, 72, // TODO これで十分? }; private static final CharSequence PREVIEW_CONTENT; + private static final int UNIT_INC = 8; + + private static final LogWrapper LOGGER = new LogWrapper(); static{ - CharSequence resourceText; - try{ - resourceText = Jindolf.loadResourceText("resources/preview.txt"); - }catch(IOException e){ - resourceText = "ABC"; - } - PREVIEW_CONTENT = resourceText; + PREVIEW_CONTENT = + ResourceManager.getTextFile("resources/font/preview.txt"); } private FontInfo fontInfo; private FontInfo lastFontInfo; - private final JList familySelector; + private final FontSelectList familySelector; private final JComboBox sizeSelector; private final JCheckBox isBoldCheck; private final JCheckBox isItalicCheck; @@ -76,7 +68,7 @@ public class FontChooser extends JPanel private final JCheckBox useFractionalCheck; private final JLabel maxBounds; private final JTextField decodeName; - private final FontPreview preview; + private final FontPreviewer preview; private final JButton resetDefault; private boolean maskListener = false; @@ -102,28 +94,13 @@ public class FontChooser extends JPanel this.fontInfo = fontInfo; this.lastFontInfo = fontInfo; - Jindolf.logger().info( - "デフォルトの発言表示フォントに" - + this.fontInfo.getFont() - + "が選択されました" ); - Jindolf.logger().info( - "発言表示のアンチエイリアス指定に" - + this.fontInfo.getFontRenderContext().isAntiAliased() - + "が指定されました" ); - Jindolf.logger().info( - "発言表示のFractional指定に" - + this.fontInfo.getFontRenderContext().usesFractionalMetrics() - + "が指定されました" ); - - this.familySelector = new JList(FontUtils.createFontSet().toArray()); - this.familySelector.setVisibleRowCount(-1); - this.familySelector - .setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + logging(this.fontInfo); + + this.familySelector = new FontSelectList(); this.sizeSelector = new JComboBox(); this.sizeSelector.setEditable(true); - this.sizeSelector.setActionCommand(ActionManager.CMD_FONTSIZESEL); - for(Integer size : POINT_SIZES){ + for(int size : POINT_SIZES){ this.sizeSelector.addItem(size); } @@ -140,14 +117,12 @@ public class FontChooser extends JPanel this.decodeName.setComponentPopupMenu(new TextPopup()); Monodizer.monodize(this.decodeName); - this.preview = new FontPreview(PREVIEW_CONTENT, this.fontInfo); + this.preview = new FontPreviewer(PREVIEW_CONTENT, this.fontInfo); this.resetDefault = new JButton("出荷時に戻す"); - this.resetDefault.addActionListener(this); design(this); updateControlls(); - updatePreview(); this.familySelector.addListSelectionListener(this); this.sizeSelector .addActionListener(this); @@ -157,6 +132,31 @@ public class FontChooser extends JPanel this.useTextAntiAliaseCheck.addItemListener(this); this.useFractionalCheck .addItemListener(this); + this.resetDefault.addActionListener(this); + + return; + } + + /** + * フォント情報に関するログ出力。 + * @param info フォント情報 + */ + private static void logging(FontInfo info){ + String form; + String logMsg; + + form = "発言表示フォントに{0}が選択されました。"; + logMsg = MessageFormat.format(form, info.getFont()); + LOGGER.info(logMsg); + + form = "発言表示のアンチエイリアス指定に{0}が指定されました。"; + logMsg = MessageFormat.format(form, info.isAntiAliased()); + LOGGER.info(logMsg); + + form = "発言表示のFractional指定に{0}が指定されました。"; + logMsg = MessageFormat.format(form, info.usesFractionalMetrics()); + LOGGER.info(logMsg); + return; } @@ -166,50 +166,39 @@ public class FontChooser extends JPanel */ private void design(Container content){ GridBagLayout layout = new GridBagLayout(); - GridBagConstraints constraints = new GridBagConstraints(); - content.setLayout(layout); - Border border; - JPanel panel; - - JComponent fontPref = createFontPrefPanel(); - + GridBagConstraints constraints = new GridBagConstraints(); constraints.insets = new Insets(5, 5, 5, 5); - constraints.weightx = 1.0; - constraints.weighty = 0.0; + constraints.weightx = 1.0; + constraints.weighty = 0.0; constraints.gridwidth = GridBagConstraints.REMAINDER; - constraints.fill = GridBagConstraints.BOTH; - content.add(fontPref, constraints); + constraints.fill = GridBagConstraints.BOTH; + content.add(createFontPrefPanel(), constraints); - constraints.weightx = 1.0; - constraints.weighty = 1.0; + constraints.weightx = 1.0; + constraints.weighty = 1.0; constraints.gridwidth = GridBagConstraints.REMAINDER; - constraints.fill = GridBagConstraints.BOTH; - border = BorderFactory.createTitledBorder("プレビュー"); - panel = new JPanel(); - panel.add(this.preview); - panel.setBorder(border); + constraints.fill = GridBagConstraints.BOTH; content.add(createPreviewPanel(), constraints); - constraints.weightx = 1.0; - constraints.weighty = 0.0; + constraints.weightx = 1.0; + constraints.weighty = 0.0; constraints.gridwidth = GridBagConstraints.REMAINDER; - constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.fill = GridBagConstraints.HORIZONTAL; content.add(createFontDecodePanel(), constraints); - constraints.insets = new Insets(5, 5, 5, 5); - constraints.weightx = 1.0; - constraints.weighty = 0.0; + constraints.weightx = 1.0; + constraints.weighty = 0.0; constraints.gridwidth = 1; - constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.fill = GridBagConstraints.HORIZONTAL; content.add(this.maxBounds, constraints); - constraints.weightx = 0.0; - constraints.weighty = 0.0; + constraints.weightx = 0.0; + constraints.weighty = 0.0; constraints.gridwidth = GridBagConstraints.REMAINDER; - constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.fill = GridBagConstraints.HORIZONTAL; content.add(this.resetDefault, constraints); return; @@ -219,47 +208,50 @@ public class FontChooser extends JPanel * フォント設定画面を生成する。 * @return フォント設定画面 */ - private JComponent createFontPrefPanel(){ + private JPanel createFontPrefPanel(){ JPanel result = new JPanel(); GridBagLayout layout = new GridBagLayout(); GridBagConstraints constraints = new GridBagConstraints(); result.setLayout(layout); - Border border; + JPanel familyBorderPanel = new JPanel(); + Border familyBorder = + BorderFactory.createTitledBorder("フォントファミリ選択"); + familyBorderPanel.setBorder(familyBorder); - constraints.insets = new Insets(0, 0, 0, 5); - constraints.weightx = 1.0; - constraints.weighty = 0.0; - constraints.gridheight = GridBagConstraints.REMAINDER; - constraints.fill = GridBagConstraints.BOTH; - border = BorderFactory.createEmptyBorder(1, 1, 1, 1); - this.familySelector.setBorder(border); + JPanel sizeBorderPanel = new JPanel(); + Border sizeBorder = + BorderFactory.createTitledBorder("ポイントサイズ指定"); + sizeBorderPanel.setBorder(sizeBorder); + + Border scrollBorder = BorderFactory.createEmptyBorder(1, 1, 1, 1); + this.familySelector.setBorder(scrollBorder); JScrollPane familyScroller = new JScrollPane(this.familySelector); - border = BorderFactory.createTitledBorder("フォントファミリ選択"); - JPanel familyPanel = new JPanel(); - familyPanel.setLayout(new BorderLayout()); - familyPanel.add(familyScroller, BorderLayout.CENTER); - familyPanel.setBorder(border); - result.add(familyPanel, constraints); - - constraints.insets = new Insets(0, 0, 0, 0); - constraints.weightx = 0.0; - constraints.gridheight = 1; - constraints.fill = GridBagConstraints.HORIZONTAL; - constraints.anchor = GridBagConstraints.WEST; - border = BorderFactory.createTitledBorder("ポイントサイズ指定"); - JPanel panel = new JPanel(); - panel.add(this.sizeSelector); - panel.setBorder(border); - result.add(panel, constraints); + familyBorderPanel.setLayout(new BorderLayout()); + familyBorderPanel.add(familyScroller); + constraints.insets = new Insets(0, 0, 0, 5); + constraints.weightx = 1.0; + constraints.weighty = 0.0; + constraints.gridheight = GridBagConstraints.REMAINDER; + constraints.fill = GridBagConstraints.BOTH; + result.add(familyBorderPanel, constraints); + + sizeBorderPanel.setLayout(new BorderLayout()); + sizeBorderPanel.add(this.sizeSelector); + constraints.insets = new Insets(0, 0, 0, 0); + constraints.weightx = 0.0; + constraints.gridheight = 1; + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.anchor = GridBagConstraints.WEST; + result.add(sizeBorderPanel, constraints); constraints.anchor = GridBagConstraints.NORTHWEST; - result.add(this.isBoldCheck, constraints); - result.add(this.isItalicCheck, constraints); + result.add(this.isBoldCheck, constraints); + result.add(this.isItalicCheck, constraints); result.add(this.useTextAntiAliaseCheck, constraints); - result.add(this.useFractionalCheck, constraints); + result.add(this.useFractionalCheck, constraints); return result; } @@ -268,17 +260,17 @@ public class FontChooser extends JPanel * プレビュー画面を生成する。 * @return プレビュー画面 */ - private JComponent createPreviewPanel(){ + private JPanel createPreviewPanel(){ JPanel result = new JPanel(); + Border border = + BorderFactory.createTitledBorder("フォントプレビュー"); + result.setBorder(border); JScrollPane scroller = new JScrollPane(this.preview); - scroller.getVerticalScrollBar().setUnitIncrement(8); + scroller.getVerticalScrollBar().setUnitIncrement(UNIT_INC); - Border border; - border = BorderFactory.createTitledBorder("プレビュー"); - result.setBorder(border); result.setLayout(new BorderLayout()); - result.add(scroller, BorderLayout.CENTER); + result.add(scroller); return result; } @@ -287,22 +279,25 @@ public class FontChooser extends JPanel * フォントデコード名表示パネルを生成する。 * @return フォントデコード名表示パネル */ - private JComponent createFontDecodePanel(){ + private JPanel createFontDecodePanel(){ JPanel result = new JPanel(); GridBagLayout layout = new GridBagLayout(); - GridBagConstraints constraints = new GridBagConstraints(); result.setLayout(layout); - constraints.weightx = 0.0; - constraints.weighty = 0.0; + GridBagConstraints constraints = new GridBagConstraints(); + + JLabel label = new JLabel("Font.deode() 識別名:"); + + constraints.weightx = 0.0; + constraints.weighty = 0.0; constraints.gridwidth = 1; - constraints.fill = GridBagConstraints.NONE; - result.add(new JLabel("Font.deode() 識別名:"), constraints); + constraints.fill = GridBagConstraints.NONE; + result.add(label, constraints); - constraints.weightx = 1.0; + constraints.weightx = 1.0; constraints.gridwidth = GridBagConstraints.REMAINDER; - constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.fill = GridBagConstraints.HORIZONTAL; result.add(this.decodeName, constraints); return result; @@ -330,51 +325,28 @@ public class FontChooser extends JPanel this.fontInfo = newInfo; updateControlls(); - updatePreview(); return; } /** - * 選択されたフォントを返す。 - * @return フォント - */ - private Font getSelectedFont(){ - return this.fontInfo.getFont(); - } - - /** - * 設定されたフォント描画設定を返す。 - * @return 描画設定 - */ - protected FontRenderContext getFontRenderContext(){ - return this.fontInfo.getFontRenderContext(); - } - - /** - * フォント設定に合わせてプレビュー画面を更新する。 - */ - private void updatePreview(){ - this.preview.setFontInfo(this.fontInfo); - return; - } - - /** * フォント設定に合わせてGUIを更新する。 + *

イベント発火は抑止される。 */ private void updateControlls(){ this.maskListener = true; - Font currentFont = getSelectedFont(); - FontRenderContext currentContext = getFontRenderContext(); + Font currentFont = getFontInfo().getFont(); + // フォント名リスト String defaultFamily = currentFont.getFamily(); - this.familySelector.setSelectedValue(defaultFamily, true); + this.familySelector.setSelectedFamily(defaultFamily); + // サイズ指定コンボボックス Integer selectedInteger = Integer.valueOf(currentFont.getSize()); this.sizeSelector.setSelectedItem(selectedInteger); int sizeItems = this.sizeSelector.getItemCount(); - for(int index = 0; index <= sizeItems - 1; index++){ + for(int index = 0; index < sizeItems; index++){ Object sizeItem = this.sizeSelector.getItemAt(index); if(sizeItem.equals(selectedInteger)){ this.sizeSelector.setSelectedIndex(index); @@ -382,26 +354,31 @@ public class FontChooser extends JPanel } } + // チェックボックス群 this.isBoldCheck .setSelected(currentFont.isBold()); this.isItalicCheck.setSelected(currentFont.isItalic()); - this.useTextAntiAliaseCheck - .setSelected(currentContext.isAntiAliased()); + .setSelected(this.fontInfo.isAntiAliased()); this.useFractionalCheck - .setSelected(currentContext.usesFractionalMetrics()); + .setSelected(this.fontInfo.usesFractionalMetrics()); + // デコード名 this.decodeName.setText(FontUtils.getFontDecodeName(currentFont)); this.decodeName.setCaretPosition(0); - Rectangle2D r2d = currentFont.getMaxCharBounds(currentContext); - Rectangle rect = r2d.getBounds(); - String boundInfo = "最大文字寸法 : " - + rect.width - + " pixel幅 × " - + rect.height - + " pixel高"; + // 寸法 + String form = "最大文字寸法\u0020:\u0020" + + "{0}\u0020pixel幅" + + "\u0020×\u0020" + + "{1}\u0020pixel高"; + Rectangle rect = this.fontInfo.getMaxCharBounds(); + String boundInfo = + MessageFormat.format(form, rect.width, rect.height); this.maxBounds.setText(boundInfo); + // プレビュー + this.preview.setFontInfo(this.fontInfo); + this.maskListener = false; return; @@ -409,15 +386,12 @@ public class FontChooser extends JPanel /** * {@inheritDoc} - * ダイアログの表示・非表示。 - * ダイアログが閉じられるまで制御を返さない。 * @param isVisible trueなら表示 {@inheritDoc} */ @Override public void setVisible(boolean isVisible){ if(isVisible){ updateControlls(); - updatePreview(); } this.lastFontInfo = this.fontInfo; @@ -428,47 +402,52 @@ public class FontChooser extends JPanel /** * {@inheritDoc} - * チェックボックス操作のリスナ。 + * フォントファミリリスト選択操作のリスナ。 * @param event 操作イベント {@inheritDoc} */ @Override - public void itemStateChanged(ItemEvent event){ + public void valueChanged(ListSelectionEvent event){ if(this.maskListener) return; - Object source = event.getSource(); + if(event.getSource() != this.familySelector) return; + if(event.getValueIsAdjusting()) return; - if( source != this.isBoldCheck - && source != this.isItalicCheck - && source != this.useTextAntiAliaseCheck - && source != this.useFractionalCheck ){ - return; - } + String familyName = this.familySelector.getSelectedFamily(); + if(familyName == null) return; - int style = 0 | Font.PLAIN; - if(this.isBoldCheck.isSelected()){ - style = style | Font.BOLD; - } - if(this.isItalicCheck.isSelected()){ - style = style | Font.ITALIC; - } - Font newFont = getSelectedFont(); - if(newFont.getStyle() != style){ - newFont = newFont.deriveFont(style); - } + Font currentFont = getFontInfo().getFont(); + int style = currentFont.getStyle(); + int size = currentFont.getSize(); - AffineTransform tx = getFontRenderContext().getTransform(); - boolean isAntiAliases = this.useTextAntiAliaseCheck.isSelected(); - boolean useFractional = this.useFractionalCheck .isSelected(); - FontRenderContext newContext = - new FontRenderContext(tx, isAntiAliases, useFractional); + Font newFont = new Font(familyName, style, size); + FontInfo newInfo = this.fontInfo.deriveFont(newFont); - FontInfo newInfo = new FontInfo(newFont, newContext); setFontInfo(newInfo); return; } /** + * {@inheritDoc} + * ボタン操作及びフォントサイズ指定コンボボックス操作のリスナ。 + * @param event 操作イベント {@inheritDoc} + */ + @Override + public void actionPerformed(ActionEvent event){ + if(this.maskListener) return; + + Object source = event.getSource(); + + if(source == this.sizeSelector){ + actionFontSizeSelected(); + }else if(source == this.resetDefault){ + setFontInfo(FontInfo.DEFAULT_FONTINFO); + } + + return; + } + + /** * フォントサイズ変更処理。 */ private void actionFontSizeSelected(){ @@ -482,159 +461,63 @@ public class FontChooser extends JPanel try{ selectedInteger = Integer.valueOf(selected.toString()); }catch(NumberFormatException e){ - selectedInteger = Integer.valueOf( - this.lastFontInfo.getFont().getSize() - ); + selectedInteger = this.lastFontInfo.getFont().getSize(); } } - if(selectedInteger.intValue() <= 0){ - selectedInteger = - Integer.valueOf(this.lastFontInfo.getFont().getSize()); + if(selectedInteger <= 0){ + selectedInteger = this.lastFontInfo.getFont().getSize(); } float fontSize = selectedInteger.floatValue(); - Font newFont = getSelectedFont().deriveFont(fontSize); - FontInfo newInfo = this.fontInfo.deriveFont(newFont); - setFontInfo(newInfo); + Font newFont = getFontInfo().getFont().deriveFont(fontSize); + FontInfo newInfo = getFontInfo().deriveFont(newFont); - int sizeItems = this.sizeSelector.getItemCount(); - for(int index = 0; index <= sizeItems - 1; index++){ - Object sizeItem = this.sizeSelector.getItemAt(index); - if(sizeItem.equals(selectedInteger)){ - this.sizeSelector.setSelectedIndex(index); - break; - } - } - - updateControlls(); - updatePreview(); + setFontInfo(newInfo); return; } /** * {@inheritDoc} - * ボタン操作及びフォントサイズ指定コンボボックス操作のリスナ。 + * チェックボックス操作のリスナ。 * @param event 操作イベント {@inheritDoc} */ @Override - public void actionPerformed(ActionEvent event){ + public void itemStateChanged(ItemEvent event){ if(this.maskListener) return; - String cmd = event.getActionCommand(); - if(cmd.equals(ActionManager.CMD_FONTSIZESEL)){ - actionFontSizeSelected(); - } - Object source = event.getSource(); - if(source == this.resetDefault){ - setFontInfo(FontInfo.DEFAULT_FONTINFO); - } - - return; - } - - /** - * {@inheritDoc} - * フォントファミリリスト選択操作のリスナ。 - * @param event 操作イベント {@inheritDoc} - */ - @Override - public void valueChanged(ListSelectionEvent event){ - if(this.maskListener) return; - - if(event.getSource() != this.familySelector) return; - if(event.getValueIsAdjusting()) return; - - Object selected = this.familySelector.getSelectedValue(); - if(selected == null) return; - - String familyName = selected.toString(); - Font currentFont = getSelectedFont(); - int style = currentFont.getStyle(); - int size = currentFont.getSize(); - - Font newFont = new Font(familyName, style, size); - FontInfo newInfo = this.fontInfo.deriveFont(newFont); - - setFontInfo(newInfo); - - return; - } - - /** - * フォントプレビュー画面用コンポーネント。 - */ - private static class FontPreview extends JComponent{ - - private static final int MARGIN = 5; - - private final GlyphDraw draw; - - private FontInfo fontInfo; - - /** - * コンストラクタ。 - * @param source 文字列 - * @param fontInfo フォント設定 - */ - public FontPreview(CharSequence source, - FontInfo fontInfo ){ - super(); - - this.fontInfo = fontInfo; - this.draw = new GlyphDraw(source, this.fontInfo); - this.draw.setFontInfo(this.fontInfo); - - this.draw.setPos(MARGIN, MARGIN); - - this.draw.setColor(Color.BLACK); - setBackground(Color.WHITE); - - updateBounds(); + if( source != this.isBoldCheck + && source != this.isItalicCheck + && source != this.useTextAntiAliaseCheck + && source != this.useFractionalCheck ){ return; } - /** - * サイズ更新。 - */ - private void updateBounds(){ - Rectangle bounds = this.draw.setWidth(Integer.MAX_VALUE); - Dimension dimension = new Dimension(bounds.width + MARGIN * 2, - bounds.height + MARGIN * 2 ); - setPreferredSize(dimension); - revalidate(); - repaint(); - return; - } + FontInfo newInfo = getFontInfo(); - /** - * フォント設定の変更。 - * @param newFontInfo フォント設定 - */ - public void setFontInfo(FontInfo newFontInfo){ - this.fontInfo = newFontInfo; - this.draw.setFontInfo(this.fontInfo); + int style = 0 | Font.PLAIN; + if(this.isBoldCheck.isSelected()){ + style = style | Font.BOLD; + } + if(this.isItalicCheck.isSelected()){ + style = style | Font.ITALIC; + } + Font newFont = newInfo.getFont(); + if(newFont.getStyle() != style){ + newFont = newFont.deriveFont(style); + newInfo = newInfo.deriveFont(newFont); + } - updateBounds(); + boolean isAntiAliases = this.useTextAntiAliaseCheck.isSelected(); + boolean useFractional = this.useFractionalCheck .isSelected(); + newInfo = newInfo.deriveRenderContext(isAntiAliases, useFractional); - return; - } + setFontInfo(newInfo); - /** - * {@inheritDoc} - * 文字列の描画。 - * @param g {@inheritDoc} - */ - @Override - public void paintComponent(Graphics g){ - super.paintComponent(g); - Graphics2D g2d = (Graphics2D) g; - this.draw.paint(g2d); - return; - } + return; } } diff --git a/src/main/java/jp/sourceforge/jindolf/FontInfo.java b/src/main/java/jp/sfjp/jindolf/glyph/FontInfo.java similarity index 56% rename from src/main/java/jp/sourceforge/jindolf/FontInfo.java rename to src/main/java/jp/sfjp/jindolf/glyph/FontInfo.java index 5ed23a5..5d2dfc6 100644 --- a/src/main/java/jp/sourceforge/jindolf/FontInfo.java +++ b/src/main/java/jp/sfjp/jindolf/glyph/FontInfo.java @@ -5,12 +5,14 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.glyph; import java.awt.Font; +import java.awt.Rectangle; import java.awt.font.FontRenderContext; import java.awt.font.GlyphVector; import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; import java.text.CharacterIterator; import jp.sourceforge.jovsonz.JsBoolean; import jp.sourceforge.jovsonz.JsNumber; @@ -27,16 +29,16 @@ public class FontInfo{ /** デフォルトのフォント設定。 */ public static final FontInfo DEFAULT_FONTINFO = new FontInfo(); - private static final String HASH_FAMILY = "family"; - private static final String HASH_SIZE = "size"; - private static final String HASH_ISBOLD = "isBold"; - private static final String HASH_ISITALIC = "isItalic"; - private static final String HASH_USEAA = "useAntiAlias"; + private static final String HASH_FAMILY = "family"; + private static final String HASH_SIZE = "size"; + private static final String HASH_ISBOLD = "isBold"; + private static final String HASH_ISITALIC = "isItalic"; + private static final String HASH_USEAA = "useAntiAlias"; private static final String HASH_FRACTIONAL = "useFractional"; - private Font font; - private FontRenderContext context; + private final Font font; + private final FontRenderContext context; /** @@ -78,19 +80,26 @@ public class FontInfo{ /** * フォントに応じた最適な描画設定を生成する。 + *

ビットマップフォントと推測されるときは + * アンチエイリアスやサブピクセル補完を無効にする。 * @param font フォント * @return 描画設定 + * @see FontUtils#guessBitmapFont(Font) */ public static FontRenderContext createBestContext(Font font){ - FontRenderContext result; - - AffineTransform identity = ImtblAffineTx.IDENTITY; + boolean isAntiAliased = true; + boolean usesFractionalMetrics = true; if(FontUtils.guessBitmapFont(font)){ - result = new FontRenderContext(identity, false, false); - }else{ - result = new FontRenderContext(identity, true, true); + isAntiAliased = false; + usesFractionalMetrics = false; } + AffineTransform identity = ImtblAffineTx.IDENTITY; + FontRenderContext result = + new FontRenderContext(identity, + isAntiAliased, + usesFractionalMetrics); + return result; } @@ -100,92 +109,124 @@ public class FontInfo{ * @return JSON Object */ public static JsObject buildJson(FontInfo fontInfo){ - Font font = fontInfo.getFont(); + Font font = fontInfo.getFont(); FontRenderContext frc = fontInfo.getFontRenderContext(); - JsPair type = new JsPair(HASH_FAMILY, - FontUtils.getRootFamilyName(font) ); - JsPair size = new JsPair(HASH_SIZE, font.getSize()); - JsPair bold = new JsPair(HASH_ISBOLD, font.isBold()); + + JsPair family = new JsPair(HASH_FAMILY, + FontUtils.getRootFamilyName(font) ); + JsPair size = new JsPair(HASH_SIZE, font.getSize()); + JsPair bold = new JsPair(HASH_ISBOLD, font.isBold()); JsPair italic = new JsPair(HASH_ISITALIC, font.isItalic()); - JsPair host = new JsPair(HASH_USEAA, frc.isAntiAliased()); - JsPair port = - new JsPair(HASH_FRACTIONAL, frc.usesFractionalMetrics()); + JsPair aa = new JsPair(HASH_USEAA, frc.isAntiAliased()); + JsPair frac = new JsPair(HASH_FRACTIONAL, + frc.usesFractionalMetrics() ); JsObject result = new JsObject(); - result.putPair(type); + result.putPair(family); result.putPair(size); result.putPair(bold); result.putPair(italic); - result.putPair(host); - result.putPair(port); + result.putPair(aa); + result.putPair(frac); return result; } /** - * JSONからのフォント設定復元。 + * JSONからフォントを復元。 * @param obj JSON Object - * @return フォント設定 + * @return フォント */ - public static FontInfo decodeJson(JsObject obj){ + private static Font decodeJsonFont(JsObject obj){ JsValue value; - Font newFont = FontUtils.createDefaultSpeechFont(); - FontRenderContext newFrc = createBestContext(newFont); - int style = newFont.getStyle(); - + Font font = null; value = obj.getValue(HASH_FAMILY); if(value instanceof JsString){ JsString string = (JsString) value; Font decoded = Font.decode(string.toRawString()); if(decoded != null){ - newFont = decoded; + font = decoded; } } - - int size = newFont.getSize(); - value = obj.getValue(HASH_SIZE); - if(value instanceof JsNumber){ - JsNumber number = (JsNumber) value; - size = number.intValue(); + if(font == null){ + font = FontUtils.createDefaultSpeechFont(); } - boolean isBold = newFont.isBold(); + boolean isBold = false; + boolean isItalic = false; + value = obj.getValue(HASH_ISBOLD); if(value instanceof JsBoolean){ JsBoolean bool = (JsBoolean) value; isBold = bool.booleanValue(); } - if(isBold) style |= Font.BOLD; - boolean isItalic = newFont.isItalic(); value = obj.getValue(HASH_ISITALIC); if(value instanceof JsBoolean){ JsBoolean bool = (JsBoolean) value; isItalic = bool.booleanValue(); } + + int style = Font.PLAIN; + if(isBold) style |= Font.BOLD; if(isItalic) style |= Font.ITALIC; - boolean isAntiAlias = newFrc.isAntiAliased(); + int size = FontUtils.DEF_SIZE; + value = obj.getValue(HASH_SIZE); + if(value instanceof JsNumber){ + JsNumber number = (JsNumber) value; + size = number.intValue(); + } + + Font derivedFont = font.deriveFont(style, (float)size); + + return derivedFont; + } + + /** + * JSONからフォント描画設定を復元。 + * @param obj JSON Object + * @param font デフォルトフォント + * @return フォント描画設定 + */ + private static FontRenderContext decodeJsonFrc(JsObject obj, + Font font ){ + FontRenderContext defFrc = createBestContext(font); + boolean isAntiAlias = defFrc.isAntiAliased(); + boolean useFractional = defFrc.usesFractionalMetrics(); + + JsValue value; + value = obj.getValue(HASH_USEAA); if(value instanceof JsBoolean){ JsBoolean bool = (JsBoolean) value; isAntiAlias = bool.booleanValue(); } - boolean useFractional = newFrc.usesFractionalMetrics(); value = obj.getValue(HASH_FRACTIONAL); if(value instanceof JsBoolean){ JsBoolean bool = (JsBoolean) value; useFractional = bool.booleanValue(); } - newFont = newFont.deriveFont(style, (float)size); + FontRenderContext newFrc = + new FontRenderContext(ImtblAffineTx.IDENTITY, + isAntiAlias, useFractional ); - newFrc = new FontRenderContext(ImtblAffineTx.IDENTITY, - isAntiAlias, useFractional); + return newFrc; + } - FontInfo result = new FontInfo(newFont, newFrc); + /** + * JSONからのフォント設定復元。 + * @param obj JSON Object + * @return フォント設定 + */ + public static FontInfo decodeJson(JsObject obj){ + Font font = decodeJsonFont(obj); + FontRenderContext frc = decodeJsonFrc(obj, font); + + FontInfo result = new FontInfo(font, frc); return result; } @@ -207,6 +248,35 @@ public class FontInfo{ } /** + * アンチエイリアス機能を使うか判定する。 + * @return アンチエイリアス機能を使うならtrue + */ + public boolean isAntiAliased(){ + boolean result = this.context.isAntiAliased(); + return result; + } + + /** + * サブピクセル精度を使うか判定する。 + * @return サブピクセル精度を使うならtrue + */ + public boolean usesFractionalMetrics(){ + boolean result = this.context.usesFractionalMetrics(); + return result; + } + + /** + * フォントの最大寸法を返す。 + * @return 最大寸法 + * @see java.awt.Font#getMaxCharBounds(FontRenderContext) + */ + public Rectangle getMaxCharBounds(){ + Rectangle2D r2d = this.font.getMaxCharBounds(this.context); + Rectangle rect = r2d.getBounds(); + return rect; + } + + /** * フォントのみ異なる設定を派生させる。 * @param newFont 新フォント * @return 新設定 @@ -225,6 +295,20 @@ public class FontInfo{ } /** + * 描画属性のみ異なる設定を派生させる。 + * @param isAntiAliases アンチエイリアス設定 + * @param useFractional サブピクセル精度設定 + * @return 新設定 + */ + public FontInfo deriveRenderContext(boolean isAntiAliases, + boolean useFractional){ + AffineTransform tx = this.context.getTransform(); + FontRenderContext newContext = + new FontRenderContext(tx, isAntiAliases, useFractional); + return deriveRenderContext(newContext); + } + + /** * 文字列からグリフ集合を生成する。 * @param iterator 文字列 * @return グリフ集合 diff --git a/src/main/java/jp/sfjp/jindolf/glyph/FontListModel.java b/src/main/java/jp/sfjp/jindolf/glyph/FontListModel.java new file mode 100644 index 0000000..f7c27f3 --- /dev/null +++ b/src/main/java/jp/sfjp/jindolf/glyph/FontListModel.java @@ -0,0 +1,138 @@ +/* + * font list model + * + * License : The MIT License + * Copyright(c) 2012 olyutorskii + */ + +package jp.sfjp.jindolf.glyph; + +import java.awt.EventQueue; +import java.util.LinkedList; +import java.util.List; +import javax.swing.AbstractListModel; + +/** + * フォントファミリ名一覧表示用リストのデータモデル。 + *

環境によってはフォントリストを完成させるのに + * 数千msかかる場合があるので、その対策として非同期に一覧を読み込む。 + *

実際のリスト作成は裏で走るタスクにより行われ、 + * リスト完成の暁にはEDTによりリスナに通知される。 + * 一般的なリストモデルと同様、 + * 基本的にスレッド間競合の問題はEDTで解決すること。 + */ +@SuppressWarnings("serial") +public class FontListModel extends AbstractListModel { + + private final List familyList = new LinkedList(); + + private volatile boolean hasDone = false; + + /** + * コンストラクタ。 + *

コンストラクタ完了と同時にリスト生成タスクが裏で走り始める。 + */ + public FontListModel(){ + super(); + + Runnable task = createFillTask(); + startTask(task); + + return; + } + + /** + * フォントリスト埋めタスクを生成する。 + * @return タスク + */ + private Runnable createFillTask(){ + Runnable task = new Runnable(){ + /** {@inheritDoc} */ + @Override + @SuppressWarnings("CallToThreadYield") + public void run(){ + Thread.yield(); + fillModel(); + } + }; + + return task; + } + + /** + * フォントファミリ名リストを設定する。 + * @param familyNames フォントファミリ名のリスト + * @return リストの要素数 + */ + private int fillList(List familyNames){ + this.familyList.addAll(familyNames); + this.hasDone = true; + int size = this.familyList.size(); + return size; + } + + /** + * フォントリストを収集しモデルに反映させる。 + */ + private void fillModel(){ + final List fontList = FontUtils.createFontList(); + + // スレッド間競合を避けるため、ここより先の処理はEDT任せ。 + EventQueue.invokeLater(new Runnable(){ + /** {@inheritDoc} */ + @Override + public void run(){ + int size = fillList(fontList); + if(size <= 0) return; + + int begin = 0; + int end = size - 1; + fireContentsChanged(this, begin, end); + + return; + } + }); + + return; + } + + /** + * フォントリスト埋めタスクを起動する。 + * @param task タスク + */ + private void startTask(Runnable task){ + Thread thread = new Thread(task); + thread.start(); + return; + } + + /** + * モデルが完成済みか否か判定する。 + * @return モデルが完成していればtrue + */ + public boolean hasCompleted(){ + return this.hasDone; + } + + /** + * {@inheritDoc} + * @param index {@inheritDoc} + * @return {@inheritDoc} + */ + @Override + public Object getElementAt(int index){ + Object result = this.familyList.get(index); + return result; + } + + /** + * {@inheritDoc} + * @return {@inheritDoc} + */ + @Override + public int getSize(){ + int result = this.familyList.size(); + return result; + } + +} diff --git a/src/main/java/jp/sfjp/jindolf/glyph/FontPreviewer.java b/src/main/java/jp/sfjp/jindolf/glyph/FontPreviewer.java new file mode 100644 index 0000000..ed3d8e6 --- /dev/null +++ b/src/main/java/jp/sfjp/jindolf/glyph/FontPreviewer.java @@ -0,0 +1,94 @@ +/* + * font previewer + * + * License : The MIT License + * Copyright(c) 2012 olyutorskii + */ + +package jp.sfjp.jindolf.glyph; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import javax.swing.JComponent; + +/** + * フォントプレビュー用コンポーネント。 + *

発言表示部と同じビジュアルを再現する必要のため、GlyphDrawで描画する。 + */ +@SuppressWarnings("serial") +public class FontPreviewer extends JComponent { + + private static final int MARGIN = 5; + + private final GlyphDraw draw; + private FontInfo fontInfo; + + + /** + * コンストラクタ。 + * @param source 文字列 + * @param fontInfo フォント設定 + */ + public FontPreviewer(CharSequence source, + FontInfo fontInfo ){ + super(); + + this.fontInfo = fontInfo; + this.draw = new GlyphDraw(source, this.fontInfo); + this.draw.setFontInfo(this.fontInfo); + + this.draw.setPos(MARGIN, MARGIN); + + this.draw.setColor(Color.BLACK); + setBackground(Color.WHITE); + + updateBounds(); + + return; + } + + /** + * サイズ更新。 + */ + private void updateBounds(){ + Rectangle bounds = this.draw.setWidth(Integer.MAX_VALUE); + Dimension dimension = new Dimension(bounds.width + MARGIN * 2, + bounds.height + MARGIN * 2 ); + + setPreferredSize(dimension); + revalidate(); + repaint(); + + return; + } + + /** + * フォント設定の変更。 + * @param newFontInfo フォント設定 + */ + public void setFontInfo(FontInfo newFontInfo){ + this.fontInfo = newFontInfo; + this.draw.setFontInfo(this.fontInfo); + + updateBounds(); + + return; + } + + /** + * {@inheritDoc} + * 文字列の描画。 + * @param g {@inheritDoc} + */ + @Override + public void paintComponent(Graphics g){ + super.paintComponent(g); + Graphics2D g2d = (Graphics2D) g; + this.draw.paint(g2d); + return; + } + +} diff --git a/src/main/java/jp/sfjp/jindolf/glyph/FontSelectList.java b/src/main/java/jp/sfjp/jindolf/glyph/FontSelectList.java new file mode 100644 index 0000000..d6e8f2a --- /dev/null +++ b/src/main/java/jp/sfjp/jindolf/glyph/FontSelectList.java @@ -0,0 +1,133 @@ +/* + * font select list + * + * License : The MIT License + * Copyright(c) 2012 olyutorskii + */ + +package jp.sfjp.jindolf.glyph; + +import javax.swing.JList; +import javax.swing.ListModel; +import javax.swing.ListSelectionModel; +import javax.swing.event.ListDataEvent; +import javax.swing.event.ListDataListener; + +/** + * フォント選択リスト。 + *

フォント一覧の遅延読み込みに対応。 + */ +@SuppressWarnings("serial") +public class FontSelectList extends JList + implements ListDataListener { + + private String selectedFamily = null; + + + /** + * コンストラクタ。 + */ + public FontSelectList(){ + super(); + + ListModel fontListModel = new FontListModel(); + setModelImpl(fontListModel); + setVisibleRowCount(-1); + setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + + return; + } + + /** + * {@link setModel(ListModel)} の下請けメソッド。 + * 与えられたモデルの更新は監視対象となる。 + * @param model リストモデル + */ + private void setModelImpl(ListModel model){ + ListModel oldModel = getModel(); + if(oldModel != null){ + oldModel.removeListDataListener(this); + } + + model.addListDataListener(this); + + super.setModel(model); + + return; + } + + /** + * {@inheritDoc} + * 与えられたモデルの更新は監視対象となる。 + * @param model {@inheritDoc} + */ + @Override + public void setModel(ListModel model){ + setModelImpl(model); + return; + } + + /** + * 指定したフォントファミリ名が選択された状態にする。 + * @param family フォントファミリ名 + */ + public void setSelectedFamily(String family){ + this.selectedFamily = family; + reSelectFamily(); + return; + } + + /** + * 選択されたファミリ名を返す。 + * @return 選択されたファミリ名。何も選択されていなければnull + */ + public String getSelectedFamily(){ + Object selected = getSelectedValue(); + if(selected == null) return null; + String result = selected.toString(); + return result; + } + + /** + * 過去に指示された選択ファミリを用いて再選択操作を試みる。 + */ + private void reSelectFamily(){ + boolean shouldScroll = true; + setSelectedValue(this.selectedFamily, shouldScroll); + return; + } + + /** + * {@inheritDoc} + * データモデル変更に伴い再選択処理を行う。 + * @param event {@inheritDoc} + */ + @Override + public void contentsChanged(ListDataEvent event){ + reSelectFamily(); + return; + } + + /** + * {@inheritDoc} + * データモデル変更に伴い再選択処理を行う。 + * @param event {@inheritDoc} + */ + @Override + public void intervalAdded(ListDataEvent event){ + reSelectFamily(); + return; + } + + /** + * {@inheritDoc} + * データモデル変更に伴い再選択処理を行う。 + * @param event {@inheritDoc} + */ + @Override + public void intervalRemoved(ListDataEvent event){ + reSelectFamily(); + return; + } + +} diff --git a/src/main/java/jp/sourceforge/jindolf/FontUtils.java b/src/main/java/jp/sfjp/jindolf/glyph/FontUtils.java similarity index 61% rename from src/main/java/jp/sourceforge/jindolf/FontUtils.java rename to src/main/java/jp/sfjp/jindolf/glyph/FontUtils.java index 5f9c8fc..8cca958 100644 --- a/src/main/java/jp/sourceforge/jindolf/FontUtils.java +++ b/src/main/java/jp/sfjp/jindolf/glyph/FontUtils.java @@ -5,14 +5,16 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.glyph; import java.awt.Font; import java.awt.GraphicsEnvironment; +import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; +import java.util.List; import java.util.Locale; -import java.util.SortedSet; -import java.util.TreeSet; +import java.util.Set; /** * フォントユーティリティ。 @@ -21,8 +23,13 @@ public final class FontUtils{ /** Font.DIALOG代替品。 */ public static final String FAMILY_DIALOG = "Dialog"; - /** Locale.ROOT代替品。 */ - private static final Locale ROOT = new Locale("", "", ""); + /** デフォルトのポイントサイズ。 */ + public static final int DEF_SIZE = 16; + + // Locale.ROOT代替品。@see Locale#ROOT + private static final Locale LOCALE_ROOT = new Locale("", "", ""); + + private static final int MS_BMP_LIMIT = 24; private static final String[] INIT_FAMILY_NAMES = { "Hiragino Kaku Gothic Pro", // for MacOS X @@ -30,11 +37,15 @@ public final class FontUtils{ "Osaka", "MS PGothic", // for WinXP "MS Gothic", + "IPAMonaPGothic", // TODO X11用のおすすめは? }; /** JIS0208:1990 チェック用。 */ - private static final String JPCHECK_CODE = "9Aあゑアアヴヰ┼ЖΩ峠凜熙"; + private static final String JPCHECK_CODE = "あ凜熙峠ゑアアヴヰ┼ЖΩ9A"; + + /** 二重引用符。 */ + private static final char DQ = '"'; /** @@ -47,18 +58,18 @@ public final class FontUtils{ /** * システムに存在する有効なファミリ名か判定する。 - * @param family フォントファミリ名。 + * @param familyName フォントファミリ名。 * @return 存在する有効なファミリ名ならtrue */ - public static boolean isValidFamilyName(String family){ + public static boolean isValidFamilyName(String familyName){ int style = 0x00 | Font.PLAIN; int size = 1; - Font dummyFont = new Font(family, style, size); + Font dummyFont = new Font(familyName, style, size); - String dummyFamily = getRootFamilyName(dummyFont); - String dummyLocalFamily = dummyFont.getFamily(); - if(dummyFamily .equals(family)) return true; - if(dummyLocalFamily.equals(family)) return true; + String dummyFamilyName = getRootFamilyName(dummyFont); + String dummyLocalFamilyName = dummyFont.getFamily(); + if(dummyFamilyName .equals(familyName)) return true; + if(dummyLocalFamilyName.equals(familyName)) return true; return false; } @@ -78,7 +89,7 @@ public final class FontUtils{ } int style = 0x00 | Font.PLAIN; - int size = 16; + int size = DEF_SIZE; Font result = new Font(defaultFamilyName, style, size); return result; @@ -86,22 +97,26 @@ public final class FontUtils{ /** * ソートされたフォントファミリ一覧表を生成する。 - * JISX0208:1990相当が表示できないファミリは弾かれる。 - * 結構実行時間がかかるかも。乱用禁物。 + *

JISX0208:1990相当が表示できないファミリは弾かれる。 + *

結構実行時間がかかるかも(数千ms)。乱用禁物。 * @return フォント一覧 */ - public static SortedSet createFontSet(){ + public static List createFontList(){ GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + Font[] allFonts = ge.getAllFonts(); - SortedSet result = new TreeSet(); - for(Font font : ge.getAllFonts()){ - if(font.canDisplayUpTo(JPCHECK_CODE) >= 0) continue; + Set checked = new HashSet(); + for(Font font : allFonts){ String familyName = font.getFamily(); - result.add(familyName.intern()); + if(checked.contains(familyName)) continue; + if(font.canDisplayUpTo(JPCHECK_CODE) >= 0) continue; + checked.add(familyName); } + List result = new ArrayList(checked); + Collections.sort(result); - return Collections.unmodifiableSortedSet(result); + return result; } /** @@ -113,7 +128,7 @@ public final class FontUtils{ */ public static boolean guessBitmapFont(Font font){ String familyName = getRootFamilyName(font); - if( font.getSize() < 24 + if( font.getSize() < MS_BMP_LIMIT && familyName.startsWith("MS") && ( familyName.contains("Gothic") || familyName.contains("Mincho") ) ){ @@ -124,24 +139,30 @@ public final class FontUtils{ /** * Font#decode()用の名前を返す。 + * 空白が含まれる場合は二重引用符で囲まれる。 * @param font フォント * @return Font#decode()用の名前 + * @see Font#decode(String) */ public static String getFontDecodeName(Font font){ StringBuilder result = new StringBuilder(); + String familyName = getRootFamilyName(font); + StringBuilder style = new StringBuilder(); - if(font.isBold()) style.append("BOLD"); - if(font.isItalic()) style.append("ITALIC"); + if(font.isBold()) style.append("BOLD"); + if(font.isItalic()) style.append("ITALIC"); if(style.length() <= 0) style.append("PLAIN"); - result.append(getRootFamilyName(font)); - result.append('-').append(style); - result.append('-').append(font.getSize()); + int fontSize = font.getSize(); + + result.append(familyName) + .append('-').append(style) + .append('-').append(fontSize); if( result.indexOf("\u0020") >= 0 || result.indexOf("\u3000") >= 0 ){ - result.insert(0, '"').append('"'); + result.insert(0, DQ).append(DQ); } return result.toString(); @@ -152,9 +173,10 @@ public final class FontUtils{ * JRE1.5対策 * @param font フォント * @return ファミリ名 + * @see Font#getFamily(Locale) */ public static String getRootFamilyName(Font font){ - return font.getFamily(ROOT); + return font.getFamily(LOCALE_ROOT); } } diff --git a/src/main/java/jp/sourceforge/jindolf/GlyphDraw.java b/src/main/java/jp/sfjp/jindolf/glyph/GlyphDraw.java similarity index 99% rename from src/main/java/jp/sourceforge/jindolf/GlyphDraw.java rename to src/main/java/jp/sfjp/jindolf/glyph/GlyphDraw.java index a0933a4..b2d98be 100644 --- a/src/main/java/jp/sourceforge/jindolf/GlyphDraw.java +++ b/src/main/java/jp/sfjp/jindolf/glyph/GlyphDraw.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.glyph; import java.awt.Color; import java.awt.FontMetrics; @@ -23,6 +23,8 @@ import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.swing.SwingConstants; +import jp.sfjp.jindolf.data.Anchor; +import jp.sfjp.jindolf.util.GUIUtils; /** * 複数行の文字列を矩形内に描画する。 diff --git a/src/main/java/jp/sourceforge/jindolf/ImtblAffineTx.java b/src/main/java/jp/sfjp/jindolf/glyph/ImtblAffineTx.java similarity index 99% rename from src/main/java/jp/sourceforge/jindolf/ImtblAffineTx.java rename to src/main/java/jp/sfjp/jindolf/glyph/ImtblAffineTx.java index cd4551f..1060074 100644 --- a/src/main/java/jp/sourceforge/jindolf/ImtblAffineTx.java +++ b/src/main/java/jp/sfjp/jindolf/glyph/ImtblAffineTx.java @@ -5,7 +5,7 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.glyph; import java.awt.geom.AffineTransform; diff --git a/src/main/java/jp/sourceforge/jindolf/Selectable.java b/src/main/java/jp/sfjp/jindolf/glyph/Selectable.java similarity index 96% rename from src/main/java/jp/sourceforge/jindolf/Selectable.java rename to src/main/java/jp/sfjp/jindolf/glyph/Selectable.java index 32e3bd9..340409f 100644 --- a/src/main/java/jp/sourceforge/jindolf/Selectable.java +++ b/src/main/java/jp/sfjp/jindolf/glyph/Selectable.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.glyph; import java.awt.Point; import java.io.IOException; diff --git a/src/main/java/jp/sourceforge/jindolf/SequenceCharacterIterator.java b/src/main/java/jp/sfjp/jindolf/glyph/SequenceCharacterIterator.java similarity index 99% rename from src/main/java/jp/sourceforge/jindolf/SequenceCharacterIterator.java rename to src/main/java/jp/sfjp/jindolf/glyph/SequenceCharacterIterator.java index eff102b..5e3cf4b 100644 --- a/src/main/java/jp/sourceforge/jindolf/SequenceCharacterIterator.java +++ b/src/main/java/jp/sfjp/jindolf/glyph/SequenceCharacterIterator.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.glyph; import java.text.CharacterIterator; diff --git a/src/main/java/jp/sourceforge/jindolf/SysEventDraw.java b/src/main/java/jp/sfjp/jindolf/glyph/SysEventDraw.java similarity index 98% rename from src/main/java/jp/sourceforge/jindolf/SysEventDraw.java rename to src/main/java/jp/sfjp/jindolf/glyph/SysEventDraw.java index daa0e80..de5c2f1 100644 --- a/src/main/java/jp/sourceforge/jindolf/SysEventDraw.java +++ b/src/main/java/jp/sfjp/jindolf/glyph/SysEventDraw.java @@ -5,13 +5,15 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.glyph; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Point; import java.awt.Rectangle; import java.io.IOException; +import jp.sfjp.jindolf.data.DialogPref; +import jp.sfjp.jindolf.data.SysEvent; import jp.sourceforge.jindolf.parser.DecodedContent; /** diff --git a/src/main/java/jp/sourceforge/jindolf/TalkDraw.java b/src/main/java/jp/sfjp/jindolf/glyph/TalkDraw.java similarity index 98% rename from src/main/java/jp/sourceforge/jindolf/TalkDraw.java rename to src/main/java/jp/sfjp/jindolf/glyph/TalkDraw.java index 1c66c90..c48d882 100644 --- a/src/main/java/jp/sourceforge/jindolf/TalkDraw.java +++ b/src/main/java/jp/sfjp/jindolf/glyph/TalkDraw.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.glyph; import java.awt.Color; import java.awt.Font; @@ -20,6 +20,13 @@ import java.text.DateFormat; import java.util.LinkedList; import java.util.List; import java.util.regex.Pattern; +import jp.sfjp.jindolf.data.Anchor; +import jp.sfjp.jindolf.data.Avatar; +import jp.sfjp.jindolf.data.DialogPref; +import jp.sfjp.jindolf.data.Period; +import jp.sfjp.jindolf.data.Talk; +import jp.sfjp.jindolf.data.Village; +import jp.sfjp.jindolf.util.GUIUtils; import jp.sourceforge.jindolf.corelib.TalkType; /** diff --git a/src/main/java/jp/sourceforge/jindolf/TextRow.java b/src/main/java/jp/sfjp/jindolf/glyph/TextRow.java similarity index 98% rename from src/main/java/jp/sourceforge/jindolf/TextRow.java rename to src/main/java/jp/sfjp/jindolf/glyph/TextRow.java index 281103c..ca78ea7 100644 --- a/src/main/java/jp/sourceforge/jindolf/TextRow.java +++ b/src/main/java/jp/sfjp/jindolf/glyph/TextRow.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.glyph; import java.awt.Graphics2D; import java.awt.Rectangle; diff --git a/src/main/java/jp/sfjp/jindolf/glyph/package-info.java b/src/main/java/jp/sfjp/jindolf/glyph/package-info.java new file mode 100644 index 0000000..cf68a13 --- /dev/null +++ b/src/main/java/jp/sfjp/jindolf/glyph/package-info.java @@ -0,0 +1,14 @@ +/* + * パッケージ情報 + * + * License : The MIT License + * Copyright(c) 2011 olyutorskii + */ + +/** + * 独自の文字列描画処理関連の一連のクラス。 + */ + +package jp.sfjp.jindolf.glyph; + +/* EOF */ diff --git a/src/main/java/jp/sourceforge/jindolf/LogFrame.java b/src/main/java/jp/sfjp/jindolf/log/LogFrame.java similarity index 73% rename from src/main/java/jp/sourceforge/jindolf/LogFrame.java rename to src/main/java/jp/sfjp/jindolf/log/LogFrame.java index 312e6f8..ce47599 100644 --- a/src/main/java/jp/sourceforge/jindolf/LogFrame.java +++ b/src/main/java/jp/sfjp/jindolf/log/LogFrame.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.log; import java.awt.Container; import java.awt.EventQueue; @@ -17,11 +17,7 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; -import java.util.logging.Formatter; import java.util.logging.Handler; -import java.util.logging.Level; -import java.util.logging.LogRecord; -import java.util.logging.SimpleFormatter; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JDialog; @@ -31,96 +27,24 @@ import javax.swing.JScrollPane; import javax.swing.JSeparator; import javax.swing.JTextArea; import javax.swing.border.Border; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; import javax.swing.text.BadLocationException; import javax.swing.text.Document; import javax.swing.text.PlainDocument; +import jp.sfjp.jindolf.dxchg.TextPopup; +import jp.sfjp.jindolf.util.GUIUtils; +import jp.sfjp.jindolf.util.Monodizer; /** * ログ表示パネル。 */ @SuppressWarnings("serial") public class LogFrame extends JDialog - implements WindowListener, ActionListener{ + implements WindowListener, ActionListener, DocumentListener{ - private static final String FRAMETITLE = "ログ表示 - " + Jindolf.TITLE; - private static final int DOCLIMIT = 100 * 1000; // 単位は文字 - private static final float CHOPRATIO = 0.9f; - private static final int CHOPPEDLEN = (int)(DOCLIMIT * CHOPRATIO); private static final Document DOC_EMPTY = new PlainDocument(); - static{ - assert DOCLIMIT > CHOPPEDLEN; - } - - /** - * ログハンドラ。 - */ - private class SwingLogger extends Handler{ - - /** - * ログハンドラの生成。 - */ - public SwingLogger(){ - super(); - Formatter formatter = new SimpleFormatter(); - setFormatter(formatter); - return; - } - - /** - * {@inheritDoc} - * @param record {@inheritDoc} - */ - @Override - public void publish(LogRecord record){ - if( ! isLoggable(record) ){ - return; - } - Formatter formatter = getFormatter(); - String message = formatter.format(record); - try{ - LogFrame.this.document - .insertString(LogFrame.this.document.getLength(), - message, - null ); - }catch(BadLocationException e){ - // IGNORE - } - - int docLength = LogFrame.this.document.getLength(); - if(docLength > DOCLIMIT){ - int offset = docLength - CHOPPEDLEN; - try{ - LogFrame.this.document.remove(0, offset); - }catch(BadLocationException e){ - // IGNORE - } - } - - showLastPos(); - - return; - } - - /** - * {@inheritDoc} - * (何もしない)。 - */ - @Override - public void flush(){ - return; - } - - /** - * {@inheritDoc} - */ - @Override - public void close(){ - setLevel(Level.OFF); - flush(); - return; - } - }; private final JTextArea textarea; private final Document document = new PlainDocument(); @@ -136,10 +60,11 @@ public class LogFrame extends JDialog * @param owner フレームオーナー */ public LogFrame(Frame owner){ - super(owner, FRAMETITLE, false); + super(owner); + setModal(false); - if(Jindolf.hasLoggingPermission()){ - this.handler = new SwingLogger(); + if(LogUtils.hasLoggingPermission()){ + this.handler = new SwingDocHandler(this.document); }else{ this.handler = null; } @@ -164,6 +89,8 @@ public class LogFrame extends JDialog this.clearButton.addActionListener(this); this.closeButton.addActionListener(this); + this.document.addDocumentListener(this); + setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); addWindowListener(this); @@ -354,4 +281,34 @@ public class LogFrame extends JDialog return; } + /** + * {@inheritDoc} + * @param event {@inheritDoc} + */ + @Override + public void changedUpdate(DocumentEvent event){ + showLastPos(); + return; + } + + /** + * {@inheritDoc} + * @param event {@inheritDoc} + */ + @Override + public void insertUpdate(DocumentEvent event){ + showLastPos(); + return; + } + + /** + * {@inheritDoc} + * @param event {@inheritDoc} + */ + @Override + public void removeUpdate(DocumentEvent event){ + showLastPos(); + return; + } + } diff --git a/src/main/java/jp/sfjp/jindolf/log/LogUtils.java b/src/main/java/jp/sfjp/jindolf/log/LogUtils.java new file mode 100644 index 0000000..2672d54 --- /dev/null +++ b/src/main/java/jp/sfjp/jindolf/log/LogUtils.java @@ -0,0 +1,117 @@ +/* + * logging common + * + * License : The MIT License + * Copyright(c) 2011 olyutorskii + */ + +package jp.sfjp.jindolf.log; + +import java.util.List; +import java.util.logging.ConsoleHandler; +import java.util.logging.Handler; +import java.util.logging.Logger; +import java.util.logging.LoggingPermission; + +/** + * ロギングの各種ユーティリティ。 + */ +public final class LogUtils { + + /** ログ管理用パーミッション。 */ + public static final LoggingPermission PERM_LOGCTL = + new LoggingPermission("control", null); + + /** + * 隠しコンストラクタ。 + */ + private LogUtils(){ + super(); + return; + } + + /** + * ログ操作のアクセス権があるか否か判定する。 + * @return アクセス権があればtrue + */ + public static boolean hasLoggingPermission(){ + SecurityManager manager = System.getSecurityManager(); + boolean result = hasLoggingPermission(manager); + return result; + } + + /** + * ログ操作のアクセス権があるか否か判定する。 + * @param manager セキュリティマネージャ + * @return アクセス権があればtrue + */ + public static boolean hasLoggingPermission(SecurityManager manager){ + if(manager == null) return true; + + try{ + manager.checkPermission(PERM_LOGCTL); + }catch(SecurityException e){ + return false; + } + + return true; + } + + /** + * ルートロガーの初期化を行う。 + * ルートロガーの既存ハンドラを全解除し、 + * {@link PileHandler}ハンドラを登録する。 + * @param useConsoleLog trueなら + * {@link java.util.logging.ConsoleHandler}も追加する。 + */ + public static void initRootLogger(boolean useConsoleLog){ + if( ! hasLoggingPermission() ){ + System.err.println( + "セキュリティ設定により、" + + "ログ設定を変更できませんでした" ); + return; + } + + Logger rootLogger = Logger.getLogger(""); + + for(Handler handler : rootLogger.getHandlers()){ + rootLogger.removeHandler(handler); + } + + Handler pileHandler = new PileHandler(); + rootLogger.addHandler(pileHandler); + + if(useConsoleLog){ + Handler consoleHandler = new ConsoleHandler(); + rootLogger.addHandler(consoleHandler); + } + + return; + } + + /** + * ロガーに新ハンドラを追加する。 + * ロガー中の全{@link PileHandler}型ハンドラに蓄積されていたログは、 + * 新ハンドラに一気に転送される。 + * {@link PileHandler}型ハンドラはロガーから削除される。 + * ログ操作のパーミッションがない場合、何もしない。 + * @param logger ロガー + * @param newHandler 新ハンドラ + */ + public static void switchHandler(Logger logger, Handler newHandler){ + if( ! hasLoggingPermission() ) return; + + List pileHandlers = PileHandler.getPileHandlers(logger); + PileHandler.removePileHandlers(logger); + + logger.addHandler(newHandler); + + for(PileHandler pileHandler : pileHandlers){ + pileHandler.delegate(newHandler); + pileHandler.close(); + } + + return; + } + +} diff --git a/src/main/java/jp/sourceforge/jindolf/LogWrapper.java b/src/main/java/jp/sfjp/jindolf/log/LogWrapper.java similarity index 94% rename from src/main/java/jp/sourceforge/jindolf/LogWrapper.java rename to src/main/java/jp/sfjp/jindolf/log/LogWrapper.java index 51753f0..27c1d05 100644 --- a/src/main/java/jp/sourceforge/jindolf/LogWrapper.java +++ b/src/main/java/jp/sfjp/jindolf/log/LogWrapper.java @@ -5,7 +5,7 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.log; import java.util.logging.Level; import java.util.logging.LogRecord; @@ -31,6 +31,15 @@ public class LogWrapper{ } /** + * コンストラクタ。 + * 新規生成された匿名ロガーを囲う。 + */ + public LogWrapper(){ + this(Logger.getAnonymousLogger()); + return; + } + + /** * ラップ対象のjava.util.loggingロガーを取得する。 * @return ラップ対象のjava.util.loggingロガー */ diff --git a/src/main/java/jp/sfjp/jindolf/log/LoggingDispatcher.java b/src/main/java/jp/sfjp/jindolf/log/LoggingDispatcher.java new file mode 100644 index 0000000..af32849 --- /dev/null +++ b/src/main/java/jp/sfjp/jindolf/log/LoggingDispatcher.java @@ -0,0 +1,78 @@ +/* + * event dispatcher with logging + * + * License : The MIT License + * Copyright(c) 2011 olyutorskii + */ + +package jp.sfjp.jindolf.log; + +import java.awt.AWTEvent; +import java.awt.EventQueue; +import java.awt.Toolkit; + +/** + * 異常系をロギングするイベントディスパッチャ。 + */ +public class LoggingDispatcher extends EventQueue{ + + private static final String FATALMSG = + "イベントディスパッチ中に異常が起きました。"; + + private static final LogWrapper LOGGER = new LogWrapper(); + + /** + * コンストラクタ。 + */ + public LoggingDispatcher(){ + super(); + return; + } + + /** + * 独自ロガーにエラーや例外を吐く、 + * カスタム化されたイベントキューに差し替える。 + */ + public static void replaceEventQueue(){ + Toolkit kit = Toolkit.getDefaultToolkit(); + EventQueue oldQueue = kit.getSystemEventQueue(); + EventQueue newQueue = new LoggingDispatcher(); + oldQueue.push(newQueue); + return; + } + + /** + * 異常系をログ出力。 + * @param e 例外 + */ + private void errlog(Throwable e){ + LOGGER.fatal(FATALMSG, e); + return; + } + + /** + * {@inheritDoc} + * 発生した例外をログ出力する。 + * @param event {@inheritDoc} + */ + @Override + protected void dispatchEvent(AWTEvent event){ + try{ + super.dispatchEvent(event); + }catch(RuntimeException e){ + errlog(e); + throw e; + }catch(Exception e){ + errlog(e); + }catch(Error e){ + errlog(e); + throw e; + } + // TODO Toolkit#beep()もするべきか + // TODO モーダルダイアログを出すべきか + // TODO 標準エラー出力抑止オプションを用意すべきか + // TODO セキュリティバイパス + return; + } + +} diff --git a/src/main/java/jp/sourceforge/jindolf/PileHandler.java b/src/main/java/jp/sfjp/jindolf/log/PileHandler.java similarity index 51% rename from src/main/java/jp/sourceforge/jindolf/PileHandler.java rename to src/main/java/jp/sfjp/jindolf/log/PileHandler.java index 9524b98..9909a53 100644 --- a/src/main/java/jp/sourceforge/jindolf/PileHandler.java +++ b/src/main/java/jp/sfjp/jindolf/log/PileHandler.java @@ -5,13 +5,15 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.log; +import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.LogRecord; +import java.util.logging.Logger; /** * なにもしないロギングハンドラ。 @@ -20,6 +22,8 @@ import java.util.logging.LogRecord; public class PileHandler extends Handler{ private final List logList = new LinkedList(); + private final List unmodList = + Collections.unmodifiableList(this.logList); /** * ロギングハンドラを生成する。 @@ -30,16 +34,57 @@ public class PileHandler extends Handler{ } /** + * ロガーに含まれる{@link PileHandler}型ハンドラのリストを返す。 + * @param logger ロガー + * @return {@link PileHandler}型ハンドラのリスト + */ + public static List getPileHandlers(Logger logger){ + List result = new LinkedList(); + + for(Handler handler : logger.getHandlers()){ + if( ! (handler instanceof PileHandler) ) continue; + PileHandler pileHandler = (PileHandler) handler; + result.add(pileHandler); + } + + return result; + } + + /** + * ロガーに含まれる{@link PileHandler}型ハンドラを全て削除する。 + * @param logger ロガー + */ + public static void removePileHandlers(Logger logger){ + for(PileHandler pileHandler : getPileHandlers(logger)){ + logger.removeHandler(pileHandler); + } + return; + } + + /** + * 蓄積されたログレコードのリストを返す。 + * 古いログが先頭に来る。 + * @return ログレコードのリスト。変更不可。 + */ + public List getRecordList(){ + return this.unmodList; + } + + /** * {@inheritDoc} * ログを内部に溜め込む。 * @param record {@inheritDoc} */ @Override public void publish(LogRecord record){ + if(record == null) return; + if( ! isLoggable(record) ){ return; } + this.logList.add(record); + return; } @@ -64,6 +109,7 @@ public class PileHandler extends Handler{ /** * 他のハンドラへ蓄積したログをまとめて出力する。 + * 最後に自分自身をクローズし、蓄積されたログを解放する。 * @param handler 他のハンドラ */ public void delegate(Handler handler){ diff --git a/src/main/java/jp/sfjp/jindolf/log/SwingDocHandler.java b/src/main/java/jp/sfjp/jindolf/log/SwingDocHandler.java new file mode 100644 index 0000000..5933331 --- /dev/null +++ b/src/main/java/jp/sfjp/jindolf/log/SwingDocHandler.java @@ -0,0 +1,101 @@ +/* + * Logging handler for Swing text component + * + * License : The MIT License + * Copyright(c) 2011 olyutorskii + */ + +package jp.sfjp.jindolf.log; + +import java.util.logging.Formatter; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogRecord; +import java.util.logging.SimpleFormatter; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; + +/** + * Swingテキストコンポーネント用データモデル{@link javax.swing.text.Document} + * に出力する{@link java.util.logging.Handler}。 + */ +public class SwingDocHandler extends Handler{ + + private static final int DOCLIMIT = 100 * 1000; // 単位は文字 + private static final float CHOPRATIO = 0.9f; + private static final int CHOPPEDLEN = (int)(DOCLIMIT * CHOPRATIO); + + static{ + assert DOCLIMIT > CHOPPEDLEN; + } + + + private final Document document; + + /** + * ログハンドラの生成。 + * @param document ドキュメントモデル + */ + public SwingDocHandler(Document document){ + super(); + + this.document = document; + + Formatter formatter = new SimpleFormatter(); + setFormatter(formatter); + + return; + } + + /** + * {@inheritDoc} + * @param record {@inheritDoc} + */ + @Override + public void publish(LogRecord record){ + if( ! isLoggable(record) ){ + return; + } + Formatter formatter = getFormatter(); + String message = formatter.format(record); + try{ + this.document.insertString(this.document.getLength(), + message, + null ); + }catch(BadLocationException e){ + assert false; + } + + int docLength = this.document.getLength(); + if(docLength > DOCLIMIT){ + int offset = docLength - CHOPPEDLEN; + try{ + this.document.remove(0, offset); + }catch(BadLocationException e){ + assert false; + } + } + + return; + } + + /** + * {@inheritDoc} + * (何もしない)。 + */ + @Override + public void flush(){ + return; + } + + /** + * {@inheritDoc} + */ + @Override + public void close(){ + setLevel(Level.OFF); + flush(); + return; + } + +} diff --git a/src/main/java/jp/sfjp/jindolf/log/package-info.java b/src/main/java/jp/sfjp/jindolf/log/package-info.java new file mode 100644 index 0000000..aa5c136 --- /dev/null +++ b/src/main/java/jp/sfjp/jindolf/log/package-info.java @@ -0,0 +1,14 @@ +/* + * パッケージ情報 + * + * License : The MIT License + * Copyright(c) 2011 olyutorskii + */ + +/** + * ロギング関連の一連のクラス。 + */ + +package jp.sfjp.jindolf.log; + +/* EOF */ diff --git a/src/main/java/jp/sourceforge/jindolf/AccountCookie.java b/src/main/java/jp/sfjp/jindolf/net/AccountCookie.java similarity index 99% rename from src/main/java/jp/sourceforge/jindolf/AccountCookie.java rename to src/main/java/jp/sfjp/jindolf/net/AccountCookie.java index 51573de..c53817e 100644 --- a/src/main/java/jp/sourceforge/jindolf/AccountCookie.java +++ b/src/main/java/jp/sfjp/jindolf/net/AccountCookie.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.net; import java.net.HttpURLConnection; import java.net.URI; diff --git a/src/main/java/jp/sourceforge/jindolf/HtmlSequence.java b/src/main/java/jp/sfjp/jindolf/net/HtmlSequence.java similarity index 98% rename from src/main/java/jp/sourceforge/jindolf/HtmlSequence.java rename to src/main/java/jp/sfjp/jindolf/net/HtmlSequence.java index 791586d..fcec02a 100644 --- a/src/main/java/jp/sourceforge/jindolf/HtmlSequence.java +++ b/src/main/java/jp/sfjp/jindolf/net/HtmlSequence.java @@ -5,7 +5,7 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.net; import java.net.URL; import jp.sourceforge.jindolf.parser.DecodedContent; diff --git a/src/main/java/jp/sourceforge/jindolf/HttpUtils.java b/src/main/java/jp/sfjp/jindolf/net/HttpUtils.java similarity index 97% rename from src/main/java/jp/sourceforge/jindolf/HttpUtils.java rename to src/main/java/jp/sfjp/jindolf/net/HttpUtils.java index d1ff8ef..993efbc 100644 --- a/src/main/java/jp/sourceforge/jindolf/HttpUtils.java +++ b/src/main/java/jp/sfjp/jindolf/net/HttpUtils.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.net; import java.io.IOException; import java.net.HttpURLConnection; @@ -13,6 +13,8 @@ import java.net.URLConnection; import java.text.NumberFormat; import java.util.regex.Matcher; import java.util.regex.Pattern; +import jp.sfjp.jindolf.VerInfo; +import jp.sfjp.jindolf.config.EnvInfo; /** * HTTP関連のユーティリティ群。 @@ -128,7 +130,7 @@ public final class HttpUtils{ */ public static String getUserAgentName(){ StringBuilder result = new StringBuilder(); - result.append(Jindolf.TITLE).append("/").append(Jindolf.VERSION); + result.append(VerInfo.TITLE).append("/").append(VerInfo.VERSION); StringBuilder rawComment = new StringBuilder(); if(EnvInfo.OS_NAME != null){ diff --git a/src/main/java/jp/sourceforge/jindolf/ProxyChooser.java b/src/main/java/jp/sfjp/jindolf/net/ProxyChooser.java similarity index 98% rename from src/main/java/jp/sourceforge/jindolf/ProxyChooser.java rename to src/main/java/jp/sfjp/jindolf/net/ProxyChooser.java index 18e1cc3..491c96c 100644 --- a/src/main/java/jp/sourceforge/jindolf/ProxyChooser.java +++ b/src/main/java/jp/sfjp/jindolf/net/ProxyChooser.java @@ -5,7 +5,7 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.net; import java.awt.Component; import java.awt.Container; @@ -29,6 +29,9 @@ import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JTextField; import javax.swing.border.Border; +import jp.sfjp.jindolf.dxchg.TextPopup; +import jp.sfjp.jindolf.util.GUIUtils; +import jp.sfjp.jindolf.util.Monodizer; /** * プロクシサーバ選択画面。 diff --git a/src/main/java/jp/sourceforge/jindolf/ProxyInfo.java b/src/main/java/jp/sfjp/jindolf/net/ProxyInfo.java similarity index 99% rename from src/main/java/jp/sourceforge/jindolf/ProxyInfo.java rename to src/main/java/jp/sfjp/jindolf/net/ProxyInfo.java index 26bd245..a30a672 100644 --- a/src/main/java/jp/sourceforge/jindolf/ProxyInfo.java +++ b/src/main/java/jp/sfjp/jindolf/net/ProxyInfo.java @@ -5,7 +5,7 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.net; import java.net.InetSocketAddress; import java.net.Proxy; diff --git a/src/main/java/jp/sourceforge/jindolf/ServerAccess.java b/src/main/java/jp/sfjp/jindolf/net/ServerAccess.java similarity index 98% rename from src/main/java/jp/sourceforge/jindolf/ServerAccess.java rename to src/main/java/jp/sfjp/jindolf/net/ServerAccess.java index 2b6c4cc..cf39785 100644 --- a/src/main/java/jp/sourceforge/jindolf/ServerAccess.java +++ b/src/main/java/jp/sfjp/jindolf/net/ServerAccess.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.net; import java.awt.image.BufferedImage; import java.io.IOException; @@ -23,6 +23,9 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; import javax.imageio.ImageIO; +import jp.sfjp.jindolf.data.Period; +import jp.sfjp.jindolf.data.Village; +import jp.sfjp.jindolf.log.LogWrapper; import jp.sourceforge.jindolf.parser.ContentBuilder; import jp.sourceforge.jindolf.parser.ContentBuilderSJ; import jp.sourceforge.jindolf.parser.ContentBuilderUCS2; @@ -41,6 +44,8 @@ public class ServerAccess{ private static final Map> IMAGE_CACHE; + private static final LogWrapper LOGGER = new LogWrapper(); + static{ Map> cache = new HashMap>(); @@ -276,7 +281,7 @@ public class ServerAccess{ if(responseCode != HttpURLConnection.HTTP_OK){ // 200 String logMessage = "発言のダウンロードに失敗しました。"; logMessage += HttpUtils.formatHttpStat(connection, 0, 0); - Jindolf.logger().warn(logMessage); + LOGGER.warn(logMessage); return null; } @@ -331,7 +336,7 @@ public class ServerAccess{ if(responseCode != HttpURLConnection.HTTP_OK){ String logMessage = "イメージのダウンロードに失敗しました。"; logMessage += HttpUtils.formatHttpStat(connection, 0, 0); - Jindolf.logger().warn(logMessage); + LOGGER.warn(logMessage); return null; } @@ -376,7 +381,7 @@ public class ServerAccess{ int responseCode = connection.getResponseCode(); if(responseCode != HttpURLConnection.HTTP_MOVED_TEMP){ // 302 String logMessage = "認証情報の送信に失敗しました。"; - Jindolf.logger().warn(logMessage); + LOGGER.warn(logMessage); connection.disconnect(); return false; } @@ -390,7 +395,7 @@ public class ServerAccess{ setAuthentication(loginCookie); - Jindolf.logger().info("正しく認証が行われました。"); + LOGGER.info("正しく認証が行われました。"); return true; } diff --git a/src/main/java/jp/sourceforge/jindolf/TallyInputStream.java b/src/main/java/jp/sfjp/jindolf/net/TallyInputStream.java similarity index 96% rename from src/main/java/jp/sourceforge/jindolf/TallyInputStream.java rename to src/main/java/jp/sfjp/jindolf/net/TallyInputStream.java index 4ebeae1..0ab55aa 100644 --- a/src/main/java/jp/sourceforge/jindolf/TallyInputStream.java +++ b/src/main/java/jp/sfjp/jindolf/net/TallyInputStream.java @@ -5,12 +5,13 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.net; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; +import jp.sfjp.jindolf.log.LogWrapper; /** * 読み込みバイト数を記録するHTTPコネクション由来のInputStream。 @@ -20,6 +21,8 @@ public class TallyInputStream extends InputStream{ private static final int BUFSIZE = 2 * 1024; + private static final LogWrapper LOGGER = new LogWrapper(); + private final HttpURLConnection conn; private final InputStream in; @@ -97,7 +100,7 @@ public class TallyInputStream extends InputStream{ long span = System.nanoTime() - this.nanoLap; String message = HttpUtils.formatHttpStat(this.conn, size, span); - Jindolf.logger().info(message); + LOGGER.info(message); this.hasClosed = true; diff --git a/src/main/java/jp/sourceforge/jindolf/TallyOutputStream.java b/src/main/java/jp/sfjp/jindolf/net/TallyOutputStream.java similarity index 95% rename from src/main/java/jp/sourceforge/jindolf/TallyOutputStream.java rename to src/main/java/jp/sfjp/jindolf/net/TallyOutputStream.java index d17ce6a..1bb7627 100644 --- a/src/main/java/jp/sourceforge/jindolf/TallyOutputStream.java +++ b/src/main/java/jp/sfjp/jindolf/net/TallyOutputStream.java @@ -5,12 +5,13 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.net; import java.io.BufferedOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.HttpURLConnection; +import jp.sfjp.jindolf.log.LogWrapper; /** * 書き込みバイト数をログ出力するHTTPコネクション由来のOutputStream。 @@ -19,6 +20,8 @@ public class TallyOutputStream extends OutputStream{ private static final int BUFSIZE = 512; + private static final LogWrapper LOGGER = new LogWrapper(); + private final HttpURLConnection conn; private final OutputStream out; @@ -80,7 +83,7 @@ public class TallyOutputStream extends OutputStream{ long span = System.nanoTime() - this.nanoLap; String message = HttpUtils.formatHttpStat(this.conn, size, span); - Jindolf.logger().info(message); + LOGGER.info(message); return; } diff --git a/src/main/java/jp/sfjp/jindolf/net/package-info.java b/src/main/java/jp/sfjp/jindolf/net/package-info.java new file mode 100644 index 0000000..1540acf --- /dev/null +++ b/src/main/java/jp/sfjp/jindolf/net/package-info.java @@ -0,0 +1,14 @@ +/* + * パッケージ情報 + * + * License : The MIT License + * Copyright(c) 2011 olyutorskii + */ + +/** + * ネットワーク通信関連の一連のクラス。 + */ + +package jp.sfjp.jindolf.net; + +/* EOF */ diff --git a/src/main/java/jp/sourceforge/jindolf/package-info.java b/src/main/java/jp/sfjp/jindolf/package-info.java similarity index 82% rename from src/main/java/jp/sourceforge/jindolf/package-info.java rename to src/main/java/jp/sfjp/jindolf/package-info.java index eb2bd98..ce3b87e 100644 --- a/src/main/java/jp/sourceforge/jindolf/package-info.java +++ b/src/main/java/jp/sfjp/jindolf/package-info.java @@ -1,13 +1,8 @@ /* - * Jindolf パッケージコメント - * - * このファイルは、SunJDK5.0以降に含まれるJavadoc用に用意された、 - * 特別な名前を持つソースファイルです。 - * このファイルはソースコードを含まず、 - * パッケージコメントとパッケージ宣言のみが含まれます。 + * パッケージ情報 * * License : The MIT License - * Copyright(c) 2008 olyutorskii + * Copyright(c) 2011 olyutorskii */ /** @@ -57,6 +52,6 @@ * Jindolf開発プロジェクト */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf; /* EOF */ diff --git a/src/main/java/jp/sourceforge/jindolf/DaySummary.java b/src/main/java/jp/sfjp/jindolf/summary/DaySummary.java similarity index 97% rename from src/main/java/jp/sourceforge/jindolf/DaySummary.java rename to src/main/java/jp/sfjp/jindolf/summary/DaySummary.java index 00963c4..ea5b052 100644 --- a/src/main/java/jp/sourceforge/jindolf/DaySummary.java +++ b/src/main/java/jp/sfjp/jindolf/summary/DaySummary.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.summary; import java.awt.Color; import java.awt.Component; @@ -43,6 +43,13 @@ import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; +import jp.sfjp.jindolf.data.Avatar; +import jp.sfjp.jindolf.data.Period; +import jp.sfjp.jindolf.data.Talk; +import jp.sfjp.jindolf.data.Topic; +import jp.sfjp.jindolf.data.Village; +import jp.sfjp.jindolf.glyph.TalkDraw; +import jp.sfjp.jindolf.util.GUIUtils; import jp.sourceforge.jindolf.corelib.TalkType; /** @@ -52,8 +59,6 @@ import jp.sourceforge.jindolf.corelib.TalkType; public class DaySummary extends JDialog implements WindowListener, ActionListener, ItemListener{ - private static final String FRAMETITLE = - "発言集計 - " + Jindolf.TITLE; private static final NumberFormat AVERAGE_FORM; private static final String PUBTALK = "白発言"; private static final String WOLFTALK = "赤発言"; @@ -90,7 +95,8 @@ public class DaySummary extends JDialog * @param owner オーナー */ public DaySummary(Frame owner){ - super(owner, FRAMETITLE, true); + super(owner); + setModal(true); GUIUtils.modifyWindowAttributes(this, true, false, true); diff --git a/src/main/java/jp/sourceforge/jindolf/GameSummary.java b/src/main/java/jp/sfjp/jindolf/summary/GameSummary.java similarity index 95% rename from src/main/java/jp/sourceforge/jindolf/GameSummary.java rename to src/main/java/jp/sfjp/jindolf/summary/GameSummary.java index fb00cda..6770915 100644 --- a/src/main/java/jp/sourceforge/jindolf/GameSummary.java +++ b/src/main/java/jp/sfjp/jindolf/summary/GameSummary.java @@ -5,7 +5,7 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.summary; import java.net.MalformedURLException; import java.net.URI; @@ -21,6 +21,16 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; +import jp.sfjp.jindolf.VerInfo; +import jp.sfjp.jindolf.data.Avatar; +import jp.sfjp.jindolf.data.Period; +import jp.sfjp.jindolf.data.Player; +import jp.sfjp.jindolf.data.SysEvent; +import jp.sfjp.jindolf.data.Talk; +import jp.sfjp.jindolf.data.Topic; +import jp.sfjp.jindolf.data.Village; +import jp.sfjp.jindolf.dxchg.FaceIconSet; +import jp.sfjp.jindolf.dxchg.WolfBBS; import jp.sourceforge.jindolf.corelib.Destiny; import jp.sourceforge.jindolf.corelib.GameRole; import jp.sourceforge.jindolf.corelib.SysEventType; @@ -36,6 +46,9 @@ public class GameSummary{ public static final Comparator COMPARATOR_CASTING = new CastingComparator(); + private static final String GENERATOR = + VerInfo.TITLE + "\u0020Ver." + VerInfo.VERSION; + private final Map playerMap = new HashMap(); @@ -652,19 +665,24 @@ public class GameSummary{ StringBuilder wikiText = new StringBuilder(); String vName = this.village.getVillageFullName(); - String generator = Jindolf.TITLE + " Ver." + Jindolf.VERSION; String author = iconSet.getAuthor() + "氏" +" [ "+iconSet.getUrlText()+" ]"; wikiText.append(WolfBBS.COMMENTLINE); wikiText.append("// ↓キャスト表開始\n"); - wikiText.append("// Village : " + vName + "\n"); - wikiText.append("// Generator : " + generator + "\n"); - wikiText.append("// アイコン作者 : " + author + '\n'); - wikiText.append("// ※アイコン画像の著作財産権保持者" - +"および画像サーバ運営者から\n"); - wikiText.append("// 新しい意向が示された場合、" - +"そちらを最優先で尊重してください。\n"); + wikiText.append("// Village : ") + .append(vName) + .append('\n'); + wikiText.append("// Generator : ") + .append(GENERATOR) + .append('\n'); + wikiText.append("// アイコン作者 : ") + .append(author) + .append('\n'); + wikiText.append("// ※アイコン画像の著作財産権保持者") + .append("および画像サーバ運営者から\n"); + wikiText.append("// 新しい意向が示された場合、") + .append("そちらを最優先で尊重してください。\n"); wikiText.append(WolfBBS.COMMENTLINE); wikiText.append("|配役") @@ -698,7 +716,10 @@ public class GameSummary{ // PukiWikiではURL内の&のエスケープは不要? wikiText.append("// ========== "); - wikiText.append(name + " acts as [" + avatar.getName() + "]"); + wikiText.append(name) + .append(" acts as [") + .append(avatar.getName()) + .append("]"); wikiText.append(" ==========\n"); String teamColor = "BGCOLOR(" @@ -757,7 +778,8 @@ public class GameSummary{ wikiText.append("RIGHT:"); wikiText.append("顔アイコン提供 : [["); wikiText.append(WolfBBS.escapeWikiBracket(iconSet.getAuthor())); - wikiText.append(">" + iconSet.getUrlText()); + wikiText.append(">") + .append(iconSet.getUrlText()); wikiText.append("]]氏"); wikiText.append("|\n"); @@ -780,12 +802,15 @@ public class GameSummary{ DateFormat.FULL); String vName = this.village.getVillageFullName(); - String generator = Jindolf.TITLE + " Ver." + Jindolf.VERSION; wikiText.append(WolfBBS.COMMENTLINE); wikiText.append("// ↓村詳細開始\n"); - wikiText.append("// Village : " + vName + "\n"); - wikiText.append("// Generator : " + generator + "\n"); + wikiText.append("// Village : ") + .append(vName) + .append('\n'); + wikiText.append("// Generator : ") + .append(GENERATOR) + .append('\n'); wikiText.append("* 村の詳細\n"); diff --git a/src/main/java/jp/sourceforge/jindolf/VillageDigest.java b/src/main/java/jp/sfjp/jindolf/summary/VillageDigest.java similarity index 98% rename from src/main/java/jp/sourceforge/jindolf/VillageDigest.java rename to src/main/java/jp/sfjp/jindolf/summary/VillageDigest.java index 1c6c17e..08e133f 100644 --- a/src/main/java/jp/sourceforge/jindolf/VillageDigest.java +++ b/src/main/java/jp/sfjp/jindolf/summary/VillageDigest.java @@ -5,7 +5,7 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.summary; import java.awt.Container; import java.awt.Dimension; @@ -41,6 +41,17 @@ import javax.swing.JTabbedPane; import javax.swing.JTextArea; import javax.swing.JViewport; import javax.swing.border.Border; +import jp.sfjp.jindolf.data.Avatar; +import jp.sfjp.jindolf.data.Period; +import jp.sfjp.jindolf.data.Player; +import jp.sfjp.jindolf.data.Village; +import jp.sfjp.jindolf.dxchg.ClipboardAction; +import jp.sfjp.jindolf.dxchg.FaceIconSet; +import jp.sfjp.jindolf.dxchg.TextPopup; +import jp.sfjp.jindolf.dxchg.WebButton; +import jp.sfjp.jindolf.dxchg.WolfBBS; +import jp.sfjp.jindolf.util.GUIUtils; +import jp.sfjp.jindolf.util.Monodizer; import jp.sourceforge.jindolf.corelib.GameRole; import jp.sourceforge.jindolf.corelib.Team; @@ -53,8 +64,6 @@ public class VillageDigest implements ActionListener, ItemListener { - private static final String FRAMETITLE = - "村のダイジェスト - " + Jindolf.TITLE; private static final String ITEMDELIM = " : "; @@ -102,7 +111,8 @@ public class VillageDigest * @param owner 親フレーム */ public VillageDigest(Frame owner){ - super(owner, FRAMETITLE, true); + super(owner); + setModal(true); GUIUtils.modifyWindowAttributes(this, true, false, true); diff --git a/src/main/java/jp/sfjp/jindolf/summary/package-info.java b/src/main/java/jp/sfjp/jindolf/summary/package-info.java new file mode 100644 index 0000000..4d45239 --- /dev/null +++ b/src/main/java/jp/sfjp/jindolf/summary/package-info.java @@ -0,0 +1,14 @@ +/* + * パッケージ情報 + * + * License : The MIT License + * Copyright(c) 2011 olyutorskii + */ + +/** + * プレイ状況のサマライズ処理関連の一連のクラス。 + */ + +package jp.sfjp.jindolf.summary; + +/* EOF */ diff --git a/src/main/java/jp/sourceforge/jindolf/GUIUtils.java b/src/main/java/jp/sfjp/jindolf/util/GUIUtils.java similarity index 78% rename from src/main/java/jp/sourceforge/jindolf/GUIUtils.java rename to src/main/java/jp/sfjp/jindolf/util/GUIUtils.java index 398b725..74492ec 100644 --- a/src/main/java/jp/sourceforge/jindolf/GUIUtils.java +++ b/src/main/java/jp/sfjp/jindolf/util/GUIUtils.java @@ -5,12 +5,10 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.util; -import java.awt.AWTEvent; import java.awt.Component; import java.awt.Dialog; -import java.awt.EventQueue; import java.awt.Frame; import java.awt.Point; import java.awt.Rectangle; @@ -21,17 +19,15 @@ import java.awt.color.ColorSpace; import java.awt.image.BufferedImage; import java.awt.image.BufferedImageOp; import java.awt.image.ColorConvertOp; -import java.io.IOException; import java.lang.reflect.InvocationTargetException; -import java.net.URL; -import javax.imageio.ImageIO; import javax.swing.BorderFactory; import javax.swing.Icon; -import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import javax.swing.border.Border; +import jp.sfjp.jindolf.ResourceManager; +import jp.sfjp.jindolf.log.LogWrapper; /** * GUI関連のユーティリティクラス。 @@ -62,6 +58,8 @@ public final class GUIUtils{ public void run(){} }; + private static final LogWrapper LOGGER = new LogWrapper(); + static{ HINTS_QUALITY = new RenderingHints(null); HINTS_SPEEDY = new RenderingHints(null); @@ -136,22 +134,6 @@ public final class GUIUtils{ } /** - * リソース名からイメージを取得する。 - * @param resource リソース名 - * @return イメージ - * @throws java.io.IOException 入力エラー - */ - public static BufferedImage loadImageFromResource(String resource) - throws IOException{ - BufferedImage result; - - URL url = Jindolf.getResource(resource); - result = ImageIO.read(url); - - return result; - } - - /** * ロゴイメージを得る。 * @return ロゴイメージ */ @@ -160,11 +142,10 @@ public final class GUIUtils{ return logoImage; } - BufferedImage image; - try{ - image = loadImageFromResource(RES_LOGOICON); - }catch(IOException e){ - Jindolf.logger().warn("ロゴイメージの取得に失敗しました", e); + BufferedImage image = + ResourceManager.getBufferedImage(RES_LOGOICON); + if(image == null){ + LOGGER.warn("ロゴイメージの取得に失敗しました"); image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB); // TODO デカく "狼" とでも描くか? } @@ -183,11 +164,10 @@ public final class GUIUtils{ return windowIconImage; } - BufferedImage image; - try{ - image = loadImageFromResource(RES_WINDOWICON); - }catch(IOException e){ - Jindolf.logger().warn("アイコンイメージの取得に失敗しました", e); + BufferedImage image = + ResourceManager.getBufferedImage(RES_WINDOWICON); + if(image == null){ + LOGGER.warn("アイコンイメージの取得に失敗しました"); image = getLogoImage(); } @@ -205,8 +185,7 @@ public final class GUIUtils{ return logoIcon; } - Icon icon = new ImageIcon(getLogoImage()); - + Icon icon = ResourceManager.getImageIcon(RES_LOGOICON); logoIcon = icon; return logoIcon; @@ -221,8 +200,7 @@ public final class GUIUtils{ return wwwIcon; } - URL url = Jindolf.getResource(RES_WWWICON); - wwwIcon = new ImageIcon(url); + wwwIcon = ResourceManager.getImageIcon(RES_WWWICON); return wwwIcon; } @@ -236,10 +214,8 @@ public final class GUIUtils{ return noImage; } - URL url = Jindolf.getResource(RES_NOIMAGE); - try{ - noImage = ImageIO.read(url); - }catch(IOException e){ + noImage = ResourceManager.getBufferedImage(RES_NOIMAGE); + if(noImage == null){ assert false; noImage = getLogoImage(); } @@ -351,40 +327,6 @@ public final class GUIUtils{ } /** - * 独自ロガーにエラーや例外を吐く、 - * カスタム化されたイベントキューに差し替える。 - */ - public static void replaceEventQueue(){ - Toolkit kit = Toolkit.getDefaultToolkit(); - EventQueue oldQueue = kit.getSystemEventQueue(); - EventQueue newQueue = new EventQueue(){ - private static final String FATALMSG = - "イベントディスパッチ中に異常が起きました。"; - @Override - protected void dispatchEvent(AWTEvent event){ - try{ - super.dispatchEvent(event); - }catch(RuntimeException e){ - Jindolf.logger().fatal(FATALMSG, e); - throw e; - }catch(Exception e){ - Jindolf.logger().fatal(FATALMSG, e); - }catch(Error e){ - Jindolf.logger().fatal(FATALMSG, e); - throw e; - } - // TODO Toolkit#beep()もするべきか - // TODO モーダルダイアログを出すべきか - // TODO 標準エラー出力抑止オプションを用意すべきか - // TODO セキュリティバイパス - return; - } - }; - oldQueue.push(newQueue); - return; - } - - /** * 任意のイメージを多階調モノクロ化する。 * 寸法は変わらない。 * @param image イメージ diff --git a/src/main/java/jp/sourceforge/jindolf/Monodizer.java b/src/main/java/jp/sfjp/jindolf/util/Monodizer.java similarity index 99% rename from src/main/java/jp/sourceforge/jindolf/Monodizer.java rename to src/main/java/jp/sfjp/jindolf/util/Monodizer.java index 73f5a42..2b51337 100644 --- a/src/main/java/jp/sourceforge/jindolf/Monodizer.java +++ b/src/main/java/jp/sfjp/jindolf/util/Monodizer.java @@ -5,7 +5,7 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.util; import java.awt.Component; import java.awt.Font; diff --git a/src/main/java/jp/sourceforge/jindolf/StringUtils.java b/src/main/java/jp/sfjp/jindolf/util/StringUtils.java similarity index 99% rename from src/main/java/jp/sourceforge/jindolf/StringUtils.java rename to src/main/java/jp/sfjp/jindolf/util/StringUtils.java index 307dee3..3d36346 100644 --- a/src/main/java/jp/sourceforge/jindolf/StringUtils.java +++ b/src/main/java/jp/sfjp/jindolf/util/StringUtils.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.util; import java.util.regex.Matcher; diff --git a/src/main/java/jp/sfjp/jindolf/util/package-info.java b/src/main/java/jp/sfjp/jindolf/util/package-info.java new file mode 100644 index 0000000..db3578d --- /dev/null +++ b/src/main/java/jp/sfjp/jindolf/util/package-info.java @@ -0,0 +1,14 @@ +/* + * パッケージ情報 + * + * License : The MIT License + * Copyright(c) 2012 olyutorskii + */ + +/** + * 各種ユーティリティクラス。 + */ + +package jp.sfjp.jindolf.util; + +/* EOF */ diff --git a/src/main/java/jp/sourceforge/jindolf/AccountPanel.java b/src/main/java/jp/sfjp/jindolf/view/AccountPanel.java similarity index 95% rename from src/main/java/jp/sourceforge/jindolf/AccountPanel.java rename to src/main/java/jp/sfjp/jindolf/view/AccountPanel.java index 750c9fa..04ab2cc 100644 --- a/src/main/java/jp/sourceforge/jindolf/AccountPanel.java +++ b/src/main/java/jp/sfjp/jindolf/view/AccountPanel.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.view; import java.awt.BorderLayout; import java.awt.Container; @@ -33,6 +33,14 @@ import javax.swing.JSeparator; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.border.Border; +import jp.sfjp.jindolf.VerInfo; +import jp.sfjp.jindolf.data.Land; +import jp.sfjp.jindolf.data.LandsModel; +import jp.sfjp.jindolf.dxchg.TextPopup; +import jp.sfjp.jindolf.log.LogWrapper; +import jp.sfjp.jindolf.net.ServerAccess; +import jp.sfjp.jindolf.util.GUIUtils; +import jp.sfjp.jindolf.util.Monodizer; import jp.sourceforge.jindolf.corelib.LandState; /** @@ -43,8 +51,8 @@ public class AccountPanel extends JDialog implements ActionListener, ItemListener{ - private static final String FRAMETITLE = - "アカウント管理 - " + Jindolf.TITLE; + private static final LogWrapper LOGGER = new LogWrapper(); + private final Map landUserIDMap = new HashMap(); @@ -65,9 +73,11 @@ public class AccountPanel * @param landsModel 国モデル * @throws java.lang.NullPointerException 引数がnull */ + @SuppressWarnings("LeakingThisInConstructor") public AccountPanel(Frame owner, LandsModel landsModel) throws NullPointerException{ - super(owner, FRAMETITLE, true); + super(owner); + setModal(true); if(landsModel == null) throw new NullPointerException(); for(Land land : landsModel.getLandList()){ @@ -267,7 +277,7 @@ public class AccountPanel * @param e ネットワークエラー */ protected void showNetworkError(IOException e){ - Jindolf.logger().warn( + LOGGER.warn( "アカウント処理中にネットワークのトラブルが発生しました", e); Land land = getSelectedLand(); @@ -283,8 +293,8 @@ public class AccountPanel JOptionPane.WARNING_MESSAGE, JOptionPane.DEFAULT_OPTION ); - JDialog dialog = pane.createDialog(this, - "通信異常発生 - " + Jindolf.TITLE); + String title = VerInfo.getFrameTitle("通信異常発生"); + JDialog dialog = pane.createDialog(this, title); dialog.pack(); dialog.setVisible(true); @@ -313,8 +323,8 @@ public class AccountPanel JOptionPane.WARNING_MESSAGE, JOptionPane.DEFAULT_OPTION ); - JDialog dialog = - pane.createDialog(this, "ログイン認証失敗 - " + Jindolf.TITLE); + String title = VerInfo.getFrameTitle("ログイン認証失敗"); + JDialog dialog = pane.createDialog(this, title); dialog.pack(); dialog.setVisible(true); diff --git a/src/main/java/jp/sourceforge/jindolf/ActionManager.java b/src/main/java/jp/sfjp/jindolf/view/ActionManager.java similarity index 95% rename from src/main/java/jp/sourceforge/jindolf/ActionManager.java rename to src/main/java/jp/sfjp/jindolf/view/ActionManager.java index 646b805..a4bac2f 100644 --- a/src/main/java/jp/sourceforge/jindolf/ActionManager.java +++ b/src/main/java/jp/sfjp/jindolf/view/ActionManager.java @@ -5,12 +5,11 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.view; import java.awt.Insets; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; -import java.net.URL; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -19,7 +18,6 @@ import javax.swing.AbstractButton; import javax.swing.ButtonGroup; import javax.swing.ButtonModel; import javax.swing.Icon; -import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JMenu; import javax.swing.JMenuBar; @@ -29,6 +27,9 @@ import javax.swing.JToolBar; import javax.swing.KeyStroke; import javax.swing.LookAndFeel; import javax.swing.UIManager; +import jp.sfjp.jindolf.ResourceManager; +import jp.sfjp.jindolf.VerInfo; +import jp.sfjp.jindolf.util.GUIUtils; /** * メニュー、ボタン、その他各種Actionを伴うイベントを生成する @@ -120,25 +121,23 @@ public class ActionManager{ KeyStroke.getKeyStroke("ctrl F"); static{ - URL iconurl; + ICON_FIND = + ResourceManager.getImageIcon("resources/image/tb_find.png"); - iconurl = Jindolf.getResource("resources/image/find.png"); - ICON_FIND = new ImageIcon(iconurl); + ICON_SEARCH_PREV = + ResourceManager.getImageIcon("resources/image/tb_findprev.png"); - iconurl = Jindolf.getResource("resources/image/findprev.png"); - ICON_SEARCH_PREV = new ImageIcon(iconurl); + ICON_SEARCH_NEXT = + ResourceManager.getImageIcon("resources/image/tb_findnext.png"); - iconurl = Jindolf.getResource("resources/image/findnext.png"); - ICON_SEARCH_NEXT = new ImageIcon(iconurl); + ICON_RELOAD = + ResourceManager.getImageIcon("resources/image/tb_reload.png"); - iconurl = Jindolf.getResource("resources/image/reload.png"); - ICON_RELOAD = new ImageIcon(iconurl); + ICON_FILTER = + ResourceManager.getImageIcon("resources/image/tb_filter.png"); - iconurl = Jindolf.getResource("resources/image/filter.png"); - ICON_FILTER = new ImageIcon(iconurl); - - iconurl = Jindolf.getResource("resources/image/editor.png"); - ICON_EDITOR = new ImageIcon(iconurl); + ICON_EDITOR = + ResourceManager.getImageIcon("resources/image/tb_editor.png"); } private final Set actionItems = @@ -203,7 +202,7 @@ public class ActionManager{ buildMenuItem(CMD_SHOWLOG, "ログ表示", KeyEvent.VK_S); buildMenuItem(CMD_HELPDOC, "ヘルプ表示", KeyEvent.VK_H); buildMenuItem(CMD_SHOWPORTAL, "ポータルサイト...", KeyEvent.VK_P); - buildMenuItem(CMD_ABOUT, Jindolf.TITLE + "について...", KeyEvent.VK_A); + buildMenuItem(CMD_ABOUT, VerInfo.TITLE + "について...", KeyEvent.VK_A); buildToolButton(CMD_RELOAD, "選択中の日を強制リロード", ICON_RELOAD); buildToolButton(CMD_SHOWFIND, "検索", ICON_FIND); diff --git a/src/main/java/jp/sourceforge/jindolf/DialogPrefPanel.java b/src/main/java/jp/sfjp/jindolf/view/DialogPrefPanel.java similarity index 98% rename from src/main/java/jp/sourceforge/jindolf/DialogPrefPanel.java rename to src/main/java/jp/sfjp/jindolf/view/DialogPrefPanel.java index 803d480..edba258 100644 --- a/src/main/java/jp/sourceforge/jindolf/DialogPrefPanel.java +++ b/src/main/java/jp/sfjp/jindolf/view/DialogPrefPanel.java @@ -5,7 +5,7 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.view; import java.awt.Container; import java.awt.GridBagConstraints; @@ -21,6 +21,7 @@ import javax.swing.JCheckBox; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.border.Border; +import jp.sfjp.jindolf.data.DialogPref; /** * 発言表示の各種設定パネル。 @@ -43,6 +44,7 @@ public class DialogPrefPanel /** * コンストラクタ。 */ + @SuppressWarnings("LeakingThisInConstructor") public DialogPrefPanel(){ this.resetDefault.addActionListener(this); this.isSimpleMode.addItemListener(this); diff --git a/src/main/java/jp/sourceforge/jindolf/FilterPanel.java b/src/main/java/jp/sfjp/jindolf/view/FilterPanel.java similarity index 98% rename from src/main/java/jp/sourceforge/jindolf/FilterPanel.java rename to src/main/java/jp/sfjp/jindolf/view/FilterPanel.java index ecf0438..e9ed3e7 100644 --- a/src/main/java/jp/sourceforge/jindolf/FilterPanel.java +++ b/src/main/java/jp/sfjp/jindolf/view/FilterPanel.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.view; import java.awt.Container; import java.awt.Frame; @@ -31,6 +31,11 @@ import javax.swing.border.Border; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.EventListenerList; +import jp.sfjp.jindolf.data.Avatar; +import jp.sfjp.jindolf.data.SysEvent; +import jp.sfjp.jindolf.data.Talk; +import jp.sfjp.jindolf.data.Topic; +import jp.sfjp.jindolf.util.GUIUtils; import jp.sourceforge.jindolf.corelib.EventFamily; import jp.sourceforge.jindolf.corelib.TalkType; @@ -43,7 +48,6 @@ public class FilterPanel extends JDialog private static final int COLS = 4; - private static final String FRAMETITLE = "発言フィルタ - " + Jindolf.TITLE; private final JCheckBox checkPublic = new JCheckBox("公開", true); private final JCheckBox checkWolf = new JCheckBox("狼", true); @@ -69,8 +73,10 @@ public class FilterPanel extends JDialog * 発言フィルタを生成する。 * @param owner フレームオーナー */ + @SuppressWarnings("LeakingThisInConstructor") public FilterPanel(Frame owner){ - super(owner, FRAMETITLE, false); + super(owner); + setModal(false); GUIUtils.modifyWindowAttributes(this, true, false, true); diff --git a/src/main/java/jp/sourceforge/jindolf/FindPanel.java b/src/main/java/jp/sfjp/jindolf/view/FindPanel.java similarity index 94% rename from src/main/java/jp/sourceforge/jindolf/FindPanel.java rename to src/main/java/jp/sfjp/jindolf/view/FindPanel.java index bbedf4a..8c0ea21 100644 --- a/src/main/java/jp/sourceforge/jindolf/FindPanel.java +++ b/src/main/java/jp/sfjp/jindolf/view/FindPanel.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.view; import java.awt.BorderLayout; import java.awt.Component; @@ -51,8 +51,13 @@ import javax.swing.event.EventListenerList; import javax.swing.event.ListDataEvent; import javax.swing.event.ListDataListener; import javax.swing.text.JTextComponent; +import jp.sfjp.jindolf.data.RegexPattern; +import jp.sfjp.jindolf.dxchg.TextPopup; +import jp.sfjp.jindolf.util.GUIUtils; import jp.sourceforge.jovsonz.JsArray; +import jp.sourceforge.jovsonz.JsComposition; import jp.sourceforge.jovsonz.JsObject; +import jp.sourceforge.jovsonz.JsTypes; import jp.sourceforge.jovsonz.JsValue; /** @@ -65,8 +70,9 @@ public class FindPanel extends JDialog ChangeListener, PropertyChangeListener { - private static final String HIST_FILE = "searchHistory.json"; - private static final String FRAMETITLE = "発言検索 - " + Jindolf.TITLE; + /** 検索履歴ファイル。 */ + public static final File HIST_FILE = new File("searchHistory.json"); + private static final String LABEL_REENTER = "再入力"; private static final String LABEL_IGNORE = "無視して検索をキャンセル"; @@ -97,8 +103,10 @@ public class FindPanel extends JDialog * 検索パネルを生成する。 * @param owner 親フレーム。 */ + @SuppressWarnings("LeakingThisInConstructor") public FindPanel(Frame owner){ - super(owner, FRAMETITLE, true); + super(owner); + setModal(true); GUIUtils.modifyWindowAttributes(this, true, false, true); @@ -476,21 +484,39 @@ public class FindPanel extends JDialog } /** - * 検索履歴をロードする。 + * JSON形式の検索履歴情報を返す。 + * @return JSON形式の検索履歴情報 */ - public void loadHistory(){ - JsValue value = ConfigFile.loadJson(new File(HIST_FILE)); - if(value == null) return; + public JsObject getJson(){ + JsObject result = new JsObject(); + + JsArray array = new JsArray(); + result.putValue("history", array); - if( ! (value instanceof JsObject) ) return; - JsObject root = (JsObject) value; + List history = this.model.getOriginalHistoryList(); + history = new ArrayList(history); + Collections.reverse(history); + for(RegexPattern regex : history){ + JsObject obj = RegexPattern.encodeJson(regex); + array.add(obj); + } + + return result; + } + + /** + * JSON形式の検索履歴を反映させる。 + * @param root JSON形式の検索履歴。nullが来たら何もしない + */ + public void putJson(JsObject root){ + if(root == null) return; - value = root.getValue("history"); - if( ! (value instanceof JsArray) ) return; + JsValue value = root.getValue("history"); + if(value.getJsTypes() != JsTypes.ARRAY) return; JsArray array = (JsArray) value; for(JsValue elem : array){ - if( ! (elem instanceof JsObject) ) continue; + if(elem.getJsTypes() != JsTypes.OBJECT) continue; JsObject regObj = (JsObject) elem; RegexPattern regex = RegexPattern.decodeJson(regObj); if(regex == null) continue; @@ -503,33 +529,15 @@ public class FindPanel extends JDialog } /** - * 検索履歴をセーブする。 + * 起動時の履歴設定と等価か判定する。 + * @param conf 比較対象 + * @return 等価ならtrue */ - public void saveHistory(){ - AppSetting setting = Jindolf.getAppSetting(); - if( ! setting.useConfigPath() ) return; - File configPath = setting.getConfigPath(); - if(configPath == null) return; - - JsObject root = new JsObject(); - JsArray array = new JsArray(); - root.putValue("history", array); - - List history = this.model.getOriginalHistoryList(); - history = new ArrayList(history); - Collections.reverse(history); - for(RegexPattern regex : history){ - JsObject obj = RegexPattern.encodeJson(regex); - array.add(obj); - } - + public boolean hasConfChanged(JsComposition conf){ if(this.loadedHistory != null){ - if(this.loadedHistory.equals(root)) return; + if(this.loadedHistory.equals(conf)) return true; } - - ConfigFile.saveJson(new File(HIST_FILE), root); - - return; + return false; } /** diff --git a/src/main/java/jp/sourceforge/jindolf/HelpFrame.java b/src/main/java/jp/sfjp/jindolf/view/HelpFrame.java similarity index 81% rename from src/main/java/jp/sourceforge/jindolf/HelpFrame.java rename to src/main/java/jp/sfjp/jindolf/view/HelpFrame.java index 772a0e8..8cfeb06 100644 --- a/src/main/java/jp/sourceforge/jindolf/HelpFrame.java +++ b/src/main/java/jp/sfjp/jindolf/view/HelpFrame.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.view; import java.awt.Container; import java.awt.GridBagConstraints; @@ -28,6 +28,13 @@ import javax.swing.JTextArea; import javax.swing.border.Border; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; +import jp.sfjp.jindolf.ResourceManager; +import jp.sfjp.jindolf.config.ConfigStore; +import jp.sfjp.jindolf.config.EnvInfo; +import jp.sfjp.jindolf.config.OptionInfo; +import jp.sfjp.jindolf.dxchg.TextPopup; +import jp.sfjp.jindolf.log.LogWrapper; +import jp.sfjp.jindolf.util.GUIUtils; /** * ヘルプ画面。 @@ -38,6 +45,9 @@ public class HelpFrame extends JFrame private static final String HELP_HTML = "resources/html/help.html"; + private static final LogWrapper LOGGER = new LogWrapper(); + + private final JTabbedPane tabPanel = new JTabbedPane(); private final JEditorPane htmlView = new JEditorPane(); private final JTextArea vmInfo = new JTextArea(); @@ -45,9 +55,12 @@ public class HelpFrame extends JFrame /** * コンストラクタ。 + * @param optinfo コマンドラインオプション + * @param configStore 設定ディレクトリ情報 */ - public HelpFrame(){ - super(Jindolf.TITLE + " ヘルプ"); + @SuppressWarnings("LeakingThisInConstructor") + public HelpFrame(OptionInfo optinfo, ConfigStore configStore){ + super(); GUIUtils.modifyWindowAttributes(this, true, false, true); @@ -76,15 +89,22 @@ public class HelpFrame extends JFrame } }); - URL topUrl = Jindolf.getResource(HELP_HTML); + URL topUrl = ResourceManager.getResource(HELP_HTML); loadURL(topUrl); StringBuilder info = new StringBuilder(); + + info.append("起動時引数:\n"); + for(String arg : optinfo.getInvokeArgList()){ + info.append("\u0020\u0020").append(arg).append('\n'); + } + info.append('\n'); + info.append(EnvInfo.getVMInfo()); - AppSetting setting = Jindolf.getAppSetting(); - if(setting.useConfigPath()){ - info.append("設定格納ディレクトリ : " - + setting.getConfigPath().getPath() ); + + if(configStore.useStoreFile()){ + info.append("設定格納ディレクトリ : ") + .append(configStore.getConfigPath().getPath()); }else{ info.append("※ 設定格納ディレクトリは使っていません。"); } @@ -146,7 +166,7 @@ public class HelpFrame extends JFrame try{ this.htmlView.setPage(url); }catch(IOException e){ - Jindolf.logger().warn("ヘルプファイルが読み込めません", e); + LOGGER.warn("ヘルプファイルが読み込めません", e); assert false; } diff --git a/src/main/java/jp/sourceforge/jindolf/LandInfoPanel.java b/src/main/java/jp/sfjp/jindolf/view/LandInfoPanel.java similarity index 97% rename from src/main/java/jp/sourceforge/jindolf/LandInfoPanel.java rename to src/main/java/jp/sfjp/jindolf/view/LandInfoPanel.java index 4ab35ca..8c039b4 100644 --- a/src/main/java/jp/sourceforge/jindolf/LandInfoPanel.java +++ b/src/main/java/jp/sfjp/jindolf/view/LandInfoPanel.java @@ -5,7 +5,7 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.view; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; @@ -15,6 +15,9 @@ import java.util.Date; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; +import jp.sfjp.jindolf.data.Land; +import jp.sfjp.jindolf.dxchg.WebButton; +import jp.sfjp.jindolf.util.Monodizer; import jp.sourceforge.jindolf.corelib.LandDef; import jp.sourceforge.jindolf.corelib.LandState; diff --git a/src/main/java/jp/sourceforge/jindolf/LandsTree.java b/src/main/java/jp/sfjp/jindolf/view/LandsTree.java similarity index 92% rename from src/main/java/jp/sourceforge/jindolf/LandsTree.java rename to src/main/java/jp/sfjp/jindolf/view/LandsTree.java index 3e3cb7e..911c5d7 100644 --- a/src/main/java/jp/sourceforge/jindolf/LandsTree.java +++ b/src/main/java/jp/sfjp/jindolf/view/LandsTree.java @@ -5,14 +5,13 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.view; import java.awt.BorderLayout; import java.awt.EventQueue; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.net.URL; import javax.swing.BorderFactory; import javax.swing.ImageIcon; import javax.swing.JButton; @@ -27,6 +26,9 @@ import javax.swing.event.TreeSelectionListener; import javax.swing.tree.TreeModel; import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; +import jp.sfjp.jindolf.ResourceManager; +import jp.sfjp.jindolf.data.Land; +import jp.sfjp.jindolf.data.LandsModel; /** * 国一覧Tree周辺コンポーネント群。 @@ -43,11 +45,10 @@ public class LandsTree private static final ImageIcon ICON_DESCEND; static{ - URL url; - url = Jindolf.getResource("resources/image/ascend.png"); - ICON_ASCEND = new ImageIcon(url); - url = Jindolf.getResource("resources/image/descend.png"); - ICON_DESCEND = new ImageIcon(url); + ICON_ASCEND = + ResourceManager.getImageIcon("resources/image/tb_ascend.png"); + ICON_DESCEND = + ResourceManager.getImageIcon("resources/image/tb_descend.png"); } private final JButton orderButton = new JButton(); @@ -59,6 +60,7 @@ public class LandsTree /** * コンストラクタ。 */ + @SuppressWarnings("LeakingThisInConstructor") public LandsTree(){ super(); @@ -70,9 +72,9 @@ public class LandsTree this.orderButton.setActionCommand(ActionManager.CMD_SWITCHORDER); this.orderButton.addActionListener(this); - URL url; - url = Jindolf.getResource("resources/image/reload.png"); - this.reloadButton.setIcon(new ImageIcon(url)); + ImageIcon icon = + ResourceManager.getImageIcon("resources/image/tb_reload.png"); + this.reloadButton.setIcon(icon); this.reloadButton.setToolTipText(TIP_ORDER); this.reloadButton.setMargin(new Insets(1, 1, 1, 1)); this.reloadButton.setActionCommand(ActionManager.CMD_VILLAGELIST); diff --git a/src/main/java/jp/sfjp/jindolf/view/LockErrorPane.java b/src/main/java/jp/sfjp/jindolf/view/LockErrorPane.java new file mode 100644 index 0000000..3ec7a3b --- /dev/null +++ b/src/main/java/jp/sfjp/jindolf/view/LockErrorPane.java @@ -0,0 +1,178 @@ +/* + * lock file warning dialog + * + * License : The MIT License + * Copyright(c) 2012 olyutorskii + */ + +package jp.sfjp.jindolf.view; + +import java.awt.Component; +import java.awt.HeadlessException; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.ButtonGroup; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JOptionPane; +import javax.swing.JRadioButton; +import jp.sfjp.jindolf.config.FileUtils; +import jp.sfjp.jindolf.config.InterVMLock; + +/** + * ロックエラー用ダイアログ。 + *

    + *
  • 強制解除 + *
  • リトライ + *
  • 設定ディレクトリを無視 + *
  • 起動中止 + *
+ * の選択を利用者に求める。 + */ +@SuppressWarnings("serial") +public class LockErrorPane extends JOptionPane implements ActionListener{ + + private final InterVMLock lock; + + private final JRadioButton continueButton = + new JRadioButton("設定ディレクトリを使わずに起動を続行"); + private final JRadioButton retryButton = + new JRadioButton("再度ロック取得を試す"); + private final JRadioButton forceButton = + new JRadioButton( + "" + + "ロックを強制解除
" + + " (※他のJindolfと設定ファイル書き込みが衝突するかも…)" + + ""); + + private final JButton okButton = new JButton("OK"); + private final JButton abortButton = new JButton("起動中止"); + + private boolean aborted = false; + + /** + * コンストラクタ。 + * @param lock 失敗したロック + */ + @SuppressWarnings("LeakingThisInConstructor") + public LockErrorPane(InterVMLock lock){ + super(); + + this.lock = lock; + + String htmlMessage = + "" + + "設定ディレクトリのロックファイル
" + + "
[ " + + FileUtils.getHtmledFileName(this.lock.getLockFile()) + + " ]
" + + "
" + + "のロックに失敗しました。
" + + "考えられる原因としては、
" + + "
    " + + "
  • 前回起動したJindolfの終了が正しく行われなかった" + + "
  • 今どこかで他のJindolfが動いている" + + "
" + + "などが考えられます。
" + + "
" + + ""; + + ButtonGroup bgrp = new ButtonGroup(); + bgrp.add(this.continueButton); + bgrp.add(this.retryButton); + bgrp.add(this.forceButton); + this.continueButton.setSelected(true); + + Object[] msg = { + htmlMessage, + this.continueButton, + this.retryButton, + this.forceButton, + }; + setMessage(msg); + + Object[] opts = { + this.okButton, + this.abortButton, + }; + setOptions(opts); + + setMessageType(JOptionPane.ERROR_MESSAGE); + + this.okButton .addActionListener(this); + this.abortButton.addActionListener(this); + + return; + } + + /** + * 「設定ディレクトリを無視して続行」が選択されたか判定する。 + * @return 「無視して続行」が選択されていればtrue + */ + public boolean isRadioContinue(){ + return this.continueButton.isSelected(); + } + + /** + * 「リトライ」が選択されたか判定する。 + * @return 「リトライ」が選択されていればtrue + */ + public boolean isRadioRetry(){ + return this.retryButton.isSelected(); + } + + /** + * 「強制解除」が選択されたか判定する。 + * @return 「強制解除」が選択されていればtrue + */ + public boolean isRadioForce(){ + return this.forceButton.isSelected(); + } + + /** + * 「起動中止」が選択されたか判定する。 + * @return 「起動中止」が押されていたならtrue + */ + public boolean isAborted(){ + return this.aborted; + } + + /** + * {@inheritDoc} + * @param parentComponent {@inheritDoc} + * @param title {@inheritDoc} + * @return {@inheritDoc} + * @throws HeadlessException {@inheritDoc} + */ + @Override + public JDialog createDialog(Component parentComponent, + String title) + throws HeadlessException{ + final JDialog dialog = + super.createDialog(parentComponent, title); + + ActionListener listener = new ActionListener(){ + public void actionPerformed(ActionEvent event){ + dialog.setVisible(false); + return; + } + }; + + this.okButton .addActionListener(listener); + this.abortButton.addActionListener(listener); + + return dialog; + } + + /** + * ボタン押下を受信する。 + * @param event イベント + */ + public void actionPerformed(ActionEvent event){ + Object source = event.getSource(); + if(source == this.okButton) this.aborted = false; + else this.aborted = true; + return; + } + +} diff --git a/src/main/java/jp/sourceforge/jindolf/OptionPanel.java b/src/main/java/jp/sfjp/jindolf/view/OptionPanel.java similarity index 95% rename from src/main/java/jp/sourceforge/jindolf/OptionPanel.java rename to src/main/java/jp/sfjp/jindolf/view/OptionPanel.java index 42f5d21..864a828 100644 --- a/src/main/java/jp/sourceforge/jindolf/OptionPanel.java +++ b/src/main/java/jp/sfjp/jindolf/view/OptionPanel.java @@ -5,7 +5,7 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.view; import java.awt.Container; import java.awt.Frame; @@ -20,6 +20,10 @@ import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JSeparator; import javax.swing.JTabbedPane; +import jp.sfjp.jindolf.glyph.FontChooser; +import jp.sfjp.jindolf.glyph.FontInfo; +import jp.sfjp.jindolf.net.ProxyChooser; +import jp.sfjp.jindolf.util.GUIUtils; /** * オプション設定パネル。 @@ -29,9 +33,6 @@ public class OptionPanel extends JDialog implements ActionListener, WindowListener{ - private static final String FRAMETITLE = - "オプション設定 - " + Jindolf.TITLE; - private final JTabbedPane tabPane = new JTabbedPane(); private final FontChooser fontChooser; @@ -47,8 +48,10 @@ public class OptionPanel * コンストラクタ。 * @param owner フレームオーナ */ + @SuppressWarnings("LeakingThisInConstructor") public OptionPanel(Frame owner){ - super(owner, FRAMETITLE, true); + super(owner); + setModal(true); GUIUtils.modifyWindowAttributes(this, true, false, true); diff --git a/src/main/java/jp/sourceforge/jindolf/PeriodView.java b/src/main/java/jp/sfjp/jindolf/view/PeriodView.java similarity index 96% rename from src/main/java/jp/sourceforge/jindolf/PeriodView.java rename to src/main/java/jp/sfjp/jindolf/view/PeriodView.java index 47b2545..a6f6229 100644 --- a/src/main/java/jp/sourceforge/jindolf/PeriodView.java +++ b/src/main/java/jp/sfjp/jindolf/view/PeriodView.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.view; import java.awt.BorderLayout; import java.awt.Color; @@ -30,6 +30,14 @@ import javax.swing.JScrollPane; import javax.swing.JViewport; import javax.swing.ScrollPaneConstants; import javax.swing.border.Border; +import jp.sfjp.jindolf.data.DialogPref; +import jp.sfjp.jindolf.data.Period; +import jp.sfjp.jindolf.data.Talk; +import jp.sfjp.jindolf.data.Topic; +import jp.sfjp.jindolf.data.Village; +import jp.sfjp.jindolf.glyph.Discussion; +import jp.sfjp.jindolf.glyph.FontInfo; +import jp.sfjp.jindolf.glyph.TalkDraw; import jp.sourceforge.jindolf.corelib.TalkType; /** @@ -57,6 +65,7 @@ public class PeriodView extends JPanel implements ItemListener{ * 発言ブラウザを内包するPeriodビューワを生成する。 * @param period 日 */ + @SuppressWarnings("LeakingThisInConstructor") public PeriodView(Period period){ super(); diff --git a/src/main/java/jp/sourceforge/jindolf/TabBrowser.java b/src/main/java/jp/sfjp/jindolf/view/TabBrowser.java similarity index 97% rename from src/main/java/jp/sourceforge/jindolf/TabBrowser.java rename to src/main/java/jp/sfjp/jindolf/view/TabBrowser.java index 06e4d36..eefd000 100644 --- a/src/main/java/jp/sourceforge/jindolf/TabBrowser.java +++ b/src/main/java/jp/sfjp/jindolf/view/TabBrowser.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.view; import java.awt.Component; import java.awt.event.ActionListener; @@ -19,6 +19,12 @@ import javax.swing.JTabbedPane; import javax.swing.SwingConstants; import javax.swing.border.Border; import javax.swing.event.EventListenerList; +import jp.sfjp.jindolf.data.DialogPref; +import jp.sfjp.jindolf.data.Period; +import jp.sfjp.jindolf.data.Village; +import jp.sfjp.jindolf.glyph.AnchorHitListener; +import jp.sfjp.jindolf.glyph.Discussion; +import jp.sfjp.jindolf.glyph.FontInfo; /** * タブを用いて村情報と各Periodを閲覧するためのコンポーネント。 diff --git a/src/main/java/jp/sourceforge/jindolf/TopView.java b/src/main/java/jp/sfjp/jindolf/view/TopView.java similarity index 95% rename from src/main/java/jp/sourceforge/jindolf/TopView.java rename to src/main/java/jp/sfjp/jindolf/view/TopView.java index 6c6d5f8..423375e 100644 --- a/src/main/java/jp/sourceforge/jindolf/TopView.java +++ b/src/main/java/jp/sfjp/jindolf/view/TopView.java @@ -5,7 +5,7 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.view; import java.awt.BorderLayout; import java.awt.CardLayout; @@ -26,6 +26,10 @@ import javax.swing.SwingConstants; import javax.swing.border.BevelBorder; import javax.swing.border.Border; import javax.swing.border.CompoundBorder; +import jp.sfjp.jindolf.VerInfo; +import jp.sfjp.jindolf.data.Land; +import jp.sfjp.jindolf.data.Village; +import jp.sfjp.jindolf.util.GUIUtils; /** * 最上位ビュー。 @@ -38,6 +42,11 @@ public class TopView extends JPanel{ private static final String LANDCARD = "LANDINFO"; private static final String BROWSECARD = "BROWSER"; + private static final String MSG_THANKS = + VerInfo.TITLE + "\u0020" + VerInfo.VERSION + + "\u0020を使ってくれてありがとう!"; + + private final JComponent cards; private final CardLayout cardLayout = new CardLayout(); @@ -185,9 +194,7 @@ public class TopView extends JPanel{ * @return ステータスバー */ private JComponent createStatusBar(){ - this.sysMessage.setText( - Jindolf.TITLE + " " + Jindolf.VERSION - + " を使ってくれてありがとう!" ); + this.sysMessage.setText(MSG_THANKS); this.sysMessage.setEditable(false); Border inside = BorderFactory.createBevelBorder(BevelBorder.LOWERED); Border outside = BorderFactory.createEmptyBorder(2, 5, 2, 2); diff --git a/src/main/java/jp/sourceforge/jindolf/TopicFilter.java b/src/main/java/jp/sfjp/jindolf/view/TopicFilter.java similarity index 93% rename from src/main/java/jp/sourceforge/jindolf/TopicFilter.java rename to src/main/java/jp/sfjp/jindolf/view/TopicFilter.java index e3ba864..da7f016 100644 --- a/src/main/java/jp/sourceforge/jindolf/TopicFilter.java +++ b/src/main/java/jp/sfjp/jindolf/view/TopicFilter.java @@ -5,7 +5,9 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.view; + +import jp.sfjp.jindolf.data.Topic; /** * 発言Topicのフィルタリングを行うインタフェース。 @@ -13,11 +15,6 @@ package jp.sourceforge.jindolf; public interface TopicFilter { /** - * フィルタの状態を表すインタフェース。 - */ - interface FilterContext{} - - /** * 与えられたTopicをフィルタリングする。 * @param topic Topic * @return フィルタリングするならtrue @@ -38,4 +35,9 @@ public interface TopicFilter { */ boolean isSame(FilterContext context); + /** + * フィルタの状態を表すインタフェース。 + */ + interface FilterContext{} + } diff --git a/src/main/java/jp/sourceforge/jindolf/VillageIconRenderer.java b/src/main/java/jp/sfjp/jindolf/view/VillageIconRenderer.java similarity index 78% rename from src/main/java/jp/sourceforge/jindolf/VillageIconRenderer.java rename to src/main/java/jp/sfjp/jindolf/view/VillageIconRenderer.java index 7ec01da..ed3999b 100644 --- a/src/main/java/jp/sourceforge/jindolf/VillageIconRenderer.java +++ b/src/main/java/jp/sfjp/jindolf/view/VillageIconRenderer.java @@ -5,13 +5,14 @@ * Copyright(c) 2008 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.view; import java.awt.Component; -import java.net.URL; import javax.swing.ImageIcon; import javax.swing.JTree; import javax.swing.tree.DefaultTreeCellRenderer; +import jp.sfjp.jindolf.ResourceManager; +import jp.sfjp.jindolf.data.Village; /** * JTreeの村別アイコン表示。 @@ -26,17 +27,16 @@ public class VillageIconRenderer extends DefaultTreeCellRenderer{ private static final ImageIcon ICON_INVALID; static{ - URL url; - url = Jindolf.getResource("resources/image/prologue.png"); - ICON_PROLOGUE = new ImageIcon(url); - url = Jindolf.getResource("resources/image/progress.png"); - ICON_PROGRESS = new ImageIcon(url); - url = Jindolf.getResource("resources/image/epilogue.png"); - ICON_EPILOGUE = new ImageIcon(url); - url = Jindolf.getResource("resources/image/gameover.png"); - ICON_GAMEOVER = new ImageIcon(url); - url = Jindolf.getResource("resources/image/cross.png"); - ICON_INVALID = new ImageIcon(url); + ICON_PROLOGUE = + ResourceManager.getImageIcon("resources/image/vs_prologue.png"); + ICON_PROGRESS = + ResourceManager.getImageIcon("resources/image/vs_progress.png"); + ICON_EPILOGUE = + ResourceManager.getImageIcon("resources/image/vs_epilogue.png"); + ICON_GAMEOVER = + ResourceManager.getImageIcon("resources/image/vs_gameover.png"); + ICON_INVALID = + ResourceManager.getImageIcon("resources/image/vs_cross.png"); } /** diff --git a/src/main/java/jp/sourceforge/jindolf/VillageInfoPanel.java b/src/main/java/jp/sfjp/jindolf/view/VillageInfoPanel.java similarity index 98% rename from src/main/java/jp/sourceforge/jindolf/VillageInfoPanel.java rename to src/main/java/jp/sfjp/jindolf/view/VillageInfoPanel.java index fc5c87b..171b0e6 100644 --- a/src/main/java/jp/sourceforge/jindolf/VillageInfoPanel.java +++ b/src/main/java/jp/sfjp/jindolf/view/VillageInfoPanel.java @@ -5,13 +5,14 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.view; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import javax.swing.JLabel; import javax.swing.JPanel; +import jp.sfjp.jindolf.data.Village; /** * 村情報表示パネル。 diff --git a/src/main/java/jp/sfjp/jindolf/view/package-info.java b/src/main/java/jp/sfjp/jindolf/view/package-info.java new file mode 100644 index 0000000..98bd551 --- /dev/null +++ b/src/main/java/jp/sfjp/jindolf/view/package-info.java @@ -0,0 +1,14 @@ +/* + * パッケージ情報 + * + * License : The MIT License + * Copyright(c) 2012 olyutorskii + */ + +/** + * 各種ビュークラス。 + */ + +package jp.sfjp.jindolf.view; + +/* EOF */ diff --git a/src/main/java/jp/sourceforge/jindolf/Jindolf.java b/src/main/java/jp/sourceforge/jindolf/Jindolf.java deleted file mode 100644 index fee2ae0..0000000 --- a/src/main/java/jp/sourceforge/jindolf/Jindolf.java +++ /dev/null @@ -1,817 +0,0 @@ -/* - * Jindolf main class - * - * License : The MIT License - * Copyright(c) 2008 olyutorskii - */ - -package jp.sourceforge.jindolf; - -import java.awt.Dimension; -import java.awt.EventQueue; -import java.awt.GraphicsEnvironment; -import java.awt.Window; -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.LineNumberReader; -import java.io.Reader; -import java.lang.reflect.InvocationTargetException; -import java.net.URL; -import java.security.Permission; -import java.text.DateFormat; -import java.text.NumberFormat; -import java.util.Date; -import java.util.Properties; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.logging.ConsoleHandler; -import java.util.logging.Handler; -import java.util.logging.Logger; -import java.util.logging.LoggingPermission; -import javax.swing.ImageIcon; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JWindow; -import javax.swing.UIManager; - -/** - * Jindolf スタートアップクラス。 - * - * コンストラクタは無いよ。 - * アプリ開始はstaticメソッド{@link #main(String[])}呼び出しから。 - */ -public final class Jindolf{ - - /** 実行に最低限必要なJREの版数。 */ - public static final String MINIMUM_JREVER = "1.5"; - - - /** このClass。 */ - public static final Class SELF_KLASS; - /** このPackage。 */ - public static final Package SELF_PACKAGE; - /** ランタイムPackage。 */ - public static final Package JRE_PACKAGE; - /** 実行環境。 */ - public static final Runtime RUNTIME; - /** セキュリティマネージャ。 */ - public static final SecurityManager SEC_MANAGER; - /** クラスローダ。 */ - public static final ClassLoader LOADER; - - - /** クラスロード時のナノカウント。 */ - public static final long NANOCT_LOADED; - /** クラスロード時刻(エポックmsec)。 */ - public static final long EPOCHMS_LOADED; - - - /** タイトル。 */ - public static final String TITLE; - /** バージョン。 */ - public static final String VERSION; - /** 作者名。 */ - public static final String AUTHOR; - /** 著作権表記。 */ - public static final String COPYRIGHT; - /** ライセンス表記。 */ - public static final String LICENSE; - /** 連絡先。 */ - public static final String CONTACT; - /** 初出。 */ - public static final String DEBUT; - /** その他、何でも書きたいこと。 */ - public static final String COMMENT; - /** クレジット。 */ - public static final String ID; - - /** 共通ロガー。 */ - private static final LogWrapper COMMON_LOGGER; - - /** 多重起動防止用セマフォ。 */ - private static final AtomicBoolean INVOKE_FLAG; - - /** スプラッシュロゴ。 */ - private static final String RES_LOGOICON = - "resources/image/logo.png"; - - private static OptionInfo option; - private static AppSetting setting; - - /** バージョン定義リソース。 */ - private static final String RES_VERDEF = "resources/version.properties"; - - static{ - SELF_KLASS = Jindolf.class; - SELF_PACKAGE = SELF_KLASS.getPackage(); - JRE_PACKAGE = java.lang.Object.class.getPackage(); - RUNTIME = Runtime.getRuntime(); - SEC_MANAGER = System.getSecurityManager(); - - ClassLoader thisLoader; - try{ - thisLoader = SELF_KLASS.getClassLoader(); - }catch(SecurityException e){ - thisLoader = null; - } - LOADER = thisLoader; - - if( ! JRE_PACKAGE.isCompatibleWith(MINIMUM_JREVER) ){ - String jreInstalled; - try{ - jreInstalled = System.getProperty("java.home"); - }catch(SecurityException e){ - jreInstalled = "※インストール位置不明"; - } - String errmsg = - "今このプログラム " + SELF_KLASS.getName() + " は\n" - +"[ " + jreInstalled - +" ]\nにインストールされた" - +" JRE" + JRE_PACKAGE.getSpecificationVersion() - +" の実行環境で実行されようとしました。\n" - +"しかしこのプログラムの実行には" - +" JRE" + MINIMUM_JREVER - + " 以降の実行環境が必要です。\n" - +"おそらく http://www.java.com/ などからの" - +"入手が可能でしょう。"; - - errorDialog("実行系の不備", errmsg); - - RUNTIME.exit(1); - } - - // ここからJRE1.5解禁。 - - NANOCT_LOADED = System.nanoTime(); - EPOCHMS_LOADED = System.currentTimeMillis(); - - Properties verProp = loadVersionDefinition(SELF_KLASS); - TITLE = getPackageInfo(verProp, "pkg-title.", "Unknown"); - VERSION = getPackageInfo(verProp, "pkg-version.", "0"); - AUTHOR = getPackageInfo(verProp, "pkg-author.", "nobody"); - LICENSE = getPackageInfo(verProp, "pkg-license.", "Unknown"); - CONTACT = getPackageInfo(verProp, "pkg-contact.", "Unknown"); - DEBUT = getPackageInfo(verProp, "pkg-debut.", "2008"); - COMMENT = getPackageInfo(verProp, "pkg-comment.", ""); - COPYRIGHT = "Copyright(c)" +"\u0020"+ DEBUT +"\u0020"+ AUTHOR; - ID = TITLE - +"\u0020"+ "Ver." + VERSION - +"\u0020"+ COPYRIGHT - +"\u0020"+ "("+ LICENSE +")"; - - Logger jre14Logger = Logger.getLogger(SELF_PACKAGE.getName()); - COMMON_LOGGER = new LogWrapper(jre14Logger); - - INVOKE_FLAG = new AtomicBoolean(false); - - new Jindolf(); - } - - - /** - * 隠れコンストラクタ。 - */ - private Jindolf(){ - super(); - assert this.getClass() == SELF_KLASS; - return; - } - - - /** - * 起動オプション情報を返す。 - * @return 起動オプション情報 - */ - public static OptionInfo getOptionInfo(){ - return option; - } - - /** - * アプリ設定を返す。 - * @return アプリ設定 - */ - public static AppSetting getAppSetting(){ - return setting; - } - - /** - * エラーダイアログをビットマップディスプレイに出現させる。 - * メインウィンドウが整備されるまでの間だけ一時的に使う。 - * 努力目標:なるべく昔のJRE環境でも例外無く動くように。 - * @param title タイトル - * @param message メッセージ - */ - private static void errorDialog(String title, String message){ - System.err.println(message); - System.err.flush(); - - if( ! JRE_PACKAGE.isCompatibleWith("1.2") ){ - return; - } - - if( JRE_PACKAGE.isCompatibleWith("1.4") - && GraphicsEnvironment.isHeadless()){ - return; - } - - JOptionPane.showMessageDialog(null, - message, - title, - JOptionPane.ERROR_MESSAGE); - - return; - } - - /** - * リソース上のパッケージ定義プロパティをロードする。 - * MANIFEST.MFが参照できない実行環境での代替品。 - * @param klass パッケージを構成する任意のクラス - * @return プロパティ - */ - private static Properties loadVersionDefinition(Class klass){ - Properties result = new Properties(); - - InputStream istream = klass.getResourceAsStream(RES_VERDEF); - try{ - result.load(istream); - }catch(IOException e){ - return result; - }finally{ - try{ - istream.close(); - }catch(IOException e){ - return result; - } - } - - return result; - } - - /** - * リソース上のプロパティから - * このクラスのパッケージのパッケージ情報を取得する。 - * MANIFEST.MFが参照できない実行環境での代替品。 - * @param prop プロパティ - * @param prefix 接頭辞 - * @param defValue 見つからなかった場合のデフォルト値 - * @return パッケージ情報 - */ - public static String getPackageInfo(Properties prop, - String prefix, - String defValue){ - return getPackageInfo(prop, SELF_PACKAGE, prefix, defValue); - } - - /** - * リソース上のプロパティからパッケージ情報を取得する。 - * MANIFEST.MFが参照できない実行環境での代替品。 - * @param prop プロパティ - * @param pkg 任意のパッケージ - * @param prefix 接頭辞 - * @param defValue デフォルト値 - * @return 見つからなかった場合のパッケージ情報 - */ - public static String getPackageInfo(Properties prop, - Package pkg, - String prefix, - String defValue){ - String propName = prefix + pkg.getName(); - String result = prop.getProperty(propName, defValue); - return result; - } - - /** - * Jindolf の実行が可能なGUI環境でなければ、即時VM実行を終了する。 - */ - private static void checkGUIEnvironment(){ - if(GraphicsEnvironment.isHeadless()){ - System.err.println( - TITLE - + " はGUI環境と接続できませんでした"); - - String dispEnv; - try{ - dispEnv = System.getenv("DISPLAY"); - }catch(SecurityException e){ - dispEnv = null; - } - - // for X11 user - if(dispEnv != null){ - System.err.println("環境変数 DISPLAY : " + dispEnv); - } - - RUNTIME.exit(1); - } - - return; - } - - /** - * コンパイル時のエラーを判定する。 - * ※ 非Unicode系の開発環境を使いたい人は適当に無視してね。 - */ - private static void checkCompileError(){ - String errmsg = - "ソースコードの文字コードが" - +"正しくコンパイルされていないかも。\n" - +"あなたは今、オリジナル開発元の意図しない文字コード環境で" - +"コンパイルされたプログラムを起動しようとしているよ。\n" - +"ソースコードの入手に際して" - +"どのような文字コード変換が行われたか認識しているかな?\n" - +"コンパイルオプションで正しい文字コードを指定したかな?"; - - if( '狼' != 0x72fc - || ' ' != 0x3000 - || '~' != 0x007e - || '\\' != 0x005c // バックスラッシュ - || '¥' != 0x00a5 // 半角円通貨 - || '~' != 0xff5e - || '�' != 0xfffd // Unicode専用特殊文字 - ){ - JOptionPane.showMessageDialog(null, - errmsg, - "コンパイルの不備", - JOptionPane.ERROR_MESSAGE); - RUNTIME.exit(1); - } - return; - } - - /** - * MANIFEST.MFパッケージ定義エラーの検出。 - * ビルド前にMANIFEST自動生成Antタスク「manifest」を忘れてないかい? - */ - private static void checkPackageDefinition(){ - String implTitle = SELF_PACKAGE.getImplementationTitle(); - String implVersion = SELF_PACKAGE.getImplementationVersion(); - String implVendor = SELF_PACKAGE.getImplementationVendor(); - - String errmsg = null; - - if( implTitle != null - && ! implTitle.equals(TITLE) ){ - errmsg = "パッケージ定義とタイトルが一致しません。" - +"["+ implTitle +"]≠["+ TITLE +"]"; - }else if( implVersion != null - && ! implVersion.equals(VERSION) ){ - errmsg = "パッケージ定義とバージョン番号が一致しません。" - +"["+ implVersion +"]≠["+ VERSION +"]"; - }else if( implVendor != null - && ! implVendor.equals(AUTHOR) ){ - errmsg = "パッケージ定義とベンダが一致しません。" - +"["+ implVendor +"]≠["+ AUTHOR +"]"; - } - - if(errmsg != null){ - JOptionPane.showMessageDialog(null, - errmsg, - "ビルドエラー", - JOptionPane.ERROR_MESSAGE); - RUNTIME.exit(1); - } - - return; - } - - /** - * 標準出力端末にヘルプメッセージ(オプションの説明)を表示する。 - */ - private static void showHelpMessage(){ - System.out.flush(); - System.err.flush(); - - CharSequence helpText = CmdOption.getHelpText(); - System.out.print(helpText); - - System.out.flush(); - System.err.flush(); - - return; - } - - /** - * スプラッシュウィンドウを作成する。 - * JRE1.6以降では呼ばれないはず。 - * @return 未表示のスプラッシュウィンドウ。 - */ - private static Window createSplashWindow(){ - Window splashWindow = new JWindow(); - - URL url = getResource(RES_LOGOICON); - ImageIcon logo = new ImageIcon(url); - JLabel splashLabel = new JLabel(logo); - - splashWindow.add(splashLabel); - splashWindow.pack(); - splashWindow.setLocationRelativeTo(null); // locate center - - return splashWindow; - } - - /** - * ロギング初期化。 - * @param useConsoleLog trueならConsoleHandlerを使う。 - */ - private static void initLogging(boolean useConsoleLog){ - boolean hasPermission = hasLoggingPermission(); - - if( ! hasPermission){ - System.out.println( - "セキュリティ設定により、" - + "ログ設定を変更できませんでした" ); - } - - Logger jre14Logger = COMMON_LOGGER.getJre14Logger(); - - if(hasPermission){ - jre14Logger.setUseParentHandlers(false); - Handler pileHandler = new PileHandler(); - jre14Logger.addHandler(pileHandler); - } - - if(hasPermission && useConsoleLog){ - Handler consoleHandler = new ConsoleHandler(); - jre14Logger.addHandler(consoleHandler); - } - - return; - } - - /** - * ログ操作のアクセス権があるか否か判定する。 - * @return アクセス権があればtrue - */ - public static boolean hasLoggingPermission(){ - if(SEC_MANAGER == null) return true; - - Permission logPermission = new LoggingPermission("control", null); - try{ - SEC_MANAGER.checkPermission(logPermission); - }catch(SecurityException e){ - return false; - } - - return true; - } - - /** - * 起動時の諸々の情報をログ出力する。 - */ - private static void dumpBootInfo(){ - DateFormat dform = DateFormat.getDateTimeInstance(); - NumberFormat nform = NumberFormat.getNumberInstance(); - - logger().info( - ID + " は " - + dform.format(new Date(EPOCHMS_LOADED)) - + " にVM上のクラス " - + SELF_KLASS.getName() + " としてロードされました。 " ); - - logger().info("Initial Nano-Count : " + nform.format(NANOCT_LOADED)); - - logger().info( - "Max-heap : " - + nform.format(RUNTIME.maxMemory()) + " Byte" - + " Total-heap : " - + nform.format(RUNTIME.totalMemory()) + " Byte"); - - logger().info("\n" + EnvInfo.getVMInfo()); - - if(getAppSetting().useConfigPath()){ - logger().info("設定格納ディレクトリに[ " - + getAppSetting().getConfigPath().getPath() - + " ]が指定されました。"); - }else{ - logger().info("設定格納ディレクトリは使いません。"); - } - - if( JRE_PACKAGE.isCompatibleWith("1.6") - && option.hasOption(CmdOption.OPT_NOSPLASH) ){ - logger().warn( - "JRE1.6以降では、" - +"Jindolfの-nosplashオプションは無効です。" - + "Java実行系の方でスプラッシュ画面の非表示を" - + "指示してください(おそらく空の-splash:オプション)" ); - } - - if(LOADER == null){ - logger().warn( - "セキュリティ設定により、" - +"クラスローダを取得できませんでした"); - } - - return; - } - - /** - * 任意のクラス群に対して一括ロード/初期化を単一スレッドで順に行う。 - * どーしてもクラス初期化の順序に依存する障害が発生する場合や - * クラス初期化のオーバーヘッドでGUIの操作性が損なわれるときなどにどうぞ。 - * - * @throws java.lang.LinkageError クラス間リンケージエラー。 - * @throws java.lang.ExceptionInInitializerError クラス初期化で異常 - */ - private static void preInitClass() - throws LinkageError, - ExceptionInInitializerError { - Object[] classes = { // Class型 または String型 - "java.lang.Object", - TabBrowser.class, - Discussion.class, - GlyphDraw.class, - java.net.HttpURLConnection.class, - java.text.SimpleDateFormat.class, - Void.class, - }; - - for(Object obj : classes){ - String className; - if(obj instanceof Class){ - className = ((Class)obj).getName(); - }else if(obj instanceof String){ - className = obj.toString(); - }else{ - continue; - } - - try{ - if(LOADER != null){ - Class.forName(className, true, LOADER); - }else{ - Class.forName(className); - } - }catch(ClassNotFoundException e){ - logger().warn("クラスの明示的ロードに失敗しました", e); - continue; - } - } - - return; - } - - /** - * AWTイベントディスパッチスレッド版スタートアップエントリ。 - */ - private static void startGUI(){ - LandsModel model = new LandsModel(); - model.loadLandList(); - - JFrame topFrame = buildMVC(model); - - GUIUtils.modifyWindowAttributes(topFrame, true, false, true); - - topFrame.pack(); - - Dimension initGeometry = - new Dimension(setting.initialFrameWidth(), - setting.initialFrameHeight()); - topFrame.setSize(initGeometry); - - if( setting.initialFrameXpos() <= Integer.MIN_VALUE - || setting.initialFrameYpos() <= Integer.MIN_VALUE ){ - topFrame.setLocationByPlatform(true); - }else{ - topFrame.setLocation(setting.initialFrameXpos(), - setting.initialFrameYpos() ); - } - - topFrame.setVisible(true); - - return; - } - - /** - * モデル・ビュー・コントローラの結合。 - * - * @param model 最上位のデータモデル - * @return アプリケーションのトップフレーム - */ - private static JFrame buildMVC(LandsModel model){ - ActionManager actionManager = new ActionManager(); - TopView topView = new TopView(); - - Controller controller = new Controller(actionManager, topView, model); - - JFrame topFrame = controller.createTopFrame(); - - return topFrame; - } - - /** - * リソースからUTF-8で記述されたテキストデータをロードする。 - * @param resourceName リソース名 - * @return テキスト文字列 - * @throws java.io.IOException 入出力の異常。おそらくビルドミス。 - */ - public static CharSequence loadResourceText(String resourceName) - throws IOException{ - InputStream is; - is = getResourceAsStream(resourceName); - is = new BufferedInputStream(is); - Reader reader = new InputStreamReader(is, "UTF-8"); - LineNumberReader lineReader = new LineNumberReader(reader); - - StringBuilder result = new StringBuilder(); - try{ - for(;;){ - String line = lineReader.readLine(); - if(line == null) break; - if(line.startsWith("#")) continue; - result.append(line).append('\n'); - } - }finally{ - lineReader.close(); - } - - return result; - } - - /** - * クラスローダを介してリソースからの入力を生成する。 - * @param name リソース名 - * @return リソースからの入力 - */ - public static InputStream getResourceAsStream(String name){ - return SELF_KLASS.getResourceAsStream(name); - } - - /** - * クラスローダを介してリソース読み込み用URLを生成する。 - * @param name リソース名 - * @return URL - */ - public static URL getResource(String name){ - return SELF_KLASS.getResource(name); - } - - /** - * 共通ロガーを取得する。 - * @return 共通ロガー - */ - public static LogWrapper logger(){ - return COMMON_LOGGER; - } - - /** - * VMごとプログラムを終了する。 - * ※おそらく随所でシャットダウンフックが起動されるはず。 - * - * @param exitCode 終了コード - * @throws java.lang.SecurityException セキュリティ違反 - */ - public static void exit(int exitCode) throws SecurityException{ - logger().info( - "終了コード[" - + exitCode - + "]でVMごとアプリケーションを終了します。" ); - RUNTIME.runFinalization(); - System.out.flush(); - System.err.flush(); - try{ - RUNTIME.exit(exitCode); - }catch(SecurityException e){ - logger().warn( - "セキュリティ設定により、" - +"VMを終了させることができません。", e); - throw e; - } - return; - } - - /** - * Jindolf のスタートアップエントリ。 - * - * @param args コマンドライン引数 - */ - public static void main(final String[] args){ - // VM内二重起動チェック - boolean hasInvoked = ! INVOKE_FLAG.compareAndSet(false, true); - if(hasInvoked){ - String errmsg = "二度目以降の起動がキャンセルされました。"; - errorDialog("多重起動", errmsg); - - // exitせずに戻るのみ - return; - } - - checkGUIEnvironment(); - - // ここからGUIウィンドウとマウス解禁 - - checkCompileError(); - checkPackageDefinition(); - - try{ - option = OptionInfo.parseOptions(args); - }catch(IllegalArgumentException e){ - String message = e.getLocalizedMessage(); - System.err.println(message); - System.err.println( - "起動オプション一覧は、" - + "起動オプションに「" - + CmdOption.OPT_HELP.toHyphened() - + "」を指定すると確認できます。" ); - Jindolf.RUNTIME.exit(1); - assert false; - return; - } - - if(option.hasOption(CmdOption.OPT_HELP)){ - showHelpMessage(); - RUNTIME.exit(0); - return; - } - - if(option.hasOption(CmdOption.OPT_VERSION)){ - System.out.println(ID); - RUNTIME.exit(0); - return; - } - - // あらゆるSwingコンポーネント操作より前に必要。 - if(option.hasOption(CmdOption.OPT_BOLDMETAL)){ - // もの凄く日本語表示が汚くなるかもよ!注意 - UIManager.put("swing.boldMetal", Boolean.TRUE); - }else{ - UIManager.put("swing.boldMetal", Boolean.FALSE); - } - - // JRE1.5用スプラッシュウィンドウ - Window splashWindow = null; - if( ! JRE_PACKAGE.isCompatibleWith("1.6") - && ! option.hasOption(CmdOption.OPT_NOSPLASH) ){ - splashWindow = createSplashWindow(); - splashWindow.setVisible(true); - Thread.yield(); - } - - setting = new AppSetting(); - setting.applyOptionInfo(option); - - if(option.hasOption(CmdOption.OPT_VMINFO)){ - System.out.println(EnvInfo.getVMInfo()); - } - - initLogging(option.hasOption(CmdOption.OPT_CONSOLELOG)); - // ここからロギング解禁 - // Jindolf.exit()もここから解禁 - - dumpBootInfo(); - - ConfigFile.setupConfigDirectory(); - ConfigFile.setupLockFile(); - // ここから設定格納ディレクトリ解禁 - - setting.loadConfig(); - - RUNTIME.addShutdownHook(new Thread(){ - @Override - public void run(){ - logger().info("シャットダウン処理に入ります…"); - System.out.flush(); - System.err.flush(); - RUNTIME.gc(); - Thread.yield(); - RUNTIME.runFinalization(); // 危険? - Thread.yield(); - return; - } - }); - - preInitClass(); - - GUIUtils.replaceEventQueue(); - - boolean hasError = false; - try{ - EventQueue.invokeAndWait(new Runnable(){ - public void run(){ - startGUI(); - return; - } - }); - }catch(InvocationTargetException e){ - logger().fatal("アプリケーション初期化に失敗しました", e); - e.printStackTrace(System.err); - hasError = true; - }catch(InterruptedException e){ - logger().fatal("アプリケーション初期化に失敗しました", e); - e.printStackTrace(System.err); - hasError = true; - }finally{ - if(splashWindow != null){ - splashWindow.setVisible(false); - splashWindow.dispose(); - splashWindow = null; - } - } - - if(hasError) exit(1); - - return; - } - -} diff --git a/src/main/java/jp/sourceforge/jindolf/OptionInfo.java b/src/main/java/jp/sourceforge/jindolf/OptionInfo.java deleted file mode 100644 index 1d9c6b3..0000000 --- a/src/main/java/jp/sourceforge/jindolf/OptionInfo.java +++ /dev/null @@ -1,295 +0,0 @@ -/* - * option argument information - * - * License : The MIT License - * Copyright(c) 2009 olyutorskii - */ - -package jp.sourceforge.jindolf; - -import java.util.Collections; -import java.util.EnumMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * コマンドラインオプション情報。 - * public static void main()の引数から展開される。 - */ -public class OptionInfo{ - - private static final Pattern PATTERN_GEOMETRY = - Pattern.compile( - "([1-9][0-9]*)x([1-9][0-9]*)" - +"(?:(\\+|\\-)([1-9][0-9]*)(\\+|\\-)([1-9][0-9]*))?" - ); - - - private Integer frameWidth = null; - private Integer frameHeight = null; - private Integer frameXpos = null; - private Integer frameYpos = null; - - private final List invokeArgs = new LinkedList(); - private final List optionList = new LinkedList(); - private final Map boolOptionMap = - new EnumMap(CmdOption.class); - private final Map stringOptionMap = - new EnumMap(CmdOption.class); - - - /** - * コンストラクタ。 - */ - protected OptionInfo(){ - super(); - return; - } - - - /** - * オプション文字列を解析する。 - * @param args main()に渡されるオプション文字列 - * @return 解析済みのオプション情報。 - * @throws IllegalArgumentException 構文エラー - */ - public static OptionInfo parseOptions(String[] args) - throws IllegalArgumentException{ - OptionInfo result = new OptionInfo(); - - result.invokeArgs.clear(); - for(String arg : args){ - if(arg == null) continue; - if(arg.length() <= 0) continue; - result.invokeArgs.add(arg); - } - Iterator iterator = result.invokeArgs.iterator(); - - while(iterator.hasNext()){ - String arg = iterator.next(); - - CmdOption option = CmdOption.parseCmdOption(arg); - if(option == null){ - throw new IllegalArgumentException( - "未定義の起動オプション[" - + arg - + "]が指定されました。"); - } - result.optionList.add(option); - - if(CmdOption.isIndepOption(option)){ - continue; - }else if(CmdOption.isBooleanOption(option)){ - Boolean bool = parseBooleanSwitch(arg, iterator); - result.boolOptionMap.put(option, bool); - continue; - } - - switch(option){ - case OPT_INITFONT: - case OPT_CONFDIR: - checkNextArg(arg, iterator); - result.stringOptionMap.put(option, iterator.next()); - break; - case OPT_GEOMETRY: - checkNextArg(arg, iterator); - String geometry = iterator.next(); - Matcher matcher = PATTERN_GEOMETRY.matcher(geometry); - if( ! matcher.matches() ){ - throw new IllegalArgumentException( - "起動オプション[" - +arg - +"]の引数形式[" - +geometry - +"]が不正です。" ); - } - String width = matcher.group(1); - String height = matcher.group(2); - String xSign = matcher.group(3); - String xPos = matcher.group(4); - String ySign = matcher.group(5); - String yPos = matcher.group(6); - try{ - result.frameWidth = Integer.parseInt(width); - result.frameHeight = Integer.parseInt(height); - if(xPos != null && xPos.length() > 0){ - result.frameXpos = Integer.parseInt(xPos); - if(xSign.equals("-")){ - result.frameXpos = -result.frameXpos; - } - } - if(yPos != null && yPos.length() > 0){ - result.frameYpos = Integer.parseInt(yPos); - if(ySign.equals("-")){ - result.frameYpos = -result.frameYpos; - } - } - }catch(NumberFormatException e){ - assert false; - throw new IllegalArgumentException(e); - } - - break; - default: - assert false; - break; - } - } - - return result; - } - - /** - * 真偽二値をとるオプション解析の下請け。 - * @param option オプション名 - * @param iterator 引数並び - * @return 真偽 - * @throws IllegalArgumentException 構文エラー - */ - private static Boolean parseBooleanSwitch( - String option, Iterator iterator ) - throws IllegalArgumentException{ - Boolean result; - checkNextArg(option, iterator); - String onoff = iterator.next(); - if( onoff.compareToIgnoreCase("on" ) == 0 - || onoff.compareToIgnoreCase("yes" ) == 0 - || onoff.compareToIgnoreCase("true") == 0){ - result = Boolean.TRUE; - }else if( onoff.compareToIgnoreCase("off" ) == 0 - || onoff.compareToIgnoreCase("no" ) == 0 - || onoff.compareToIgnoreCase("false") == 0){ - result = Boolean.FALSE; - }else{ - throw new IllegalArgumentException( - "起動オプション[" - +option - +"]の引数形式[" - +onoff - +"]が不正です。" - +"on, off, yes, no, true, false" - +"のいずれかを指定してください。"); - } - return result; - } - - /** - * 追加引数を持つオプションのチェック。 - * @param option オプション名 - * @param iterator 引数並び - * @throws IllegalArgumentException 構文エラー - */ - private static void checkNextArg(CharSequence option, - Iterator iterator ) - throws IllegalArgumentException{ - if( ! iterator.hasNext() ){ - throw new IllegalArgumentException( - "起動オプション[" - +option - +"]に引数がありません。"); - } - return; - } - - - /** - * 全引数のリストを返す。 - * @return 全引数のリスト - */ - public List getInvokeArgList(){ - return Collections.unmodifiableList(this.invokeArgs); - } - - /** - * オプションが指定されていたか否か判定する。 - * @param option オプション - * @return 指定されていたらtrue - */ - public boolean hasOption(CmdOption option){ - if(this.optionList.contains(option)) return true; - return false; - } - - /** - * 真偽値をとるオプション値を返す。 - * 複数回指定された場合は最後の値。 - * @param option オプション - * @return 真偽値。オプション指定がなかった場合はnull - * @throws IllegalArgumentException 真偽値を取るオプションではない。 - */ - public Boolean getBooleanArg(CmdOption option) - throws IllegalArgumentException{ - if( ! CmdOption.isBooleanOption(option) ){ - throw new IllegalArgumentException(); - } - Boolean result = this.boolOptionMap.get(option); - return result; - } - - /** - * 文字列引数をとるオプション値を返す。 - * 複数回指定された場合は最後の値。 - * @param option オプション - * @return 文字列。オプション指定がなかった場合はnull - */ - public String getStringArg(CmdOption option){ - String result = this.stringOptionMap.get(option); - return result; - } - - /** - * 排他的オプションのいずれかが指定されたか判定する。 - * 後から指定された方が有効となる。 - * @param options 排他的オプション群 - * @return いずれかのオプション。どれも指定されなければnull - */ - public CmdOption getExclusiveOption(CmdOption... options){ - CmdOption result = null; - for(CmdOption option : this.optionList){ - for(CmdOption excOption : options){ - if(option == excOption){ - result = option; - break; - } - } - } - return result; - } - - /** - * 初期のフレーム幅を返す。 - * @return 初期のフレーム幅。オプション指定されてなければnull - */ - public Integer initialFrameWidth(){ - return this.frameWidth; - } - - /** - * 初期のフレーム高を返す。 - * @return 初期のフレーム高。オプション指定されてなければnull - */ - public Integer initialFrameHeight(){ - return this.frameHeight; - } - - /** - * 初期のフレーム位置のX座標を返す。 - * @return 初期のフレーム位置のX座標。オプション指定されてなければnull - */ - public Integer initialFrameXpos(){ - return this.frameXpos; - } - - /** - * 初期のフレーム位置のY座標を返す。 - * @return 初期のフレーム位置のY座標。オプション指定されてなければnull - */ - public Integer initialFrameYpos(){ - return this.frameYpos; - } - -} diff --git a/src/main/resources/jp/sourceforge/jindolf/resources/preview.txt b/src/main/resources/jp/sfjp/jindolf/resources/font/preview.txt similarity index 100% rename from src/main/resources/jp/sourceforge/jindolf/resources/preview.txt rename to src/main/resources/jp/sfjp/jindolf/resources/font/preview.txt diff --git a/src/main/resources/jp/sourceforge/jindolf/resources/help.txt b/src/main/resources/jp/sfjp/jindolf/resources/help.txt similarity index 100% rename from src/main/resources/jp/sourceforge/jindolf/resources/help.txt rename to src/main/resources/jp/sfjp/jindolf/resources/help.txt diff --git a/src/main/resources/jp/sourceforge/jindolf/resources/html/help.css b/src/main/resources/jp/sfjp/jindolf/resources/html/help.css similarity index 100% rename from src/main/resources/jp/sourceforge/jindolf/resources/html/help.css rename to src/main/resources/jp/sfjp/jindolf/resources/html/help.css diff --git a/src/main/resources/jp/sourceforge/jindolf/resources/html/help.html b/src/main/resources/jp/sfjp/jindolf/resources/html/help.html similarity index 100% rename from src/main/resources/jp/sourceforge/jindolf/resources/html/help.html rename to src/main/resources/jp/sfjp/jindolf/resources/html/help.html diff --git a/src/main/resources/jp/sourceforge/jindolf/resources/html/keyassign.html b/src/main/resources/jp/sfjp/jindolf/resources/html/keyassign.html similarity index 100% rename from src/main/resources/jp/sourceforge/jindolf/resources/html/keyassign.html rename to src/main/resources/jp/sfjp/jindolf/resources/html/keyassign.html diff --git a/src/main/resources/jp/sourceforge/jindolf/resources/html/license.html b/src/main/resources/jp/sfjp/jindolf/resources/html/license.html similarity index 100% rename from src/main/resources/jp/sourceforge/jindolf/resources/html/license.html rename to src/main/resources/jp/sfjp/jindolf/resources/html/license.html diff --git a/src/main/resources/jp/sourceforge/jindolf/resources/html/options.html b/src/main/resources/jp/sfjp/jindolf/resources/html/options.html similarity index 100% rename from src/main/resources/jp/sourceforge/jindolf/resources/html/options.html rename to src/main/resources/jp/sfjp/jindolf/resources/html/options.html diff --git a/src/main/resources/jp/sourceforge/jindolf/resources/image/logo.png b/src/main/resources/jp/sfjp/jindolf/resources/image/logo.png similarity index 100% rename from src/main/resources/jp/sourceforge/jindolf/resources/image/logo.png rename to src/main/resources/jp/sfjp/jindolf/resources/image/logo.png diff --git a/src/main/resources/jp/sourceforge/jindolf/resources/image/noimage.png b/src/main/resources/jp/sfjp/jindolf/resources/image/noimage.png similarity index 100% rename from src/main/resources/jp/sourceforge/jindolf/resources/image/noimage.png rename to src/main/resources/jp/sfjp/jindolf/resources/image/noimage.png diff --git a/src/main/resources/jp/sourceforge/jindolf/resources/image/ascend.png b/src/main/resources/jp/sfjp/jindolf/resources/image/tb_ascend.png similarity index 100% rename from src/main/resources/jp/sourceforge/jindolf/resources/image/ascend.png rename to src/main/resources/jp/sfjp/jindolf/resources/image/tb_ascend.png diff --git a/src/main/resources/jp/sourceforge/jindolf/resources/image/descend.png b/src/main/resources/jp/sfjp/jindolf/resources/image/tb_descend.png similarity index 100% rename from src/main/resources/jp/sourceforge/jindolf/resources/image/descend.png rename to src/main/resources/jp/sfjp/jindolf/resources/image/tb_descend.png diff --git a/src/main/resources/jp/sourceforge/jindolf/resources/image/editor.png b/src/main/resources/jp/sfjp/jindolf/resources/image/tb_editor.png similarity index 100% rename from src/main/resources/jp/sourceforge/jindolf/resources/image/editor.png rename to src/main/resources/jp/sfjp/jindolf/resources/image/tb_editor.png diff --git a/src/main/resources/jp/sourceforge/jindolf/resources/image/filter.png b/src/main/resources/jp/sfjp/jindolf/resources/image/tb_filter.png similarity index 100% rename from src/main/resources/jp/sourceforge/jindolf/resources/image/filter.png rename to src/main/resources/jp/sfjp/jindolf/resources/image/tb_filter.png diff --git a/src/main/resources/jp/sourceforge/jindolf/resources/image/find.png b/src/main/resources/jp/sfjp/jindolf/resources/image/tb_find.png similarity index 100% rename from src/main/resources/jp/sourceforge/jindolf/resources/image/find.png rename to src/main/resources/jp/sfjp/jindolf/resources/image/tb_find.png diff --git a/src/main/resources/jp/sourceforge/jindolf/resources/image/findnext.png b/src/main/resources/jp/sfjp/jindolf/resources/image/tb_findnext.png similarity index 100% rename from src/main/resources/jp/sourceforge/jindolf/resources/image/findnext.png rename to src/main/resources/jp/sfjp/jindolf/resources/image/tb_findnext.png diff --git a/src/main/resources/jp/sourceforge/jindolf/resources/image/findprev.png b/src/main/resources/jp/sfjp/jindolf/resources/image/tb_findprev.png similarity index 100% rename from src/main/resources/jp/sourceforge/jindolf/resources/image/findprev.png rename to src/main/resources/jp/sfjp/jindolf/resources/image/tb_findprev.png diff --git a/src/main/resources/jp/sourceforge/jindolf/resources/image/reload.png b/src/main/resources/jp/sfjp/jindolf/resources/image/tb_reload.png similarity index 100% rename from src/main/resources/jp/sourceforge/jindolf/resources/image/reload.png rename to src/main/resources/jp/sfjp/jindolf/resources/image/tb_reload.png diff --git a/src/main/resources/jp/sourceforge/jindolf/resources/image/cross.png b/src/main/resources/jp/sfjp/jindolf/resources/image/vs_cross.png similarity index 100% rename from src/main/resources/jp/sourceforge/jindolf/resources/image/cross.png rename to src/main/resources/jp/sfjp/jindolf/resources/image/vs_cross.png diff --git a/src/main/resources/jp/sourceforge/jindolf/resources/image/epilogue.png b/src/main/resources/jp/sfjp/jindolf/resources/image/vs_epilogue.png similarity index 100% rename from src/main/resources/jp/sourceforge/jindolf/resources/image/epilogue.png rename to src/main/resources/jp/sfjp/jindolf/resources/image/vs_epilogue.png diff --git a/src/main/resources/jp/sourceforge/jindolf/resources/image/gameover.png b/src/main/resources/jp/sfjp/jindolf/resources/image/vs_gameover.png similarity index 100% rename from src/main/resources/jp/sourceforge/jindolf/resources/image/gameover.png rename to src/main/resources/jp/sfjp/jindolf/resources/image/vs_gameover.png diff --git a/src/main/resources/jp/sourceforge/jindolf/resources/image/progress.png b/src/main/resources/jp/sfjp/jindolf/resources/image/vs_progress.png similarity index 100% rename from src/main/resources/jp/sourceforge/jindolf/resources/image/progress.png rename to src/main/resources/jp/sfjp/jindolf/resources/image/vs_progress.png diff --git a/src/main/resources/jp/sourceforge/jindolf/resources/image/prologue.png b/src/main/resources/jp/sfjp/jindolf/resources/image/vs_prologue.png similarity index 100% rename from src/main/resources/jp/sourceforge/jindolf/resources/image/prologue.png rename to src/main/resources/jp/sfjp/jindolf/resources/image/vs_prologue.png diff --git a/src/main/resources/jp/sourceforge/jindolf/resources/image/winicon.png b/src/main/resources/jp/sfjp/jindolf/resources/image/winicon.png similarity index 100% rename from src/main/resources/jp/sourceforge/jindolf/resources/image/winicon.png rename to src/main/resources/jp/sfjp/jindolf/resources/image/winicon.png diff --git a/src/main/resources/jp/sourceforge/jindolf/resources/image/www.png b/src/main/resources/jp/sfjp/jindolf/resources/image/www.png similarity index 100% rename from src/main/resources/jp/sourceforge/jindolf/resources/image/www.png rename to src/main/resources/jp/sfjp/jindolf/resources/image/www.png diff --git a/src/main/resources/jp/sfjp/jindolf/resources/version.properties b/src/main/resources/jp/sfjp/jindolf/resources/version.properties new file mode 100644 index 0000000..7f74c02 --- /dev/null +++ b/src/main/resources/jp/sfjp/jindolf/resources/version.properties @@ -0,0 +1,12 @@ +# Version definition +# [ with Maven resource filtering ] + +pkg-title.jp.sfjp.jindolf = ${pom.name} +pkg-version.jp.sfjp.jindolf = ${pom.version} +pkg-author.jp.sfjp.jindolf = olyutorskii +pkg-license.jp.sfjp.jindolf = The MIT License +pkg-contact.jp.sfjp.jindolf = ${pom.url} +pkg-inception.jp.sfjp.jindolf = ${pom.inceptionYear} +pkg-comment.jp.sfjp.jindolf = + +# EOF # diff --git a/src/main/resources/jp/sourceforge/jindolf/resources/faceIconSet.properties b/src/main/resources/jp/sfjp/jindolf/resources/wolfbbs/faceIconSet.properties similarity index 100% rename from src/main/resources/jp/sourceforge/jindolf/resources/faceIconSet.properties rename to src/main/resources/jp/sfjp/jindolf/resources/wolfbbs/faceIconSet.properties diff --git a/src/main/resources/jp/sourceforge/jindolf/resources/version.properties b/src/main/resources/jp/sourceforge/jindolf/resources/version.properties deleted file mode 100644 index efae2b4..0000000 --- a/src/main/resources/jp/sourceforge/jindolf/resources/version.properties +++ /dev/null @@ -1,12 +0,0 @@ -# Version definition -# [ with Maven resource filtering ] - -pkg-title.jp.sourceforge.jindolf = ${pom.name} -pkg-version.jp.sourceforge.jindolf = ${pom.version} -pkg-author.jp.sourceforge.jindolf = olyutorskii -pkg-license.jp.sourceforge.jindolf = The MIT License -pkg-contact.jp.sourceforge.jindolf = ${pom.url} -pkg-debut.jp.sourceforge.jindolf = ${pom.inceptionYear} -pkg-comment.jp.sourceforge.jindolf = - -# EOF # diff --git a/src/test/java/jp/sfjp/jindolf/config/CmdOptionTest.java b/src/test/java/jp/sfjp/jindolf/config/CmdOptionTest.java new file mode 100644 index 0000000..6a87a14 --- /dev/null +++ b/src/test/java/jp/sfjp/jindolf/config/CmdOptionTest.java @@ -0,0 +1,237 @@ +/* + * CmdOption test + * + * Copyright 2012 olyutorskii + */ + +package jp.sfjp.jindolf.config; + +import java.util.List; +import java.util.Arrays; +import java.util.LinkedList; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * + */ +public class CmdOptionTest { + + public CmdOptionTest() { + } + + @BeforeClass + public static void setUpClass() throws Exception { + } + + @AfterClass + public static void tearDownClass() throws Exception { + } + + @Before + public void setUp() { + } + + @After + public void tearDown() { + } + + /** + * Test of values method, of class CmdOption. + */ + @Test + public void testValues() { + System.out.println("values"); + + CmdOption[] values = CmdOption.values(); + + assertEquals(12, values.length); + + List list = Arrays.asList(values); + + List testList = new LinkedList(); + testList.add(CmdOption.OPT_HELP); + testList.add(CmdOption.OPT_VERSION); + testList.add(CmdOption.OPT_BOLDMETAL); + testList.add(CmdOption.OPT_NOSPLASH); + testList.add(CmdOption.OPT_GEOMETRY); + testList.add(CmdOption.OPT_VMINFO); + testList.add(CmdOption.OPT_CONSOLELOG); + testList.add(CmdOption.OPT_INITFONT); + testList.add(CmdOption.OPT_ANTIALIAS); + testList.add(CmdOption.OPT_FRACTIONAL); + testList.add(CmdOption.OPT_CONFDIR); + testList.add(CmdOption.OPT_NOCONF); + + assertTrue(list.containsAll(testList)); + assertTrue(testList.containsAll(list)); + assertEquals(testList.size(), list.size()); + + return; + } + + /** + * Test of valueOf method, of class CmdOption. + */ + @Test + public void testValueOf() { + System.out.println("valueOf"); + + CmdOption expResult; + CmdOption result; + + expResult = CmdOption.OPT_HELP; + result = CmdOption.valueOf("OPT_HELP"); + assertEquals(expResult, result); + + try{ + CmdOption.valueOf("X"); + fail(); + }catch(IllegalArgumentException e){ + // GOOD + } + + return; + } + + /** + * Test of getHelpText method, of class CmdOption. + */ + @Test + public void testGetHelpText() { + System.out.println("getHelpText"); + + CharSequence result = CmdOption.getHelpText(); + + assertNotNull(result); + assertTrue(result.length() > 0); + assertTrue(result.toString().endsWith("\n")); + + return; + } + + /** + * Test of parseCmdOption method, of class CmdOption. + */ + @Test + public void testParseCmdOption() { + System.out.println("parseCmdOption"); + + assertNull(CmdOption.parseCmdOption("")); + assertNull(CmdOption.parseCmdOption("X")); + + assertEquals(CmdOption.OPT_HELP, CmdOption.parseCmdOption("-help")); + assertEquals(CmdOption.OPT_HELP, CmdOption.parseCmdOption("-?")); + + assertEquals(CmdOption.OPT_NOCONF, + CmdOption.parseCmdOption("-noconfdir")); + + return; + } + + /** + * Test of matches method, of class CmdOption. + */ + @Test + public void testMatches() { + System.out.println("matches"); + + assertFalse(CmdOption.OPT_HELP.matches("")); + assertFalse(CmdOption.OPT_HELP.matches("help")); + + assertTrue(CmdOption.OPT_HELP.matches("-help")); + assertTrue(CmdOption.OPT_HELP.matches("-h")); + assertTrue(CmdOption.OPT_HELP.matches("--help")); + assertTrue(CmdOption.OPT_HELP.matches("-?")); + + assertTrue(CmdOption.OPT_VERSION.matches("-version")); + assertTrue(CmdOption.OPT_BOLDMETAL.matches("-boldMetal")); + assertTrue(CmdOption.OPT_NOSPLASH.matches("-nosplash")); + assertTrue(CmdOption.OPT_GEOMETRY.matches("-geometry")); + assertTrue(CmdOption.OPT_VMINFO.matches("-vminfo")); + assertTrue(CmdOption.OPT_CONSOLELOG.matches("-consolelog")); + assertTrue(CmdOption.OPT_INITFONT.matches("-initfont")); + assertTrue(CmdOption.OPT_ANTIALIAS.matches("-antialias")); + assertTrue(CmdOption.OPT_FRACTIONAL.matches("-fractional")); + assertTrue(CmdOption.OPT_CONFDIR.matches("-confdir")); + assertTrue(CmdOption.OPT_NOCONF.matches("-noconfdir")); + + return; + } + + /** + * Test of isIndepOption method, of class CmdOption. + */ + @Test + public void testIsIndepOption() { + System.out.println("isIndepOption"); + + for(CmdOption opt : CmdOption.values()){ + switch(opt){ + case OPT_HELP: + case OPT_VERSION: + case OPT_VMINFO: + case OPT_BOLDMETAL: + case OPT_NOSPLASH: + case OPT_CONSOLELOG: + case OPT_NOCONF: + assertTrue(opt.isIndepOption()); + break; + default: + assertFalse(opt.isIndepOption()); + break; + } + } + + return; + } + + /** + * Test of isBooleanOption method, of class CmdOption. + */ + @Test + public void testIsBooleanOption() { + System.out.println("isBooleanOption"); + + for(CmdOption opt : CmdOption.values()){ + switch(opt){ + case OPT_ANTIALIAS: + case OPT_FRACTIONAL: + assertTrue(opt.isBooleanOption()); + break; + default: + assertFalse(opt.isBooleanOption()); + break; + } + } + + return; + } + + /** + * Test of toString method, of class CmdOption. + */ + @Test + public void testToString() { + System.out.println("toString"); + + assertEquals("-help", CmdOption.OPT_HELP.toString()); + assertEquals("-version", CmdOption.OPT_VERSION.toString()); + assertEquals("-boldMetal", CmdOption.OPT_BOLDMETAL.toString()); + assertEquals("-nosplash", CmdOption.OPT_NOSPLASH.toString()); + assertEquals("-geometry", CmdOption.OPT_GEOMETRY.toString()); + assertEquals("-vminfo", CmdOption.OPT_VMINFO.toString()); + assertEquals("-consolelog", CmdOption.OPT_CONSOLELOG.toString()); + assertEquals("-initfont", CmdOption.OPT_INITFONT.toString()); + assertEquals("-antialias", CmdOption.OPT_ANTIALIAS.toString()); + assertEquals("-fractional", CmdOption.OPT_FRACTIONAL.toString()); + assertEquals("-confdir", CmdOption.OPT_CONFDIR.toString()); + assertEquals("-noconfdir", CmdOption.OPT_NOCONF.toString()); + + return; + } +} diff --git a/src/test/java/jp/sfjp/jindolf/config/OptionInfoTest.java b/src/test/java/jp/sfjp/jindolf/config/OptionInfoTest.java new file mode 100644 index 0000000..0fbff02 --- /dev/null +++ b/src/test/java/jp/sfjp/jindolf/config/OptionInfoTest.java @@ -0,0 +1,378 @@ +/* + * OptionInfo test + * + * Copyright 2012 olyutorskii + */ + +package jp.sfjp.jindolf.config; + +import java.util.List; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * + */ +public class OptionInfoTest { + + public OptionInfoTest() { + } + + @BeforeClass + public static void setUpClass() throws Exception { + } + + @AfterClass + public static void tearDownClass() throws Exception { + } + + @Before + public void setUp() { + } + + @After + public void tearDown() { + } + + /** + * Test of parseOptions method, of class OptionInfo. + */ + @Test + public void testParseOptions() { + System.out.println("parseOptions"); + + OptionInfo result; + + result = OptionInfo.parseOptions(); + assertNotNull(result); + + result = OptionInfo.parseOptions(null, null); + assertNotNull(result); + assertTrue(result.getInvokeArgList().isEmpty()); + + result = OptionInfo.parseOptions(new String[]{}); + assertNotNull(result); + + result = OptionInfo.parseOptions("-help"); + assertNotNull(result); + + try{ + result = OptionInfo.parseOptions("X"); + fail(); + }catch(IllegalArgumentException e){ + assertEquals("未定義の起動オプション[X]が指定されました。", + e.getMessage() ); + } + + try{ + result = OptionInfo.parseOptions(""); + fail(); + }catch(IllegalArgumentException e){ + assertEquals("未定義の起動オプション[]が指定されました。", + e.getMessage() ); + } + + return; + } + + /** + * Test of getInvokeArgList method, of class OptionInfo. + */ + @Test + public void testGetInvokeArgList() { + System.out.println("getInvokeArgList"); + + OptionInfo result; + List list; + + result = OptionInfo.parseOptions(); + list = result.getInvokeArgList(); + assertTrue(list.isEmpty()); + + result = OptionInfo.parseOptions("-help"); + list = result.getInvokeArgList(); + assertEquals(1, list.size()); + assertEquals("-help", list.get(0)); + + result = OptionInfo.parseOptions("-initfont", "on", "-help"); + list = result.getInvokeArgList(); + assertEquals(3, list.size()); + assertEquals("-initfont", list.get(0)); + assertEquals("on", list.get(1)); + assertEquals("-help", list.get(2)); + + return; + } + + /** + * Test of hasOption method, of class OptionInfo. + */ + @Test + public void testHasOption() { + System.out.println("hasOption"); + + OptionInfo result; + + result = OptionInfo.parseOptions(); + assertFalse(result.hasOption(CmdOption.OPT_HELP)); + assertFalse(result.hasOption(CmdOption.OPT_INITFONT)); + + result = OptionInfo.parseOptions("-help"); + assertTrue(result.hasOption(CmdOption.OPT_HELP)); + assertFalse(result.hasOption(CmdOption.OPT_INITFONT)); + + result = OptionInfo.parseOptions("-initfont", "on", "-help"); + assertTrue(result.hasOption(CmdOption.OPT_HELP)); + assertTrue(result.hasOption(CmdOption.OPT_INITFONT)); + + result = OptionInfo.parseOptions("-initfont", "off", "-help"); + assertTrue(result.hasOption(CmdOption.OPT_HELP)); + assertTrue(result.hasOption(CmdOption.OPT_INITFONT)); + + return; + } + + /** + * Test of getBooleanArg method, of class OptionInfo. + */ + @Test + public void testGetBooleanArg() { + System.out.println("getBooleanArg"); + + OptionInfo result; + + try{ + result = OptionInfo.parseOptions("-antialias"); + fail(); + }catch(IllegalArgumentException e){ + String expMsg = + "起動オプション[-antialias]に引数がありません。"; + assertEquals(expMsg, e.getMessage()); + } + + try{ + result = OptionInfo.parseOptions("-fractional"); + fail(); + }catch(IllegalArgumentException e){ + String expMsg = + "起動オプション[-fractional]に引数がありません。"; + assertEquals(expMsg, e.getMessage()); + } + + result = OptionInfo.parseOptions("-help"); + try{ + result.getBooleanArg(CmdOption.OPT_HELP); + fail(); + }catch(IllegalArgumentException e){ + String expMsg = + "起動オプション[-help]は" + + "真偽を指定するオプションではありません。"; + assertEquals(expMsg, e.getMessage()); + } + + result = OptionInfo.parseOptions(); + assertNull(result.getBooleanArg(CmdOption.OPT_ANTIALIAS)); + assertNull(result.getBooleanArg(CmdOption.OPT_FRACTIONAL)); + + + String[] flags; + + flags = new String[]{"on", "yes", "true", "ON", "YES", "TRUE"}; + for(String flag : flags){ + result = OptionInfo.parseOptions("-antialias", flag); + assertTrue(result.getBooleanArg(CmdOption.OPT_ANTIALIAS)); + result = OptionInfo.parseOptions("-fractional", flag); + assertTrue(result.getBooleanArg(CmdOption.OPT_FRACTIONAL)); + } + + flags = new String[]{"off", "no", "false", "OFF", "NO", "FALSE"}; + for(String flag : flags){ + result = OptionInfo.parseOptions("-antialias", flag); + assertFalse(result.getBooleanArg(CmdOption.OPT_ANTIALIAS)); + result = OptionInfo.parseOptions("-fractional", flag); + assertFalse(result.getBooleanArg(CmdOption.OPT_FRACTIONAL)); + } + + try{ + result = OptionInfo.parseOptions("-antialias", "X"); + fail(); + }catch(IllegalArgumentException e){ + String expMsg = + "起動オプション[-antialias]の真偽指定[X]が不正です。" + + "on, off, yes, no, true, false" + + "のいずれかを指定してください。"; + assertEquals(expMsg, e.getMessage()); + } + + try{ + result = OptionInfo.parseOptions("-fractional", "X"); + fail(); + }catch(IllegalArgumentException e){ + String expMsg = + "起動オプション[-fractional]の真偽指定[X]が不正です。" + + "on, off, yes, no, true, false" + + "のいずれかを指定してください。"; + assertEquals(expMsg, e.getMessage()); + } + + result = OptionInfo.parseOptions("-antialias", "on", + "-antialias", "off" ); + assertFalse(result.getBooleanArg(CmdOption.OPT_ANTIALIAS)); + + return; + } + + /** + * Test of getStringArg method, of class OptionInfo. + */ + @Test + public void testGetStringArg() { + System.out.println("getStringArg"); + + OptionInfo result; + + try{ + result = OptionInfo.parseOptions("-initfont"); + fail(); + }catch(IllegalArgumentException e){ + String expMsg = + "起動オプション[-initfont]に引数がありません。"; + assertEquals(expMsg, e.getMessage()); + } + + try{ + result = OptionInfo.parseOptions("-confdir"); + fail(); + }catch(IllegalArgumentException e){ + String expMsg = + "起動オプション[-confdir]に引数がありません。"; + assertEquals(expMsg, e.getMessage()); + } + + result = OptionInfo.parseOptions(); + assertNull(result.getStringArg(CmdOption.OPT_INITFONT)); + assertNull(result.getStringArg(CmdOption.OPT_CONFDIR)); + + result = OptionInfo.parseOptions("-initfont", "Monospaced-PLAIN-16"); + assertEquals("Monospaced-PLAIN-16", + result.getStringArg(CmdOption.OPT_INITFONT)); + + result = OptionInfo.parseOptions("-confdir", "/tmp/x"); + assertEquals("/tmp/x", + result.getStringArg(CmdOption.OPT_CONFDIR)); + + result = OptionInfo.parseOptions("-confdir", "/tmp/x", + "-confdir", "/tmp/y" ); + assertEquals("/tmp/y", + result.getStringArg(CmdOption.OPT_CONFDIR)); + + return; + } + + /** + * Test of getExclusiveOption method, of class OptionInfo. + */ + @Test + public void testGetExclusiveOption() { + System.out.println("getExclusiveOption"); + + OptionInfo result; + CmdOption opt; + + result = OptionInfo.parseOptions(); + opt = result.getExclusiveOption(CmdOption.OPT_CONFDIR, + CmdOption.OPT_NOCONF ); + assertNull(opt); + + result = OptionInfo.parseOptions("-help"); + opt = result.getExclusiveOption(CmdOption.OPT_CONFDIR, + CmdOption.OPT_NOCONF ); + assertNull(opt); + + result = OptionInfo.parseOptions("-confdir", "/tmp/x"); + opt = result.getExclusiveOption(CmdOption.OPT_CONFDIR, + CmdOption.OPT_NOCONF ); + assertSame(CmdOption.OPT_CONFDIR, opt); + + result = OptionInfo.parseOptions("-noconfdir"); + opt = result.getExclusiveOption(CmdOption.OPT_CONFDIR, + CmdOption.OPT_NOCONF ); + assertSame(CmdOption.OPT_NOCONF, opt); + + result = OptionInfo.parseOptions("-confdir", "/tmp/x", + "-noconfdir" ); + opt = result.getExclusiveOption(CmdOption.OPT_CONFDIR, + CmdOption.OPT_NOCONF ); + assertSame(CmdOption.OPT_NOCONF, opt); + + result = OptionInfo.parseOptions("-noconfdir", + "-confdir", "/tmp/x" ); + opt = result.getExclusiveOption(CmdOption.OPT_CONFDIR, + CmdOption.OPT_NOCONF ); + assertSame(CmdOption.OPT_CONFDIR, opt); + + return; + } + + /** + * Test of geometry option, of class OptionInfo. + */ + @Test + public void testGeometry() { + System.out.println("initialFrameWidth"); + + OptionInfo result; + + result = OptionInfo.parseOptions(); + assertNull(result.initialFrameWidth()); + assertNull(result.initialFrameHeight()); + assertNull(result.initialFrameXpos()); + assertNull(result.initialFrameYpos()); + + try{ + result = OptionInfo.parseOptions("-geometry"); + fail(); + }catch(IllegalArgumentException e){ + String expMsg = + "起動オプション[-geometry]に引数がありません。"; + assertEquals(expMsg, e.getMessage()); + } + + try{ + result = OptionInfo.parseOptions("-geometry", "Q"); + fail(); + }catch(IllegalArgumentException e){ + String expMsg = + "起動オプション[-geometry]の" + + "ジオメトリ指定[Q]が不正です。" + + "WIDTHxHEIGHT[(+|-)XPOS(+|-)YPOS]" + + "の形式で指定してください"; + assertEquals(expMsg, e.getMessage()); + } + + result = OptionInfo.parseOptions("-geometry", "800x600"); + assertEquals(800, result.initialFrameWidth().intValue()); + assertEquals(600, result.initialFrameHeight().intValue()); + assertNull(result.initialFrameXpos()); + assertNull(result.initialFrameYpos()); + + result = OptionInfo.parseOptions("-geometry", "800x600+100+200"); + assertEquals(800, result.initialFrameWidth().intValue()); + assertEquals(600, result.initialFrameHeight().intValue()); + assertEquals(100, result.initialFrameXpos().intValue()); + assertEquals(200, result.initialFrameYpos().intValue()); + + result = OptionInfo.parseOptions("-geometry", "800x600-100-200"); + assertEquals(800, result.initialFrameWidth().intValue()); + assertEquals(600, result.initialFrameHeight().intValue()); + assertEquals(-100, result.initialFrameXpos().intValue()); + assertEquals(-200, result.initialFrameYpos().intValue()); + + return; + } + +} diff --git a/src/test/java/jp/sourceforge/jindolf/AvatarTest.java b/src/test/java/jp/sfjp/jindolf/data/AvatarTest.java similarity index 99% rename from src/test/java/jp/sourceforge/jindolf/AvatarTest.java rename to src/test/java/jp/sfjp/jindolf/data/AvatarTest.java index 79557c4..4d65e74 100644 --- a/src/test/java/jp/sourceforge/jindolf/AvatarTest.java +++ b/src/test/java/jp/sfjp/jindolf/data/AvatarTest.java @@ -4,7 +4,7 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.data; import java.util.List; import java.util.regex.Matcher; diff --git a/src/test/java/jp/sourceforge/jindolf/HttpUtilsTest.java b/src/test/java/jp/sfjp/jindolf/net/HttpUtilsTest.java similarity index 98% rename from src/test/java/jp/sourceforge/jindolf/HttpUtilsTest.java rename to src/test/java/jp/sfjp/jindolf/net/HttpUtilsTest.java index b674bb3..a99e3ff 100644 --- a/src/test/java/jp/sourceforge/jindolf/HttpUtilsTest.java +++ b/src/test/java/jp/sfjp/jindolf/net/HttpUtilsTest.java @@ -4,7 +4,7 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.net; import org.junit.After; import org.junit.AfterClass; diff --git a/src/test/java/jp/sourceforge/jindolf/StringUtilsTest.java b/src/test/java/jp/sfjp/jindolf/util/StringUtilsTest.java similarity index 99% rename from src/test/java/jp/sourceforge/jindolf/StringUtilsTest.java rename to src/test/java/jp/sfjp/jindolf/util/StringUtilsTest.java index 9efaf9f..2e0f70f 100644 --- a/src/test/java/jp/sourceforge/jindolf/StringUtilsTest.java +++ b/src/test/java/jp/sfjp/jindolf/util/StringUtilsTest.java @@ -4,7 +4,7 @@ * Copyright(c) 2009 olyutorskii */ -package jp.sourceforge.jindolf; +package jp.sfjp.jindolf.util; import java.util.regex.Matcher; import java.util.regex.Pattern; -- 2.11.0