OSDN Git Service

add a little program 'chartool'
authormshio <mshio@54a90f34-5e62-402c-8eae-46c47f0b2e07>
Fri, 28 May 2010 13:57:17 +0000 (13:57 +0000)
committermshio <mshio@54a90f34-5e62-402c-8eae-46c47f0b2e07>
Fri, 28 May 2010 13:57:17 +0000 (13:57 +0000)
git-svn-id: svn+ssh://svn.osdn.net/svnroot/sawarabi-fonts/trunk@7 54a90f34-5e62-402c-8eae-46c47f0b2e07

13 files changed:
chartool/build.xml [new file with mode: 0644]
chartool/js/charpalette.js [new file with mode: 0644]
chartool/src/jp/sourceforge/sawarabifonts/chartool/CharProperty.java [new file with mode: 0644]
chartool/src/jp/sourceforge/sawarabifonts/chartool/ConfigScript.java [new file with mode: 0644]
chartool/src/jp/sourceforge/sawarabifonts/chartool/GlyphViewer.java [new file with mode: 0644]
chartool/src/jp/sourceforge/sawarabifonts/chartool/GuiController.java [new file with mode: 0644]
chartool/src/jp/sourceforge/sawarabifonts/chartool/HistoryBuffer.java [new file with mode: 0644]
chartool/src/jp/sourceforge/sawarabifonts/chartool/InvalidSearchStringException.java [new file with mode: 0644]
chartool/src/jp/sourceforge/sawarabifonts/chartool/JsScriptableObject.java [new file with mode: 0644]
chartool/src/jp/sourceforge/sawarabifonts/chartool/Main.java [new file with mode: 0644]
chartool/src/jp/sourceforge/sawarabifonts/chartool/MainPanel.java [new file with mode: 0644]
chartool/src/jp/sourceforge/sawarabifonts/chartool/PropertyPanel.java [new file with mode: 0644]
chartool/src/jp/sourceforge/sawarabifonts/chartool/SearchPanel.java [new file with mode: 0644]

