# HG changeset patch # Parent 85c2fdb8101fdd9fdf1922a21e922490c43fc43a # User Jan Peska api changes notifications diff --git a/openide.awt/apichanges.xml b/openide.awt/apichanges.xml --- a/openide.awt/apichanges.xml +++ b/openide.awt/apichanges.xml @@ -52,6 +52,19 @@ + Add notification category to the NotificationDisplayer API + + + + + + Clients can specify notification category. There are 3 default categories (Info, Warning, Error) but clients can also create a custom category using layer.xml + + + + + + The value in Preferences for Actions.checkbox can have a default diff --git a/openide.awt/manifest.mf b/openide.awt/manifest.mf --- a/openide.awt/manifest.mf +++ b/openide.awt/manifest.mf @@ -2,5 +2,5 @@ OpenIDE-Module: org.openide.awt OpenIDE-Module-Localizing-Bundle: org/openide/awt/Bundle.properties AutoUpdate-Essential-Module: true -OpenIDE-Module-Specification-Version: 7.56 +OpenIDE-Module-Specification-Version: 7.57 diff --git a/openide.awt/src/org/openide/awt/Bundle.properties b/openide.awt/src/org/openide/awt/Bundle.properties --- a/openide.awt/src/org/openide/awt/Bundle.properties +++ b/openide.awt/src/org/openide/awt/Bundle.properties @@ -143,3 +143,10 @@ Yellow=Yellow SelectColor=Select Color + +INFO_CATEGORY=Info +INFO_CATEGORY_DESCRIPTION=Informational notifications +WARNING_CATEGORY=Warning +WARNING_CATEGORY_DESCRIPTION=Warning notifications +ERROR_CATEGORY=Error +ERROR_CATEGORY_DESCRIPTION=Error notifications diff --git a/openide.awt/src/org/openide/awt/NotificationCategoryFactory.java b/openide.awt/src/org/openide/awt/NotificationCategoryFactory.java new file mode 100644 --- /dev/null +++ b/openide.awt/src/org/openide/awt/NotificationCategoryFactory.java @@ -0,0 +1,148 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2013 Sun Microsystems, Inc. + */ +package org.openide.awt; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.ResourceBundle; +import org.openide.awt.NotificationDisplayer.Category; +import org.openide.util.Lookup; +import org.openide.util.LookupEvent; +import org.openide.util.LookupListener; +import org.openide.util.NbBundle; +import org.openide.util.lookup.Lookups; + +/** + * + * @author jpeska + */ +class NotificationCategoryFactory { + + static final String ATTR_CATEGORY_NAME = "categoryName"; //NOI18N + static final String ATTR_BUNDLE_NAME = "localizingBundle"; //NOI18N + static final String ATTR_DISPLAY_NAME_KEY = "diplayNameKey"; //NOI18N + static final String ATTR_DESCRIPTION_KEY = "descriptionKey"; //NOI18N + private static final String CATEGORY_LIST_PATH = "Notification/Category"; //NOI18N + private static NotificationCategoryFactory theInstance; + private Lookup.Result lookupRes; + private Map name2category; + private List categories; + + private NotificationCategoryFactory() { + } + + static Category create(Map attrs) { + String categoryName = attrs.get(ATTR_CATEGORY_NAME); + String bundleName = attrs.get(ATTR_BUNDLE_NAME); + String displayNameKey = attrs.get(ATTR_DISPLAY_NAME_KEY); + String descriptionKey = attrs.get(ATTR_DESCRIPTION_KEY); + return create(categoryName, bundleName, displayNameKey, descriptionKey); + } + + static Category create(String categoryName, String bundleName, String displayNameKey, String descriptionKey) { + ResourceBundle bundle = NbBundle.getBundle(bundleName); + String displayName = bundle.getString(displayNameKey); + String description = bundle.getString(descriptionKey); + return new Category(categoryName, displayName, description); + } + + /** + * @return The one and only instance of this class. + */ + public static NotificationCategoryFactory getInstance() { + if (null == theInstance) { + theInstance = new NotificationCategoryFactory(); + } + return theInstance; + } + + Category getCategory(String categoryName) { + assert null != categoryName; + synchronized (this) { + initCategories(); + return name2category.get(categoryName); + } + } + + List getCategories() { + synchronized (this) { + initCategories(); + return categories; + } + } + + private void initCategories() { + synchronized (this) { + if (null == name2category) { + if (null == lookupRes) { + lookupRes = initLookup(); + lookupRes.addLookupListener(new LookupListener() { + @Override + public void resultChanged(LookupEvent ev) { + synchronized (NotificationCategoryFactory.this) { + name2category = null; + categories = null; + } + } + }); + } + int index = 0; + categories = new ArrayList(Category.getDefaultCategories()); + categories.addAll(lookupRes.allInstances()); + name2category = new HashMap(categories.size()); + for (Category c : categories) { + name2category.put(c.getName(), c); + c.setIndex(index++); + } + } + } + } + + private Lookup.Result initLookup() { + Lookup lkp = Lookups.forPath(CATEGORY_LIST_PATH); + Lookup.Template template = new Lookup.Template(Category.class); + Lookup.Result res = lkp.lookup(template); + return res; + } +} diff --git a/openide.awt/src/org/openide/awt/NotificationDisplayer.java b/openide.awt/src/org/openide/awt/NotificationDisplayer.java --- a/openide.awt/src/org/openide/awt/NotificationDisplayer.java +++ b/openide.awt/src/org/openide/awt/NotificationDisplayer.java @@ -43,12 +43,18 @@ package org.openide.awt; import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.Icon; +import javax.swing.ImageIcon; import javax.swing.JComponent; import org.openide.awt.StatusDisplayer.Message; +import org.openide.util.ImageUtilities; import org.openide.util.Lookup; +import org.openide.util.NbBundle; /** * Creates and shows clickable notifications in the main status line. @@ -63,14 +69,126 @@ * Priority of Notification */ public static enum Priority { - HIGH, - NORMAL, - LOW, + HIGH(new ImageIcon(ImageUtilities.loadImage("org/openide/awt/resources/priority_high.png"))), //NOI18N + NORMAL(new ImageIcon(ImageUtilities.loadImage("org/openide/awt/resources/priority_normal.png"))), //NOI18N + LOW(new ImageIcon(ImageUtilities.loadImage("org/openide/awt/resources/priority_low.png"))), //NOI18N /** Priority that shows the notification without details. * Details shall be shown only later, per user request. * @since 7.18 */ - SILENT + SILENT(new ImageIcon(ImageUtilities.loadImage("org/openide/awt/resources/priority_silent.png"))); //NOI18N + + private final Icon icon; + + private Priority(Icon icon) { + this.icon = icon; + } + + /** + * Returns priority icon + * + * @since 7.57 + */ + public Icon getIcon() { + return icon; + } + } + + /** + * Category of Notification, displayed in Notifications TC. Use one of the defaults categories (INFO, WARNING, ERROR) or create a custom category. + * + * To create a custom add following code to your layer.xml: + *
+     * {@code
+     * 
+     *      
+     *          
+     *              
+     *
+     *               
+     *               
+     *               
+     *          
+     *      
+     * 
+     * }
+     * 
+ * + * @since 7.57 + */ + public static final class Category implements Comparable{ + + public static final Category INFO = new Category("default_category_info", NbBundle.getMessage(NotificationDisplayer.class, "INFO_CATEGORY"), //NOI18N + NbBundle.getMessage(NotificationDisplayer.class, "INFO_CATEGORY_DESCRIPTION")); //NOI18N + public static final Category WARNING = new Category("default_category_warning", NbBundle.getMessage(NotificationDisplayer.class, "WARNING_CATEGORY"), //NOI18N + NbBundle.getMessage(NotificationDisplayer.class, "WARNING_CATEGORY_DESCRIPTION")); //NOI18N + public static final Category ERROR = new Category("default_category_error", NbBundle.getMessage(NotificationDisplayer.class, "ERROR_CATEGORY"), //NOI18N + NbBundle.getMessage(NotificationDisplayer.class, "ERROR_CATEGORY_DESCRIPTION")); //NOI18N + + private final String name; + private final String displayName; + private final String description; + private int index; + + Category(String name, String displayName, String description) { + this.name = name; + this.displayName = displayName; + this.description = description; + } + + /** + * Returns category name - unique id + * + * @since 7.57 + */ + public String getName() { + return name; + } + + /** + * Returns category display name + * + * @since 7.57 + */ + public String getDisplayName() { + return displayName; + } + + void setIndex(int index) { + this.index = index; + } + + /** + * Returns category description + * + * @since 7.57 + */ + public String getDescription() { + return description; + } + + @Override + public int compareTo(Category other) { + return index - other.index; + } + + /** + * Returns all available categories + * + * @since 7.57 + */ + public static List getCategories() { + return NotificationCategoryFactory.getInstance().getCategories(); + } + + static List getDefaultCategories() { + List defaultCategories = new ArrayList(); + defaultCategories.add(ERROR); + defaultCategories.add(WARNING); + defaultCategories.add(INFO); + return defaultCategories; + } } /** @@ -120,6 +238,44 @@ String detailsText, ActionListener detailsAction, Priority priority); /** + * Create and show new notification. + * @param title Notification title. Html is not supported, any html tags will + * be escaped. + * @param icon Notification icon + * @param detailsText Detailed description of the notification. If detailsAction + * is non-null then this text will be presented as a clickable link. Html is + * not supported, any html tags will be escaped. + * @param detailsAction Action to invoke when user click details text or null. + * @param priority Notification priority + * @param category Notification category. + * @return New notification. + * @since 7.57 + */ + public Notification notify(String title, Icon icon, + String detailsText, ActionListener detailsAction, Priority priority, Category category) { + return notify(title, icon, detailsText, detailsAction, priority); + } + + /** + * Create and show new notification. + * + * @param title Notification title. Html is not supported, any html tags will be escaped. + * @param icon Notification icon + * @param detailsText Detailed description of the notification. If detailsAction + * is non-null then this text will be presented as a clickable link. Html is + * not supported, any html tags will be escaped. + * @param detailsAction Action to invoke when user click details text or null. + * @param priority Notification priority + * @param categoryName Notification category name, refers to a custom category created in e.g. layer.xml. + * @return New notification. + * @since 7.57 + */ + public Notification notify(String title, Icon icon, + String detailsText, ActionListener detailsAction, Priority priority, String categoryName) { + return notify(title, icon, detailsText, detailsAction, priority, NotificationCategoryFactory.getInstance().getCategory(categoryName)); + } + + /** * Create and show new notification with customized content. * @param title Notification title. Html is not supported, any html tags will * be escaped. @@ -127,7 +283,7 @@ * @param balloonDetails Component that will show below notification title * in a balloon. * @param popupDetails Component that will show below notification title - * in notifications popup list. + * in notifications list. * @param priority Notification priority. * @return New notification. */ @@ -135,6 +291,48 @@ JComponent balloonDetails, JComponent popupDetails, Priority priority); /** + * Create and show new notification with customized content. + * @param title Notification title. Html is not supported, any html tags will + * be escaped. + * @param icon Notification icon + * @param balloonDetails Component that will show below notification title + * in a balloon. + * @param popupDetails Component that will show below notification title + * in notifications list. + * @param priority Notification priority. + * @param category Notification category. + * @return New notification. + * @since 7.57 + */ + public Notification notify(String title, Icon icon, + JComponent balloonDetails, JComponent popupDetails, Priority priority, Category category) { + return notify(title, icon, balloonDetails, popupDetails, priority); + } + + /** + Create and show new notification with customized content. + * @param title Notification title. Html is not supported, any html tags will + * be escaped. + * @param icon Notification icon + * @param balloonDetails Component that will show below notification title + * in a balloon. + * @param popupDetails Component that will show below notification title + * in notifications list. + * @param priority Notification priority. + * @param categoryName Notification category name, refers to a custom category created in e.g. layer.xml. + * @return New notification. + * @since 7.57 + */ + public Notification notify(String title, Icon icon, + JComponent balloonDetails, JComponent popupDetails, Priority priority, String categoryName) { + return notify(title, icon, balloonDetails, popupDetails, priority, NotificationCategoryFactory.getInstance().getCategory(categoryName)); + } + + static Category createCategory(Map attrs) { + return NotificationCategoryFactory.create(attrs); + } + + /** * Simple implementation of NotificationDisplayer which shows the notifications * on the main status line. */ diff --git a/bugzilla/src/org/netbeans/modules/bugzilla/resources/p2.png b/openide.awt/src/org/openide/awt/resources/priority_high.png copy from bugzilla/src/org/netbeans/modules/bugzilla/resources/p2.png copy to openide.awt/src/org/openide/awt/resources/priority_high.png diff --git a/bugzilla/src/org/netbeans/modules/bugzilla/resources/p4.png b/openide.awt/src/org/openide/awt/resources/priority_low.png copy from bugzilla/src/org/netbeans/modules/bugzilla/resources/p4.png copy to openide.awt/src/org/openide/awt/resources/priority_low.png diff --git a/bugzilla/src/org/netbeans/modules/bugzilla/resources/p3.png b/openide.awt/src/org/openide/awt/resources/priority_normal.png copy from bugzilla/src/org/netbeans/modules/bugzilla/resources/p3.png copy to openide.awt/src/org/openide/awt/resources/priority_normal.png diff --git a/bugzilla/src/org/netbeans/modules/bugzilla/resources/p5.png b/openide.awt/src/org/openide/awt/resources/priority_silent.png copy from bugzilla/src/org/netbeans/modules/bugzilla/resources/p5.png copy to openide.awt/src/org/openide/awt/resources/priority_silent.png diff --git a/openide.awt/test/unit/src/org/openide/awt/NotificationCategoryFactoryTest.java b/openide.awt/test/unit/src/org/openide/awt/NotificationCategoryFactoryTest.java new file mode 100644 --- /dev/null +++ b/openide.awt/test/unit/src/org/openide/awt/NotificationCategoryFactoryTest.java @@ -0,0 +1,235 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2013 Sun Microsystems, Inc. + */ +package org.openide.awt; + +import java.beans.PropertyVetoException; +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.net.URLStreamHandler; +import java.net.URLStreamHandlerFactory; +import java.util.Enumeration; +import java.util.List; +import junit.framework.Assert; +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertNull; +import static junit.framework.Assert.fail; +import org.netbeans.junit.Manager; +import org.netbeans.junit.NbTestCase; +import org.openide.awt.NotificationDisplayer.Category; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileSystem; +import org.openide.filesystems.FileUtil; +import org.openide.filesystems.MultiFileSystem; +import org.openide.filesystems.Repository; +import org.openide.filesystems.XMLFileSystem; +import org.openide.util.Lookup; +import org.openide.util.lookup.Lookups; +import org.openide.util.lookup.ProxyLookup; + +/** + * + * @author jpeska + */ +public class NotificationCategoryFactoryTest extends NbTestCase { + + public static final String CATEGORY_NAME_A = "nb-notification-unittestA"; + public static final String CATEGORY_DISPLAY_NAME_A = "unitTestCategoryLabelA"; + public static final String CATEGORY_DESCRIPTION_A = "unitTestCategoryDescriptionA"; + public static final String CATEGORY_NAME_B = "nb-notification-unittestB"; + public static final String CATEGORY_DISPLAY_NAME_B = "unitTestCategoryLabelB"; + public static final String CATEGORY_DESCRIPTION_B = "unitTestCategoryDescriptionB"; + public static final String CATEGORY_NAME_C = "nb-notification-unittestC"; + public static final String CATEGORY_DISPLAY_NAME_C = "unitTestCategoryLabelC"; + public static final String CATEGORY_DESCRIPTION_C = "unitTestCategoryDescriptionC"; + + static { + String[] layers = new String[]{"org/openide/awt/mf-layer.xml"};//NOI18N + IDEInitializer.setup(layers, new Object[0]); + } + + public NotificationCategoryFactoryTest(String name) { + super(name); + } + + public void testGetCategory() { + NotificationCategoryFactory factory = NotificationCategoryFactory.getInstance(); + + List categories = factory.getCategories(); + categories.removeAll(Category.getDefaultCategories()); + assertEquals(2, categories.size()); + + Category cA = categories.get(0); + assertEquals(CATEGORY_NAME_A, cA.getName()); + assertEquals(CATEGORY_DISPLAY_NAME_A, cA.getDisplayName()); + assertEquals(CATEGORY_DESCRIPTION_A, cA.getDescription()); + + Category cB = categories.get(1); + assertEquals(CATEGORY_NAME_B, cB.getName()); + assertEquals(CATEGORY_DISPLAY_NAME_B, cB.getDisplayName()); + assertEquals(CATEGORY_DESCRIPTION_B, cB.getDescription()); + + assertFalse(cA.equals(cB)); + + Category category = factory.getCategory(CATEGORY_NAME_A); + assertNotNull(category); + assertEquals(CATEGORY_NAME_A, category.getName()); + + category = factory.getCategory(CATEGORY_NAME_B); + assertNotNull(category); + + category = factory.getCategory("unknown category name"); + assertNull(category); + + try { + factory.getCategory(null); + fail("null category name is not acceptable"); + } catch (AssertionError e) { + //expected + } + } + + public void testCreate() { + Category category = NotificationCategoryFactory.create(CATEGORY_NAME_C, + "org.openide.awt.TestBundle", + "LBL_unittest_categoryC", + "HINT_unittest_categoryC"); + + assertNotNull(category); + assertEquals(CATEGORY_NAME_C, category.getName()); + assertEquals(CATEGORY_DISPLAY_NAME_C, category.getDisplayName()); + assertEquals(CATEGORY_DESCRIPTION_C, category.getDescription()); + } + + public static class IDEInitializer extends ProxyLookup { + + public static IDEInitializer DEFAULT_LOOKUP = null; + private static FileSystem lfs; + + static { + IDEInitializer.class.getClassLoader().setDefaultAssertionStatus(true); + System.setProperty("org.openide.util.Lookup", IDEInitializer.class.getName()); + Assert.assertEquals(IDEInitializer.class, Lookup.getDefault().getClass()); + } + + public IDEInitializer() { + Assert.assertNull(DEFAULT_LOOKUP); + DEFAULT_LOOKUP = this; + URL.setURLStreamHandlerFactory(new MyURLHandlerFactory()); + } + + /** + * Set the global default lookup with the specified content. + * + * @param layers xml-layer URLs to be present in the system filesystem. + * @param instances object instances to be present in the default lookup. + */ + public static void setup( + String[] layers, + Object[] instances) { + ClassLoader classLoader = IDEInitializer.class.getClassLoader(); + File workDir = new File(Manager.getWorkDirPath()); + URL[] urls = new URL[layers.length]; + int i, k = urls.length; + for (i = 0; i < k; i++) { + urls[i] = classLoader.getResource(layers[i]); + } + + // 1) create repository + XMLFileSystem systemFS = new XMLFileSystem(); + lfs = FileUtil.createMemoryFileSystem(); + try { + systemFS.setXmlUrls(urls); + } catch (Exception ex) { + ex.printStackTrace(); + } + MyFileSystem myFileSystem = new MyFileSystem( + new FileSystem[]{lfs, systemFS}); + Repository repository = new Repository(myFileSystem); + + Object[] lookupContent = new Object[instances.length + 1]; + lookupContent[0] = repository; + System.arraycopy(instances, 0, lookupContent, 1, instances.length); + + DEFAULT_LOOKUP.setLookups(new Lookup[]{ + Lookups.fixed(lookupContent), + Lookups.metaInfServices(classLoader), + Lookups.singleton(classLoader),}); + Assert.assertTrue(myFileSystem.isDefault()); + } + + public static void cleanWorkDir() { + try { + Enumeration en = lfs.getRoot().getChildren(false); + while (en.hasMoreElements()) { + ((FileObject) en.nextElement()).delete(); + } + } catch (IOException ex) { + ex.printStackTrace(); + } + } + + private static class MyFileSystem extends MultiFileSystem { + + public MyFileSystem(FileSystem[] fileSystems) { + super(fileSystems); + try { + setSystemName("TestFS"); + } catch (PropertyVetoException ex) { + ex.printStackTrace(); + } + } + } + + private static class MyURLHandlerFactory implements URLStreamHandlerFactory { + + public URLStreamHandler createURLStreamHandler(String protocol) { + if (protocol.equals("nbfs")) { + return FileUtil.nbfsURLStreamHandler(); + } + return null; + } + } + } +} diff --git a/openide.awt/test/unit/src/org/openide/awt/TestBundle.properties b/openide.awt/test/unit/src/org/openide/awt/TestBundle.properties --- a/openide.awt/test/unit/src/org/openide/awt/TestBundle.properties +++ b/openide.awt/test/unit/src/org/openide/awt/TestBundle.properties @@ -46,3 +46,11 @@ Callback=Close NumberLover=Number lover! +LBL_unittest_categoryA=unitTestCategoryLabelA +HINT_unittest_categoryA=unitTestCategoryDescriptionA + +LBL_unittest_categoryB=unitTestCategoryLabelB +HINT_unittest_categoryB=unitTestCategoryDescriptionB + +LBL_unittest_categoryC=unitTestCategoryLabelC +HINT_unittest_categoryC=unitTestCategoryDescriptionC \ No newline at end of file diff --git a/openide.awt/test/unit/src/org/openide/awt/mf-layer.xml b/openide.awt/test/unit/src/org/openide/awt/mf-layer.xml new file mode 100644 --- /dev/null +++ b/openide.awt/test/unit/src/org/openide/awt/mf-layer.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +