Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Improve tests.
[graphlib_java.git] / DrawingWindow.java
index 3b42553..e7766d0 100644 (file)
@@ -1,8 +1,22 @@
-import java.awt.*;
-import java.awt.event.*;
-import java.awt.image.*;
-import javax.swing.*;
-import java.util.*;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics2D;
+import java.awt.Graphics;
+import java.awt.Point;
+import java.awt.Polygon;
+import java.awt.Toolkit;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.image.BufferedImage;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
 
 /**
  * Fenêtre de dessin
@@ -20,7 +34,7 @@ import java.util.*;
  * possible de fermer la fenêtre via le gestionnaire de fenêtres.
  *
  * @author Arnaud Giersch <arnaud.giersch@univ-fcomte.fr>
- * @version 20141014
+ * @version 20141021b
  */
 public class DrawingWindow {
 
@@ -46,6 +60,11 @@ public class DrawingWindow {
         this.width = width;
         this.height = height;
 
+        mouseLock = new Object();
+        mouseEvent = null;
+        mousePos = new Point(0, 0);
+        mouseButton = 0;
+
         image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
         graphics = image.createGraphics();
 
@@ -144,7 +163,7 @@ public class DrawingWindow {
      * @see #setBgColor(String)
      * @see #setBgColor(float, float, float)
      * @see #setColor(Color)
-     * @see #clearGraph()
+     * @see #clearGraph
      */
     public void setBgColor(Color color) {
         bgColor = color;
@@ -158,7 +177,7 @@ public class DrawingWindow {
      * @see #setBgColor(float, float, float)
      * @see #setColor(int)
      * @see #getPointColor
-     * @see #clearGraph()
+     * @see #clearGraph
      */
     public void setBgColor(int rgb) {
         setBgColor(new Color(rgb));
@@ -172,7 +191,7 @@ public class DrawingWindow {
      * @see #setBgColor(int)
      * @see #setBgColor(float, float, float)
      * @see #setColor(String)
-     * @see #clearGraph()
+     * @see #clearGraph
      * @see <a href="http://www.w3.org/TR/SVG/types.html#ColorKeywords">liste des noms de couleurs</a>
      */
     public void setBgColor(String name) {
@@ -192,7 +211,7 @@ public class DrawingWindow {
      * @see #setBgColor(int)
      * @see #setBgColor(String)
      * @see #setColor(float, float, float)
-     * @see #clearGraph()
+     * @see #clearGraph
      */
     public void setBgColor(float red, float green, float blue) {
         setBgColor(new Color(red, green, blue));
@@ -223,6 +242,8 @@ public class DrawingWindow {
      * @see #setColor
      */
     public void drawPoint(int x, int y) {
+        if (x < 0 || y < 0 || x >= width || y >= height)
+            return;
         synchronized (image) {
             image.setRGB(x, y, graphics.getColor().getRGB());
         }
@@ -385,7 +406,88 @@ public class DrawingWindow {
      * @see #setBgColor(int)
      */
     public int getPointColor(int x, int y) {
-        return image.getRGB(x, y);
+        return (x < 0 || y < 0 || x >= width || y >= height) ?
+            0 : image.getRGB(x, y) & 0x00ffffff;
+    }
+
+    /**
+     * Attend l'appui sur un des boutons de la souris.
+     *
+     * @return vrai (true) si un bouton a été pressé
+     *
+     * @see #waitMousePress(long)
+     * @see #getMouseX
+     * @see #getMouseY
+     * @see #getMouseButton
+     */
+    public boolean waitMousePress() {
+        return waitMousePress(-1);
+    }
+
+    /**
+     * Attend l'appui sur un des boutons de la souris.
+     *
+     * @param timeout   temps maximal d'attente (millisecondes)
+     *
+     * @return vrai (true) si un bouton a été pressé
+     *
+     * @see #waitMousePress()
+     * @see #getMouseX
+     * @see #getMouseY
+     * @see #getMouseButton
+     */
+    public boolean waitMousePress(long timeout) {
+        boolean result = false;
+        synchronized (mouseLock) {
+            if (timeout != 0) {
+                mouseEvent = null;
+                try {
+                    if (timeout > 0)
+                        mouseLock.wait(timeout);
+                    else // (timeout < 0)
+                        mouseLock.wait();
+                }
+                catch (InterruptedException e) {
+                }
+            }
+            if (mouseEvent != null) {
+                mousePos.setLocation(mouseEvent.getPoint());
+                mouseButton = mouseEvent.getButton();
+                mouseEvent = null;
+                result = true;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Retourne la position (x) de la souris la dernière fois qu'un
+     * bouton a été pressé pendant l'appel à {@link #waitMousePress()}.
+     *
+     * @return position (x)
+     */
+    public int getMouseX() {
+        return mousePos.x;
+    }
+
+    /**
+     * Retourne la position (y) de la souris la dernière fois qu'un
+     * bouton a été pressé pendant l'appel à {@link #waitMousePress()}.
+     *
+     * @return position (y)
+     */
+    public int getMouseY() {
+        return mousePos.y;
+    }
+
+    /**
+     * Retourne le numéro du bouton de la souris pressé pendant
+     * le dernier appel à {@link #waitMousePress()}.
+     *
+     * @return numéro de bouton (1: gauche, 2: milieu, 3: droit)
+     */
+    public int getMouseButton() {
+        return mouseButton;
     }
 
     /**
@@ -415,8 +517,7 @@ public class DrawingWindow {
         javax.swing.SwingUtilities.invokeLater(new Runnable() {
                 public void run() {
                     WindowEvent ev =
-                        new WindowEvent(frame,
-                                        WindowEvent.WINDOW_CLOSING);
+                        new WindowEvent(frame, WindowEvent.WINDOW_CLOSING);
                     Toolkit.getDefaultToolkit()
                         .getSystemEventQueue().postEvent(ev);
                 }
@@ -428,8 +529,11 @@ public class DrawingWindow {
      * Suspend l'exécution pendant un certain temps.
      *
      * @param secs          temps d'attente en seconde
+     *
+     * @see #msleep
+     * @see #usleep
      */
-    static void sleep(long secs) {
+    public static void sleep(long secs) {
         try {
             Thread.sleep(secs * 1000);
         }
@@ -441,8 +545,11 @@ public class DrawingWindow {
      * Suspend l'exécution pendant un certain temps.
      *
      * @param msecs          temps d'attente en millisecondes
+     *
+     * @see #sleep
+     * @see #usleep
      */
-    static void msleep(long msecs) {
+    public static void msleep(long msecs) {
         try {
             Thread.sleep(msecs);
         }
@@ -454,8 +561,11 @@ public class DrawingWindow {
      * Suspend l'exécution pendant un certain temps.
      *
      * @param usecs          temps d'attente en microsecondes
+     *
+     * @see #sleep
+     * @see #msleep
      */
-    static void usleep(long usecs) {
+    public static void usleep(long usecs) {
         try {
             Thread.sleep(usecs / 1000, (int)(usecs % 1000) * 1000);
         }
@@ -621,35 +731,78 @@ public class DrawingWindow {
         colorMap = Collections.unmodifiableMap(m);
     }
 
+    private static int instances = 0;
+
     private final String title; // window's title
     private JFrame frame;       // the frame (window)
     private DWPanel panel;      // the panel showing the image
     private BufferedImage image; // the image we draw into
     private Graphics2D graphics; // graphics associated with image
     private Color bgColor;       // background color, for clearGraph()
+    private boolean isClosed;    // is the window closed ?
+    private Object mouseLock;       // lock for mouse events
+    private MouseEvent mouseEvent;  // last mouse event
+    private Point mousePos;         // last mouse position
+    private int mouseButton;        // last mouse click
 
     // To be run on the Event Dispatching Thread
     void createGUI() {
-        panel = new DWPanel(this);
-
+        panel = new DWPanel();
         frame = new JFrame(title);
         frame.add(panel);
         frame.pack();
         frame.setResizable(false);
         frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
-        frame.addKeyListener(panel);
+        frame.addWindowListener(new DWWindowHandler());
+        frame.addKeyListener(new DWKeyHandler());
+        panel.addMouseListener(new DWMouseHandler());
         frame.setLocationByPlatform(true);
         frame.setVisible(true);
     }
 
-    private class DWPanel extends JPanel implements KeyListener {
+    private class DWWindowHandler extends WindowAdapter {
+        public void windowOpened(WindowEvent ev) {
+            DrawingWindow w = DrawingWindow.this;
+            DrawingWindow.instances++;
+            w.isClosed = false;
+        }
 
-        private static final long serialVersionUID = 0;
+        public void windowClosed(WindowEvent ev) {
+            DrawingWindow w = DrawingWindow.this;
+            if (!w.isClosed) {
+                w.isClosed = true;
+                if (DrawingWindow.instances <= 0)
+                    throw new AssertionError("Bad instance counter: " +
+                                             DrawingWindow.instances);
+                DrawingWindow.instances--;
+                if (DrawingWindow.instances == 0)
+                    System.exit(0);
+            }
+        }
+    }
 
-        final DrawingWindow w;
+    private class DWKeyHandler extends KeyAdapter {
+        public void keyPressed(KeyEvent ev) {
+            DrawingWindow w = DrawingWindow.this;
+            if (ev.getKeyCode() == KeyEvent.VK_ESCAPE) {
+                w.closeGraph();
+            }
+        }
+    }
+
+    private class DWMouseHandler extends MouseAdapter {
+        public void mousePressed(MouseEvent ev) {
+            DrawingWindow w = DrawingWindow.this;
+            synchronized (w.mouseLock) {
+                w.mouseEvent = ev;
+                mouseLock.notifyAll();
+            }
+        }
+    }
 
-        DWPanel(DrawingWindow w) {
-            this.w = w;
+    private class DWPanel extends JPanel {
+        DWPanel() {
+            DrawingWindow w = DrawingWindow.this;
             Dimension dimension = new Dimension(w.width, w.height);
             super.setMinimumSize(dimension);
             super.setMaximumSize(dimension);
@@ -657,19 +810,12 @@ public class DrawingWindow {
         }
 
         public void paint(Graphics g) {
+            DrawingWindow w = DrawingWindow.this;
             synchronized (w.image) {
                 g.drawImage(w.image, 0, 0, null);
             }
         }
 
-        public void keyPressed(KeyEvent e) {
-            if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
-                w.closeGraph();
-            }
-        }
-
-        public void keyReleased(KeyEvent e) { }
-        public void keyTyped(KeyEvent e) { }
-
+        private static final long serialVersionUID = 0;
     }
 }