OSDN Git Service

2006-02-23 Scott Gilbertson <scottg@mantatest.com>
[pf3gnuchains/gcc-fork.git] / libjava / gnu / awt / xlib / XCanvasPeer.java
1 /* Copyright (C) 2000, 2002, 2003  Free Software Foundation
2
3    This file is part of libgcj.
4
5 This software is copyrighted work licensed under the terms of the
6 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
7 details.  */
8
9 package gnu.awt.xlib;
10
11 import java.awt.Dimension;
12 import java.awt.BufferCapabilities;
13 import java.awt.Component;
14 import java.awt.EventQueue;
15 import java.awt.Rectangle;
16 import java.awt.Color;
17 import java.awt.Container;
18 import java.awt.Image;
19 import java.awt.GraphicsConfiguration;
20 import java.awt.Font;
21 import java.awt.FontMetrics;
22 import java.awt.Graphics;
23 import java.awt.Point;
24 import java.awt.Toolkit;
25 import java.awt.AWTEvent;
26 import java.awt.Cursor;
27 import java.awt.Shape;
28
29 import java.awt.peer.*;
30 import java.awt.image.*;
31
32 import java.awt.event.MouseListener;
33 import java.awt.event.PaintEvent;
34
35 import java.util.EventListener;
36
37 import gnu.gcj.xlib.WMSizeHints;
38 import gnu.gcj.xlib.Window;
39 import gnu.gcj.xlib.WindowAttributes;
40 import gnu.gcj.xlib.Display;
41 import gnu.gcj.xlib.Visual;
42 import gnu.gcj.xlib.Screen;
43 import gnu.gcj.xlib.XImage;
44
45 import gnu.awt.j2d.*;
46
47 public class XCanvasPeer implements CanvasPeer
48 {
49   static final Dimension MIN_SIZE = new Dimension(1, 1);
50   
51   public // temporary
52   
53   Window window;
54   Window parent;
55
56   Component component;
57   XGraphicsConfiguration config;
58   private WindowAttributes attributes = new WindowAttributes();
59   private long eventMask;
60   
61   public XCanvasPeer(Component component)
62   {
63     this.component = component;
64     
65     // Set up graphics configuration (ie. screen + visual):
66
67     config = (XGraphicsConfiguration)
68       component.getGraphicsConfiguration();
69
70     if (config == null)
71       {
72         // This will usually only happen for toplevel windows
73         config = getXToolkit().getDefaultXGraphicsConfiguration();
74       } 
75
76     Rectangle bounds = component.getBounds();
77     parent = locateParentWindow(bounds);
78         
79     // Windows in X must atleast be of size 1x1
80     boolean boundsChanged = false;
81     if (bounds.width < 1)
82       {
83         boundsChanged = true;
84         bounds.width = 1;
85       }
86     if (bounds.height < 1)
87       {
88         boundsChanged = true;
89         bounds.height = 1;
90       }
91         
92     /* don't worry about this calling back to us, since the real
93        component object has not yet received a reference to this peer
94        object. */
95     component.setBounds(bounds);
96             
97
98     /* Set background color */
99     Color bg = component.getBackground();
100     if (bg != null)
101       {
102         int[] components =
103         {
104           bg.getRed(),
105           bg.getGreen(),
106           bg.getBlue(),
107           0xff
108         };
109
110         ColorModel cm = config.getColorModel();
111         long pixel = cm.getDataElement(components, 0);
112         attributes.setBackground(pixel);
113       }
114         
115     /* Set exposure mask so that we get exposure events
116        that can be translated into paint() calls. */
117     long eventMask = WindowAttributes.MASK_EXPOSURE;
118
119     /* It would be nice to set up all other required events here, but
120        it is not possible to do so before after all the children of
121        this component has been realized.  The reason is that it is not
122        determined whether a component is lightweight before after the
123        addNotify() method has been called.  Thus, it is not possible
124        for parent component to determine what events it needs to
125        furnish for lightweight children.  Instead, we currently rely
126        on the component calling our setEventMask() method after the
127        correct event mask has been determined. */
128
129     attributes.setEventMask(eventMask);
130         
131             
132     // TODO: set more window attributes?
133
134     /* don't allow event queue to process events from the newly
135        created window before this peer has been registered as client
136        data. */
137     synchronized (getXToolkit().eventLoop)
138       {
139         window = new gnu.gcj.xlib.Window(parent, bounds, attributes);
140         window.setClientData(this); /* make it possible to find back
141                                        to this peer object. Used by
142                                        XEventQueue. */
143       }
144     
145     initWindowProperties();
146
147     if (component.isVisible())
148       EventQueue.invokeLater(new DoMap(window));
149   }
150
151   /**
152    * Override this in subclasses to implement other ways of obtaining
153    * parent windows.  Toplevel windows will typically have a different
154    * implementation.
155    */
156   gnu.gcj.xlib.Window locateParentWindow(Rectangle bounds)
157   {
158     Container parent = component.getParent();
159     while (parent.isLightweight())
160       {
161         bounds.x += parent.getX();
162         bounds.y += parent.getY();
163         parent = parent.getParent();
164         // a null pointer here is a genuine error
165       }
166     
167     XCanvasPeer parentPeer = (XCanvasPeer) parent.getPeer();
168     if (parentPeer == null)
169       throw new NullPointerException("Parent has no peer. This should " +
170                                      "not be possible, since the " +
171                                      "calls leading here should come " +
172                                      "from parent, after it has " +
173                                      "set the parent peer.");
174     return parentPeer.window;
175   }
176     
177
178   /** 
179    * Template method to allow subclasses to apply properties to X11
180    * window right after creation.
181    */
182   void initWindowProperties()
183   {
184   }
185     
186   XToolkit getXToolkit()
187   {
188     return XToolkit.INSTANCE;
189   }
190
191   protected void ensureFlush()
192   {
193     getXToolkit().flushIfIdle();
194   }
195
196   public Component getComponent()
197   {
198     return component;
199   }
200   
201   long getBasicEventMask()
202   {
203     return WindowAttributes.MASK_EXPOSURE;
204   }
205     
206   // -------- java.awt.peer.ComponentPeer implementation
207
208   public int checkImage(Image img, int width, int height, ImageObserver o)
209   {
210     throw new UnsupportedOperationException("FIXME, not implemented");
211   }
212   public Image createImage(ImageProducer prod)
213   {
214     return new XOffScreenImage (config, window, prod, config.getColorModel());
215   }
216   public Image createImage(int width, int height)
217   {
218     return new XOffScreenImage (config, window, width, height, config.getColorModel());
219   }
220   public void dispose()
221   {
222     throw new UnsupportedOperationException("FIXME, not implemented");
223   }
224
225   public GraphicsConfiguration getGraphicsConfiguration()
226   {
227     return config;
228   }
229
230   public FontMetrics getFontMetrics(Font f)
231   {
232     throw new UnsupportedOperationException("FIXME, not implemented");
233   }
234
235   public ColorModel getColorModel ()
236   {
237     return null;
238   }
239
240   public Graphics getGraphics()
241   {
242     DirectRasterGraphics gfxDevice = new XGraphics(window, config);
243     IntegerGraphicsState igState = new IntegerGraphicsState(gfxDevice);
244     Graphics2DImpl gfx2d = new Graphics2DImpl(config);
245
246     gfx2d.setState(igState);
247     gfx2d.setColor(component.getBackground());
248     return gfx2d;
249   }
250
251   private Rectangle locationBounds;
252   public Point getLocationOnScreen()
253   {
254     locationBounds = window.getBounds (locationBounds);
255     return new Point (locationBounds.x,locationBounds.y);
256   }
257
258   public Dimension getMinimumSize ()
259   {
260     return MIN_SIZE;
261   }
262
263   public Dimension minimumSize ()
264   {
265     return getMinimumSize ();
266   }
267
268   public Dimension getPreferredSize ()
269   {
270     return component.getSize();
271   }
272     
273   public Dimension preferredSize ()
274   {
275     return getPreferredSize();
276   }
277     
278   public Toolkit getToolkit()
279   {
280     return getXToolkit();
281   }
282
283   public void handleEvent(AWTEvent event)
284   {
285     int id = event.getID ();
286     
287     switch (id)
288     {
289       case PaintEvent.PAINT:
290       case PaintEvent.UPDATE:
291       {
292         try
293         {
294           Graphics g = getGraphics ();
295           g.setClip (((PaintEvent)event).getUpdateRect ());
296           
297           if (id == PaintEvent.PAINT)
298             component.paint (g);
299           else
300             component.update (g);
301           
302           g.dispose ();
303         }
304         catch (InternalError e)
305         {
306           System.err.println (e);
307         }
308       }
309       break;
310     }
311   }
312
313   public boolean isFocusTraversable()
314   {
315     throw new UnsupportedOperationException("FIXME, not implemented");
316   }
317
318   public void paint(Graphics gfx)
319   {
320     // do nothing by default
321   }
322     
323   public boolean prepareImage(Image img, int width, int height,
324                               ImageObserver o)
325   {
326     throw new UnsupportedOperationException("FIXME, not implemented");
327   }
328
329   public void print(Graphics graphics)
330   {
331     paint(graphics);
332   }
333
334   public void repaint(long tm, int x, int y, int w, int h)
335   {
336     /* TODO?
337
338        X allows intelligent X servers to do smart
339        refreshing. Perhaps involve X in repainting of components,
340        rather that keeping it all within the local event queue. */
341     
342     PaintEvent updateEvent = new PaintEvent(component,
343                                             PaintEvent.UPDATE,
344                                             new Rectangle(x, y, w, h));
345     getXToolkit().queue.postEvent(updateEvent);
346   }
347     
348   public void requestFocus()
349   {
350     throw new UnsupportedOperationException("FIXME, not implemented");
351   }
352
353   public void setBackground(Color color)
354   {
355     if (color != null)
356     {
357       int[] components =
358       {
359         color.getRed (),
360         color.getGreen (),
361         color.getBlue (),
362         0xff
363       };
364       
365       ColorModel cm = config.getColorModel ();
366       long pixel = cm.getDataElement (components, 0);
367       attributes.setBackground (pixel);
368       window.setAttributes (attributes);
369     }
370   }
371
372   public void setBounds(int x, int y, int width, int height)
373   {
374     width  = Math.max(width,  1);
375     height = Math.max(height, 1);
376     window.setBounds(x, y, width, height);
377     ensureFlush();          
378   }
379     
380   public void reshape (int x, int y, int width, int height)
381   {
382     setBounds (x, y, width, height);
383   }
384
385   public void setCursor(Cursor cursor)
386   {
387     throw new UnsupportedOperationException("FIXME, not implemented");
388   }
389
390   public void setEnabled(boolean enabled)
391   {
392     throw new UnsupportedOperationException("FIXME, not implemented");
393   }
394
395   public void enable ()
396   {
397     setEnabled (true);
398   }
399
400   public void disable ()
401   {
402     setEnabled (false);
403   }
404
405   public void setEventMask(long eventMask)
406   {
407     if (this.eventMask != eventMask)
408     {
409       this.eventMask = eventMask;
410       long xEventMask = getBasicEventMask ();
411       
412       if ((eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0)
413       {
414         xEventMask |=
415           WindowAttributes.MASK_BUTTON_PRESS |
416           WindowAttributes.MASK_BUTTON_RELEASE;
417       }
418       
419       attributes.setEventMask (xEventMask);
420       window.setAttributes (attributes);
421       ensureFlush ();
422     }
423   }
424
425   public void setFont(Font font)
426   {
427     /* default canvas peer does not keep track of font, since it won't
428        paint anything. */
429   }
430
431   public void setForeground(Color color)
432   {
433     /* default canvas peer does not keep track of foreground, since it won't
434        paint anything. */
435   }
436         
437   public void setVisible(boolean visible)
438   {
439     if (visible)
440       {
441         window.map();
442         ensureFlush();      
443       }
444     else
445       {
446         window.unmap();
447         ensureFlush();      
448       }
449   }
450         
451   public void show ()
452   {
453     setVisible (true);
454   }
455
456   public void hide ()
457   {
458     setVisible (false);
459   }
460
461   public boolean isFocusable ()
462   {
463     return false;
464   }
465
466   public boolean requestFocus (Component source, boolean b1, 
467                                boolean b2, long x)
468   {
469     return false;
470   }
471
472   public boolean isObscured ()
473   {
474     return false;
475   }
476
477   public boolean canDetermineObscurity ()
478   {
479     return false;
480   }
481
482   public void coalescePaintEvent (PaintEvent e)
483   {
484   }
485
486   public void updateCursorImmediately ()
487   {
488   }
489
490   public VolatileImage createVolatileImage (int width, int height)
491   {
492     return null;
493   }
494
495   public boolean handlesWheelScrolling ()
496   {
497     return false;
498   }
499
500   public void createBuffers (int x, BufferCapabilities capabilities)
501     throws java.awt.AWTException
502
503   {
504   }
505
506   public Image getBackBuffer ()
507   {
508     return null;
509   }
510
511   public void flip (BufferCapabilities.FlipContents contents)
512   {
513   }
514
515   public void destroyBuffers ()
516   {
517   }
518
519   static class DoMap implements Runnable 
520   {
521     Window window;
522     public DoMap(Window w) 
523     {
524       this.window = w;
525     }
526     
527     public void run() 
528     {
529       window.map();
530     }
531   }
532
533   /**
534    * @since 1.5
535    */
536   public boolean isRestackSupported ()
537   {
538     return false;
539   }
540
541   /**
542    * @since 1.5
543    */
544   public void cancelPendingPaint (int x, int y, int width, int height)
545   {
546   }
547
548   /**
549    * @since 1.5
550    */
551   public void restack ()
552   {
553   }
554
555   /**
556    * @since 1.5
557    */
558   public Rectangle getBounds ()
559   {
560     return null;
561   }
562
563   /**
564    * @since 1.5
565    */
566   public void reparent (ContainerPeer parent)
567   {
568   }
569
570   /**
571    * @since 1.5
572    */
573   public void setBounds (int x, int y, int width, int height, int z)
574   {
575   }
576
577   /**
578    * @since 1.5
579    */
580   public boolean isReparentSupported ()
581   {
582     return false;
583   }
584
585   /**
586    * @since 1.5
587    */
588   public void layout ()
589   {
590   }
591 }