OSDN Git Service

libjava/
[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, 2007  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   protected 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   protected synchronized void removeHeavyweightDescendent(Component comp)
110   {
111     heavyweightDescendents.remove(comp);
112     focusOwner = null;
113   }
114
115   /**
116    * Returns an array of all registered heavyweight descendents.
117    *
118    * @return all registered heavyweight descendents
119    */
120   protected Component[] getHeavyweightDescendents()
121   {
122     Component[] heavyweights = new Component[heavyweightDescendents.size()];
123     heavyweights = (Component[]) heavyweightDescendents.toArray(heavyweights);
124     return heavyweights;
125   }
126
127   /**
128    * Returns the insets of the container.
129    *
130    * This is implemented to return the insets of the Swing container.
131    *
132    * @return the insets of the container
133    */
134   public Insets insets()
135   {
136     Insets retVal;
137     if (swingComponent != null)
138       retVal = swingComponent.getJComponent().getInsets();
139     else
140       retVal = new Insets(0, 0, 0, 0);
141     return retVal;
142   }
143
144   /**
145    * Returns the insets of the container.
146    *
147    * This is implemented to return the insets of the Swing container.
148    *
149    * @return the insets of the container
150    */
151   public Insets getInsets()
152   {
153     return insets();
154   }
155
156   /**
157    * Called before the validation of this containers begins.
158    */
159   public void beginValidate()
160   {
161     // Nothing to do here.
162   }
163
164   /**
165    * Called after the validation of this containers ended.
166    */
167   public void endValidate()
168   {
169     // Nothing to do here.
170   }
171
172   /**
173    * Called before the layout of this containers begins.
174    */
175   public void beginLayout()
176   {
177     // Nothing to do here.
178   }
179
180   /**
181    * Called after the layout of this containers ended.
182    */
183   public void endLayout()
184   {
185     // Nothing to do here.
186   }
187
188   /**
189    * Returns <code>false</code> unconditionally. This method is not used at
190    * the moment.
191    *
192    * @return <code>false</code>
193    */
194   public boolean isPaintPending()
195   {
196     return false;
197   }
198
199   /**
200    * Returns <code>false</code> unconditionally. This method is not used at
201    * the moment.
202    *
203    * @return <code>false</code>
204    */
205   public boolean isRestackSupported()
206   {
207     return false;
208   }
209
210   /**
211    * This method is not used at the moment.
212    */
213   public void cancelPendingPaint(int x, int y, int width, int height)
214   {
215     // Nothing to do here.
216   }
217
218   /**
219    * This method is not used at the moment.
220    */
221   public void restack()
222   {
223     // Nothing to do here.
224   }
225
226   /**
227    * Performs the super behaviour (call peerPaintComponent() and
228    * awtComponent.paint()), and forwards the paint request to the heavyweight
229    * descendents of the container.
230    */
231   protected void peerPaint(Graphics g, boolean update)
232   {
233     if (isDoubleBuffering())
234       {
235         int width = awtComponent.getWidth();
236         int height = awtComponent.getHeight();
237         if (backbuffer == null
238             || backbuffer.getWidth(awtComponent) < width
239             || backbuffer.getHeight(awtComponent) < height)
240           backbuffer = awtComponent.createImage(width, height);
241         Graphics g2 = backbuffer.getGraphics();
242         Rectangle clip = g.getClipRect();
243         try
244           {
245             g2.setClip(clip);
246             super.peerPaint(g2, update);
247             peerPaintChildren(g2);
248           }
249         finally
250           {
251             g2.dispose();
252           }
253         g.drawImage(backbuffer, 0, 0, awtComponent);
254       }
255     else
256       {
257         super.peerPaint(g, update);
258         peerPaintChildren(g);
259       }
260   }
261
262   /**
263    * Determines if we should do double buffering or not.
264    *
265    * @return if we should do double buffering or not
266    */
267   private boolean isDoubleBuffering()
268   {
269     Object prop =
270       SystemProperties.getProperty("gnu.awt.swing.doublebuffering", "false");
271     return prop.equals("true");
272   }
273
274   /**
275    * Paints any heavyweight child components.
276    *
277    * @param g the graphics to use for painting
278    */
279   protected synchronized void peerPaintChildren(Graphics g)
280   {
281     // TODO: Is this the right painting order?
282     for (Iterator i = heavyweightDescendents.iterator(); i.hasNext();)
283       {
284         Component child = (Component) i.next();
285         ComponentPeer peer = child.getPeer();
286
287         if (peer instanceof SwingComponentPeer && child.isVisible())
288           {
289             // TODO: The translation here doesn't work for deeper
290             // nested children. Fix this!
291             Graphics g2 = g.create(child.getX(), child.getY(),
292                                    child.getWidth(), child.getHeight());
293             try
294               {
295                 // update() is only called for the topmost component if
296                 // necessary, all other components only get paint() called.
297                 ((SwingComponentPeer) peer).peerPaint(g2, false);
298               }
299             finally
300               {
301                 g2.dispose();
302               }
303           }
304       }
305   }
306
307   /**
308    * Handles mouse events by dispatching it to the correct component.
309    *
310    * @param ev the mouse event
311    */
312   protected void handleMouseEvent(MouseEvent ev)
313   {
314     Component comp = awtComponent.getComponentAt(ev.getPoint());
315     if(comp == null) comp = awtComponent;
316     ComponentPeer peer = comp.getPeer();
317     if (awtComponent != comp && !comp.isLightweight() && peer instanceof SwingComponentPeer)
318       {
319         ev.translatePoint(comp.getX(), comp.getY());
320         ev.setSource(comp);
321         ((SwingComponentPeer) peer).handleMouseEvent(ev);
322       }
323   }
324
325   /**
326    * Handles mouse events by dispatching it to the correct component.
327    *
328    * @param ev the mouse event
329    */
330   protected void handleMouseMotionEvent(MouseEvent ev)
331   {
332     Component comp = awtComponent.getComponentAt(ev.getPoint());
333     if (comp != null)
334       {
335         ComponentPeer peer = comp.getPeer();
336         if (awtComponent != comp && !comp.isLightweight() && peer instanceof SwingComponentPeer)
337           {
338             ev.translatePoint(comp.getX(), comp.getY());
339             ((SwingComponentPeer) peer).handleMouseMotionEvent(ev);
340           }
341       }
342   }
343   
344   /**
345    * Handles key events on the component. This is usually forwarded to the
346    * SwingComponent's processKeyEvent() method.
347    *
348    * @param e the key event
349    */
350   protected void handleKeyEvent(KeyEvent e)
351   {
352     Component owner = getFocusOwner();
353     if(owner != null)
354       owner.getPeer().handleEvent(e);
355     else 
356       super.handleKeyEvent(e);
357   }
358
359   private Component focusOwner = null;
360   
361   private Component getFocusOwner()
362   {
363       if(focusOwner == null)
364       {
365         for(Iterator iter=heavyweightDescendents.iterator(); iter.hasNext();)
366         {
367            Component child = (Component) iter.next();
368           if(child.isFocusable())
369           {
370               focusOwner = child;
371             break;
372           }          
373       }
374       }
375       return focusOwner;
376   }
377   
378 }