package com.ethon.plugin;

import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
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.image.BufferedImage;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JTextField;

import com.ethon.DataBase;
import com.ethon.mode.DataPoint;
import com.ethon.tools.CoordTransfer;
import com.ethon.tools.CounterUtil;
import com.ethon.tools.ImageGenerator;
import com.ethon.ui.DataField;
import com.ethon.ui.IntTextField;

/**
 * 对方蒙的Spatial Neighborhood Clustering算法的改进版本
 * SNC2与原始版本的SNC算法相比引入一阶偏导势值来判断聚类的边缘，从而能够有效地处理噪声。
 * 另外，SNC2引入噪声阀值，允许对存在交叉部分的两个聚类簇进行聚类的合并操作 算法分为四步，分别是： 1、初始化网格 2、搜索局部极大势值，确定聚类中心
 * 3、根据一阶偏导值搜索每个聚类中心所代表的完整聚类 4、根据用户自行设定的噪声阀值进行聚类的合并
 * 
 * @author ethonchan@gmail.com
 * 
 */
public class SNC2 {
	private Frame parent;
	// 将数据空间的每个维度划分的网格数目
	private int K;
	// 算法所处理的数据的最小值（x,y）以及划分网格的宽度
	private double dx, dy, xmin, ymin;
	// 数据场的影响因子，设定为Max(dx,dy)
	private double sigma;
	// 划分后的网格
	private Grid[][] grids;
	// 算法找到的聚类
	List<SCluster> cls;

	/**
	 * 根据用户指定的划分网格数目，将数据空间划分为一定数量的网格，并且将所有的数据分配到网格中
	 * 
	 * @param K
	 *            数据空间的每个维度划分的网格数目
	 */
	public SNC2(Frame parent, int K) {
		this.parent=parent;
		this.K = K;
	}

	public void process() {
		// 初始化网格
		initializeGrids();

		// 搜索局部极大势值，找出聚类中心
		cls = new ArrayList<SCluster>();
		for (int x = 0, clusterNumber = 1; x < K; x++) {
			for (int y = 0; y < K; y++) {
				if (isLocalMax(x, y))
					cls.add(new SCluster(x, y, clusterNumber++));
			}
		}

		// 搜索每个聚类中心所代表的完整聚类
		for (int i = 0, len = cls.size(); i < len; i++) {
			SCluster cluster = cls.get(i);
			cluster = searchCluster(cluster);
			cls.set(i, cluster);
		}
		// 根据用户自行设定的噪声阀值进行聚类的合并
		mergeCluster();


		// 准备绘图
		BufferedImage img = ImageGenerator.drawImage(null, DataBase.sLen);
		img = showCoord(img);
		Graphics g = img.getGraphics();
		CoordTransfer tsf = new CoordTransfer();

		DataPoint[] points = DataBase.getInstance().getPoints();
		g.setColor(Color.gray);
		for (DataPoint point : points) {
			int[] coord = tsf.getPanelCoord(point.getCoord_X(),
					point.getCoord_Y());
			g.fillOval(coord[0] - 1, coord[1] - 1, 2, 2);
		}

		for (int i = 0, len = cls.size(); i < len; i++) {
			SCluster c = cls.get(i);
			float t = (float) c.clusterNumber / (float) cls.size();
			Color color = CounterUtil.HLStoRGB(t, (float) 0.5, (float) 0.5);
			c.color = color;
		}

		// 输出聚类信息
		for (SCluster cluster : cls) {
			List<Coord> content = cluster.contentList;

			g.setColor(cluster.color);
			for (Coord gnumber : content) {
				int x = gnumber.getX();
				int y = gnumber.getY();

				Grid grid = grids[x][y];
				ArrayList<DataPoint> list = grid.list;

				for (DataPoint point : list) {
					int[] coord = tsf.getPanelCoord(point.getCoord_X(),
							point.getCoord_Y());
					g.fillOval(coord[0] - 1, coord[1] - 1, 2, 2);
				}
			}
		}

		for (SCluster cluster : cls) {
			g.setColor(Color.black);
			Coord c = cluster.center;
			int x = c.getX();
			int y = c.getY();
			double xloc = xmin + dx / 2 + dx * x;
			double yloc = ymin + dy / 2 + dy * y;
			int[] coord = tsf.getPanelCoord(xloc, yloc);
			g.fillOval(coord[0] - 8, coord[1] - 8, 16, 16);
			g.setFont(new Font("SansSerif", Font.BOLD, 25));
			g.drawString(Integer.toString(cluster.clusterNumber), coord[0],
					coord[1]);
		}

		g.dispose();

		DataField.updateImagePanel(img);

	}

