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

From: Pierre-Mikael Legris (perki_at_perki.com)
Date: 02/01/04


Date: 1 Feb 2004 01:58:15 -0800

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>
* 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;
  }
}



Relevant Pages

  • Tom Millers Skeletal Animation Problems, Please Help
    ... I know the mesh viewer works from DirectX SDK, ... private AnimationRootFrame rootFrame; ... private void CreateAnimation ... /// Draw a frame and all child and sibling frames ...
    (microsoft.public.win32.programmer.directx.managed)
  • Re: NonStatic erorr
    ... public void PrintName() ... private void button1_Click ... So for example you need to expose it from inside the Frame1 class ... class Frame1: Frame ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: NonStatic erorr
    ... private void button1_Click ... public dialog(config myConfigs) ... So for example you need to expose it from inside the Frame1 class ... class Frame1: Frame ...
    (microsoft.public.dotnet.languages.csharp)
  • Frames
    ... added onto the frame seems to expand to the size of the frame itself. ... private Frame registerPage = new Frame; ... private TextField userAddress = new TextField; ... private void jbInit() throws Exception { ...
    (comp.lang.java.help)
  • Re: Optimized Shadow Volume Rendering
    ... delta was employed, at a delta of 2,3 or 4 then the shadow started to ... Jack ... > (n frames below threshold could aggregate to significant distance). ... >> problems for high end systems that update every frame for a light that ...
    (microsoft.public.win32.programmer.directx.graphics)