All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.microemu.app.ui.swt.SwtDeviceComponent Maven / Gradle / Ivy

There is a newer version: 2.0.4
Show newest version
/*
 *  MicroEmulator
 *  Copyright (C) 2001-2003 Bartek Teodorczyk 
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package org.microemu.app.ui.swt;

import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;

import javax.microedition.lcdui.Command;

import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontMetrics;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.microemu.CommandManager;
import org.microemu.DisplayComponent;
import org.microemu.MIDletBridge;
import org.microemu.device.Device;
import org.microemu.device.DeviceFactory;
import org.microemu.device.impl.Rectangle;
import org.microemu.device.impl.SoftButton;
import org.microemu.device.swt.SwtButton;
import org.microemu.device.swt.SwtDeviceDisplay;
import org.microemu.device.swt.SwtImmutableImage;
import org.microemu.device.swt.SwtInputMethod;



public class SwtDeviceComponent extends Canvas
{
	private static SwtDeviceComponent instance;
	private static HashMap colors = new HashMap();

	private SwtDisplayComponent dc;
	
	private Image fBuffer = null;

	private SwtButton prevOverButton;
	private SwtButton overButton;
	private SwtButton pressedButton;
	
	private SoftButton initialPressedSoftButton;

	private boolean mousePressed;
  
  KeyListener keyListener = new KeyListener()
  {
		public void keyPressed(KeyEvent ev)
		{
	    	if (MIDletBridge.getCurrentMIDlet() == null) {
	    		return;
	    	}

	    	Device device = DeviceFactory.getDevice();
	    	
			for (Iterator it = device.getButtons().iterator(); it.hasNext(); ) {
				SwtButton button = (SwtButton) it.next();
				if (ev.keyCode == button.getKeyboardKey()) {
					ev.keyCode = button.getKeyCode();
					break;
				}
			}
	    		    	
	    	((SwtInputMethod) device.getInputMethod()).keyPressed(ev);
			
			pressedButton = ((SwtInputMethod) device.getInputMethod()).getButton(ev);
			if (pressedButton != null) {
				org.microemu.device.impl.Shape shape = pressedButton.getShape();
				if (shape != null) {
					Rectangle r = shape.getBounds();
		  			redraw(r.x, r.y, r.width, r.height, true);
				}
			} else {
				redraw();
			}
		}   
	  
		public void keyReleased(KeyEvent ev)
		{
	    	if (MIDletBridge.getCurrentMIDlet() == null) {
	    		return;
	    	}

	    	Device device = DeviceFactory.getDevice();
	    	
			for (Iterator it = device.getButtons().iterator(); it.hasNext(); ) {
				SwtButton button = (SwtButton) it.next();
				if (ev.keyCode == button.getKeyboardKey()) {
					ev.keyCode = button.getKeyCode();
					break;
				}
			}

			((SwtInputMethod) device.getInputMethod()).keyReleased(ev);
			
			prevOverButton = pressedButton;
			pressedButton = null;
			if (prevOverButton != null) {
				org.microemu.device.impl.Shape shape = prevOverButton.getShape();
				if (shape != null) {
					Rectangle r = shape.getBounds();
		  			redraw(r.x, r.y, r.width, r.height, true);
				}
			} else {
				redraw();
			}
		}   
  };
  
	MouseAdapter mouseListener = new MouseAdapter() 
	{    
		public void mouseDown(MouseEvent e) 
		{
	    	if (MIDletBridge.getCurrentMIDlet() == null) {
	    		return;
	    	}
	    	
			Device device = DeviceFactory.getDevice();
			org.microemu.device.impl.Rectangle rect = ((SwtDeviceDisplay) device.getDeviceDisplay()).getDisplayRectangle();
			SwtInputMethod inputMethod = (SwtInputMethod) device.getInputMethod();
			// if the displayable is in full screen mode, we should not
			// invoke any associated commands, but send the raw key codes
			// instead
			boolean fullScreenMode = device.getDeviceDisplay().isFullScreenMode();

			if (rect.x <= e.x && (rect.x + rect.width) > e.x
					&& rect.y <= e.y && (rect.y + rect.height) > e.y) {
				if (device.hasPointerEvents()) {
					if (!fullScreenMode) {
						Iterator it = device.getSoftButtons().iterator();
						while (it.hasNext()) {
							SoftButton button = (SoftButton) it.next();
							if (button.isVisible()) {
								org.microemu.device.impl.Rectangle pb = button.getPaintable();
								if (pb != null && pb.contains(e.x - rect.x, e.y - rect.y)) {
									initialPressedSoftButton = button;
									button.setPressed(true);
									dc.repaintRequest(pb.x, pb.y, pb.width, pb.height);
									break;
								}
							}
						}
					}
					if (fullScreenMode) {
						inputMethod.pointerPressed(e.x - rect.x, e.y - rect.y);
					} else {
						org.microemu.device.impl.Rectangle pb = ((SwtDeviceDisplay) device.getDeviceDisplay()).getDisplayPaintable();
						inputMethod.pointerPressed(e.x - rect.x - pb.x, e.y - rect.y - pb.y);
					}
				}
			} else {
		    	pressedButton = getButton(e.x, e.y);	
				if (pressedButton != null) {
					if (pressedButton instanceof SoftButton && !fullScreenMode) {
						Command cmd = ((SoftButton) pressedButton).getCommand();
						if (cmd != null) {
							CommandManager.getInstance().commandAction(cmd);
						}
					} else {
						Event event = new Event();
						event.widget = e.widget;
						KeyEvent ev = new KeyEvent(event);
						ev.keyCode = pressedButton.getKeyCode();
						inputMethod.mousePressed(ev);
					}
					// optimize for some video cards.
					Rectangle r = pressedButton.getShape().getBounds();
					redraw(r.x, r.y, r.width, r.height, true);
				}
			}
			
			mousePressed = true;
		}

		public void mouseUp(MouseEvent e) 
		{
	    	if (MIDletBridge.getCurrentMIDlet() == null) {
	    		return;
	    	}

			Device device = DeviceFactory.getDevice();
			org.microemu.device.impl.Rectangle rect = ((SwtDeviceDisplay) device.getDeviceDisplay()).getDisplayRectangle();
			SwtInputMethod inputMethod = (SwtInputMethod) device.getInputMethod();
			boolean fullScreenMode = device.getDeviceDisplay().isFullScreenMode();
			if (rect.x <= e.x && (rect.x + rect.width) > e.x
					&& rect.y <= e.y && (rect.y + rect.height) > e.y) {
				if (device.hasPointerEvents()) {
					if (!fullScreenMode) {
						if (initialPressedSoftButton != null && initialPressedSoftButton.isPressed()) {
							initialPressedSoftButton.setPressed(false);
							org.microemu.device.impl.Rectangle pb = initialPressedSoftButton.getPaintable();
							if (pb != null) {
								dc.repaintRequest(pb.x, pb.y, pb.width, pb.height);
								if (pb.contains(e.x - rect.x, e.y - rect.y)) {
									Command cmd = initialPressedSoftButton.getCommand();
									if (cmd != null) {
										CommandManager.getInstance().commandAction(cmd);
									}
								}
							}
						}
						initialPressedSoftButton = null;
					}
					if (fullScreenMode) {
						inputMethod.pointerReleased(e.x - rect.x, e.y - rect.y);
					} else {
						org.microemu.device.impl.Rectangle pb = ((SwtDeviceDisplay) device.getDeviceDisplay()).getDisplayPaintable();
						inputMethod.pointerReleased(e.x - rect.x - pb.x, e.y - rect.y - pb.y);
					}
				}
			} else {
		    	SwtButton prevOverButton = getButton(e.x, e.y);
				if (prevOverButton != null) {
					inputMethod.mouseReleased(prevOverButton.getKeyCode());
				}
				pressedButton = null;
				//	optimize for some video cards.
				if (prevOverButton != null) {
					Rectangle r = prevOverButton.getShape().getBounds();
					redraw(r.x, r.y, r.width, r.height, true);
				} else {
					redraw();
				}
			}
			
			mousePressed = false;
		}
	};
  

	MouseMoveListener mouseMoveListener = new MouseMoveListener() 
	{
		public void mouseMove(MouseEvent e)
		{
			prevOverButton = overButton;
			overButton = getButton(e.x, e.y);
			if (overButton != prevOverButton) {
	      		// optimize for some video cards.
	      		if (prevOverButton != null) {
	      			Rectangle r = prevOverButton.getShape().getBounds();
	      			redraw(r.x, r.y, r.width, r.height, true);
	      		}
	      		if (overButton != null) {
	      			Rectangle r = overButton.getShape().getBounds();
	      			redraw(r.x, r.y, r.width, r.height, true);
	      		}
			}
			
			if (mousePressed) {
				Device device = DeviceFactory.getDevice();
				org.microemu.device.impl.Rectangle rect = ((SwtDeviceDisplay) device.getDeviceDisplay()).getDisplayRectangle();
				SwtInputMethod inputMethod = (SwtInputMethod) device.getInputMethod();
				boolean fullScreenMode = device.getDeviceDisplay().isFullScreenMode();
				if (rect.x <= e.x && (rect.x + rect.width) > e.x
						&& rect.y <= e.y && (rect.y + rect.height) > e.y) {
					if (device.hasPointerMotionEvents()) {
						if (!fullScreenMode) {
							if (initialPressedSoftButton != null) {
								org.microemu.device.impl.Rectangle pb = initialPressedSoftButton.getPaintable();
								if (pb != null) {
									if (pb.contains(e.x - rect.x, e.y - rect.y)) {
										if (!initialPressedSoftButton.isPressed()) {
											initialPressedSoftButton.setPressed(true);
											dc.repaintRequest(pb.x, pb.y, pb.width, pb.height);
										}
									} else {
										if (initialPressedSoftButton.isPressed()) {
											initialPressedSoftButton.setPressed(false);
											dc.repaintRequest(pb.x, pb.y, pb.width, pb.height);
										}
									}
								}
							}
						}
						if (fullScreenMode) {
							inputMethod.pointerDragged(e.x - rect.x, e.y - rect.y);
						} else {
							org.microemu.device.impl.Rectangle pb = ((SwtDeviceDisplay) device.getDeviceDisplay()).getDisplayPaintable();
							inputMethod.pointerDragged(e.x - rect.x - pb.x, e.y - rect.y - pb.y);
						}
					}
				}
			}
		}    
	};
  
  
	public SwtDeviceComponent(Composite parent) 
	{
		super(parent, SWT.NO_BACKGROUND);
		instance = this;
		mousePressed = false;
    
		dc = new SwtDisplayComponent(this);    
    
	    this.initialPressedSoftButton = null;

	    addKeyListener(keyListener);
		addMouseListener(mouseListener);
		addMouseMoveListener(mouseMoveListener);
		addPaintListener(new PaintListener() 
		{
			public void paintControl(PaintEvent e) 
			{
				SwtDeviceComponent.this.paintControl(e);
			}
		});
	}
  
  
	public DisplayComponent getDisplayComponent()
	{
		return dc;
	}
  
  
	public Point computeSize(int wHint, int hHint, boolean changed)
	{
		javax.microedition.lcdui.Image tmp = DeviceFactory.getDevice().getNormalImage();

		return new Point(tmp.getWidth(), tmp.getHeight());		
	}
							 
  
	public void paintControl(PaintEvent pe) 
	{
		Point size= getSize();

		if (size.x <= 0 || size.y <= 0)
		 return;

		if (fBuffer != null) {
			org.eclipse.swt.graphics.Rectangle r= fBuffer.getBounds();
			if (r.width != size.x || r.height != size.y) {
			fBuffer.dispose();
			fBuffer= null;
			}
		}
		if (fBuffer == null) {
			fBuffer= new Image(getDisplay(), size.x, size.y);
		}

		SwtGraphics gc = new SwtGraphics(new GC(fBuffer));
		try {
			Device device = DeviceFactory.getDevice();
			
			gc.drawImage(((SwtImmutableImage) device.getNormalImage()).getImage()
			        , 0, 0);
    
			org.microemu.device.impl.Rectangle displayRectangle = 
					((SwtDeviceDisplay) device.getDeviceDisplay()).getDisplayRectangle();
			gc.translate(displayRectangle.x, displayRectangle.y);
			dc.paint(gc);
			gc.translate(-displayRectangle.x, -displayRectangle.y);

	    	if (prevOverButton != null) {
				org.microemu.device.impl.Shape shape = prevOverButton.getShape();
				if (shape != null) {
					drawImageInShape(
							gc, 
							((SwtImmutableImage) device.getNormalImage()).getImage(), 
							shape);
				}
				prevOverButton = null;
			}
			if (overButton != null) {
				org.microemu.device.impl.Shape shape = overButton.getShape();
				if (shape != null) {
					drawImageInShape(
							gc, 
							((SwtImmutableImage) device.getOverImage()).getImage(), 
							shape);
				}
			}
			if (pressedButton != null) {
				org.microemu.device.impl.Shape shape = pressedButton.getShape();
				if (shape != null) {
					drawImageInShape(
							gc, 
							((SwtImmutableImage) device.getPressedImage()).getImage(), 
							shape);
				}
			}

			org.microemu.device.impl.Rectangle rect;
			if (prevOverButton != null ) {				
				rect = prevOverButton.getShape().getBounds();
				if (rect != null) {
					gc.drawImage(((SwtImmutableImage) DeviceFactory.getDevice().getNormalImage()).getImage(), 
							rect.x, rect.y, rect.width, rect.height,
							rect.x, rect.y, rect.width, rect.height);
				}
				prevOverButton = null;
			}
			if (overButton != null) {
				rect = overButton.getShape().getBounds();
				if (rect != null) {
					gc.drawImage(((SwtImmutableImage) DeviceFactory.getDevice().getOverImage()).getImage(), 
							rect.x, rect.y, rect.width, rect.height,
							rect.x, rect.y, rect.width, rect.height);
				}
			}
			if (pressedButton != null) {
				rect = pressedButton.getShape().getBounds();
				if (rect != null) {
					gc.drawImage(((SwtImmutableImage) DeviceFactory.getDevice().getPressedImage()).getImage(), 
							rect.x, rect.y, rect.width, rect.height,
							rect.x, rect.y, rect.width, rect.height);
				}
			}
		} finally {
			gc.dispose();
		}
		
		pe.gc.drawImage(fBuffer, 0, 0);
	}


  	private void drawImageInShape(SwtGraphics g, Image image, org.microemu.device.impl.Shape shape) {
  		org.eclipse.swt.graphics.Rectangle clipSave = g.getClipping();
		if (shape instanceof org.microemu.device.impl.Polygon) {
			// TODO not implemented yet
//			g.setCliping(region);
		}
		org.microemu.device.impl.Rectangle r = shape.getBounds();
		g.drawImage(image, 
				r.x, r.y, r.width, r.height,
				r.x, r.y, r.width, r.height);
		g.setClipping(clipSave);
	}
  	
  	
	private SwtButton getButton(int x, int y)
	{
		for (Enumeration e = DeviceFactory.getDevice().getButtons().elements(); e.hasMoreElements(); ) {
			SwtButton button = (SwtButton) e.nextElement();
			if (button.getShape() != null) {
				try {
					org.microemu.device.impl.Shape tmp = (org.microemu.device.impl.Shape) button.getShape().clone();
				      if (tmp.contains(x, y)) {
				    	  return button;
				      }
				} catch (CloneNotSupportedException ex) {
					ex.printStackTrace();
				}
			}
		}        
		return null;
	}

  
	private class CreateImageRunnable implements Runnable
	{
		private ImageData data;
		private Image image;
		
		CreateImageRunnable(ImageData data)
		{
			this.data = data;
		}
		
		Image getImage()
		{
			return image;
		}
			
		public void run() 
		{
			image = new Image(instance.getParent().getDisplay(), data);
		}		
	}
	
	
	public static Image createImage(int width, int height)
	{
		return new Image(instance.getDisplay(), width, height);
	}


	public static Image createImage(Image image)
	{
		return new Image(instance.getDisplay(), image, SWT.IMAGE_COPY);
	}
	
	
	public static Image createImage(ImageData data)
	{
		CreateImageRunnable createImageRunnable = instance.new CreateImageRunnable(data);		
		instance.getDisplay().syncExec(createImageRunnable); 
		
		return createImageRunnable.getImage(); 
	}

	
	public static Image createImage(InputStream is) 
	{
		ImageData data = new ImageData(is);
			
		CreateImageRunnable createImageRunnable = instance.new CreateImageRunnable(data);		
		instance.getDisplay().syncExec(createImageRunnable); 
		
		return createImageRunnable.getImage(); 
	}
	
	
	public static Image createImage(InputStream is, ImageFilter filter)
			throws IOException
	{
		try {
			ImageData data = new ImageData(is);
		
			RGB[] rgbs = data.getRGBs();
			if (rgbs != null) {	
				for (int i = 0; i < rgbs.length; i++) {
					rgbs[i] = filter.filterRGB(0, 0, rgbs[i]);
				}
			} else {
				RGB rgb;
				int pixel;
				for (int y = 0; y < data.height; y++) {
					for (int x = 0; x < data.width; x++) {
						pixel = data.getPixel(x, y);
						rgb = new RGB((pixel >> 16) & 255, (pixel >> 8) & 255, pixel & 255);
						rgb = filter.filterRGB(x, y, rgb);					
						data.setPixel(x, y, (rgb.red << 16) + (rgb.green << 8) + rgb.blue);
					}
				}
			}		
				
			CreateImageRunnable createImageRunnable = instance.new CreateImageRunnable(data);		
			instance.getDisplay().syncExec(createImageRunnable); 
			
			return createImageRunnable.getImage(); 
		} catch (SWTException ex) {
			throw new IOException(ex.toString());
		}
	}
	
	
	private class CreateColorRunnable implements Runnable
	{
		private RGB rgb;
		private Color color;
		
		CreateColorRunnable(RGB rgb)
		{
			this.rgb = rgb;
		}
		
		Color getColor()
		{
			return color;
		}
			
		public void run() 
		{
			color = new Color(instance.getParent().getDisplay(), rgb);
		}		
	}


	public static Color getColor(RGB rgb) 
	{
		Color result = (Color) colors.get(rgb);
		
		if (result == null) {
			CreateColorRunnable createColorRunnable = instance.new CreateColorRunnable(rgb);		
			instance.getDisplay().syncExec(createColorRunnable); 		
			result = createColorRunnable.getColor();
			colors.put(rgb, result);
		}
		
		return result;
	}


	private class GetFontMetricsRunnable implements Runnable
	{
		private Font font;
		private FontMetrics fontMetrics;
		
		GetFontMetricsRunnable(Font font)
		{
			this.font = font;
		}
		
		FontMetrics getFontMetrics()
		{
			return fontMetrics;
		}
			
		public void run() 
		{
			SwtGraphics gc = new SwtGraphics(instance.getParent().getDisplay());
			gc.setFont(font);
			fontMetrics = gc.getFontMetrics();
			gc.dispose();
		}		
	}


	private class GetFontRunnable implements Runnable
	{
		private String name;
		private int size;
		private int style;
		private boolean antialiasing;
		private Font font;
		
		GetFontRunnable(String name, int size, int style, boolean antialiasing)
		{
			this.name = name;
			this.size = size;
			this.style = style;
		}
		
		Font getFont()
		{
			return font;
		}
			
		public void run() 
		{
			SwtGraphics gc = new SwtGraphics(instance.getParent().getDisplay());
			gc.setAntialias(antialiasing);
			gc.setFont(new Font(instance.getParent().getDisplay(), name, size, style));
			font = gc.getFont();
			gc.dispose();
		}		
	}


	private class StringWidthRunnable implements Runnable
	{
		private Font font;
		private String str;
		private int stringWidth;
		
		StringWidthRunnable(Font font, String str)
		{
			this.font = font;
			this.str = str;
		}
		
		int stringWidth()
		{
			return stringWidth;
		}
			
		public void run() 
		{
			SwtGraphics gc = new SwtGraphics(instance.getParent().getDisplay());
			gc.setFont(font);
			stringWidth = gc.stringWidth(str);
			gc.dispose();
		}		
	}


	public static Font getFont(String name, int size, int style, boolean antialiasing) 
	{
		GetFontRunnable getFontRunnable = instance.new GetFontRunnable(name, size, style, antialiasing);
		
		instance.getDisplay().syncExec(getFontRunnable); 
		
		return getFontRunnable.getFont(); 
	}


	public static FontMetrics getFontMetrics(Font font) 
	{
		GetFontMetricsRunnable getFontMetricsRunnable = instance.new GetFontMetricsRunnable(font);
		
		instance.getDisplay().syncExec(getFontMetricsRunnable); 
		
		return getFontMetricsRunnable.getFontMetrics(); 
	}
	
	
	public static int stringWidth(Font font, String str)
	{
		StringWidthRunnable stringWidthRunnable = instance.new StringWidthRunnable(font, str);
		
		instance.getDisplay().syncExec(stringWidthRunnable); 

		return stringWidthRunnable.stringWidth(); 
	}
  
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy