/* QtToolkit.java --
   Copyright (C)  2005  Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath 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
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */

package gnu.java.awt.peer.qt;

import gnu.classpath.Configuration;
import gnu.java.awt.EmbeddedWindow;
import gnu.java.awt.peer.ClasspathFontPeer;
import gnu.java.awt.peer.EmbeddedWindowPeer;
import gnu.java.awt.peer.ClasspathTextLayoutPeer;
import java.awt.AWTEvent;
import java.awt.AWTException;
import java.awt.Button;
import java.awt.Canvas;
import java.awt.Checkbox;
import java.awt.CheckboxMenuItem;
import java.awt.Choice;
import java.awt.Component;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Frame;
import java.awt.Image;
import java.awt.Label;
import java.awt.List;
import java.awt.MenuBar;
import java.awt.Menu;
import java.awt.MenuItem;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.FileDialog;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.awt.PopupMenu;
import java.awt.PrintJob;
import java.awt.Scrollbar;
import java.awt.ScrollPane;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.datatransfer.Clipboard;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragGestureRecognizer;
import java.awt.dnd.DragSource;
import java.awt.dnd.peer.DragSourceContextPeer;
import java.awt.event.AWTEventListener;
import java.awt.image.ColorModel;
import java.awt.image.DirectColorModel;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.awt.im.InputMethodHighlight;
import java.awt.peer.ButtonPeer;
import java.awt.peer.FontPeer;
import java.awt.peer.PanelPeer;
import java.awt.peer.CanvasPeer;
import java.awt.peer.FramePeer; 
import java.awt.peer.PopupMenuPeer;
import java.awt.peer.CheckboxMenuItemPeer;
import java.awt.peer.LabelPeer;
import java.awt.peer.RobotPeer;
import java.awt.peer.CheckboxPeer;
import java.awt.peer.LightweightPeer; 
import java.awt.peer.ScrollPanePeer;
import java.awt.peer.ChoicePeer;        
import java.awt.peer.ListPeer;
import java.awt.peer.ScrollbarPeer;
import java.awt.peer.ComponentPeer;    
import java.awt.peer.MenuBarPeer;
import java.awt.peer.TextAreaPeer;
import java.awt.peer.ContainerPeer;
import java.awt.peer.MenuComponentPeer;
import java.awt.peer.TextComponentPeer;
import java.awt.peer.DialogPeer;
import java.awt.peer.MenuItemPeer;
import java.awt.peer.TextFieldPeer;
import java.awt.peer.FileDialogPeer;
import java.awt.peer.MenuPeer;
import java.awt.peer.WindowPeer;
import java.awt.font.FontRenderContext;
import java.io.InputStream;
import java.net.URL;
import java.text.AttributedString;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.imageio.spi.IIORegistry;

import gnu.java.awt.ClasspathToolkit;

public class QtToolkit extends ClasspathToolkit
{
  public static EventQueue eventQueue = null; // the native event queue
  public static QtRepaintThread repaintThread = null; 
  public static MainQtThread guiThread = null;
  public static QtGraphicsEnvironment graphicsEnv = null;

  private static void initToolkit()
  {
    eventQueue = new EventQueue();
    repaintThread = new QtRepaintThread();
    if (Configuration.INIT_LOAD_LIBRARY)
      System.loadLibrary("qtpeer");

    String theme = null;
    try 
      {
	String style = System.getProperty("qtoptions.style");
	if(style != null)
	  theme = style;
      } 
    catch(SecurityException e)
      {
      }
    catch(IllegalArgumentException e)
      {
      }

    boolean doublebuffer = true;
    try 
      {
	String style = System.getProperty("qtoptions.nodoublebuffer");
	if(style != null)
	  doublebuffer = false;
      } 
    catch(SecurityException e)
      {
      }
    catch(IllegalArgumentException e)
      {
      }

    guiThread = new MainQtThread( theme, doublebuffer );
    guiThread.start();
    repaintThread.start();
  }

  /**
   * Construct the toolkit!
   */
  public QtToolkit()
  {
    if( guiThread == null )
      initToolkit();

    while (!guiThread.isRunning()); // make sure the GUI thread has started.

    if( graphicsEnv == null )
      graphicsEnv = new QtGraphicsEnvironment( this );
  }

  native String[] nativeFontFamilies();
  
  native int numScreens();

  native int defaultScreen();

  // ************ Public methods *********************

  public synchronized native void beep();

  public int checkImage(Image image, int w, int h, ImageObserver observer)
  {
    if(image instanceof QtImage)
      return ((QtImage)image).checkImage(observer);

    return ImageObserver.ERROR; // FIXME
  }

  protected ButtonPeer createButton( Button target )
  {
    return new QtButtonPeer( this, target );
  }

  protected CanvasPeer createCanvas(Canvas target)
  {
    return new QtCanvasPeer( this, target );
  }

  protected CheckboxPeer createCheckbox(Checkbox target)
  {
    return new QtCheckboxPeer( this, target );
  }

  protected  ChoicePeer createChoice(Choice target)
  {
    return new QtChoicePeer( this, target );
  }

  protected CheckboxMenuItemPeer createCheckboxMenuItem(CheckboxMenuItem target)
  {
    return new QtMenuItemPeer( this, target );
  }

