OSDN Git Service

改行コード指定
[jindolf/Jindolf.git] / src / main / java / jp / sourceforge / jindolf / DaySummary.java
index c757951..00963c4 100644 (file)
-/*\r
- * summary of day panel\r
- *\r
- * License : The MIT License\r
- * Copyright(c) 2008 olyutorskii\r
- */\r
-\r
-package jp.sourceforge.jindolf;\r
-\r
-import java.awt.Color;\r
-import java.awt.Component;\r
-import java.awt.Container;\r
-import java.awt.Dimension;\r
-import java.awt.Frame;\r
-import java.awt.GridBagConstraints;\r
-import java.awt.GridBagLayout;\r
-import java.awt.Image;\r
-import java.awt.Insets;\r
-import java.awt.LayoutManager;\r
-import java.awt.event.ActionEvent;\r
-import java.awt.event.ActionListener;\r
-import java.awt.event.ItemEvent;\r
-import java.awt.event.ItemListener;\r
-import java.awt.event.WindowEvent;\r
-import java.awt.event.WindowListener;\r
-import java.text.NumberFormat;\r
-import java.util.HashMap;\r
-import java.util.List;\r
-import java.util.Map;\r
-import java.util.SortedSet;\r
-import java.util.TreeSet;\r
-import javax.swing.ImageIcon;\r
-import javax.swing.JButton;\r
-import javax.swing.JComboBox;\r
-import javax.swing.JDialog;\r
-import javax.swing.JLabel;\r
-import javax.swing.JScrollPane;\r
-import javax.swing.JSeparator;\r
-import javax.swing.JTable;\r
-import javax.swing.ListSelectionModel;\r
-import javax.swing.SwingConstants;\r
-import javax.swing.table.DefaultTableCellRenderer;\r
-import javax.swing.table.DefaultTableModel;\r
-import javax.swing.table.TableColumn;\r
-import javax.swing.table.TableColumnModel;\r
-import jp.sourceforge.jindolf.corelib.TalkType;\r
-\r
-/**\r
- * その日ごとの集計。\r
- */\r
-@SuppressWarnings("serial")\r
-public class DaySummary extends JDialog\r
-        implements WindowListener, ActionListener, ItemListener{\r
-\r
-    private static final String FRAMETITLE =\r
-            "発言集計 - " + Jindolf.TITLE;\r
-    private static final NumberFormat AVERAGE_FORM;\r
-    private static final String PUBTALK   = "白発言";\r
-    private static final String WOLFTALK  = "赤発言";\r
-    private static final String GRAVETALK = "青発言";\r
-    private static final String PRVTALK   = "灰発言";\r
-    private static final String ALLTALK   = "全発言";\r
-    private static final int HORIZONTAL_GAP = 5;\r
-    private static final int VERTICAL_GAP   = 1;\r
-    private static final Color COLOR_ALL = new Color(0xffff80);\r
-\r
-    static{\r
-        AVERAGE_FORM = NumberFormat.getInstance();\r
-        AVERAGE_FORM.setMaximumFractionDigits(1);\r
-        AVERAGE_FORM.setMinimumFractionDigits(1);\r
-    }\r
-\r
-\r
-    private final DefaultTableModel tableModel;\r
-    private final TableColumn avatarColumn;\r
-\r
-    private final JTable tableComp;\r
-    private final JComboBox typeSelector = new JComboBox();\r
-    private final JButton closeButton = new JButton("閉じる");\r
-    private final JLabel caption = new JLabel();\r
-    private final JLabel totalSum = new JLabel();\r
-\r
-    private TalkType talkFilter;\r
-    private Period period;\r
-\r
-\r
-    /**\r
-     * コンストラクタ。\r
-     * 集計結果を表示するモーダルダイアログを生成する。\r
-     * @param owner オーナー\r
-     */\r
-    public DaySummary(Frame owner){\r
-        super(owner, FRAMETITLE, true);\r
-\r
-        GUIUtils.modifyWindowAttributes(this, true, false, true);\r
-\r
-        setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);\r
-        addWindowListener(this);\r
-\r
-        this.tableModel = createInitModel();\r
-        this.tableComp = new JTable();\r
-        this.tableComp.setModel(this.tableModel);\r
-        this.tableComp.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);\r
-        this.tableComp.setIntercellSpacing(\r
-                new Dimension(HORIZONTAL_GAP, VERTICAL_GAP) );\r
-        this.tableComp.setDefaultEditor(Object.class, null);\r
-        this.tableComp.setDefaultRenderer(Object.class, new CustomRenderer());\r
-        this.tableComp.setShowGrid(true);\r
-\r
-        TableColumnModel tcolModel = this.tableComp.getColumnModel();\r
-\r
-        this.avatarColumn = tcolModel.getColumn(0);\r
-\r
-        DefaultTableCellRenderer renderer;\r
-\r
-        renderer = new DefaultTableCellRenderer();\r
-        renderer.setHorizontalAlignment(SwingConstants.RIGHT);\r
-        tcolModel.getColumn(1).setCellRenderer(renderer);\r
-\r
-        renderer = new DefaultTableCellRenderer();\r
-        renderer.setHorizontalAlignment(SwingConstants.RIGHT);\r
-        tcolModel.getColumn(2).setCellRenderer(renderer);\r
-\r
-        renderer = new DefaultTableCellRenderer();\r
-        renderer.setHorizontalAlignment(SwingConstants.RIGHT);\r
-        tcolModel.getColumn(3).setCellRenderer(renderer);\r
-\r
-        this.typeSelector.addItem(PUBTALK);\r
-        this.typeSelector.addItem(WOLFTALK);\r
-        this.typeSelector.addItem(GRAVETALK);\r
-        this.typeSelector.addItem(PRVTALK);\r
-        this.typeSelector.addItem(ALLTALK);\r
-\r
-        this.closeButton.addActionListener(this);\r
-        this.typeSelector.addItemListener(this);\r
-\r
-        this.typeSelector.setSelectedItem(null);\r
-        this.typeSelector.setSelectedItem(PUBTALK);\r
-\r
-        design();\r
-\r
-        clearModel();\r
-\r
-        return;\r
-    }\r
-\r
-\r
-    /**\r
-     * 初期のデータモデルを生成する。\r
-     * @return データモデル\r
-     */\r
-    private static DefaultTableModel createInitModel(){\r
-        DefaultTableModel result;\r
-        result = new DefaultTableModel();\r
-\r
-        Object[] rowHeads = {"名前", "発言回数", "平均文字列長", "最終発言"};\r
-        result.setColumnCount(rowHeads.length);\r
-        result.setColumnIdentifiers(rowHeads);\r
-\r
-        return result;\r
-    }\r
-\r
-\r
-    /**\r
-     * テーブルをクリアする。\r
-     */\r
-    private void clearModel(){\r
-        int rows = this.tableModel.getRowCount();\r
-        for(int ct = 1; ct <= rows; ct++){\r
-            this.tableModel.removeRow(0);\r
-        }\r
-    }\r
-\r
-    /**\r
-     * 行を追加する。\r
-     * @param avatar アバター\r
-     * @param talkCount 発言回数\r
-     * @param totalChars 発言文字総数\r
-     * @param lastTime 最終発言時刻\r
-     */\r
-    private void appendRow(Avatar avatar,\r
-                            Integer talkCount,\r
-                            Integer totalChars,\r
-                            String lastTime ){\r
-        String talks = talkCount + " 回";\r
-\r
-        double average;\r
-        if(talkCount <= 0) average = 0.0;\r
-        else               average = (double)totalChars / (double)talkCount;\r
-        String chars = AVERAGE_FORM.format(average) + " 文字";\r
-\r
-        Object[] row = {avatar, talks, chars, lastTime};\r
-        int rowIndex = this.tableModel.getRowCount();\r
-\r
-        this.tableModel.insertRow(rowIndex, row);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * デザインを行う。\r
-     */\r
-    private void design(){\r
-        Container content = getContentPane();\r
-\r
-        LayoutManager layout = new GridBagLayout();\r
-        GridBagConstraints constraints = new GridBagConstraints();\r
-        content.setLayout(layout);\r
-\r
-        constraints.insets = new Insets(5, 5, 5, 5);\r
-\r
-        constraints.gridwidth = 1;\r
-        constraints.fill = GridBagConstraints.NONE;\r
-        constraints.anchor = GridBagConstraints.WEST;\r
-        content.add(this.caption, constraints);\r
-\r
-        constraints.gridwidth = GridBagConstraints.REMAINDER;\r
-        constraints.fill = GridBagConstraints.NONE;\r
-        content.add(this.typeSelector, constraints);\r
-\r
-        JScrollPane scroller = new JScrollPane(this.tableComp);\r
-        constraints.weightx = 1.0;\r
-        constraints.weighty = 1.0;\r
-        constraints.fill = GridBagConstraints.BOTH;\r
-        content.add(scroller, constraints);\r
-\r
-        constraints.weightx = 0.0;\r
-        constraints.weighty = 0.0;\r
-        constraints.fill = GridBagConstraints.NONE;\r
-        constraints.anchor = GridBagConstraints.WEST;\r
-        content.add(this.totalSum, constraints);\r
-\r
-        constraints.weightx = 1.0;\r
-        constraints.weighty = 0.0;\r
-        constraints.fill = GridBagConstraints.HORIZONTAL;\r
-        content.add(new JSeparator(), constraints);\r
-\r
-        constraints.weightx = 0.0;\r
-        constraints.weighty = 0.0;\r
-        constraints.fill = GridBagConstraints.NONE;\r
-        constraints.anchor = GridBagConstraints.EAST;\r
-        content.add(this.closeButton, constraints);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * 与えられたPeriodで集計を更新する。\r
-     * @param newPeriod 日\r
-     */\r
-    public void summaryPeriod(Period newPeriod){\r
-        this.period = newPeriod;\r
-        summaryPeriod();\r
-    }\r
-\r
-    /**\r
-     * 集計を更新する。\r
-     */\r
-    private void summaryPeriod(){\r
-        clearModel();\r
-\r
-        if(this.period == null) return;\r
-\r
-        SortedSet<Avatar> avatarSet = new TreeSet<Avatar>();\r
-        Map<Avatar, Integer> talkCount  = new HashMap<Avatar, Integer>();\r
-        Map<Avatar, Integer> totalChars = new HashMap<Avatar, Integer>();\r
-        Map<Avatar, Talk> lastTalk = new HashMap<Avatar, Talk>();\r
-\r
-        List<Topic> topicList = this.period.getTopicList();\r
-        for(Topic topic : topicList){\r
-            if( ! (topic instanceof Talk)) continue;\r
-            Talk talk = (Talk) topic;\r
-            if(talk.getTalkCount() <= 0) continue;\r
-            if(   this.talkFilter != null\r
-               && talk.getTalkType() != this.talkFilter) continue;\r
-\r
-            Avatar avatar = talk.getAvatar();\r
-\r
-            Integer counts = talkCount.get(avatar);\r
-            if(counts == null) counts = Integer.valueOf(0);\r
-            counts++;\r
-            talkCount.put(avatar, counts);\r
-\r
-            Integer total = totalChars.get(avatar);\r
-            if(total == null) total = Integer.valueOf(0);\r
-            total += talk.getTotalChars();\r
-            totalChars.put(avatar, total);\r
-\r
-            lastTalk.put(avatar, talk);\r
-\r
-            avatarSet.add(avatar);\r
-        }\r
-\r
-        int sum = 0;\r
-        for(Avatar avatar : avatarSet){\r
-            Integer counts = talkCount.get(avatar);\r
-            Integer total = totalChars.get(avatar);\r
-            String lastTime = lastTalk.get(avatar).getAnchorNotation();\r
-            appendRow(avatar, counts, total, lastTime);\r
-            sum += counts;\r
-        }\r
-\r
-        this.totalSum.setText("合計:" + sum + " 発言");\r
-\r
-        Village village = this.period.getVillage();\r
-        String villageName = village.getVillageName();\r
-        String periodCaption = this.period.getCaption();\r
-        this.caption.setText(villageName + "村 " + periodCaption);\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param event {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void windowActivated(WindowEvent event){\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param event {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void windowDeactivated(WindowEvent event){\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param event {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void windowIconified(WindowEvent event){\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param event {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void windowDeiconified(WindowEvent event){\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param event {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void windowOpened(WindowEvent event){\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * ダイアログのクローズボタン押下処理を行う。\r
-     * @param event ウィンドウ変化イベント {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void windowClosing(WindowEvent event){\r
-        close();\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * @param event {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void windowClosed(WindowEvent event){\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * クローズボタン押下処理。\r
-     * @param event イベント {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void actionPerformed(ActionEvent event){\r
-        if(event.getSource() != this.closeButton) return;\r
-        close();\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * {@inheritDoc}\r
-     * コンボボックス操作処理。\r
-     * @param event イベント {@inheritDoc}\r
-     */\r
-    @Override\r
-    public void itemStateChanged(ItemEvent event){\r
-        if(event.getStateChange() != ItemEvent.SELECTED) return;\r
-\r
-        Object selected = this.typeSelector.getSelectedItem();\r
-        if     (selected == PUBTALK)   this.talkFilter = TalkType.PUBLIC;\r
-        else if(selected == WOLFTALK)  this.talkFilter = TalkType.WOLFONLY;\r
-        else if(selected == GRAVETALK) this.talkFilter = TalkType.GRAVE;\r
-        else if(selected == PRVTALK)   this.talkFilter = TalkType.PRIVATE;\r
-        else if(selected == ALLTALK)   this.talkFilter = null;\r
-\r
-        summaryPeriod();\r
-\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * このパネルを閉じる。\r
-     */\r
-    private void close(){\r
-        clearModel();\r
-        this.period = null;\r
-        setVisible(false);\r
-        return;\r
-    }\r
-\r
-    /**\r
-     * Avatar 顔イメージ描画用カスタムセルレンダラ。\r
-     */\r
-    private class CustomRenderer extends DefaultTableCellRenderer{\r
-\r
-        /**\r
-         * コンストラクタ。\r
-         */\r
-        public CustomRenderer(){\r
-            super();\r
-            return;\r
-        }\r
-\r
-        /**\r
-         * {@inheritDoc}\r
-         * セルに{@link Avatar}がきたら顔アイコンと名前を表示する。\r
-         * @param value {@inheritDoc}\r
-         */\r
-        @Override\r
-        public void setValue(Object value){\r
-            if(value instanceof Avatar){\r
-                Avatar avatar = (Avatar) value;\r
-\r
-                Village village = DaySummary.this.period.getVillage();\r
-                Image image = village.getAvatarFaceImage(avatar);\r
-                if(image == null) image = village.getGraveImage();\r
-                if(image != null){\r
-                    ImageIcon icon = new ImageIcon(image);\r
-                    setIcon(icon);\r
-                }\r
-\r
-                setText(avatar.getName());\r
-\r
-                Dimension prefSize = getPreferredSize();\r
-\r
-                int cellHeight = VERTICAL_GAP * 2 + prefSize.height;\r
-                if(DaySummary.this.tableComp.getRowHeight() < cellHeight){\r
-                    DaySummary.this.tableComp.setRowHeight(cellHeight);\r
-                }\r
-\r
-                int cellWidth = HORIZONTAL_GAP * 2 + prefSize.width;\r
-                if(  DaySummary.this.avatarColumn.getPreferredWidth()\r
-                   < cellWidth ){\r
-                    DaySummary.this.avatarColumn.setPreferredWidth(cellWidth);\r
-                }\r
-\r
-                return;\r
-            }\r
-\r
-            super.setValue(value);\r
-\r
-            return;\r
-        }\r
-\r
-        /**\r
-         *  {@inheritDoc}\r
-         * 統計種別によってセル色を変える。\r
-         * @param table {@inheritDoc}\r
-         * @param value {@inheritDoc}\r
-         * @param isSelected {@inheritDoc}\r
-         * @param hasFocus {@inheritDoc}\r
-         * @param row {@inheritDoc}\r
-         * @param column {@inheritDoc}\r
-         * @return {@inheritDoc}\r
-         */\r
-        @Override\r
-        public Component getTableCellRendererComponent(JTable table,\r
-                                                           Object value,\r
-                                                           boolean isSelected,\r
-                                                           boolean hasFocus,\r
-                                                           int row,\r
-                                                           int column ){\r
-            Component result = super.getTableCellRendererComponent(table,\r
-                                                                   value,\r
-                                                                   isSelected,\r
-                                                                   hasFocus,\r
-                                                                   row,\r
-                                                                   column );\r
-\r
-            Object selected = DaySummary.this.typeSelector.getSelectedItem();\r
-            Color bgColor = null;\r
-            if(selected == PUBTALK){\r
-                bgColor = TalkDraw.COLOR_PUBLIC;\r
-            }else if(selected == WOLFTALK){\r
-                bgColor = TalkDraw.COLOR_WOLFONLY;\r
-            }else if(selected == GRAVETALK){\r
-                bgColor = TalkDraw.COLOR_GRAVE;\r
-            }else if(selected == PRVTALK){\r
-                bgColor = TalkDraw.COLOR_PRIVATE;\r
-            }else if(selected == ALLTALK){\r
-                bgColor = COLOR_ALL;\r
-            }else{\r
-                assert false;\r
-                return null;\r
-            }\r
-\r
-            result.setForeground(Color.BLACK);\r
-            result.setBackground(bgColor);\r
-\r
-            return result;\r
-        }\r
-    }\r
-\r
-}\r
+/*
+ * summary of day panel
+ *
+ * License : The MIT License
+ * Copyright(c) 2008 olyutorskii
+ */
+
+package jp.sourceforge.jindolf;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Image;
+import java.awt.Insets;
+import java.awt.LayoutManager;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowListener;
+import java.text.NumberFormat;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JScrollPane;
+import javax.swing.JSeparator;
+import javax.swing.JTable;
+import javax.swing.ListSelectionModel;
+import javax.swing.SwingConstants;
+import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.table.DefaultTableModel;
+import javax.swing.table.TableColumn;
+import javax.swing.table.TableColumnModel;
+import jp.sourceforge.jindolf.corelib.TalkType;
+
+/**
+ * その日ごとの集計。
+ */
+@SuppressWarnings("serial")
+public class DaySummary extends JDialog
+        implements WindowListener, ActionListener, ItemListener{
+
+    private static final String FRAMETITLE =
+            "発言集計 - " + Jindolf.TITLE;
+    private static final NumberFormat AVERAGE_FORM;
+    private static final String PUBTALK   = "白発言";
+    private static final String WOLFTALK  = "赤発言";
+    private static final String GRAVETALK = "青発言";
+    private static final String PRVTALK   = "灰発言";
+    private static final String ALLTALK   = "全発言";
+    private static final int HORIZONTAL_GAP = 5;
+    private static final int VERTICAL_GAP   = 1;
+    private static final Color COLOR_ALL = new Color(0xffff80);
+
+    static{
+        AVERAGE_FORM = NumberFormat.getInstance();
+        AVERAGE_FORM.setMaximumFractionDigits(1);
+        AVERAGE_FORM.setMinimumFractionDigits(1);
+    }
+
+
+    private final DefaultTableModel tableModel;
+    private final TableColumn avatarColumn;
+
+    private final JTable tableComp;
+    private final JComboBox typeSelector = new JComboBox();
+    private final JButton closeButton = new JButton("閉じる");
+    private final JLabel caption = new JLabel();
+    private final JLabel totalSum = new JLabel();
+
+    private TalkType talkFilter;
+    private Period period;
+
+
+    /**
+     * コンストラクタ。
+     * 集計結果を表示するモーダルダイアログを生成する。
+     * @param owner オーナー
+     */
+    public DaySummary(Frame owner){
+        super(owner, FRAMETITLE, true);
+
+        GUIUtils.modifyWindowAttributes(this, true, false, true);
+
+        setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
+        addWindowListener(this);
+
+        this.tableModel = createInitModel();
+        this.tableComp = new JTable();
+        this.tableComp.setModel(this.tableModel);
+        this.tableComp.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+        this.tableComp.setIntercellSpacing(
+                new Dimension(HORIZONTAL_GAP, VERTICAL_GAP) );
+        this.tableComp.setDefaultEditor(Object.class, null);
+        this.tableComp.setDefaultRenderer(Object.class, new CustomRenderer());
+        this.tableComp.setShowGrid(true);
+
+        TableColumnModel tcolModel = this.tableComp.getColumnModel();
+
+        this.avatarColumn = tcolModel.getColumn(0);
+
+        DefaultTableCellRenderer renderer;
+
+        renderer = new DefaultTableCellRenderer();
+        renderer.setHorizontalAlignment(SwingConstants.RIGHT);
+        tcolModel.getColumn(1).setCellRenderer(renderer);
+
+        renderer = new DefaultTableCellRenderer();
+        renderer.setHorizontalAlignment(SwingConstants.RIGHT);
+        tcolModel.getColumn(2).setCellRenderer(renderer);
+
+        renderer = new DefaultTableCellRenderer();
+        renderer.setHorizontalAlignment(SwingConstants.RIGHT);
+        tcolModel.getColumn(3).setCellRenderer(renderer);
+
+        this.typeSelector.addItem(PUBTALK);
+        this.typeSelector.addItem(WOLFTALK);
+        this.typeSelector.addItem(GRAVETALK);
+        this.typeSelector.addItem(PRVTALK);
+        this.typeSelector.addItem(ALLTALK);
+
+        this.closeButton.addActionListener(this);
+        this.typeSelector.addItemListener(this);
+
+        this.typeSelector.setSelectedItem(null);
+        this.typeSelector.setSelectedItem(PUBTALK);
+
+        design();
+
+        clearModel();
+
+        return;
+    }
+
+
+    /**
+     * 初期のデータモデルを生成する。
+     * @return データモデル
+     */
+    private static DefaultTableModel createInitModel(){
+        DefaultTableModel result;
+        result = new DefaultTableModel();
+
+        Object[] rowHeads = {"名前", "発言回数", "平均文字列長", "最終発言"};
+        result.setColumnCount(rowHeads.length);
+        result.setColumnIdentifiers(rowHeads);
+
+        return result;
+    }
+
+
+    /**
+     * テーブルをクリアする。
+     */
+    private void clearModel(){
+        int rows = this.tableModel.getRowCount();
+        for(int ct = 1; ct <= rows; ct++){
+            this.tableModel.removeRow(0);
+        }
+    }
+
+    /**
+     * 行を追加する。
+     * @param avatar アバター
+     * @param talkCount 発言回数
+     * @param totalChars 発言文字総数
+     * @param lastTime 最終発言時刻
+     */
+    private void appendRow(Avatar avatar,
+                            Integer talkCount,
+                            Integer totalChars,
+                            String lastTime ){
+        String talks = talkCount + " 回";
+
+        double average;
+        if(talkCount <= 0) average = 0.0;
+        else               average = (double)totalChars / (double)talkCount;
+        String chars = AVERAGE_FORM.format(average) + " 文字";
+
+        Object[] row = {avatar, talks, chars, lastTime};
+        int rowIndex = this.tableModel.getRowCount();
+
+        this.tableModel.insertRow(rowIndex, row);
+
+        return;
+    }
+
+    /**
+     * デザインを行う。
+     */
+    private void design(){
+        Container content = getContentPane();
+
+        LayoutManager layout = new GridBagLayout();
+        GridBagConstraints constraints = new GridBagConstraints();
+        content.setLayout(layout);
+
+        constraints.insets = new Insets(5, 5, 5, 5);
+
+        constraints.gridwidth = 1;
+        constraints.fill = GridBagConstraints.NONE;
+        constraints.anchor = GridBagConstraints.WEST;
+        content.add(this.caption, constraints);
+
+        constraints.gridwidth = GridBagConstraints.REMAINDER;
+        constraints.fill = GridBagConstraints.NONE;
+        content.add(this.typeSelector, constraints);
+
+        JScrollPane scroller = new JScrollPane(this.tableComp);
+        constraints.weightx = 1.0;
+        constraints.weighty = 1.0;
+        constraints.fill = GridBagConstraints.BOTH;
+        content.add(scroller, constraints);
+
+        constraints.weightx = 0.0;
+        constraints.weighty = 0.0;
+        constraints.fill = GridBagConstraints.NONE;
+        constraints.anchor = GridBagConstraints.WEST;
+        content.add(this.totalSum, constraints);
+
+        constraints.weightx = 1.0;
+        constraints.weighty = 0.0;
+        constraints.fill = GridBagConstraints.HORIZONTAL;
+        content.add(new JSeparator(), constraints);
+
+        constraints.weightx = 0.0;
+        constraints.weighty = 0.0;
+        constraints.fill = GridBagConstraints.NONE;
+        constraints.anchor = GridBagConstraints.EAST;
+        content.add(this.closeButton, constraints);
+
+        return;
+    }
+
+    /**
+     * 与えられたPeriodで集計を更新する。
+     * @param newPeriod 日
+     */
+    public void summaryPeriod(Period newPeriod){
+        this.period = newPeriod;
+        summaryPeriod();
+    }
+
+    /**
+     * 集計を更新する。
+     */
+    private void summaryPeriod(){
+        clearModel();
+
+        if(this.period == null) return;
+
+        SortedSet<Avatar> avatarSet = new TreeSet<Avatar>();
+        Map<Avatar, Integer> talkCount  = new HashMap<Avatar, Integer>();
+        Map<Avatar, Integer> totalChars = new HashMap<Avatar, Integer>();
+        Map<Avatar, Talk> lastTalk = new HashMap<Avatar, Talk>();
+
+        List<Topic> topicList = this.period.getTopicList();
+        for(Topic topic : topicList){
+            if( ! (topic instanceof Talk)) continue;
+            Talk talk = (Talk) topic;
+            if(talk.getTalkCount() <= 0) continue;
+            if(   this.talkFilter != null
+               && talk.getTalkType() != this.talkFilter) continue;
+
+            Avatar avatar = talk.getAvatar();
+
+            Integer counts = talkCount.get(avatar);
+            if(counts == null) counts = Integer.valueOf(0);
+            counts++;
+            talkCount.put(avatar, counts);
+
+            Integer total = totalChars.get(avatar);
+            if(total == null) total = Integer.valueOf(0);
+            total += talk.getTotalChars();
+            totalChars.put(avatar, total);
+
+            lastTalk.put(avatar, talk);
+
+            avatarSet.add(avatar);
+        }
+
+        int sum = 0;
+        for(Avatar avatar : avatarSet){
+            Integer counts = talkCount.get(avatar);
+            Integer total = totalChars.get(avatar);
+            String lastTime = lastTalk.get(avatar).getAnchorNotation();
+            appendRow(avatar, counts, total, lastTime);
+            sum += counts;
+        }
+
+        this.totalSum.setText("合計:" + sum + " 発言");
+
+        Village village = this.period.getVillage();
+        String villageName = village.getVillageName();
+        String periodCaption = this.period.getCaption();
+        this.caption.setText(villageName + "村 " + periodCaption);
+
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param event {@inheritDoc}
+     */
+    @Override
+    public void windowActivated(WindowEvent event){
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param event {@inheritDoc}
+     */
+    @Override
+    public void windowDeactivated(WindowEvent event){
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param event {@inheritDoc}
+     */
+    @Override
+    public void windowIconified(WindowEvent event){
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param event {@inheritDoc}
+     */
+    @Override
+    public void windowDeiconified(WindowEvent event){
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param event {@inheritDoc}
+     */
+    @Override
+    public void windowOpened(WindowEvent event){
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * ダイアログのクローズボタン押下処理を行う。
+     * @param event ウィンドウ変化イベント {@inheritDoc}
+     */
+    @Override
+    public void windowClosing(WindowEvent event){
+        close();
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @param event {@inheritDoc}
+     */
+    @Override
+    public void windowClosed(WindowEvent event){
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * クローズボタン押下処理。
+     * @param event イベント {@inheritDoc}
+     */
+    @Override
+    public void actionPerformed(ActionEvent event){
+        if(event.getSource() != this.closeButton) return;
+        close();
+        return;
+    }
+
+    /**
+     * {@inheritDoc}
+     * コンボボックス操作処理。
+     * @param event イベント {@inheritDoc}
+     */
+    @Override
+    public void itemStateChanged(ItemEvent event){
+        if(event.getStateChange() != ItemEvent.SELECTED) return;
+
+        Object selected = this.typeSelector.getSelectedItem();
+        if     (selected == PUBTALK)   this.talkFilter = TalkType.PUBLIC;
+        else if(selected == WOLFTALK)  this.talkFilter = TalkType.WOLFONLY;
+        else if(selected == GRAVETALK) this.talkFilter = TalkType.GRAVE;
+        else if(selected == PRVTALK)   this.talkFilter = TalkType.PRIVATE;
+        else if(selected == ALLTALK)   this.talkFilter = null;
+
+        summaryPeriod();
+
+        return;
+    }
+
+    /**
+     * このパネルを閉じる。
+     */
+    private void close(){
+        clearModel();
+        this.period = null;
+        setVisible(false);
+        return;
+    }
+
+    /**
+     * Avatar 顔イメージ描画用カスタムセルレンダラ。
+     */
+    private class CustomRenderer extends DefaultTableCellRenderer{
+
+        /**
+         * コンストラクタ。
+         */
+        public CustomRenderer(){
+            super();
+            return;
+        }
+
+        /**
+         * {@inheritDoc}
+         * セルに{@link Avatar}がきたら顔アイコンと名前を表示する。
+         * @param value {@inheritDoc}
+         */
+        @Override
+        public void setValue(Object value){
+            if(value instanceof Avatar){
+                Avatar avatar = (Avatar) value;
+
+                Village village = DaySummary.this.period.getVillage();
+                Image image = village.getAvatarFaceImage(avatar);
+                if(image == null) image = village.getGraveImage();
+                if(image != null){
+                    ImageIcon icon = new ImageIcon(image);
+                    setIcon(icon);
+                }
+
+                setText(avatar.getName());
+
+                Dimension prefSize = getPreferredSize();
+
+                int cellHeight = VERTICAL_GAP * 2 + prefSize.height;
+                if(DaySummary.this.tableComp.getRowHeight() < cellHeight){
+                    DaySummary.this.tableComp.setRowHeight(cellHeight);
+                }
+
+                int cellWidth = HORIZONTAL_GAP * 2 + prefSize.width;
+                if(  DaySummary.this.avatarColumn.getPreferredWidth()
+                   < cellWidth ){
+                    DaySummary.this.avatarColumn.setPreferredWidth(cellWidth);
+                }
+
+                return;
+            }
+
+            super.setValue(value);
+
+            return;
+        }
+
+        /**
+         *  {@inheritDoc}
+         * 統計種別によってセル色を変える。
+         * @param table {@inheritDoc}
+         * @param value {@inheritDoc}
+         * @param isSelected {@inheritDoc}
+         * @param hasFocus {@inheritDoc}
+         * @param row {@inheritDoc}
+         * @param column {@inheritDoc}
+         * @return {@inheritDoc}
+         */
+        @Override
+        public Component getTableCellRendererComponent(JTable table,
+                                                           Object value,
+                                                           boolean isSelected,
+                                                           boolean hasFocus,
+                                                           int row,
+                                                           int column ){
+            Component result = super.getTableCellRendererComponent(table,
+                                                                   value,
+                                                                   isSelected,
+                                                                   hasFocus,
+                                                                   row,
+                                                                   column );
+
+            Object selected = DaySummary.this.typeSelector.getSelectedItem();
+            Color bgColor = null;
+            if(selected == PUBTALK){
+                bgColor = TalkDraw.COLOR_PUBLIC;
+            }else if(selected == WOLFTALK){
+                bgColor = TalkDraw.COLOR_WOLFONLY;
+            }else if(selected == GRAVETALK){
+                bgColor = TalkDraw.COLOR_GRAVE;
+            }else if(selected == PRVTALK){
+                bgColor = TalkDraw.COLOR_PRIVATE;
+            }else if(selected == ALLTALK){
+                bgColor = COLOR_ALL;
+            }else{
+                assert false;
+                return null;
+            }
+
+            result.setForeground(Color.BLACK);
+            result.setBackground(bgColor);
+
+            return result;
+        }
+    }
+
+}