001:import java.awt.event.* ; // ActionEvent MouseEvent MouseAdapter WindowEvent WindowAdapter
002:import javax.swing.* ;    // ButtonGroup JFrame JLabel JPanel JRadioButton JTextField
003:import java.awt.* ;       // BorderLayout Color Container Dimension Graphics Graphics2D
004:import java.awt.geom.RectangularShape;
005:import java.awt.geom.Ellipse2D;
006:import java.awt.geom.Rectangle2D;
007:import java.awt.geom.PathIterator;
008:import java.awt.geom.AffineTransform;
009:import java.awt.geom.Point2D;
010:import java.awt.geom.GeneralPath;
011:
012:interface ColoredShape extends Shape {
013:	public double getX();
014:	public double getY();
015:	public double getWidth();
016:	public double getHeight();
017:	public void   setFrame(double x, double y, double w, double h);
018:	public void   draw(Graphics2D gg);
019:}
020:
021:class ColoredEllipse extends Ellipse2D.Double
022:                     implements ColoredShape {
023:	Color   color;
024:	boolean spread;
025:
026:	ColoredEllipse(double x, double y, double w, double h, Color c, boolean s) {
027:		super(x, y, w, h);
028:		color = c;
029:		spread = s;
030:	}
031:
032:	public void   draw(Graphics2D gg) {
033:		gg.setColor(color);
034:		if(spread) gg.fill(this);
035:		else       gg.draw(this);
036:	}
037:}
038:
039:class ColoredRectangle extends Rectangle2D.Double
040:                       implements ColoredShape {
041:	Color   color;
042:	boolean spread;
043:
044:	ColoredRectangle(double x, double y, double w, double h, Color c, boolean s) {
045:		super(x, y, w, h);
046:		color = c;
047:		spread = s;
048:	}
049:
050:	public void   draw(Graphics2D gg) {
051:		gg.setColor(color);
052:		if(spread) gg.fill(this);
053:		else       gg.draw(this);
054:	}
055:}
056:
057:class TrianglePath implements PathIterator {
058:	int index = 0;
059:	AffineTransform affine = new AffineTransform();
060:	double[] x = new double[3];
061:	double[] y = new double[3];
062:
063:	TrianglePath(double x, double y, double w, double h, boolean ud) {
064:		if(ud) {
065:			this.x[0] = x+w*0.5;
066:			this.y[0] = y;
067:			this.x[1] = x;
068:			this.y[1] = y+h;
069:			this.x[2] = x+w;
070:			this.y[2] = y+h;
071:		} else {
072:			this.x[0] = x;
073:			this.y[0] = y;
074:			this.x[1] = x+w;
075:			this.y[1] = y;
076:			this.x[2] = x+w*0.5;
077:			this.y[2] = y+h;
078:		}
079:	}
080:
081:	public int currentSegment(double[] path) {
082:		if(index>2) return PathIterator.SEG_CLOSE;
083:		Point2D.Double p = new Point2D.Double(x[index], y[index]);
084:		affine.transform(p,p);
085:		path[0] = p.x;
086:		path[1] = p.y;
087:		if(index==0) return PathIterator.SEG_MOVETO;
088:		else         return PathIterator.SEG_LINETO;
089:	}
090:
091:	public int currentSegment(float[] path) {
092:		if(index>2) return PathIterator.SEG_CLOSE;
093:		Point2D.Double p = new Point2D.Double(x[index], y[index]);
094:		affine.transform(p,p);
095:		path[0] = (float)p.x;
096:		path[1] = (float)p.y;
097:		if(index==0) return PathIterator.SEG_MOVETO;
098:		else         return PathIterator.SEG_LINETO;
099:	}
100:
101:	public int getWindingRule() { return PathIterator.WIND_EVEN_ODD; }
102:
103:	public boolean isDone() {
104:		if(index<4) return false;
105:		else        return true;
106:	}
107:
108:	public void next() { index++; }
109:
110:	public void setAffine(AffineTransform at) { affine = at; }
111:}
112:
113:class ColoredTriangle extends RectangularShape
114:                              implements ColoredShape {
115:	Color   color;
116:	boolean spread;
117:	boolean upsidedown;
118:	GeneralPath path = new GeneralPath();
119:	TrianglePath pathIterator;
120:	double x;
121:	double y;
122:	double w;
123:	double h;
124:
125:	ColoredTriangle(double x, double y, double w, double h,
126:	                Color c, boolean ud, boolean s) {
127:		this.x = x;
128:		this.y = y;
129:		this.w = w;
130:		this.h = h;
131:		color = c;
132:		upsidedown = ud;
133:		spread = s;
134:
135:		pathIterator = new TrianglePath(x, y, w, h, ud);
136:		path.append(pathIterator, true);
137:	}
138:
139:	public double getX()      { return x; }
140:	public double getY()      { return y; }
141:	public double getWidth()  { return w; }
142:	public double getHeight() { return h; }
143:	public void   setFrame(double x, double y, double w, double h){
144:		double xd = x - this.x;
145:		double yd = y - this.y;
146:		this.x = x;
147:		this.y = y;
148:		this.w = w;
149:		this.h = h;
150:		path.transform(AffineTransform.getTranslateInstance(xd,yd));
151:		pathIterator.affine.concatenate(AffineTransform.getTranslateInstance(xd,yd));
152:	}
153:	public void   draw(Graphics2D gg) {
154:		gg.setColor(color);
155:		if(spread) gg.fill(this);
156:		else       gg.draw(this);
157:	}
158:	public boolean isEmpty()  { return false; }
159:	public PathIterator getPathIterator(AffineTransform at) {
160:		TrianglePath pi = new TrianglePath(x, y, w, h, upsidedown);
161:		pi.setAffine(at);
162:		return pi;
163:	}
164:	public Rectangle2D getBounds2D() {
165:		throw(new UnsupportedOperationException());
166:	}
167:	public boolean intersects(double x, double y, double w, double h) {
168:		if(this.x+this.w<x) return false;
169:		if(x+w<this.x) return false;
170:		if(this.y+this.h<y) return false;
171:		if(y+h<this.y) return false;
172:		return true;
173:	}
174:	public boolean contains(double x, double y, double w, double h) {
175:		throw(new UnsupportedOperationException());
176:	}
177:	public boolean contains(double x, double y) {
178:		if(x<this.x) return false;
179:		if(x>(this.x+w)) return false;
180:		if(y<this.y) return false;
181:		if(y>(this.y+h)) return false;
182:		return true;
183:	}
184:}
185:
186:public class Graph2d2z extends JPanel {
187:	static int              shapetype = 0;                  // ものの形状 0:楕円、 1:矩形、
188:	                                                        // 2:△、 3:▽
189:	static boolean          shapeSpread = false;            // 塗りつぶしボタンの状態
190:	final static Color      bc = Color.white;               // 背景色
191:	static       Color      dc = Color.red;                 // 描画色
192:	final static JTextField tw = new JTextField("30",3);    // ものの幅
193:	final static JTextField th = new JTextField("30",3);    // ものの高さ
194:	final int               MAX_NUM = 100;                  // ものの最大個数
195:	int                     nshape = 0;                     // ものの個数
196:	ColoredShape[]          shape = new ColoredShape[MAX_NUM]; // 矩形のもの
197:	double                  x, y;                           // ドラッグ前の座標
198:
199:	public Graph2d2z() {
200:		addMouseListener(new MouseAdapter() {
201:			public void mouseClicked(MouseEvent e) {        // マウスがクリックされた場合
202:				double x = (double)e.getX();                         // カーソルの座標
203:				double y = (double)e.getY();
204:				double w = Double.parseDouble(tw.getText().trim());  // 下欄に表示中の幅
205:				double h = Double.parseDouble(th.getText().trim());  // 高さ
206:				if(nshape<MAX_NUM && shapetype==0) {                 // 下欄で楕円を指定中
207:					shape[nshape++] =
208:					   new ColoredEllipse(x-w/2.0, y-h/2.0, w, h, dc, shapeSpread);   // 楕円の生成
209:				} else if(nshape<MAX_NUM && shapetype==1) {
210:					shape[nshape++] =
211:					   new ColoredRectangle(x-w/2.0, y-h/2.0, w, h, dc, shapeSpread); // 矩形の生成
212:				} else if(nshape<MAX_NUM && shapetype==2) {
213:					shape[nshape++] =
214:					   new ColoredTriangle(x-w/2.0, y-h/2.0, w, h, dc, true, shapeSpread);  // △の生成
215:				} else if(nshape<MAX_NUM && shapetype==3) {
216:					shape[nshape++] =
217:					   new ColoredTriangle(x-w/2.0, y-h/2.0, w, h, dc, false, shapeSpread); // ▽の生成
218:				} else {
219:					System.out.println("これ以上書けません");
220:				}
221:				repaint();                                  // 再描画
222:			}
223:			public void mousePressed(MouseEvent e) {        // マウスが押された場合
224:				x = (double)e.getX();                       // カーソルの座標を保存
225:				y = (double)e.getY();
226:			}
227:		});
228:		addMouseMotionListener(new MouseMotionAdapter() {
229:			public void mouseDragged(MouseEvent e) {        // マウスがドラッグされた場合
230:				double newx = (double)e.getX();             // 新しい座標
231:				double newy = (double)e.getY();
232:				for(int i=0; i<nshape; i++) {               // 保存してある全図形について
233:					if(shape[i].contains(x,y)){                         // カーソルが触れている場合
234:						shape[i].setFrame(shape[i].getX() + newx - x,   // 図形を移動
235:						                  shape[i].getY() + newy - y,
236:						                  shape[i].getWidth(), shape[i].getHeight());
237:					}
238:				}
239:				x = newx;                                   // 新しい座標を保存
240:				y = newy;
241:				double w = (double)getWidth();              // 表示枠の幅と高さ
242:				double h = (double)getHeight();
243:				int j=0;                                    // 保存してある全図形について
244:				while(j<nshape) {
245:					if(!shape[j].intersects(0.0, 0.0, w, h)) {          // 表示枠の外にある場合
246:						for(int i=j+1; i<nshape; i++) shape[i-1] = shape[i];   // その図形を消去
247:						nshape--;
248:					}
249:					j++;
250:				}
251:				repaint();                                  // 再描画
252:			}
253:		});
254:		setBackground(bc);
255:	}
256:
257:	public void paintComponent(Graphics g) {
258:		super.paintComponent(g);
259:		Graphics2D gg = (Graphics2D)g;
260:		for(int i=0; i<nshape; i++) {                       // 保存してある全図形について
261:			shape[i].draw(gg);                              // 描画
262:		}
263:	}
264:
265:	public static void main(String[] args) {
266:		JFrame frame = new JFrame();
267:		frame.addWindowListener(new WindowAdapter() { 
268:			public void windowClosing(WindowEvent e) { System.exit(0); }
269:		});
270:		final Container cont = frame.getContentPane();      // コンテントペイン
271:		cont.setLayout(new BorderLayout());                 // 
272:		cont.add(new Graph2d2z(), BorderLayout.CENTER );    // 描画用パネルを CENTER に
273:		JPanel southpan = new JPanel();                     // ボタンをならべるパネル
274:		JButton button = new JButton("色選択");             // カラーチューザを呼び出すボタン
275:		button.addActionListener(new ActionListener() {
276:			public void actionPerformed(ActionEvent e) {
277:				Color c = JColorChooser.showDialog(cont, "Choose", Color.white);
278:				if( c!=null ) dc = c;
279:			}
280:		});
281:		southpan.add(button);
282:		JRadioButton buttonE = new JRadioButton("楕円", true);   // 図形選択用ボタン
283:		buttonE.addActionListener(new ActionListener() {
284:			public void actionPerformed(ActionEvent e) {
285:				shapetype = 0;
286:			}
287:		});
288:		JRadioButton buttonR = new JRadioButton("矩形", false);  // 図形選択用ボタン
289:		buttonR.addActionListener(new ActionListener() {
290:			public void actionPerformed(ActionEvent e) {
291:				shapetype = 1;
292:			}
293:		});
294:		JRadioButton buttonT = new JRadioButton("△", false);    // 図形選択用ボタン
295:		buttonT.addActionListener(new ActionListener() {
296:			public void actionPerformed(ActionEvent e) {
297:				shapetype = 2;
298:			}
299:		});
300:		JRadioButton buttonN = new JRadioButton("▽", false);    // 図形選択用ボタン
301:		buttonN.addActionListener(new ActionListener() {
302:			public void actionPerformed(ActionEvent e) {
303:				shapetype = 3;
304:			}
305:		});
306:		JRadioButton buttonS = new JRadioButton("塗りつぶし", false);// ぬりつぶしor枠だけ
307:		buttonS.addActionListener(new ActionListener() {
308:			public void actionPerformed(ActionEvent e) {
309:				shapeSpread = !shapeSpread;
310:			}
311:		});
312:		ButtonGroup bg = new ButtonGroup();                      //
313:		bg.add(buttonE);
314:		bg.add(buttonR);
315:		bg.add(buttonT);
316:		bg.add(buttonN);
317:		southpan.add(buttonE);
318:		southpan.add(buttonR);
319:		southpan.add(buttonT);
320:		southpan.add(buttonN);
321:		southpan.add(new JLabel(" 幅"));
322:		southpan.add(tw);
323:		southpan.add(new JLabel(" 高さ"));
324:		southpan.add(th);
325:		southpan.add(buttonS);
326:		cont.add( southpan, BorderLayout.SOUTH);
327:		frame.setSize(560, 300);
328:		frame.setVisible(true);
329:	}
330:}