	private BufferedImage showCoord(BufferedImage img) {
		CoordTransfer tsf = new CoordTransfer();
		Graphics g = img.getGraphics();
		g.setColor(Color.black);
		// x的最大值，y的最大值
		int[] len = tsf.getPanelCoord(xmin + dx * K, ymin + dy * K);

		// 画出横的网格线
		for (int y = 0; y <= K; y++) {
			double yloc = ymin + dy * y;
			int[] coord = tsf.getPanelCoord(xmin, yloc);

			g.drawLine(coord[0], coord[1], len[0], coord[1]);
		}

		// 画出纵的网格线
		for (int x = 0; x <= K; x++) {
			double xloc = xmin + dx * x;
			int[] coord = tsf.getPanelCoord(xloc, ymin);

			g.drawLine(coord[0], coord[1], coord[0], len[1]);
		}

		g.dispose();
		return img;
	}

	/**
	 * 搜索聚类中心所代表的聚类簇包含的网格
	 * 
	 * @param cluster
	 *            由聚类中心所标记的聚类簇
	 * @return 完整的聚类簇
	 */
	public SCluster searchCluster(SCluster cluster) {
		List<Coord> list = cluster.contentList;
		while (true) {
			List<Coord> upDown = checkUpAndDown(cluster);
			for (Coord c : upDown) {
				if (!list.contains(c))
					list.add(c);
			}
			upDown.clear();

			List<Coord> leftRight = checkLeftAndRight(cluster);
			if (leftRight.size() == 0)
				break;

			for (Coord c : leftRight) {
				if (!list.contains(c))
					list.add(c);
			}
			leftRight.clear();
		}

		return cluster;
	}

	/**
	 * 根据用户自行设定的噪声阀值进行聚类的合并，具体分为三步 1、统计被Cluster包含的所有网格，输出他们的密度信息 2、接收用户指定的噪声阀值
	 * 3、滤掉噪声网格，并且合并聚类
	 * 
	 */
	public void mergeCluster() {
		int[] staAll = getStatisticsOfClusters();
		int[] staIts = getStatisticsOfIntersection();

		String msg ="<html><pre>"
				+ "   被包含在聚类簇中的网格的统计结果：<br/>"
				+ "      min = " + staAll[0] + ", "+ "max = " + staAll[1] + "<br />"
				+ "      sum = " + staAll[2] + ", "+ "avg = " + staAll[3] + "<br />"
				+ "   所有聚类簇中的交叉网格的统计结果：<br/>"
				+ "      min = " + staIts[0] + ", "+ "max = " + staIts[1] + "<br />" 
				+ "      sum = " + staIts[2] + ", "+ "avg = " + staIts[3]
				+ "</pre></html>";

		StatisInfoDialog dialog=new StatisInfoDialog(parent,msg);
		int thread = dialog.getValue();

		// 移除密度低于thread的网格
		for (int i = 0, len = cls.size(); i < len; i++) {
			SCluster cluster = cls.get(i);
			List<Coord> clist = cluster.contentList;
			List<Coord> slist = new LinkedList<Coord>();
			for (Coord ci : clist) {
				int x = ci.getX();
				int y = ci.getY();
				int den = grids[x][y].getPnumber();

				if (den >= thread)
					slist.add(new Coord(x, y));
			}
			cluster.contentList = slist;
			cls.set(i, cluster);
		}

		// 合并还存在交叉部分的网格
		for (int i1 = 0, len = cls.size(); i1 < len; i1++) {
			SCluster cluster1 = cls.get(i1);
			for (int i2 = i1 + 1; i2 < len; i2++) {
				SCluster cluster2 = cls.get(i2);
				List<Coord> its = getIntersection(cluster1, cluster2);
				if (its.size() > 0) {
					List<Coord> list1 = cluster1.contentList;
					List<Coord> list2 = cluster2.contentList;
					for (Coord l : list1) {
						if (!list2.contains(l))
							list2.add(l);
					}
					cluster1.contentList.clear();
					cls.set(i1, cluster1);
					cls.set(i2, cluster2);
					break;
				}
			}
		}

		List<SCluster> result = new ArrayList<SCluster>();
		int clusterNumber = 1;
		for (SCluster cluster : cls) {
			if (cluster.contentList.size() == 0)
				continue;
			cluster.clusterNumber = clusterNumber;
			clusterNumber++;
			result.add(cluster);
		}
		cls = result;
	}

