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

Quick Search    Search Deep

Source code: gnu/java/awt/peer/gtk/GtkToolkit.java


1   /* GtkToolkit.java -- Implements an AWT Toolkit using GTK for peers
2      Copyright (C) 1998, 1999, 2002, 2003, 2004, 2005  Free Software Foundation, Inc.
3   
4   This file is part of GNU Classpath.
5   
6   GNU Classpath is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10  
11  GNU Classpath is distributed in the hope that it will be useful, but
12  WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  General Public License for more details.
15  
16  You should have received a copy of the GNU General Public License
17  along with GNU Classpath; see the file COPYING.  If not, write to the
18  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19  02110-1301 USA.
20  
21  Linking this library statically or dynamically with other modules is
22  making a combined work based on this library.  Thus, the terms and
23  conditions of the GNU General Public License cover the whole
24  combination.
25  
26  As a special exception, the copyright holders of this library give you
27  permission to link this library with independent modules to produce an
28  executable, regardless of the license terms of these independent
29  modules, and to copy and distribute the resulting executable under
30  terms of your choice, provided that you also meet, for each linked
31  independent module, the terms and conditions of the license of that
32  module.  An independent module is a module which is not derived from
33  or based on this library.  If you modify this library, you may extend
34  this exception to your version of the library, but you are not
35  obligated to do so.  If you do not wish to do so, delete this
36  exception statement from your version. */
37  
38  
39  package gnu.java.awt.peer.gtk;
40  
41  import gnu.classpath.Configuration;
42  import gnu.java.awt.EmbeddedWindow;
43  import gnu.java.awt.peer.ClasspathFontPeer;
44  import gnu.java.awt.peer.ClasspathTextLayoutPeer;
45  import gnu.java.awt.peer.EmbeddedWindowPeer;
46  
47  import java.awt.*;
48  import java.awt.datatransfer.Clipboard;
49  import java.awt.dnd.DragGestureEvent;
50  import java.awt.dnd.peer.DragSourceContextPeer;
51  import java.awt.font.FontRenderContext;
52  import java.awt.im.InputMethodHighlight;
53  import java.awt.image.BufferedImage;
54  import java.awt.image.ColorModel;
55  import java.awt.image.DirectColorModel;
56  import java.awt.image.ImageConsumer;
57  import java.awt.image.ImageObserver;
58  import java.awt.image.ImageProducer;
59  import java.awt.peer.*;
60  import java.io.InputStream;
61  import java.net.URL;
62  import java.text.AttributedString;
63  import java.util.HashMap;
64  import java.util.HashSet;
65  import java.util.Hashtable;
66  import java.util.Iterator;
67  import java.util.LinkedHashMap;
68  import java.util.Map;
69  import java.util.Properties;
70  
71  import javax.imageio.spi.IIORegistry;
72  
73  /* This class uses a deprecated method java.awt.peer.ComponentPeer.getPeer().
74     This merits comment.  We are basically calling Sun's bluff on this one.
75     We think Sun has deprecated it simply to discourage its use as it is
76     bad programming style.  However, we need to get at a component's peer in
77     this class.  If getPeer() ever goes away, we can implement a hash table
78     that will keep up with every window's peer, but for now this is faster. */
79  
80  /**
81   * This class accesses a system property called
82   * <tt>gnu.java.awt.peer.gtk.Graphics</tt>.  If the property is defined and
83   * equal to "Graphics2D", the cairo-based GdkGraphics2D will be used in
84   * drawing contexts. Any other value will cause the older GdkGraphics
85   * object to be used.
86   */
87  public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
88  {
89    Hashtable containers = new Hashtable();
90    static EventQueue q;
91    static boolean useGraphics2dSet;
92    static boolean useGraphics2d;
93    static Thread mainThread;
94  
95    public static boolean useGraphics2D()
96    {
97      if (useGraphics2dSet)
98        return useGraphics2d;
99      useGraphics2d = System.getProperty("gnu.java.awt.peer.gtk.Graphics", 
100                                        "Graphics").equals("Graphics2D");
101     useGraphics2dSet = true;
102     return useGraphics2d;
103   }
104 
105   static native void gtkInit(int portableNativeSync);
106 
107   static
108   {
109     if (Configuration.INIT_LOAD_LIBRARY)
110       System.loadLibrary("gtkpeer");
111 
112     int portableNativeSync;     
113     String portNatSyncProp = 
114       System.getProperty("gnu.classpath.awt.gtk.portable.native.sync");
115     
116     if (portNatSyncProp == null)
117       portableNativeSync = -1;  // unset
118     else if (Boolean.valueOf(portNatSyncProp).booleanValue())
119       portableNativeSync = 1;   // true
120     else
121       portableNativeSync = 0;   // false
122 
123     gtkInit(portableNativeSync);
124 
125     mainThread = new Thread ("GTK main thread")
126       {
127         public void run ()
128         {
129           gtkMain ();
130         }
131       };
132     mainThread.start ();
133   }
134 
135   public GtkToolkit ()
136   {
137   }
138 
139   public native void beep();
140   private native void getScreenSizeDimensions(int[] xy);
141   
142   public int checkImage (Image image, int width, int height, 
143        ImageObserver observer) 
144   {
145     int status = ImageObserver.ALLBITS 
146       | ImageObserver.WIDTH 
147       | ImageObserver.HEIGHT;
148 
149     if (image instanceof GtkImage)
150   return ((GtkImage) image).checkImage (observer);
151 
152     if (observer != null)
153       observer.imageUpdate (image, status,
154                             -1, -1,
155                             image.getWidth (observer),
156                             image.getHeight (observer));
157     
158     return status;
159   }
160 
161   /** 
162    * A helper class to return to clients in cases where a BufferedImage is
163    * desired but its construction fails.
164    */
165   private class GtkErrorImage extends Image
166   {
167     public GtkErrorImage()
168     {
169     }
170 
171     public int getWidth(ImageObserver observer)
172     {
173       return -1;
174     }
175 
176     public int getHeight(ImageObserver observer)
177     {
178       return -1;
179     }
180 
181     public ImageProducer getSource()
182     {
183 
184       return new ImageProducer() 
185         {          
186           HashSet consumers = new HashSet();          
187           public void addConsumer(ImageConsumer ic)
188           {
189             consumers.add(ic);
190           }
191 
192           public boolean isConsumer(ImageConsumer ic)
193           {
194             return consumers.contains(ic);
195           }
196 
197           public void removeConsumer(ImageConsumer ic)
198           {
199             consumers.remove(ic);
200           }
201 
202           public void startProduction(ImageConsumer ic)
203           {
204             consumers.add(ic);
205             Iterator i = consumers.iterator();
206             while(i.hasNext())
207               {
208                 ImageConsumer c = (ImageConsumer) i.next();
209                 c.imageComplete(ImageConsumer.IMAGEERROR);
210               }
211           }
212           public void requestTopDownLeftRightResend(ImageConsumer ic)
213           {
214             startProduction(ic);
215           }        
216         };
217     }
218 
219     public Graphics getGraphics() 
220     { 
221       return null; 
222     }
223 
224     public Object getProperty(String name, ImageObserver observer)
225     {
226       return null;
227     }
228     public Image getScaledInstance(int width, int height, int flags)
229     {
230       return new GtkErrorImage();
231     }
232 
233     public void flush() 
234     {
235     }
236   }
237 
238 
239   /** 
240    * Helper to return either a BufferedImage -- the argument -- or a
241    * GtkErrorImage if the argument is null.
242    */
243 
244   private Image bufferedImageOrError(BufferedImage b)
245   {
246     if (b == null) 
247       return new GtkErrorImage();
248     else
249       return b;
250   }
251 
252 
253   public Image createImage (String filename)
254   {
255     if (filename.length() == 0)
256       return new GtkImage ();
257 
258     if (useGraphics2D())
259       return bufferedImageOrError(GdkPixbufDecoder.createBufferedImage (filename));
260     else
261       return new GtkImage (filename);
262   }
263 
264   public Image createImage (URL url)
265   {
266     if (useGraphics2D())
267       return bufferedImageOrError(GdkPixbufDecoder.createBufferedImage (url));
268     else
269       return new GtkImage (url);
270   }
271 
272   public Image createImage (ImageProducer producer) 
273   {
274     if (useGraphics2D())
275       return bufferedImageOrError(GdkPixbufDecoder.createBufferedImage (producer));
276     else
277       return new GtkImage (producer);
278   }
279 
280   public Image createImage (byte[] imagedata, int imageoffset,
281           int imagelength)
282   {
283     if (useGraphics2D())
284       return bufferedImageOrError(GdkPixbufDecoder.createBufferedImage (imagedata,
285                                                    imageoffset, 
286                                                                         imagelength));
287     else
288       {
289         byte[] datacopy = new byte[imagelength];
290         System.arraycopy (imagedata, imageoffset, datacopy, 0, imagelength);
291         return new GtkImage (datacopy);
292       }
293   }
294   
295   /**
296    * Creates an ImageProducer from the specified URL. The image is assumed
297    * to be in a recognised format. 
298    *
299    * @param url URL to read image data from.
300    */  
301   public ImageProducer createImageProducer(URL url)
302   {
303     return new GdkPixbufDecoder(url);  
304   }
305 
306   /**
307    * Returns the native color model (which isn't the same as the default
308    * ARGB color model, but doesn't have to be). 
309    */
310   public ColorModel getColorModel () 
311   {
312     /* Return the GDK-native ABGR format */
313     return new DirectColorModel(32, 
314         0x000000FF,
315         0x0000FF00,
316         0x00FF0000,
317         0xFF000000);
318   }
319 
320   public String[] getFontList () 
321   {
322     return (new String[] { "Dialog", 
323          "DialogInput", 
324          "Monospaced", 
325          "Serif", 
326          "SansSerif" });
327   }
328 
329   private class LRUCache extends LinkedHashMap
330   {    
331     int max_entries;
332     public LRUCache(int max)
333     {
334       super(max, 0.75f, true);
335       max_entries = max;
336     }
337     protected boolean removeEldestEntry(Map.Entry eldest)
338     {
339       return size() > max_entries;
340     }
341   }
342 
343   private LRUCache fontCache = new LRUCache(50);
344   private LRUCache metricsCache = new LRUCache(50);
345   private LRUCache imageCache = new LRUCache(50);
346 
347   public FontMetrics getFontMetrics (Font font) 
348   {
349     synchronized (metricsCache)
350       {
351         if (metricsCache.containsKey(font))
352           return (FontMetrics) metricsCache.get(font);
353       }
354 
355     FontMetrics m = new GdkFontMetrics (font);
356     synchronized (metricsCache)
357       {
358         metricsCache.put(font, m);
359       }
360     return m;
361   }
362 
363   public Image getImage (String filename) 
364   {
365     if (imageCache.containsKey(filename))
366       return (Image) imageCache.get(filename);
367     else
368       {
369         Image im = createImage(filename);
370         imageCache.put(filename, im);
371         return im;
372       }
373   }
374 
375   public Image getImage (URL url) 
376   {
377     if (imageCache.containsKey(url))
378       return (Image) imageCache.get(url);
379     else
380       {
381         Image im = createImage(url);
382         imageCache.put(url, im);
383         return im;
384       }
385   }
386 
387   public PrintJob getPrintJob (Frame frame, String jobtitle, Properties props) 
388   {
389     return null;
390   }
391 
392   public native int getScreenResolution();
393 
394   public Dimension getScreenSize ()
395   {
396     int dim[] = new int[2];
397     getScreenSizeDimensions(dim);
398     return new Dimension(dim[0], dim[1]);
399   }
400 
401   public Clipboard getSystemClipboard() 
402   {
403     SecurityManager secman = System.getSecurityManager();
404     if (secman != null)
405       secman.checkSystemClipboardAccess();
406 
407     return GtkClipboard.getInstance();
408   }
409 
410   /**
411    * Prepares a GtkImage. For every other kind of Image it just
412    * assumes the image is already prepared for rendering.
413    */
414   public boolean prepareImage (Image image, int width, int height, 
415              ImageObserver observer) 
416   {
417     /* GtkImages are always prepared, as long as they're loaded. */
418     if (image instanceof GtkImage)
419       return ((((GtkImage)image).checkImage (observer) & 
420          ImageObserver.ALLBITS) != 0);
421 
422     /* Assume anything else is too */
423     return true;
424   }
425 
426   public native void sync();
427 
428   protected void setComponentState (Component c, GtkComponentPeer cp)
429   {
430     /* Make the Component reflect Peer defaults */
431     if (c.getForeground () == null)
432       c.setForeground (cp.getForeground ());
433     if (c.getBackground () == null)
434       c.setBackground (cp.getBackground ());
435     //        if (c.getFont () == null)
436     //    c.setFont (cp.getFont ());
437       
438     /* Make the Peer reflect the state of the Component */
439     if (! (c instanceof Window))
440       {
441   cp.setCursor (c.getCursor ());
442   
443   Rectangle bounds = c.getBounds ();
444   cp.setBounds (bounds.x, bounds.y, bounds.width, bounds.height);
445   cp.setVisible (c.isVisible ());
446       }
447   }
448 
449   protected ButtonPeer createButton (Button b)
450   {
451     return new GtkButtonPeer (b);
452   }
453 
454   protected CanvasPeer createCanvas (Canvas c) 
455   {
456     return new GtkCanvasPeer (c);
457   }
458 
459   protected CheckboxPeer createCheckbox (Checkbox cb) 
460   {
461     return new GtkCheckboxPeer (cb);
462   }
463 
464   protected CheckboxMenuItemPeer createCheckboxMenuItem (CheckboxMenuItem cmi)
465   {
466     return new GtkCheckboxMenuItemPeer (cmi);
467   }
468 
469   protected ChoicePeer createChoice (Choice c) 
470   {
471     return new GtkChoicePeer (c);
472   }
473 
474   protected DialogPeer createDialog (Dialog d)
475   {
476     return new GtkDialogPeer (d);
477   }
478 
479   protected FileDialogPeer createFileDialog (FileDialog fd)
480   {
481     return new GtkFileDialogPeer (fd);
482   }
483 
484   protected FramePeer createFrame (Frame f)
485   {
486     return new GtkFramePeer (f);
487   }
488 
489   protected LabelPeer createLabel (Label label) 
490   {
491     return new GtkLabelPeer (label);
492   }
493 
494   protected ListPeer createList (List list)
495   {
496     return new GtkListPeer (list);
497   }
498 
499   protected MenuPeer createMenu (Menu m) 
500   {
501     return new GtkMenuPeer (m);
502   }
503 
504   protected MenuBarPeer createMenuBar (MenuBar mb) 
505   {
506     return new GtkMenuBarPeer (mb);
507   }
508 
509   protected MenuItemPeer createMenuItem (MenuItem mi) 
510   {
511     return new GtkMenuItemPeer (mi);
512   }
513 
514   protected PanelPeer createPanel (Panel p) 
515   {
516     return new GtkPanelPeer (p);
517   }
518 
519   protected PopupMenuPeer createPopupMenu (PopupMenu target) 
520   {
521     return new GtkPopupMenuPeer (target);
522   }
523 
524   protected ScrollPanePeer createScrollPane (ScrollPane sp) 
525   {
526     return new GtkScrollPanePeer (sp);
527   }
528 
529   protected ScrollbarPeer createScrollbar (Scrollbar sb) 
530   {
531     return new GtkScrollbarPeer (sb);
532   }
533 
534   protected TextAreaPeer createTextArea (TextArea ta) 
535   {
536     return new GtkTextAreaPeer (ta);
537   }
538 
539   protected TextFieldPeer createTextField (TextField tf) 
540   {
541     return new GtkTextFieldPeer (tf);
542   }
543 
544   protected WindowPeer createWindow (Window w)
545   {
546     return new GtkWindowPeer (w);
547   }
548 
549   public EmbeddedWindowPeer createEmbeddedWindow (EmbeddedWindow w)
550   {
551     return new GtkEmbeddedWindowPeer (w);
552   }
553 
554   /** 
555    * @deprecated part of the older "logical font" system in earlier AWT
556    * implementations. Our newer Font class uses getClasspathFontPeer.
557    */
558   protected FontPeer getFontPeer (String name, int style) {
559     // All fonts get a default size of 12 if size is not specified.
560     return getFontPeer(name, style, 12);
561   }
562 
563   /**
564    * Private method that allows size to be set at initialization time.
565    */
566   private FontPeer getFontPeer (String name, int style, int size) 
567   {
568     Map attrs = new HashMap ();
569     ClasspathFontPeer.copyStyleToAttrs (style, attrs);
570     ClasspathFontPeer.copySizeToAttrs (size, attrs);
571     return getClasspathFontPeer (name, attrs);
572   }
573 
574   /**
575    * Newer method to produce a peer for a Font object, even though Sun's
576    * design claims Font should now be peerless, we do not agree with this
577    * model, hence "ClasspathFontPeer". 
578    */
579 
580   public ClasspathFontPeer getClasspathFontPeer (String name, Map attrs)
581   {
582     Map keyMap = new HashMap (attrs);
583     // We don't know what kind of "name" the user requested (logical, face,
584     // family), and we don't actually *need* to know here. The worst case
585     // involves failure to consolidate fonts with the same backend in our
586     // cache. This is harmless.
587     keyMap.put ("GtkToolkit.RequestedFontName", name);
588     if (fontCache.containsKey (keyMap))
589       return (ClasspathFontPeer) fontCache.get (keyMap);
590     else
591       {
592         ClasspathFontPeer newPeer = new GdkFontPeer (name, attrs);
593         fontCache.put (keyMap, newPeer);
594         return newPeer;
595       }
596   }
597 
598   public ClasspathTextLayoutPeer getClasspathTextLayoutPeer (AttributedString str, 
599                                                              FontRenderContext frc)
600   {
601     return new GdkTextLayout(str, frc);
602   }
603 
604   protected EventQueue getSystemEventQueueImpl() 
605   {
606     synchronized (GtkToolkit.class)
607       {
608         if (q == null)
609           {
610             q = new EventQueue();
611             GtkGenericPeer.enableQueue (q);
612           }
613       }    
614     return q;
615   }
616 
617   protected native void loadSystemColors (int[] systemColors);
618 
619   public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent e)
620   {
621     throw new Error("not implemented");
622   }
623 
624   public Map mapInputMethodHighlight(InputMethodHighlight highlight)
625   {
626     throw new Error("not implemented");
627   }
628 
629   public Rectangle getBounds()
630   {
631     int[] dims = new int[2];
632     getScreenSizeDimensions(dims);
633     return new Rectangle(0, 0, dims[0], dims[1]);
634   }
635   
636   // ClasspathToolkit methods
637 
638   public GraphicsEnvironment getLocalGraphicsEnvironment()
639   {
640     return new GdkGraphicsEnvironment();
641   }
642 
643   public Font createFont(int format, InputStream stream)
644   {
645     throw new UnsupportedOperationException();
646   }
647 
648   public RobotPeer createRobot (GraphicsDevice screen) throws AWTException
649   {
650     return new GdkRobotPeer (screen);
651   }
652 
653   public void registerImageIOSpis(IIORegistry reg)
654   {
655     GdkPixbufDecoder.registerSpis(reg);
656   }
657 
658   public static native void gtkMain();
659 } // class GtkToolkit