<html>\r
<head>\r
-<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">\r
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>\r
<style type="text/css">\r
<!--\r
p {\r
<p>「キャラクターなんとかJ」はオープンソースソフトウェアです。ソースコードは「The Apache License Version 2.0」です。</p>\r
<p><font color="red">本ソフトウェアは完全に無保証です。</font>本ソフトウェアは「現状のまま」、かつ明示か暗黙であるかを問わず、一切の保証を付けずに提供されます。</p>\r
<p><a href="http://sourceforge.jp/projects/charactermanaj/releases/">ここから最新リリース</a> 、\r
-および<a href="http://sourceforge.jp/projects/charactermanaj/svn/view/tags/?root=charactermanaj">最新リリースのソースコード</a>を取得することができます。</p>\r
+および<a href="http://sourceforge.jp/projects/charactermanaj/scm/svn/">最新リリースのソースコード</a>を取得することができます。</p>\r
<p>商用利用であるかを否かを問わず、どなたでも、自由にお使いいただけます。登録や費用は一切必要ありません。再配布も自由になさってかまいません。</p> \r
<p></p>\r
<p>このアプリケーション自身(javaコード)は<a href="http://hp.vector.co.jp/authors/VA017626/">seraphy</a>によって書かれました。<br>\r
<html>\r
<head>\r
-<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">\r
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>\r
<style type="text/css">\r
<!--\r
p {\r
<p>「キャラクターなんとかJ」はオープンソースソフトウェアです。ソースコードは「The Apache License Version 2.0」です。</p>\r
<p><font color="red">本ソフトウェアは完全に無保証です。</font>本ソフトウェアは「現状のまま」、かつ明示か暗黙であるかを問わず、一切の保証を付けずに提供されます。</p>\r
<p><a href="http://sourceforge.jp/projects/charactermanaj/releases/">ここから最新リリース</a> 、\r
-および<a href="http://sourceforge.jp/projects/charactermanaj/svn/view/tags/?root=charactermanaj">最新リリースのソースコード</a>を取得することができます。</p>\r
+および<a href="http://sourceforge.jp/projects/charactermanaj/scm/svn/">最新リリースのソースコード</a>を取得することができます。</p>\r
<p>商用利用であるかを否かを問わず、どなたでも、自由にお使いいただけます。登録や費用は一切必要ありません。再配布も自由になさってかまいません。</p> \r
<p></p>\r
<p>このアプリケーション自身(javaコード)は<a href="http://hp.vector.co.jp/authors/VA017626/">seraphy</a>によって書かれました。<br>\r
import java.io.File;\r
import java.io.FileOutputStream;\r
import java.io.OutputStreamWriter;\r
+import java.io.StringReader;\r
import java.io.Writer;\r
import java.net.URL;\r
import java.nio.charset.Charset;\r
import java.util.Map;\r
import java.util.Properties;\r
import java.util.TreeMap;\r
+import java.util.logging.Level;\r
+import java.util.logging.Logger;\r
\r
import javax.swing.AbstractAction;\r
import javax.swing.BorderFactory;\r
import javax.swing.event.ChangeListener;\r
import javax.swing.event.HyperlinkEvent;\r
import javax.swing.event.HyperlinkListener;\r
+import javax.swing.text.Document;\r
+import javax.swing.text.EditorKit;\r
\r
import charactermanaj.model.AppConfig;\r
import charactermanaj.util.DesktopUtilities;\r
import charactermanaj.util.DirectoryConfig;\r
import charactermanaj.util.ErrorMessageHelper;\r
-import charactermanaj.util.LocalizedResourceTextLoader;\r
+import charactermanaj.util.LocalizedTextResource;\r
import charactermanaj.util.SystemUtil;\r
\r
\r
* @author seraphy\r
*/\r
public class AboutBox {\r
- \r
+\r
+ /**\r
+ * ロガー\r
+ */\r
+ private static Logger logger = Logger.getLogger(AboutBox.class.getName());\r
+\r
private JFrame parent;\r
\r
public AboutBox(JFrame parent) {\r
}\r
\r
protected JPanel createAboutPanel() {\r
- String message = LocalizedResourceTextLoader.getInstance().getText("appinfo/about.html", Charset.forName("UTF-8"));\r
+ LocalizedTextResource textResource = new LocalizedTextResource() {\r
+ @Override\r
+ protected URL getResource(String resourceName) {\r
+ return getClass().getClassLoader().getResource(resourceName);\r
+ }\r
+ };\r
+\r
+ String message = textResource.getText("appinfo/about.html",\r
+ Charset.forName("UTF-8"));\r
\r
AppConfig appConfig = AppConfig.getInstance();\r
\r
editorPane.setEditable(false);\r
editorPane.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE);\r
editorPane.setContentType("text/html");\r
- editorPane.setText(message);\r
+\r
+ // HTML上のcharsetの指定を無視する.\r
+ Document doc = editorPane.getDocument();\r
+ doc.putProperty("IgnoreCharsetDirective", Boolean.TRUE);\r
+\r
+ // editorPane.setText(message);\r
+ // HTML上のcontent-typeを無視する設定はread時のみ有効のようなのでreadを使う.\r
+ EditorKit editorKit = editorPane.getEditorKit();\r
+ try {\r
+ StringReader rd = new StringReader(message);\r
+ try {\r
+ editorKit.read(rd, doc, 0);\r
+\r
+ } finally {\r
+ rd.close();\r
+ }\r
+ } catch (Exception ex) {\r
+ logger.log(Level.SEVERE, ex.toString(), ex);\r
+ }\r
+\r
editorPane.setSelectionStart(0);\r
editorPane.setSelectionEnd(0);\r
aboutPanel.add(new JScrollPane(editorPane), BorderLayout.CENTER);\r
\r
buf.append("<h2>Character Database</h2>");\r
buf.append("<table border=\"1\">");\r
- buf.append("<tr><td>User</td>");\r
+ buf.append("<tr><td>Location</td>");\r
buf.append("<td>" + escape(charactersDir) + "</td></tr>");\r
buf.append("</table>");\r
\r
}\r
\r
// HTMLとして文字列を返す.\r
- \r
+\r
buf.append("</html>");\r
return buf.toString();\r
}\r
package charactermanaj.util;\r
\r
-import java.io.BufferedReader;\r
-import java.io.IOException;\r
-import java.io.InputStream;\r
-import java.io.InputStreamReader;\r
import java.net.URL;\r
import java.nio.charset.Charset;\r
import java.util.Locale;\r
\r
/**\r
* リソースからローカライズされたテキストを取得する.<br>\r
+ * \r
* @author seraphy\r
- *\r
+ * \r
*/\r
public class LocalizedResourceTextLoader extends ResourceLoader {\r
\r
private static final LocalizedResourceTextLoader inst = new LocalizedResourceTextLoader();\r
\r
+ private LocalizedTextResource textResource = new LocalizedTextResource() {\r
+ @Override\r
+ protected URL getResource(String resourceName) {\r
+ return LocalizedResourceTextLoader.this.getResource(resourceName);\r
+ }\r
+ };\r
+\r
private LocalizedResourceTextLoader() {\r
super();\r
}\r
* リソース名を指定して、テキストファイルを読み込んで、その文字列を返す.<br>\r
* リソースは現在のデフォルトロケールを優先で検索されます.<br>\r
* ファイルエンコーディングを引数csで指定する.<br>\r
- * @param name リソース名\r
- * @param cs ファイルのエンコーディング\r
+ * \r
+ * @param name\r
+ * リソース名\r
+ * @param cs\r
+ * ファイルのエンコーディング\r
* @return ファイルの内容(テキスト)\r
*/\r
public String getText(String name, Charset cs) {\r
- return getText(name, cs, Locale.getDefault());\r
+ return textResource.getText(name, cs);\r
}\r
\r
public String getText(String name, Charset cs, Locale locale) {\r
- if (name == null || name.length() == 0 || cs == null || locale == null) {\r
- throw new IllegalArgumentException();\r
- }\r
- \r
- String language = locale.getLanguage();\r
- String country = locale.getCountry();\r
- String variant = locale.getVariant();\r
-\r
- int extpos = name.lastIndexOf(".");\r
- int folderpos = name.lastIndexOf("/");\r
- \r
- String basename;\r
- String ext;\r
- if (folderpos > extpos) {\r
- basename = name;\r
- ext = "";\r
- } else {\r
- basename = name.substring(0, extpos);\r
- ext = name.substring(extpos);\r
- }\r
- \r
- String[] resourceNamesStr = {\r
- basename + "_" + language + "_" + country + "_" + variant + ext,\r
- basename + "_" + language + "_" + country + ext,\r
- basename + "_" + language + ext,\r
- basename + ext,\r
- };\r
-\r
- ResourceNames resourceNames = new ResourceNames(resourceNamesStr);\r
- String text = loadText(resourceNames, cs);\r
- if (text == null) {\r
- throw new RuntimeException("resource not found: " + resourceNames);\r
- }\r
- return text;\r
- }\r
-\r
- protected String loadText(ResourceNames resourceNames, Charset cs) {\r
- if (resourceNames == null || cs == null) {\r
- throw new IllegalArgumentException();\r
- }\r
-\r
- for (String resourceName : resourceNames) {\r
- URL url = getResource(resourceName);\r
- if (url == null) {\r
- continue;\r
- }\r
- StringBuilder buf = new StringBuilder();\r
- try {\r
- InputStream is = url.openStream();\r
- try {\r
- BufferedReader rd = new BufferedReader(new InputStreamReader(is, cs));\r
- try {\r
- int ch;\r
- while ((ch = rd.read()) != -1) {\r
- buf.append((char) ch);\r
- }\r
- } finally {\r
- rd.close();\r
- }\r
- } finally {\r
- is.close();\r
- }\r
- } catch (IOException ex) {\r
- throw new RuntimeException("resource loading error: " + ex, ex);\r
- }\r
- return buf.toString();\r
- }\r
- return null;\r
+ return textResource.getText(name, cs, locale);\r
}\r
}\r
--- /dev/null
+package charactermanaj.util;\r
+\r
+import java.io.BufferedReader;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.io.InputStreamReader;\r
+import java.net.URL;\r
+import java.nio.charset.Charset;\r
+import java.util.Locale;\r
+\r
+/**\r
+ * リソース名を指定してローカライズされたテキストを取得するための抽象実装.<br>\r
+ * リソースの取得部は派生クラスにて実装する必要がある.<br>\r
+ * \r
+ * @author seraphy\r
+ */\r
+public abstract class LocalizedTextResource {\r
+\r
+ /**\r
+ * リソース名を指定して、テキストファイルを読み込んで、その文字列を返す.<br>\r
+ * リソースは現在のデフォルトロケールを優先で検索されます.<br>\r
+ * ファイルエンコーディングを引数csで指定する.<br>\r
+ * \r
+ * @param name\r
+ * リソース名\r
+ * @param cs\r
+ * ファイルのエンコーディング\r
+ * @return ファイルの内容(テキスト)\r
+ */\r
+ public String getText(String name, Charset cs) {\r
+ return getText(name, cs, Locale.getDefault());\r
+ }\r
+\r
+ /**\r
+ * リソース名と文字コードを指定して、ロケールに対応する文字列を取得する.<br>\r
+ * リソースがなければ実行時例外が発生する.\r
+ * \r
+ * @param name\r
+ * リソース名\r
+ * @param cs\r
+ * 文字コード\r
+ * @param locale\r
+ * 取得するロケール\r
+ * @return テキスト\r
+ */\r
+ public String getText(String name, Charset cs, Locale locale) {\r
+ ResourceNames resourceNames = createResourceNames(name, locale);\r
+ String text = loadText(resourceNames, cs);\r
+ if (text == null) {\r
+ throw new RuntimeException("resource not found: " + resourceNames);\r
+ }\r
+ return text;\r
+ }\r
+\r
+ /**\r
+ * リソース名とロケールを指定して読み込む実リソース名のグループを作成して返す.\r
+ * \r
+ * @param name\r
+ * リソース名\r
+ * @param locale\r
+ * ロケール\r
+ * @return リソース名グループ(優先順)\r
+ */\r
+ protected ResourceNames createResourceNames(String name, Locale locale) {\r
+ if (name == null || name.length() == 0 || locale == null) {\r
+ throw new IllegalArgumentException();\r
+ }\r
+\r
+ String language = locale.getLanguage();\r
+ String country = locale.getCountry();\r
+ String variant = locale.getVariant();\r
+\r
+ int extpos = name.lastIndexOf(".");\r
+ int folderpos = name.lastIndexOf("/");\r
+\r
+ String basename;\r
+ String ext;\r
+ if (folderpos > extpos) {\r
+ basename = name;\r
+ ext = "";\r
+ } else {\r
+ basename = name.substring(0, extpos);\r
+ ext = name.substring(extpos);\r
+ }\r
+\r
+ String[] resourceNamesStr = {\r
+ basename + "_" + language + "_" + country + "_" + variant + ext,\r
+ basename + "_" + language + "_" + country + ext,\r
+ basename + "_" + language + ext, basename + ext,};\r
+\r
+ return new ResourceNames(resourceNamesStr);\r
+ }\r
+\r
+ /**\r
+ * リソース名グループを指定して、リソースをテキストとして取得する.<br>\r
+ * リソース名グループの優先順にリソースの取得を試みて最初に成功したものを返す.<br>\r
+ * ひとつも成功しなければnullが返される.<br>\r
+ * \r
+ * @param resourceNames\r
+ * リソース名グループ\r
+ * @param cs\r
+ * 文字コード\r
+ * @return リソースのテキスト\r
+ */\r
+ protected String loadText(ResourceNames resourceNames, Charset cs) {\r
+ if (resourceNames == null || cs == null) {\r
+ throw new IllegalArgumentException();\r
+ }\r
+\r
+ for (String resourceName : resourceNames) {\r
+ URL url = getResource(resourceName);\r
+ if (url == null) {\r
+ // リソースがなければ次の候補へスキップする.\r
+ continue;\r
+ }\r
+ StringBuilder buf = new StringBuilder();\r
+ try {\r
+ InputStream is = url.openStream();\r
+ try {\r
+ BufferedReader rd = new BufferedReader(\r
+ new InputStreamReader(is, cs));\r
+ try {\r
+ int ch;\r
+ while ((ch = rd.read()) != -1) {\r
+ buf.append((char) ch);\r
+ }\r
+ } finally {\r
+ rd.close();\r
+ }\r
+ } finally {\r
+ is.close();\r
+ }\r
+ } catch (IOException ex) {\r
+ throw new RuntimeException("resource loading error: " + ex, ex);\r
+ }\r
+ // 1つでも成功すれば、それで終了する.\r
+ return buf.toString();\r
+ }\r
+ // 一つも成功しなかった場合\r
+ return null;\r
+ }\r
+\r
+ /**\r
+ * リソース名からリソースを取得する.<br>\r
+ * 存在しなければnullを返す.<br>\r
+ * \r
+ * @param resourceName\r
+ * リソース名\r
+ * @return リソース、またはnull\r
+ */\r
+ protected abstract URL getResource(String resourceName);\r
+}\r
ArrayList<String> resources = new ArrayList<String>();\r
\r
// リソースとしてコピー対象とするパッケージ名\r
- String[] names = new String[]{"appinfo", "languages", "menu",\r
- "template"};\r
+ String[] names = new String[]{"languages", "menu", "template"};\r
\r
ClassLoader cl = getClass().getClassLoader();\r
\r