All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.netbeans.modules.properties.PropertiesLocaleNode Maven / Gradle / Ivy

There is a newer version: RELEASE230
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.netbeans.modules.properties;

import java.awt.Component;
import java.awt.datatransfer.Transferable;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import javax.swing.Action;
import javax.swing.SwingUtilities;

import org.openide.DialogDescriptor;
import org.openide.filesystems.FileUtil;
import org.openide.nodes.CookieSet;
import org.openide.nodes.Node;
import org.openide.nodes.NodeTransfer;
import org.openide.NotifyDescriptor;
import org.openide.DialogDisplayer;
import org.openide.actions.CopyAction;
import org.openide.actions.CutAction;
import org.openide.actions.DeleteAction;
import org.openide.actions.EditAction;
import org.openide.actions.FileSystemAction;
import org.openide.actions.NewAction;
import org.openide.actions.OpenAction;
import org.openide.actions.PasteAction;
import org.openide.actions.PropertiesAction;
import org.openide.actions.SaveAsTemplateAction;
import org.openide.actions.ToolsAction;
import org.openide.filesystems.FileStateInvalidException;
import org.openide.filesystems.FileStatusEvent;
import org.openide.filesystems.FileStatusListener;
import org.openide.filesystems.FileSystem;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.StatusDecorator;
import org.openide.util.actions.SystemAction;
import org.openide.util.datatransfer.NewType;
import org.openide.util.datatransfer.PasteType;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;


/** 
 * Node representing a single properties file.
 *
 * @see  PropertiesDataNode
 * @author Ian Formanek
 * @author Marian Petras
 */
