Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / GUI / February 2004

Tip: Looking for answers? Try searching our database.

Problem while resizing JInternalFrame Modal + Solution to get Modal Floating Component

Thread view: 
Pierre-Mikael Legris - 01 Feb 2004 09:58 GMT
Hi,

Here is teh code I made to get Floating Modal Components on a Frame,
It works quite well, I still have a problem when creating Modal
JInternalFrame.. they desapear when resised.

I hope to find some help...

AnyWay If you don't need resizing this code shows no other problems
(yet?)

Regards

Pierre-Mikael Legris

------------------ ModalJpanel.java -------------
import java.awt.*;
import java.awt.event.*;

import javax.swing.*;
import javax.swing.event.*;
import javax.swing.event.InternalFrameListener;
import javax.swing.event.MouseInputAdapter;

/**
* Copyright 2004 SimpleData Sarl http://simpledata.ch<BR>
* Provided "As This" Can be used or modified freely as long as a
* reference to it's initial author and to SimpleData is kept.<BR><BR>
*
* <HR>
* A Container that shows up on a Frame as Modal<BR>
* Was initially written to get JInternalFrame as modal
* but it finally shows a great way of having floating
* Modal Components<BR>
* Known BUG: doesn't grab all keyboard strokes
* (exemple ALT+... for menus)<BR>
* Known BUG2: When using JInternalFrames, resizes makes it disapear
* for a totally unkown reason.<BR>
* @author Pierre-Mikael Legris http://simpledata.ch
*/
public class ModalJPanel  implements AWTEventListener {
 
 // to avoid loops
 private boolean closing = false;
 
 // the Frame I belong To
 private JFrame frame;
 
 // the GlassPane the frame has before mine
 private Component previousGlassPane;
 
 // the Glass to do the trick
 private JPanel glass;
 
 // I don't not trust isVisible() call ;)
 private boolean myVisible;
 
 // The Container I'm displaying
 private Container content;
 
 /**
 * Modal component that has the ability of
 * locking the actual JFrame. <BR>
 * If you extends this class or uses it without using
 * a createXXXX method
 * do not forget to create a way to call ModalJPanel.close()
 * @param origin the origin component to display it
 */
 public ModalJPanel(Container content,Component origin)  {
   this.content = content;
   myVisible = false;
   // get the first JFrame containing this Component
   frame = (JFrame)
   SwingUtilities.getAncestorOfClass(new Frame().getClass(), origin);
   if (frame == null) {
     System.out.println(
        "Cannot find a JFrame for component:"+origin);
     return;
   }
   
   // create opaque glass pane
   glass = new JPanel();
   glass.setLayout(null);
   glass.setOpaque(false);
   
   // Attach modal behavior to frame
   //    Associate dummy mouse listeners
   // Otherwise mouse events pass through
   MouseInputAdapter adapter =  new MouseInputAdapter(){};
   glass.addMouseListener(adapter);
   glass.addMouseMotionListener(adapter);
   glass.addMouseWheelListener(new MouseWheelListener() {
     public void mouseWheelMoved(MouseWheelEvent e) {
     }
   });
   
   //    Add this modal internal frame to glass pane
   glass.add(content);
   glass.setCursor(Cursor.getPredefinedCursor (Cursor.WAIT_CURSOR));
   glass.setSize(frame.getSize());
   
   content.setCursor(
     Cursor.getPredefinedCursor (Cursor.DEFAULT_CURSOR));
 }
 
 
 /**
 * close and release the glass Pane
 */
 public void close() {
   // Avoid infinite close loops
   if (closing) return;
   closing = true;
   
   // unregister listeners
   setVisible(false);
   
   // release the glass
   glass.removeAll();
   glass = null;
   
   // release my components
   content.removeAll();
   content = null;
 }
 
