А.1 TestDraw import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Graphics; import java.io.FileNotFoundException; import java.util.ArrayList; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.table.TableModel; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class TestDraw extends JFrame { /** * processor for working with csv file */ private static CSVProcessor proc; /** * path to csv-file */ public static String path = new String("d:\\Рабочий уголок\\ООП\\ІІ семестр\\Save\\curs\\test.csv"); public final static JTable table = new JTable(); public TestDraw() { super("Пузиркова діаграма"); final DiagramDrawer drawer = new DiagramDrawer(); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); proc = new CSVProcessor(); try { proc.download(path); } catch (FileNotFoundException e1) { System.out.println("Exception 1: File Not Found!\n"); } ArrayList bubbles = new ArrayList(); try { bubbles = proc.parse(); drawer.setBubbles(bubbles); } catch (CSVParseException e) { e.printStackTrace(); } setDefaultLookAndFeelDecorated(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JPanel mainPanel = new JPanel(); mainPanel.setLayout(new BorderLayout()); TableModel model = new MyTableModel(bubbles); table.setModel(model); final JScrollPane scrollPane = new JScrollPane(table); table.setFillsViewportHeight(true); mainPanel.add(scrollPane, BorderLayout.WEST); scrollPane.setPreferredSize(new Dimension(400, 600)); scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); final JButton leftButton = new JButton("Зберегти зображення"); final JButton centerButton = new JButton("Запам'ятати стан"); final JButton rightButton = new JButton("Відновити стан"); leftButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { drawer.saveImage(); } }); centerButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { proc.deparse(drawer.getBubbles()); proc.serialize(); try { proc.upload(path); } catch (FileNotFoundException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } }); rightButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { proc.deserialize(); try{ proc.upload(path); proc.download(path); try { drawer.setBubbles(proc.parse()); } catch (CSVParseException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } catch (FileNotFoundException e1) { System.out.println("Exception 1.5: File Not Found!\n"); } table.setModel(new MyTableModel(drawer.getBubbles())); drawer.findScale(); repaint(); } }); JPanel button_panel = new JPanel(); button_panel.setLayout(new FlowLayout()); button_panel.setPreferredSize(new Dimension(600, 45)); drawer.setPreferredSize(new Dimension(500, 500)); button_panel.add(leftButton); button_panel.add(centerButton); button_panel.add(rightButton); JPanel panel = new JPanel(); panel.setLayout(new BorderLayout()); panel.add(button_panel, BorderLayout.NORTH); panel.add(drawer, BorderLayout.CENTER); mainPanel.add(panel, BorderLayout.EAST); getContentPane().add(mainPanel); setPreferredSize(new Dimension(1000, 600)); setResizable(false); pack(); setLocationRelativeTo(null); setVisible(true); } public static void main(String[] args) { Thread thread = new Thread(new Runnable() { @Override public void run() { new TestDraw(); } }); thread.start(); try { thread.join(); } catch (InterruptedException e) { e.printStackTrace(); } } } А.2 Bubble import java.awt.Color; public class Bubble { private double X; private double Y; private double R; public boolean selected = false; public Color color; public Bubble(double X, double Y, double R, Color color){ this.X=X; this.Y=Y; this.R=R; this.color = color; } public void setX(double X) { this.X = X; } public double getX() { return X; } public void setY(double Y) { this.Y = Y; } public double getY() { return Y; } public void setR(double R) { this.R = R; } public double getR() { return R; } } А.3 DiagramDrawer import java.awt.Button; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.event.InputEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.geom.Ellipse2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Random; import javax.imageio.ImageIO; import javax.swing.JFileChooser; import javax.swing.JPanel; public class DiagramDrawer extends JPanel implements MouseListener, MouseMotionListener { @Override public void paint(Graphics g) { super.paint(g); draw(g); } /** * pixel width */ private static int w = 500; /** * pixel height */ private static int h = 500; /** * scale */ private double scl = 1.0d; /** * bubble list */ private ArrayList bubbles; /** * get bubble list */ public ArrayList getList() { return bubbles; } /** * set new list */ public void setBubbles(ArrayList bubbles) { this.bubbles = new ArrayList(bubbles); } /** * construct */ public DiagramDrawer() { super(); this.bubbles = new ArrayList(); this.addMouseListener(this); this.addMouseMotionListener(this); } /** * get this list */ public ArrayList getBubbles() { return bubbles; } /** * find scale */ public void findScale() { double maxX = bubbles.get(0).getX(); for (Bubble b : bubbles) { if (b.getX() > maxX) { maxX = b.getX(); } } double maxY = bubbles.get(0).getY(); for (Bubble b : bubbles) { if (b.getY() > maxY) { maxY = b.getY(); } } double maxR = bubbles.get(0).getR(); for (Bubble b : bubbles) { if (b.getR() > maxR) { maxR = b.getR(); } } double realWidth = maxX + 2 * maxR; double realHeight = maxY + 2 * maxR; if (realWidth > realHeight) { scl = w / realWidth; } else { scl = h / realHeight; } } /** * draw circle * * @x coordinate * @y coordinate * @r radius */ private void drawCircle(double x, double y, double r, Graphics g,boolean selected,Color color) { g.setColor(color); Graphics2D g2d = (Graphics2D)g; if(selected) { g.setColor(Color.black); g.drawOval((int)(x - r), (int)(y - r), (int)(r * 2), (int)(r * 2)); } g.setColor(color); g2d.fill(new Ellipse2D.Double(x - r, y - r, r * 2, r * 2)); g.setColor(Color.black); g.drawLine((int)x, (int)y, (int)x, (int)y); } /** * draw mrg */ private static int mrg = 30; /** * draw coordinate */ private void drawCoordinate(Graphics g) { // coords g.setColor(Color.black); // oy g.drawLine(mrg, mrg, mrg, h - mrg); g.drawLine(mrg, mrg, mrg + 3, mrg + 10); g.drawLine(mrg, mrg, mrg - 3, mrg + 10); // ox g.drawLine(mrg, h - mrg, w - mrg, h - mrg); g.drawLine(w - mrg, h - mrg, w- mrg - 10, h - mrg - 3); g.drawLine(w - mrg, h - mrg, w- mrg - 10, h - mrg + 3); // end coord int step = 70; // у for (int i = h - mrg-step; i > 0; i -= step) { g.setColor(Color.gray); g.drawLine(mrg - 3, i, w-mrg, i); g.setColor(Color.lightGray); g.drawLine(mrg - 3, i+step/2, w-mrg, i+step/2); g.setColor(Color.black); g.drawString(String.valueOf((int) ((h - mrg - i) / scl)),0, i+5); } // х for (int i = mrg+step; i < w; i += step) { g.setColor(Color.gray); g.drawLine(i, mrg, i, h - mrg + 3); g.setColor(Color.lightGray); g.drawLine(i-step/2, mrg, i-step/2, h - mrg + 3); g.setColor(Color.black); g.drawString(String.valueOf((int) ((i-mrg) / scl)), i-5,h-mrg/4); } g.setColor(Color.black); } /** * diagram image */ private BufferedImage image; /** * save image * @name of image */ public void saveImage(){ JFileChooser filesave = new JFileChooser("d:/Рабочий уголок/ООП/ІІ семестр/Save/curs/"); FileNameExtensionFilter f = new FileNameExtensionFilter("jpg files","*.jpg","jpg"); filesave.addChoosableFileFilter(f); filesave.setFileFilter(f); int ret = filesave.showDialog(null, "Зберегти зображення"); if(ret==filesave.APPROVE_OPTION){ try { ImageIO.write(image,"jpg",new File(filesave.getSelectedFile().getAbsolutePath()+".jpg")); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } /** * drawing */ public void draw(Graphics g) { if(sn==-1)findScale(); image = new BufferedImage(w, h,BufferedImage.TYPE_INT_RGB); Graphics gImg = image.createGraphics(); gImg.setColor(Color.white); gImg.fillRect(0, 0, w, h); drawCoordinate(gImg); for (Bubble b : bubbles) { drawCircle(mrg + b.getX() * scl, h - b.getY() * scl - mrg, b.getR() * scl, gImg, b.selected, b.color); } g.drawImage(image, 50, 0, null); } private double findXY(double x1, double y1, double x2, double y2){ return (Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))); } /** * check and select circle * */ private int checkBubbles(double x, double y, int a){ int result = -1; for (int i = 0; i < a;i++) { bubbles.get(i).selected = false; } for (int i = a; i < bubbles.size();i++) { bubbles.get(i).selected = false; if(findXY(x,y,bubbles.get(i).getX(),bubbles.get(i).getY())<=bubbles.get(i).getR()) { if (result==-1) { bubbles.get(i).selected = true; TestDraw.table.setRowSelectionInterval(i, i); result = i; } } } return result; } /** * select circle number * */ public int sn = -1; @Override public void mouseClicked(MouseEvent arg0) { double x = (arg0.getX()-mrg-50)/scl; double y =(h-arg0.getY()-mrg)/scl; if(arg0.getModifiers()==InputEvent.BUTTON1_MASK) { if(sn!=-1&& findXY(x,y,bubbles.get(sn).getX(),bubbles.get(sn).getY())>bubbles.get(sn).getR())sn=-1; int a = checkBubbles(x,y, sn+1); if(a==-1)sn = -1; else sn = a; } if(arg0.getModifiers()==InputEvent.BUTTON3_MASK){ if(sn==-1){ Random rand = new Random(); Bubble b = new Bubble(x,y,w/scl/10,new Color(50 + rand.nextInt(205), 50 + rand.nextInt(205),50 + rand.nextInt(205), 130)); bubbles.add(b); } else { bubbles.get(sn).setX(x); bubbles.get(sn).setY(y); } } if(arg0.getModifiers()==InputEvent.BUTTON2_MASK){ if(sn!=-1){ bubbles.remove(bubbles.get(sn)); sn = -1; } } repaint(); // TODO Auto-generated method stub } @Override public void mouseEntered(MouseEvent arg0) { // TODO Auto-generated method stub } @Override public void mouseExited(MouseEvent arg0) { // TODO Auto-generated method stub } /** * coordinate x for pressed mouse * */ private double xP; /** * coordinate Y for pressed mouse * */ private double yP; @Override public void mousePressed(MouseEvent arg0) { // TODO Auto-generated method stub if(arg0.getModifiers()==InputEvent.BUTTON1_MASK){ xP = (arg0.getX()-mrg-50)/scl; yP =(h-arg0.getY()-mrg)/scl; } } @Override public void mouseReleased(MouseEvent arg0) { // TODO Auto-generated method stub findScale(); TestDraw.table.setModel(new MyTableModel(bubbles)); if(sn!=-1)TestDraw.table.setRowSelectionInterval(sn, sn); repaint(); } @Override public void mouseDragged(MouseEvent arg0) { // TODO Auto-generated method stub if(arg0.getModifiers()==InputEvent.BUTTON1_MASK){ double x = (arg0.getX()-mrg-50)/scl; double y =(h-arg0.getY()-mrg)/scl; if(sn!=-1) { double dR = findXY(x,y,bubbles.get(sn).getX(),bubbles.get(sn).getY())-findXY(xP,yP,bubbles.get(sn).getX(),bubbles.get(sn).getY()); if(dR!=0) bubbles.get(sn).setR(bubbles.get(sn).getR()+dR/10); } repaint(); } } @Override public void mouseMoved(MouseEvent arg0) { // TODO Auto-generated method stub } } А.4 MyTableModel import java.util.HashSet; import java.util.List; import java.util.Set; import javax.swing.event.TableModelListener; import javax.swing.table.TableModel; public class MyTableModel implements TableModel { private Set listeners = new HashSet(); private List bubbles; public MyTableModel(List bubbles) { this.bubbles = bubbles; } public void addTableModelListener(TableModelListener listener) { listeners.add(listener); } public Class getColumnClass(int columnIndex) { return String.class; } public int getColumnCount() { return 3; } public String getColumnName(int columnIndex) { switch (columnIndex) { case 0: return "Координата Х"; case 1: return "Координата У"; case 2: return "Радіус"; } return ""; } public int getRowCount() { return bubbles.size(); } public Object getValueAt(int rowIndex, int columnIndex) { Bubble bubble = bubbles.get(rowIndex); switch (columnIndex) { case 0: return (int)bubble.getX(); case 1: return (int)bubble.getY(); case 2: return (int)bubble.getR(); } return ""; } public boolean isCellEditable(int rowIndex, int columnIndex) { return false; } public void removeTableModelListener(TableModelListener listener) { listeners.remove(listener); } public void setValueAt(Object value, int rowIndex, int columnIndex) { } } А.5 CSVProcessor import java.awt.Color; import java.io.*; import java.util.ArrayList; import java.util.Random; public class CSVProcessor { /** * constructor */ public CSVProcessor (){ list = new ArrayList(); } /** * our list */ public ArrayList list; /** * file path for (de)serialize */ private static String pathSer = new String("d:\\Рабочий уголок\\ООП\\ІІ семестр\\Save\\curs\\serialized.dat"); /** * download strings from file to array * @throws FileNotFoundException */ public void download(String path)throws FileNotFoundException{ File f = new File(path); list.clear(); BufferedReader reader = new BufferedReader(new FileReader(f)); try{ String str; while((str = reader.readLine())!= null) list.add(str); } catch (IOException e2) { System.out.println("Exception 2: Can Not Read Line!"); } finally{ if(reader!=null) try { reader.close(); } catch (IOException e3) { System.out.println("Exeption 3.1: File Can Not Close!"); } } } /** * upload strings from array to file * @throws FileNotFoundException */ public void upload(String path)throws FileNotFoundException{ File f = new File(path); f.getParentFile().mkdirs(); try { f.createNewFile(); } catch (IOException e) { System.out.println("can not create file"); e.printStackTrace(); } PrintWriter pw = null; try{ pw = new PrintWriter(f); for (String str : list) { pw.println(str); } }catch (IOException e){ }finally{ if(pw!=null) pw.close(); } } /** * serialize to file */ public void serialize(){ ObjectOutputStream obout = null; try { obout = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(pathSer))); } catch (IOException e6) { System.out.println("Exception 6: Invalid Object Stream!"); } try { obout.writeObject(list); } catch (IOException e7) { System.out.println("Exception 7: Can Not Write Object!"); } finally { try { obout.close(); } catch (IOException e8) { System.out.println("Exception 8.1: Can Not Close Stream!"); } } } /** * deserialize from file */ public void deserialize(){ ObjectInputStream obinp = null; try{ obinp = new ObjectInputStream(new BufferedInputStream(new FileInputStream(pathSer))); @SuppressWarnings("unchecked") ArrayList temp = (ArrayList) obinp.readObject(); list = temp; } catch (FileNotFoundException e1) { System.out.println("Exception 1.4: File Not Found!"); } catch (ClassNotFoundException e9) { System.out.println("Exception 9: Class Not Found!"); } catch (IOException e10) { System.out.println("Exception 10: Can Not Create Or Read Object!"); } finally{ try { obinp.close(); } catch (IOException e8) { System.out.println("Exception 8.2: Can Not Close Stream!"); } } } /** * parsing data */ public ArrayList parse() throws CSVParseException{ Random rand = new Random(); int len = list.get(0).split(";").length; if (len == 0) throw new CSVParseException("Not CSV Format!"); if (len !=3) throw new CSVParseException("Wrong column number!"); ArrayList bubbles = new ArrayList(); for (String str : list) { String[] tokens = str.split(";"); if (tokens.length != 3) throw new CSVParseException("Wrong line length!"); try { bubbles.add(new Bubble(Double.parseDouble(tokens[0]),Double.parseDouble(tokens[1]), Double.parseDouble(tokens[2]),new Color(50 + rand.nextInt(205), 50 + rand.nextInt(205),50 + rand.nextInt(205), 130))); } catch(NumberFormatException e) { System.out.println("Not a number!"); } } return bubbles; } /** * deparsing data */ public void deparse(ArrayList bubbles) { list.clear(); for(Bubble b : bubbles) list.add(b.getX()+";"+b.getY()+";"+b.getR()); } /** * return private pathSer */ public static String getPathSer (){ return pathSer; } /** * add new string to list * @param str string to add */ public void addString (String str){ list.add(str); } /** * remove string from list * @param num number of string to remove */ public void removeString (int num){ list.remove(num); } } А.6 CSVParseException public class CSVParseException extends Exception{ private static final long serialVersionUID = 1L; public CSVParseException() { super(); } public CSVParseException(String msg) { super(msg); } public CSVParseException(Throwable cause) { super(cause); } }