• R/O
  • HTTP
  • SSH
  • HTTPS

Jindolf: Commit

Jindolfプロジェクトは、CGIゲーム「人狼BBS」を快適にプレイするための専用クライアントを製作するために発足したオープンソースプロジェクトです。


Commit MetaInfo

Revisão1621a6d5093037ba126caf830601f72248df457b (tree)
Hora2020-04-06 23:14:35
AutorOlyutorskii <olyutorskii@user...>
CommiterOlyutorskii

Mensagem de Log

Remove dialog editor.

Mudança Sumário

Diff

--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -7,6 +7,7 @@ Jindolf 変更履歴
77 3.304.X (2020-XX-XX)
88 ・G国亡国に伴い JinParser 2.102.2 に対応。
99 ・ログイン管理画面の廃止。
10+ ・発言エディタの廃止。
1011 ・JinArchiverによるXMLアーカイブファイルのビューア機能。
1112
1213 3.303.106 (2019-05-07)
--- a/src/main/java/jp/sfjp/jindolf/Controller.java
+++ b/src/main/java/jp/sfjp/jindolf/Controller.java
@@ -61,7 +61,6 @@ import jp.sfjp.jindolf.data.xml.VillageLoader;
6161 import jp.sfjp.jindolf.dxchg.CsvExporter;
6262 import jp.sfjp.jindolf.dxchg.WebIPCDialog;
6363 import jp.sfjp.jindolf.dxchg.WolfBBS;
64-import jp.sfjp.jindolf.editor.TalkPreview;
6564 import jp.sfjp.jindolf.glyph.AnchorHitEvent;
6665 import jp.sfjp.jindolf.glyph.AnchorHitListener;
6766 import jp.sfjp.jindolf.glyph.Discussion;
@@ -100,8 +99,6 @@ public class Controller
10099 private static final Logger LOGGER = Logger.getAnonymousLogger();
101100
102101 private static final String ERRTITLE_LAF = "Look&Feel";
103- private static final String ERRFORM_LAFLOAD =
104- "このLook&Feel[{0}]を読み込む事ができません。";
105102 private static final String ERRFORM_LAFGEN =
106103 "このLook&Feel[{0}]を生成する事ができません。";
107104
@@ -167,7 +164,6 @@ public class Controller
167164 reloadVillageListButton.setEnabled(false);
168165
169166 TopFrame topFrame = this.windowManager.getTopFrame();
170- TalkPreview talkPreview = this.windowManager.getTalkPreview();
171167 OptionPanel optionPanel = this.windowManager.getOptionPanel();
172168 FindPanel findPanel = this.windowManager.getFindPanel();
173169 FilterPanel filterPanel = this.windowManager.getFilterPanel();
@@ -193,15 +189,11 @@ public class Controller
193189
194190 ConfigStore config = this.appSetting.getConfigStore();
195191
196- JsObject draft = config.loadDraftConfig();
197- talkPreview.putJson(draft);
198-
199192 JsObject history = config.loadHistoryConfig();
200193 findPanel.putJson(history);
201194
202195 FontInfo fontInfo = this.appSetting.getFontInfo();
203196 periodTab.setFontInfo(fontInfo);
204- talkPreview.setFontInfo(fontInfo);
205197 optionPanel.getFontChooser().setFontInfo(fontInfo);
206198
207199 ProxyInfo proxyInfo = this.appSetting.getProxyInfo();
@@ -644,15 +636,6 @@ public class Controller
644636 }
645637
646638 /**
647- * 発言エディタを表示する。
648- */
649- private void actionTalkPreview(){
650- TalkPreview talkPreview = this.windowManager.getTalkPreview();
651- toggleWindow(talkPreview);
652- return;
653- }
654-
655- /**
656639 * オプション設定画面を表示する。
657640 */
658641 private void actionOption(){
@@ -694,11 +677,9 @@ public class Controller
694677
695678 this.topView.getTabBrowser().setFontInfo(newFontInfo);
696679
697- TalkPreview talkPreview = this.windowManager.getTalkPreview();
698680 OptionPanel optionPanel = this.windowManager.getOptionPanel();
699681 FontChooser fontChooser = optionPanel.getFontChooser();
700682
701- talkPreview.setFontInfo(newFontInfo);
702683 fontChooser.setFontInfo(newFontInfo);
703684
704685 return;
@@ -1483,9 +1464,6 @@ public class Controller
14831464 case ActionManager.CMD_SHOWFILT:
14841465 actionShowFilter();
14851466 break;
1486- case ActionManager.CMD_SHOWEDIT:
1487- actionTalkPreview();
1488- break;
14891467 case ActionManager.CMD_SHOWLOG:
14901468 actionShowLog();
14911469 break;
@@ -1585,12 +1563,6 @@ public class Controller
15851563 configStore.saveHistoryConfig(findConf);
15861564 }
15871565
1588- TalkPreview talkPreview = this.windowManager.getTalkPreview();
1589- JsObject draftConf = talkPreview.getJson();
1590- if( ! talkPreview.hasConfChanged(draftConf) ){
1591- configStore.saveDraftConfig(draftConf);
1592- }
1593-
15941566 this.appSetting.saveConfig();
15951567
15961568 LOGGER.info("VMごとアプリケーションを終了します。");
--- a/src/main/java/jp/sfjp/jindolf/config/ConfigStore.java
+++ b/src/main/java/jp/sfjp/jindolf/config/ConfigStore.java
@@ -42,8 +42,6 @@ public class ConfigStore {
4242
4343 /** 検索履歴ファイル。 */
4444 public static final File HIST_FILE = new File("searchHistory.json");
45- /** 原稿ファイル。 */
46- public static final File DRAFT_FILE = new File("draft.json");
4745 /** ネットワーク設定ファイル。 */
4846 public static final File NETCONFIG_FILE = new File("netconfig.json");
4947 /** 台詞表示設定ファイル。 */
@@ -396,16 +394,6 @@ public class ConfigStore {
396394 }
397395
398396 /**
399- * 原稿ファイルを読み込む。
400- *
401- * @return 原稿データ。原稿を読まないもしくは読めない場合はnull
402- */
403- public JsObject loadDraftConfig(){
404- JsObject result = loadJsObject(DRAFT_FILE);
405- return result;
406- }
407-
408- /**
409397 * ネットワーク設定ファイルを読み込む。
410398 *
411399 * @return ネットワーク設定データ。
@@ -451,17 +439,6 @@ public class ConfigStore {
451439 }
452440
453441 /**
454- * 原稿ファイルに書き込む。
455- *
456- * @param root 原稿データ
457- * @return 書き込まなかったもしくは書き込めなかった場合はfalse
458- */
459- public boolean saveDraftConfig(JsComposition<?> root){
460- boolean result = saveJson(DRAFT_FILE, root);
461- return result;
462- }
463-
464- /**
465442 * ネットワーク設定ファイルに書き込む。
466443 *
467444 * @param root ネットワーク設定
--- a/src/main/java/jp/sfjp/jindolf/editor/BalloonBorder.java
+++ /dev/null
@@ -1,177 +0,0 @@
1-/*
2- * baloon border
3- *
4- * License : The MIT License
5- * Copyright(c) 2008 olyutorskii
6- */
7-
8-package jp.sfjp.jindolf.editor;
9-
10-import java.awt.BorderLayout;
11-import java.awt.Color;
12-import java.awt.Component;
13-import java.awt.Graphics;
14-import java.awt.Graphics2D;
15-import java.awt.Insets;
16-import java.awt.LayoutManager;
17-import java.awt.RenderingHints;
18-import javax.swing.JComponent;
19-import javax.swing.border.Border;
20-
21-/**
22- * フキダシ風Border。
23- */
24-public class BalloonBorder implements Border{
25-
26- private static final int RADIUS = 5;
27-
28-
29- /**
30- * コンストラクタ。
31- */
32- public BalloonBorder(){
33- super();
34- return;
35- }
36-
37-
38- /**
39- * 隙間が透明なフキダシ装飾を任意のコンポーネントに施す。
40- * @param inner 装飾対象のコンポーネント
41- * @return 装飾されたコンポーネント
42- */
43- public static JComponent decorateTransparentBorder(JComponent inner){
44- JComponent result = new TransparentContainer(inner);
45-
46- Border border = new BalloonBorder();
47- result.setBorder(border);
48-
49- return result;
50- }
51-
52- /**
53- * {@inheritDoc}
54- * @param comp {@inheritDoc}
55- * @return {@inheritDoc}
56- */
57- @Override
58- public Insets getBorderInsets(Component comp){
59- Insets insets = new Insets(RADIUS, RADIUS, RADIUS, RADIUS);
60- return insets;
61- }
62-
63- /**
64- * {@inheritDoc}
65- * 必ずfalseを返す(このBorderは透明)。
66- * @return {@inheritDoc}
67- */
68- @Override
69- public boolean isBorderOpaque(){
70- return false;
71- }
72-
73- /**
74- * {@inheritDoc}
75- * @param comp {@inheritDoc}
76- * @param g {@inheritDoc}
77- * @param x {@inheritDoc}
78- * @param y {@inheritDoc}
79- * @param width {@inheritDoc}
80- * @param height {@inheritDoc}
81- */
82- @Override
83- public void paintBorder(Component comp,
84- Graphics g,
85- int x, int y,
86- int width, int height ){
87- final int diameter = RADIUS * 2;
88- final int innerWidth = width - diameter;
89- final int innerHeight = height - diameter;
90-
91- Graphics2D g2d = (Graphics2D) g;
92-
93- Color bgColor = comp.getBackground();
94- g2d.setColor(bgColor);
95-
96- Object antiAliaseHint =
97- g2d.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
98- g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
99- RenderingHints.VALUE_ANTIALIAS_ON );
100-
101- g2d.fillRect(x + RADIUS, y,
102- innerWidth, RADIUS);
103- g2d.fillRect(x, y + RADIUS,
104- RADIUS, innerHeight);
105- g2d.fillRect(x + RADIUS + innerWidth, y + RADIUS,
106- RADIUS, innerHeight);
107- g2d.fillRect(x + RADIUS, y + RADIUS + innerHeight,
108- innerWidth, RADIUS);
109-
110- int right = 90; // 90 degree right angle
111-
112- g2d.fillArc(x + innerWidth, y,
113- diameter, diameter, right * 0, right);
114- g2d.fillArc(x, y,
115- diameter, diameter, right * 1, right);
116- g2d.fillArc(x, y + innerHeight,
117- diameter, diameter, right * 2, right);
118- g2d.fillArc(x + innerWidth, y + innerHeight,
119- diameter, diameter, right * 3, right);
120-
121- g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, antiAliaseHint);
122-
123- return;
124- }
125-
126- /**
127- * 透明コンテナ。
128- * 1つの子を持ち、背景色操作を委譲する。
129- * つまりこのコンテナにBorderを設定すると子の背景色が反映される。
130- */
131- @SuppressWarnings("serial")
132- private static class TransparentContainer extends JComponent{
133-
134- private final JComponent inner;
135-
136- /**
137- * コンストラクタ。
138- * @param inner 内部コンポーネント
139- */
140- public TransparentContainer(JComponent inner){
141- super();
142-
143- this.inner = inner;
144-
145- setOpaque(false);
146-
147- LayoutManager layout = new BorderLayout();
148- setLayout(layout);
149- add(this.inner, BorderLayout.CENTER);
150-
151- return;
152- }
153-
154- /**
155- * {@inheritDoc}
156- * 子の背景色を返す。
157- * @return {@inheritDoc}
158- */
159- @Override
160- public Color getBackground(){
161- Color bg = this.inner.getBackground();
162- return bg;
163- }
164-
165- /**
166- * {@inheritDoc}
167- * 背景色指定をフックし、子の背景色を指定する。
168- * @param bg {@inheritDoc}
169- */
170- @Override
171- public void setBackground(Color bg){
172- this.inner.setBackground(bg);
173- return;
174- }
175- }
176-
177-}
--- a/src/main/java/jp/sfjp/jindolf/editor/EditArray.java
+++ /dev/null
@@ -1,741 +0,0 @@
1-/*
2- * エディタ集合の操作
3- *
4- * License : The MIT License
5- * Copyright(c) 2008 olyutorskii
6- */
7-
8-package jp.sfjp.jindolf.editor;
9-
10-import java.awt.Dimension;
11-import java.awt.EventQueue;
12-import java.awt.Font;
13-import java.awt.GridBagConstraints;
14-import java.awt.GridBagLayout;
15-import java.awt.LayoutManager;
16-import java.awt.Rectangle;
17-import java.awt.event.FocusEvent;
18-import java.awt.event.FocusListener;
19-import java.util.ArrayList;
20-import java.util.List;
21-import javax.swing.JPanel;
22-import javax.swing.Scrollable;
23-import javax.swing.SwingConstants;
24-import javax.swing.event.ChangeEvent;
25-import javax.swing.event.ChangeListener;
26-import javax.swing.event.DocumentEvent;
27-import javax.swing.event.DocumentListener;
28-import javax.swing.text.BadLocationException;
29-import javax.swing.text.Document;
30-import javax.swing.text.JTextComponent;
31-import javax.swing.text.NavigationFilter;
32-import javax.swing.text.Position.Bias;
33-
34-/**
35- * エディタ集合の操作。
36- * ※ このクラスはすべてシングルスレッドモデルで作られている。
37- */
38-@SuppressWarnings("serial")
39-public class EditArray extends JPanel
40- implements Scrollable,
41- FocusListener {
42-
43- private static final int MAX_EDITORS = 50;
44-
45- private final List<TalkEditor> editorList = new ArrayList<>();
46- private boolean onAdjusting = false;
47-
48- private final NavigationFilter keyNavigator = new CustomNavigation();
49- private final DocumentListener documentListener = new DocWatcher();
50-
51- private TalkEditor activeEditor;
52-
53- private Font textFont;
54-
55- /**
56- * コンストラクタ。
57- */
58- public EditArray(){
59- super();
60-
61- setOpaque(false);
62-
63- LayoutManager layout = new GridBagLayout();
64- setLayout(layout);
65-
66- TalkEditor firstEditor = incrementTalkEditor();
67- setActiveEditor(firstEditor);
68-
69- return;
70- }
71-
72- /**
73- * 個別エディタの生成を行う。
74- * @return エディタ
75- */
76- private TalkEditor createTalkEditor(){
77- TalkEditor editor = new TalkEditor();
78- editor.setNavigationFilter(this.keyNavigator);
79- editor.addTextFocusListener(this);
80- Document document = editor.getDocument();
81- document.addDocumentListener(this.documentListener);
82-
83- if(this.textFont == null){
84- this.textFont = editor.getTextFont();
85- }else{
86- editor.setTextFont(this.textFont);
87- }
88-
89- return editor;
90- }
91-
92- /**
93- * エディタ集合を一つ増やす。
94- * @return 増えたエディタ
95- */
96- private TalkEditor incrementTalkEditor(){
97- TalkEditor editor = createTalkEditor();
98-
99- GridBagConstraints constraints = new GridBagConstraints();
100-
101- constraints.gridx = 0;
102- constraints.gridy = GridBagConstraints.RELATIVE;
103-
104- constraints.gridwidth = GridBagConstraints.REMAINDER;
105- constraints.gridheight = 1;
106-
107- constraints.weightx = 1.0;
108- constraints.weighty = 0.0;
109-
110- constraints.fill = GridBagConstraints.HORIZONTAL;
111- constraints.anchor = GridBagConstraints.NORTHEAST;
112-
113- add(editor, constraints);
114-
115- this.editorList.add(editor);
116-
117- int sequenceNumber = this.editorList.size();
118- editor.setSequenceNumber(sequenceNumber);
119-
120- return editor;
121- }
122-
123- /**
124- * 1から始まる通し番号指定でエディタを取得する。
125- * 存在しない通し番号が指定された場合は新たにエディタが追加される。
126- * @param sequenceNumber 通し番号
127- * @return エディタ
128- */
129- private TalkEditor getTalkEditor(int sequenceNumber){
130- while(this.editorList.size() < sequenceNumber){
131- incrementTalkEditor();
132- }
133-
134- TalkEditor result = this.editorList.get(sequenceNumber - 1);
135-
136- return result;
137- }
138-
139- /**
140- * 指定したエディタの次の通し番号を持つエディタを返す。
141- * エディタがなければ追加される。
142- * @param editor エディタ
143- * @return 次のエディタ
144- */
145- private TalkEditor nextEditor(TalkEditor editor){
146- int sequenceNumber = editor.getSequenceNumber();
147- TalkEditor nextEditor = getTalkEditor(sequenceNumber + 1);
148- return nextEditor;
149- }
150-
151- /**
152- * 指定したエディタの前の通し番号を持つエディタを返す。
153- * @param editor エディタ
154- * @return 前のエディタ。
155- * 最初のエディタ(通し番号1)が指定されればnullを返す。
156- */
157- private TalkEditor prevEditor(TalkEditor editor){
158- int sequenceNumber = editor.getSequenceNumber();
159- if(sequenceNumber <= 1) return null;
160- TalkEditor prevEditor = getTalkEditor(sequenceNumber - 1);
161- return prevEditor;
162- }
163-
164- /**
165- * 指定したエディタがエディタ集合の最後のエディタか判定する。
166- * @param editor エディタ
167- * @return 最後のエディタならtrue
168- */
169- private boolean isLastEditor(TalkEditor editor){
170- int seqNo = editor.getSequenceNumber();
171- int size = this.editorList.size();
172- if(seqNo >= size) return true;
173- return false;
174- }
175-
176- /**
177- * Documentからその持ち主であるエディタを取得する。
178- * @param document Documentインスタンス
179- * @return 持ち主のエディタ。見つからなければnull。
180- */
181- private TalkEditor getEditorFromDocument(Document document){
182- for(TalkEditor editor : this.editorList){
183- if(editor.getDocument() == document) return editor;
184- }
185- return null;
186- }
187-
188- /**
189- * エディタ集合から任意のエディタを除く。
190- * ただし最初のエディタは消去不可。
191- * @param editor エディタ
192- */
193- private void removeEditor(TalkEditor editor){
194- if(editor.getParent() != this) return;
195-
196- int seqNo = editor.getSequenceNumber();
197- if(seqNo <= 1) return;
198- TalkEditor prevEditor = prevEditor(editor);
199- if(editor.isActive()){
200- setActiveEditor(prevEditor);
201- }
202- if(editor.hasEditorFocus()){
203- prevEditor.requestEditorFocus();
204- }
205-
206- this.editorList.remove(seqNo - 1);
207-
208- editor.setNavigationFilter(null);
209- editor.removeTextFocusListener(this);
210- Document document = editor.getDocument();
211- document.removeDocumentListener(this.documentListener);
212- editor.clearText();
213-
214- remove(editor);
215- revalidate();
216-
217- int renumber = 1;
218- for(TalkEditor newEditor : this.editorList){
219- newEditor.setSequenceNumber(renumber++);
220- }
221-
222- return;
223- }
224-
225- /**
226- * エディタ間文字調整タスクをディスパッチスレッドとして事後投入する。
227- * エディタ間文字調整タスクが実行中であれば何もしない。
228- * きっかけとなったエディタ上でIME操作が確定していなければ何もしない。
229- * @param triggerEvent ドキュメント変更イベント
230- */
231- private void detachAdjustTask(DocumentEvent triggerEvent){
232- if(this.onAdjusting) return;
233-
234- Document document = triggerEvent.getDocument();
235- final TalkEditor triggerEditor = getEditorFromDocument(document);
236- if(triggerEditor.onIMEoperation()) return;
237-
238- this.onAdjusting = true;
239-
240- EventQueue.invokeLater(new Runnable(){
241- @Override
242- public void run(){
243- try{
244- adjustTask(triggerEditor);
245- }finally{
246- EditArray.this.onAdjusting = false;
247- }
248- return;
249- }
250- });
251-
252- return;
253- }
254-
255- /**
256- * エディタ間文字調整タスク本体。
257- * @param triggerEditor タスク実行のきっかけとなったエディタ
258- */
259- private void adjustTask(TalkEditor triggerEditor){
260- int initCaretPos = triggerEditor.getCaretPosition();
261-
262- TalkEditor newFocus = null;
263- int newCaretPos = -1;
264-
265- TalkEditor current = triggerEditor;
266- for(;;){
267- TalkEditor next;
268-
269- if( ! isLastEditor(current) ){
270- next = nextEditor(current);
271- String nextContents = next.getText();
272- int nextLength = nextContents.length();
273-
274- current.appendTail(nextContents);
275- String rest = current.chopRest();
276- int restLength;
277- if(rest == null) restLength = 0;
278- else restLength = rest.length();
279-
280- int chopLength = nextLength - restLength;
281- if(chopLength > 0){
282- next.chopHead(chopLength);
283- }else if(chopLength < 0){
284- rest = rest.substring(0, -chopLength);
285- next.appendHead(rest);
286- }else{
287- if(newFocus == null){
288- newFocus = current;
289- newCaretPos = initCaretPos;
290- }
291- break;
292- }
293- }else{
294- String rest = current.chopRest();
295- if(rest == null || this.editorList.size() >= MAX_EDITORS){
296- if(newFocus == null){
297- newFocus = current;
298- if(current.getTextLength() >= initCaretPos){
299- newCaretPos = initCaretPos;
300- }else{
301- newCaretPos = current.getTextLength();
302- }
303- }
304- break;
305- }
306- next = nextEditor(current);
307- next.appendHead(rest);
308- }
309-
310- if(newFocus == null){
311- int currentLength = current.getTextLength();
312- if(initCaretPos >= currentLength){
313- initCaretPos -= currentLength;
314- }else{
315- newFocus = current;
316- newCaretPos = initCaretPos;
317- }
318- }
319-
320- current = next;
321- }
322-
323- if(newFocus != null){
324- newFocus.requestEditorFocus();
325- newFocus.setCaretPosition(newCaretPos);
326- }
327-
328- adjustEditorsTail();
329-
330- return;
331- }
332-
333- /**
334- * エディタ集合末尾の空エディタを切り詰める。
335- * ただし最初のエディタ(通し番号1)は削除されない。
336- * フォーカスを持つエディタが削除された場合は、
337- * 削除されなかった最後のエディタにフォーカスが移る。
338- */
339- private void adjustEditorsTail(){
340- int editorNum = this.editorList.size();
341- if(editorNum <= 0) return;
342- TalkEditor lastEditor = this.editorList.get(editorNum - 1);
343-
344- TalkEditor prevlostEditor = null;
345-
346- boolean lostFocusedEditor = false;
347-
348- for(;;){
349- int textLength = lastEditor.getTextLength();
350- int seqNo = lastEditor.getSequenceNumber();
351-
352- if(lostFocusedEditor){
353- prevlostEditor = lastEditor;
354- }
355-
356- if(textLength > 0) break;
357- if(seqNo <= 1) break;
358-
359- if(lastEditor.hasEditorFocus()) lostFocusedEditor = true;
360- removeEditor(lastEditor);
361-
362- lastEditor = prevEditor(lastEditor); // TODO ちょっと変
363- }
364-
365- if(prevlostEditor != null){
366- int textLength = prevlostEditor.getTextLength();
367- prevlostEditor.requestEditorFocus();
368- prevlostEditor.setCaretPosition(textLength);
369- }
370-
371- return;
372- }
373-
374- /**
375- * フォーカスを持つエディタを取得する。
376- * @return エディタ
377- */
378- public TalkEditor getFocusedTalkEditor(){
379- for(TalkEditor editor : this.editorList){
380- if(editor.hasEditorFocus()) return editor;
381- }
382- return null;
383- }
384-
385- /**
386- * フォーカスを持つエディタの次エディタがあればフォーカスを移し、
387- * カレット位置を0にする。
388- */
389- // TODO エディタのスクロール位置調整が必要。
390- public void forwardEditor(){
391- TalkEditor editor = getFocusedTalkEditor();
392- if(isLastEditor(editor)) return;
393- TalkEditor next = nextEditor(editor);
394- next.setCaretPosition(0);
395- next.requestEditorFocus();
396- return;
397- }
398-
399- /**
400- * フォーカスを持つエディタの前エディタがあればフォーカスを移し、
401- * カレット位置を末尾に置く。
402- */
403- public void backwardEditor(){
404- TalkEditor editor = getFocusedTalkEditor();
405- TalkEditor prev = prevEditor(editor);
406- if(prev == null) return;
407- int length = prev.getTextLength();
408- prev.setCaretPosition(length);
409- prev.requestEditorFocus();
410- return;
411- }
412-
413- /**
414- * 任意のエディタをアクティブにする。
415- * 同時にアクティブなエディタは一つのみ。
416- * @param editor アクティブにするエディタ
417- */
418- private void setActiveEditor(TalkEditor editor){
419- if(this.activeEditor != null){
420- this.activeEditor.setActive(false);
421- }
422-
423- this.activeEditor = editor;
424-
425- if(this.activeEditor != null){
426- this.activeEditor.setActive(true);
427- }
428-
429- fireChangeActive();
430-
431- return;
432- }
433-
434- /**
435- * アクティブなエディタを返す。
436- * @return アクティブなエディタ。
437- */
438- public TalkEditor getActiveEditor(){
439- return this.activeEditor;
440- }
441-
442- /**
443- * 全発言を連結した文字列を返す。
444- * @return 連結文字列
445- */
446- public CharSequence getAllText(){
447- StringBuilder result = new StringBuilder();
448-
449- for(TalkEditor editor : this.editorList){
450- String text = editor.getText();
451- result.append(text);
452- }
453-
454- return result;
455- }
456-
457- /**
458- * 先頭エディタの0文字目から字を詰め込む。
459- * 2番目移行のエディタへはみ出すかもしれない。
460- * @param seq 詰め込む文字列
461- */
462- public void setAllText(CharSequence seq){
463- TalkEditor firstEditor = getTalkEditor(1);
464- Document doc = firstEditor.getDocument();
465- try{
466- doc.insertString(0, seq.toString(), null);
467- }catch(BadLocationException e){
468- assert false;
469- }
470- return;
471- }
472-
473- /**
474- * 全エディタをクリアする。
475- */
476- public void clearAllEditor(){
477- int editorNum = this.editorList.size();
478- if(editorNum <= 0) return;
479-
480- TalkEditor lastEditor = this.editorList.get(editorNum - 1);
481- for(;;){
482- removeEditor(lastEditor);
483- lastEditor = prevEditor(lastEditor);
484- if(lastEditor == null) break;
485- }
486-
487- TalkEditor firstEditor = getTalkEditor(1);
488- firstEditor.clearText();
489- setActiveEditor(firstEditor);
490-
491- return;
492- }
493-
494- /**
495- * テキスト編集用フォントを指定する。
496- * @param textFont フォント
497- */
498- public void setTextFont(Font textFont){
499- this.textFont = textFont;
500- for(TalkEditor editor : this.editorList){
501- editor.setTextFont(this.textFont);
502- editor.repaint();
503- }
504- revalidate();
505- return;
506- }
507-
508- /**
509- * テキスト編集用フォントを取得する。
510- * @return フォント
511- */
512- public Font getTextFont(){
513- return this.textFont;
514- }
515-
516- /**
517- * アクティブエディタ変更通知用リスナの登録。
518- * @param listener リスナ
519- */
520- public void addChangeListener(ChangeListener listener){
521- this.listenerList.add(ChangeListener.class, listener);
522- return;
523- }
524-
525- /**
526- * アクティブエディタ変更通知用リスナの削除。
527- * @param listener リスナ
528- */
529- public void removeChangeListener(ChangeListener listener){
530- this.listenerList.remove(ChangeListener.class, listener);
531- return;
532- }
533-
534- /**
535- * アクティブエディタ変更通知を行う。
536- */
537- private void fireChangeActive(){
538- ChangeEvent event = new ChangeEvent(this);
539-
540- ChangeListener[] listeners =
541- this.listenerList.getListeners(ChangeListener.class);
542- for(ChangeListener listener : listeners){
543- listener.stateChanged(event);
544- }
545-
546- return;
547- }
548-
549- /**
550- * {@inheritDoc}
551- * エディタのフォーカス取得とともにアクティブ状態にする。
552- * @param event {@inheritDoc}
553- */
554- @Override
555- public void focusGained(FocusEvent event){
556- Object source = event.getSource();
557- if( ! (source instanceof JTextComponent) ) return;
558- JTextComponent textComp = (JTextComponent) source;
559-
560- Document document = textComp.getDocument();
561- TalkEditor editor = getEditorFromDocument(document);
562-
563- setActiveEditor(editor);
564-
565- return;
566- }
567-
568- /**
569- * {@inheritDoc}
570- * @param event {@inheritDoc}
571- */
572- @Override
573- public void focusLost(FocusEvent event){
574- // NOTHING
575- return;
576- }
577-
578- /**
579- * {@inheritDoc}
580- * @return {@inheritDoc}
581- */
582- @Override
583- public Dimension getPreferredScrollableViewportSize(){
584- Dimension result = getPreferredSize();
585- return result;
586- }
587-
588- /**
589- * {@inheritDoc}
590- * 横スクロールバーを極力出さないようレイアウトでがんばる。
591- * @return {@inheritDoc}
592- */
593- @Override
594- public boolean getScrollableTracksViewportWidth(){
595- return true;
596- }
597-
598- /**
599- * {@inheritDoc}
600- * 縦スクロールバーを出しても良いのでレイアウトでがんばらない。
601- * @return {@inheritDoc}
602- */
603- @Override
604- public boolean getScrollableTracksViewportHeight(){
605- return false;
606- }
607-
608- /**
609- * {@inheritDoc}
610- * @param visibleRect {@inheritDoc}
611- * @param orientation {@inheritDoc}
612- * @param direction {@inheritDoc}
613- * @return {@inheritDoc}
614- */
615- @Override
616- public int getScrollableBlockIncrement(Rectangle visibleRect,
617- int orientation,
618- int direction ){
619- if(orientation == SwingConstants.VERTICAL){
620- return visibleRect.height;
621- }
622- return 10;
623- }
624-
625- /**
626- * {@inheritDoc}
627- * @param visibleRect {@inheritDoc}
628- * @param orientation {@inheritDoc}
629- * @param direction {@inheritDoc}
630- * @return {@inheritDoc}
631- */
632- @Override
633- public int getScrollableUnitIncrement(Rectangle visibleRect,
634- int orientation,
635- int direction ){
636- return 30; // TODO フォント高の1.5倍くらい?
637- }
638-
639- /**
640- * エディタ内のカーソル移動を監視するための、
641- * カスタム化したナビゲーションフィルター。
642- * 必要に応じてエディタ間カーソル移動を行う。
643- */
644- private class CustomNavigation extends NavigationFilter{
645-
646- /**
647- * コンストラクタ。
648- */
649- public CustomNavigation(){
650- super();
651- return;
652- }
653-
654- /**
655- * {@inheritDoc}
656- * カーソル移動が行き詰まった場合、
657- * 隣接するエディタ間でカーソル移動を行う。
658- * @param text {@inheritDoc}
659- * @param pos {@inheritDoc}
660- * @param bias {@inheritDoc}
661- * @param direction {@inheritDoc}
662- * @param biasRet {@inheritDoc}
663- * @return {@inheritDoc}
664- * @throws javax.swing.text.BadLocationException {@inheritDoc}
665- */
666- @Override
667- public int getNextVisualPositionFrom(JTextComponent text,
668- int pos,
669- Bias bias,
670- int direction,
671- Bias[] biasRet )
672- throws BadLocationException {
673- int result = super.getNextVisualPositionFrom(text,
674- pos,
675- bias,
676- direction,
677- biasRet );
678- if(result != pos) return result;
679-
680- switch(direction){
681- case SwingConstants.WEST:
682- case SwingConstants.NORTH:
683- backwardEditor();
684- break;
685- case SwingConstants.EAST:
686- case SwingConstants.SOUTH:
687- forwardEditor();
688- break;
689- default:
690- assert false;
691- }
692-
693- return result;
694- }
695- }
696-
697- /**
698- * エディタの内容変更を監視し、随時エディタ間調整を行う。
699- */
700- private class DocWatcher implements DocumentListener{
701-
702- /**
703- * コンストラクタ。
704- */
705- public DocWatcher(){
706- super();
707- return;
708- }
709-
710- /**
711- * {@inheritDoc}
712- * @param event {@inheritDoc}
713- */
714- @Override
715- public void changedUpdate(DocumentEvent event){
716- detachAdjustTask(event);
717- return;
718- }
719-
720- /**
721- * {@inheritDoc}
722- * @param event {@inheritDoc}
723- */
724- @Override
725- public void insertUpdate(DocumentEvent event){
726- detachAdjustTask(event);
727- return;
728- }
729-
730- /**
731- * {@inheritDoc}
732- * @param event {@inheritDoc}
733- */
734- @Override
735- public void removeUpdate(DocumentEvent event){
736- detachAdjustTask(event);
737- return;
738- }
739- }
740-
741-}
--- a/src/main/java/jp/sfjp/jindolf/editor/TalkEditor.java
+++ /dev/null
@@ -1,551 +0,0 @@
1-/*
2- * 原稿作成支援エディタ
3- *
4- * License : The MIT License
5- * Copyright(c) 2008 olyutorskii
6- */
7-
8-package jp.sfjp.jindolf.editor;
9-
10-import java.awt.Color;
11-import java.awt.Dimension;
12-import java.awt.Font;
13-import java.awt.GridBagConstraints;
14-import java.awt.GridBagLayout;
15-import java.awt.Insets;
16-import java.awt.LayoutManager;
17-import java.awt.Rectangle;
18-import java.awt.event.FocusListener;
19-import javax.swing.BorderFactory;
20-import javax.swing.JComponent;
21-import javax.swing.JLabel;
22-import javax.swing.JPanel;
23-import javax.swing.JPopupMenu;
24-import javax.swing.border.Border;
25-import javax.swing.event.DocumentEvent;
26-import javax.swing.event.DocumentListener;
27-import javax.swing.text.BadLocationException;
28-import javax.swing.text.Document;
29-import javax.swing.text.NavigationFilter;
30-import javax.swing.text.PlainDocument;
31-import javax.swing.text.Segment;
32-import jp.sfjp.jindolf.dxchg.TextPopup;
33-
34-/**
35- * 原稿作成支援エディタ。
36- * 文字数行数管理などを行う。
37- * 200文字もしくは10行まで入力可能。
38- * ※ 10回目に出現する改行文字は許される。
39- * ※ 2010-11-27以降、G国では5行制限が10行に緩和された。
40- */
41-@SuppressWarnings("serial")
42-public class TalkEditor
43- extends JPanel
44- implements DocumentListener {
45-
46- private static final int MAX_CHARS = 200;
47- private static final int MAX_LINES = 10;
48-
49- private static final Color COLOR_ACTIVATED = Color.GRAY;
50-
51-
52- private final PlainDocument document = new PlainDocument();
53-
54- private int sequenceNumber;
55-
56- private boolean isActive = false;
57-
58- private final JLabel seqCount = new JLabel();
59- private final JLabel talkStat = new JLabel();
60- private final TextEditor textEditor = new TextEditor();
61-
62- private Font textFont;
63-
64-
65- /**
66- * コンストラクタ。
67- * 通し番号は0が指定される。
68- */
69- public TalkEditor(){
70- this(0);
71- return;
72- }
73-
74- /**
75- * コンストラクタ。
76- * @param seqNumber 通し番号
77- */
78- @SuppressWarnings("LeakingThisInConstructor")
79- private TalkEditor(int seqNumber){
80- super();
81-
82- setOpaque(true);
83-
84- this.document.addDocumentListener(this);
85-
86- this.seqCount.setForeground(Color.WHITE);
87- this.talkStat.setForeground(Color.WHITE);
88- this.seqCount.setOpaque(false);
89- this.talkStat.setOpaque(false);
90-
91- this.textEditor.setMargin(new Insets(3, 3, 3, 3));
92- this.textEditor.setDocument(this.document);
93-
94- JPopupMenu popup = new TextPopup();
95- this.textEditor.setComponentPopupMenu(popup);
96-
97- this.textFont = this.textEditor.getFont();
98-
99- setSequenceNumber(seqNumber);
100- updateStat();
101- setActive(false);
102-
103- design();
104-
105- return;
106- }
107-
108-
109- /**
110- * 指定された文字列の指定された位置から、
111- * 最大何文字まで1発言におさめる事ができるか判定する。
112- * @param source 検査対象
113- * @param start 検査開始位置
114- * @return 1発言に納めていい長さ。
115- */
116- public static int choplimit(CharSequence source, int start){
117- int length = source.length();
118- if(start >= length) return 0;
119-
120- int chars = 0;
121- int lines = 0;
122-
123- for(int pos = start; pos < length; pos++){
124- chars++;
125- if(chars >= MAX_CHARS) break;
126- char ch = source.charAt(pos);
127- if(ch == '\n'){
128- lines++;
129- if(lines >= MAX_LINES) break;
130- }
131- }
132-
133- return chars;
134- }
135-
136- /**
137- * レイアウトを行う。
138- */
139- private void design(){
140- LayoutManager layout = new GridBagLayout();
141- GridBagConstraints constraints = new GridBagConstraints();
142-
143- setLayout(layout);
144-
145- constraints.gridx = 0;
146- constraints.gridy = 0;
147- constraints.gridwidth = 1;
148- constraints.gridheight = 1;
149- constraints.weightx = 0.0;
150- constraints.weighty = 0.0;
151- constraints.fill = GridBagConstraints.NONE;
152- constraints.anchor = GridBagConstraints.NORTHWEST;
153- constraints.insets = new Insets(0, 0, 1, 3);
154- add(this.seqCount, constraints);
155-
156- constraints.gridx = 1;
157- constraints.gridy = 0;
158- constraints.gridwidth = 1;
159- constraints.gridheight = 2;
160- constraints.weightx = 1.0;
161- constraints.weighty = 0.0;
162- constraints.fill = GridBagConstraints.HORIZONTAL;
163- constraints.anchor = GridBagConstraints.NORTHWEST;
164- constraints.insets = new Insets(0, 0, 0, 0);
165- JComponent decorated =
166- BalloonBorder.decorateTransparentBorder(this.textEditor);
167- add(decorated, constraints);
168-
169- constraints.gridx = 0;
170- constraints.gridy = 1;
171- constraints.gridwidth = 1;
172- constraints.gridheight = 1;
173- constraints.weightx = 0.0;
174- constraints.weighty = 0.0;
175- constraints.fill = GridBagConstraints.NONE;
176- constraints.anchor = GridBagConstraints.NORTHEAST;
177- constraints.insets = new Insets(0, 0, 0, 3);
178- add(this.talkStat, constraints);
179-
180- Border border = BorderFactory.createEmptyBorder(5, 5, 5, 5);
181- setBorder(border);
182-
183- return;
184- }
185-
186- /**
187- * テキスト編集用フォントを指定する。
188- * @param textFont フォント
189- */
190- public void setTextFont(Font textFont){
191- this.textFont = textFont;
192- this.textEditor.setFont(this.textFont);
193- this.textEditor.repaint();
194- revalidate();
195- return;
196- }
197-
198- /**
199- * テキスト編集用フォントを取得する。
200- * @return フォント
201- */
202- public Font getTextFont(){
203- return this.textFont;
204- }
205-
206- /**
207- * テキストコンポーネントにNavigationFilterを設定する。
208- * @param navigator ナビゲーションフィルタ
209- */
210- public void setNavigationFilter(NavigationFilter navigator){
211- this.textEditor.setNavigationFilter(navigator);
212- return;
213- }
214-
215- /**
216- * 通し番号を取得する。
217- * @return 通し番号
218- */
219- public int getSequenceNumber(){
220- return this.sequenceNumber;
221- }
222-
223- /**
224- * 通し番号を設定する。
225- * @param seqNumber 通し番号
226- */
227- public void setSequenceNumber(int seqNumber){
228- this.sequenceNumber = seqNumber;
229- String seqText = "=== #" + this.sequenceNumber + " ===";
230- this.seqCount.setText(seqText);
231- return;
232- }
233-
234- /**
235- * Documentを取得する。
236- * @return 管理中のDocument
237- */
238- public Document getDocument(){
239- return this.document;
240- }
241-
242- /**
243- * 現在のエディタの文字列内容を取得する。
244- * @return 文字列内容
245- */
246- public String getText(){
247- int length = this.document.getLength();
248- String result = "";
249- try{
250- result = this.document.getText(0, length);
251- }catch(BadLocationException e){
252- assert false;
253- }
254- return result;
255- }
256-
257- /**
258- * 現在のエディタの文字列長を取得する。
259- * @return 文字列長
260- */
261- public int getTextLength(){
262- return this.document.getLength();
263- }
264-
265- /**
266- * 現在の行数を取得する。
267- * ※ 改行文字の総数より一つ多い場合もある。
268- * @return 行数
269- */
270- private int getTextLines(){
271- int lines = 0;
272-
273- Segment segment = new Segment();
274- segment.setPartialReturn(true);
275-
276- boolean hasLineContents = false;
277- int pos = 0;
278- int remain = getTextLength();
279- while(remain > 0){
280- try{
281- this.document.getText(pos, remain, segment);
282- }catch(BadLocationException e){
283- assert false;
284- }
285-
286- for(;;){
287- char ch = segment.current();
288- if(ch == Segment.DONE) break;
289-
290- if(ch == '\n'){
291- if( ! hasLineContents ){
292- lines++;
293- }
294- hasLineContents = false;
295- }else if( ! hasLineContents ){
296- hasLineContents = true;
297- lines++;
298- }
299-
300- segment.next();
301- }
302-
303- pos += segment.count;
304- remain -= segment.count;
305- }
306-
307- return lines;
308- }
309-
310- /**
311- * エディタ先頭に文字列を挿入する。
312- * @param text 挿入文字列
313- */
314- public void appendHead(CharSequence text){
315- if(text == null) return;
316- if(text.length() <= 0) return;
317-
318- try{
319- this.document.insertString(0, text.toString(), null);
320- }catch(BadLocationException e){
321- assert false;
322- }
323-
324- return;
325- }
326-
327- /**
328- * エディタ末尾に文字列を追加する。
329- * @param text 追加文字列
330- */
331- public void appendTail(CharSequence text){
332- if(text == null) return;
333- if(text.length() <= 0) return;
334-
335- int offset = getTextLength();
336- try{
337- this.document.insertString(offset, text.toString(), null);
338- }catch(BadLocationException e){
339- assert false;
340- }
341-
342- return;
343- }
344-
345- /**
346- * エディタ先頭から文字列を削除する。
347- * @param chopLength 削除文字数
348- */
349- public void chopHead(int chopLength){
350- if(chopLength <= 0) return;
351-
352- int modLength;
353- int textLength = getTextLength();
354- if(chopLength > textLength) modLength = textLength;
355- else modLength = chopLength;
356-
357- try{
358- this.document.remove(0, modLength);
359- }catch(BadLocationException e){
360- assert false;
361- }
362-
363- return;
364- }
365-
366- /**
367- * テキストを空にする。
368- */
369- public void clearText(){
370- int textLength = this.document.getLength();
371- try{
372- this.document.remove(0, textLength);
373- }catch(BadLocationException e){
374- assert false;
375- }
376- return;
377- }
378-
379- /**
380- * アクティブ状態を指定する。
381- * アクティブ状態の場合、背景色が変わる。
382- * @param isActiveArg trueならアクティブ状態
383- */
384- public void setActive(boolean isActiveArg){
385- this.isActive = isActiveArg;
386-
387- if(this.isActive){
388- setOpaque(true);
389- setBackground(COLOR_ACTIVATED);
390- Dimension size = getSize();
391- Rectangle bounds = new Rectangle(size);
392- scrollRectToVisible(bounds);
393- this.textEditor.scrollCaretToVisible();
394- }else{
395- setOpaque(false);
396- }
397-
398- repaint();
399-
400- return;
401- }
402-
403- /**
404- * アクティブ状態を取得する。
405- * @return アクティブ状態ならtrue
406- */
407- public boolean isActive(){
408- return this.isActive;
409- }
410-
411- /**
412- * エディタが現在IME操作中か判定する。
413- * @return IME操作中ならtrue
414- */
415- public boolean onIMEoperation(){
416- boolean result = this.textEditor.onIMEoperation();
417- return result;
418- }
419-
420- /**
421- * エディタの現在のカーソル位置を取得する。
422- * @return 0から始まるカーソル位置
423- */
424- public int getCaretPosition(){
425- int caretPos = this.textEditor.getCaretPosition();
426- return caretPos;
427- }
428-
429- /**
430- * エディタのカーソル位置を設定する。
431- * @param pos 0から始まるカーソル位置
432- * @throws java.lang.IllegalArgumentException 範囲外のカーソル位置指定
433- */
434- public void setCaretPosition(int pos) throws IllegalArgumentException{
435- this.textEditor.setCaretPosition(pos);
436- return;
437- }
438-
439- /**
440- * 集計情報表示(文字数、行数)を更新する。
441- */
442- private void updateStat(){
443- if(onIMEoperation()) return;
444-
445- int charTotal = getTextLength();
446- int lineNumber = getTextLines();
447-
448- StringBuilder statistics = new StringBuilder();
449- statistics.append(charTotal)
450- .append("字 ")
451- .append(lineNumber)
452- .append("行");
453- this.talkStat.setText(statistics.toString());
454-
455- return;
456- }
457-
458- /**
459- * このテキストエディタに収まらない末尾文章を切り出す。
460- * @return 最小の末尾文書。余裕があり切り出す必要がなければnullを返す。
461- */
462- public String chopRest(){
463- String text = getText();
464- int textLength = getTextLength();
465- int choppedlen = choplimit(text, 0);
466-
467- int restLength = textLength - choppedlen;
468- if(restLength <= 0) return null;
469-
470- String rest = null;
471- try{
472- rest = this.document.getText(choppedlen, restLength);
473- this.document.remove(choppedlen, restLength);
474- }catch(BadLocationException e){
475- assert false;
476- }
477-
478- return rest;
479- }
480-
481- /**
482- * テキストエディタにフォーカスを設定する。
483- * @return 絶対失敗する場合はfalse
484- */
485- public boolean requestEditorFocus(){
486- boolean result = this.textEditor.requestFocusInWindow();
487- return result;
488- }
489-
490- /**
491- * テキストエディタがフォーカスを保持しているか判定する。
492- * @return フォーカスを保持していればtrue
493- */
494- public boolean hasEditorFocus(){
495- boolean result = this.textEditor.hasFocus();
496- return result;
497- }
498-
499- /**
500- * 子エディタのフォーカス監視リスナを登録する。
501- * @param listener FocusListener
502- */
503- public void addTextFocusListener(FocusListener listener){
504- this.textEditor.addFocusListener(listener);
505- return;
506- }
507-
508- /**
509- * 子エディタからフォーカス監視リスナを外す。
510- * @param listener FocusListener
511- */
512- public void removeTextFocusListener(FocusListener listener){
513- this.textEditor.removeFocusListener(listener);
514- return;
515- }
516-
517- /**
518- * {@inheritDoc}
519- * 集計情報を更新する。
520- * @param event {@inheritDoc}
521- */
522- // TODO いつ呼ばれるのか不明
523- @Override
524- public void changedUpdate(DocumentEvent event){
525- updateStat();
526- return;
527- }
528-
529- /**
530- * {@inheritDoc}
531- * 集計情報を更新する。
532- * @param event {@inheritDoc}
533- */
534- @Override
535- public void insertUpdate(DocumentEvent event){
536- updateStat();
537- return;
538- }
539-
540- /**
541- * {@inheritDoc}
542- * 集計情報を更新する。
543- * @param event {@inheritDoc}
544- */
545- @Override
546- public void removeUpdate(DocumentEvent event){
547- updateStat();
548- return;
549- }
550-
551-}
--- a/src/main/java/jp/sfjp/jindolf/editor/TalkPreview.java
+++ /dev/null
@@ -1,516 +0,0 @@
1-/*
2- * 発言エディットパネル
3- *
4- * License : The MIT License
5- * Copyright(c) 2008 olyutorskii
6- */
7-
8-package jp.sfjp.jindolf.editor;
9-
10-import java.awt.BorderLayout;
11-import java.awt.Color;
12-import java.awt.Container;
13-import java.awt.Font;
14-import java.awt.GridBagConstraints;
15-import java.awt.GridBagLayout;
16-import java.awt.Insets;
17-import java.awt.LayoutManager;
18-import java.awt.event.ActionEvent;
19-import java.awt.event.ActionListener;
20-import java.io.File;
21-import javax.swing.BorderFactory;
22-import javax.swing.JButton;
23-import javax.swing.JComponent;
24-import javax.swing.JFrame;
25-import javax.swing.JLabel;
26-import javax.swing.JOptionPane;
27-import javax.swing.JPanel;
28-import javax.swing.JPopupMenu;
29-import javax.swing.JScrollPane;
30-import javax.swing.JSplitPane;
31-import javax.swing.JViewport;
32-import javax.swing.border.BevelBorder;
33-import javax.swing.border.Border;
34-import javax.swing.border.TitledBorder;
35-import javax.swing.event.ChangeEvent;
36-import javax.swing.event.ChangeListener;
37-import javax.swing.text.JTextComponent;
38-import jp.sfjp.jindolf.dxchg.ClipboardAction;
39-import jp.sfjp.jindolf.dxchg.TextPopup;
40-import jp.sfjp.jindolf.glyph.FontInfo;
41-import jp.sfjp.jindolf.util.GUIUtils;
42-import jp.sourceforge.jovsonz.JsArray;
43-import jp.sourceforge.jovsonz.JsComposition;
44-import jp.sourceforge.jovsonz.JsObject;
45-import jp.sourceforge.jovsonz.JsString;
46-import jp.sourceforge.jovsonz.JsTypes;
47-import jp.sourceforge.jovsonz.JsValue;
48-
49-/**
50- * 発言エディットパネル。
51- */
52-@SuppressWarnings("serial")
53-public class TalkPreview extends JFrame
54- implements ActionListener, ChangeListener{
55-
56- /** 原稿ファイル。 */
57- public static final File DRAFT_FILE = new File("draft.json");
58-
59- private static final Color COLOR_EDITORBACK = Color.BLACK;
60-
61- private final JTextComponent freeMemo = new TextEditor();
62-
63- private final EditArray editArray = new EditArray();
64-
65- private final JButton cutButton = new JButton("カット");
66- private final JButton copyButton = new JButton("コピー");
67- private final JButton clearButton = new JButton("クリア");
68- private final JButton cutAllButton = new JButton("全カット");
69- private final JButton copyAllButton = new JButton("全コピー");
70- private final JButton clearAllButton = new JButton("全クリア");
71- private final JButton closeButton = new JButton("閉じる");
72- private final TitledBorder numberBorder =
73- BorderFactory.createTitledBorder("");
74- private final JComponent singleGroup = buildSingleGroup();
75- private final JComponent multiGroup = buildMultiGroup();
76- private final JLabel letsBrowser =
77- new JLabel("投稿はWebブラウザからどうぞ");
78-
79- private JsObject loadedDraft = null;
80-
81- /**
82- * コンストラクタ。
83- */
84- @SuppressWarnings("LeakingThisInConstructor")
85- public TalkPreview(){
86- super();
87-
88- GUIUtils.modifyWindowAttributes(this, true, false, true);
89-
90- setDefaultCloseOperation(HIDE_ON_CLOSE);
91-
92- this.cutButton .addActionListener(this);
93- this.copyButton .addActionListener(this);
94- this.clearButton .addActionListener(this);
95- this.cutAllButton .addActionListener(this);
96- this.copyAllButton .addActionListener(this);
97- this.clearAllButton .addActionListener(this);
98- this.closeButton .addActionListener(this);
99-
100- this.editArray.addChangeListener(this);
101-
102- Container content = getContentPane();
103- design(content);
104-
105- setBorderNumber(1);
106-
107- return;
108- }
109-
110- /**
111- * レイアウトを行う。
112- * @param content コンテナ
113- */
114- private void design(Container content){
115- JComponent freeNotePanel = buildFreeNotePanel();
116-
117- JScrollPane scrollPane = new JScrollPane();
118- scrollPane.setHorizontalScrollBarPolicy(
119- JScrollPane.HORIZONTAL_SCROLLBAR_NEVER
120- );
121- JViewport viewPort = new JViewport();
122- viewPort.setBackground(COLOR_EDITORBACK);
123- viewPort.setView(this.editArray);
124- scrollPane.setViewport(viewPort);
125-
126- LayoutManager layout;
127- Border border;
128-
129- JComponent editPanel = new JPanel();
130- layout = new BorderLayout();
131- editPanel.setLayout(layout);
132- editPanel.add(scrollPane, BorderLayout.CENTER);
133- JComponent buttonPanel = buildButtonPanel();
134- editPanel.add(buttonPanel, BorderLayout.EAST);
135- border = BorderFactory.createTitledBorder("発言編集");
136- editPanel.setBorder(border);
137-
138- JSplitPane split = new JSplitPane();
139- split.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
140- split.setContinuousLayout(false);
141- split.setDividerSize(10);
142- split.setDividerLocation(200);
143- split.setOneTouchExpandable(true);
144- split.setLeftComponent(freeNotePanel);
145- split.setRightComponent(editPanel);
146-
147- Border inside = BorderFactory.createBevelBorder(BevelBorder.LOWERED);
148- Border outside = BorderFactory.createEmptyBorder(2, 5, 2, 2);
149- border = BorderFactory.createCompoundBorder(inside, outside);
150- this.letsBrowser.setBorder(border);
151-
152- layout = new BorderLayout();
153- content.setLayout(layout);
154- content.add(split, BorderLayout.CENTER);
155- content.add(this.letsBrowser, BorderLayout.SOUTH);
156-
157- return;
158- }
159-
160- /**
161- * ボタン群を生成する。
162- * @return ボタン群
163- */
164- private JComponent buildButtonPanel(){
165- JPanel panel = new JPanel();
166-
167- LayoutManager layout = new GridBagLayout();
168- GridBagConstraints constraints = new GridBagConstraints();
169-
170- panel.setLayout(layout);
171-
172- constraints.weightx = 1.0;
173- constraints.weighty = 0.0;
174- constraints.fill = GridBagConstraints.NONE;
175- constraints.anchor = GridBagConstraints.WEST;
176- constraints.gridx = 1;
177- constraints.gridy = GridBagConstraints.RELATIVE;
178- constraints.gridwidth = 1;
179- constraints.gridheight = 1;
180-
181-
182- constraints.insets = new Insets(3, 3, 3, 3);
183- panel.add(this.singleGroup, constraints);
184-
185- constraints.insets = new Insets(10, 3, 3, 3);
186- panel.add(this.multiGroup, constraints);
187-
188- constraints.weighty = 1.0;
189- constraints.anchor = GridBagConstraints.SOUTH;
190- constraints.insets = new Insets(3, 3, 10, 3);
191- panel.add(this.closeButton, constraints);
192-
193- return panel;
194- }
195-
196- /**
197- * アクティブ発言操作ボタン群を生成する。
198- * @return ボタン群
199- */
200- private JComponent buildSingleGroup(){
201- JComponent panel = new JPanel();
202-
203- LayoutManager layout = new GridBagLayout();
204- GridBagConstraints constraints = new GridBagConstraints();
205-
206- panel.setLayout(layout);
207-
208- constraints.weightx = 1.0;
209- constraints.weighty = 0.0;
210- constraints.fill = GridBagConstraints.HORIZONTAL;
211- constraints.gridx = 1;
212- constraints.gridy = GridBagConstraints.RELATIVE;
213- constraints.gridwidth = 1;
214- constraints.gridheight = 1;
215- constraints.insets = new Insets(3, 3, 3, 3);
216-
217- panel.add(this.cutButton, constraints);
218- panel.add(this.copyButton, constraints);
219- panel.add(this.clearButton, constraints);
220-
221- panel.setBorder(this.numberBorder);
222-
223- return panel;
224- }
225-
226- /**
227- * 全発言操作ボタン群を生成する。
228- * @return ボタン群
229- */
230- private JComponent buildMultiGroup(){
231- JComponent panel = new JPanel();
232-
233- LayoutManager layout = new GridBagLayout();
234- GridBagConstraints constraints = new GridBagConstraints();
235-
236- panel.setLayout(layout);
237-
238- constraints.weightx = 1.0;
239- constraints.weighty = 0.0;
240- constraints.fill = GridBagConstraints.HORIZONTAL;
241- constraints.gridx = 1;
242- constraints.gridy = GridBagConstraints.RELATIVE;
243- constraints.gridwidth = 1;
244- constraints.gridheight = 1;
245- constraints.insets = new Insets(3, 3, 3, 3);
246-
247- panel.add(this.cutAllButton, constraints);
248- panel.add(this.copyAllButton, constraints);
249- panel.add(this.clearAllButton, constraints);
250-
251- Border border = BorderFactory.createTitledBorder("全発言を");
252- panel.setBorder(border);
253-
254- return panel;
255- }
256-
257- /**
258- * フリーノート部を生成する。
259- * @return フリーノート部
260- */
261- private JComponent buildFreeNotePanel(){
262- Insets margin = new Insets(3, 3, 3, 3);
263- this.freeMemo.setMargin(margin);
264- JPopupMenu popup = new TextPopup();
265- this.freeMemo.setComponentPopupMenu(popup);
266-
267- JScrollPane scrollPane = new JScrollPane();
268- scrollPane.setHorizontalScrollBarPolicy(
269- JScrollPane.HORIZONTAL_SCROLLBAR_NEVER
270- );
271- JViewport viewPort = new JViewport();
272- viewPort.setView(this.freeMemo);
273- scrollPane.setViewport(viewPort);
274-
275- JComponent panel = new JPanel();
276-
277- LayoutManager layout = new GridBagLayout();
278- GridBagConstraints constraints = new GridBagConstraints();
279-
280- panel.setLayout(layout);
281-
282- constraints.weightx = 1.0;
283- constraints.weighty = 1.0;
284- constraints.fill = GridBagConstraints.BOTH;
285- constraints.insets = new Insets(1, 1, 1, 1);
286- panel.add(scrollPane, constraints);
287-
288- Border border = BorderFactory.createTitledBorder("フリーメモ");
289- panel.setBorder(border);
290-
291- return panel;
292- }
293-
294- /**
295- * アクティブ発言の通し番号表示を更新。
296- * @param num 通し番号
297- */
298- private void setBorderNumber(int num){
299- String title = "発言#"+num+" を";
300- this.numberBorder.setTitle(title);
301- this.singleGroup.revalidate();
302- this.singleGroup.repaint();
303- return;
304- }
305-
306- /**
307- * テキスト編集用フォントを指定する。
308- * 描画属性は無視される。
309- * @param fontInfo フォント設定
310- */
311- public void setFontInfo(FontInfo fontInfo){
312- setTextFont(fontInfo.getFont());
313- return;
314- }
315-
316- /**
317- * テキスト編集用フォントを指定する。
318- * @param textFont フォント
319- */
320- public void setTextFont(Font textFont){
321- this.freeMemo.setFont(textFont);
322- this.editArray.setTextFont(textFont);
323- return;
324- }
325-
326- /**
327- * テキスト編集用フォントを取得する。
328- * @return フォント
329- */
330- public Font getTextFont(){
331- return this.editArray.getTextFont();
332- }
333-
334- /**
335- * 発言クリア操作の確認ダイアログを表示する。
336- * @return OKなら0, Cancelなら2
337- */
338- private int warnClear(){
339- int result = JOptionPane.showConfirmDialog(
340- this,
341- "本当に発言をクリアしてもよいですか?",
342- "発言クリア確認",
343- JOptionPane.OK_CANCEL_OPTION,
344- JOptionPane.QUESTION_MESSAGE );
345- return result;
346- }
347-
348- /**
349- * JSON形式の原稿情報を返す。
350- * @return JSON形式の原稿情報
351- */
352- public JsObject getJson(){
353- JsObject result = new JsObject();
354- JsString memo = new JsString(this.freeMemo.getText());
355- result.putValue("freeMemo", memo);
356-
357- JsArray array = new JsArray();
358- JsString text = new JsString(this.editArray.getAllText());
359- array.add(text);
360- result.putValue("drafts", array);
361-
362- return result;
363- }
364-
365- /**
366- * JSON形式の原稿情報を反映させる。
367- * @param root JSON形式の原稿情報。nullが来たら何もしない
368- */
369- public void putJson(JsObject root){
370- if(root == null) return;
371-
372- JsValue value;
373-
374- value = root.getValue("freeMemo");
375- if(value.getJsTypes() == JsTypes.STRING){
376- JsString memo = (JsString) value;
377- this.freeMemo.setText(memo.toRawString());
378- }
379-
380- value = root.getValue("drafts");
381- if(value.getJsTypes() != JsTypes.ARRAY) return;
382- JsArray array = (JsArray) value;
383-
384- StringBuilder draftAll = new StringBuilder();
385- for(JsValue elem : array){
386- if(elem.getJsTypes() != JsTypes.STRING) continue;
387- JsString draft = (JsString) elem;
388- draftAll.append(draft.toRawString());
389- }
390- this.editArray.clearAllEditor();
391- this.editArray.setAllText(draftAll);
392-
393- this.loadedDraft = root;
394-
395- return;
396- }
397-
398- /**
399- * 起動時の原稿と等価か判定する。
400- * @param conf 比較対象
401- * @return 等価ならtrue
402- */
403- public boolean hasConfChanged(JsComposition<?> conf){
404- if(this.loadedDraft != null){
405- if(this.loadedDraft.equals(conf)) return true;
406- }
407- return false;
408- }
409-
410- /**
411- * アクティブな発言をカットしクリップボードへコピーする。
412- */
413- private void actionCutActive(){
414- actionCopyActive();
415- actionClearActive(false);
416- return;
417- }
418-
419- /**
420- * アクティブな発言をクリップボードにコピーする。
421- */
422- private void actionCopyActive(){
423- TalkEditor activeEditor = this.editArray.getActiveEditor();
424- if(activeEditor == null) return;
425-
426- CharSequence text = activeEditor.getText();
427- ClipboardAction.copyToClipboard(text);
428-
429- return;
430- }
431-
432- /**
433- * アクティブな発言をクリアする。
434- * @param confirm trueなら確認ダイアログを出す
435- */
436- private void actionClearActive(boolean confirm){
437- if(confirm && warnClear() != 0 ) return;
438-
439- TalkEditor activeEditor = this.editArray.getActiveEditor();
440- if(activeEditor == null) return;
441-
442- activeEditor.clearText();
443-
444- return;
445- }
446-
447- /**
448- * 全発言をカットしクリップボードへコピーする。
449- */
450- private void actionCutAll(){
451- actionCopyAll();
452- actionClearAll(false);
453- return;
454- }
455-
456- /**
457- * 全発言をクリップボードにコピーする。
458- */
459- private void actionCopyAll(){
460- CharSequence text = this.editArray.getAllText();
461- ClipboardAction.copyToClipboard(text);
462- return;
463- }
464-
465- /**
466- * 全発言をクリアする。
467- * @param confirm trueなら確認ダイアログを出す
468- */
469- private void actionClearAll(boolean confirm){
470- if(confirm && warnClear() != 0 ) return;
471- this.editArray.clearAllEditor();
472- return;
473- }
474-
475- /**
476- * 上位ウィンドウをクローズする。
477- */
478- private void actionClose(){
479- setVisible(false);
480- return;
481- }
482-
483- /**
484- * {@inheritDoc}
485- * 各種ボタン操作の処理。
486- * @param event {@inheritDoc}
487- */
488- @Override
489- public void actionPerformed(ActionEvent event){
490- Object source = event.getSource();
491- if (source == this.cutButton) actionCutActive();
492- else if(source == this.copyButton) actionCopyActive();
493- else if(source == this.clearButton) actionClearActive(true);
494- else if(source == this.cutAllButton) actionCutAll();
495- else if(source == this.copyAllButton) actionCopyAll();
496- else if(source == this.clearAllButton) actionClearAll(true);
497- else if(source == this.closeButton) actionClose();
498- return;
499- }
500-
501- /**
502- * アクティブなエディタが変更された時の処理。
503- * @param event イベント情報
504- */
505- @Override
506- public void stateChanged(ChangeEvent event){
507- TalkEditor activeEditor = this.editArray.getActiveEditor();
508- int seqNo = activeEditor.getSequenceNumber();
509- setBorderNumber(seqNo);
510- return;
511- }
512-
513- // TODO アンドゥ・リドゥ機能
514- // TODO バルーンの雰囲気を選択できるようにしたい。(白、赤、青、灰)
515- // TODO アンカーの表記揺れの指摘
516-}
--- a/src/main/java/jp/sfjp/jindolf/editor/TextEditor.java
+++ /dev/null
@@ -1,286 +0,0 @@
1-/*
2- * 原稿作成支援用テキストコンポーネント
3- *
4- * License : The MIT License
5- * Copyright(c) 2008 olyutorskii
6- */
7-
8-package jp.sfjp.jindolf.editor;
9-
10-import java.awt.Rectangle;
11-import java.awt.event.InputMethodEvent;
12-import java.awt.event.InputMethodListener;
13-import java.nio.CharBuffer;
14-import java.text.AttributedCharacterIterator;
15-import javax.swing.JTextArea;
16-import javax.swing.text.AbstractDocument;
17-import javax.swing.text.AttributeSet;
18-import javax.swing.text.BadLocationException;
19-import javax.swing.text.Document;
20-import javax.swing.text.DocumentFilter;
21-import javax.swing.text.DocumentFilter.FilterBypass;
22-import javax.swing.text.PlainDocument;
23-
24-/**
25- * 原稿作成支援用テキストコンポーネント。
26- */
27-@SuppressWarnings("serial")
28-public class TextEditor extends JTextArea
29- implements InputMethodListener {
30-
31- private static final int MAX_DOCUMENT = 10 * 1000;
32-
33- private final DocumentFilter documentFilter = new CustomFilter();
34-
35- private boolean onIMEoperation = false;
36-
37- /**
38- * コンストラクタ。
39- */
40- @SuppressWarnings("LeakingThisInConstructor")
41- public TextEditor(){
42- super();
43-
44- setLineWrap(true);
45- setWrapStyleWord(false);
46-
47- Document document = new PlainDocument();
48- setDocument(document);
49-
50- addInputMethodListener(this);
51-
52- return;
53- }
54-
55- /**
56- * エディタが現在IME操作中か判定する。
57- * @return IME操作中ならtrue
58- */
59- public boolean onIMEoperation(){
60- return this.onIMEoperation;
61- }
62-
63- /**
64- * 現在のカーソルが表示されるようスクロールエリアを操作する。
65- */
66- public void scrollCaretToVisible(){
67- int caretPosition = getCaretPosition();
68-
69- Rectangle caretBounds;
70- try{
71- caretBounds = modelToView(caretPosition);
72- }catch(BadLocationException e){
73- assert false;
74- return;
75- }
76-
77- scrollRectToVisible(caretBounds);
78-
79- return;
80- }
81-
82- /**
83- * {@inheritDoc}
84- * Document変更をフックしてフィルタを仕込む。
85- * @param document {@inheritDoc}
86- */
87- @Override
88- public final void setDocument(Document document){
89- Document oldDocument = getDocument();
90- if(oldDocument instanceof AbstractDocument){
91- AbstractDocument abstractDocument =
92- (AbstractDocument) oldDocument;
93- abstractDocument.setDocumentFilter(null);
94- }
95-
96- super.setDocument(document);
97-
98- if(document instanceof AbstractDocument){
99- AbstractDocument abstractDocument = (AbstractDocument) document;
100- abstractDocument.setDocumentFilter(this.documentFilter);
101- }
102-
103- return;
104- }
105-
106- /**
107- * {@inheritDoc}
108- * このエディタ中の指定領域が表示されるようスクロールエリアを操作する。
109- * キーボードフォーカスを保持しないときは無視。
110- * @param rect {@inheritDoc}
111- */
112- @Override
113- public void scrollRectToVisible(Rectangle rect){
114- if( ! hasFocus() ) return;
115- super.scrollRectToVisible(rect);
116- return;
117- }
118-
119- /**
120- * {@inheritDoc}
121- * @param event {@inheritDoc}
122- */
123- @Override
124- public void caretPositionChanged(InputMethodEvent event){
125- // NOTHING
126- return;
127- }
128-
129- /**
130- * {@inheritDoc}
131- * このテキストエディタで現在IMEの変換中か否か判定する処理を含む。
132- * @param event {@inheritDoc}
133- */
134- @Override
135- public void inputMethodTextChanged(InputMethodEvent event){
136- int committed = event.getCommittedCharacterCount();
137- AttributedCharacterIterator aci = event.getText();
138- if(aci == null){
139- this.onIMEoperation = false;
140- return;
141- }
142- int begin = aci.getBeginIndex();
143- int end = aci.getEndIndex();
144- int span = end - begin;
145-
146- if(committed >= span) this.onIMEoperation = false;
147- else this.onIMEoperation = true;
148-
149- return;
150- }
151-
152- /**
153- * 入力文字列に制限を加えるDocumentFilter。
154- * \n,\f 以外の制御文字はタブも含め入力禁止。
155- * U+FFFF はjava.textパッケージで特別扱いなのでこれも入力禁止。
156- * ※ ただしIME操作中は制限なし。
157- */
158- private class CustomFilter extends DocumentFilter{
159-
160- /**
161- * コンストラクタ。
162- */
163- public CustomFilter(){
164- super();
165- return;
166- }
167-
168- /**
169- * 入力禁止文字の判定。
170- * @param ch 検査対象文字
171- * @return 入力禁止ならfalse。ただしIME操作中は必ずtrue。
172- */
173- private boolean isValid(char ch){
174- if(onIMEoperation()) return true;
175-
176- if(ch == '\n') return true;
177- // if(ch == '\f') return true;
178-
179- if(ch == '\uffff') return false;
180- if(Character.isISOControl(ch)) return false;
181-
182- // if( ! CodeX0208.isValid(ch) ) return false;
183- if(Character.isHighSurrogate(ch)) return false;
184- if(Character.isLowSurrogate(ch) ) return false;
185-
186- return true;
187- }
188-
189- /**
190- * 与えられた文字列から入力禁止文字を除いた文字列に変換する。
191- * @param input 検査対象文字列
192- * @return 除去済み文字列
193- */
194- private String filter(CharSequence input){
195- if(onIMEoperation()) return input.toString();
196-
197- int length = input.length();
198- CharBuffer buf = CharBuffer.allocate(length);
199-
200- for(int pos = 0; pos < length; pos++){
201- char ch = input.charAt(pos);
202- if(ch == '\u2211') ch = '\u03a3'; // Σ変換
203- if(ch == '\u00ac') ch = '\uffe2'; // ¬変換
204- // if(ch == 0x005c ) ch = '\u00a5';
205- // バックスラッシュから円へ
206- if(isValid(ch)) buf.append(ch);
207- }
208-
209- buf.flip();
210- return buf.toString();
211- }
212-
213- /**
214- * {@inheritDoc}
215- * @param fb {@inheritDoc}
216- * @param offset {@inheritDoc}
217- * @param text {@inheritDoc}
218- * @param attrs {@inheritDoc}
219- * @throws javax.swing.text.BadLocationException {@inheritDoc}
220- */
221- @Override
222- public void insertString(FilterBypass fb,
223- int offset,
224- String text,
225- AttributeSet attrs)
226- throws BadLocationException{
227- String filtered = filter(text);
228-
229- if( ! onIMEoperation() ){
230- Document document = fb.getDocument();
231- int docLength = document.getLength();
232- int rest = MAX_DOCUMENT - docLength;
233- if(rest < 0){
234- return;
235- }else if(rest < filtered.length()){
236- filtered = filtered.substring(0, rest);
237- }
238- }
239-
240- fb.insertString(offset, filtered, attrs);
241-
242- return;
243- }
244-
245- /**
246- * {@inheritDoc}
247- * @param fb {@inheritDoc}
248- * @param offset {@inheritDoc}
249- * @param length {@inheritDoc}
250- * @param text {@inheritDoc}
251- * @param attrs {@inheritDoc}
252- * @throws javax.swing.text.BadLocationException {@inheritDoc}
253- */
254- @Override
255- public void replace(FilterBypass fb,
256- int offset,
257- int length,
258- String text,
259- AttributeSet attrs)
260- throws BadLocationException{
261- String filtered = filter(text);
262-
263- if( ! onIMEoperation() ){
264- Document document = fb.getDocument();
265- int docLength = document.getLength();
266- docLength -= length;
267- int rest = MAX_DOCUMENT - docLength;
268- if(rest < 0){
269- return;
270- }else if(rest < filtered.length()){
271- filtered = filtered.substring(0, rest);
272- }
273- }
274-
275- fb.replace(offset, length, filtered, attrs);
276-
277- return;
278- }
279- }
280-
281- // TODO 禁則チェック。20文字を超える長大なブレーク禁止文字列の出現の監視。
282- // TODO 連続したホワイトスペースに対する警告。
283- // TODO 先頭もしくは末尾のホワイトスペース出現に対する警告。
284- // TODO 改行記号の表示
285- // TODO 改発言記号の導入
286-}
--- a/src/main/java/jp/sfjp/jindolf/editor/package-info.java
+++ /dev/null
@@ -1,14 +0,0 @@
1-/*
2- * パッケージ情報
3- *
4- * License : The MIT License
5- * Copyright(c) 2011 olyutorskii
6- */
7-
8-/**
9- * 発言エディタ関連の一連のクラス。
10- */
11-
12-package jp.sfjp.jindolf.editor;
13-
14-/* EOF */
--- a/src/main/java/jp/sfjp/jindolf/view/ActionManager.java
+++ b/src/main/java/jp/sfjp/jindolf/view/ActionManager.java
@@ -79,8 +79,6 @@ public class ActionManager{
7979 /** アクション{@value}。 */
8080 public static final String CMD_SHOWFILT = "SHOWFILT";
8181 /** アクション{@value}。 */
82- public static final String CMD_SHOWEDIT = "SHOWEDIT";
83- /** アクション{@value}。 */
8482 public static final String CMD_SHOWLOG = "SHOWLOG";
8583 /** アクション{@value}。 */
8684 public static final String CMD_HELPDOC = "HELPDOC";
@@ -231,7 +229,6 @@ public class ActionManager{
231229 buildMenuItem(CMD_WEBDAY, "この日をブラウザで表示...", KeyEvent.VK_B);
232230 buildMenuItem(CMD_OPTION, "オプション...", KeyEvent.VK_O);
233231 buildMenuItem(CMD_SHOWFILT, "発言フィルタ", KeyEvent.VK_F);
234- buildMenuItem(CMD_SHOWEDIT, "発言エディタ", KeyEvent.VK_E);
235232 buildMenuItem(CMD_SHOWLOG, "ログ表示", KeyEvent.VK_S);
236233 buildMenuItem(CMD_HELPDOC, "ヘルプ表示", KeyEvent.VK_H);
237234 buildMenuItem(CMD_SHOWPORTAL, "ポータルサイト...", KeyEvent.VK_P);
@@ -248,7 +245,6 @@ public class ActionManager{
248245 buildToolButton(CMD_SEARCHPREV, "↑前候補", ICON_SEARCH_PREV);
249246 buildToolButton(CMD_SEARCHNEXT, "↓次候補", ICON_SEARCH_NEXT);
250247 buildToolButton(CMD_SHOWFILT, "発言フィルタ", ICON_FILTER);
251- buildToolButton(CMD_SHOWEDIT, "発言エディタ", ICON_EDITOR);
252248 return;
253249 }
254250
@@ -264,7 +260,6 @@ public class ActionManager{
264260 getMenuItem(CMD_SEARCHPREV).setIcon(ICON_SEARCH_PREV);
265261 getMenuItem(CMD_SEARCHNEXT).setIcon(ICON_SEARCH_NEXT);
266262 getMenuItem(CMD_SHOWFILT) .setIcon(ICON_FILTER);
267- getMenuItem(CMD_SHOWEDIT) .setIcon(ICON_EDITOR);
268263 return;
269264 }
270265
@@ -463,7 +458,6 @@ public class ActionManager{
463458 this.menuPreference.add(this.menuLook);
464459
465460 this.menuTool.add(getMenuItem(CMD_SHOWFILT));
466- this.menuTool.add(getMenuItem(CMD_SHOWEDIT));
467461 this.menuTool.add(getMenuItem(CMD_SHOWLOG));
468462
469463 this.menuHelp.add(getMenuItem(CMD_HELPDOC));
@@ -508,7 +502,6 @@ public class ActionManager{
508502 toolBar.add(getToolButton(CMD_SEARCHPREV));
509503 toolBar.addSeparator();
510504 toolBar.add(getToolButton(CMD_SHOWFILT));
511- toolBar.add(getToolButton(CMD_SHOWEDIT));
512505
513506 return toolBar;
514507 }
--- a/src/main/java/jp/sfjp/jindolf/view/WindowManager.java
+++ b/src/main/java/jp/sfjp/jindolf/view/WindowManager.java
@@ -16,7 +16,6 @@ import javax.swing.SwingUtilities;
1616 import javax.swing.UIManager;
1717 import javax.swing.UnsupportedLookAndFeelException;
1818 import jp.sfjp.jindolf.VerInfo;
19-import jp.sfjp.jindolf.editor.TalkPreview;
2019 import jp.sfjp.jindolf.log.LogFrame;
2120 import jp.sfjp.jindolf.summary.DaySummary;
2221 import jp.sfjp.jindolf.summary.VillageDigest;
@@ -30,8 +29,6 @@ public class WindowManager {
3029 getFrameTitle("発言フィルタ");
3130 private static final String TITLE_LOGGER =
3231 getFrameTitle("ログ表示");
33- private static final String TITLE_EDITOR =
34- getFrameTitle("発言エディタ");
3532 private static final String TITLE_OPTION =
3633 getFrameTitle("オプション設定");
3734 private static final String TITLE_FIND =
@@ -48,7 +45,6 @@ public class WindowManager {
4845
4946 private FilterPanel filterPanel;
5047 private LogFrame logFrame;
51- private TalkPreview talkPreview;
5248 private OptionPanel optionPanel;
5349 private FindPanel findPanel;
5450 private VillageDigest villageDigest;
@@ -70,6 +66,7 @@ public class WindowManager {
7066
7167 /**
7268 * ウィンドウタイトルに前置詞をつける。
69+ *
7370 * @param text 元タイトル
7471 * @return タイトル文字列
7572 */
@@ -81,6 +78,7 @@ public class WindowManager {
8178
8279 /**
8380 * 発言フィルタウィンドウを生成する。
81+ *
8482 * @return 発言フィルタウィンドウ
8583 */
8684 protected FilterPanel createFilterPanel(){
@@ -98,6 +96,7 @@ public class WindowManager {
9896
9997 /**
10098 * 発言フィルタウィンドウを返す。
99+ *
101100 * @return 発言フィルタウィンドウ
102101 */
103102 public FilterPanel getFilterPanel(){
@@ -109,6 +108,7 @@ public class WindowManager {
109108
110109 /**
111110 * ログウィンドウを生成する。
111+ *
112112 * @return ログウィンドウ
113113 */
114114 protected LogFrame createLogFrame(){
@@ -128,6 +128,7 @@ public class WindowManager {
128128
129129 /**
130130 * ログウィンドウを返す。
131+ *
131132 * @return ログウィンドウ
132133 */
133134 public LogFrame getLogFrame(){
@@ -138,36 +139,8 @@ public class WindowManager {
138139 }
139140
140141 /**
141- * 発言エディタウィンドウを生成する。
142- * @return 発言エディタウィンドウ
143- */
144- protected TalkPreview createTalkPreview(){
145- TalkPreview result;
146-
147- result = new TalkPreview();
148- result.setTitle(TITLE_EDITOR);
149- result.pack();
150- result.setSize(700, 500);
151- result.setVisible(false);
152-
153- this.windowSet.add(result);
154-
155- return result;
156- }
157-
158- /**
159- * 発言エディタウィンドウを返す。
160- * @return 発言エディタウィンドウ
161- */
162- public TalkPreview getTalkPreview(){
163- if(this.talkPreview == null){
164- this.talkPreview = createTalkPreview();
165- }
166- return this.talkPreview;
167- }
168-
169- /**
170142 * オプション設定ウィンドウを生成する。
143+ *
171144 * @return オプション設定ウィンドウ
172145 */
173146 protected OptionPanel createOptionPanel(){
@@ -186,6 +159,7 @@ public class WindowManager {
186159
187160 /**
188161 * オプション設定ウィンドウを返す。
162+ *
189163 * @return オプション設定ウィンドウ
190164 */
191165 public OptionPanel getOptionPanel(){
@@ -197,6 +171,7 @@ public class WindowManager {
197171
198172 /**
199173 * 検索ウィンドウを生成する。
174+ *
200175 * @return 検索ウィンドウ
201176 */
202177 protected FindPanel createFindPanel(){
@@ -214,6 +189,7 @@ public class WindowManager {
214189
215190 /**
216191 * 検索ウィンドウを返す。
192+ *
217193 * @return 検索ウィンドウ
218194 */
219195 public FindPanel getFindPanel(){
@@ -225,6 +201,7 @@ public class WindowManager {
225201
226202 /**
227203 * 村ダイジェストウィンドウを生成する。
204+ *
228205 * @return 村ダイジェストウィンドウ
229206 */
230207 protected VillageDigest createVillageDigest(){
@@ -243,6 +220,7 @@ public class WindowManager {
243220
244221 /**
245222 * 村ダイジェストウィンドウを返す。
223+ *
246224 * @return 村ダイジェストウィンドウ
247225 */
248226 public VillageDigest getVillageDigest(){
@@ -254,6 +232,7 @@ public class WindowManager {
254232
255233 /**
256234 * 発言集計ウィンドウを生成する。
235+ *
257236 * @return 発言集計ウィンドウ
258237 */
259238 protected DaySummary createDaySummary(){
@@ -272,6 +251,7 @@ public class WindowManager {
272251
273252 /**
274253 * 発言集計ウィンドウを返す。
254+ *
275255 * @return 発言集計ウィンドウ
276256 */
277257 public DaySummary getDaySummary(){
@@ -283,6 +263,7 @@ public class WindowManager {
283263
284264 /**
285265 * ヘルプウィンドウを生成する。
266+ *
286267 * @return ヘルプウィンドウ
287268 */
288269 protected HelpFrame createHelpFrame(){
@@ -301,6 +282,7 @@ public class WindowManager {
301282
302283 /**
303284 * ヘルプウィンドウを返す。
285+ *
304286 * @return ヘルプウィンドウ
305287 */
306288 public HelpFrame getHelpFrame(){
@@ -312,6 +294,7 @@ public class WindowManager {
312294
313295 /**
314296 * トップフレームを生成する。
297+ *
315298 * @return トップフレーム
316299 */
317300 protected TopFrame createTopFrame(){
@@ -323,6 +306,7 @@ public class WindowManager {
323306
324307 /**
325308 * トップフレームを返す。
309+ *
326310 * @return トップフレーム
327311 */
328312 public TopFrame getTopFrame(){
Show on old repository browser