	/**
	 * 所有被包含的网格的密度统计
	 * 
	 * @return 统计结果{最小密度，最大密度，所有密度和，网格数量}
	 */
	private int[] getStatisticsOfClusters() {
		int minDen = Integer.MAX_VALUE;
		int maxDen = Integer.MIN_VALUE;
		int allDen = 0;
		int num = 0;

		for (SCluster cluster : cls) {
			List<Coord> clist = cluster.contentList;
			for (Coord ci : clist) {
				int x = ci.getX();
				int y = ci.getY();
				int den = grids[x][y].getPnumber();

				if (minDen > den)
					minDen = den;
				if (maxDen < den)
					maxDen = den;
				allDen += den;
				num++;
			}
		}
		if(minDen==Integer.MAX_VALUE)	minDen=0;
		if(maxDen==Integer.MIN_VALUE)	maxDen=-1;
		return new int[] { minDen, maxDen, allDen, num };
	}

	/**
	 * 交叉部分的网格的密度统计
	 * 
	 * @return 统计结果{最小密度，最大密度，所有密度和，网格数量}
	 */
	private int[] getStatisticsOfIntersection() {
		// 所有交叉网格的密度统计
		int minDen = Integer.MAX_VALUE;
		int maxDen = Integer.MIN_VALUE;
		int allDen = 0;
		int num = 0;
		List<Coord> its = getIntersection();
		for (Coord it : its) {
			int x = it.getX();
			int y = it.getY();
			int den = grids[x][y].getPnumber();

			if (minDen > den)
				minDen = den;
			if (maxDen < den)
				maxDen = den;
			allDen += den;
			num++;
		}
		if(minDen==Integer.MAX_VALUE)	minDen=0;
		if(maxDen==Integer.MIN_VALUE)	maxDen=-1;
		return new int[] { minDen, maxDen, allDen, num };
	}

	/**
	 * 求所有SCluster的交集
	 * 
	 * @return 所有SCluster的交集
	 */
	private List<Coord> getIntersection() {
		List<Coord> result = new LinkedList<Coord>();
		for (int i1 = 0, len = cls.size(); i1 < len; i1++) {
			SCluster cluster1 = cls.get(i1);
			for (int i2 = i1 + 1; i2 < len; i2++) {
				SCluster cluster2 = cls.get(i2);
				List<Coord> tp = getIntersection(cluster1, cluster2);
				for (Coord t : tp) {
					if (!result.contains(t))
						result.add(t);
				}
			}
		}
		return result;
	}

