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.palette.ui;
043:
044: import org.netbeans.modules.palette.Category;
045: import org.netbeans.modules.palette.CategoryListener;
046: import org.netbeans.modules.palette.Item;
047: import org.netbeans.modules.palette.Settings;
048: import org.netbeans.modules.palette.Utils;
049: import org.openide.util.Utilities;
050:
051: import javax.swing.*;
052: import javax.swing.border.EmptyBorder;
053: import javax.swing.event.ListSelectionEvent;
054: import javax.swing.event.ListSelectionListener;
055: import java.awt.*;
056: import java.awt.event.MouseListener;
057: import java.awt.event.MouseEvent;
058: import java.awt.event.MouseAdapter;
059:
060: /**
061: * A visual component for a single palette category. Contains expand/collapse button
062: * and a list of palette items.
063: *
064: * @author David Kaspar, Jan Stola, S. Aubrecht
065: */
066: class CategoryDescriptor implements CategoryListener {
067: private PalettePanel palettePanel;
068: private Category category;
069: private JPanel wholePanel;
070: private CategoryButton categoryButton;
071: private CategoryList itemsList;
072: private DefaultListModel itemsListModel;
073: private boolean opened;
074: private boolean resetItems = true;
075: private Settings settings;
076:
077: CategoryDescriptor(PalettePanel palettePanel, Category category) {
078: assert palettePanel != null : "No palette panel"; // NOI18N
079: assert category != null : "No category node"; // NOI18N
080: this .palettePanel = palettePanel;
081: this .category = category;
082: this .settings = palettePanel.getSettings();
083: wholePanel = new JPanel() {
084: public void addNotify() {
085: super .addNotify();
086: CategoryDescriptor.this .category
087: .addCategoryListener(CategoryDescriptor.this );
088: }
089:
090: public void removeNotify() {
091: super .removeNotify();
092: CategoryDescriptor.this .category
093: .removeCategoryListener(CategoryDescriptor.this );
094: }
095: };
096:
097: wholePanel.setLayout(new GridBagLayout());
098: wholePanel.setBorder(new EmptyBorder(0, 0, 0, 0));
099:
100: MouseListener listener = createMouseListener();
101:
102: categoryButton = new CategoryButton(this , category);
103: categoryButton.addMouseListener(listener);
104: GridBagConstraints gbc = new GridBagConstraints(0, 0, 1, 1,
105: 1.0, 0.0, GridBagConstraints.NORTH,
106: GridBagConstraints.HORIZONTAL, new Insets(1, 0, 0, 0),
107: 0, 0);
108: wholePanel.add(categoryButton, gbc);
109:
110: itemsList = new CategoryList(category, palettePanel);
111: itemsList.setModel(itemsListModel = new DefaultListModel());
112: itemsList.setShowNames(palettePanel.getSettings()
113: .getShowItemNames());
114: itemsList.setIconSize(palettePanel.getSettings().getIconSize());
115: itemsList.addMouseListener(listener);
116: itemsList.addListSelectionListener(new ListSelectionListener() {
117: public void valueChanged(ListSelectionEvent e) {
118: CategoryDescriptor.this .palettePanel.select(
119: CategoryDescriptor.this .category,
120: (Item) itemsList.getSelectedValue());
121: }
122: });
123: gbc = new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0,
124: GridBagConstraints.CENTER, GridBagConstraints.BOTH,
125: new Insets(0, 0, 0, 0), 0, 0);
126: wholePanel.add(itemsList, gbc);
127: wholePanel.setFocusTraversalPolicy(new MyFocusTraversal(this ));
128: doSetOpened(settings.isExpanded(category));
129: }
130:
131: private MouseListener createMouseListener() {
132: return new MouseAdapter() {
133: public void mouseClicked(MouseEvent event) {
134: if (SwingUtilities.isRightMouseButton(event)) {
135: JComponent comp = (JComponent) event.getSource();
136: Item item = null;
137: if (comp instanceof JList) {
138: JList list = (JList) comp;
139: Point p = event.getPoint();
140: int index = list.locationToIndex(p);
141: if (index >= 0
142: && !list.getCellBounds(index, index)
143: .contains(p)) {
144: index = -1;
145: }
146: if (index >= 0) {
147: item = (Item) list.getModel().getElementAt(
148: index);
149: }
150: }
151: Action[] actions = null == item ? category
152: .getActions() : item.getActions();
153: JPopupMenu popup = Utilities.actionsToPopup(
154: actions, getComponent());
155: Utils.addCustomizationMenuItems(popup,
156: getPalettePanel().getController(),
157: getPalettePanel().getSettings());
158: popup.show(comp, event.getX(), event.getY());
159: }
160: }
161: };
162: }
163:
164: void refresh() {
165: categoryButton.updateProperties();
166: categoryButton.repaint();
167: if (isOpened() && resetItems) {
168: computeItems();
169: }
170: }
171:
172: void computeItems() {
173: DefaultListModel newModel = new DefaultListModel();
174: Item[] items = category.getItems();
175: if (items != null) {
176: for (int i = 0; i < items.length; i++) {
177: if (settings.isVisible(items[i])) {
178: newModel.addElement(items[i]);
179: }
180: }
181: }
182: itemsListModel = newModel;
183: itemsList.setModel(newModel);
184: resetItems = false;
185: }
186:
187: void resetItems() {
188: resetItems = true;
189: }
190:
191: Category getCategory() {
192: return category;
193: }
194:
195: boolean isOpened() {
196: return opened;
197: }
198:
199: boolean isSelected() {
200: return categoryButton.isFocusOwner()
201: || itemsList.getSelectedIndex() >= 0;
202: }
203:
204: void setSelectedItem(Item item) {
205: if (itemsList.getSelectedValue() == item) {
206: return;
207: }
208: if (item == null) {
209: int selectedIndex = itemsList.getSelectedIndex();
210: itemsList.removeSelectionInterval(selectedIndex,
211: selectedIndex);
212: } else {
213: itemsList.setSelectedValue(item, true);
214: }
215: }
216:
217: void setOpened(boolean b) {
218: if (opened == b) {
219: return;
220: }
221: doSetOpened(b);
222: settings.setExpanded(category, b);
223: }
224:
225: private void doSetOpened(boolean b) {
226: opened = b;
227: if (opened) {
228: if (resetItems) {
229: computeItems();
230: }
231: } else {
232: palettePanel.select(category, null);
233: }
234: itemsList.setVisible(opened);
235: categoryButton.setSelected(opened);
236: if (opened) {
237: itemsList.ensureIndexIsVisible(0);
238: }
239: }
240:
241: void setPositionY(int yPosition) {
242: wholePanel.setLocation(0, yPosition);
243: }
244:
245: JComponent getComponent() {
246: return wholePanel;
247: }
248:
249: int getPreferredHeight(int width) {
250: return isOpened() ? itemsList.getPreferredHeight(width)
251: + categoryButton.getPreferredSize().height
252: : categoryButton.getPreferredSize().height;
253: }
254:
255: void setWidth(int width) {
256: wholePanel.setSize(width, wholePanel.getHeight());
257: }
258:
259: void setShowNames(boolean showNames) {
260: itemsList.setShowNames(showNames);
261: }
262:
263: void setIconSize(int iconSize) {
264: itemsList.setIconSize(iconSize);
265: }
266:
267: void setItemWidth(int itemWidth) {
268: itemsList.setFixedCellWidth(itemWidth);
269: }
270:
271: PalettePanel getPalettePanel() {
272: return palettePanel;
273: }
274:
275: public void categoryModified(Category category) {
276: resetItems();
277: palettePanel.refresh();
278: }
279:
280: CategoryList getList() {
281: return itemsList;
282: }
283:
284: CategoryButton getButton() {
285: return categoryButton;
286: }
287:
288: private static class MyFocusTraversal extends FocusTraversalPolicy {
289: private CategoryDescriptor descriptor;
290:
291: public MyFocusTraversal(CategoryDescriptor descriptor) {
292: this .descriptor = descriptor;
293: }
294:
295: public Component getComponentBefore(Container focusCycleRoot,
296: Component aComponent) {
297: if (focusCycleRoot == descriptor.wholePanel
298: && aComponent == descriptor.categoryButton)
299: return descriptor.itemsList;
300: return null;
301: }
302:
303: public Component getComponentAfter(Container focusCycleRoot,
304: Component aComponent) {
305: if (focusCycleRoot == descriptor.wholePanel
306: && aComponent == descriptor.itemsList)
307: return descriptor.categoryButton;
308: return null;
309: }
310:
311: public Component getLastComponent(Container focusCycleRoot) {
312: if (focusCycleRoot == descriptor.wholePanel)
313: return descriptor.itemsList;
314: return null;
315: }
316:
317: public Component getFirstComponent(Container focusCycleRoot) {
318: if (focusCycleRoot == descriptor.wholePanel)
319: return descriptor.categoryButton;
320: return null;
321: }
322:
323: public Component getDefaultComponent(Container focusCycleRoot) {
324: return getFirstComponent(focusCycleRoot);
325: }
326: }
327: }
|