<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
- <version>4.10</version>
+ <version>4.11</version>
<scope>test</scope>
</dependency>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
- <version>2.5.1</version>
+ <version>3.0</version>
<configuration>
<source>1.6</source> <!-- for NetBeans IDE -->
<target>1.6</target>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
- <version>2.3</version>
+ <version>2.4</version>
<configuration>
<archiveBaseDirectory>.</archiveBaseDirectory>
<descriptors>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
- <version>2.1.2</version>
- <!-- 2.2はplexus-archiverへの依存性で問題あり -->
+ <version>2.2.1</version>
<configuration>
<includePom>true</includePom>
<archive>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
- <version>3.1</version>
+ <version>3.2</version>
<configuration>
<generateReports>true</generateReports>
<locales>ja</locales>
<configuration>
<effort>Max</effort>
<threshold>Low</threshold>
+ <!-- for Jenkins -->
+ <findbugsXmlOutput>true</findbugsXmlOutput>
+ <findbugsXmlWithMessages>true</findbugsXmlWithMessages>
+ <xmlOutput>true</xmlOutput>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>cobertura-maven-plugin</artifactId>
+ <version>2.5.2</version>
+ <configuration>
+ <encoding>${project.build.sourceEncoding}</encoding>
+ <formats>
+ <format>html</format>
+ <format>xml</format> <!-- for Jenkins -->
+ </formats>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
- <version>2.5.1</version>
+ <version>2.6</version>
<configuration>
<linkOnly>true</linkOnly>
<offline>true</offline>
<version>2.5.2</version>
<configuration>
<encoding>${project.build.sourceEncoding}</encoding>
+ <formats>
+ <format>html</format>
+ <format>xml</format> <!-- for Jenkins -->
+ </formats>
</configuration>
</plugin>
<skip>false</skip>
<effort>Max</effort>
<threshold>Low</threshold>
+ <!-- for Jenkins -->
+ <findbugsXmlOutput>true</findbugsXmlOutput>
+ <findbugsXmlWithMessages>true</findbugsXmlWithMessages>
+ <xmlOutput>true</xmlOutput>
<!-- excludeFilterFile/ -->
</configuration>
</plugin>
package jp.sfjp.jindolf.log;
import java.awt.Container;
-import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
-import java.awt.event.WindowEvent;
-import java.awt.event.WindowListener;
import java.util.logging.Handler;
-import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JDialog;
-import javax.swing.JPopupMenu;
-import javax.swing.JScrollBar;
-import javax.swing.JScrollPane;
import javax.swing.JSeparator;
-import javax.swing.JTextArea;
-import javax.swing.border.Border;
-import javax.swing.event.DocumentEvent;
-import javax.swing.event.DocumentListener;
-import javax.swing.text.BadLocationException;
-import javax.swing.text.Document;
-import javax.swing.text.PlainDocument;
-import jp.sfjp.jindolf.dxchg.TextPopup;
-import jp.sfjp.jindolf.util.GUIUtils;
-import jp.sfjp.jindolf.util.Monodizer;
/**
- * ã\83ã\82°è¡¨ç¤ºã\83\91ã\83\8dã\83«。
+ * ã\83ã\82°è¡¨ç¤ºã\82¦ã\82£ã\83³ã\83\89ã\82¦。
*/
@SuppressWarnings("serial")
-public class LogFrame extends JDialog
- implements WindowListener, ActionListener, DocumentListener{
+public class LogFrame extends JDialog {
- private static final Document DOC_EMPTY = new PlainDocument();
+ private static final String CMD_CLOSELOG = "CMD_CLOSE_LOG";
+ private static final String CMD_CLEARLOG = "CMD_CLEAR_LOG";
- private final JTextArea textarea;
- private final Document document = new PlainDocument();
- private final JScrollPane scrollPane;
- private final JScrollBar vertical;
- private final Handler handler;
-
+ private final LogPanel logPanel = new LogPanel();
private final JButton clearButton = new JButton("クリア");
private final JButton closeButton = new JButton("閉じる");
+
/**
- * ã\83ã\82°è¡¨ç¤ºã\83\91ã\83\8dã\83«ã\81®ç\94\9fæ\88\90。
+ * ã\82³ã\83³ã\82¹ã\83\88ã\83©ã\82¯ã\82¿。
* @param owner フレームオーナー
*/
public LogFrame(Frame owner){
super(owner);
- setModal(false);
-
- if(LogUtils.hasLoggingPermission()){
- this.handler = new SwingDocHandler(this.document);
- }else{
- this.handler = null;
- }
-
- GUIUtils.modifyWindowAttributes(this, true, false, true);
-
- this.textarea = new JTextArea();
- this.textarea.setEditable(false);
- this.textarea.setLineWrap(true);
- this.textarea.setDocument(DOC_EMPTY);
- Border border = BorderFactory.createEmptyBorder(3, 3, 3, 3);
- this.textarea.setBorder(border);
- Monodizer.monodize(this.textarea);
- JPopupMenu popup = new TextPopup();
- this.textarea.setComponentPopupMenu(popup);
-
- this.scrollPane = new JScrollPane(this.textarea);
- this.vertical = this.scrollPane.getVerticalScrollBar();
design();
- this.clearButton.addActionListener(this);
- this.closeButton.addActionListener(this);
+ this.clearButton.setActionCommand(CMD_CLEARLOG);
+ this.closeButton.setActionCommand(CMD_CLOSELOG);
- this.document.addDocumentListener(this);
+ ActionListener actionListener = new ActionWatcher();
+ this.clearButton.addActionListener(actionListener);
+ this.closeButton.addActionListener(actionListener);
- setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
- addWindowListener(this);
+ setResizable(true);
+ setLocationByPlatform(true);
+ setModal(false);
return;
}
constraints.fill = GridBagConstraints.BOTH;
constraints.gridwidth = GridBagConstraints.REMAINDER;
- content.add(this.scrollPane, constraints);
+ content.add(this.logPanel, constraints);
constraints.weighty = 0.0;
constraints.fill = GridBagConstraints.HORIZONTAL;
}
/**
- * ロギングハンドラを取得する。
+ * ロギングハンドラを返す。
* @return ロギングハンドラ
*/
public Handler getHandler(){
- return this.handler;
+ return this.logPanel.getHandler();
}
/**
- * 垂直スクロールバーを末端に設定する。
+ * ログ内容をクリアする。
*/
- private void showLastPos(){
- if( ! isVisible() ) return;
- if(this.textarea.getDocument() != this.document) return;
-
- EventQueue.invokeLater(new Runnable(){
- public void run(){
- LogFrame.this.vertical.setValue(Integer.MAX_VALUE);
- return;
- }
- });
-
+ public void clearLog(){
+ this.logPanel.clearLog();
return;
}
- /**
- * ウィンドウクローズ処理。
- */
- private void close(){
- setVisible(false);
- return;
- }
/**
- * ã\83ã\82°ã\82¯ã\83ªã\82¢å\87¦ç\90\86。
+ * ã\83\9cã\82¿ã\83³æ\93\8dä½\9cã\82\92ç\9b£è¦\96ã\81\99ã\82\8b。
*/
- private void clear(){
- try{
- this.document.remove(0, this.document.getLength());
- }catch(BadLocationException e){
- assert false;
- }
- return;
- }
+ private final class ActionWatcher implements ActionListener{
- /**
- * {@inheritDoc}
- * ウィンドウの表示・非表示を設定する。
- * @param visible trueなら表示 {@inheritDoc}
- */
- @Override
- public void setVisible(boolean visible){
- super.setVisible(visible);
-
- if(visible){
- this.textarea.setDocument(this.document);
- showLastPos();
- }else{
- this.textarea.setDocument(DOC_EMPTY);
+ /**
+ * コンストラクタ。
+ */
+ ActionWatcher(){
+ super();
+ return;
}
- 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){
- this.textarea.setDocument(DOC_EMPTY);
- return;
- }
-
- /**
- * {@inheritDoc}
- * @param event {@inheritDoc}
- */
- @Override
- public void windowDeiconified(WindowEvent event){
- this.textarea.setDocument(this.document);
- showLastPos();
- return;
- }
-
- /**
- * {@inheritDoc}
- * @param event {@inheritDoc}
- */
- @Override
- public void windowOpened(WindowEvent event){
- this.textarea.setDocument(this.document);
- showLastPos();
- return;
- }
+ /**
+ * {@inheritDoc}
+ * ボタン押下イベント処理。
+ * @param event {@inheritDoc}
+ */
+ @Override
+ public void actionPerformed(ActionEvent event){
+ String cmd = event.getActionCommand();
- /**
- * {@inheritDoc}
- * @param event {@inheritDoc}
- */
- @Override
- public void windowClosed(WindowEvent event){
- return;
- }
-
- /**
- * {@inheritDoc}
- * @param event {@inheritDoc}
- */
- @Override
- public void windowClosing(WindowEvent event){
- close();
- return;
- }
+ if (CMD_CLEARLOG.equals(cmd)) clearLog();
+ else if(CMD_CLOSELOG.equals(cmd)) setVisible(false);
- /**
- * {@inheritDoc}
- * @param event {@inheritDoc}
- */
- @Override
- public void actionPerformed(ActionEvent event){
- Object source = event.getSource();
- if(source == this.clearButton){
- clear();
- }else if(source == this.closeButton){
- close();
+ return;
}
- return;
- }
-
- /**
- * {@inheritDoc}
- * @param event {@inheritDoc}
- */
- @Override
- public void changedUpdate(DocumentEvent event){
- showLastPos();
- return;
- }
-
- /**
- * {@inheritDoc}
- * @param event {@inheritDoc}
- */
- @Override
- public void insertUpdate(DocumentEvent event){
- showLastPos();
- return;
- }
-
- /**
- * {@inheritDoc}
- * @param event {@inheritDoc}
- */
- @Override
- public void removeUpdate(DocumentEvent event){
- showLastPos();
- return;
}
}
--- /dev/null
+/*
+ * Log panel
+ *
+ * License : The MIT License
+ * Copyright(c) 2012 olyutorskii
+ */
+
+package jp.sfjp.jindolf.log;
+
+import java.awt.Adjustable;
+import java.awt.EventQueue;
+import java.util.logging.Handler;
+import javax.swing.BorderFactory;
+import javax.swing.JPopupMenu;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.border.Border;
+import javax.swing.event.AncestorEvent;
+import javax.swing.event.AncestorListener;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Document;
+import javax.swing.text.PlainDocument;
+import jp.sfjp.jindolf.dxchg.TextPopup;
+import jp.sfjp.jindolf.util.Monodizer;
+
+/**
+ * スクロールバー付きログ表示パネル。
+ * 垂直スクロールバーは自動的に最下部へトラックする。
+ */
+@SuppressWarnings("serial")
+public class LogPanel extends JScrollPane {
+
+ private static final Document DOC_EMPTY = new PlainDocument();
+
+
+ private final Document document = new PlainDocument();
+ private final Handler handler;
+
+ private final JTextArea textarea = new JTextArea();
+
+
+ /**
+ * コンストラクタ。
+ */
+ public LogPanel(){
+ super();
+
+ if(LogUtils.hasLoggingPermission()){
+ this.handler = new SwingDocHandler(this.document);
+ }else{
+ this.handler = null;
+ }
+
+ this.textarea.setDocument(DOC_EMPTY);
+ this.textarea.setEditable(false);
+ this.textarea.setLineWrap(true);
+ Monodizer.monodize(this.textarea);
+
+ Border border = BorderFactory.createEmptyBorder(3, 3, 3, 3);
+ this.textarea.setBorder(border);
+
+ JPopupMenu popup = new TextPopup();
+ this.textarea.setComponentPopupMenu(popup);
+
+ setViewportView(this.textarea);
+
+ DocumentListener docListener = new DocWatcher();
+ this.document.addDocumentListener(docListener);
+
+ AncestorListener ancestorListener = new AncestorWatcher();
+ addAncestorListener(ancestorListener);
+
+ return;
+ }
+
+ /**
+ * ロギングハンドラを返す。
+ * @return ロギングハンドラ
+ */
+ public Handler getHandler(){
+ return this.handler;
+ }
+
+ /**
+ * 垂直スクロールバーをドキュメント下端に設定し、
+ * ログの最新部を表示する。
+ * 不可視状態なら何もしない。
+ */
+ private void showLastPos(){
+ if(this.textarea.getDocument() != this.document) return;
+
+ final Adjustable yPos = getVerticalScrollBar();
+ EventQueue.invokeLater(new Runnable(){
+ @Override
+ public void run(){
+ yPos.setValue(Integer.MAX_VALUE);
+ return;
+ }
+ });
+
+ return;
+ }
+
+ /**
+ * モデルとビューを連携させる。
+ * スクロール位置は末端に。
+ */
+ private void attachModel(){
+ if(this.textarea.getDocument() != this.document){
+ this.textarea.setDocument(this.document);
+ }
+ showLastPos();
+ return;
+ }
+
+ /**
+ * モデルとビューを切り離す。
+ */
+ private void detachModel(){
+ if(this.textarea.getDocument() == DOC_EMPTY) return;
+ this.textarea.setDocument(DOC_EMPTY);
+ return;
+ }
+
+ /**
+ * ログ内容をクリアする。
+ */
+ public void clearLog(){
+ try{
+ int docLength = this.document.getLength();
+ this.document.remove(0, docLength);
+ }catch(BadLocationException e){
+ assert false;
+ }
+ return;
+ }
+
+
+ /**
+ * 画面更新が必要な状態か監視し、必要に応じてモデルとビューを切り離す。
+ */
+ private final class AncestorWatcher implements AncestorListener{
+
+ /**
+ * コンストラクタ。
+ */
+ AncestorWatcher(){
+ super();
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param event {@inheritDoc}
+ */
+ @Override
+ public void ancestorAdded(AncestorEvent event){
+ attachModel();
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param event {@inheritDoc}
+ */
+ @Override
+ public void ancestorRemoved(AncestorEvent event){
+ detachModel();
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param event {@inheritDoc}
+ */
+ @Override
+ public void ancestorMoved(AncestorEvent event){
+ return;
+ }
+
+ }
+
+
+ /**
+ * ドキュメント操作を監視し、スクロールバーを更新する。
+ */
+ private final class DocWatcher implements DocumentListener{
+
+ /**
+ * コンストラクタ。
+ */
+ DocWatcher(){
+ super();
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param event {@inheritDoc}
+ */
+ @Override
+ public void changedUpdate(DocumentEvent event){
+ showLastPos();
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param event {@inheritDoc}
+ */
+ @Override
+ public void insertUpdate(DocumentEvent event){
+ showLastPos();
+ return;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param event {@inheritDoc}
+ */
+ @Override
+ public void removeUpdate(DocumentEvent event){
+ showLastPos();
+ return;
+ }
+
+ }
+
+}