OSDN Git Service

Merged gcj-eclipse branch to trunk.
[pf3gnuchains/gcc-fork.git] / libjava / classpath / gnu / java / awt / peer / swing / SwingContainerPeer.java
1 /* SwingContainerPeer.java -- A Swing based peer for AWT containers
2    Copyright (C)  2006  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 package gnu.java.awt.peer.swing;
39
40 import gnu.classpath.SystemProperties;
41
42 import java.awt.Component;
43 import java.awt.Container;
44 import java.awt.Graphics;
45 import java.awt.Image;
46 import java.awt.Insets;
47 import java.awt.Rectangle;
48 import java.awt.event.KeyEvent;
49 import java.awt.event.MouseEvent;
50 import java.awt.peer.ComponentPeer;
51 import java.awt.peer.ContainerPeer;
52 import java.util.Iterator;
53 import java.util.LinkedList;
54
55 /**
56  * A peer for Container to be used with the Swing based AWT peers.
57  *
58  * @author Roman Kennke (kennke@aicas.com)
59  */
60 public class SwingContainerPeer
61   extends SwingComponentPeer
62   implements ContainerPeer
63 {
64
65   /**
66    * Stores all heavyweight descendents of the container. This is used
67    * in {@link #peerPaintChildren(Graphics)}.
68    */
69   private LinkedList heavyweightDescendents;
70
71   /**
72    * The backbuffer used for painting UPDATE events.
73    */
74   private Image backbuffer;
75
76   /**
77    * Creates a new SwingContainerPeer.
78    *
79    * @param awtCont
80    */
81   public SwingContainerPeer(Container awtCont)
82   {
83     heavyweightDescendents = new LinkedList();
84   }
85
86   /**
87    * Registers a heavyweight descendent. This is then painted by
88    * {@link #peerPaintChildren(Graphics)}.
89    *
90    * @param comp the descendent to register
91    *
92    * @see #peerPaintChildren(Graphics)
93    * @see #removeHeavyweightDescendent(Component)
94    */
95   synchronized void addHeavyweightDescendent(Component comp)
96   {
97     heavyweightDescendents.add(comp);
98     focusOwner = null;
99   }
100
101   /**
102    * Unregisters a heavyweight descendent.
103    *
104    * @param comp the descendent to unregister
105    *
106    * @see #peerPaintChildren(Graphics)
107    * @see #addHeavyweightDescendent(Component)
108    */
109   synchronized void removeHeavyweightDescendent(Component comp)
110   {
111     heavyweightDescendents.remove(comp);
112     focusOwner = null;
113   }
114
115   /**
116    * Returns the insets of the container.
117    *
118    * This is implemented to return the insets of the Swing container.
119    *
120    * @return the insets of the container
121    */
122   public Insets insets()
123   {
124     Insets retVal;
125     if (swingComponent != null)
126       retVal = swingComponent.getJComponent().getInsets();
127     else
128       retVal = new Insets(0, 0, 0, 0);
129     return retVal;
130   }
131
132   /**
133    * Returns the insets of the container.
134    *
135    * This is implemented to return the insets of the Swing container.
136    *
137    * @return the insets of the container
138    */
139   public Insets getInsets()
140   {
141     return insets();
142   }
143
144   /**
145    * Called before the validation of this containers begins.
146    */
147   public void beginValidate()
148   {
149     // Nothing to do here.
150   }
151
152   /**
153    * Called after the validation of this containers ended.
154    */
155   public void endValidate()
156   {
157     // Nothing to do here.
158   }
159
160   /**
161    * Called before the layout of this containers begins.
162    */
163   public void beginLayout()
164   {
165     // Nothing to do here.
166   }
167
168   /**
169    * Called after the layout of this containers ended.
170    */
171   public void endLayout()
172   {
173     // Nothing to do here.
174   }
175
176   /**
177    * Returns <code>false</code> unconditionally. This method is not used at
178    * the moment.
179    *
180    * @return <code>false</code>
181    */
182   public boolean isPaintPending()
183   {
184     return false;
185   }
186
187   /**
188    * Returns <code>false</code> unconditionally. This method is not used at
189    * the moment.
190    *
191    * @return <code>false</code>
192    */
193   public boolean isRestackSupported()
194   {
195     return false;
196   }
197
198   /**
199    * This method is not used at the moment.
200    */
201   public void cancelPendingPaint(int x, int y, int width, int height)
202   {
203     // Nothing to do here.
204   }
205
206   /**
207    * This method is not used at the moment.
208    */
209   public void restack()
210   {
211     // Nothing to do here.
212   }
213
214   /**
215    * Performs the super behaviour (call peerPaintComponent() and
216    * awtComponent.paint()), and forwards the paint request to the heavyweight
217    * descendents of the container.
218    */
219   protected void peerPaint(Graphics g, boolean update)
220   {
221     if (isDoubleBuffering())
222       {
223         int width = awtComponent.getWidth();
224         int height = awtComponent.getHeight();
225         if (backbuffer == null
226             || backbuffer.getWidth(awtComponent) < width
227             || backbuffer.getHeight(awtComponent) < height)
228           backbuffer = awtComponent.createImage(width, height);
229         Graphics g2 = backbuffer.getGraphics();
230         Rectangle clip = g.getClipRect();
231         try
232           {
233             g2.setClip(clip);
234             super.peerPaint(g2, update);
235             peerPaintChildren(g2);
236           }
237         finally
238           {
239             g2.dispose();
240           }
241         g.drawImage(backbuffer, 0, 0, awtComponent);
242       }
243     else
244       {
245         super.peerPaint(g, update);
246         peerPaintChildren(g);
247       }
248   }
249
250   /**
251    * Determines if we should do double buffering or not.
252    *
253    * @return if we should do double buffering or not
254    */
255   private boolean isDoubleBuffering()
256   {
257     Object prop =
258       SystemProperties.getProperty("gnu.awt.swing.doublebuffering", "false");
259     return prop.equals("true");
260   }
261
262   /**
263    * Paints any heavyweight child components.
264    *
265    * @param g the graphics to use for painting
266    */
267   protected synchronized void peerPaintChildren(Graphics g)
268   {
269     // TODO: Is this the right painting order?
270     for (Iterator i = heavyweightDescendents.iterator(); i.hasNext();)
271       {
272         Component child = (Component) i.next();
273         ComponentPeer peer = child.getPeer();
274
275         if (peer instanceof SwingComponentPeer && child.isVisible())
276           {
277             // TODO: The translation here doesn't work for deeper
278             // nested children. Fix this!
279             Graphics g2 = g.create(child.getX(), child.getY(),
280                                    child.getWidth(), child.getHeight());
281             try
282               {
283                 // update() is only called for the topmost component if
284                 // necessary, all other components only get paint() called.
285                 ((SwingComponentPeer) peer).peerPaint(g2, false);
286               }
287             finally
288               {
289                 g2.dispose();
290               }
291           }
292       }
293   }
294
295   /**
296    * Handles mouse events by dispatching it to the correct component.
297    *
298    * @param ev the mouse event
299    */
300   protected void handleMouseEvent(MouseEvent ev)
301   {
302     Component comp = awtComponent.getComponentAt(ev.getPoint());
303     if(comp == null) comp = awtComponent;
304     ComponentPeer peer = comp.getPeer();
305     if (awtComponent != comp && !comp.isLightweight() && peer instanceof SwingComponentPeer)
306       {
307         ev.translatePoint(comp.getX(), comp.getY());
308         ev.setSource(comp);
309         ((SwingComponentPeer) peer).handleMouseEvent(ev);
310       }
311   }
312
313   /**
314    * Handles mouse events by dispatching it to the correct component.
315    *
316    * @param ev the mouse event
317    */
318   protected void handleMouseMotionEvent(MouseEvent ev)
319   {
320     Component comp = awtComponent.getComponentAt(ev.getPoint());
321     if (comp != null)
322       {
323         ComponentPeer peer = comp.getPeer();
324         if (awtComponent != comp && !comp.isLightweight() && peer instanceof SwingComponentPeer)
325           {
326             ev.translatePoint(comp.getX(), comp.getY());
327             ((SwingComponentPeer) peer).handleMouseMotionEvent(ev);
328           }
329       }
330   }
331   
332   /**
333    * Handles key events on the component. This is usually forwarded to the
334    * SwingComponent's processKeyEvent() method.
335    *
336    * @param e the key event
337    */
338   protected void handleKeyEvent(KeyEvent e)
339   {
340     Component owner = getFocusOwner();
341     if(owner != null)
342       owner.dispatchEvent(e);
343     else 
344       super.handleKeyEvent(e);
345   }
346
347   private Component focusOwner = null;
348   
349   private Component getFocusOwner()
350   {
351       if(focusOwner == null)
352       {
353         for(Iterator iter=heavyweightDescendents.iterator(); iter.hasNext();)
354         {
355            Component child = (Component) iter.next();
356           if(child.isFocusable())
357           {
358               focusOwner = child;
359             break;
360           }          
361       }
362       }
363       return focusOwner;
364   }
365   
366 }