 /**
 * Override setVisible to install/remove key events
 * hook that will allow
 * us to disable key events when the glass pane is visible.
 */
 public void setVisible(boolean visible)
 {
   Toolkit tk = Toolkit.getDefaultToolkit();
   
   //    visible called and not visible yet
   if (visible && (! myVisible))
   {
     myVisible = true;
     
     // Grab key events
     tk.addAWTEventListener (this, AWTEvent.KEY_EVENT_MASK);
     
     
     //    store previous Pane .. dunno if it has any effect
     previousGlassPane = frame.getGlassPane();
     // Change glass pane to our panel
     frame.setGlassPane(glass);
     
     glass.setVisible(true);
     // refresh evreything!
     glass.revalidate();
     glass.requestFocus();
     content.requestFocus();
     frame.repaint();
   }
   
   // ! visible called and I'm visible
   if ((! visible) && myVisible) {
     myVisible = false;
     
     // Release key events
     tk.removeAWTEventListener (this);
     glass.setVisible(false);
     
     //    put the GlassPane Back in order
     frame.setGlassPane(previousGlassPane);
   }
   content.setVisible(visible);
 }
 
 /*
 * To grab all key events
 * @see java.awt.event.AWTEventListener#eventDispatched(java.awt.AWTEvent)
 */
 public void eventDispatched(AWTEvent event) {
   if (event instanceof KeyEvent &&
       event.getSource() instanceof Component)
   {
     Component destination =  (Component) event.getSource();
     // Destination is me or one of my fellows Components :) nice..
     if (SwingUtilities.isDescendingFrom(destination,content))
       return;
     
     
     JFrame master = (JFrame)
     SwingUtilities.getAncestorOfClass(new Frame().getClass(),
     destination);
     // Consume events only for our window
     if (master == this.frame)
       ((KeyEvent)event).consume();
   }
 }
 
 /**
 * Place smartly a component on a Container.
 * by preventing it from going out of a Frame.<BR>
 * Note: c.getSize() will be called and assumed as the final size
 * as well as c.getParent().getSize()
 * <B>Warning:</B> this method
 * MUST BE CALLED <B>AFTER</B> the Component
 * has been added!! and Container should have a null layout
 * @param desiredLocation is the prefered Location on this container
 * @param c the Component you want to display
 */
 public static void smartLocation(Point desiredLocation, Component c)
{
   Container master = c.getParent();
   // find out my JFrame
   if (master == null) return; // failed no Container
   
   Dimension masterD = master.getSize();
   Dimension cD = c.getSize();
   
   Point result = (Point) desiredLocation.clone();
   
   if ((result.getY() + cD.getHeight()) > masterD.getHeight())
     result.setLocation(result.getX(),masterD.getHeight()-cD.getHeight());
   if ((result.getX() + cD.getWidth()) > masterD.getWidth())
     result.setLocation(masterD.getWidth()-cD.getWidth(),result.getY());
   // allways prefers to left corner
   if (result.getX() < 0) result.setLocation(0d,result.getY());
   if (result.getY() < 0) result.setLocation(result.getX(),0d);
   // done
   c.setLocation(result);
 }
 
 /**
 * Do the Math for originLocation + delta
 */
 public static Point getDesiredLocation
 (Component c,Component origin,Point delta) {
   // set the location near it's origin
   Point pointOrigin =
   SwingUtilities.convertPoint(origin,0, 0, c.getParent());
   Point desiredLocation = new Point();
   desiredLocation.setLocation(pointOrigin.getX() + delta.getX(),
   pointOrigin.getY() + delta.getY());
   return desiredLocation;
 }
 
 //-------------------- CREATION ----------------------------//
 
