24babda6be342ea3f526ecd0bcf8972595f86e28
[jalview.git] / src / jalview / gui / SplitFrame.java
1 package jalview.gui;
2
3 import jalview.jbgui.GSplitFrame;
4
5 import java.awt.Component;
6 import java.awt.MouseInfo;
7 import java.awt.Point;
8 import java.awt.Rectangle;
9 import java.awt.event.ActionEvent;
10 import java.awt.event.ActionListener;
11 import java.awt.event.KeyAdapter;
12 import java.awt.event.KeyEvent;
13 import java.awt.event.KeyListener;
14 import java.util.Map.Entry;
15
16 import javax.swing.AbstractAction;
17 import javax.swing.JComponent;
18 import javax.swing.KeyStroke;
19 import javax.swing.event.InternalFrameAdapter;
20 import javax.swing.event.InternalFrameEvent;
21
22 public class SplitFrame extends GSplitFrame
23 {
24   private static final long serialVersionUID = 1L;
25
26   public SplitFrame(JComponent top, JComponent bottom)
27   {
28     super(top, bottom);
29     init();
30   }
31
32   /**
33    * Initialise this frame.
34    */
35   protected void init()
36   {
37     setSize(AlignFrame.DEFAULT_WIDTH, Desktop.instance.getHeight() - 20);
38
39     addCloseFrameListener();
40     
41     addKeyListener();
42
43     addKeyBindings();
44
45   }
46
47   /**
48    * Add a listener to tidy up when the frame is closed.
49    */
50   protected void addCloseFrameListener()
51   {
52     addInternalFrameListener(new InternalFrameAdapter()
53     {
54       @Override
55       public void internalFrameClosed(InternalFrameEvent evt)
56       {
57         if (getTopComponent() instanceof AlignFrame)
58         {
59           ((AlignFrame) getTopComponent())
60                   .closeMenuItem_actionPerformed(true);
61         }
62         if (getBottomComponent() instanceof AlignFrame)
63         {
64           ((AlignFrame) getBottomComponent())
65                   .closeMenuItem_actionPerformed(true);
66         }
67       };
68     });
69   }
70
71   /**
72    * Add a key listener that delegates to whichever split component the mouse is
73    * in (or does nothing if neither).
74    */
75   protected void addKeyListener()
76   {
77     // TODO Key Bindings rather than KeyListener are recommended for Swing
78     addKeyListener(new KeyAdapter() {
79
80       @Override
81       public void keyPressed(KeyEvent e)
82       {
83         Component c = getComponentAtMouse();
84         if (c != null)
85         {
86           for (KeyListener kl : c.getKeyListeners())
87           {
88             kl.keyPressed(e);
89           }
90         }
91       }
92
93       @Override
94       public void keyReleased(KeyEvent e)
95       {
96         Component c = getComponentAtMouse();
97         if (c != null)
98         {
99           for (KeyListener kl : c.getKeyListeners())
100           {
101             kl.keyReleased(e);
102           }
103         }
104       }
105       
106     });
107   }
108
109   /**
110    * Returns the split pane component the mouse is in, or null if neither.
111    * 
112    * @return
113    */
114   protected Component getComponentAtMouse()
115   {
116     Point loc = MouseInfo.getPointerInfo().getLocation();
117     
118     if (isIn(loc, getTopComponent())) {
119       return getTopComponent();
120     }
121     else if (isIn(loc, getBottomComponent()))
122     {
123       return getBottomComponent();
124     }
125     return null;
126   }
127
128   private boolean isIn(Point loc, JComponent comp)
129   {
130     Point p = comp.getLocationOnScreen();
131     Rectangle r = new Rectangle(p.x, p.y, comp.getWidth(), comp.getHeight());
132     return r.contains(loc);
133   }
134
135   /**
136    * Set key bindings (recommended for Swing over key accelerators). For now,
137    * delegate to the corresponding key accelerator for the AlignFrame that the
138    * mouse is in. Hopefully can be simplified in future if AlignFrame is changed
139    * to use key bindings rather than accelerators.
140    */
141   private void addKeyBindings()
142   {
143     if (getTopComponent() instanceof AlignFrame)
144     {
145       for (Entry<KeyStroke, ActionListener> acc : ((AlignFrame) getTopComponent())
146               .getAccelerators().entrySet())
147       {
148
149         final KeyStroke ks = acc.getKey();
150         this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(ks, ks);
151         this.getActionMap().put(ks, new AbstractAction()
152         {
153           @Override
154           public void actionPerformed(ActionEvent e)
155           {
156             Component c = getComponentAtMouse();
157             if (c instanceof AlignFrame)
158             {
159               ((AlignFrame) c).getAccelerators().get(ks)
160                       .actionPerformed(null);
161             }
162           }
163         });
164       }
165       /*
166        * Disable unwanted here
167        */
168       // X expand views - wrecks the split pane view
169       this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).remove(
170               KeyStroke.getKeyStroke(KeyEvent.VK_X, 0, false));
171     }
172   }
173 }