OSDN Git Service

Merge commit 'cb03a1ed529387c1084e04e6f141eb9d35d095b8'
[jindolf/Jindolf.git] / src / main / java / jp / sfjp / jindolf / glyph / TalkDraw.java
1 /*
2  * 会話部描画
3  *
4  * License : The MIT License
5  * Copyright(c) 2008 olyutorskii
6  */
7
8 package jp.sfjp.jindolf.glyph;
9
10 import java.awt.Color;
11 import java.awt.Font;
12 import java.awt.Graphics2D;
13 import java.awt.Point;
14 import java.awt.Polygon;
15 import java.awt.Rectangle;
16 import java.awt.RenderingHints;
17 import java.awt.image.BufferedImage;
18 import java.io.IOException;
19 import java.text.DateFormat;
20 import java.util.LinkedList;
21 import java.util.List;
22 import java.util.regex.Pattern;
23 import jp.sfjp.jindolf.data.Anchor;
24 import jp.sfjp.jindolf.data.Avatar;
25 import jp.sfjp.jindolf.data.DialogPref;
26 import jp.sfjp.jindolf.data.Period;
27 import jp.sfjp.jindolf.data.Talk;
28 import jp.sfjp.jindolf.data.Village;
29 import jp.sfjp.jindolf.util.GUIUtils;
30 import jp.sfjp.jindolf.view.AvatarPics;
31 import jp.sourceforge.jindolf.corelib.TalkType;
32
33 /**
34  * 会話部の描画。
35  * 会話部描画領域は、キャプション部と発言部から構成される。
36  */
37 public class TalkDraw extends AbstractTextRow{
38
39     /** 通常会話の色。 */
40     public static final Color COLOR_PUBLIC   = new Color(0xffffff);
41     /** 狼間ささやきの色。 */
42     public static final Color COLOR_WOLFONLY = new Color(0xff7777);
43     /** 灰色発言の色。 */
44     public static final Color COLOR_PRIVATE  = new Color(0x939393);
45     /** 墓下発言の色。 */
46     public static final Color COLOR_GRAVE    = new Color(0x9fb7cf);
47
48     private static final Color COLOR_CAPTIONFG = Color.WHITE;
49     private static final Color COLOR_DIALOGFG  = Color.BLACK;
50
51     private static final Color COLOR_SIMPLEFG = Color.BLACK;
52     private static final Color COLOR_SIMPLEBG = Color.WHITE;
53
54     private static final int BALOONTIP_WIDTH = 16;
55     private static final int BALOONTIP_HEIGHT = 8;
56     private static final int UPPER_MARGIN = 5;
57     private static final int UNDER_MARGIN = 10;
58     private static final int OFFSET_ANCHOR = 36;
59     private static final int CAPTION_DIALOG_GAP = 3;
60
61     private static final Color COLOR_TRANS = new Color(0, 0, 0, 0);
62     private static final int BALOON_R = 10;
63     private static final BufferedImage BALOON_PUBLIC;
64     private static final BufferedImage BALOON_WOLFONLY;
65     private static final BufferedImage BALOON_GRAVE;
66     private static final BufferedImage BALOON_PRIVATE;
67     private static final BufferedImage SQUARE_PUBLIC;
68     private static final BufferedImage SQUARE_WOLFONLY;
69     private static final BufferedImage SQUARE_GRAVE;
70     private static final BufferedImage SQUARE_PRIVATE;
71
72     private static final float ANCHOR_FONT_RATIO = 0.9f;
73
74     static{
75         BALOON_PUBLIC   = createWedgeImage(COLOR_PUBLIC);
76         BALOON_WOLFONLY = createBubbleImage(COLOR_WOLFONLY);
77         BALOON_PRIVATE  = createBubbleImage(COLOR_PRIVATE);
78         BALOON_GRAVE    = createBubbleImage(COLOR_GRAVE);
79         SQUARE_PUBLIC   = createSquareImage(COLOR_PUBLIC);
80         SQUARE_WOLFONLY = createSquareImage(COLOR_WOLFONLY);
81         SQUARE_GRAVE    = createSquareImage(COLOR_GRAVE);
82         SQUARE_PRIVATE  = createSquareImage(COLOR_PRIVATE);
83     }
84
85
86     private final Talk talk;
87     private Anchor showingAnchor;
88
89     private final GlyphDraw caption;
90     private BufferedImage faceImage;
91     private final GlyphDraw dialog;
92     private final List<AnchorDraw> anchorTalks = new LinkedList<>();
93     private Point imageOrigin;
94     private Point dialogOrigin;
95     private Point tipOrigin;
96     private int baloonWidth;
97     private int baloonHeight;
98
99     private FontInfo anchorFontInfo;
100     private DialogPref dialogPref;
101
102
103     /**
104      * コンストラクタ。
105      * @param talk 一発言
106      */
107     public TalkDraw(Talk talk){
108         this(talk, new DialogPref(), FontInfo.DEFAULT_FONTINFO);
109         return;
110     }
111
112     /**
113      * コンストラクタ。
114      * @param talk 一発言
115      * @param dialogPref 発言表示設定
116      * @param fontInfo フォント設定
117      */
118     public TalkDraw(Talk talk, DialogPref dialogPref, FontInfo fontInfo){
119         super(fontInfo);
120
121         this.talk = talk;
122         this.anchorFontInfo = deriveAnchorFontInfo(this.fontInfo);
123         this.dialogPref = dialogPref;
124
125         this.faceImage = getFaceImage();
126         this.caption = new GlyphDraw(getCaptionString(), this.fontInfo);
127         this.dialog  = new GlyphDraw(this.talk.getDialog(), this.fontInfo);
128
129         setColorDesign();
130
131         Period period = this.talk.getPeriod();
132         List<Anchor> anchorList = Anchor.getAnchorList(this.talk.getDialog(),
133                                                        period.getDay() );
134         this.dialog.setAnchorSet(anchorList);
135
136         return;
137     }
138
139
140     /**
141      * 指定した色で描画したクサビイメージを取得する。
142      * @param color 色
143      * @return クサビイメージ
144      */
145     private static BufferedImage createWedgeImage(Color color){
146         BufferedImage image;
147         image = new BufferedImage(BALOONTIP_WIDTH,
148                                   BALOONTIP_HEIGHT,
149                                   BufferedImage.TYPE_INT_ARGB);
150         Graphics2D g2 = image.createGraphics();
151         RenderingHints renderHints = GUIUtils.getQualityHints();
152         g2.addRenderingHints(renderHints);
153         g2.setColor(COLOR_TRANS);
154         g2.fillRect(0, 0, BALOONTIP_WIDTH, BALOONTIP_HEIGHT);
155         g2.setColor(color);
156         Polygon poly = new Polygon();
157         poly.addPoint(8, 8);
158         poly.addPoint(16, 8);
159         poly.addPoint(16, 0);
160         g2.fillPolygon(poly);
161         return image;
162     }
163
164     /**
165      * 指定した色で描画した泡イメージを取得する。
166      * @param color 色
167      * @return 泡イメージ
168      */
169     private static BufferedImage createBubbleImage(Color color){
170         BufferedImage image;
171         image = new BufferedImage(BALOONTIP_WIDTH,
172                                   BALOONTIP_HEIGHT,
173                                   BufferedImage.TYPE_INT_ARGB);
174         Graphics2D g2 = image.createGraphics();
175         RenderingHints renderHints = GUIUtils.getQualityHints();
176         g2.addRenderingHints(renderHints);
177         g2.setColor(COLOR_TRANS);
178         g2.fillRect(0, 0, BALOONTIP_WIDTH, BALOONTIP_HEIGHT);
179         g2.setColor(color);
180         g2.fillOval(2, 4, 4, 4);
181         g2.fillOval(8, 2, 6, 6);
182         return image;
183     }
184
185     /**
186      * 指定した色で描画した長方形イメージを返す。
187      * @param color 色
188      * @return 長方形イメージ
189      */
190     private static BufferedImage createSquareImage(Color color){
191         BufferedImage image;
192         image = new BufferedImage(BALOONTIP_WIDTH,
193                                   BALOONTIP_HEIGHT,
194                                   BufferedImage.TYPE_INT_ARGB);
195         Graphics2D g2 = image.createGraphics();
196         RenderingHints renderHints = GUIUtils.getQualityHints();
197         g2.addRenderingHints(renderHints);
198         g2.setColor(color);
199         g2.fillRect(0, 0, BALOONTIP_WIDTH, BALOONTIP_HEIGHT);
200         return image;
201     }
202
203     /**
204      * 会話表示用フォントからアンカー表示用フォントを派生させる。
205      * @param font 派生元フォント
206      * @return 派生先フォント
207      */
208     private static Font deriveAnchorFont(Font font){
209         float fontSize = font.getSize2D();
210         float newSize = fontSize * ANCHOR_FONT_RATIO;
211         return font.deriveFont(newSize);
212     }
213
214     /**
215      * 会話表示用フォント設定からアンカー表示用フォント設定を派生させる。
216      * @param info 派生元フォント設定
217      * @return 派生先フォント設定
218      */
219     private static FontInfo deriveAnchorFontInfo(FontInfo info){
220         Font newFont = deriveAnchorFont(info.getFont());
221         FontInfo result = info.deriveFont(newFont);
222         return result;
223     }
224
225     /**
226      * 発言種別毎の色を返す。
227      * @param type 発言種別
228      * @return 色
229      */
230     public static Color getTypedColor(TalkType type){
231         Color result;
232
233         switch(type){
234         case PUBLIC:   result = TalkDraw.COLOR_PUBLIC;   break;
235         case WOLFONLY: result = TalkDraw.COLOR_WOLFONLY; break;
236         case GRAVE:    result = TalkDraw.COLOR_GRAVE;    break;
237         case PRIVATE:  result = TalkDraw.COLOR_PRIVATE;  break;
238         default:       return null;
239         }
240
241         return result;
242     }
243
244     /**
245      * 配色を設定する。
246      */
247     private void setColorDesign(){
248         if(this.dialogPref.isSimpleMode()){
249             this.caption.setColor(COLOR_SIMPLEFG);
250         }else{
251             this.caption.setColor(COLOR_CAPTIONFG);
252         }
253
254         this.dialog.setColor(COLOR_DIALOGFG);
255
256         return;
257     }
258
259     /**
260      * Talk取得。
261      * @return Talkインスタンス
262      */
263     public Talk getTalk(){
264         return this.talk;
265     }
266
267     /**
268      * 顔イメージを返す。
269      * @return 顔イメージ
270      */
271     private BufferedImage getFaceImage(){
272         Village village = this.talk.getPeriod().getVillage();
273         AvatarPics avatarPics = village.getAvatarPics();
274         Avatar avatar = this.talk.getAvatar();
275
276         boolean useBodyImage = this.dialogPref.useBodyImage();
277         boolean useMonoImage = this.dialogPref.useMonoImage();
278
279         BufferedImage image;
280         if(this.talk.isGrave()){
281             if(useMonoImage){
282                 if(useBodyImage){
283                     image = avatarPics.getAvatarBodyMonoImage(avatar);
284                 }else{
285                     image = avatarPics.getAvatarFaceMonoImage(avatar);
286                 }
287             }else{
288                 if(useBodyImage){
289                     image = avatarPics.getGraveBodyImage();
290                 }else{
291                     image = avatarPics.getGraveImage();
292                 }
293             }
294         }else{
295             if(useBodyImage){
296                 image = avatarPics.getAvatarBodyImage(avatar);
297             }else{
298                 image = avatarPics.getAvatarFaceImage(avatar);
299             }
300         }
301
302         return image;
303     }
304
305     /**
306      * キャプション文字列を取得する。
307      * @return キャプション文字列
308      */
309     private CharSequence getCaptionString(){
310         StringBuilder result = new StringBuilder();
311
312         Avatar avatar = this.talk.getAvatar();
313
314         if(this.talk.hasTalkNo()){
315             result.append(this.talk.getAnchorNotation_G()).append(' ');
316         }
317         result.append(avatar.getFullName()).append(' ');
318         result.append(this.talk.getAnchorNotation());
319         result.append('\n');
320
321         DateFormat dform =
322             DateFormat.getDateTimeInstance(DateFormat.MEDIUM,
323                                            DateFormat.MEDIUM);
324         long epoch = this.talk.getTimeFromID();
325         String decoded = dform.format(epoch);
326         result.append(decoded);
327
328         int count = this.talk.getTalkCount();
329         if(count > 0){
330             TalkType type = this.talk.getTalkType();
331             result.append(" (").append(Talk.encodeColorName(type));
332             result.append('#').append(count).append(')');
333         }
334
335         int charNum = this.talk.getTotalChars();
336         if(charNum > 0){
337             result.append(' ').append(charNum).append('字');
338         }
339
340         return result;
341     }
342
343     /**
344      * 会話部背景色を返す。
345      * @return 会話部背景色
346      */
347     protected Color getTalkBgColor(){
348         if(this.dialogPref.isSimpleMode()) return COLOR_SIMPLEBG;
349
350         TalkType type = this.talk.getTalkType();
351         Color result = getTypedColor(type);
352
353         return result;
354     }
355
356     /**
357      * {@inheritDoc}
358      * @return {@inheritDoc}
359      */
360     @Override
361     public Rectangle recalcBounds(){
362         int newWidth = getWidth();
363
364         int imageWidth  = 0;
365         int imageHeight = 0;
366         if( ! this.dialogPref.isSimpleMode()){
367             imageWidth  = this.faceImage.getWidth(null);
368             imageHeight = this.faceImage.getHeight(null);
369         }
370
371         int tipWidth = BALOON_WOLFONLY.getWidth();
372
373         int modWidth;
374         int minWidth = imageWidth + tipWidth + BALOON_R * 2;
375         if(newWidth < minWidth) modWidth = minWidth;
376         else                    modWidth = newWidth;
377
378         this.caption.setWidth(modWidth);
379         int captionWidth  = this.caption.getWidth();
380         int captionHeight = this.caption.getHeight() + CAPTION_DIALOG_GAP;
381
382         this.dialog.setWidth(modWidth - minWidth);
383         int dialogWidth  = this.dialog.getWidth();
384         int dialogHeight = this.dialog.getHeight();
385
386         if(this.dialogPref.alignBaloonWidth()){
387             this.baloonWidth  = (modWidth - minWidth) + BALOON_R * 2;
388         }else{
389             this.baloonWidth  = dialogWidth + BALOON_R * 2;
390         }
391         this.baloonHeight = dialogHeight + BALOON_R * 2;
392
393         int imageAndDialogWidth = imageWidth + tipWidth + this.baloonWidth;
394
395         int totalWidth = Math.max(captionWidth, imageAndDialogWidth);
396
397         int totalHeight = captionHeight;
398         totalHeight += Math.max(imageHeight, this.baloonHeight);
399
400         int imageYpos = captionHeight;
401         int dialogYpos = captionHeight;
402         int tipYpos = captionHeight;
403         if(imageHeight < this.baloonHeight){
404             imageYpos += (this.baloonHeight - imageHeight) / 2;
405             tipYpos += (this.baloonHeight - BALOON_WOLFONLY.getHeight()) / 2;
406             dialogYpos += BALOON_R;
407         }else{
408             dialogYpos += (imageHeight - this.baloonHeight) / 2 + BALOON_R;
409             tipYpos += (imageHeight - BALOON_WOLFONLY.getHeight()) / 2;
410         }
411
412         this.imageOrigin = new Point(0, imageYpos);
413         this.caption.setPos(this.bounds.x + 0, this.bounds.y + 0);
414         this.dialogOrigin =
415                 new Point(imageWidth+tipWidth+BALOON_R, dialogYpos);
416         this.dialog.setPos(this.bounds.x + imageWidth+tipWidth+BALOON_R,
417                            this.bounds.y + dialogYpos);
418         this.tipOrigin = new Point(imageWidth, tipYpos);
419
420         for(AnchorDraw anchorDraw : this.anchorTalks){
421             anchorDraw.setWidth(modWidth - OFFSET_ANCHOR);
422             totalHeight += anchorDraw.getHeight();
423         }
424
425         if(    this.dialogPref.isSimpleMode()
426             || this.dialogPref.alignBaloonWidth() ){
427             this.bounds.width = newWidth;
428         }else{
429             this.bounds.width = totalWidth;
430         }
431         this.bounds.height = UPPER_MARGIN + totalHeight + UNDER_MARGIN;
432
433         return this.bounds;
434     }
435
436     /**
437      * {@inheritDoc}
438      * @param xPos {@inheritDoc}
439      * @param yPos {@inheritDoc}
440      */
441     @Override
442     public void setPos(int xPos, int yPos){
443         super.setPos(xPos, yPos);
444         this.caption.setPos(this.bounds.x, this.bounds.y + UPPER_MARGIN);
445         this.dialog.setPos(this.bounds.x + this.dialogOrigin.x,
446                            this.bounds.y + this.dialogOrigin.y
447                                          + UPPER_MARGIN);
448         return;
449     }
450
451     /**
452      * アイコンイメージとフキダシを繋ぐ補助イメージを返す。
453      * @return 補助イメージ
454      */
455     private BufferedImage getTipImage(){
456         BufferedImage tip;
457
458         TalkType type = this.talk.getTalkType();
459
460         if(this.dialogPref.isSimpleMode()){
461             switch(type){
462             case PUBLIC:   tip = SQUARE_PUBLIC;   break;
463             case WOLFONLY: tip = SQUARE_WOLFONLY; break;
464             case GRAVE:    tip = SQUARE_GRAVE;    break;
465             case PRIVATE:  tip = SQUARE_PRIVATE;  break;
466             default:
467                 assert false;
468                 tip = null;
469                 break;
470             }
471         }else{
472             switch(type){
473             case PUBLIC:   tip = BALOON_PUBLIC;   break;
474             case WOLFONLY: tip = BALOON_WOLFONLY; break;
475             case GRAVE:    tip = BALOON_GRAVE;    break;
476             case PRIVATE:  tip = BALOON_PRIVATE;  break;
477             default:
478                 assert false;
479                 tip = null;
480                 break;
481             }
482         }
483
484         return tip;
485     }
486
487     /**
488      * {@inheritDoc}
489      * @param g {@inheritDoc}
490      */
491     @Override
492     public void paint(Graphics2D g){
493         final int xPos = this.bounds.x;
494         final int yPos = this.bounds.y + UPPER_MARGIN;
495
496         this.caption.paint(g);
497
498         if(this.dialogPref.isSimpleMode() ){
499             RenderingHints.Key aaHintKey = RenderingHints.KEY_ANTIALIASING;
500             Object aaHintTemp = RenderingHints.VALUE_ANTIALIAS_OFF;
501             Object aaHintOrig = g.getRenderingHint(aaHintKey);
502
503             RenderingHints.Key strokeHintKey =
504                     RenderingHints.KEY_STROKE_CONTROL;
505             Object strokeHintTemp = RenderingHints.VALUE_STROKE_NORMALIZE;
506             Object strokeHintOrig = g.getRenderingHint(strokeHintKey);
507
508             g.setRenderingHint(aaHintKey, aaHintTemp);
509             g.setRenderingHint(strokeHintKey, strokeHintTemp);
510
511             g.drawLine(xPos,                     this.bounds.y,
512                        xPos + this.bounds.width, this.bounds.y );
513
514             g.setRenderingHint(aaHintKey, aaHintOrig);
515             g.setRenderingHint(strokeHintKey, strokeHintOrig);
516         }else{
517             g.drawImage(this.faceImage,
518                         xPos + this.imageOrigin.x,
519                         yPos + this.imageOrigin.y,
520                         null );
521         }
522
523         BufferedImage tip = getTipImage();
524         g.drawImage(tip,
525                     xPos + this.tipOrigin.x,
526                     yPos + this.tipOrigin.y,
527                     null );
528
529         g.setColor(getTalkBgColor());
530         g.fillRoundRect(
531                 xPos + this.dialogOrigin.x - BALOON_R,
532                 yPos + this.dialogOrigin.y - BALOON_R,
533                 this.baloonWidth,
534                 this.baloonHeight,
535                 BALOON_R,
536                 BALOON_R );
537
538         this.dialog.paint(g);
539
540         int anchorX = xPos + OFFSET_ANCHOR;
541         int anchorY = yPos + this.dialogOrigin.y + this.baloonHeight;
542
543         for(AnchorDraw anchorDraw : this.anchorTalks){
544             anchorDraw.setPos(anchorX, anchorY);
545             anchorDraw.paint(g);
546             anchorY += anchorDraw.getHeight();
547         }
548
549         return;
550     }
551
552     /**
553      * {@inheritDoc}
554      * @param fontInfo {@inheritDoc}
555      */
556     @Override
557     public void setFontInfo(FontInfo fontInfo){
558         super.setFontInfo(fontInfo);
559
560         this.anchorFontInfo = deriveAnchorFontInfo(this.fontInfo);
561
562         this.caption.setFontInfo(this.fontInfo);
563         this.dialog .setFontInfo(this.fontInfo);
564
565         for(AnchorDraw anchorDraw : this.anchorTalks){
566             anchorDraw.setFontInfo(this.anchorFontInfo);
567         }
568
569         recalcBounds();
570
571         return;
572     }
573
574     /**
575      * 発言設定を更新する。
576      * @param pref 発言設定
577      */
578     public void setDialogPref(DialogPref pref){
579         this.dialogPref = pref;
580         this.faceImage = getFaceImage();
581
582         for(AnchorDraw anchorDraw : this.anchorTalks){
583             anchorDraw.setDialogPref(this.dialogPref);
584         }
585
586         setColorDesign();
587         recalcBounds();
588
589         return;
590     }
591
592     /**
593      * {@inheritDoc}
594      * @param from {@inheritDoc}
595      * @param to {@inheritDoc}
596      */
597     @Override
598     public void drag(Point from, Point to){
599         this.caption.drag(from, to);
600         this.dialog.drag(from, to);
601         for(AnchorDraw anchorDraw : this.anchorTalks){
602             anchorDraw.drag(from, to);
603         }
604         return;
605     }
606
607     /**
608      * {@inheritDoc}
609      * @param appendable {@inheritDoc}
610      * @return {@inheritDoc}
611      * @throws java.io.IOException {@inheritDoc}
612      */
613     @Override
614     public Appendable appendSelected(Appendable appendable)
615             throws IOException{
616         this.caption.appendSelected(appendable);
617         this.dialog .appendSelected(appendable);
618
619         for(AnchorDraw anchorDraw : this.anchorTalks){
620             anchorDraw.appendSelected(appendable);
621         }
622
623         return appendable;
624     }
625
626     /**
627      * {@inheritDoc}
628      */
629     @Override
630     public void clearSelect(){
631         this.caption.clearSelect();
632         this.dialog.clearSelect();
633         for(AnchorDraw anchorDraw : this.anchorTalks){
634             anchorDraw.clearSelect();
635         }
636         return;
637     }
638
639     /**
640      * 与えられた座標にアンカー文字列が存在すればAnchorを返す。
641      * @param pt 座標
642      * @return アンカー
643      */
644     public Anchor getAnchor(Point pt){
645         Anchor result = this.dialog.getAnchor(pt);
646         return result;
647     }
648
649     /**
650      * アンカーを展開表示する。
651      * アンカーにnullを指定すればアンカー表示は非表示となる。
652      * @param anchor アンカー
653      * @param talkList アンカーの示す一連のTalk
654      */
655     public void showAnchorTalks(Anchor anchor, List<Talk> talkList){
656         if(anchor == null || this.showingAnchor == anchor){
657             this.showingAnchor = null;
658             this.anchorTalks.clear();
659             recalcBounds();
660             return;
661         }
662
663         this.showingAnchor = anchor;
664
665         this.anchorTalks.clear();
666         for(Talk anchorTalk : talkList){
667             AnchorDraw anchorDraw =
668                     new AnchorDraw(anchorTalk,
669                                    this.dialogPref,
670                                    this.anchorFontInfo );
671             this.anchorTalks.add(anchorDraw);
672         }
673
674         recalcBounds();
675
676         return;
677     }
678
679     /**
680      * 与えられた座標に検索マッチ文字列があればそのインデックスを返す。
681      * @param pt 座標
682      * @return 検索マッチインデックス
683      */
684     public int getRegexMatchIndex(Point pt){
685         int index = this.dialog.getRegexMatchIndex(pt);
686         return index;
687     }
688
689     /**
690      * 検索文字列パターンを設定する。
691      * @param searchRegex パターン
692      * @return ヒット数
693      */
694     public int setRegex(Pattern searchRegex){
695         int total = 0;
696
697         total += this.dialog.setRegex(searchRegex);
698         /*
699         for(AnchorDraw anchorDraw : this.anchorTalks){
700             total += anchorDraw.setRegex(searchRegex);
701         }
702         */
703         // TODO よくわからんので保留
704         return total;
705     }
706
707     /**
708      * 検索ハイライトインデックスを返す。
709      * @return 検索ハイライトインデックス。見つからなければ-1。
710      */
711     public int getHotTargetIndex(){
712         return this.dialog.getHotTargetIndex();
713     }
714
715     /**
716      * 検索ハイライトを設定する。
717      * @param index ハイライトインデックス。負ならハイライト全クリア。
718      */
719     public void setHotTargetIndex(int index){
720         this.dialog.setHotTargetIndex(index);
721         return;
722     }
723
724     /**
725      * 検索一致件数を返す。
726      * @return 検索一致件数
727      */
728     public int getRegexMatches(){
729         return this.dialog.getRegexMatches();
730     }
731
732     /**
733      * 特別な検索ハイライト描画をクリアする。
734      */
735     public void clearHotTarget(){
736         this.dialog.clearHotTarget();
737         return;
738     }
739
740     /**
741      * 特別な検索ハイライト領域の寸法を返す。
742      * @return ハイライト領域寸法
743      */
744     public Rectangle getHotTargetRectangle(){
745         return this.dialog.getHotTargetRectangle();
746     }
747
748 }