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.modules.progress.ui;
043:
044: import java.awt.Color;
045: import java.awt.Component;
046: import java.awt.Dimension;
047: import java.awt.Graphics;
048: import java.awt.GridLayout;
049: import java.awt.Insets;
050: import java.awt.Toolkit;
051: import java.awt.event.ActionEvent;
052: import java.awt.event.KeyEvent;
053: import java.util.HashSet;
054: import java.util.Iterator;
055: import javax.swing.AbstractAction;
056: import javax.swing.Action;
057: import javax.swing.BorderFactory;
058: import javax.swing.JComponent;
059: import javax.swing.JPanel;
060: import javax.swing.JScrollPane;
061: import javax.swing.KeyStroke;
062: import javax.swing.border.Border;
063: import org.netbeans.progress.spi.InternalHandle;
064:
065: /**
066: *
067: * @author mkleint
068: */
069: public class PopupPane extends JScrollPane {
070: private JPanel view;
071: private HashSet<ListComponent> listComponents;
072: /** Creates a new instance of PopupPane */
073: private ListComponent selected;
074:
075: public PopupPane() {
076: listComponents = new HashSet<ListComponent>();
077: view = new JPanel();
078: GridLayout grid = new GridLayout(0, 1);
079: grid.setHgap(0);
080: grid.setVgap(0);
081: view.setLayout(grid);
082: view.setBorder(BorderFactory.createEmptyBorder());
083: setName("progresspopup"); //NOI18N
084: setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
085: setViewportView(view);
086: setFocusable(true);
087: setRequestFocusEnabled(true);
088:
089: Action down = new MoveDownAction();
090: getActionMap().put("Move-Down", down);
091: getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0),
092: "Move-Down");
093: getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
094: KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0),
095: "Move-Down");
096:
097: Action up = new MoveUpAction();
098: getActionMap().put("Move-Up", up);
099: getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0),
100: "Move-Up");
101: getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
102: KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "Move-Up");
103: Action cancel = new CancelAction();
104: getActionMap().put("Cancel-Task", cancel);
105: getInputMap().put(
106: KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0),
107: "Cancel-Task");
108: getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
109: KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0),
110: "Cancel-Task");
111:
112: Action select = new SelectAction();
113: getActionMap().put("select-task", select);
114: getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0),
115: "select-task");
116: getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
117: KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0),
118: "select-task");
119:
120: setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
121: // addFocusListener(new FocusListener() {
122: // public void focusLost(java.awt.event.FocusEvent e) {
123: // System.out.println("popup focus gained temp?=" + e.isTemporary());
124: // }
125: //
126: // public void focusGained(java.awt.event.FocusEvent e) {
127: // System.out.println("popup focus lost temporary?=" + e.isTemporary());
128: // }
129: //
130: // });
131: }
132:
133: public void addListComponent(ListComponent lst) {
134: listComponents.add(lst);
135: if (view.getComponentCount() > 0) {
136: JComponent previous = (JComponent) view.getComponent(view
137: .getComponentCount() - 1);
138: previous.setBorder(new BottomLineBorder());
139: }
140: lst.setBorder(BorderFactory.createEmptyBorder());
141: view.add(lst);
142: if (listComponents.size() > 3) {
143: setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
144: } else {
145: setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
146: }
147: }
148:
149: public void removeListComponent(InternalHandle handle) {
150: Iterator it = listComponents.iterator();
151: while (it.hasNext()) {
152: ListComponent comp = (ListComponent) it.next();
153: if (comp.getHandle() == handle) {
154: view.remove(comp);
155: it.remove();
156: break;
157: }
158: }
159: if (listComponents.size() > 3) {
160: setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
161: } else {
162: setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
163: }
164: }
165:
166: public Dimension getPreferredSize() {
167: int count = view.getComponentCount();
168: int height = count > 0 ? view.getComponent(0)
169: .getPreferredSize().height : 0;
170: int offset = count > 3 ? height * 3 + 5 : (count * height) + 5;
171: // 22 is the width of the additional scrollbar
172: return new Dimension(count > 3 ? ListComponent.ITEM_WIDTH + 22
173: : ListComponent.ITEM_WIDTH + 2, offset);
174: }
175:
176: /**
177: * bold font is now used not only for explicitly selected items, but for any
178: * change in currently selected task.
179: */
180: public void updateBoldFont(InternalHandle handle) {
181: Iterator it = listComponents.iterator();
182: while (it.hasNext()) {
183: ListComponent comp = (ListComponent) it.next();
184: comp.markAsActive(handle == comp.getHandle());
185: }
186: }
187:
188: private static class BottomLineBorder implements Border {
189: private Insets ins = new Insets(0, 0, 1, 0);
190: private Color col = new Color(221, 229, 248);
191:
192: public BottomLineBorder() {
193: }
194:
195: public Insets getBorderInsets(Component c) {
196: return ins;
197: }
198:
199: public boolean isBorderOpaque() {
200: return false;
201: }
202:
203: public void paintBorder(Component c, Graphics g, int x, int y,
204: int width, int height) {
205: Color old = g.getColor();
206: g.setColor(col);
207: g.drawRect(x, y + height - 2, width, 1);
208: g.setColor(old);
209: }
210: }
211:
212: private int findIndex(Component comp) {
213: Component[] comps = view.getComponents();
214: for (int i = 0; i < comps.length; i++) {
215: if (comps[i] == comp) {
216: return i;
217: }
218: }
219: return -1;
220: }
221:
222: public void requestFocus() {
223: //#63666 - don't focus any of the tasks explicitly, wait for user action.
224: // if (view.getComponentCount() > 1) {
225: // if (selected == null || !selected.isDisplayable()) {
226: // selected = (ListComponent)view.getComponent(0);
227: // }
228: // selected.requestFocus();
229: // } else {
230: super .requestFocus();
231: // }
232: }
233:
234: private class MoveDownAction extends AbstractAction {
235:
236: MoveDownAction() {
237: }
238:
239: public void actionPerformed(ActionEvent actionEvent) {
240: int index = -1;
241: if (selected != null) {
242: index = findIndex(selected);
243: }
244: index = index + 1;
245: if (index >= PopupPane.this .view.getComponentCount()) {
246: index = 0;
247: }
248: selected = (ListComponent) PopupPane.this .view
249: .getComponent(index);
250: selected.requestFocus();
251: }
252:
253: }
254:
255: private class MoveUpAction extends AbstractAction {
256:
257: MoveUpAction() {
258: }
259:
260: public void actionPerformed(ActionEvent actionEvent) {
261: int index = PopupPane.this .view.getComponentCount();
262: if (selected != null) {
263: index = findIndex(selected);
264: // selected.setBackground(new Color(249, 249, 249));
265: }
266: index = index - 1;
267: if (index < 0) {
268: index = PopupPane.this .view.getComponentCount() - 1;
269: }
270: selected = (ListComponent) PopupPane.this .view
271: .getComponent(index);
272: selected.requestFocus();
273: // selected.setBackground(selectBgColor);
274: // selected.scrollRectToVisible(selected.getBounds());
275: }
276: }
277:
278: private class CancelAction extends AbstractAction {
279: public CancelAction() {
280: }
281:
282: public void actionPerformed(ActionEvent actionEvent) {
283: if (selected != null) {
284: Action act = selected.getCancelAction();
285: if (act != null) {
286: act.actionPerformed(actionEvent);
287: } else {
288: Toolkit.getDefaultToolkit().beep();
289: }
290: }
291: }
292: }
293:
294: private class SelectAction extends AbstractAction {
295: public SelectAction() {
296: }
297:
298: public void actionPerformed(ActionEvent actionEvent) {
299: if (selected != null) {
300: selected.getHandle().requestExplicitSelection();
301: }
302: }
303: }
304:
305: private class ViewAction extends AbstractAction {
306: public ViewAction() {
307: }
308:
309: public void actionPerformed(ActionEvent actionEvent) {
310: if (selected != null) {
311: selected.getHandle().requestView();
312: }
313: }
314: }
315:
316: }
|