--- /dev/null
+/*\r
+ * period viewer\r
+ *\r
+ * Copyright(c) 2008 olyutorskii\r
+ * $Id: PeriodView.java 972 2009-12-26 05:05:15Z olyutorskii $\r
+ */\r
+\r
+package jp.sourceforge.jindolf;\r
+\r
+import java.awt.BorderLayout;\r
+import java.awt.Color;\r
+import java.awt.Component;\r
+import java.awt.GridBagConstraints;\r
+import java.awt.GridBagLayout;\r
+import java.awt.Insets;\r
+import java.awt.LayoutManager;\r
+import java.awt.Rectangle;\r
+import java.awt.event.ItemEvent;\r
+import java.awt.event.ItemListener;\r
+import java.util.List;\r
+import javax.swing.BorderFactory;\r
+import javax.swing.DefaultComboBoxModel;\r
+import javax.swing.DefaultListCellRenderer;\r
+import javax.swing.JComboBox;\r
+import javax.swing.JLabel;\r
+import javax.swing.JList;\r
+import javax.swing.JPanel;\r
+import javax.swing.JScrollBar;\r
+import javax.swing.JScrollPane;\r
+import javax.swing.JViewport;\r
+import javax.swing.ScrollPaneConstants;\r
+import javax.swing.border.Border;\r
+import jp.sourceforge.jindolf.corelib.TalkType;\r
+\r
+/**\r
+ * 発言ブラウザを内包するPeriodビューワ。\r
+ */\r
+@SuppressWarnings("serial")\r
+public class PeriodView extends JPanel implements ItemListener{\r
+\r
+ private static final Color COLOR_SELECT = new Color(0xffff80);\r
+ private static final Color COLOR_NORMALBG = Color.BLACK;\r
+ private static final Color COLOR_SIMPLEBG = Color.WHITE;\r
+\r
+ private Period period;\r
+\r
+ private final Discussion discussion;\r
+ private final JScrollPane scroller = new JScrollPane();\r
+ private final JLabel caption = new JLabel();\r
+ private final JLabel limit = new JLabel();\r
+ private final JComboBox talkSelector = new JComboBox();\r
+ private final DefaultComboBoxModel model = new DefaultComboBoxModel();\r
+\r
+ private DialogPref dialogPref = new DialogPref();\r
+\r
+ /**\r
+ * 発言ブラウザを内包するPeriodビューワを生成する。\r
+ * @param period 日\r
+ */\r
+ public PeriodView(Period period){\r
+ super();\r
+\r
+ this.period = period;\r
+\r
+ this.talkSelector.setEditable(false);\r
+ this.talkSelector.setMaximumRowCount(20);\r
+ this.talkSelector.setModel(this.model);\r
+ this.talkSelector.setRenderer(new AnchorRenderer());\r
+ this.talkSelector.addItemListener(this);\r
+\r
+ this.discussion = new Discussion();\r
+ Border border =\r
+ BorderFactory.createMatteBorder(15, 15, 15, 15, Color.BLACK);\r
+ this.discussion.setBorder(border);\r
+ this.discussion.setPeriod(this.period);\r
+\r
+ JViewport viewPort = this.scroller.getViewport();\r
+ viewPort.setBackground(Color.BLACK);\r
+ viewPort.setView(this.discussion);\r
+\r
+ this.scroller.setHorizontalScrollBarPolicy(\r
+ ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);\r
+ this.scroller.setVerticalScrollBarPolicy(\r
+ ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);\r
+\r
+ design();\r
+\r
+ setColorDesign();\r
+\r
+ return;\r
+ }\r
+\r
+ /**\r
+ * デザインを行う。\r
+ */\r
+ private void design(){\r
+ LayoutManager layout;\r
+\r
+ JPanel topPanel = new JPanel();\r
+ layout = new GridBagLayout();\r
+ GridBagConstraints constraints = new GridBagConstraints();\r
+ topPanel.setLayout(layout);\r
+ constraints.insets = new Insets(1, 3, 1, 3);\r
+ constraints.weightx = 1.0;\r
+ constraints.anchor = GridBagConstraints.WEST;\r
+ constraints.fill = GridBagConstraints.NONE;\r
+ topPanel.add(this.caption, constraints);\r
+ constraints.weightx = 0.0;\r
+ constraints.anchor = GridBagConstraints.EAST;\r
+ topPanel.add(this.limit, constraints);\r
+ constraints.weightx = 0.0;\r
+ topPanel.add(this.talkSelector, constraints);\r
+\r
+ layout = new BorderLayout();\r
+ setLayout(layout);\r
+ add(topPanel, BorderLayout.NORTH);\r
+ add(this.scroller, BorderLayout.CENTER);\r
+\r
+ return;\r
+ }\r
+\r
+ /**\r
+ * 配色を設定する。\r
+ */\r
+ private void setColorDesign(){\r
+ Color bgColor;\r
+\r
+ if(this.dialogPref.isSimpleMode()){\r
+ bgColor = COLOR_SIMPLEBG;\r
+ }else{\r
+ bgColor = COLOR_NORMALBG;\r
+ }\r
+\r
+ JViewport viewPort = this.scroller.getViewport();\r
+ viewPort.setBackground(bgColor);\r
+\r
+ Border border =\r
+ BorderFactory.createMatteBorder(15, 15, 15, 15, bgColor);\r
+ this.discussion.setBorder(border);\r
+\r
+ repaint();\r
+\r
+ return;\r
+ }\r
+\r
+ /**\r
+ * Periodを更新する。\r
+ * 古いPeriodの表示内容は消える。\r
+ * 新しいPeriodの表示内容はまだ反映されない。\r
+ * @param period 新しいPeriod\r
+ */\r
+ public void setPeriod(Period period){\r
+ this.discussion.setPeriod(period);\r
+\r
+ this.period = period;\r
+\r
+ updateTopPanel();\r
+\r
+ return;\r
+ }\r
+\r
+ /**\r
+ * 現在のPeriodを返す。\r
+ * @return 現在のPeriod\r
+ */\r
+ public Period getPeriod(){\r
+ return this.discussion.getPeriod();\r
+ }\r
+\r
+ /**\r
+ * 上部のGUI(村名、発言一覧)を、Periodの状態に合わせて更新する。\r
+ */\r
+ private void updateTopPanel(){\r
+ if(this.period == null){\r
+ this.caption.setText("");\r
+ this.limit.setText("");\r
+ this.model.removeAllElements();\r
+ return;\r
+ }\r
+\r
+ Village village = this.period.getVillage();\r
+ String villageName = village.getVillageName();\r
+\r
+ String dayCaption = this.period.getCaption();\r
+ String limitCaption = this.period.getLimit();\r
+ String account = this.period.getLoginName();\r
+\r
+ String loginout;\r
+ if(this.period.isFullOpen()){\r
+ loginout = "";\r
+ }else if(account != null){\r
+ loginout = " (ログイン中)";\r
+ }else{\r
+ loginout = " (ログアウト中)";\r
+ }\r
+\r
+ String info = villageName + "村 " + dayCaption + loginout;\r
+ this.caption.setText(info);\r
+ this.limit.setText("更新時刻 " + limitCaption);\r
+\r
+ this.model.removeAllElements();\r
+ this.model.addElement(" ");\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
+ this.model.addElement(talk);\r
+ }\r
+\r
+ return;\r
+ }\r
+\r
+ /**\r
+ * フィルタを適用してPeriodの内容を出力する。\r
+ */\r
+ public void showTopics(){\r
+ Period newPeriod = this.discussion.getPeriod();\r
+ setPeriod(newPeriod);\r
+ return;\r
+ }\r
+\r
+ /**\r
+ * フォント描画設定を変更する。\r
+ * @param fontInfo フォント設定\r
+ */\r
+ // TODO スクロール位置の復元\r
+ public void setFontInfo(FontInfo fontInfo){\r
+ this.discussion.setFontInfo(fontInfo);\r
+\r
+ revalidate();\r
+ repaint();\r
+\r
+ return;\r
+ }\r
+\r
+ /**\r
+ * 発言表示設定を更新する。\r
+ * @param pref 表示設定\r
+ */\r
+ public void setDialogPref(DialogPref pref){\r
+ this.dialogPref = pref;\r
+ this.discussion.setDialogPref(this.dialogPref);\r
+\r
+ setColorDesign();\r
+ revalidate();\r
+ repaint();\r
+\r
+ return;\r
+ }\r
+\r
+ /**\r
+ * ビューポート内の発言ブラウザを返す。\r
+ * @return 内部ブラウザ\r
+ */\r
+ public Discussion getDiscussion(){\r
+ return this.discussion;\r
+ }\r
+\r
+ /**\r
+ * スクロール位置を返す。\r
+ * @return スクロール位置\r
+ */\r
+ public int getVerticalPosition(){\r
+ JScrollBar vt = this.scroller.getVerticalScrollBar();\r
+ int pos = vt.getValue();\r
+ return pos;\r
+ }\r
+\r
+ /**\r
+ * スクロール位置を設定する。\r
+ * @param pos スクロール位置\r
+ */\r
+ public void setVerticalPosition(int pos){\r
+ JScrollBar vt = this.scroller.getVerticalScrollBar();\r
+ vt.setValue(pos);\r
+ return;\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ * コンボボックス操作のリスナ。\r
+ * @param event コンボボックス操作イベント {@inheritDoc}\r
+ */\r
+ public void itemStateChanged(ItemEvent event){\r
+ if(event.getStateChange() != ItemEvent.SELECTED) return;\r
+\r
+ Object selected = this.talkSelector.getSelectedItem();\r
+ if( ! (selected instanceof Talk) ) return;\r
+ Talk talk = (Talk) selected;\r
+\r
+ scrollToTalk(talk);\r
+\r
+ return;\r
+ }\r
+\r
+ /**\r
+ * 任意の発言が表示されるようスクロールする。\r
+ * @param talk 発言\r
+ */\r
+ public void scrollToTalk(Talk talk){\r
+ if(talk == null) return;\r
+ if(talk.getPeriod() != this.period) return;\r
+\r
+ Rectangle rect = this.discussion.getTalkBounds(talk);\r
+ if(rect == null) return;\r
+\r
+ Rectangle showRect = new Rectangle(rect);\r
+ showRect.y -= 15;\r
+ showRect.height = this.scroller.getHeight();\r
+ this.discussion.scrollRectToVisible(showRect);\r
+\r
+ return;\r
+ }\r
+\r
+ /**\r
+ * Talkをアイテムに持つコンボボックス用のセル描画。\r
+ */\r
+ private static class AnchorRenderer extends DefaultListCellRenderer{\r
+\r
+ /**\r
+ * コンストラクタ。\r
+ */\r
+ public AnchorRenderer(){\r
+ super();\r
+ return;\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ * Talkのアンカー表記と発言者名を描画する。\r
+ * @param list {@inheritDoc}\r
+ * @param value {@inheritDoc}\r
+ * @param index {@inheritDoc}\r
+ * @param isSelected {@inheritDoc}\r
+ * @param cellHasFocus {@inheritDoc}\r
+ * @return {@inheritDoc}\r
+ */\r
+ @Override\r
+ public Component getListCellRendererComponent(\r
+ JList list,\r
+ Object value,\r
+ int index,\r
+ boolean isSelected,\r
+ boolean cellHasFocus ){\r
+ Talk talk = null;\r
+ Object newValue = value;\r
+ if(value instanceof Talk){\r
+ talk = (Talk) value;\r
+ newValue = new StringBuilder()\r
+ .append(talk.getAnchorNotation())\r
+ .append(' ')\r
+ .append(talk.getAvatar().getName())\r
+ .toString();\r
+ }\r
+\r
+ Component superResult =\r
+ super.getListCellRendererComponent(list,\r
+ newValue,\r
+ index,\r
+ isSelected,\r
+ cellHasFocus);\r
+\r
+ if(talk != null){\r
+ Color bgColor = null;\r
+ if(isSelected){\r
+ bgColor = COLOR_SELECT;\r
+ }else{\r
+ TalkType type = talk.getTalkType();\r
+ bgColor = TalkDraw.getTypedColor(type);\r
+ }\r
+ superResult.setForeground(Color.BLACK);\r
+ superResult.setBackground(bgColor);\r
+ }\r
+\r
+ return superResult;\r
+ }\r
+ }\r
+\r
+ // TODO フィルタ中の発言をプルダウン選択したらどうあるべきか?\r
+}\r