機能の拡張〜ダイアログ〜

引き続き機能の拡張をしていきます。

辞書の追加

現在、辞書機能として、アルクのオンライン辞書だけを利用していますが、これを複数使えるようにしてみましょう。
ダイアログを表示するボタンをつけ、そのダイアログで使う辞書を選ぶようにします。

まず、ダイアログを実装するため、jfaceのDialogクラスを継承したクラスを作ります。

MyDialog.java

package dictionary;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;

public class MyDialog extends Dialog{
	
	public MyDialog(Shell parent) {
		super(parent);
	}
	
	protected void configureShell(Shell newShell) {
		super.configureShell(newShell);
		newShell.setText("プロパティー");
	}
	
	protected Control createDialogArea(Composite parent) {
		return parent;
	}
}
上のクラスを使って、ダイアログを表示するだけのボタンをつけてみましょう。

DicView.java


import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.IDialogConstants;import org.eclipse.swt.widgets.Shell;
・
public class DicView extends ViewPart {
    ・
    ・
	private void makeAction(){
        ・
        ・
		bars.getToolBarManager().add(new Separator());
		
		IAction dialogAction = new Action(){
			public void run(){
				Shell shell = new Shell();
				MyDialog dialog = new MyDialog(shell);
				if(dialog.open() == IDialogConstants.OK_ID){
					//ダイアログをOKを押して閉じたときの処理
				}
			}
		};	
		dialogAction.setToolTipText("プロパティー");
		bars.getToolBarManager().add(dialogAction);
	}
}

これで起動すると、上の図のようにボタンが追加され、押すと[OK][Cancel]というボタンだけのダイアログが表示されます。アイコンを追加していないので赤いボタンです。

次は、辞書を追加するということなので、新しい辞書のクラスを作ります。英和和英辞書はあるので、国語辞書を追加しましょう。今度は、gooの国語辞書を使って実装します。

(現在は、サイトの仕様変更に伴い以下の実装では国語辞書は使用できません。参考程度にご利用ください。)

JapaneseDic.java

package dictionary;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.net.UnknownHostException;
import java.nio.charset.Charset;

public class JapaneseDic {

