OSDN Git Service

Merge commit '2458eff3aea04f67893bc824b5cf896fbb767332'
[jindolf/Jindolf.git] / src / main / java / jp / sourceforge / jindolf / TalkDraw.java
diff --git a/src/main/java/jp/sourceforge/jindolf/TalkDraw.java b/src/main/java/jp/sourceforge/jindolf/TalkDraw.java
new file mode 100644 (file)
index 0000000..0ab616b
--- /dev/null
@@ -0,0 +1,715 @@
+/*\r
+ * 会話部描画\r
+ *\r
+ * Copyright(c) 2008 olyutorskii\r
+ * $Id: TalkDraw.java 995 2010-03-15 03:54:09Z olyutorskii $\r
+ */\r
+\r
+package jp.sourceforge.jindolf;\r
+\r
+import java.awt.Color;\r
+import java.awt.Font;\r
+import java.awt.Graphics2D;\r
+import java.awt.Point;\r
+import java.awt.Polygon;\r
+import java.awt.Rectangle;\r
+import java.awt.RenderingHints;\r
+import java.awt.image.BufferedImage;\r
+import java.io.IOException;\r
+import java.text.DateFormat;\r
+import java.util.LinkedList;\r
+import java.util.List;\r
+import java.util.regex.Pattern;\r
+import jp.sourceforge.jindolf.corelib.TalkType;\r
+\r
+/**\r
+ * 会話部の描画。\r
+ * 会話部描画領域は、キャプション部と発言部から構成される。\r
+ */\r
+public class TalkDraw extends AbstractTextRow{\r
+\r
+    /** 通常会話の色。 */\r
+    public static final Color COLOR_PUBLIC   = new Color(0xffffff);\r
+    /** 狼間ささやきの色。 */\r
+    public static final Color COLOR_WOLFONLY = new Color(0xff7777);\r
+    /** 灰色発言の色。 */\r
+    public static final Color COLOR_PRIVATE  = new Color(0x939393);\r
+    /** 墓下発言の色。 */\r
+    public static final Color COLOR_GRAVE    = new Color(0x9fb7cf);\r
+\r
+    private static final Color COLOR_CAPTIONFG = Color.WHITE;\r
+    private static final Color COLOR_DIALOGFG  = Color.BLACK;\r
+\r
+    private static final Color COLOR_SIMPLEFG = Color.BLACK;\r
+    private static final Color COLOR_SIMPLEBG = Color.WHITE;\r
+\r
+    private static final int BALOONTIP_WIDTH = 16;\r
+    private static final int BALOONTIP_HEIGHT = 8;\r
+    private static final int UPPER_MARGIN = 5;\r
+    private static final int UNDER_MARGIN = 10;\r
+    private static final int OFFSET_ANCHOR = 36;\r
+    private static final int CAPTION_DIALOG_GAP = 3;\r
+\r
+    private static final Color COLOR_TRANS = new Color(0, 0, 0, 0);\r
+    private static final int BALOON_R = 10;\r
+    private static final BufferedImage BALOON_PUBLIC;\r
+    private static final BufferedImage BALOON_WOLFONLY;\r
+    private static final BufferedImage BALOON_GRAVE;\r
+    private static final BufferedImage BALOON_PRIVATE;\r
+    private static final BufferedImage SQUARE_PUBLIC;\r
+    private static final BufferedImage SQUARE_WOLFONLY;\r
+    private static final BufferedImage SQUARE_GRAVE;\r
+    private static final BufferedImage SQUARE_PRIVATE;\r
+\r
+    private static final float ANCHOR_FONT_RATIO = 0.9f;\r
+\r
+    static{\r
+        BALOON_PUBLIC   = createWedgeImage(COLOR_PUBLIC);\r
+        BALOON_WOLFONLY = createBubbleImage(COLOR_WOLFONLY);\r
+        BALOON_PRIVATE  = createBubbleImage(COLOR_PRIVATE);\r
+        BALOON_GRAVE    = createBubbleImage(COLOR_GRAVE);\r
+        SQUARE_PUBLIC   = createSquareImage(COLOR_PUBLIC);\r
+        SQUARE_WOLFONLY = createSquareImage(COLOR_WOLFONLY);\r
+        SQUARE_GRAVE    = createSquareImage(COLOR_GRAVE);\r
+        SQUARE_PRIVATE  = createSquareImage(COLOR_PRIVATE);\r
+    }\r
+\r
+    /**\r
+     * 指定した色で描画したクサビイメージを取得する。\r
+     * @param color 色\r
+     * @return クサビイメージ\r
+     */\r
+    private static BufferedImage createWedgeImage(Color color){\r
+        BufferedImage image;\r
+        image = new BufferedImage(BALOONTIP_WIDTH,\r
+                                  BALOONTIP_HEIGHT,\r
+                                  BufferedImage.TYPE_INT_ARGB);\r
+        Graphics2D g2 = image.createGraphics();\r
+        RenderingHints renderHints = GUIUtils.getQualityHints();\r
+        g2.addRenderingHints(renderHints);\r
+        g2.setColor(COLOR_TRANS);\r
+        g2.fillRect(0, 0, BALOONTIP_WIDTH, BALOONTIP_HEIGHT);\r
+        g2.setColor(color);\r
+        Polygon poly = new Polygon();\r
+        poly.addPoint(8, 8);\r
+        poly.addPoint(16, 8);\r
+        poly.addPoint(16, 0);\r
+        g2.fillPolygon(poly);\r
+        return image;\r
+    }\r
+\r
+    /**\r
+     * 指定した色で描画した泡イメージを取得する。\r
+     * @param color 色\r
+     * @return 泡イメージ\r
+     */\r
+    private static BufferedImage createBubbleImage(Color color){\r
+        BufferedImage image;\r
+        image = new BufferedImage(BALOONTIP_WIDTH,\r
+                                  BALOONTIP_HEIGHT,\r
+                                  BufferedImage.TYPE_INT_ARGB);\r
+        Graphics2D g2 = image.createGraphics();\r
+        RenderingHints renderHints = GUIUtils.getQualityHints();\r
+        g2.addRenderingHints(renderHints);\r
+        g2.setColor(COLOR_TRANS);\r
+        g2.fillRect(0, 0, BALOONTIP_WIDTH, BALOONTIP_HEIGHT);\r
+        g2.setColor(color);\r
+        g2.fillOval(2, 4, 4, 4);\r
+        g2.fillOval(8, 2, 6, 6);\r
+        return image;\r
+    }\r
+\r
+    /**\r
+     * 指定した色で描画した長方形イメージを返す。\r
+     * @param color 色\r
+     * @return 長方形イメージ\r
+     */\r
+    private static BufferedImage createSquareImage(Color color){\r
+        BufferedImage image;\r
+        image = new BufferedImage(BALOONTIP_WIDTH,\r
+                                  BALOONTIP_HEIGHT,\r
+                                  BufferedImage.TYPE_INT_ARGB);\r
+        Graphics2D g2 = image.createGraphics();\r
+        RenderingHints renderHints = GUIUtils.getQualityHints();\r
+        g2.addRenderingHints(renderHints);\r
+        g2.setColor(color);\r
+        g2.fillRect(0, 0, BALOONTIP_WIDTH, BALOONTIP_HEIGHT);\r
+        return image;\r
+    }\r
+\r
+    /**\r
+     * 会話表示用フォントからアンカー表示用フォントを派生させる。\r
+     * @param font 派生元フォント\r
+     * @return 派生先フォント\r
+     */\r
+    private static Font deriveAnchorFont(Font font){\r
+        float fontSize = font.getSize2D();\r
+        float newSize = fontSize * ANCHOR_FONT_RATIO;\r
+        return font.deriveFont(newSize);\r
+    }\r
+\r
+    /**\r
+     * 会話表示用フォント設定からアンカー表示用フォント設定を派生させる。\r
+     * @param info 派生元フォント設定\r
+     * @return 派生先フォント設定\r
+     */\r
+    private static FontInfo deriveAnchorFontInfo(FontInfo info){\r
+        Font newFont = deriveAnchorFont(info.getFont());\r
+        FontInfo result = info.deriveFont(newFont);\r
+        return result;\r
+    }\r
+\r
+    /**\r
+     * 発言種別毎の色を返す。\r
+     * @param type 発言種別\r
+     * @return 色\r
+     */\r
+    public static Color getTypedColor(TalkType type){\r
+        Color result;\r
+\r
+        switch(type){\r
+        case PUBLIC:   result = TalkDraw.COLOR_PUBLIC;   break;\r
+        case WOLFONLY: result = TalkDraw.COLOR_WOLFONLY; break;\r
+        case GRAVE:    result = TalkDraw.COLOR_GRAVE;    break;\r
+        case PRIVATE:  result = TalkDraw.COLOR_PRIVATE;  break;\r
+        default:       return null;\r
+        }\r
+\r
+        return result;\r
+    }\r
+\r
+    private final Talk talk;\r
+    private Anchor showingAnchor;\r
+\r
+    private final GlyphDraw caption;\r
+    private BufferedImage faceImage;\r
+    private final GlyphDraw dialog;\r
+    private final List<AnchorDraw> anchorTalks = new LinkedList<AnchorDraw>();\r
+    private Point imageOrigin;\r
+    private Point dialogOrigin;\r
+    private Point tipOrigin;\r
+    private int baloonWidth;\r
+    private int baloonHeight;\r
+\r
+    private FontInfo anchorFontInfo;\r
+    private DialogPref dialogPref;\r
+\r
+    /**\r
+     * コンストラクタ。\r
+     * @param talk 一発言\r
+     */\r
+    public TalkDraw(Talk talk){\r
+        this(talk, new DialogPref(), FontInfo.DEFAULT_FONTINFO);\r
+        return;\r
+    }\r
+\r
+    /**\r
+     * コンストラクタ。\r
+     * @param talk 一発言\r
+     * @param dialogPref 発言表示設定\r
+     * @param fontInfo フォント設定\r
+     */\r
+    public TalkDraw(Talk talk, DialogPref dialogPref, FontInfo fontInfo){\r
+        super(fontInfo);\r
+\r
+        this.talk = talk;\r
+        this.anchorFontInfo = deriveAnchorFontInfo(this.fontInfo);\r
+        this.dialogPref = dialogPref;\r
+\r
+        this.faceImage = getFaceImage();\r
+        this.caption = new GlyphDraw(getCaptionString(), this.fontInfo);\r
+        this.dialog  = new GlyphDraw(this.talk.getDialog(), this.fontInfo);\r
+\r
+        setColorDesign();\r
+\r
+        Period period = this.talk.getPeriod();\r
+        List<Anchor> anchorList = Anchor.getAnchorList(this.talk.getDialog(),\r
+                                                       period.getDay() );\r
+        this.dialog.setAnchorSet(anchorList);\r
+\r
+        return;\r
+    }\r
+\r
+    /**\r
+     * 配色を設定する。\r
+     */\r
+    private void setColorDesign(){\r
+        if(this.dialogPref.isSimpleMode()){\r
+            this.caption.setColor(COLOR_SIMPLEFG);\r
+        }else{\r
+            this.caption.setColor(COLOR_CAPTIONFG);\r
+        }\r
+\r
+        this.dialog.setColor(COLOR_DIALOGFG);\r
+\r
+        return;\r
+    }\r
+\r
+    /**\r
+     * Talk取得。\r
+     * @return Talkインスタンス\r
+     */\r
+    public Talk getTalk(){\r
+        return this.talk;\r
+    }\r
+\r
+    /**\r
+     * 顔イメージを返す。\r
+     * @return 顔イメージ\r
+     */\r
+    private BufferedImage getFaceImage(){\r
+        Village village = this.talk.getPeriod().getVillage();\r
+        Avatar avatar = this.talk.getAvatar();\r
+\r
+        boolean useBodyImage = this.dialogPref.useBodyImage();\r
+        boolean useMonoImage = this.dialogPref.useMonoImage();\r
+\r
+        BufferedImage image;\r
+        if(this.talk.isGrave()){\r
+            if(useMonoImage){\r
+                if(useBodyImage){\r
+                    image = village.getAvatarBodyMonoImage(avatar);\r
+                }else{\r
+                    image = village.getAvatarFaceMonoImage(avatar);\r
+                }\r
+            }else{\r
+                if(useBodyImage){\r
+                    image = village.getGraveBodyImage();\r
+                }else{\r
+                    image = village.getGraveImage();\r
+                }\r
+            }\r
+        }else{\r
+            if(useBodyImage){\r
+                image = village.getAvatarBodyImage(avatar);\r
+            }else{\r
+                image = village.getAvatarFaceImage(avatar);\r
+            }\r
+        }\r
+\r
+        return image;\r
+    }\r
+\r
+    /**\r
+     * キャプション文字列を取得する。\r
+     * @return キャプション文字列\r
+     */\r
+    private CharSequence getCaptionString(){\r
+        StringBuilder result = new StringBuilder();\r
+\r
+        Avatar avatar = this.talk.getAvatar();\r
+\r
+        if(this.talk.hasTalkNo()){\r
+            result.append(this.talk.getAnchorNotation_G()).append(' ');\r
+        }\r
+        result.append(avatar.getFullName()).append(' ');\r
+        result.append(this.talk.getAnchorNotation());\r
+        result.append('\n');\r
+\r
+        DateFormat dform =\r
+            DateFormat.getDateTimeInstance(DateFormat.MEDIUM,\r
+                                           DateFormat.MEDIUM);\r
+        long epoch = this.talk.getTimeFromID();\r
+        String decoded = dform.format(epoch);\r
+        result.append(decoded);\r
+\r
+        int count = this.talk.getTalkCount();\r
+        if(count > 0){\r
+            TalkType type = this.talk.getTalkType();\r
+            result.append(" (").append(Talk.encodeColorName(type));\r
+            result.append('#').append(count).append(')');\r
+        }\r
+\r
+        int charNum = this.talk.getTotalChars();\r
+        if(charNum > 0){\r
+            result.append(' ').append(charNum).append('字');\r
+        }\r
+\r
+        return result;\r
+    }\r
+\r
+    /**\r
+     * 会話部背景色を返す。\r
+     * @return 会話部背景色\r
+     */\r
+    protected Color getTalkBgColor(){\r
+        if(this.dialogPref.isSimpleMode()) return COLOR_SIMPLEBG;\r
+\r
+        TalkType type = this.talk.getTalkType();\r
+        Color result = getTypedColor(type);\r
+\r
+        return result;\r
+    }\r
+\r
+    /**\r
+     * {@inheritDoc}\r
+     * @return {@inheritDoc}\r
+     */\r
+    public Rectangle recalcBounds(){\r
+        int newWidth = getWidth();\r
+\r
+        int imageWidth  = 0;\r
+        int imageHeight = 0;\r
+        if( ! this.dialogPref.isSimpleMode()){\r
+            imageWidth  = this.faceImage.getWidth(null);\r
+            imageHeight = this.faceImage.getHeight(null);\r
+        }\r
+\r
+        int tipWidth = BALOON_WOLFONLY.getWidth();\r
+\r
+        int modWidth;\r
+        int minWidth = imageWidth + tipWidth + BALOON_R * 2;\r
+        if(newWidth < minWidth) modWidth = minWidth;\r
+        else                    modWidth = newWidth;\r
+\r
+        this.caption.setWidth(modWidth);\r
+        int captionWidth  = this.caption.getWidth();\r
+        int captionHeight = this.caption.getHeight() + CAPTION_DIALOG_GAP;\r
+\r
+        this.dialog.setWidth(modWidth - minWidth);\r
+        int dialogWidth  = this.dialog.getWidth();\r
+        int dialogHeight = this.dialog.getHeight();\r
+\r
+        if(this.dialogPref.alignBaloonWidth()){\r
+            this.baloonWidth  = (modWidth - minWidth) + BALOON_R * 2;\r
+        }else{\r
+            this.baloonWidth  = dialogWidth + BALOON_R * 2;\r
+        }\r
+        this.baloonHeight = dialogHeight + BALOON_R * 2;\r
+\r
+        int imageAndDialogWidth = imageWidth + tipWidth + this.baloonWidth;\r
+\r
+        int totalWidth = Math.max(captionWidth, imageAndDialogWidth);\r
+\r
+        int totalHeight = captionHeight;\r
+        totalHeight += Math.max(imageHeight, this.baloonHeight);\r
+\r
+        int imageYpos = captionHeight;\r
+        int dialogYpos = captionHeight;\r
+        int tipYpos = captionHeight;\r
+        if(imageHeight < this.baloonHeight){\r
+            imageYpos += (this.baloonHeight - imageHeight) / 2;\r
+            tipYpos += (this.baloonHeight - BALOON_WOLFONLY.getHeight()) / 2;\r
+            dialogYpos += BALOON_R;\r
+        }else{\r
+            dialogYpos += (imageHeight - this.baloonHeight) / 2 + BALOON_R;\r
+            tipYpos += (imageHeight - BALOON_WOLFONLY.getHeight()) / 2;\r
+        }\r
+\r
+        this.imageOrigin = new Point(0, imageYpos);\r
+        this.caption.setPos(this.bounds.x + 0, this.bounds.y + 0);\r
+        this.dialogOrigin =\r
+                new Point(imageWidth+tipWidth+BALOON_R, dialogYpos);\r
+        this.dialog.setPos(this.bounds.x + imageWidth+tipWidth+BALOON_R,\r
+                           this.bounds.y + dialogYpos);\r
+        this.tipOrigin = new Point(imageWidth, tipYpos);\r
+\r
+        for(AnchorDraw anchorDraw : this.anchorTalks){\r
+            anchorDraw.setWidth(modWidth - OFFSET_ANCHOR);\r
+            totalHeight += anchorDraw.getHeight();\r
+        }\r
+\r
+        if(   this.dialogPref.isSimpleMode()\r
+           || this.dialogPref.alignBaloonWidth() ){\r
+            this.bounds.width = newWidth;\r
+        }else{\r
+            this.bounds.width = totalWidth;\r
+        }\r
+        this.bounds.height = UPPER_MARGIN + totalHeight + UNDER_MARGIN;\r
+\r
+        return this.bounds;\r
+    }\r
+\r
+    /**\r
+     * {@inheritDoc}\r
+     * @param xPos {@inheritDoc}\r
+     * @param yPos {@inheritDoc}\r
+     */\r
+    @Override\r
+    public void setPos(int xPos, int yPos){\r
+        super.setPos(xPos, yPos);\r
+        this.caption.setPos(this.bounds.x, this.bounds.y + UPPER_MARGIN);\r
+        this.dialog.setPos(this.bounds.x + this.dialogOrigin.x,\r
+                           this.bounds.y + this.dialogOrigin.y\r
+                                         + UPPER_MARGIN);\r
+        return;\r
+    }\r
+\r
+    /**\r
+     * アイコンイメージとフキダシを繋ぐ補助イメージを返す。\r
+     * @return 補助イメージ\r
+     */\r
+    private BufferedImage getTipImage(){\r
+        BufferedImage tip;\r
+\r
+        TalkType type = this.talk.getTalkType();\r
+\r
+        if(this.dialogPref.isSimpleMode()){\r
+            switch(type){\r
+            case PUBLIC:   tip = SQUARE_PUBLIC;   break;\r
+            case WOLFONLY: tip = SQUARE_WOLFONLY; break;\r
+            case GRAVE:    tip = SQUARE_GRAVE;    break;\r
+            case PRIVATE:  tip = SQUARE_PRIVATE;  break;\r
+            default:\r
+                assert false;\r
+                tip = null;\r
+                break;\r
+            }\r
+        }else{\r
+            switch(type){\r
+            case PUBLIC:   tip = BALOON_PUBLIC;   break;\r
+            case WOLFONLY: tip = BALOON_WOLFONLY; break;\r
+            case GRAVE:    tip = BALOON_GRAVE;    break;\r
+            case PRIVATE:  tip = BALOON_PRIVATE;  break;\r
+            default:\r
+                assert false;\r
+                tip = null;\r
+                break;\r
+            }\r
+        }\r
+\r
+        return tip;\r
+    }\r
+\r
+    /**\r
+     * {@inheritDoc}\r
+     * @param g {@inheritDoc}\r
+     */\r
+    public void paint(Graphics2D g){\r
+        final int xPos = this.bounds.x;\r
+        final int yPos = this.bounds.y + UPPER_MARGIN;\r
+\r
+        this.caption.paint(g);\r
+\r
+        if(this.dialogPref.isSimpleMode() ){\r
+            g.drawLine(xPos,                     this.bounds.y,\r
+                       xPos + this.bounds.width, this.bounds.y );\r
+        }else{\r
+            g.drawImage(this.faceImage,\r
+                        xPos + this.imageOrigin.x,\r
+                        yPos + this.imageOrigin.y,\r
+                        null );\r
+        }\r
+\r
+        BufferedImage tip = getTipImage();\r
+        g.drawImage(tip,\r
+                    xPos + this.tipOrigin.x,\r
+                    yPos + this.tipOrigin.y,\r
+                    null );\r
+\r
+        g.setColor(getTalkBgColor());\r
+        g.fillRoundRect(\r
+                xPos + this.dialogOrigin.x - BALOON_R,\r
+                yPos + this.dialogOrigin.y - BALOON_R,\r
+                this.baloonWidth,\r
+                this.baloonHeight,\r
+                BALOON_R,\r
+                BALOON_R );\r
+\r
+        this.dialog.paint(g);\r
+\r
+        int anchorX = xPos + OFFSET_ANCHOR;\r
+        int anchorY = yPos + this.dialogOrigin.y + baloonHeight;\r
+\r
+        for(AnchorDraw anchorDraw : this.anchorTalks){\r
+            anchorDraw.setPos(anchorX, anchorY);\r
+            anchorDraw.paint(g);\r
+            anchorY += anchorDraw.getHeight();\r
+        }\r
+\r
+        return;\r
+    }\r
+\r
+    /**\r
+     * {@inheritDoc}\r
+     * @param fontInfo {@inheritDoc}\r
+     */\r
+    @Override\r
+    public void setFontInfo(FontInfo fontInfo){\r
+        super.setFontInfo(fontInfo);\r
+\r
+        this.anchorFontInfo = deriveAnchorFontInfo(this.fontInfo);\r
+\r
+        this.caption.setFontInfo(this.fontInfo);\r
+        this.dialog .setFontInfo(this.fontInfo);\r
+\r
+        for(AnchorDraw anchorDraw : this.anchorTalks){\r
+            anchorDraw.setFontInfo(this.anchorFontInfo);\r
+        }\r
+\r
+        recalcBounds();\r
+\r
+        return;\r
+    }\r
+\r
+    /**\r
+     * 発言設定を更新する。\r
+     * @param pref 発言設定\r
+     */\r
+    public void setDialogPref(DialogPref pref){\r
+        this.dialogPref = pref;\r
+        this.faceImage = getFaceImage();\r
+\r
+        for(AnchorDraw anchorDraw : this.anchorTalks){\r
+            anchorDraw.setDialogPref(this.dialogPref);\r
+        }\r
+\r
+        setColorDesign();\r
+        recalcBounds();\r
+\r
+        return;\r
+    }\r
+\r
+    /**\r
+     * {@inheritDoc}\r
+     * @param from {@inheritDoc}\r
+     * @param to {@inheritDoc}\r
+     */\r
+    public void drag(Point from, Point to){\r
+        this.caption.drag(from, to);\r
+        this.dialog.drag(from, to);\r
+        for(AnchorDraw anchorDraw : this.anchorTalks){\r
+            anchorDraw.drag(from, to);\r
+        }\r
+        return;\r
+    }\r
+\r
+    /**\r
+     * {@inheritDoc}\r
+     * @param appendable {@inheritDoc}\r
+     * @return {@inheritDoc}\r
+     * @throws java.io.IOException {@inheritDoc}\r
+     */\r
+    public Appendable appendSelected(Appendable appendable)\r
+            throws IOException{\r
+        this.caption.appendSelected(appendable);\r
+        this.dialog .appendSelected(appendable);\r
+\r
+        for(AnchorDraw anchorDraw : this.anchorTalks){\r
+            anchorDraw.appendSelected(appendable);\r
+        }\r
+\r
+        return appendable;\r
+    }\r
+\r
+    /**\r
+     * {@inheritDoc}\r
+     */\r
+    public void clearSelect(){\r
+        this.caption.clearSelect();\r
+        this.dialog.clearSelect();\r
+        for(AnchorDraw anchorDraw : this.anchorTalks){\r
+            anchorDraw.clearSelect();\r
+        }\r
+        return;\r
+    }\r
+\r
+    /**\r
+     * 与えられた座標にアンカー文字列が存在すればAnchorを返す。\r
+     * @param pt 座標\r
+     * @return アンカー\r
+     */\r
+    public Anchor getAnchor(Point pt){\r
+        Anchor result = this.dialog.getAnchor(pt);\r
+        return result;\r
+    }\r
+\r
+    /**\r
+     * アンカーを展開表示する。\r
+     * アンカーにnullを指定すればアンカー表示は非表示となる。\r
+     * @param anchor アンカー\r
+     * @param talkList アンカーの示す一連のTalk\r
+     */\r
+    public void showAnchorTalks(Anchor anchor, List<Talk> talkList){\r
+        if(anchor == null || this.showingAnchor == anchor){\r
+            this.showingAnchor = null;\r
+            this.anchorTalks.clear();\r
+            recalcBounds();\r
+            return;\r
+        }\r
+\r
+        this.showingAnchor = anchor;\r
+\r
+        this.anchorTalks.clear();\r
+        for(Talk anchorTalk : talkList){\r
+            AnchorDraw anchorDraw =\r
+                    new AnchorDraw(anchorTalk,\r
+                                   this.dialogPref,\r
+                                   this.anchorFontInfo );\r
+            this.anchorTalks.add(anchorDraw);\r
+        }\r
+\r
+        recalcBounds();\r
+\r
+        return;\r
+    }\r
+\r
+    /**\r
+     * 与えられた座標に検索マッチ文字列があればそのインデックスを返す。\r
+     * @param pt 座標\r
+     * @return 検索マッチインデックス\r
+     */\r
+    public int getRegexMatchIndex(Point pt){\r
+        int index = this.dialog.getRegexMatchIndex(pt);\r
+        return index;\r
+    }\r
+\r
+    /**\r
+     * 検索文字列パターンを設定する。\r
+     * @param searchRegex パターン\r
+     * @return ヒット数\r
+     */\r
+    public int setRegex(Pattern searchRegex){\r
+        int total = 0;\r
+\r
+        total += this.dialog.setRegex(searchRegex);\r
+/*\r
+        for(AnchorDraw anchorDraw : this.anchorTalks){\r
+            total += anchorDraw.setRegex(searchRegex);\r
+        }\r
+*/ // TODO よくわからんので保留\r
+        return total;\r
+    }\r
+\r
+    /**\r
+     * 検索ハイライトインデックスを返す。\r
+     * @return 検索ハイライトインデックス。見つからなければ-1。\r
+     */\r
+    public int getHotTargetIndex(){\r
+        return this.dialog.getHotTargetIndex();\r
+    }\r
+\r
+    /**\r
+     * 検索ハイライトを設定する。\r
+     * @param index ハイライトインデックス。負ならハイライト全クリア。\r
+     */\r
+    public void setHotTargetIndex(int index){\r
+        this.dialog.setHotTargetIndex(index);\r
+        return;\r
+    }\r
+\r
+    /**\r
+     * 検索一致件数を返す。\r
+     * @return 検索一致件数\r
+     */\r
+    public int getRegexMatches(){\r
+        return this.dialog.getRegexMatches();\r
+    }\r
+\r
+    /**\r
+     * 特別な検索ハイライト描画をクリアする。\r
+     */\r
+    public void clearHotTarget(){\r
+        this.dialog.clearHotTarget();\r
+        return;\r
+    }\r
+\r
+    /**\r
+     * 特別な検索ハイライト領域の寸法を返す。\r
+     * @return ハイライト領域寸法\r
+     */\r
+    public Rectangle getHotTargetRectangle(){\r
+        return this.dialog.getHotTargetRectangle();\r
+    }\r
+\r
+}\r