import java.util.ArrayList;
import java.text.DecimalFormat;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.text.DefaultFormatter;
class PlotSurface extends JPanel {
private Model model;
public PlotSurface(Model model)
{
this.model = model;
setBackground(Color.WHITE);
}
public void update()
{
repaint();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(150,150);
}
@Override
public void paintComponent(Graphics g) {
final Mark ORIGIN_POINT = new Mark(getWidth()/2, getHeight()/2);
final Mark PANEL_NORTH_WEST = new Mark(0,0);
final Mark PANEL_NORTH_EAST= new Mark(getWidth(),0);
final Mark PANEL_SOUTH_WEST = new Mark(0,getHeight());
final Mark PANEL_SOUTH_EAST = new Mark(getWidth(),getHeight());
final int STEP = 150/model.getR();
model.setOrigin(ORIGIN_POINT);
model.setStep(STEP);
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.WHITE);
g2.fillRect(0, 0, getWidth(), getHeight());
paintForm(g2, ORIGIN_POINT, STEP);
paintPlot(g2, ORIGIN_POINT, STEP, PANEL_NORTH_WEST, PANEL_NORTH_EAST, PANEL_SOUTH_WEST, PANEL_SOUTH_EAST);
paintPoints(g2, ORIGIN_POINT, STEP);
}
private void paintForm(Graphics2D g2, Mark ORIGIN_POINT, int STEP)
{
g2.setColor(Color.BLUE);
g2.fillArc((int)( ORIGIN_POINT.getX() - STEP*model.getR() / 2), (int) (ORIGIN_POINT.getY() - STEP*model.getR()/ 2), (int)(STEP*model.getR()), (int) (STEP*model.getR()),270,90);
int xPoly[] = {(int) ORIGIN_POINT.getX(),(int) ORIGIN_POINT.getX(), (int) ORIGIN_POINT.getX() - STEP*model.getR()/2, (int) ORIGIN_POINT.getX( ) - STEP*model.getR()/2};
int yPoly[] = {(int) ORIGIN_POINT.getY(),(int) ORIGIN_POINT.getY() - STEP*model.getR(), (int) ORIGIN_POINT.getY() - STEP*model.getR(), (int) ORIGIN_POINT.getY()};
Polygon poly = new Polygon(xPoly, yPoly, xPoly.length);
g2.fillPolygon(poly);
int xTriangle[] = {(int) ORIGIN_POINT.getX(),(int) ORIGIN_POINT.getX(), (int) ORIGIN_POINT.getX() - STEP*model.getR()};
int yTriangle[] = {(int) ORIGIN_POINT.getY(),(int) ORIGIN_POINT.getY() + STEP*model.getR()/2, (int) ORIGIN_POINT.getY()};
poly = new Polygon(xTriangle, yTriangle, xTriangle.length);
g2.fillPolygon(poly);
}
private void paintPlot(Graphics2D g2, Mark ORIGIN_POINT, int STEP, Mark PANEL_NORTH_WEST, Mark PANEL_NORTH_EAST,Mark PANEL_SOUTH_WEST, Mark PANEL_SOUTH_EAST )
{
g2.setColor(Color.BLACK);
g2.drawLine(0,(int) ORIGIN_POINT.getY(),(int)PANEL_NORTH_EAST.getX(),(int)ORIGIN_POINT.getY());
g2.drawLine((int) ORIGIN_POINT.getX(),(int) PANEL_NORTH_EAST.getY(),(int)ORIGIN_POINT.getX(),(int)PANEL_SOUTH_EAST.getY());
int POINTS_NUMBER = 0;
for (int i = (int) ORIGIN_POINT.getX(); i < (int) PANEL_NORTH_EAST.getX(); i+=STEP) {
g2.fillOval(i,(int) ORIGIN_POINT.getY(),3,3);
g2.drawString(Integer.valueOf(POINTS_NUMBER++).toString(),i,(int) ORIGIN_POINT.getY());
}
POINTS_NUMBER = 0;
for (int i = (int) ORIGIN_POINT.getX(); i > (int) PANEL_NORTH_WEST.getX(); i-=STEP) {
g2.fillOval(i,(int) ORIGIN_POINT.getY(),3,3);
g2.drawString(Integer.valueOf(POINTS_NUMBER--).toString(),i,(int) ORIGIN_POINT.getY());
}
POINTS_NUMBER = 0;
for (int i = (int) ORIGIN_POINT.getY(); i > (int) PANEL_NORTH_WEST.getY(); i-=STEP) {
g2.fillOval((int) ORIGIN_POINT.getX(),i,3,3);
g2.drawString(Integer.valueOf(POINTS_NUMBER++).toString(),(int) ORIGIN_POINT.getX(),i);
}
POINTS_NUMBER = 0;
for (int i = (int) ORIGIN_POINT.getY(); i < (int) PANEL_SOUTH_WEST.getY(); i+=STEP) {
g2.fillOval((int) ORIGIN_POINT.getX(),i,3,3);
g2.drawString(Integer.valueOf(POINTS_NUMBER--).toString(),(int) ORIGIN_POINT.getX(),i);
}
}
private void paintPoints(Graphics2D g2, Mark ORIGIN_POINT, int STEP)
{
for (Mark point : model.getPoints()) {
if (model.getForm().IsPointBelongsToForm(point))
{
paintPoint(g2,point,ORIGIN_POINT,STEP,Color.GREEN);
point.setIsBelongToForm(true);
}
else
{
paintPoint(g2,point,ORIGIN_POINT,STEP,Color.RED);
if (point.getIsBelongToForm() && !point.isAnimating()) {
point.setIsAnimating(true);
point.setIsBelongToForm(false);
AnimationThread animation = new AnimationThread(point, model.getR(), this);
animation.start();
}
}
}
}
private void paintPoint(Graphics2D g2, Mark point, Mark ORIGIN_POINT, int STEP, Color color) {
int x = (int) (point.getX()*STEP + ORIGIN_POINT.getX());
int y = (int) (STEP*point.getY() + ORIGIN_POINT.getY());
int radius = point.getRadius();
g2.setColor(color);
g2.fillOval(x-radius/2,y -radius/2,radius,radius);
g2.setColor(Color.BLACK);
g2.drawOval(x-radius/2,y -radius/2,radius,radius);
}
}
class Mark
{
private double x, y;
volatile private int radius;
private boolean isBelongToForm, _isAnimating;
public Mark(double x,double y)
{
this.x = x;
this.y = y;
radius = 10;
isBelongToForm = false;
_isAnimating = false;
}
public double getX() {return x;}
public double getY() {return y;}
public boolean getIsBelongToForm() {return isBelongToForm;}
public boolean isAnimating() { return _isAnimating; }
public int getRadius() { return radius; }
public void setX(double x) {this.x = x;}
public void setY(double y) {this.y = y;}
public void setIsBelongToForm(boolean state) { isBelongToForm = state;}
public void setIsAnimating(boolean a) { _isAnimating = a; }
public void setRadius(int r) { radius = r; }
}
class Form{
private double R;
public Form(double R){
this.R = R;
}
public Boolean IsPointBelongsToForm(Mark point){
return IsPointBelongToFirstZone(point) || IsPointBelongToSecondZone(point) || IsPointBelongToThirdZone(point);
}
private Boolean IsPointBelongToFirstZone(Mark point){
return (point.getX() >= -R/2) && (point.getX() <= 0) && (point.getY() <= 0) && (point.getY() >= -R);
}
private Boolean IsPointBelongToSecondZone(Mark point){
return (point.getX() <= 0) && (point.getY() >= 0) && (point.getX() >= -R) && (point.getY() <= (0.5)*point.getX() + R/2);
}
private Boolean IsPointBelongToThirdZone(Mark point){
return (point.getX() >= 0) && (point.getY() >= 0) && ( (Math.pow(point.getX(), 2) + Math.pow(point.getY(), 2)) <= Math.pow(-R/2, 2));
}
}
class Model
{
private double x, y;
private double selectedX, selectedY;
private int R;
private Mark origin;
private Form form;
private double step;
private ArrayList<Mark> points;
public Model()
{
points = new ArrayList<Mark>();
this.x = 0;
this.y = 0;
this.R = 1;
this.origin = null;
this.step = 0;
this.selectedX = 0;
this.selectedY = 0;
this.form = new Form(R);
}
public Form getForm() {return form;}
public double getSelectedX() {return selectedX;}
public double getSelectedY() {return selectedY;}
public double getX() {return x;}
public double getY() {return y;}
public int getR() {return R;}
public Mark getOrigin() {return origin;}
public double getStep() {return step;}
public ArrayList<Mark> getPoints() { return points;}
public void clearPoints() {points.clear();}
public void addPoint(Mark point) {points.add(point); }
public void setForm(Form form) {this.form = form;}
public void setSelectedX(double x) {this.selectedX = x;}
public void setSelectedY(double y) {this.selectedY = y;}
public void setX(double x) {this.x = x;}
public void setY(double y) {this.y = y;}
public void setR(int R) {
this.R = R;
form = new Form(R);
}
public void setOrigin(int x, int y) {this.origin = new Mark(x,y); }
public void setOrigin(Mark newOrigin) {this.origin = newOrigin;}
public void setStep(double step) { this.step = step; }
}
class AnimationThread extends Thread
{
private double R;
private PlotSurface plot;
private Mark point;
public AnimationThread(Mark point, double R, PlotSurface plot)
{
this.R = R;
this.plot = plot;
this.point = point;
}
@Override
public void run()
{
for (int i = 0; i< 12; ++i)
{
point.setRadius((int)(120*R)/(12+i));
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
plot.repaint();
}
});
try
{
Thread.sleep(50);
}
catch (InterruptedException e) {}
}
for (int i = 0; i< 12; ++i)
{
point.setRadius((int)(120*R)/(24-i));
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
plot.repaint();
}
});
try
{
Thread.sleep((long)50);
}
catch (InterruptedException e) {}
}
point.setIsAnimating(false);
}
}
class View
{
final Model model;
final JFrame frame;
final JPanel header, footer;
final PlotSurface plot;
final JLabel lblR, lblX, lblY, coords;
final JSpinner spinnerR;
final JComboBox<String> comboX;
ButtonGroup groupY= new ButtonGroup();
final JButton clearButton = new JButton("clear");
public View()
{
model = new Model();
frame = new JFrame("Lab №4. Var 36. Markelow, Staroselskii");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(500, 500));
footer = new JPanel();
footer.setLayout(new FlowLayout());
footer.setBackground(Color.GRAY);
header = new JPanel();
header.setLayout(new FlowLayout());
header.setBackground(Color.GRAY);
plot = new PlotSurface(model);
final MouseAdapter mouseAdapter = new MouseAdapter()
{
@Override
public void mousePressed(MouseEvent e) {
model.setX((e.getX()-model.getOrigin().getX())/model.getStep());
model.setY((e.getY()-model.getOrigin().getY())/model.getStep());
model.addPoint(new Mark(model.getX(), model.getY()));
update();
}
};
plot.addMouseListener(mouseAdapter);
plot.addMouseMotionListener(mouseAdapter);
lblR = new JLabel();
lblR.setText("R: ");
lblR.setForeground(Color.WHITE);
SpinnerNumberModel spinnerModel = new SpinnerNumberModel(new Integer(1),new Integer(1),new Integer(50), new Integer(1));
spinnerR = new JSpinner(spinnerModel);
JComponent comp = spinnerR.getEditor();
JFormattedTextField field = (JFormattedTextField) comp.getComponent(0);
DefaultFormatter formatter = (DefaultFormatter) field.getFormatter();
formatter.setCommitsOnValidEdit(true);
ChangeListener spinnerRListener = new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
model.setR((Integer)spinnerR.getValue());
update();
}
};
spinnerR.addChangeListener(spinnerRListener);
header.add(lblR);
header.add(spinnerR);
lblX = new JLabel();
lblX.setText("X: ");
lblX.setForeground(Color.WHITE);
String choices[] = {"0","1","2","-1","-2","-3"};
comboX = new JComboBox<String>();
for (int i = 0; i < choices.length; i++)
comboX.addItem (choices[i]);
comboX.addItemListener(new ItemListener(){
@Override
public void itemStateChanged(ItemEvent e)
{
String item = (String)comboX.getSelectedItem();
model.setX(Integer.valueOf(item));
model.setSelectedX(model.getX());
model.setY(model.getSelectedY());
model.addPoint(new Mark(model.getX(),model.getY()));
update();
}
});
header.add(lblX);
header.add(comboX);
lblY = new JLabel();
lblY.setText("Y: ");
lblY.setForeground(Color.WHITE);
header.add(lblY);
groupY = new ButtonGroup();
ActionListener radioButtonActionListner = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
String command = evt.getActionCommand();
model.setY(Integer.valueOf(command));
model.setSelectedY(model.getY());
model.setX(model.getSelectedX());
model.addPoint(new Mark(model.getX(),model.getY()));
update();
}
};
String radioButtonContraints[] = {"-2","-1","0","1","2"};
JRadioButton radioButton = new JRadioButton(radioButtonContraints[0]);
for (int i = 0; i < radioButtonContraints.length; i++) {
radioButton = new JRadioButton(radioButtonContraints[i]);
Integer yCord = Integer.valueOf(radioButtonContraints[i])*(-1);
radioButton.setActionCommand(yCord.toString());
radioButton.addActionListener(radioButtonActionListner);
if (i==2)
radioButton.setSelected(true);
groupY.add(radioButton);
header.add(radioButton);
}
ActionListener buttonClearActionListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
model.clearPoints();
update();
}
};
clearButton.addActionListener(buttonClearActionListener);
header.add(clearButton);
coords = new JLabel();
coords.setText("COORDS");
coords.setForeground(Color.WHITE);
footer.add(coords);
frame.add(header, BorderLayout.NORTH);
frame.add(plot, BorderLayout.CENTER);
frame.add(footer,BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
}
private void update()
{
plot.update();
String pos;
if (model.getOrigin() == null)
pos = model.getX() + "," + model.getY();
else {
double x = model.getX();
double y = model.getY();
DecimalFormat format = new DecimalFormat("#.##");
x = Double.valueOf(format.format(x));
y = Double.valueOf(format.format(-y));
pos = x+ "," + y;
}
coords.setText(pos);
}
}
public class Lab4UI {
private static void startGUI() {
try
{ UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); }
catch (UnsupportedLookAndFeelException ex)
{ ex.printStackTrace(); }
catch (IllegalAccessException ex)
{ ex.printStackTrace(); }
catch (InstantiationException ex)
{ ex.printStackTrace(); }
catch (ClassNotFoundException ex)
{ ex.printStackTrace(); }
UIManager.put("swing.boldMetal", Boolean.FALSE);
View view = new View();
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
startGUI();
}});
}
}