	/**
	 * 求两个SCluster的交集
	 * 
	 * @param cluster1
	 *            第一个SCluster
	 * @param cluster2
	 *            第二个SCluster
	 * @return 两个SCluster的交集
	 */
	private List<Coord> getIntersection(SCluster cluster1, SCluster cluster2) {
		List<Coord> list1 = cluster1.contentList;
		List<Coord> list2 = cluster2.contentList;
		List<Coord> result = new LinkedList<Coord>();
		for (Coord i1 : list1) {
			for (Coord i2 : list2) {
				if (i1 == i2)
					result.add(i1);
			}
		}
		return result;
	}

	/**
	 * 在上下方向搜索完整的聚类所包含的网格
	 * 
	 * @param cluster
	 *            尚未完整的聚类簇
	 * @return 当前情况下上下方向符合条件的新网格
	 */
	private List<Coord> checkUpAndDown(SCluster cluster) {
		List<Coord> list = cluster.contentList;
		List<Coord> result = new LinkedList<Coord>();

		for (Coord gnumber : list) {
			int x = gnumber.getX();
			int y = gnumber.getY();

			boolean flag = true;
			while (flag) {
				flag = checkUpGrid(x, y, list, result);
				y--;
			}

			y = gnumber.getY();
			flag = true;
			while (flag) {
				flag = checkDownGrid(x, y, list, result);
				y++;
			}
		}
		return result;
	}

	/**
	 * 在左右方向搜索完整的聚类所包含的网格
	 * 
	 * @param cluster
	 *            尚未完整的聚类簇
	 * @return 当前情况下左右方向符合条件的新网格
	 */
	List<Coord> checkLeftAndRight(SCluster cluster) {
		List<Coord> list = cluster.contentList;
		List<Coord> result = new LinkedList<Coord>();

		for (Coord gnumber : list) {
			int x = gnumber.getX();
			int y = gnumber.getY();

			boolean flag = true;
			while (flag) {
				flag = checkLeftGrid(x, y, list, result);
				x--;
			}

			x = gnumber.getX();
			flag = true;
			while (flag) {
				flag = checkRightGrid(x++, y, list, result);
				x++;
			}
		}
		return result;
	}

	/**
	 * 检查上方的grid，如果上方的grid的Y偏导值大于当前网格的Y偏导值，就返回true，否则返回false
	 * 
	 * @param x
	 *            当前网格的X坐标
	 * @param y
	 *            当前网格的Y坐标
	 * @param list
	 *            当前聚类簇所包含的网格列表
	 * @return 上方网格是否符合条件
	 */
	private boolean checkUpGrid(int x, int y, List<Coord> list,
			List<Coord> result) {
		if (y == 0)
			return false;

		if (grids[x][y].getYdp() > grids[x][y - 1].getYdp())
			return false;
		Coord coord = new Coord(x, y - 1);

		if (!list.contains(coord) && !result.contains(coord))
			result.add(coord);
		return true;
	}

	/**
	 * 检查下方的grid，如果下方的grid的Y偏导值小于当前网格的Y偏导值，就返回true，否则返回false
	 * 
	 * @param x
	 *            当前网格的X坐标
	 * @param y
	 *            当前网格的Y坐标
	 * @param list
	 *            当前聚类出所包含的网格列表
	 * @return 下方的网格是否符合条件
	 */
	private boolean checkDownGrid(int x, int y, List<Coord> list,
			List<Coord> result) {
		if (y == K - 1)
			return false;

		if (grids[x][y].getYdp() < grids[x][y + 1].getYdp())
			return false;
		Coord coord = new Coord(x, y + 1);
		if (!list.contains(coord) && !result.contains(coord))
			result.add(coord);
		return true;
	}