public final class PropertiesLocaleNode extends FileEntryNode
                                        implements CookieSet.Factory,
                                                   Node.Cookie {

    /** Icon base for the PropertiesDataNode node. */
    private static final String LOCALE_ICON_BASE = "org/netbeans/modules/properties/propertiesLocale.gif"; // NOI18N

    private FileStatusListener fsStatusListener;
    
    /** Creates a new PropertiesLocaleNode for the given locale-specific file */
    public PropertiesLocaleNode (PropertiesFileEntry fe) {
        super(fe, fe.getChildren());
        setDisplayName(Util.getLocaleLabel(fe));

        setIconBaseWithExtension(LOCALE_ICON_BASE);        
        setShortDescription(messageToolTip());

        // the node uses lookup based on CookieSet from PropertiesFileEntry
        CookieSet cookieSet = fe.getCookieSet();
        cookieSet.add(PropertiesOpen.class, this);
        cookieSet.add(fe);
        cookieSet.add(fe.getDataObject());
        cookieSet.add(this);

        fsStatusListener = new FSListener();
        try {
            FileSystem fs = fe.getFile().getFileSystem();
            fs.addFileStatusListener(FileUtil.weakFileStatusListener(fsStatusListener, fs));
        } catch (FileStateInvalidException ex) {
        }
    }

    private class FSListener implements FileStatusListener, Runnable {
        public void annotationChanged(FileStatusEvent ev) {
            if (ev.isNameChange() && ev.hasChanged(getFileEntry().getFile())) {
                SwingUtilities.invokeLater(this);
            }
        }

        public void run() {
            fireDisplayNameChange(null, null);
        }
    }

    /** Implements CookieSet.Factory interface method. */
    @SuppressWarnings("unchecked")
    public  T createCookie(Class clazz) {
        if(clazz.isAssignableFrom(PropertiesOpen.class)) {
            return (T) ((PropertiesDataObject) getFileEntry().getDataObject()).getOpenSupport();
        } else {
            return null;
        }
    }

    /** Lazily initialize set of node's actions.
     * Overrides superclass method.
     *
     * @return array of actions for this node
     */
    @Override
    protected SystemAction[] createActions () {
        return new SystemAction[] {
            SystemAction.get(EditAction.class),
            SystemAction.get(OpenAction.class),
            null,
            SystemAction.get(CutAction.class),
            SystemAction.get(CopyAction.class),
            SystemAction.get(PasteAction.class),
            null,
            SystemAction.get(DeleteAction.class),
            SystemAction.get(LangRenameAction.class),
            null,
            SystemAction.get(NewAction.class),
            SystemAction.get(SaveAsTemplateAction.class),
            null,
            SystemAction.get(FileSystemAction.class),
            null,
            SystemAction.get(ToolsAction.class),
            SystemAction.get(PropertiesAction.class)
        };
    }

    @Override
    public Action getPreferredAction() {
        return getActions(false)[0];
    }

    /** Gets the name. Note: It gets only the local part of the name  (e.g. "de_DE_EURO").
     * Reason is to allow user change only this part of name by renaming (on Node).
     * Overrides superclass method. 
     *
     * @return locale part of name
     */
    @Override
    public String getName() {
        String localeName = "invalid"; // NOI18N
        if (getFileEntry().getFile().isValid() && !getFileEntry().getFile().isVirtual()) {
            localeName = Util.getLocaleSuffix (getFileEntry());
            if (localeName.length() > 0) {
                if (localeName.charAt(0) == PropertiesDataLoader.PRB_SEPARATOR_CHAR) {
                    localeName = localeName.substring(1);
                }
            }
        }
        return localeName;
    }
    
    /** Sets the system name. Overrides superclass method.
     *
     * @param name the new name
     */
    @Override
    public void setName (String name) {
        if(!name.startsWith(getFileEntry().getDataObject().getPrimaryFile().getName())) {
            name = Util.assembleName (getFileEntry().getDataObject().getPrimaryFile().getName(), name);
        }
        
        // new name is same as old one, do nothing
        if (name.equals(super.getName())) {
            return;
        }

        super.setName (name);
        setDisplayName(Util.getLocaleLabel(getFileEntry()));
        setShortDescription(messageToolTip());
    }

    /** Gets tooltip message for this node. Helper method. */
    private String messageToolTip () {
        FileObject fo = getFileEntry().getFile();
        return FileUtil.getFileDisplayName(fo);
    }
    
    @Override
    public String getHtmlDisplayName() { // inspired by DataNode
        try {
            StatusDecorator stat = getFileEntry().getFile().getFileSystem().getDecorator();
            String result = stat.annotateNameHtml (
                super.getDisplayName(), Collections.singleton(getFileEntry().getFile()));

            //Make sure the super string was really modified
            if (result != null && !super.getDisplayName().equals(result)) {
                return result;
            }
        } catch (FileStateInvalidException e) {
            //do nothing and fall through
        }
        return super.getHtmlDisplayName();
    }

    /** This node can be renamed. Overrides superclass method. */
    @Override
    public boolean canRename() {
        return getFileEntry().isDeleteAllowed ();
    }

    /** List new types that can be created in this node. Overrides superclass method.
     * @return new types
     */
    @Override
    public NewType[] getNewTypes () {
        return new NewType[] { new NewPropertyType((PropertiesFileEntry)getFileEntry()) };
    }

    static class NewPropertyType extends NewType {
        private PropertiesFileEntry pfEntry;

        NewPropertyType(PropertiesFileEntry pfe) {
            pfEntry = pfe;
        }

                /** Getter for name property. */
            @Override
                public String getName() {
                    return NbBundle.getBundle(PropertiesLocaleNode.class).getString("LAB_NewPropertyAction");
                }
                
                /** Gets help context. */ 
            @Override
                public HelpCtx getHelpCtx() {
                    return new HelpCtx(Util.HELP_ID_ADDING);
                }

                /** Creates new type. */
                public void create() throws IOException {
                    final PropertyPanel panel = new PropertyPanel();

                    Object selectedOption = DialogDisplayer.getDefault().notify(
                            new DialogDescriptor(
                                    panel,
                                    NbBundle.getMessage(BundleEditPanel.class,
                                                        "CTL_NewPropertyTitle")));  //NOI18N
                    if (selectedOption != NotifyDescriptor.OK_OPTION) {
                        return;
                    }

                    String key = panel.getKey();
                    String value = panel.getValue();
                    String comment = panel.getComment();

                    // add key to all entries
            if(!pfEntry.getHandler().getStructure().addItem(key, value, comment)) {
                        DialogDisplayer.getDefault().notify(
                                new NotifyDescriptor.Message(
                                        NbBundle.getMessage(
                                                PropertiesLocaleNode.class, "MSG_KeyExists",
                                                key,
                                        Util.getLocaleLabel(pfEntry)),
                                        NotifyDescriptor.ERROR_MESSAGE));
                    }
                }
    }

    /** Indicates if this node has a customizer. Overrides superclass method. 
     * @return true */
    @Override
    public boolean hasCustomizer() {
        return true;
    }
    
    /** Gets node customizer. Overrides superclass method. */
    @Override
    public Component getCustomizer() {
        return new LocaleNodeCustomizer((PropertiesFileEntry)getFileEntry());
    }
    
    /** Creates paste types for this node. Overrides superclass method. */
    @Override
    protected void createPasteTypes(Transferable t, List s) {
        super.createPasteTypes(t, s);
        Element.ItemElem item;
        Node n = NodeTransfer.node(t, NodeTransfer.MOVE);
        // cut
        if (n != null && n.canDestroy ()) {
            item = n.getCookie(Element.ItemElem.class);
            if (item != null) {
                // are we pasting into the same node
                Node n2 = getChildren().findChild(item.getKey());
                if (n == n2) {
                    return;
                }
                s.add(new KeyPasteType(item, n, KeyPasteType.MODE_PASTE_WITH_VALUE));
                s.add(new KeyPasteType(item, n, KeyPasteType.MODE_PASTE_WITHOUT_VALUE));
                return;
            }
        }
        // copy
        else {
            item = NodeTransfer.cookie(t, NodeTransfer.COPY, Element.ItemElem.class);
            if (item != null) {
                s.add(new KeyPasteType(item, null, KeyPasteType.MODE_PASTE_WITH_VALUE));
                s.add(new KeyPasteType(item, null, KeyPasteType.MODE_PASTE_WITHOUT_VALUE));
                return;
            }
        }
    }

    
    /** Paste type for keys. */
    private class KeyPasteType extends PasteType {
        
        /** Transferred item. */
        private Element.ItemElem item;

        /** The node to destroy or null. */
        private Node node;

        /** Paste mode. */
        int mode;

        /** Paste with value mode. */
        public static final int MODE_PASTE_WITH_VALUE = 1;
        
        /** Paste without value mode. */
        public static final int MODE_PASTE_WITHOUT_VALUE = 2;

        
        /** Constructs new KeyPasteType for the specific type of operation paste. */
        public KeyPasteType(Element.ItemElem item, Node node, int mode) {
            this.item = item;
            this.node = node;
            this.mode = mode;
        }

        /** Gets name. 
         * @return human presentable name of this paste type. */
        @Override
        public String getName() {
            String pasteKey = mode == 1 ? "CTL_PasteKeyValue" : "CTL_PasteKeyNoValue";
            return NbBundle.getBundle(PropertiesLocaleNode.class).getString(pasteKey);
        }

        /** Performs the paste action.
         * @return Transferable which should be inserted into the clipboard after
         * paste action. It can be null, which means that clipboard content
         * should stay the same
         */
        public Transferable paste() throws IOException {
            PropertiesStructure ps = ((PropertiesFileEntry)getFileEntry()).getHandler().getStructure();
            String value;
            if (mode == MODE_PASTE_WITH_VALUE) {
                value = item.getValue();
            } else {
                value = "";
            }
            if (ps != null) {
                Element.ItemElem newItem = ps.getItem(item.getKey());
                if (newItem == null) {
                    ps.addItem(item.getKey(), value, item.getComment());
                }
                else {
                    newItem.setValue(value);
                    newItem.setComment(item.getComment());
                }
                if (node != null) {
                    node.destroy();
                }
            }

            return null;
        }
    } // End of inner KeyPasteType class.

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy