onDrag(comp, new P1<Point>() {public void e(Point initPoint) {
			startP[0] = currentLocationF.e();
		}}, new P2<Point, Point>() {public void e(Point p, Point initPoint) {
			newLocationF.e(new Point(
					startP[0].x + p.x - initPoint.x,
					startP[0].y + p.y - initPoint.y
					));
		}});
	}
	public static Rectangle bound(Point... points) {
		int smallestX = Integer.MAX_VALUE;
		int smallestY = Integer.MAX_VALUE;
		int largestX = Integer.MIN_VALUE;
		int largestY = Integer.MIN_VALUE;
		for (Point point : points) {
			if (point==null) {
				continue;
			}
			if (point.x > largestX) largestX = point.x;
			if (point.y > largestY) largestY = point.y;
			if (point.x < smallestX) smallestX = point.x;
			if (point.y < smallestY) smallestY = point.y;
		}
		return new Rectangle(smallestX, smallestY, largestX - smallestX, largestY - smallestY);
	}
	public static StartStopPanel startStopPanel(final F0<P0> startF) {
		StartStopPanel panel = new StartStopPanel();
		panel.setLayout(new FlowLayout());
	
		final JButton startBtn = new JButton("Start");
		if (startF==null) {
			startBtn.setEnabled(false);
		}
		final JButton stopBtn = new JButton("Stop");
		stopBtn.setEnabled(false);
	
		final P0[] stopF = {null};
		panel.stopF = stopF;
		P0 startF1 = new P0() {public void e() {
			startBtn.setEnabled(false);
			stopBtn.setEnabled(true);
			
			final P0 stopF1 = startF.e();
	
			stopF[0] = new P0() {public void e() {
				startBtn.setEnabled(true);
				stopBtn.setEnabled(false);
				
				stopF1.e();
			}};
		}};
		startBtn.addActionListener(SwingUtil.toActionListener(startF1));
		stopBtn.addActionListener(SwingUtil.toActionListener(Fs.invokeRef(stopF)));
			
		panel.add(startBtn);
		panel.add(stopBtn);
		return panel;
	}
	public static class StartStopPanel extends JPanel {
		public P0[] stopF;

		public void stop() {
			if (stopF[0] != null) {
				stopF[0].e();
			}
		}
		public void link(Window window) {
			if (window!=null) {
				onClose(window, Fs.invokeRef(stopF));
			}
		}
	}

	public static P0 selectAllF(final JTextField tb) {
		return new P0() {public void e() {
			tb.selectAll();
		}};
	}
	public static Component dialogControls(Component... comps) {
		return panel_vertical(new JSeparator(), panel(comps));
	}
	public static void onAction(final AbstractButton btn, final P0 action) {
		btn.addActionListener(toActionListener(ThreadUtil.async(new P0() {public void e() {
			btn.setEnabled(false);
			action.e();
			btn.setEnabled(true);
		}})));
	}
	
	public static void main(String[] args) {
		JTextField tf = new JTextField();
		onlyLowerAlphaNumeric(tf);
		DesktopUI4.alert(tf);
	}
	public static void onlyLowerAlphaNumeric(final JTextField tf) {
		onChange(tf, new P1<String>() {public void e(final String str) {
			asyncRun(new P0() {public void e() {
				String newVal = str.replaceAll("\\W+", "").toLowerCase();
//				System.out.println(newVal);
				tf.setText(newVal);
			}});
		}});
	}
	public static ActionListener toActionListener(final P0 f) {
	    return new ActionListener() {
	        public void actionPerformed(ActionEvent e) {
	            f.e();
	        }
	    };
	}
	public static Rectangle expand(Rectangle rect, int amount) {
		return new Rectangle(
				rect.x - amount,
				rect.y - amount,
				rect.width + amount*2,
				rect.height + amount*2
				);
	}
	public static void draw(BufferedImage image, Rectangle rectangle,
			BufferedImage backgroundImg) {
		Graphics2D g = backgroundImg.createGraphics();
		if (rectangle == null) {
			g.drawImage(image, 0, 0, null);
		} else {
			g.drawImage(image, rectangle.x, rectangle.y, null);
		}
		g.dispose();
	}
	public static P0 setVisibleF(final Window w, final boolean visible) {
		return new P0() {public void e() {
			w.setVisible(visible);
		}};
	}
	public static void onMouseHover(Component comp, final P1<Boolean> p1) {
		comp.addMouseListener(new MouseAdapter() {
			
			@Override
			public void mouseExited(MouseEvent arg0) {
				p1.e(false);
			}
			
			@Override
			public void mouseEntered(MouseEvent arg0) {
				p1.e(true);
			}
		});

	}
	public static Color alpha(int alpha, Color color) {
		return new Color(color.getRed(), color.getGreen(), color.getBlue(), alpha);
	}
	public static GetSet<Integer> getSetIndex(final JComboBox combobox) {
		return new GetSet<Integer>(
				new F0<Integer>() {public Integer e() {
					return combobox.getSelectedIndex();
				}},
				new P1<Integer>() {public void e(Integer obj) {
					combobox.setSelectedIndex(obj);
				}}