Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/jempeg/empeg/emplode/dialog/EmpegScreen.java


1   /**
2   * Copyright (c) 2001, Mike Schrag & Daniel Zimmerman
3   * All rights reserved.
4   *
5   * Redistribution and use in source and binary forms, with or without
6   * modification, are permitted provided that the following conditions are met:
7   *
8   * Redistributions of source code must retain the above copyright notice,
9   * this list of conditions and the following disclaimer.
10  *
11  * Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * Neither the name of Mike Schrag, Daniel Zimmerman, nor the names of any
16  * other contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31  package org.jempeg.empeg.emplode.dialog;
32  
33  import org.jempeg.empeg.logoedit.LogoFormatUtils;
34  import org.jempeg.empeg.protocol.ProtocolClient;
35  import org.jempeg.util.Debug;
36  
37  import javax.swing.JComponent;
38  import javax.swing.AbstractAction;
39  
40  import java.awt.Color;
41  import java.awt.Dimension;
42  import java.awt.Graphics;
43  import java.awt.Rectangle;
44  import java.awt.event.ActionEvent;
45  import java.awt.event.WindowAdapter;
46  import java.awt.event.WindowEvent;
47  import java.awt.event.WindowListener;
48  import java.io.IOException;
49  
50  /**
51  * An EmpegScreen is a renderer for the GrabScreenPacket.  This basically grabs
52  * the bytes off of the Empeg's screen and displays them in a JComponent of
53  * configurable size.
54  *
55  * @author Mike Schrag
56  * @version $Revision: 1.7 $
57  */
58  public class EmpegScreen extends JComponent {
59    public static Color[] DEFAULT_COLORS = new Color[16];
60  
61    static {
62      // I stepped the color faster up the grayscale, because it was _REALLY_ dark on my screen with the correct stepping
63      int step = 50;
64      for (int i = 0; i < DEFAULT_COLORS.length; i ++) {
65        DEFAULT_COLORS[i] = new Color(Math.min(i * step, 255), Math.min(i * step, 255), Math.min(i * step, 255));
66      }
67    }
68        
69    private ProtocolClient myClient;
70    private Object myLock;
71    private byte[] myScreen;
72    private int myPixelSize;
73    private Color[] myColors;
74    private boolean myGrabbing;
75    private boolean myStopGrabbing;
76    
77      /**
78      * Creates an EmpegScreen without grabbing, a pixel size of 2, and the default colorset (grayscale)
79      */
80    public EmpegScreen(ProtocolClient _client) throws IOException {
81      this(_client, DEFAULT_COLORS, 2, -1);
82    }
83    
84      /**
85      * Creates an EmpegScreen without grabbing and with the default colorset (grayscale)
86      */
87    public EmpegScreen(ProtocolClient _client, int _pixelSize) throws IOException {
88      this(_client, DEFAULT_COLORS, _pixelSize, -1);
89    }
90    
91      /**
92      * Creates an EmpegScreen with grabbing, but with the default colorset (grayscale)
93      */
94    public EmpegScreen(ProtocolClient _client, int _pixelSize, int _millisBetweenGrabs) throws IOException {
95      this(_client, DEFAULT_COLORS, _pixelSize, _millisBetweenGrabs);
96    }
97    
98      /**
99      * Creates an EmpegScreen without timed grabbing
100     */
101   public EmpegScreen(ProtocolClient _client, Color[] _colors, int _pixelSize) throws IOException {
102     this(_client, _colors, _pixelSize, -1);
103   }
104   
105     /**
106     * Creates an EmpegScreen.  If _millisBetweenGrabs is greater than -1, then startGrabbing is automatically called.
107     *
108     * @param _client              The ProtocolClient that this can use to grab the Empeg screen
109     * @param _colors              A color array going from dark to light of length 16
110     * @param _pixelSize            The number of pixels that each Empeg pxiel should be represented as onscreen
111     * @param _millisBetweenGrabs  The number of milliseconds between each screen grab (-1 will turn off timed grabbing)
112     */
113   public EmpegScreen(ProtocolClient _client, Color[] _colors, int _pixelSize, int _millisBetweenGrabs) throws IOException {
114     this(_colors, _pixelSize);
115     myLock = new Object();
116     myClient = _client;
117     if (_millisBetweenGrabs == -1) {
118       grabScreen();
119     } else {
120       startGrabbing(_millisBetweenGrabs);
121     }
122   }
123 
124     /**
125     * Creates an EmpegScreen with a prebuilt byte array.
126     *
127     * @array _screen    The bytes of the screen (2048 bytes long)
128     * @array _colors    A color array going from dark to light of length 16
129     * @array _pixelSize  The number of pixels that each Empeg pxiel should be represented as onscreen
130     */
131   public EmpegScreen(byte[] _screen, Color[] _colors, int _pixelSize) {
132     this(_colors, _pixelSize);
133     myScreen = _screen;
134   }
135 
136   protected EmpegScreen(Color[] _colors, int _pixelSize) {
137     if (_colors.length != 16) {
138       throw new RuntimeException("Color array must be exactly 16 colors long.");
139     }
140     myLock = new Object();
141     myColors = _colors;
142     myPixelSize = _pixelSize;
143     setBackground(Color.black);
144   }
145     
146     /**
147     * Stops grabbing screens from the ProtocolClient
148     */
149   public void stopGrabbing() {
150     myStopGrabbing = true;
151   }
152   
153     /**
154     * Starts grabbing screens from the ProtocolClient.
155     */
156   public void startGrabbing(int _millisBetweenGrabs) {
157     myGrabbing = true;
158     myStopGrabbing = false;
159     ScreenUpdater su = new ScreenUpdater(_millisBetweenGrabs);
160     Thread t = new Thread(su);
161     t.start();
162   }
163   
164     /**
165     * Grabs a screen from the ProtocolClient.
166     */
167   public void grabScreen() throws IOException {
168     synchronized (myLock) {
169       myScreen = myClient.grabScreen();
170       repaint();
171     }
172   }
173   
174   public void paintComponent(Graphics _g) {
175     synchronized (myLock) {
176       _g.setColor(getBackground());
177       Rectangle r = getBounds();
178       _g.fillRect(0, 0, r.width, r.height);
179       if (myScreen != null) {
180         for (int y = 0; y < 32; y ++) {
181           for (int x = 0; x < 128; x ++) {
182             int value = LogoFormatUtils.from4bpp(myScreen, x, y);
183             r.setBounds((x * myPixelSize) + x + 1, (y * myPixelSize) + y + 1, myPixelSize, myPixelSize);
184             
185             _g.setColor(myColors[value]);
186             _g.fillRect(r.x, r.y, r.width, r.height);
187           }
188         }
189       }
190     }
191   }
192   
193   public Dimension getPreferredSize() {
194     return new Dimension(myPixelSize * 128 + 129, myPixelSize * 32 + 33);
195   }
196   
197   protected class ScreenUpdater implements Runnable {
198     private int myMillisBetweenGrabs;
199     
200     public ScreenUpdater(int _millisBetweenGrabs) {
201       myMillisBetweenGrabs = _millisBetweenGrabs;
202     }
203     
204     public void run() {
205       while (!myStopGrabbing) {
206         try {
207           Thread.sleep(myMillisBetweenGrabs);
208         } catch (Exception e) {
209         }
210         
211         try {
212           EmpegScreen.this.grabScreen();
213         }
214           catch (IOException e) {
215             Debug.println(e);
216           }
217       }
218       myGrabbing = false;
219     }
220   }
221   
222   /**
223   * Creates an AbstractAction that will regrab this EmpegScreen.  Use this to easily hook
224   * the screen updating up to a JButton (for instance)
225   */
226   public AbstractAction createGrabAction() {
227     return new AbstractAction() {
228       public void actionPerformed(ActionEvent _event) {
229         try {
230           EmpegScreen.this.grabScreen();
231         }
232           catch (IOException e) {
233             Debug.println(e);
234           }
235       }
236     };
237   }
238   
239   /**
240   * Creates an AbstractAction that will regrab this EmpegScreen.  Use this to easily hook
241   * the screen updating up to a JButton (for instance)
242   */
243   public AbstractAction createRepeatingGrabAction() {
244     return new AbstractAction() {
245       public void actionPerformed(ActionEvent _event) {
246         if (!EmpegScreen.this.myGrabbing) { 
247           EmpegScreen.this.startGrabbing(1000);
248         } else{
249           EmpegScreen.this.stopGrabbing();
250         }
251       }
252     };
253   }
254   
255   /**
256   * Creates a WindowListener that will stop grabbing on shutdown.
257   */
258   public WindowListener createStopGrabbingWindowListener() {
259     return new WindowAdapter() {
260       public void windowClosed(WindowEvent _event) {
261         EmpegScreen.this.stopGrabbing();
262       }
263     };
264   }
265 }