diff --git a/chartool/build.xml b/chartool/build.xml
new file mode 100644 (file)
index 0000000..e33dd41
--- /dev/null
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="chartool" default="dest" basedir=".">
+
+  <property name="src" location="src"/>
+  <property name="build" location="build"/>
+  <property name="dest" location="dest"/>
+  <property name="lib" location="lib"/>
+  <property name="temp" location="temp"/>
+  <property name="rhino.ftp.dir" 
+           value="ftp://ftp.mozilla.org/pub/mozilla.org/js"/>
+  <property name="rhino.name" value="rhino1_7R2"/>
+  <property name="manifest.name" value="MANIFEST.MF"/>
+
+  <target name="init">
+    <mkdir dir="${build}"/>
+    <mkdir dir="${lib}"/>
+  </target>
+
+  <target name="rhino.check" depends="init">
+    <available file="${lib}/js.jar" property="rhino.exists"/>
+  </target>
+
+  <target name="download" depends="rhino.check" unless="rhino.exists">
+    <mkdir dir="${temp}"/>
+    <get src="${rhino.ftp.dir}/${rhino.name}.zip" 
+        dest="${temp}/${rhino.name}.zip"/>
+    <unzip src="${temp}/${rhino.name}.zip" dest="${temp}"/>
+    <move file="${temp}/${rhino.name}/js.jar" todir="${lib}"/>
+  </target>
+
+  <target name="compile" depends="download">
+    <javac srcdir="${src}" 
+           destdir="${build}"
+           classpath="${lib}/js.jar"/>
+  </target>
+
+  <target name="manifest" depends="compile">
+    <mkdir dir="${temp}"/>
+    <manifest file="${temp}/${manifest.name}">
+      <attribute name="Class-Path" value=". lib/js.jar"/>
+      <attribute name="Main-Class"
+                value="jp.sourceforge.sawarabifonts.chartool.Main"/>
+    </manifest>
+  </target>
+
+  <target name="dest" depends="manifest">
+    <mkdir dir="${dest}"/>
+    <copy todir="${dest}/lib">
+      <fileset dir="${lib}"/>
+    </copy>
+    <copy todir="${dest}/js">
+      <fileset dir="js"/>
+    </copy>
+    <jar destfile="${dest}/chartool.jar"
+        basedir="${build}"
+        manifest="${temp}/${manifest.name}"/>
+  </target>
+
+  <target name="clean">
+    <delete dir="${build}"/>
+    <delete dir="${temp}"/>
+  </target>
+</project>
diff --git a/chartool/js/charpalette.js b/chartool/js/charpalette.js
new file mode 100644 (file)
index 0000000..efb4625
--- /dev/null
@@ -0,0 +1,10 @@
+var fonts = [
+];
+
+var script = [
+       function(property, modifier) {
+       },
+       function(property, modifier) {
+       },
+];
+
diff --git a/chartool/src/jp/sourceforge/sawarabifonts/chartool/CharProperty.java b/chartool/src/jp/sourceforge/sawarabifonts/chartool/CharProperty.java
new file mode 100644 (file)
index 0000000..3935e89
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2010, mshio <mshio@users.sourceforge.jp>
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * ---
+ * Require JDK 1.5 (or later)
+ */
+package jp.sourceforge.sawarabifonts.chartool;
+
+public class CharProperty {
+       final String character;
+       final String name;
+       final String code;
+
+       public CharProperty(String character, String code) {
+               this(character, code, "");
+       }
+
+       public CharProperty(String character, String code, String name) {
+               this.character = character;
+               this.code = code;
+               this.name = name;
+       }
+}
diff --git a/chartool/src/jp/sourceforge/sawarabifonts/chartool/ConfigScript.java b/chartool/src/jp/sourceforge/sawarabifonts/chartool/ConfigScript.java
new file mode 100644 (file)
index 0000000..2f2c9e8
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2010, mshio <mshio@users.sourceforge.jp>
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * ---
+ * Require JDK 1.5 (or later)
+ */
+package jp.sourceforge.sawarabifonts.chartool;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.logging.Logger;
+
+import javax.swing.JFrame;
+
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.EvaluatorException;
+import org.mozilla.javascript.Function;
+import org.mozilla.javascript.ScriptableObject;
+
+public class ConfigScript {
+       private final static ConfigScript instance = new ConfigScript();
+       private JsScriptableObject scriptable = null;
+
+       private ConfigScript() { }
+
+       public static ConfigScript getInstance() {
+               return instance;
+       }
+
+       public void load() throws IOException {
+               load("js/charpalette.js");
+       }
+
+       public void load(String filename) throws IOException {
+               File f = new File(filename);
+               FileReader in = new FileReader(f);
+               Context cx = Context.enter();
+               scriptable = new JsScriptableObject();
+               cx.initStandardObjects(scriptable);
+               setupVariables();
+               try {
+                       cx.evaluateReader(scriptable, in, "<config>", 0, null);
+               } finally {
+                       Context.exit();
+               }
+       }
+
+       public boolean isLoaded() {
+               return scriptable != null;
+       }
+
+       public String[] getFontNames() {
+               String[] ret = null;
+               if (scriptable.has("fonts", scriptable)) {
+                       Object o = scriptable.get("fonts", scriptable);
+                       try {
+                               ret = (String[]) Context.jsToJava(o, String[].class);
+                       } catch (EvaluatorException e) {
+                               e.printStackTrace();
+                               Logger.getLogger(Main.LOGNAME).warning(e.getMessage());
+                       }
+               }
+               return ret;
+       }
+
+       private Function[] getScriptFunction() {
+               final String NAME = "script";
+               Function[] ret = null;
+               if (scriptable.has(NAME, scriptable)) {
+                       Object o = scriptable.get(NAME, scriptable);
+                       try {
+                               ret = (Function[]) Context.jsToJava(o, Function[].class);
+                       } catch (EvaluatorException e) {
+                               e.printStackTrace();
+                               Logger.getLogger(Main.LOGNAME).warning(e.getMessage());
+                       }
+               }
+               return ret;
+       }
+
+       public void execScript(int id, String property, int modifier) throws Exception {
+               Function[] fs = getScriptFunction();
+               if (fs == null || fs.length <= id) { return ; }
+
+               Context cx = Context.enter();
+//             Class<?> clazz = org.jdesktop.jdic.desktop.Desktop.class;
+//             cx.setApplicationClassLoader(clazz.getClassLoader());
+               try {
+                       fs[id].call(cx, scriptable, scriptable, new Object[] {property, modifier});
+               } finally {
+                       Context.exit();
+               }
+       }
+
+       private void setupVariables() {
+               final int RO = ScriptableObject.READONLY;
+               final int DE = ScriptableObject.DONTENUM;
+               String home = System.getProperty("user.home");
+               ScriptableObject.defineProperty(scriptable, "HOME", home, RO);
+
+               String[] fs = new String[] { "alert" };
+               scriptable.defineFunctionProperties(fs, JsScriptableObject.class, DE);
+       }
+
+       public void setFrame(JFrame frame) {
+               scriptable.setFrame(frame);
+       }
+}
diff --git a/chartool/src/jp/sourceforge/sawarabifonts/chartool/GlyphViewer.java b/chartool/src/jp/sourceforge/sawarabifonts/chartool/GlyphViewer.java
new file mode 100644 (file)
index 0000000..a090734
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2010, mshio <mshio@users.sourceforge.jp>
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * ---
+ * Require JDK 1.5 (or later)
+ */
+package jp.sourceforge.sawarabifonts.chartool;
+
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.Toolkit;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.StringSelection;
+import java.awt.event.ActionEvent;
+import java.io.IOException;
+import java.util.logging.Logger;
+
+import javax.swing.JMenu;
+import javax.swing.JPopupMenu;
+import javax.swing.JTextField;
+import javax.swing.border.CompoundBorder;
+import javax.swing.border.EmptyBorder;
+import javax.swing.border.EtchedBorder;
+import javax.swing.event.CaretEvent;
+import javax.swing.event.CaretListener;
+import javax.swing.text.TextAction;
+
+public class GlyphViewer extends JTextField {
+       private static final long serialVersionUID = 5811308266106026080L;
+
+       public GlyphViewer(GuiController controller) {
+               Font f = new Font(getFont().getFontName(), Font.PLAIN, 64);
+               setFont(f);
+               setHorizontalAlignment(JTextField.CENTER);
+               setEditable(false);
+               EmptyBorder m = new EmptyBorder(10, 10, 10, 10);
+               setBorder(new CompoundBorder(new EtchedBorder(), m));
+
+               controller.setGlyphViewer(this);
+               setPreferredSize(new Dimension(100, 100));
+
+               final JPopupMenu menu = new GlyphViewerMenu();
+               addCaretListener(new CaretListener() {
+                       public void caretUpdate(CaretEvent e) {
+                               String s = getSelectedText();
+                               if (s != null && s.length() > 0) {
+                                       menu.show(GlyphViewer.this, 70, 70);
+                               }
+                       }
+               });
+       }
+
+       private void copyChar() {
+               Clipboard b = Toolkit.getDefaultToolkit().getSystemClipboard();
+               StringSelection s = new StringSelection(getText());
+               b.setContents(s, s);
+       }
+
+       private void changeFont(String nm) {
+               Font f = getFont();
+               int sz = f.getSize();
+               int st = f.getStyle();
+               setFont(new Font(nm, st, sz));
+       }
+
+       class GlyphViewerMenu extends JPopupMenu {
+               private static final long serialVersionUID = 847563481396381931L;
+
+               GlyphViewerMenu() {
+                       add(new TextAction("Copy") {
+                               private static final long serialVersionUID = -4087404094754292233L;
+                               public void actionPerformed(ActionEvent e) { copyChar(); }
+                       });
+                       JMenu fontmenu = new JMenu("font");
+                       setFontMenu(fontmenu, "Dialog");
+                       try {
+                               addCustomFontMenu(fontmenu);
+                       } catch (IOException e) {
+                               e.printStackTrace();
+                               Logger.getLogger(Main.LOGNAME).warning(e.getMessage());
+                       }
+                       add(fontmenu);
+               }
+
+               private void addCustomFontMenu(JMenu menu) throws IOException {
+                       ConfigScript s = ConfigScript.getInstance();
+                       if (! s.isLoaded()) { s.load(); }
+                       String[] fnt = s.getFontNames();
+                       if (fnt != null) {
+                               for (String nm: fnt) setFontMenu(menu, nm);
+                       } else {
+                               String msg = "configuration of fonts is not found.";
+                               System.err.println(msg);
+                               Logger.getLogger(Main.LOGNAME).warning(msg);
+                       }
+               }
+
+               private void setFontMenu(JMenu menu, final String nm) {
+                       menu.add(new TextAction(nm) {
+                               private static final long serialVersionUID = 7621704223879655193L;
+                               public void actionPerformed(ActionEvent e) { changeFont(nm); }
+                       });
+               }
+       }
+}
diff --git a/chartool/src/jp/sourceforge/sawarabifonts/chartool/GuiController.java b/chartool/src/jp/sourceforge/sawarabifonts/chartool/GuiController.java
new file mode 100644 (file)
index 0000000..6665683
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2010, mshio <mshio@users.sourceforge.jp>
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * ---
+ * Require JDK 1.5 (or later)
+ */
+package jp.sourceforge.sawarabifonts.chartool;
+
+import java.util.logging.Logger;
+
+public class GuiController {
+       private final Main main;
+       private GlyphViewer glyphViewer = null;
+       private SearchPanel searchPanel = null;
+       private PropertyPanel propertyPanel = null;
+
+       public GuiController(Main main) {
+               this.main = main;
+       }
+
+       public void setGlyphViewer(GlyphViewer g) {
+               this.glyphViewer = g;
+       }
+
+       public void setPropertyPanel(PropertyPanel p) {
+               this.propertyPanel = p;
+       }
+
+       public void setSearchPanel(SearchPanel s) {
+               this.searchPanel = s;
+       }
+
+       private boolean isHexChar(char ch) {
+               return (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') ||
+                               (ch >= 'A' && ch <= 'F');
+       }
+
+       private boolean foundByCode(String searchText, int pos) {
+               char ch = searchText.charAt(pos);
+               int len = searchText.length();
+               if (isHexChar(ch)) {
+                       boolean four = false;
+                       int p = pos;
+                       for (;;) {
+                               four = p - pos >= 3;
+                               if (p - pos == 4) {
+                                       if (showGlyphByCode(searchText, pos, pos + 5) || 
+                                                       (four && showGlyphByCode(searchText, pos, pos + 4))) {
+                                               return true;
+                                       }
+                               } else if (p + 1 < len && isHexChar(searchText.charAt(p + 1))) {
+                                       p++;
+                               } else {
+                                       break;
+                               }
+                       }
+                       int b = pos;
+                       for (;;) {
+                               four = p - b >= 3;
+                               if (p - b == 4) {
+                                       if (showGlyphByCode(searchText, b, b + 5) ||
+                                                       (four && showGlyphByCode(searchText, b + 1, b + 5))) {
+                                               return true;
+                                       }
+                               } else if (b - 1 >= 0 && isHexChar(searchText.charAt(b - 1))) {
+                                       b--; 
+                               } else {
+                                       if (four) { return showGlyphByCode(searchText, b, b + 4); }
+                                       break;
+                               }
+                       }
+               }
+               return false;
+       }
+
+       public void onSearch(String searchText, int pos, String selected) {
+               if (searchText.length() == 0) { return; }
+               if (pos >= searchText.length()) { pos = 0; }
+
+               if (! foundByCode(searchText, pos)) {
+                       String s = searchText.substring(pos);
+                       if (s.length() == 0) { s = searchText; }
+                       try {
+                               showGlyph(main.searchChar(s));
+                               boolean h = Character.isHighSurrogate(s.charAt(0));
+                               searchPanel.setCaretPosition(pos, h ? 2 : 1);
+                       } catch (InvalidSearchStringException e) {
+                               e.printStackTrace();
+                               Logger.getLogger(Main.LOGNAME).warning(e.getMessage());
+                       }
+               }
+       }
+
+       private boolean showGlyphByCode(String text, int pos0, int pos1) {
+               boolean ret = false;
+               int c = Integer.parseInt(text.substring(pos0, pos1), 16);
+               try {
+                       CharProperty p = main.searchChar(c);
+                       int len = p.character.length();
+                       if ((len >= 2 && Character.isHighSurrogate(p.character.charAt(0)) &&
+                                       Character.isLowSurrogate(p.character.charAt(1))) || len <= 1) {
+                               showGlyph(main.searchChar(c));
+                               searchPanel.setCaretPosition(pos0, pos1 - pos0);
+                               ret = true;
+                       }
+               } catch (InvalidSearchStringException e) {
+                       e.printStackTrace();
+                       Logger.getLogger(Main.LOGNAME).warning(e.getMessage());
+               }
+               return ret;
+       }
+
+       private void showGlyph(CharProperty cp) {
+               if (cp != null) {
+                       glyphViewer.setText(cp.character);
+                       propertyPanel.setCode(cp.code);
+               }
+       }
+}
diff --git a/chartool/src/jp/sourceforge/sawarabifonts/chartool/HistoryBuffer.java b/chartool/src/jp/sourceforge/sawarabifonts/chartool/HistoryBuffer.java
new file mode 100644 (file)
index 0000000..24d99cc
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2010, mshio <mshio@users.sourceforge.jp>
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * ---
+ * Require JDK 1.5 (or later)
+ */
+package jp.sourceforge.sawarabifonts.chartool;
+
+import java.util.LinkedList;
+import java.util.ListIterator;
+
+public class HistoryBuffer {
+       private final static int MAX_LENGTH = 100;
+       private final LinkedList<String> buffer = new LinkedList<String>();
+       private ListIterator<String> iterator = null;
+       private boolean prev = true;
+
+       public void add(String buf) {
+               buffer.add(buf);
+               if (buffer.size() >= MAX_LENGTH) { buffer.removeFirst(); }
+               iterator = buffer.listIterator(buffer.size() - 1);
+               prev = true;
+       }
+
+       public String getPrev() {
+               String ret = null;
+               if (! buffer.isEmpty() && iterator.hasPrevious()) {
+                       ret = iterator.previous();
+                       if (! prev && iterator.hasPrevious()) { ret = iterator.previous(); }
+                       prev = true;
+               }
+               return ret;
+       }
+
+       public String getNext() {
+               String ret = null;
+               if (! buffer.isEmpty() && iterator.hasNext()) {
+                       ret = iterator.next();
+                       if (prev && iterator.hasNext()) { ret = iterator.next(); }
+                       prev = false;
+               }
+               return ret;
+       }
+
+       public String getCurrent() {
+               return buffer.isEmpty() ? null : buffer.getLast();
+       }
+}
diff --git a/chartool/src/jp/sourceforge/sawarabifonts/chartool/InvalidSearchStringException.java b/chartool/src/jp/sourceforge/sawarabifonts/chartool/InvalidSearchStringException.java
new file mode 100644 (file)
index 0000000..d910eb9
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2010, mshio <mshio@users.sourceforge.jp>
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * ---
+ * Require JDK 1.5 (or later)
+ */
+package jp.sourceforge.sawarabifonts.chartool;
+
+public class InvalidSearchStringException extends Exception {
+       private static final long serialVersionUID = -320568592282581589L;
+}
diff --git a/chartool/src/jp/sourceforge/sawarabifonts/chartool/JsScriptableObject.java b/chartool/src/jp/sourceforge/sawarabifonts/chartool/JsScriptableObject.java
new file mode 100644 (file)
index 0000000..3af9990
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2010, mshio <mshio@users.sourceforge.jp>
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * ---
+ * Require JDK 1.5 (or later)
+ */
+package jp.sourceforge.sawarabifonts.chartool;
+
+import javax.swing.JFrame;
+import javax.swing.JOptionPane;
+
+import org.mozilla.javascript.ScriptableObject;
+
+public class JsScriptableObject extends ScriptableObject {
+       private static final long serialVersionUID = 2857654503604299849L;
+
+       private JFrame frame = null;
+
+       @Override
+       public String getClassName() {
+               return "JsScriptableObject";
+       }
+
+       public void setFrame(JFrame frame) {
+               this.frame = frame;
+       }
+
+       public void alert(String message) {
+               if (frame != null) {
+                       JOptionPane.showMessageDialog(frame, message);
+               }
+       }
+}
diff --git a/chartool/src/jp/sourceforge/sawarabifonts/chartool/Main.java b/chartool/src/jp/sourceforge/sawarabifonts/chartool/Main.java
new file mode 100644 (file)
index 0000000..e7bd20b
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2010, mshio <mshio@users.sourceforge.jp>
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * ---
+ * Require JDK 1.5 (or later)
+ */
+package jp.sourceforge.sawarabifonts.chartool;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.logging.FileHandler;
+import java.util.logging.Logger;
+
+import javax.swing.JFrame;
+import javax.swing.SwingUtilities;
+
+public class Main {
+       public static final String LOGNAME = "jp.sourceforge.sawarabifonts.chartool.log";
+
+       public static void main(String[] args) {
+               SwingUtilities.invokeLater(new Runnable() {
+                       public void run() {
+                               Main m = new Main();
+                               m.setupLogger();
+                               m.showGUI();
+                       }
+               });
+       }
+
+       private void showGUI() {
+               JFrame f = new JFrame();
+               setupConfigScript(f);
+               f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+               f.add(new MainPanel(this));
+               f.setSize(340, 120);
+               f.setVisible(true);
+       }
+
+       private void setupLogger() {
+               Logger log = Logger.getLogger(LOGNAME);
+               try {
+                       File f = new File("log");
+                       if (! f.exists()) { f.mkdir(); }
+                       log.addHandler(new FileHandler("log/error", 200000, 10, false));
+               } catch (SecurityException e) {
+                       e.printStackTrace();
+               } catch (IOException e) {
+                       e.printStackTrace();
+               }
+       }
+
+       private void setupConfigScript(JFrame frame) {
+               ConfigScript s = ConfigScript.getInstance();
+               if (! s.isLoaded()) {
+                       try {
+                               s.load();
+                       } catch (IOException e) {
+                               e.printStackTrace();
+                               Logger.getLogger(LOGNAME).warning(e.getMessage());
+                       }
+               }
+               s.setFrame(frame);
+       }
+
+       public CharProperty searchChar(String str) throws InvalidSearchStringException {
+               if (str == null || str.length() == 0) { return null; }
+
+               String code = null;
+               String ch = null;
+               char c = str.charAt(0);
+               if (Character.isHighSurrogate(c)) {
+                       if (str.length() >= 2) {
+                               char c1 = str.charAt(1);
+                               int t = ((int) c - 0xd800) * 0x400 + (int) c1 - 0xdc00 + 0x10000;
+                               code = Integer.toHexString(t);
+                               ch = new String(new char[] { c, c1 });
+                       } else {
+                               code = fillZero(Integer.toHexString(c), 4);
+                               ch = new String(new char[] { c });
+                       }
+               } else {
+                       code = fillZero(Integer.toHexString(c), 4);
+                       ch = new String(new char[] { c });
+               }
+               return new CharProperty(ch, code);
+       }
+
+       public CharProperty searchChar(int code) throws InvalidSearchStringException {
+               String h = Integer.toHexString(code);
+               String s = null;
+               String c = null;
+               if (h.length() >= 5) {
+                       int x = code - 0x10000;
+                       int c0 = x / 0x400 + 0xd800;
+                       int c1 = x % 0x400 + 0xdc00;
+                       s = new String(new char[] { (char) c0, (char) c1});
+                       c = h;
+               } else {
+                       s = new String(new char[] { (char) code });
+                       c = fillZero(h, 4);
+               }
+               return new CharProperty(s, c);
+       }
+
+       private String fillZero(String str, int length) {
+               String ret = str;
+               int l = str.length();
+               if (l < length) {
+                       StringBuilder sb = new StringBuilder(length);
+                       for (int i = 0; length - l - i > 0; i++) { sb.append('0'); }
+                       sb.append(str);
+                       ret = sb.toString();
+               }
+               return ret;
+       }
+}
diff --git a/chartool/src/jp/sourceforge/sawarabifonts/chartool/MainPanel.java b/chartool/src/jp/sourceforge/sawarabifonts/chartool/MainPanel.java
new file mode 100644 (file)
index 0000000..b9eb1e8
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2010, mshio <mshio@users.sourceforge.jp>
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * ---
+ * Require JDK 1.5 (or later)
+ */
+package jp.sourceforge.sawarabifonts.chartool;
+
+import java.awt.BorderLayout;
+
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+import javax.swing.border.EmptyBorder;
+
+class MainPanel extends JPanel {
+       private static final long serialVersionUID = 7520947148504510083L;
+
+       public MainPanel(Main m) {
+               GuiController c = new GuiController(m);
+               final SearchPanel sp = new SearchPanel(c);
+               PropertyPanel pp = new PropertyPanel(c);
+               GlyphViewer gv = new GlyphViewer(c);
+
+               EmptyBorder b = new EmptyBorder(10, 10, 10, 10);
+               this.setBorder(b);
+               this.setLayout(new BorderLayout());
+
+               JPanel p = new JPanel();
+               EmptyBorder e = new EmptyBorder(0, 10, 0, 0);
+               p.setBorder(e);
+               p.setLayout(new BorderLayout());
+               p.add(sp, BorderLayout.NORTH);
+               p.add(pp, BorderLayout.CENTER);
+               this.add(p, BorderLayout.CENTER);
+
+               this.add(gv, BorderLayout.WEST);
+
+               SwingUtilities.invokeLater(new Runnable() {
+                       public void run() { sp.setFocus(); }
+               });
+       }
+}
diff --git a/chartool/src/jp/sourceforge/sawarabifonts/chartool/PropertyPanel.java b/chartool/src/jp/sourceforge/sawarabifonts/chartool/PropertyPanel.java
new file mode 100644 (file)
index 0000000..bab4af0
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2010, mshio <mshio@users.sourceforge.jp>
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * ---
+ * Require JDK 1.5 (or later)
+ */
+package jp.sourceforge.sawarabifonts.chartool;
+
+import java.awt.FontMetrics;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import java.util.logging.Logger;
+
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+public class PropertyPanel extends JPanel {
+       private static final long serialVersionUID = -762290847824180418L;
+
+       private final static int MARGIN_LEFT = 5;
+       private final static int MARGIN_TOP = 5;
+       private final int labelWidth;
+       private final JButton[] buttons;
+       private final JLabel[] properties;
+
+       public PropertyPanel(GuiController controller) {
+               setLayout(null);
+               FontMetrics fm = getFontMetrics(getFont());
+               String[] t = new String[] { "Code: ", "Name: " };
+               buttons = new JButton[t.length];
+               properties = new JLabel[t.length];
+               labelWidth = setPropertyLabels(t, fm);
+               int maxWidth = setPropertyButtons(t, fm, labelWidth);
+               setPropertyLabels(t, fm, maxWidth);
+               addComponentListener(new ComponentAdapter() {
+                       @Override public void componentResized(ComponentEvent e) {
+                               onResized();
+                       }
+               });
+
+               controller.setPropertyPanel(this);
+       }
+
+       public void setCode(String code) {
+               properties[0].setText(code);
+       }
+
+       private void setPropertyLabels(String[] text, FontMetrics fm, int x) {
+               int y = MARGIN_TOP;
+               int h = fm.getHeight();
+               for (int i = 0; i < text.length; i++) {
+                       properties[i] = new JLabel();
+                       add(properties[i]);
+                       properties[i].setLocation(x, y);
+                       y += h;
+               }
+       }
+
+       private int setPropertyLabels(String[] text, FontMetrics fm) {
+               int max = 0;
+               int y = MARGIN_TOP;
+               int h = fm.getHeight();
+               for (String t : text) {
+                       JLabel n = new JLabel(t);
+                       n = new JLabel(t);
+                       add(n);
+                       n.setLocation(MARGIN_LEFT, y);
+                       int w = fm.stringWidth(t);
+                       n.setSize(w, h);
+                       y += h;
+                       if (max < w) max = w;
+               }
+               return max + MARGIN_LEFT;
+       }
+
+       private int setPropertyButtons(String[] text, FontMetrics fm, int x) {
+               int w = fm.stringWidth("S");
+               int h = fm.getHeight();
+               int y = MARGIN_TOP;
+
+               for (int i = 0; i < text.length; i++) {
+                       JButton b = new JButton("S");
+                       b.setFocusable(false);
+                       final int id = i;
+                       b.addActionListener(new ActionListener() {
+                               public void actionPerformed(ActionEvent e) {
+                                       String t = properties[id].getText();
+                                       ConfigScript s = ConfigScript.getInstance();
+                                       try {
+                                               s.execScript(id, t, e.getModifiers());
+                                       } catch (Exception ex) {
+                                               ex.printStackTrace();
+                                               Logger.getLogger(Main.LOGNAME).warning(ex.getMessage());
+                                       }
+                               }
+                       });
+                       add(b);
+                       b.setLocation(x, y);
+                       b.setSize(w + 10, h);
+                       y += h;
+                       buttons[i] = b;
+               }
+               return w;
+       }
+
+       private void onResized() {
+               int y = MARGIN_TOP;
+               int h = getFontMetrics(getFont()).getHeight();
+               int w = getWidth() - labelWidth - buttons[0].getWidth();
+               for (int i = 0; i < properties.length; i++) {
+                       properties[i].setLocation(labelWidth, y);
+                       properties[i].setSize(w, h);
+                       buttons[i].setLocation(labelWidth + w, y);
+                       y += h;
+               }
+       }
+
+}
diff --git a/chartool/src/jp/sourceforge/sawarabifonts/chartool/SearchPanel.java b/chartool/src/jp/sourceforge/sawarabifonts/chartool/SearchPanel.java
new file mode 100644 (file)
index 0000000..97b51f9
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2010, mshio <mshio@users.sourceforge.jp>
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * ---
+ * Require JDK 1.5 (or later)
+ */
+package jp.sourceforge.sawarabifonts.chartool;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Toolkit;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+import javax.swing.Action;
+import javax.swing.ActionMap;
+import javax.swing.JButton;
+import javax.swing.JMenuItem;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.JTextField;
+import javax.swing.KeyStroke;
+import javax.swing.text.DefaultEditorKit;
+import javax.swing.text.JTextComponent;
+import javax.swing.text.Keymap;
+import javax.swing.text.TextAction;
+
+public class SearchPanel extends JPanel {
+       private static final long serialVersionUID = 1971690273660748828L;
+
+       private final JTextField searchField;
+       private final HistoryBuffer buffer = new HistoryBuffer();
+       private final SearchFieldPopup popup;
+
+       public SearchPanel(final GuiController controller) {
+               setLayout(new BorderLayout());
+
+               searchField = new JTextField();
+               popup = new SearchFieldPopup();
+               searchField.addMouseListener(new MouseAdapter() {
+                       @Override
+                       public void mouseClicked(MouseEvent e) {
+                               if (e.getButton() == MouseEvent.BUTTON3) {
+                                       popup.show(searchField, e.getX(), e.getY());
+                               }
+                       }
+               });
+               setupKeymap(controller);
+               
+               add(searchField, BorderLayout.CENTER);
+               add(makeSearchButton(), BorderLayout.EAST);
+
+               controller.setSearchPanel(this);
+       }
+
+       private JButton makeSearchButton() {
+               JButton b = new JButton("Search");
+               Keymap k = searchField.getKeymap();
+               Action a = k.getAction(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0));
+               b.addActionListener(a);
+               b.setFocusable(false);
+
+               return b;
+       }
+
+       public void setFocus() {
+               searchField.requestFocusInWindow();
+       }
+
+       public void setCaretPosition(int position, int length) {
+               if (searchField.getText().length() > position) {
+                       searchField.setSelectionStart(position);
+                       searchField.setSelectionEnd(position + length); 
+               } else {
+                       searchField.setSelectionStart(0);
+                       searchField.setSelectionEnd(length);
+               }
+       }
+
+       private void setupKeymap(final GuiController controller) {
+               Keymap map = JTextComponent.addKeymap("charpalette", searchField.getKeymap());
+               searchField.setKeymap(map);
+
+               setupSearchKeymap(controller);
+               setupHistoryUpKeymap();
+               setupHistoryDownKeymap();
+       }
+
+       private void setupHistoryUpKeymap() {
+               Keymap map = searchField.getKeymap();
+               KeyStroke key0 = KeyStroke.getKeyStroke(KeyEvent.VK_P, KeyEvent.CTRL_MASK);
+               KeyStroke key1 = KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0);
+               Action a = new TextAction("history-up") {
+                       private static final long serialVersionUID = 8417010810041845179L;
+                       public void actionPerformed(ActionEvent e) {
+                               String s = buffer.getPrev();
+                               if (s != null) {
+                                       searchField.setText(s);
+                                       searchField.setCaretPosition(0);
+                               }
+                       }
+               }; 
+               map.addActionForKeyStroke(key0, a);
+               map.addActionForKeyStroke(key1, a);
+       }
+
+       private void setupHistoryDownKeymap() {
+               Keymap map = searchField.getKeymap();
+               KeyStroke key0 = KeyStroke.getKeyStroke(KeyEvent.VK_N, KeyEvent.CTRL_MASK);
+               KeyStroke key1 = KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0);
+               Action a = new TextAction("history-down") {
+                       private static final long serialVersionUID = 2292000606648845301L;
+                       public void actionPerformed(ActionEvent e) {
+                               String s = buffer.getNext();
+                               if (s != null) {
+                                       searchField.setText(s);
+                                       searchField.setCaretPosition(0);
+                               }
+                       }
+               }; 
+               map.addActionForKeyStroke(key0, a);
+               map.addActionForKeyStroke(key1, a);
+       }
+
+       private void setupSearchKeymap(final GuiController controller) {
+               KeyStroke key = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
+               Action a = new TextAction("search") {
+                       private static final long serialVersionUID = 7670487950463928408L;
+                       public void actionPerformed(ActionEvent e) {
+                               String st = searchField.getSelectedText();
+                               int p = searchField.getCaretPosition();
+                               controller.onSearch(searchField.getText(), p, st);
+                               String s = buffer.getCurrent();
+                               String t = searchField.getText();
+                               if (s == null || ! s.equals(t)) {
+                                       buffer.add(t);
+                               }
+                       }
+               };
+               searchField.getKeymap().addActionForKeyStroke(key, a);
+       }
+
+
+       class SearchFieldPopup extends JPopupMenu {
+               private static final long serialVersionUID = 5225317856689478836L;
+
+               final JMenuItem cut;
+               final JMenuItem copy;
+               final JMenuItem paste;
+               final JMenuItem clear;
+
+               SearchFieldPopup() {
+                       cut = makeMenuItem("Cut", DefaultEditorKit.cutAction);
+                       copy = makeMenuItem("Copy", DefaultEditorKit.copyAction);
+                       paste = makeMenuItem("Paste", DefaultEditorKit.pasteAction);
+                       clear = new JMenuItem(new TextAction("Clear") {
+                               private static final long serialVersionUID = 3995545953271258486L;
+                               public void actionPerformed(ActionEvent e) {
+                                       searchField.setText("");
+                               }
+                       });
+                       add(cut);
+                       add(copy);
+                       add(paste);
+                       add(clear);
+               }
+
+               private JMenuItem makeMenuItem(String name, String action) {
+                       JMenuItem ret = null;
+                       Action a = getActionFromTextField(action);
+                       if (a != null) {
+                               ret = new JMenuItem();
+                               ret.setAction(a);
+                               ret.setText(name);
+                       }
+                       return ret;
+               }
+
+               private Action getActionFromTextField(String name) {
+                       ActionMap m = searchField.getActionMap();
+                       return m.get(name);
+               }
+
+               private boolean isClipboardContentsString(Clipboard c) {
+                       boolean ret = false;
+                       try {
+                               ret = c.isDataFlavorAvailable(DataFlavor.stringFlavor);
+                       } catch (IllegalStateException e) {
+                               e.printStackTrace();
+                       }
+                       return ret;
+               }
+
+               private Clipboard getClipboard() {
+                       Toolkit k = Toolkit.getDefaultToolkit();
+                       return k.getSystemClipboard();
+               }
+
+               @Override
+               public void show(Component invoker, int x, int y) {
+                       boolean s = searchField.getSelectedText() != null;
+                       cut.setEnabled(s);
+                       copy.setEnabled(s);
+                       paste.setEnabled(isClipboardContentsString(getClipboard()));
+                       clear.setEnabled(searchField.getText().length() != 0);
+                       super.show(invoker, x, y);
+               }
+       }
+
+}