	/**
	 * 检查左方的grid，如果左方的grid的X偏导值大于当前网格的X偏导值，就返回true，否则返回false
	 * 
	 * @param x
	 *            当前网格的X坐标
	 * @param y
	 *            当前网格的Y坐标
	 * @param list
	 *            当前聚类所包含的网格列表
	 * @return 左方的网格是否符合条件
	 */
	private boolean checkLeftGrid(int x, int y, List<Coord> list,
			List<Coord> result) {
		if (x == 0)
			return false;

		if (grids[x][y].getXdp() > grids[x - 1][y].getXdp())
			return false;

		Coord coord = new Coord(x - 1, y);
		if (!list.contains(coord) && !result.contains(coord))
			result.add(coord);
		return true;
	}

	/**
	 * 检查右方的grid，如果右方的grid的X偏导值小于当前网格的X偏导值，就返回true，否则返回false
	 * 
	 * @param x
	 *            当前网格的X坐标
	 * @param y
	 *            当前网格的Y坐标
	 * @param list
	 *            当前聚类所包含的网格列表
	 * @return 右方的网格是否符合条件
	 */
	private boolean checkRightGrid(int x, int y, List<Coord> list,
			List<Coord> result) {
		if (x == K - 1)
			return false;

		if (grids[x][y].getXdp() < grids[x + 1][y].getXdp())
			return false;

		Coord coord = new Coord(x + 1, y);
		if (!list.contains(coord) && !result.contains(coord))
			result.add(coord);

		return true;
	}

	/**
	 * 检验坐标为（gridX，gridY）的网格是否具有局部极大值
	 * 
	 * @param gridX
	 *            中心网格的x坐标
	 * @param gridY
	 *            中心网格的y坐标
	 * @return 具有局部极大值则返回true，反之返回false
	 */
	private boolean isLocalMax(int gridX, int gridY) {
		Grid[] ngb = getNeighborGrids(gridX, gridY);
		double pot = grids[gridX][gridY].getPotential();

		for (Grid g : ngb) {
			if (g.getPotential() > pot)
				return false;
		}

		return true;
	}

	/**
	 * 计算每个网格的一阶偏导势值
	 */
	public void initializeGrids() {
		grids = new Grid[K][K];

		DataPoint[] points = DataBase.getInstance().getPoints();
		// 遍历找出数据的最大最小取值，并据此确定每个网格的变长dx dy
		xmin = Double.MAX_VALUE;
		ymin = Double.MAX_VALUE;
		double xmax = Double.MIN_VALUE;
		double ymax = Double.MIN_VALUE;

		for (DataPoint p : points) {
			double x = p.getCoord_X();
			double y = p.getCoord_Y();

			if (xmin > x)
				xmin = x;
			if (ymin > y)
				ymin = y;

			if (xmax < x)
				xmax = x;
			if (ymax < y)
				ymax = y;
		}
		dx = (xmax - xmin) / K;
		dy = (ymax - ymin) / K;

		// 设定数据场的影响因子
		sigma = Math.max(dx, dy);

		// 将每个数据点分配到相应的网格中，注意这里有可能有一部分网格为空
		for (DataPoint p : points) {
			double x = p.getCoord_X();
			double y = p.getCoord_Y();

			int xl = (int) Math.floor((x - xmin) / dx);
			int yl = (int) Math.floor((y - ymin) / dy);
			if (xl == K)
				xl = K - 1;
			if (yl == K)
				yl = K - 1;
			if (grids[xl][yl] == null)
				grids[xl][yl] = new Grid();

			grids[xl][yl].addDataPoint(p);
		}

		// 确认网格没有空的
		for (int x = 0; x < K; x++) {
			for (int y = 0; y < K; y++) {
				Grid grid = grids[x][y];
				if (grid == null) {
					double xloc = xmin + dx / 2 + dx * x;
					double yloc = ymin + dy / 2 + dy * y;

					grid = new Grid();
					grid.setCenter(xloc, yloc);
					grids[x][y] = grid;
				}
			}
		}

		// 计算每个网格的势值及一阶偏导势值
		double sigma2 = sigma * sigma;
		for (int x = 0; x < K; x++) {
			for (int y = 0; y < K; y++) {
				double xloc = grids[x][y].getXCenter();
				double yloc = grids[x][y].getYCenter();
				double pot = 0;
				double xdp = 0;
				double ydp = 0;
				for (int xi = 0; xi < K; xi++) {
					for (int yi = 0; yi < K; yi++) {
						Grid gi = grids[xi][yi];
						if (gi.getPnumber() == 0)
							continue;

						double xdist = gi.getXCenter() - xloc;
						double ydist = gi.getYCenter() - yloc;
						double tpot = (xdist * xdist + ydist * ydist) / sigma2;
						tpot = gi.getPnumber() * Math.pow(Math.E, -tpot);
						pot += tpot;
						xdp += xdist * tpot;
						ydp += ydist * tpot;
					}
				}
				grids[x][y].setPotential(pot);
				grids[x][y].setXdp(xdp);
				grids[x][y].setYdp(ydp);
			}
		}
	}

