| 1 | /* |
| 2 | * $Id: JEmbeddedFrame.java,v 1.6 2006/03/07 23:30:50 hastings Exp $ |
| 3 | * |
| 4 | * (c) Copyright, Moebius Solutions, Inc., 2004 |
| 5 | * |
| 6 | * All Rights Reserved |
| 7 | * |
| 8 | * This material may be reproduced by or for the U. S. Government |
| 9 | * pursuant to the copyright license under the clause at |
| 10 | * DFARS 252.227-7014 (OCT 2001). |
| 11 | */ |
| 12 | |
| 13 | package com.moesol.ui; |
| 14 | |
| 15 | import java.awt.event.ActionEvent; |
| 16 | import java.awt.event.ActionListener; |
| 17 | import java.awt.event.HierarchyEvent; |
| 18 | import java.awt.event.HierarchyListener; |
| 19 | import java.awt.event.WindowAdapter; |
| 20 | import java.awt.event.WindowEvent; |
| 21 | import java.util.logging.Level; |
| 22 | import java.util.logging.Logger; |
| 23 | |
| 24 | import javax.swing.JFrame; |
| 25 | import javax.swing.Timer; |
| 26 | |
| 27 | import com.moesol.bindings.platform_sdk.windows_api.HWND; |
| 28 | |
| 29 | |
| 30 | /** |
| 31 | * @author robert |
| 32 | */ |
| 33 | public class JEmbeddedFrame extends JFrame { |
| 34 | private static final Logger s_logger = Logger.getLogger(JEmbeddedFrame.class.getName()); |
| 35 | public static final int DEFAULT_REPAINT_PERIOD = 500; |
| 36 | |
| 37 | private HWND m_hwnd_parent; |
| 38 | private HWND m_hwnd; |
| 39 | private Timer m_paint_timer = null; |
| 40 | |
| 41 | public JEmbeddedFrame(HWND hwnd) { |
| 42 | s_logger.log(Level.FINEST, "Created JEmbeddedFrame, parent={0}", hwnd); |
| 43 | m_hwnd_parent = hwnd; |
| 44 | setUndecorated(true); |
| 45 | setLocation(0, 0); |
| 46 | addHierarchyListener(new EmbedOnDisplay()); |
| 47 | addWindowListener(new WindowAdapter() { |
| 48 | public void windowClosed(WindowEvent arg0) { |
| 49 | stopRepaintTimer(); |
| 50 | } |
| 51 | }); |
| 52 | setVisible(true); |
| 53 | } |
| 54 | |
| 55 | private class EmbedOnDisplay implements HierarchyListener { |
| 56 | public void hierarchyChanged(HierarchyEvent e) { |
| 57 | if (!isDisplayabilityChange(e)) { return; } |
| 58 | if (!isDisplayable()) { |
| 59 | m_hwnd = null; |
| 60 | return; |
| 61 | } |
| 62 | m_hwnd = jni_getHwnd(); |
| 63 | if (m_hwnd == null) { |
| 64 | throw new RuntimeException("Displayable, but no HWND"); |
| 65 | } |
| 66 | |
| 67 | if (m_hwnd_parent == null) { return; } |
| 68 | jni_reparentWindow(m_hwnd, m_hwnd_parent); |
| 69 | } |
| 70 | private boolean isDisplayabilityChange(HierarchyEvent e) { |
| 71 | return (0 != (HierarchyEvent.DISPLAYABILITY_CHANGED & e.getChangeFlags())); |
| 72 | } |
| 73 | } |
| 74 | private native HWND jni_getHwnd(); |
| 75 | private native boolean jni_reparentWindow(HWND hwnd, HWND hwnd_parent); |
| 76 | |
| 77 | /** |
| 78 | * This method starts a repaint timer that will repaint this frame every |
| 79 | * half second. This is a hack that fixes up a few repaint problems we have |
| 80 | * with this window when embedded. You should only call this method if you |
| 81 | * are experiencing repaint problems and your window can afford to be |
| 82 | * repainted every half second. |
| 83 | */ |
| 84 | public void startRepaintTimer() { |
| 85 | startRepaintTimer(DEFAULT_REPAINT_PERIOD); |
| 86 | } |
| 87 | public void startRepaintTimer(int period) { |
| 88 | if (m_paint_timer == null) { |
| 89 | m_paint_timer = createRepaintTimer(); |
| 90 | } |
| 91 | m_paint_timer.setCoalesce(true); |
| 92 | m_paint_timer.setInitialDelay(period); |
| 93 | m_paint_timer.setDelay(period); |
| 94 | m_paint_timer.setRepeats(true); |
| 95 | m_paint_timer.setLogTimers(false); |
| 96 | m_paint_timer.start(); |
| 97 | } |
| 98 | |
| 99 | public void stopRepaintTimer() { |
| 100 | if (m_paint_timer == null) { |
| 101 | return; |
| 102 | } |
| 103 | m_paint_timer.stop(); |
| 104 | } |
| 105 | |
| 106 | private Timer createRepaintTimer() { |
| 107 | return new Timer(DEFAULT_REPAINT_PERIOD, new ActionListener() { |
| 108 | public void actionPerformed(ActionEvent arg0) { |
| 109 | repaint(); |
| 110 | } |
| 111 | }); |
| 112 | } |
| 113 | } |
| 114 | |