Send clicks to monitor panel to Lua (for instance for mouse emulation)
[jpcrr.git] / org / jpc / pluginsaux / PCMonitorPanel.java
blob88bf990d6035cd4915d9330d2a34d9ab5d556e33
1 /*
2 JPC-RR: A x86 PC Hardware Emulator
3 Release 1
5 Copyright (C) 2007-2009 Isis Innovation Limited
6 Copyright (C) 2009-2010 H. Ilari Liusvaara
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License version 2 as published by
10 the Free Software Foundation.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 Based on JPC x86 PC Hardware emulator,
22 A project from the Physics Dept, The University of Oxford
24 Details about original JPC can be found at:
26 www-jpc.physics.ox.ac.uk
30 package org.jpc.pluginsaux;
32 import java.awt.*;
33 import java.util.*;
34 import java.awt.event.ActionListener;
35 import java.awt.event.MouseListener;
36 import java.awt.event.ActionEvent;
37 import java.awt.event.MouseEvent;
38 import javax.swing.*;
39 import org.jpc.pluginsbase.Plugins;
40 import org.jpc.pluginsbase.Plugin;
41 import org.jpc.pluginsaux.HUDRenderer;
42 import java.io.*;
43 import java.awt.image.BufferedImage;
44 import java.awt.image.DataBufferInt;
45 import org.jpc.emulator.VGADigitalOut;
46 import org.jpc.emulator.*;
47 import org.jpc.output.*;
48 import static org.jpc.Misc.errorDialog;
49 import org.jpc.pluginsaux.PNGSaver;
51 /**
53 * @author Rhys Newman
55 public class PCMonitorPanel implements ActionListener, MouseListener
57 private static final long serialVersionUID = 6;
58 private OutputStatic outputServer;
59 private PC pc;
60 private OutputClient outputClient;
61 private volatile boolean signalCheck;
62 private BufferedImage buffer;
63 private int ssSeq;
64 private int[] renderBuffer;
65 private int renderBufferW;
66 private int renderBufferH;
67 private int[] rawImageData;
68 private int screenWidth, screenHeight;
69 private MonitorPanel monitorPanel;
70 private Thread monitorThread;
71 private HUDRenderer renderer;
72 private PCMonitorPanelEmbedder embedder;
73 private java.util.List<JMenu> menusNeeded;
74 private OutputFrameImage lastFrame;
76 private volatile boolean clearBackground;
78 public PCMonitorPanel(PCMonitorPanelEmbedder embedWhere, OutputStatic serv)
80 clearBackground = true;
81 monitorPanel = new MonitorPanel();
82 monitorPanel.setDoubleBuffered(false);
83 monitorPanel.requestFocusInWindow();
84 outputServer = serv;
85 outputClient = new OutputClient(serv);
87 monitorPanel.setInputMap(JPanel.WHEN_FOCUSED, null);
89 embedder = embedWhere;
90 renderer = new HUDRenderer(1);
91 embedder.notifyRenderer(renderer);
92 menusNeeded = new ArrayList<JMenu>();
93 JMenu lamp;
94 JMenuItem lampx;
96 menusNeeded.add(lamp = new JMenu("Gain"));
98 lampx = new JMenuItem("1x");
99 lampx.setActionCommand("LAMP1X");
100 lampx.addActionListener(this);
101 lamp.add(lampx);
103 lampx = new JMenuItem("2x");
104 lampx.setActionCommand("LAMP2X");
105 lampx.addActionListener(this);
106 lamp.add(lampx);
108 lampx = new JMenuItem("4x");
109 lampx.setActionCommand("LAMP4X");
110 lampx.addActionListener(this);
111 lamp.add(lampx);
113 lampx = new JMenuItem("8x");
114 lampx.setActionCommand("LAMP8X");
115 lampx.addActionListener(this);
116 lamp.add(lampx);
118 lampx = new JMenuItem("16x");
119 lampx.setActionCommand("LAMP16X");
120 lampx.addActionListener(this);
121 lamp.add(lampx);
123 lampx = new JMenuItem("32x");
124 lampx.setActionCommand("LAMP32X");
125 lampx.addActionListener(this);
126 lamp.add(lampx);
128 menusNeeded.add(lamp = new JMenu("Screenshot"));
130 lampx = new JMenuItem("VGA output buffer");
131 lampx.setActionCommand("SSVGAOUT");
132 lampx.addActionListener(this);
133 lamp.add(lampx);
135 lampx = new JMenuItem("render buffer");
136 lampx.setActionCommand("SSRENDER");
137 lampx.addActionListener(this);
138 lamp.add(lampx);
140 monitorPanel.addMouseListener(this);
141 resizeDisplay(480, 360, true);
144 public void eci_screenshot_vgabuffer()
146 screenShot(false);
149 public void eci_screenshot_renderbuffer()
151 screenShot(true);
154 public java.util.List<JMenu> getMenusNeeded()
156 return menusNeeded;
159 public JPanel getMonitorPanel()
161 return monitorPanel;
164 public void startThread()
166 (new Thread(new Runnable() { public void run() { main(); }}, "Monitor Panel Thread")).start();
169 public void setPC(PC _pc)
171 pc = _pc;
174 public void main()
176 monitorThread = Thread.currentThread();
177 while (true) //JVM will kill us.
179 synchronized(this) {
180 if(outputClient.aquire()) {
181 OutputFrame f = outputServer.lastFrame(OutputFrameImage.class);
182 if(f != null)
183 lastFrame = (OutputFrameImage)f;
184 else {
185 outputClient.releaseWaitAll();
186 continue;
188 int w = lastFrame.getWidth();
189 int h = lastFrame.getHeight();
190 embedder.notifyFrameReceived(w, h);
191 int[] buffer = lastFrame.getImageData();
192 renderer.setBackground(buffer, w, h);
193 outputClient.releaseWaitAll();
194 w = renderBufferW = renderer.getRenderWidth();
195 h = renderBufferH = renderer.getRenderHeight();
196 renderBuffer = renderer.getFinishedAndReset();
197 if(w > 0 && h > 0 && (w != screenWidth || h != screenHeight)) {
198 resizeDisplay(w, h, false);
199 embedder.notifySizeChange(w, h);
201 if(renderBuffer == null)
202 continue;
204 for(int y = 0; y < h; y++) {
205 int offset = y * w;
206 if(w > 0)
207 System.arraycopy(renderBuffer, offset, rawImageData, offset, w);
210 monitorPanel.repaint(0, 0, w, h);
216 public void resizeDisplay(int width, int height, boolean repaint)
218 monitorPanel.setPreferredSize(new Dimension(width, height));
219 monitorPanel.setMaximumSize(new Dimension(width, height));
220 monitorPanel.setMinimumSize(new Dimension(width, height));
222 if(width > 0 && height > 0) {
223 buffer = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
224 buffer.setAccelerationPriority(1);
225 DataBufferInt buf = (DataBufferInt) buffer.getRaster().getDataBuffer();
226 rawImageData = buf.getData();
228 screenWidth = width;
229 screenHeight = height;
230 clearBackground = true;
231 monitorPanel.revalidate();
232 if(repaint)
233 monitorPanel.repaint(0, 0, screenWidth, screenHeight);
236 public void actionPerformed(ActionEvent e)
238 String command = e.getActionCommand();
239 if(command == null)
240 return;
241 if(command.equals("LAMP1X"))
242 renderer.setLightAmplification(1);
243 if(command.equals("LAMP2X"))
244 renderer.setLightAmplification(2);
245 if(command.equals("LAMP4X"))
246 renderer.setLightAmplification(4);
247 if(command.equals("LAMP8X"))
248 renderer.setLightAmplification(8);
249 if(command.equals("LAMP16X"))
250 renderer.setLightAmplification(16);
251 if(command.equals("LAMP32X"))
252 renderer.setLightAmplification(32);
253 if(command.equals("SSVGAOUT"))
254 screenShot(false);
255 if(command.equals("SSRENDER"))
256 screenShot(true);
259 private void screenShot(boolean asRendered)
261 int w = 0;
262 int h = 0;
263 int[] buffer = null;
265 if(asRendered) {
266 w = renderBufferW;
267 h = renderBufferH;
268 buffer = renderBuffer;
269 } else {
270 if(lastFrame != null) {
271 w = lastFrame.getWidth();
272 h = lastFrame.getHeight();
273 buffer = lastFrame.getImageData();
274 if(w * h > buffer.length) {
275 System.err.println("Error: Can't get stable VGA output buffer.");
276 return;
280 if(buffer == null || w == 0 || h == 0) {
281 System.err.println("Error: No image to screenshot.");
282 return;
286 String name = "Screenshot-" + System.currentTimeMillis() + "-" + (ssSeq++) + ".png";
287 try {
288 DataOutputStream out = new DataOutputStream(new FileOutputStream(name));
289 PNGSaver.savePNG(out, buffer, w, h);
290 out.close();
291 } catch(Exception e) {
292 errorDialog(e, "Can't save screenshot", null, "Dismiss");
294 System.err.println("Informative: Screenshot '" + name + "' saved.");
297 public class MonitorPanel extends JPanel
299 private static final long serialVersionUID = 9;
300 public void update(Graphics g)
302 paint(g);
305 public void paint(Graphics g)
307 int s2w, s2h;
308 if(screenHeight > 0 && screenWidth > 0) {
309 s2w = screenWidth;
310 s2h = screenHeight;
311 } else {
312 Dimension s1 = getSize();
313 s2w = s1.width;
314 s2h = s1.height;
316 if (clearBackground)
318 g.setColor(Color.white);
319 Dimension s1 = getSize();
321 if (s1.width > s2w)
322 g.fillRect(s2w, 0, s1.width - s2w, s1.height);
323 if (s1.height > s2h)
324 g.fillRect(0, s2h, s1.width, s1.height - s2h);
325 clearBackground = false;
327 g.drawImage(buffer, 0, 0, null);
328 Dimension s = getSize();
329 g.setColor(getBackground());
330 g.fillRect(s2w, 0, s.width - s2w, s2h);
331 g.fillRect(0, s2h, s.width, s.height - s2h);
335 private int getButtonNumber(MouseEvent e)
337 int button = e.getButton();
338 if(button == MouseEvent.BUTTON1)
339 return 1;
340 else if(button == MouseEvent.BUTTON2)
341 return 2;
342 else if(button == MouseEvent.BUTTON3)
343 return 3;
344 return 0;
347 public void mouseClicked(MouseEvent e)
349 int button = getButtonNumber(e);
350 int x = e.getX();
351 int y = e.getY();
352 embedder.sendMessage("MouseClicked " + button + " " + x + " " + y);
355 public void mouseEntered(MouseEvent e)
359 public void mouseExited(MouseEvent e)
363 public void mousePressed(MouseEvent e)
365 int button = getButtonNumber(e);
366 int x = e.getX();
367 int y = e.getY();
368 embedder.sendMessage("MousePressed " + button + " " + x + " " + y);
371 public void mouseReleased(MouseEvent e)
373 int button = getButtonNumber(e);
374 int x = e.getX();
375 int y = e.getY();
376 embedder.sendMessage("MouseReleased " + button + " " + x + " " + y);