	/**
	 * 获取坐标为（gridX，gridY）的网格的邻居网格，这里采用四邻域
	 * 
	 * @param gridX
	 *            中心网格x坐标
	 * @param gridY
	 *            中心网格y坐标
	 * @return 中心网格的四邻域网格
	 */
	private Grid[] getNeighborGrids(int gridX, int gridY) {
		LinkedList<Grid> result = new LinkedList<Grid>();

		if (gridX > 0)
			result.add(grids[gridX - 1][gridY]);
		if (gridY > 0)
			result.add(grids[gridX][gridY - 1]);
		if (gridX < K - 1)
			result.add(grids[gridX + 1][gridY]);
		if (gridY < K - 1)
			result.add(grids[gridX][gridY + 1]);

		Grid[] array = new Grid[result.size()];
		array = result.toArray(array);
		return array;
	}

	private class Coord {
		private int x;
		private int y;

		public Coord(int x, int y) {
			this.x = x;
			this.y = y;
		}

		public int getX() {
			return x;
		}

		public int getY() {
			return y;
		}

		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + getOuterType().hashCode();
			result = prime * result + x;
			result = prime * result + y;
			return result;
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			Coord other = (Coord) obj;
			if (!getOuterType().equals(other.getOuterType()))
				return false;
			if (x != other.x)
				return false;
			if (y != other.y)
				return false;
			return true;
		}

		private SNC2 getOuterType() {
			return SNC2.this;
		}

