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

Quick Search    Search Deep

Source code: com/yaftp/utils/ExtendedDesktopPane.java


1    /**
2    *
3    * CopyRights Jean-Yves MENGANT 1999,2000,2001,2002
4    *
5    * This program is free software; you can redistribute it and/or
6    * modify it under the terms of the GNU General Public License
7    * as published by the Free Software Foundation; either version 2
8    * of the License, or any later version.
9    *
10   * This program is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   * GNU General Public License for more details.
14   *
15   * You should have received a copy of the GNU General Public License
16   * along with this program; if not, write to the Free Software
17   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18   */
19  package com.yaftp.utils ;
20  
21  import javax.swing.*;
22  import java.awt.*;
23  import java.awt.event.*;
24  
25  /**
26  
27    this components simulates a MDI like framework
28  
29    A desktop pane that supports tiling and cascading
30    NB : a null layoutManager is associated with this class ,
31    caller should be cautious since some of the algorithms used
32    inside suppose that the JDesktopPane is known
33  
34    @author Jean-Yves MENGANT
35  
36  
37  */
38  
39  public class ExtendedDesktopPane
40  extends JDesktopPane {
41  
42    private final ImageIcon _TILE_ICON_  =  new ImageIcon(
43                                   getClass().getResource("images/tiled.gif") ,
44                                                          "tiled"
45                                                          ) ;
46  
47    private final ImageIcon _CASCADE_ICON_  =  new ImageIcon(
48                                   getClass().getResource("images/cascade.gif") ,
49                                                          "cascade"
50                                                          ) ;
51  
52    protected int nextX;    // Next X position
53    protected int nextY;    // Next Y position
54    protected int offsetX = DEFAULT_OFFSETX;
55    protected int offsetY = DEFAULT_OFFSETY;
56  
57    protected static final int DEFAULT_OFFSETX = 24;
58    protected static final int DEFAULT_OFFSETY = 24;
59    protected static final int UNUSED_HEIGHT = 48;
60  
61    /** defaulted to tile */
62    protected boolean _cascaded = false ;
63  
64    /** used for debugging purposes if set to true */
65    private boolean _debug = false ;
66  
67    private JFrame _parent ;
68  
69    public void set_parent( JFrame parent )
70    { _parent = parent ; }
71  
72    /**
73      provide a reasonable preffered size
74    */
75    public Dimension getPreferredSize()
76    { return new Dimension(400,200) ; }
77  
78    /**
79      Layout all of the children of this container
80      so that they are cascaded.
81    */
82    public void cascadeAll()
83    {
84    Component[] comps = getComponents();
85    int count = comps.length;
86      nextX = 0;
87      nextY = 0;
88      for (int i = count - 1; i >= 0; i--)
89      {
90      Component comp = comps[i];
91        if (comp instanceof JInternalFrame && comp.isVisible())
92          cascade(comp);
93      }
94    }
95  
96    /**
97      Layout all of the children of this container
98      so that they are tiled.
99    */
100   public void tileAll()
101   {
102   DesktopManager manager = getDesktopManager();
103     // No desktop manager - do nothing
104     if (manager == null)
105       return;
106 
107     Component[] comps = getComponents();
108     Component comp;
109     int count = 0;
110     // Count and handle only the internal frames
111     for (int i = 0; i < comps.length; i++)
112     {
113       comp = comps[i];
114       if (comp instanceof JInternalFrame && comp.isVisible())
115       count++;
116     }
117     if (count != 0)
118     {
119     double root = Math.sqrt((double)count);
120     int rows = (int)root;
121     int columns = count/rows;
122     int spares = count - (columns * rows);
123     Dimension paneSize = getSize();
124     if ( _debug )
125       System.out.println("paneSize="+paneSize) ;
126     int columnWidth = paneSize.width/columns;
127     // We leave some space at the bottom that doesn't get covered
128     int availableHeight = paneSize.height - UNUSED_HEIGHT;
129     // int availableHeight = paneSize.height;
130     int mainHeight = availableHeight/rows;
131     int smallerHeight = availableHeight/(rows + 1);
132     int rowHeight = mainHeight;
133     int x = 0;
134     int y = 0;
135     int thisRow = rows;
136     int normalColumns = columns - spares;
137       for (int i = comps.length - 1; i >= 0; i--)
138       {
139         comp = comps[i];
140         if (comp instanceof JInternalFrame && comp.isVisible())
141         {
142           manager.setBoundsForFrame((JComponent)comp, x, y, columnWidth, rowHeight);
143           y += rowHeight;
144           if (--thisRow == 0)
145           {
146             // Filled the row
147             y = 0;
148             x += columnWidth;
149             // Switch to smaller rows if necessary
150             if (--normalColumns <= 0)
151             {
152               thisRow = rows + 1;
153               rowHeight = smallerHeight;
154             }
155             else
156               thisRow = rows;
157           }
158         }
159       }
160     }
161   }
162 
163   /**
164     Place a component so that it is cascaded
165     relative to the previous one
166   */
167   protected void cascade(Component comp)
168   {
169   Dimension paneSize = getSize();
170   int targetWidth = 3 * paneSize.width/4;
171   int targetHeight = 3 * paneSize.height/4;
172   DesktopManager manager = getDesktopManager();
173     if (manager == null)
174     {
175       comp.setBounds(0, 0, targetWidth, targetHeight);
176       return;
177     }
178     if (nextX + targetWidth > paneSize.width ||
179       nextY + targetHeight > paneSize.height)
180     {
181       nextX = 0;
182       nextY = 0;
183     }
184 
185     manager.setBoundsForFrame((JComponent)comp, nextX, nextY, targetWidth, targetHeight);
186     nextX += offsetX;
187     nextY += offsetY;
188   }
189 
190   private void tileOrCascadeAll()
191   {
192     if ( _cascaded )
193       cascadeAll() ;
194     else
195       tileAll() ;
196     revalidate() ;
197   }
198 
199   /*
200     add internal Frame in a thread safe way since this component
201     is not guaranteed to be invoked from the Swing Event thread
202     ( this is the case when an FTP document is requested through
203       the FTP data thread )
204   */
205   class _SWING_THREAD_SAFE_ADD_INTERNALFRAME_
206   extends Thread
207   {
208     private String _title ;
209     private Component _comp ;
210 
211     public _SWING_THREAD_SAFE_ADD_INTERNALFRAME_( String title ,
212                                                   Component comp
213                                                 )
214     {
215       _title = title ;
216       _comp = comp   ;
217     }
218 
219     public void addComponent()
220     {
221     if ( _comp == null )
222       return ; // Os dependent editors send null Java component to this method
223     JInternalFrame frame = new JInternalFrame( _title , true , true , true , true ) ;
224 
225       // this hardcoded preffered size is candidate for later improvements
226       int preferredWidth = _comp.getPreferredSize().width ;
227       int preferredHeight = _comp.getPreferredSize().height ;
228 
229       frame.setPreferredSize( new Dimension( preferredWidth,preferredHeight) );
230       frame.getContentPane().setLayout( new GridLayout(1,1) ) ;
231       frame.getContentPane().add( _comp ) ;
232       frame.setVisible(true) ;
233 
234       ExtendedDesktopPane.this.add( frame ) ;
235 
236       Dimension currentSize = getSize() ;
237 
238       if ( ( currentSize.width == 0 ) ||
239            ( currentSize.height == 0 )
240          )
241       {
242         //ExtendedDesktopPane.this.addNotify() ;
243         if ( _parent != null )
244         {
245           _parent.pack() ;
246           tileOrCascadeAll() ;
247         }
248         else
249           frame.setBounds( 0, 0 , preferredWidth , preferredHeight );
250       }
251       else
252         tileOrCascadeAll() ;
253     }
254 
255     public void run()
256     {
257        if ( _debug  )
258          System.out.println("thread safe add") ;
259        addComponent() ;
260     }
261 
262   }
263 
264   /**
265     build a new JInternalFrame with given panel
266     and add it to the current list
267     This is done in a Swing THREAD SAFE way
268 
269   */
270   public void addComponent( String title ,
271                             Component comp
272                           )
273   {
274   _SWING_THREAD_SAFE_ADD_INTERNALFRAME_ t = new _SWING_THREAD_SAFE_ADD_INTERNALFRAME_(title,comp) ;
275     SwingUtilities.invokeLater( t ) ;
276     // t.addComponent() ;
277   }
278 
279 
280   class _TILE_FRAME_
281   implements ActionListener {
282     public void actionPerformed( ActionEvent e )
283     {
284       _cascaded = false ;
285       tileOrCascadeAll() ;
286     }
287   }
288 
289   class _CASCADE_FRAME_
290   implements ActionListener {
291 
292     public void actionPerformed( ActionEvent e )
293     {
294       _cascaded = true ;
295       tileOrCascadeAll() ;
296     }
297   }
298 
299   class _TEST_DOCUMENT_
300   extends SwingEditorPanePanel
301   {
302     public _TEST_DOCUMENT_()
303     throws UtilsError
304     {
305       setEditorKit( SwingEditorPanePanel.HTML );
306       load("<H1>Hello world</H1>") ;
307     }
308   }
309 
310   class _ADD_FRAME_ implements ActionListener {
311 
312     public void actionPerformed( ActionEvent e )
313     {
314       try {
315         addComponent( "test panell" ,  new _TEST_DOCUMENT_() ) ;
316       } catch ( UtilsError f )
317       { System.out.println("document load failed : " + f.getMessage() ) ; }
318     }
319   }
320 
321   /**
322     debug mode method
323   */
324   public SwingEditorPanePanel newTestDocument()
325   {
326     try {
327       return new _TEST_DOCUMENT_() ;
328     } catch ( UtilsError f )
329     { System.out.println("document load failed : " + f.getMessage() ) ; }
330     return null ;
331   }
332 
333   public ExtendedDesktopPane()
334   {
335     super() ;
336     // this.addComponentListener( listener );
337     SwingComponentPopup panePopup = new SwingComponentPopup(this) ;
338     // adding some specific menuItems to the _parent provided windowMenu
339     panePopup.addMenuItem( "tile internal frames" ,
340                             new _TILE_FRAME_() ,
341                             _TILE_ICON_
342                            ) ;
343     panePopup.addMenuItem( "cascade internal frames"  ,
344                            new _CASCADE_FRAME_() ,
345                            _CASCADE_ICON_
346                          ) ;
347 
348     if ( _debug )
349     {
350       panePopup.addMenuItem( "add new test frame"  ,
351                              new _ADD_FRAME_()
352                            ) ;
353     }
354   }
355 
356   public static void main ( String args[] )
357   {
358 
359     JFrame f = new JFrame("Testing ExtendedDesktopPane")  ;
360     f.setForeground(Color.black) ;
361     f.setBackground(Color.lightGray) ;
362     f.getContentPane().setLayout(new BorderLayout() ) ;
363     f.addWindowListener
364     (
365     // Exit the debug window frame
366       new WindowAdapter() {
367       public void windowClosing( WindowEvent e )
368       { System.exit(0)  ; }
369     }
370 
371     ) ;
372 
373     JTabbedPane tabPanel = new JTabbedPane() ;
374 
375     ExtendedDesktopPane intFrame = new ExtendedDesktopPane() ;
376     intFrame.setVisible(true) ;
377     intFrame.setPreferredSize(new Dimension(400,200)) ;
378     SwingMessageArea message = new SwingMessageArea()  ;
379     message.headerFooter("test");
380     message.headerFooter("test");
381     JButton b = new JButton ("Add Frame") ;
382     // b.addActionListener( new _ADD_FRAME_(intFrame) ) ;
383     JPanel buttonPanel = new JPanel() ;
384     buttonPanel.setLayout( new FlowLayout() ) ;
385     buttonPanel.add(b) ;
386 
387     // build the vsplit pane
388     JSplitPane vSplit = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT ,
389                                         buttonPanel  ,
390                                         intFrame
391                                        ) ;
392     vSplit.setOneTouchExpandable(true);
393     vSplit.setContinuousLayout(true) ;
394 
395     String ftpTitle = "test Panel" ;
396     JPanel testPanel = new JPanel() ;
397     testPanel.setLayout( new BorderLayout() ) ;
398     testPanel.add( BorderLayout.CENTER , new JButton("test panel") ) ;
399 
400     tabPanel.addTab( ftpTitle ,
401                      null ,
402                      testPanel ,
403                      "test panel"
404                    ) ;
405 
406     ftpTitle = "FTP connection" ;
407     tabPanel.addTab( ftpTitle ,
408                      null ,
409                      vSplit ,
410                      "tab test Panel "
411                    ) ;
412 
413     f.getContentPane().add( "Center", tabPanel ) ;
414     intFrame.set_parent(f);
415     intFrame.addComponent( "test " ,  intFrame.newTestDocument() ) ;
416 
417     f.pack() ;
418 
419     f.setVisible(true) ;
420   }
421 
422 }