  public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent dge) 
  {
    throw new RuntimeException("Not implemented");
  }

  protected FramePeer createFrame(Frame target)
  {
    return new QtFramePeer( this, target );
  }

  protected FileDialogPeer createFileDialog(FileDialog target)
  {
    return new QtFileDialogPeer( this, target );
  }

  public Image createImage(ImageProducer producer)
  {
    return new QtImage( producer );
  }
  
  public Image createImage(byte[] imageData,
			   int imageOffset,
			   int imageLength)
  {
    byte[] dataCopy = new byte[imageLength];
    System.arraycopy(imageData, imageOffset, dataCopy, 0, imageLength);
    return new QtImage( dataCopy );
  }
  
  public Image createImage(String filename)
  {
    return new QtImage( filename );
  }

  public Image createImage(URL url)
  {
    return new QtImage( url );
  }

  protected TextFieldPeer createTextField(TextField target)
  {
    return new QtTextFieldPeer(this,target);
  }
  
  protected LabelPeer createLabel(Label target)
  {
    return new QtLabelPeer( this, target );
  }

  protected ListPeer createList(List target)
  {
    return new QtListPeer( this, target );
  }

  protected ScrollbarPeer createScrollbar(Scrollbar target)
  {
    return new QtScrollbarPeer( this, target );
  }

  protected ScrollPanePeer createScrollPane(ScrollPane target)
  {
    return new QtScrollPanePeer( this, target );
  }

  protected TextAreaPeer createTextArea(TextArea target)
  {
    return new QtTextAreaPeer( this, target );
  }

  protected PanelPeer createPanel(Panel target)
  {
    return new QtPanelPeer( this, target);
  }

  protected WindowPeer createWindow(Window target)
  {
    return new QtWindowPeer( this, target );
  }

  protected DialogPeer createDialog(Dialog target)
  {
    return new QtDialogPeer( this, target );
  }

  protected MenuBarPeer createMenuBar(MenuBar target)
  {
    return new QtMenuBarPeer( this, target );
  }

  protected MenuPeer createMenu(Menu target)
  {
    return new QtMenuPeer( this, target );
  }

  protected PopupMenuPeer createPopupMenu(PopupMenu target)
  {
    return new QtPopupMenuPeer( this, target );
  }

  protected MenuItemPeer createMenuItem(MenuItem target)
  {
    return new QtMenuItemPeer( this, target );
  }

  /**
   * @since 1.4
   */
  public AWTEventListener[] getAWTEventListeners()
  {
    return null; // FIXME
  }

  /**
   * @since 1.4
   */
  public AWTEventListener[] getAWTEventListeners(long mask)
  {
    return null; // FIXME
  }

  public ColorModel getColorModel()
  {
    return new DirectColorModel(32, 
				0x00FF0000,
				0x0000FF00,
				0x000000FF,
				0xFF000000);
  }

  /**
   * Just return the defaults.
   */
  public String[] getFontList()
  {
    String[] builtIn = new String[] { "Dialog", 
				      "DialogInput", 
				      "Monospaced", 
				      "Serif", 
				      "SansSerif" };
    String[] nat = nativeFontFamilies();
    String[] allFonts = new String[ nat.length + 5 ];
    System.arraycopy(builtIn, 0, allFonts, 0, 5);
    System.arraycopy(nat, 0, allFonts, 5, nat.length);
    return allFonts;
  }

  public FontMetrics getFontMetrics(Font font)
  {
    return new QtFontMetrics(font);
  }

  protected FontPeer getFontPeer(String name,
				 int style)
  {
    Map attrs = new HashMap ();
    ClasspathFontPeer.copyStyleToAttrs(style, attrs);
    ClasspathFontPeer.copySizeToAttrs(12, attrs); // Default size is 12.
    return getClasspathFontPeer (name, attrs);
  }

  public Image getImage(String filename)
  {
    return new QtImage(filename);
  }

  public Image getImage(URL url)
  {
    return createImage( url );
  }

  public PrintJob getPrintJob(Frame frame,
			      String jobtitle,
			      Properties props)
  {
    throw new RuntimeException("Not implemented");
  }

  public Clipboard getSystemClipboard()
  {
    throw new RuntimeException("Not implemented");
  }

  protected EventQueue getSystemEventQueueImpl()
  {
    return eventQueue;
  }

  public native Dimension getScreenSize();

  public native int getScreenResolution();

  public Map mapInputMethodHighlight(InputMethodHighlight highlight)
  {
    return null; // FIXME
  }  
  
  public boolean prepareImage(Image image, int w, int h, ImageObserver observer)
  {
    if(image instanceof QtImage)
      return true;
    return false; // FIXME?
  }

  public native void sync();

  // ********************** ClasspathToolkit methods

  public GraphicsEnvironment getLocalGraphicsEnvironment()
  {
    return graphicsEnv;
  }

  public ClasspathFontPeer getClasspathFontPeer (String name, Map attrs)
  {  
    return new QtFontPeer (name, attrs);
  }

  public ClasspathTextLayoutPeer getClasspathTextLayoutPeer(AttributedString str, 
							    FontRenderContext frc)
  {
    return null;
  }

  // FIXME
  public Font createFont(int format, InputStream stream)
  {
    throw new UnsupportedOperationException();
  }

  // FIXME
  public RobotPeer createRobot (GraphicsDevice screen) throws AWTException
  {
    throw new UnsupportedOperationException();
  }

  public EmbeddedWindowPeer createEmbeddedWindow(EmbeddedWindow w)
  {
    //    return new QtEmbeddedWindowPeer( this, w );
    return null;
  }
}