		@Override
		public String toString() {
			return "[x=" + x + ", y=" + y + "]";
		}

	}

	private class Grid {
		private double xall = 0;
		private double yall = 0;
		private double potential = -1;
		private double xdp = -1;
		private double ydp = -1;
		private int pnumber = 0;
		private ArrayList<DataPoint> list = new ArrayList<DataPoint>();

		public void addDataPoint(DataPoint point) {
			pnumber++;
			xall += point.getCoord_X();
			yall += point.getCoord_Y();
			list.add(point);
		}

		public void setCenter(double xloc, double yloc) {
			this.xall = xloc;
			this.yall = yloc;
		}

		public double getPotential() {
			return potential;
		}

		public void setPotential(double potential) {
			this.potential = potential;
		}

		public double getXdp() {
			return xdp;
		}

		public void setXdp(double xdp) {
			this.xdp = xdp;
		}

		public double getYdp() {
			return ydp;
		}

		public int getPnumber() {
			return pnumber;
		}

		public void setYdp(double ydp) {
			this.ydp = ydp;
		}

		public double getXCenter() {
			if (pnumber == 0)
				return xall;
			else
				return xall / pnumber;
		}

		public double getYCenter() {
			if (pnumber == 0)
				return yall;
			else
				return yall / pnumber;
		}
	}

	class SCluster {
		Coord center;
		Color color;
		int clusterNumber = 0;
		List<Coord> contentList = new LinkedList<Coord>();

		SCluster(int x, int y, int clusterNumber) {
			center = new Coord(x, y);
			color = Color.green;
			this.clusterNumber = clusterNumber;

			contentList.add(center);
			if (x > 0)
				contentList.add(new Coord(x - 1, y));
			if (x < K - 1)
				contentList.add(new Coord(x + 1, y));
			if (y > 0)
				contentList.add(new Coord(x, y - 1));
			if (y < K - 1)
				contentList.add(new Coord(x, y + 1));

		}

		void addGrid(int x, int y) {
			contentList.add(new Coord(x, y));
		}

		boolean containGrid(int x, int y) {
			Coord gridNumber = new Coord(x, y);
			return contentList.contains(gridNumber);
		}
	}
	
	private class StatisInfoDialog extends JDialog {
		private static final long serialVersionUID = 1L;

		private JTextField field;
				
		private int value=0;
		
		/**
		 * 新建一个对话框
		 * @param parent	对话框的拥有者
		 * @param currentValue	当前设定的抽样比例
		 */
		public StatisInfoDialog(Frame parent, String msg){
			super(parent,true);
			
			GridBagLayout grid=new GridBagLayout();
			GridBagConstraints cons=new GridBagConstraints();
			setLayout(grid);
			
			setTitle("请输入噪声参数");
			
			JLabel pane=new JLabel(msg);
			pane.setSize(200, 250);
			cons.gridwidth=2;
			cons.gridheight=2;
			grid.setConstraints(pane, cons);
			add(pane);
					
			JLabel label2=new JLabel("噪声阀值 = ", JLabel.CENTER);
			label2.setToolTipText("在右侧输入框中输入噪声阀值");
			cons.gridx=0;
			cons.gridwidth=GridBagConstraints.RELATIVE;
			cons.gridheight=1;
			cons.insets=new Insets(0,5,0,5);
			grid.setConstraints(label2, cons);
			add(label2);
			
			cons.gridx=1;
			cons.gridwidth=GridBagConstraints.REMAINDER;
			cons.fill=GridBagConstraints.BOTH;
			field=new IntTextField(1);
			field.setToolTipText("输入噪声阀值（整形参数）");
			field.setText("0");
			grid.setConstraints(field, cons);
			add(field);
			
			JButton confirm=new JButton("确定");
			confirm.setToolTipText("保存设置");
			confirm.addActionListener(new ConfirmListener());
			cons.fill=GridBagConstraints.NONE;
			cons.gridx=0;
			cons.gridwidth=GridBagConstraints.RELATIVE;
			grid.setConstraints(confirm, cons);
			add(confirm);
			
			JButton cancel=new JButton("取消");
			cancel.setToolTipText("取消设置");
			cancel.addActionListener(new CancelListener());
			cons.gridx=1;
			grid.setConstraints(cancel, cons);
			add(cancel);
			
			setDefaultCloseOperation(DISPOSE_ON_CLOSE);
			if(parent!=null){
				setLocationRelativeTo(parent);
				setLocation(parent.getWidth()/2, parent.getHeight()/2);
			}
			setSize(260, 230);
			setVisible(true);
		}

		public int getValue() {
			return value;
		}
		
		/**
		 * 点击确定按钮的事件监听器
		 * @author <a href="mailto:ethonchan@gmail.com">ethonchan</a>
		 *
		 */
		class ConfirmListener implements ActionListener{
			public void actionPerformed(ActionEvent e) {
				String str = field.getText();
				value=Integer.parseInt(str);
				StatisInfoDialog.this.setVisible(false);
			}
		}
		
		/**
		 * 点击取消按钮的事件监听器
		 * @author <a href="mailto:ethonchan@gmail.com">ethonchan</a>
		 *
		 */
		class CancelListener implements ActionListener{
			public void actionPerformed(ActionEvent e) {
				StatisInfoDialog.this.setVisible(false);
			}
		}
	}
}
