001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.editor.ext;
043:
044: import java.awt.Color;
045: import java.awt.Component;
046: import java.awt.Dimension;
047: import java.awt.event.ActionEvent;
048: import java.awt.event.ActionListener;
049: import java.awt.event.KeyEvent;
050: import java.awt.event.MouseAdapter;
051: import java.awt.event.MouseListener;
052: import java.awt.event.MouseEvent;
053: import java.beans.PropertyChangeListener;
054: import java.beans.PropertyChangeEvent;
055: import java.util.Iterator;
056: import java.util.Map;
057:
058: import javax.swing.Action;
059: import javax.swing.ActionMap;
060: import javax.swing.BorderFactory;
061: import javax.swing.InputMap;
062: import javax.swing.JComponent;
063: import javax.swing.JScrollPane;
064: import javax.swing.JLabel;
065: import javax.swing.JList;
066: import javax.swing.KeyStroke;
067: import javax.swing.SwingUtilities;
068: import javax.swing.text.JTextComponent;
069:
070: import org.netbeans.editor.BaseKit;
071: import org.netbeans.editor.Settings;
072: import org.netbeans.editor.SettingsUtil;
073: import org.netbeans.editor.SettingsChangeListener;
074: import org.netbeans.editor.SettingsChangeEvent;
075: import org.netbeans.editor.Utilities;
076:
077: /**
078: * Pane displaying the completion view and accompanying components
079: * like label for title etc.
080: *
081: * @author Miloslav Metelka, Martin Roskanin
082: * @version 1.00
083: */
084:
085: public class ScrollCompletionPane extends JScrollPane implements
086: ExtCompletionPane, PropertyChangeListener,
087: SettingsChangeListener {
088:
089: private ExtEditorUI extEditorUI;
090:
091: private JComponent view;
092:
093: private JLabel topLabel;
094:
095: private Dimension minSize;
096:
097: private Dimension maxSize;
098:
099: private ViewMouseListener viewMouseL;
100:
101: private Dimension scrollBarSize;
102:
103: private Dimension minSizeDefault;
104:
105: public ScrollCompletionPane(ExtEditorUI extEditorUI) {
106: this .extEditorUI = extEditorUI;
107:
108: // Compute size of the scrollbars
109: Dimension smallSize = getPreferredSize();
110: setHorizontalScrollBarPolicy(HORIZONTAL_SCROLLBAR_ALWAYS);
111: setVerticalScrollBarPolicy(VERTICAL_SCROLLBAR_ALWAYS);
112: scrollBarSize = getPreferredSize();
113: scrollBarSize.width -= smallSize.width;
114: scrollBarSize.height -= smallSize.height;
115: setHorizontalScrollBarPolicy(HORIZONTAL_SCROLLBAR_AS_NEEDED);
116: setVerticalScrollBarPolicy(VERTICAL_SCROLLBAR_AS_NEEDED);
117:
118: // Make it invisible initially
119: super .setVisible(false);
120:
121: // Add the title component
122: installTitleComponent();
123:
124: // Add the completion view
125: CompletionView completionView = extEditorUI.getCompletion()
126: .getView();
127: if (completionView instanceof JComponent) {
128: view = (JComponent) completionView;
129: setViewportView(view);
130: }
131:
132: // Prevent the bug with displaying without the scrollbar
133: getViewport().setMinimumSize(new Dimension(4, 4));
134:
135: Settings.addSettingsChangeListener(this );
136:
137: viewMouseL = new ViewMouseListener();
138: synchronized (extEditorUI.getComponentLock()) {
139: // if component already installed in ExtEditorUI simulate installation
140: JTextComponent component = extEditorUI.getComponent();
141: if (component != null) {
142: propertyChange(new PropertyChangeEvent(extEditorUI,
143: ExtEditorUI.COMPONENT_PROPERTY, null, component));
144: }
145:
146: extEditorUI.addPropertyChangeListener(this );
147: }
148:
149: putClientProperty("HelpID", ScrollCompletionPane.class
150: .getName()); // !!! NOI18N
151: }
152:
153: public void settingsChange(SettingsChangeEvent evt) {
154: Class kitClass = Utilities.getKitClass(extEditorUI
155: .getComponent());
156:
157: if (kitClass != null) {
158: minSize = (Dimension) SettingsUtil.getValue(kitClass,
159: ExtSettingsNames.COMPLETION_PANE_MIN_SIZE,
160: ExtSettingsDefaults.defaultCompletionPaneMinSize);
161: minSizeDefault = new Dimension(minSize);
162: setMinimumSize(minSize);
163:
164: maxSize = (Dimension) SettingsUtil.getValue(kitClass,
165: ExtSettingsNames.COMPLETION_PANE_MAX_SIZE,
166: ExtSettingsDefaults.defaultCompletionPaneMaxSize);
167: setMaximumSize(maxSize);
168:
169: }
170: }
171:
172: public void propertyChange(PropertyChangeEvent evt) {
173: String propName = evt.getPropertyName();
174:
175: if (ExtEditorUI.COMPONENT_PROPERTY.equals(propName)) {
176: if (evt.getNewValue() != null) { // just installed
177:
178: settingsChange(null);
179:
180: if (view != null) {
181: // Add mouse listener
182: view.addMouseListener(viewMouseL);
183: }
184:
185: } else { // just deinstalled
186:
187: if (view != null) {
188: // Unregister Escape key
189: view.removeMouseListener(viewMouseL);
190: }
191: }
192: }
193: }
194:
195: public void setVisible(boolean visible) {
196: //new RuntimeException("ScrollCompletionPane.setVisible(" + visible + ")").printStackTrace();
197: if (view instanceof JList) {
198: JList listView = (JList) view;
199: listView.ensureIndexIsVisible(listView.getSelectedIndex());
200: }
201:
202: super .setVisible(visible);
203: }
204:
205: public void refresh() {
206: if (view instanceof JList) {
207: JList listView = (JList) view;
208: listView.ensureIndexIsVisible(listView.getSelectedIndex());
209: }
210:
211: SwingUtilities.invokeLater( // !!! ? is it needed
212: new Runnable() {
213: public void run() {
214: if (isShowing()) { // #18810
215: // extEditorUI.getPopupManager().reset(extEditorUI.getComponent());
216: revalidate();
217: }
218: }
219: });
220: }
221:
222: /** Set the title of the pane according to the completion query results. */
223: public void setTitle(String title) {
224: topLabel.setText(title);
225: }
226:
227: protected void installTitleComponent() {
228: topLabel = new JLabel();
229: topLabel.setForeground(Color.blue);
230: topLabel.setBorder(BorderFactory.createEmptyBorder(0, 2, 0, 2));
231: setColumnHeaderView(topLabel);
232: }
233:
234: protected Dimension getTitleComponentPreferredSize() {
235: return topLabel.getPreferredSize();
236: }
237:
238: public void setSize(int width, int height) {
239: int maxWidth = width;
240: int maxHeight = height;
241:
242: minSize.width = minSizeDefault.width;
243: minSize.height = minSizeDefault.height;
244: setMinimumSize(minSize);
245:
246: Dimension ps = getPreferredSize();
247:
248: /* Add size of the vertical scrollbar by default. This could be improved
249: * to be done only if the height exceeds the bounds. */
250: ps.width += scrollBarSize.width;
251: ps.width = Math.max(Math.max(ps.width, minSize.width),
252: getTitleComponentPreferredSize().width);
253:
254: maxWidth = Math.min(maxWidth, maxSize.width);
255: maxHeight = Math.min(maxHeight, maxSize.height);
256: boolean displayHorizontalScrollbar = (ps.width - scrollBarSize.width) > maxWidth;
257:
258: if (ps.width > maxWidth) {
259: ps.width = maxWidth;
260: if (displayHorizontalScrollbar) {
261: ps.height += scrollBarSize.height; // will show horizontal scrollbar
262: minSize.height += scrollBarSize.height;
263: setMinimumSize(minSize);
264: }
265:
266: }
267:
268: ps.height = Math.min(Math.max(ps.height, minSize.height),
269: maxHeight);
270: super .setSize(ps.width, ps.height);
271: }
272:
273: public void setSize(Dimension d) {
274: setSize(d.width, d.height);
275: }
276:
277: public JComponent getComponent() {
278: return this ;
279: }
280:
281: class ViewMouseListener extends MouseAdapter {
282:
283: public void mouseClicked(MouseEvent evt) {
284: if (SwingUtilities.isLeftMouseButton(evt)) {
285: JTextComponent component = extEditorUI.getComponent();
286: if (component != null && evt.getClickCount() == 2) {
287: JDCPopupPanel jdc = ExtUtilities
288: .getJDCPopupPanel(component);
289: if (jdc != null) {
290: Action a = jdc
291: .getActionMap()
292: .get(
293: JDCPopupPanel.COMPLETION_SUBSTITUTE_TEXT);
294: if (a != null) {
295: a.actionPerformed(new ActionEvent(
296: component,
297: ActionEvent.ACTION_PERFORMED, "")); // NOI18N
298: }
299: }
300: }
301: }
302: }
303: }
304:
305: }
|