Source code: com/maddyhome/idea/vim/ui/ExEntryPanel.java
1 package com.maddyhome.idea.vim.ui;
2
3 /*
4 * IdeaVim - A Vim emulator plugin for IntelliJ Idea
5 * Copyright (C) 2003 Rick Maddy
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22 import com.intellij.openapi.actionSystem.DataContext;
23 import com.intellij.openapi.diagnostic.Logger;
24 import com.intellij.openapi.editor.Editor;
25 import java.awt.Color;
26 import java.awt.Component;
27 import java.awt.Container;
28 import java.awt.Font;
29 import java.awt.GridBagConstraints;
30 import java.awt.GridBagLayout;
31 import java.awt.KeyboardFocusManager;
32 import java.awt.Point;
33 import java.awt.Rectangle;
34 import java.awt.event.ComponentAdapter;
35 import java.awt.event.ComponentEvent;
36 import javax.swing.BorderFactory;
37 import javax.swing.JComponent;
38 import javax.swing.JLabel;
39 import javax.swing.JPanel;
40 import javax.swing.JRootPane;
41 import javax.swing.JScrollPane;
42 import javax.swing.KeyStroke;
43 import javax.swing.SwingUtilities;
44
45 /**
46 * This is used to enter ex commands such as searches and "colon" commands
47 * TODO - support complete set of command line editing keys
48 * TODO - redo focus change support to work like MorePanel
49 */
50 public class ExEntryPanel extends JPanel
51 {
52 public static ExEntryPanel getInstance()
53 {
54 if (instance == null)
55 {
56 instance = new ExEntryPanel();
57 }
58
59 return instance;
60 }
61
62 private ExEntryPanel()
63 {
64 setBorder(BorderFactory.createEtchedBorder());
65
66 Font font = new Font("Monospaced", Font.PLAIN, 12);
67 label = new JLabel(" ");
68 label.setFont(font);
69 entry = new ExTextField();
70 entry.setFont(font);
71 entry.setBorder(null);
72
73 setForeground(entry.getForeground());
74 setBackground(entry.getBackground());
75
76 label.setForeground(entry.getForeground());
77 label.setBackground(entry.getBackground());
78
79 GridBagLayout layout = new GridBagLayout();
80 GridBagConstraints gbc = new GridBagConstraints();
81
82 setLayout(layout);
83 gbc.gridx = 0;
84 layout.setConstraints(this.label, gbc);
85 add(this.label);
86 gbc.gridx = 1;
87 gbc.weightx = 1.0;
88 gbc.fill = GridBagConstraints.HORIZONTAL;
89 layout.setConstraints(entry, gbc);
90 add(entry);
91 setBorder(BorderFactory.createLineBorder(Color.BLACK));
92
93 newGlass = new CommandEntryGlass();
94 newGlass.add(this);
95 newGlass.addComponentListener(new ComponentAdapter() {
96 public void componentResized(ComponentEvent e)
97 {
98 positionPanel();
99 }
100 });
101 }
102
103 /**
104 * Turns on the ex entry field for the given editor
105 * @param editor The editor to use for dislay
106 * @param context The data context
107 * @param label The label for the ex entry (i.e. :, /, or ?)
108 * @param initText The initial text for the entry
109 * @param count A holder for the ex entry count
110 */
111 public void activate(Editor editor, DataContext context, String label, String initText, int count)
112 {
113 last = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
114 entry.setEditor(editor, context);
115 JComponent comp = editor.getContentComponent();
116 this.label.setText(label);
117 this.count = count;
118 entry.setDocument(entry.createDefaultModel());
119 entry.setText(initText);
120 parent = comp;
121 root = SwingUtilities.getRootPane(parent);
122 oldGlass = root.getGlassPane();
123 root.setGlassPane(newGlass);
124
125 positionPanel();
126
127 newGlass.setVisible(true);
128 entry.requestFocus();
129 active = true;
130 }
131
132 /**
133 * Gets the label for the ex entry. This should be one of ":", "/", or "?"
134 * @return The ex entry label
135 */
136 public String getLabel()
137 {
138 return label.getText();
139 }
140
141 /**
142 * Gets the count given during activation
143 * @return The count
144 */
145 public int getCount()
146 {
147 return count;
148 }
149
150 /**
151 * Pass the keystroke on to the text edit for handling
152 * @param stroke The keystroke
153 */
154 public void handleKey(KeyStroke stroke)
155 {
156 entry.handleKey(stroke);
157 }
158
159 private void positionPanel()
160 {
161 if (parent == null) return;
162
163 Container scroll = SwingUtilities.getAncestorOfClass(JScrollPane.class, parent);
164 int height = (int)getPreferredSize().getHeight();
165 Rectangle bounds = scroll.getBounds();
166 bounds.translate(0, scroll.getHeight() - height);
167 bounds.height = height;
168 Point pos = SwingUtilities.convertPoint(scroll.getParent(), bounds.getLocation(), newGlass);
169 bounds.setLocation(pos);
170 setBounds(bounds);
171 repaint();
172 }
173
174 /**
175 * Gets the text entered by the user. This includes any initial text but does not include the label
176 * @return The user entered text
177 */
178 public String getText()
179 {
180 return entry.getText();
181 }
182
183 /**
184 * Turns off the ex entry field and puts the focus back to the original component
185 * @param changeFocus true if focus should be put back, false if not
186 */
187 public void deactivate(boolean changeFocus)
188 {
189 logger.info("deactivate");
190 if (!active) return;
191 active = false;
192 newGlass.setVisible(false);
193 root.setGlassPane(oldGlass);
194 if (changeFocus)
195 {
196 logger.debug("parent.requestFocus()");
197 //parent.requestFocus();
198 last.requestFocus();
199 }
200 parent = null;
201 }
202
203 /**
204 * Checks if the ex entry panel is currently active
205 * @return true if active, false if not
206 */
207 public boolean isActive()
208 {
209 return active;
210 }
211
212 class CommandEntryGlass extends JPanel
213 {
214 CommandEntryGlass()
215 {
216 setLayout(null);
217 setOpaque(false);
218 }
219 }
220
221 private JComponent parent;
222 private JLabel label;
223 private ExTextField entry;
224 private JPanel newGlass;
225 private Component oldGlass;
226 private JRootPane root;
227 private int count;
228 private Component last;
229
230 private boolean active;
231
232 private static ExEntryPanel instance;
233
234 private static Logger logger = Logger.getInstance(ExEntryPanel.class.getName());
235 }