001: /*
002: * The contents of this file are subject to the terms of the Common Development
003: * and Distribution License (the License). You may not use this file except in
004: * compliance with the License.
005: *
006: * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
007: * or http://www.netbeans.org/cddl.txt.
008: *
009: * When distributing Covered Code, include this CDDL Header Notice in each file
010: * and include the License file at http://www.netbeans.org/cddl.txt.
011: * If applicable, add the following below the CDDL Header, with the fields
012: * enclosed by brackets [] replaced by your own identifying information:
013: * "Portions Copyrighted [year] [name of copyright owner]"
014: *
015: * The Original Software is NetBeans. The Initial Developer of the Original
016: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
017: * Microsystems, Inc. All Rights Reserved.
018: */
019:
020: package org.netbeans.modules.sql.project.base;
021:
022: import java.awt.Image;
023: import org.netbeans.api.java.queries.AccessibilityQuery;
024: import org.netbeans.api.queries.VisibilityQuery;
025: import org.openide.filesystems.FileObject;
026: import org.openide.util.NbBundle;
027: import org.openide.util.Utilities;
028:
029: // XXX needs unit test
030:
031: /**
032: * Provides display name and icon utilities for
033: * {@link PackageViewChildren.PackageNode} and {@link PackageListView.PackageItem}.
034: * @author Jesse Glick
035: */
036: public final class PackageDisplayUtils {
037:
038: private PackageDisplayUtils() {
039: }
040:
041: /** whether to turn on #42589 */
042: private static final boolean TRUNCATE_PACKAGE_NAMES = Boolean
043: .getBoolean("org.netbeans.spi.java.project.support.ui.packageView.TRUNCATE_PACKAGE_NAMES"); // NOI18N
044:
045: private static final Image PACKAGE = Utilities
046: .loadImage("org/netbeans/spi/java/project/support/ui/package.gif"); // NOI18N
047: private static final Image PACKAGE_EMPTY = Utilities
048: .loadImage("org/netbeans/spi/java/project/support/ui/packageEmpty.gif"); // NOI18N
049: private static final Image PACKAGE_PRIVATE = Utilities
050: .loadImage("org/netbeans/spi/java/project/support/ui/packagePrivate.gif"); // NOI18N
051: private static final Image PACKAGE_PUBLIC = Utilities
052: .loadImage("org/netbeans/spi/java/project/support/ui/packagePublic.gif"); // NOI18N
053:
054: /**
055: * Find the proper display label for a package.
056: * @param pkg the actual folder
057: * @param pkgname the dot-separated package name (<code>""</code> for default package)
058: * @return an appropriate display label for it
059: */
060: public static String getDisplayLabel(String pkgname) {
061: return computePackageName(pkgname, TRUNCATE_PACKAGE_NAMES);
062: }
063:
064: /**
065: * Find the proper tool tip for a package.
066: * May have more info than the display label.
067: * @param pkg the actual folder
068: * @param pkgname the dot-separated package name (<code>""</code> for default package)
069: * @return an appropriate display label for it
070: */
071: public static String getToolTip(FileObject pkg, String pkgname) {
072: String pkglabel = computePackageName(pkgname, false);
073: Boolean b = AccessibilityQuery.isPubliclyAccessible(pkg);
074: if (b != null) {
075: if (b.booleanValue()) {
076: return NbBundle.getMessage(PackageDisplayUtils.class,
077: "LBL_public_package", pkglabel);
078: } else {
079: return NbBundle.getMessage(PackageDisplayUtils.class,
080: "LBL_private_package", pkglabel);
081: }
082: } else {
083: return NbBundle.getMessage(PackageDisplayUtils.class,
084: "LBL_package", pkglabel);
085: }
086: }
087:
088: /**
089: * Get package name.
090: * Handles default package specially.
091: * @param truncate if true, show a truncated version to save display space
092: */
093: private static String computePackageName(String pkgname,
094: boolean truncate) {
095: if (pkgname.length() == 0) {
096: return NbBundle.getMessage(PackageDisplayUtils.class,
097: "LBL_DefaultPackage"); // NOI18N
098: } else {
099: if (truncate) {
100: // #42589: keep only first letter of first package component, up to three of others
101: return pkgname.replaceFirst("^([^.])[^.]+\\.", "$1.")
102: .replaceAll("([^.]{3})[^.]+\\.", "$1."); // NOI18N
103: } else {
104: return pkgname;
105: }
106: }
107: }
108:
109: /**
110: * Find the proper display icon for a package.
111: * @param pkg the actual folder
112: * @param pkgname the dot-separated package name (<code>""</code> for default package)
113: * @return an appropriate display icon for it
114: */
115: public static Image getIcon(FileObject pkg, String pkgname) {
116: return getIcon(pkg, pkgname, isEmpty(pkg));
117: }
118:
119: /** Performance optiomization if the the isEmpty status is alredy known.
120: *
121: */
122: public static Image getIcon(FileObject pkg, String pkgname,
123: boolean empty) {
124: if (empty) {
125: return PACKAGE_EMPTY;
126: } else {
127: Boolean b = pkg.isValid() ? AccessibilityQuery
128: .isPubliclyAccessible(pkg) : null;
129: if (b != null) {
130: if (b.booleanValue()) {
131: return PACKAGE_PUBLIC;
132: } else {
133: return PACKAGE_PRIVATE;
134: }
135: } else {
136: return PACKAGE;
137: }
138: }
139: }
140:
141: /**
142: * Check whether a package is empty (devoid of files except for subpackages).
143: */
144: public static boolean isEmpty(FileObject fo) {
145: return isEmpty(fo, true);
146: }
147:
148: /**
149: * Check whether a package is empty (devoid of files except for subpackages).
150: * @param recurse specifies whether to check if subpackages are empty too.
151: */
152: public static boolean isEmpty(FileObject fo, boolean recurse) {
153: FileObject[] kids = fo.getChildren();
154: for (int i = 0; i < kids.length; i++) {
155: if (!kids[i].isFolder()
156: && VisibilityQuery.getDefault().isVisible(kids[i])) {
157: return false;
158: } else if (recurse
159: && VisibilityQuery.getDefault().isVisible(kids[i])
160: && !isEmpty(kids[i])) {
161: return false;
162: }
163: }
164: return true;
165: }
166:
167: /**
168: * Check whether a package should be displayed.
169: * It should be displayed if {@link VisibilityQuery} says it should be,
170: * and it is either completely empty, or contains files (as opposed to
171: * containing some subpackages but no files).
172: */
173: public static boolean isSignificant(FileObject pkg)
174: throws IllegalArgumentException {
175: if (!pkg.isFolder()) {
176: throw new IllegalArgumentException("Not a folder"); // NOI18N
177: }
178: if (!VisibilityQuery.getDefault().isVisible(pkg)) {
179: return false;
180: }
181: FileObject[] kids = pkg.getChildren();
182: boolean subpackages = false;
183: for (int i = 0; i < kids.length; i++) {
184: if (!VisibilityQuery.getDefault().isVisible(kids[i])) {
185: continue;
186: }
187: if (kids[i].isData()) {
188: return true;
189: } else {
190: subpackages = true;
191: }
192: }
193: return !subpackages;
194: }
195:
196: }
|