	public String getHtml(String words) {
		return urlToHtml("http://dictionary.goo.ne.jp/search.php?MT=" 
				+ words
				+ "&search_history=&kind=jn&kwassist=0&mode=0");
		
	}
	public String urlToHtml(String urlstring){
		try {
			URL url = new URL(urlstring);
			URLConnection urlcon = url.openConnection();
			urlcon.setDoOutput(true);

			BufferedReader buffer;
			try {
				buffer = new BufferedReader(new InputStreamReader(urlcon.getInputStream(), Charset.forName("euc-jp")));
			} catch (UnknownHostException e) {
				return "ネットに接続できませんでした。";
			} catch (IOException e) {
				return null;
			}

			String message = new String(),line;
			while ((line = buffer.readLine()) != null) {
				message += line + "\n";
			}
			buffer.close();
			return setHtml(message);
			
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	private String setHtml(String message) {
		int begin = message.indexOf("<div style=\"line-height:1.4em;margin:14px;\">");
		int end = message.indexOf("<font size=\"-2\" font color=\"#666666\">");
		if (begin < 0)
			return "単語を発見できませんでした。";
		int titleBegin = message.indexOf("<title lang=\"ja\">");
		int titleEnd = message.indexOf("- goo 辞書</title>");
		return "<html><font size=-1>" + message.substring(titleBegin+17, titleEnd)+ "<br>"
				+ message.substring(begin + 44, end) + "</html>";
	}
}

これは、EnglishDic.javaとほとんど同じ実装方法です。アドレスや、htmlの抜き出す操作などが違うだけです。
また、getHtmlとurlToHtmlを分けて書いているのは、この後の処理に関係しています。

このクラスをEnglishDicクラスと同様に扱うため、EnglishDicクラスとJapaneseDicクラスにインターフェースを実装して扱うようにします。

Dictionary.java

package dictionary;

public interface Dictionary {
	String getHtml(String words);
}

上のインターフェースを使って以下のように修正します。

EnglishDic.java

public class EnglishDic implements Dictionary {
・
・
}

JapaneseDic.java

public class JapaneseDic implements Dictionary {
・
・
}

DicView.java

public class DicView extends ViewPart {
	private Dictionary dictionary;
    ・
    ・
}

DicView.javaの修正は、フィールド(EnglishDic english)を上のように変更しています。その名前の変更に伴うクラス内の修正は省略します。

これで、国語辞書を使う準備が整いましたので、両方を使えるようにしていきましょう。
以下のように追加します。

MyDialog.java


import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Group;
・
・
public class MyDialog extends Dialog{
	public int dicNum = -1;

    ・
    ・
    ・

	protected Control createDialogArea(Composite parent) {
		Composite composite = (Composite) super.createDialogArea(parent);
		
		Group group = new Group(composite, SWT.NONE);
		group.setText("辞書選択");
		group.setLayout(new GridLayout(1,false));
		
		Button button1 = new Button(group, SWT.RADIO);
		button1.setText("英和和英辞書(アルク)");
		button1.addSelectionListener(new SelectionListener() {
                  public void widgetSelected(SelectionEvent e) {
            	        dicNum = 0;
                  }

			public void widgetDefaultSelected(SelectionEvent e) {
				dicNum = 0;
			}
            });
		
		Button button2 = new Button(group, SWT.RADIO);
		button2.setText("国語辞典(goo)");
		button2.addSelectionListener(new SelectionListener() {
                  public void widgetSelected(SelectionEvent e) {
            	        dicNum = 1;
                  }

			public void widgetDefaultSelected(SelectionEvent e) {
				dicNum = 1;
			}
            });
		return composite;
	}
}

上のようにして、ラジオボタンを追加します。フィールドのdicNumでどちらの辞書を使うかを調べます。

そして、このクラスを使って、DicView.javaを編集します。

DicView.java

public class DicView extends ViewPart {
    ・
    ・
    ・
	private void makeAction(){
        ・
        ・
		IAction dialogAction = new Action(){
			public void run(){
				Shell shell = new Shell();
				MyDialog dialog = new MyDialog(shell);
				if(dialog.open() == IDialogConstants.OK_ID){//ダイアログのOKを押したときの処理
					if(dialog.dicNum == 0)
						dictionary = new EnglishDic();
					if(dialog.dicNum == 1)
						dictionary = new JapaneseDic();
				}
			}
		};	
	}
}

これで起動すると、ダイアログにラジオボタンが二つ表示されるようになり、国語辞書のほうを選ぶことで国語辞書の検索ができるようになりました。

今のままだと、ボタンが赤い画像のままなので、上の画像に変更します。
アクションボタンのときと同じように、dictionaryパッケージのiconsフォルダに上の画像を入れておきましょう。

DicView.java

public class DicView extends ViewPart {
    ・
    ・
	private void makeAction(){
        ・
        ・
		try {
			dialogAction.setImageDescriptor(getImageDescriptor("icons/prop_ps.gif"));
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}
	}
}
	

上の処理を追加すると、上の図のようにアイコンが表示されるようになります。

これで、辞書の切り替え機能が完成しました。

リンク・画像の処理

今回追加した辞書では、リンクがついていたり、画像が張ってあったりすることがあります。
今のままだとリンクに飛ぶこともできないし、画像を表示することもできませんので、そこの部分を修正していきます。

まず、画像を表示するために、以下の部分を追加します。

JapaneseDiv.java

public class JapaneseDic implements Dictionary{
    ・
    ・
	private String setHtml(String message) {
		・
        ・
        ・
		return "<html><font size=-1>" + message.substring(titleBegin+17, titleEnd)+ "<br>"
				+ getImage(message.substring(begin + 44, end)) + "</html>";
	}
	
	private String getImage(String html){
		StringBuffer sbuf = new StringBuffer(html);
		int begin = 0;
		while((begin = sbuf.indexOf("<img src=\"/")) > 0){
			sbuf.insert(begin + 10, "http://dictionary.goo.ne.jp/");
		}
		return sbuf.toString();
	}
}

上のようにして、html中の画像のURLを修正することで、画像が表示されるようになります。

次にリンクの処理をします。以下のようにします。

Dictionary.java

package dictionary;

public interface Dictionary {
	String getHtml(String words);
	String urlToHtml(String url);
}

DicView.java

import org.eclipse.swt.browser.LocationEvent;
import org.eclipse.swt.browser.LocationListener;
・
・
public class DicView extends ViewPart {
    ・
    ・
	public void createPartControl(Composite parent) {
        ・
        ・
		browser = new Browser(parent, SWT.MULTI | SWT.BORDER);
		gridData = new GridData();
		gridData.horizontalAlignment = GridData.FILL;
		gridData.verticalAlignment = GridData.FILL;
		gridData.grabExcessHorizontalSpace = true;
		gridData.grabExcessVerticalSpace = true;
		browser.setLayoutData(gridData);
		browser.addLocationListener(new LocationListener() {
			public void changing(LocationEvent event) { //browserの切り替え時に呼ばれる
				if(event.location.indexOf("about:blank") < 0 && dictionary instanceof JapaneseDic){
					String newUrl = "http://dictionary.goo.ne.jp/" + event.location.substring(6);
					browser.setText(dictionary.urlToHtml(newUrl));
				}
			}
			
			public void changed(LocationEvent event) {} //browserが切り替え終わったら呼ばれる
		});
	
		makeAction();
		
	}
    ・
    ・
}

上のように、browserにLocationListenerをつけています。changingメソッドはbrowserの切り替えが起こるときに呼ばれますので、そのとき飛ぼうとしているリンク先のアドレスを利用して、urlToHtmlメソッドでhtmlの編集をしています。
urlToHtmlメソッドを利用するために、インターフェースも編集しました。インターフェースにメソッドを追加したので、EnglishDic.javaも編集しておきましょう。

EnglishDic.java

public class EnglishDic implements Dictionary{

	public String getHtml(String words){
		return urlToHtml("http://www2.alc.co.jp/ejr/index.php?word_in="
						+ words
						+ "&word_in2=%82%A0%82%A2%82%A4%82%A6%82%A8&word_in3=PVawEWi72JXCKoa0Je");
	}
	
	public String urlToHtml(String urlstring) {
		try {
			URL url = new URL(urlstring);
			URLConnection urlcon = url.openConnection();
			urlcon.setDoOutput(true);
                        ・
            ・
                    }
        ・
        ・
    }
    ・
    ・
}

これで、国語辞書の機能が使えるようになりました。
<前へ 次へ>