 /**
 * Create a floating Modal JInternalFrame<BR>
 * <B>Placement</B><BR>
 * Assuming pointOrigin is the position of origin on the Frame:<BR>
 * the component will be placed at <BR>
 * (pointOrigin.x + delta.x, pointOrigin.y + delta y)<BR><BR>
 * <B>BUG!!</B> If you set resizable to true!! the
 * Jintenal Frame will disapear on resize!!
 * @param component the component to draw
 * @param origin the origin component to display it
 * @param delta the delta to apply to origin position.
 * @param resizable true if you want this frame to be resizable
 */
 public static ModalJPanel createSimpleModalJInternalFrame
 (Component component,Component origin,Point delta,boolean resizable)
{
   
   // create a JInternalFrame
   JInternalFrame jif = new JInternalFrame("",true,resizable);
   
   
   // get a ModalJpane containing this JIF
   final ModalJPanel result = new ModalJPanel(jif,origin);
   
   jif.addInternalFrameListener(new InternalFrameListener() {
     // add a listener to call ModalJpane.close();
     public void internalFrameClosed(InternalFrameEvent e) {
       result.close();           
     }
     public void internalFrameActivated(InternalFrameEvent e) {}
     public void internalFrameClosing(InternalFrameEvent e) {}
     public void internalFrameDeactivated(InternalFrameEvent e) {}
     public void internalFrameDeiconified(InternalFrameEvent e) {}
     public void internalFrameIconified(InternalFrameEvent e) {}
     public void internalFrameOpened(InternalFrameEvent e) {}
   });
   
   // add the component to the JInternalFrame
   jif.getContentPane().add(component);
   jif.setVisible(true);
   
   //        setThis item visible
   result.setVisible(true);
   
   // for a mysterious reason placement, position and
   // getPrefferdSize() gives valid result
   // only when result is Visible.. ???  
   
   jif.setSize(jif.getPreferredSize());
   smartLocation(getDesiredLocation(jif,origin,delta),jif);
   
   return result;
 }
 
 
 /**
 * Create a floating JPanel with a close button on it
 * Use this as an exemple If you want to use this class<BR><BR>
 * <B>Placement</B><BR>
 * Assuming pointOrigin is the position of origin on the Frame:<BR>
 * the component will be placed at <BR>
 * (pointOrigin.x + delta.x, pointOrigin.y + delta y)<BR><BR>
 * @param component the component to draw
 * @param origin the origin component to display it
 * @param delta the delta to apply to origin position.
 */
 public static ModalJPanel createSimpleModalJPanel
 (Component component,Component origin,Point delta) {
   Container c = new Container();
   final ModalJPanel result = new ModalJPanel(c,origin);
   
   //        ----------- ok now design of our popup ------------//
   c.setLayout(new BorderLayout());
   
   // close button
   JButton jb = new JButton("X");
   jb.addActionListener(new ActionListener() {
     public void actionPerformed(ActionEvent e) {
       result.close();
     }
   });
   
   // add Components
   c.add(jb,BorderLayout.NORTH);
   c.add(component,BorderLayout.CENTER);
   
   // debug COmponents
   c.add(new TextField(),BorderLayout.SOUTH);
   
   // setThis item visible
   result.setVisible(true);
   
   // for a mysterious reason placement, position and
   // getPrefferdSize() gives valid result
   // only when result is Visible.. ???  
   
   c.setSize(c.getPreferredSize());
   smartLocation(getDesiredLocation(c,origin,delta),c);
   
   return result;
 }
}
Pierre-Mikael Legris - 01 Feb 2004 15:10 GMT
Posting to publication tooks enough time to find a work around.

The problem is that something is calling setVisible(false) on the
glass..
which is not very convenient..

Now my glass overwrites JPanel's setVisible method, but.. this is just
a trick. And I'm not satisfied with it.. If would appreciate comments
or tips to do this in a better way.

BTW, I encountered problems with a JComBox that was displaying on the
GlassPane wich does mean UNDER my Component.. wasn't convenient
neither..
I used setLightWeightPopupEnabled(false) on the JCombox .. but I have
a problem with too .. comments, tips, etc.. welcome too :)

The class is "about" to be ready and some people may find it usefull .
It's visible on this web page:
http://simpledata.ch/public/ModalJPanel.java.html
(this is a modified version of what I posted previously)

Regards

PM Legris


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2009 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.