This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 48263
Collapse All | Expand All

(-)a/properties/manifest.mf (-1 / +1 lines)
Lines 1-6 Link Here
1
Manifest-Version: 1.0
1
Manifest-Version: 1.0
2
OpenIDE-Module: org.netbeans.modules.properties/1
2
OpenIDE-Module: org.netbeans.modules.properties/1
3
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/properties/Bundle.properties
3
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/properties/Bundle.properties
4
OpenIDE-Module-Specification-Version: 1.26
4
OpenIDE-Module-Specification-Version: 1.27
5
OpenIDE-Module-Layer: org/netbeans/modules/properties/Layer.xml
5
OpenIDE-Module-Layer: org/netbeans/modules/properties/Layer.xml
6
AutoUpdate-Show-In-Client: false
6
AutoUpdate-Show-In-Client: false
(-)a/properties/src/org/netbeans/modules/properties/BundleEditPanel.java (-27 / +123 lines)
Lines 73-80 Link Here
73
public class BundleEditPanel extends JPanel implements PropertyChangeListener {
73
public class BundleEditPanel extends JPanel implements PropertyChangeListener {
74
    
74
    
75
    /** PropertiesDataObject this panel presents. */
75
    /** PropertiesDataObject this panel presents. */
76
    private PropertiesDataObject obj;
76
//    private PropertiesDataObject obj;
77
    
77
78
    /** */
79
    private BundleStructure structure;
80
78
    /** Document listener for value and comment textareas. */
81
    /** Document listener for value and comment textareas. */
79
    private DocumentListener listener;
82
    private DocumentListener listener;
80
    
83
    
Lines 88-95 Link Here
88
    private int lastSelectedColumn;
91
    private int lastSelectedColumn;
89
    
92
    
90
    /** Creates new form BundleEditPanel */
93
    /** Creates new form BundleEditPanel */
94
    @Deprecated
91
    public BundleEditPanel(final PropertiesDataObject obj, PropertiesTableModel propTableModel) {
95
    public BundleEditPanel(final PropertiesDataObject obj, PropertiesTableModel propTableModel) {
92
        this.obj = obj;
96
//        this.obj = obj;
97
        this.structure = obj.getBundleStructure();
93
        
98
        
94
        initComponents();
99
        initComponents();
95
        initAccessibility();
100
        initAccessibility();
Lines 153-159 Link Here
153
                obj.getBundleStructure().sort(modelIndex);
158
                obj.getBundleStructure().sort(modelIndex);
154
            }
159
            }
155
        });
160
        });
156
        
161
157
        
162
        
158
        table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
163
        table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
159
            public void valueChanged(ListSelectionEvent evt) {
164
            public void valueChanged(ListSelectionEvent evt) {
Lines 168-173 Link Here
168
        
173
        
169
    } // End of constructor.
174
    } // End of constructor.
170
    
175
    
176
    /** Creates new form BundleEditPanel */
177
    public BundleEditPanel(final BundleStructure structure, PropertiesTableModel propTableModel) {
178
        this.structure = structure;
179
180
        initComponents();
181
        initAccessibility();
182
        initSettings();
183
184
        // Sets table column model.
185
        table.setColumnModel(new TableViewColumnModel());
186
187
        // Sets custom table header renderer (with sorting indicators).
188
        JTableHeader header = table.getTableHeader();
189
        header.setDefaultRenderer(
190
                new TableViewHeaderRenderer(structure, header.getDefaultRenderer()));
191
192
        // Sets table model.
193
        table.setModel(propTableModel);
194
195
        // Sets table cell editor.
196
        JTextField textField = new JTextField();
197
        // Force the document to accept newlines. The textField doesn't like
198
        // it, but the same document is used by the <code>textValue</code> text
199
        // area that must accept newlines.
200
        textField.getDocument().putProperty("filterNewlines",  Boolean.FALSE); // NOI18N
201
        textField.setBorder(new LineBorder(Color.black));
202
        textField.getAccessibleContext().setAccessibleName(NbBundle.getBundle(BundleEditPanel.class).getString("ACSN_CellEditor"));
203
        textField.getAccessibleContext().setAccessibleDescription(NbBundle.getBundle(BundleEditPanel.class).getString("ACSD_CellEditor"));
204
        listener = new ModifiedListener();
205
        table.setDefaultEditor(PropertiesTableModel.StringPair.class,
206
            new PropertiesTableCellEditor(textField, textComment, textValue, valueLabel, listener));
207
208
        // Sets renderer.
209
        table.setDefaultRenderer(PropertiesTableModel.StringPair.class, new TableViewRenderer());
210
211
        updateAddButton();
212
213
        // property change listener - listens to editing state of the table
214
        table.addPropertyChangeListener(new PropertyChangeListener() {
215
            public void propertyChange(PropertyChangeEvent evt) {
216
                if (evt.getPropertyName().equals("tableCellEditor")) { // NOI18N
217
                    updateEnabled();
218
                } else if (evt.getPropertyName().equals("model")) { // NOI18N
219
                    updateAddButton();
220
                }
221
            }
222
        });
223
224
        // listens on clikcs on table header, detects column and sort accordingly to chosen one
225
        table.getTableHeader().addMouseListener(new MouseAdapter() {
226
            @Override
227
            public void mouseClicked(MouseEvent e) {
228
                TableColumnModel colModel = table.getColumnModel();
229
                int columnModelIndex = colModel.getColumnIndexAtX(e.getX());
230
                // No column was clicked.
231
                if (columnModelIndex < 0) {
232
                    return;
233
                }
234
                int modelIndex = colModel.getColumn(columnModelIndex).getModelIndex();
235
                // not detected column
236
                if (modelIndex < 0) {
237
                    return;
238
                }
239
                structure.sort(modelIndex);
240
            }
241
        });
242
243
        ListSelectionListener listSelectionListener = new ListSelectionListener() {
244
245
            public void valueChanged(ListSelectionEvent evt) {
246
                final boolean correctCellSelection = !selectionUpdateDisabled;
247
                SwingUtilities.invokeLater(new Runnable() {
248
                    public void run() {
249
                        updateSelection(correctCellSelection);
250
                    }
251
                });
252
            }
253
        };
254
255
        table.getColumnModel().getSelectionModel().addListSelectionListener(listSelectionListener);
256
        table.getSelectionModel().addListSelectionListener(listSelectionListener);
257
258
    } // End of constructor.
171
    
259
    
172
    /** Stops editing if editing is in run. */
260
    /** Stops editing if editing is in run. */
173
    protected void stopEditing() {
261
    protected void stopEditing() {
Lines 229-235 Link Here
229
                    if (ex == null) {
317
                    if (ex == null) {
230
                        return;
318
                        return;
231
                    } 
319
                    } 
232
                    String [] keys = obj.getBundleStructure().getKeys();
320
                    String [] keys = structure.getKeys();
233
                    int idx;
321
                    int idx;
234
                    for (idx = 0; idx < keys.length; idx++) {
322
                    for (idx = 0; idx < keys.length; idx++) {
235
                        String key = keys[idx];
323
                        String key = keys[idx];
Lines 248-254 Link Here
248
        }
336
        }
249
        
337
        
250
        lastSelectedColumn = column;
338
        lastSelectedColumn = column;
251
        BundleStructure structure = obj.getBundleStructure();
339
//        BundleStructure structure = obj.getBundleStructure();
252
        removeButton.setEnabled((row >= 0) && (!structure.isReadOnly()));
340
        removeButton.setEnabled((row >= 0) && (!structure.isReadOnly()));
253
        String value;
341
        String value;
254
        String comment;
342
        String comment;
Lines 281-294 Link Here
281
    }
369
    }
282
    
370
    
283
    private void updateAddButton() {
371
    private void updateAddButton() {
284
        addButton.setEnabled(!obj.getBundleStructure().isReadOnly());
372
        addButton.setEnabled(!structure.isReadOnly());
285
    }
373
    }
286
    
374
    
287
    /** Returns the main table with all values */
375
    /** Returns the main table with all values */
288
    public JTable getTable() {
376
    public JTable getTable() {
289
        return table;
377
        return table;
290
    }
378
    }
291
    
292
    
379
    
293
    /** Initializes <code>settings</code> variable. */
380
    /** Initializes <code>settings</code> variable. */
294
    private void initSettings() {
381
    private void initSettings() {
Lines 511-520 Link Here
511
        if (DialogDisplayer.getDefault().notify(msg).equals(NotifyDescriptor.OK_OPTION)) {
598
        if (DialogDisplayer.getDefault().notify(msg).equals(NotifyDescriptor.OK_OPTION)) {
512
            try {
599
            try {
513
                // Starts "atomic" acion for special undo redo manager of open support.
600
                // Starts "atomic" acion for special undo redo manager of open support.
514
                obj.getOpenSupport().atomicUndoRedoFlag = new Object();
601
//                obj.getOpenSupport().atomicUndoRedoFlag = new Object();
602
                structure.getOpenSupport().atomicUndoRedoFlag = new Object();
515
                
603
                
516
                for (int i=0; i < obj.getBundleStructure().getEntryCount(); i++) {
604
                for (int i=0; i < structure.getEntryCount(); i++) {
517
                    PropertiesFileEntry entry = obj.getBundleStructure().getNthEntry(i);
605
                    PropertiesFileEntry entry = structure.getNthEntry(i);
518
                    if (entry != null) {
606
                    if (entry != null) {
519
                        PropertiesStructure ps = entry.getHandler().getStructure();
607
                        PropertiesStructure ps = entry.getHandler().getStructure();
520
                        if (ps != null) {
608
                        if (ps != null) {
Lines 524-530 Link Here
524
                }
612
                }
525
            } finally {
613
            } finally {
526
                // finishes "atomic" undo redo action for special undo redo manager of open support
614
                // finishes "atomic" undo redo action for special undo redo manager of open support
527
                obj.getOpenSupport().atomicUndoRedoFlag = null;
615
//                obj.getOpenSupport().atomicUndoRedoFlag = null;
616
                structure.getOpenSupport().atomicUndoRedoFlag = null;
528
            }
617
            }
529
        }
618
        }
530
    }//GEN-LAST:event_removeButtonActionPerformed
619
    }//GEN-LAST:event_removeButtonActionPerformed
Lines 563-576 Link Here
563
            selectionUpdateDisabled = true;
652
            selectionUpdateDisabled = true;
564
653
565
            // Starts "atomic" acion for special undo redo manager of open support.
654
            // Starts "atomic" acion for special undo redo manager of open support.
566
            obj.getOpenSupport().atomicUndoRedoFlag = new Object();
655
//            obj.getOpenSupport().atomicUndoRedoFlag = new Object();
567
            
656
            structure.getOpenSupport().atomicUndoRedoFlag = new Object();
568
            String existingLocales = "";
657
            String existingLocales = "";
569
            String comma = ",\r\n"; //NOI18N
658
            String comma =",\r\n";
570
            int count = obj.getBundleStructure().getEntryCount();
571
            // add key to all entries
659
            // add key to all entries
572
            for (int i=0; i < count; i++) {
660
            for (int i=0; i < structure.getEntryCount(); i++) {
573
                PropertiesFileEntry entry = obj.getBundleStructure().getNthEntry(i);
661
                PropertiesFileEntry entry = structure.getNthEntry(i);
574
                
662
                
575
                if (entry != null && !entry.getHandler().getStructure().addItem(key, value, comment)) {
663
                if (entry != null && !entry.getHandler().getStructure().addItem(key, value, comment)) {
576
                    existingLocales += Util.getLocaleLabel(entry) + comma;
664
                    existingLocales += Util.getLocaleLabel(entry) + comma;
Lines 591-600 Link Here
591
                    NotifyDescriptor.ERROR_MESSAGE);
679
                    NotifyDescriptor.ERROR_MESSAGE);
592
                    DialogDisplayer.getDefault().notify(msg);
680
                    DialogDisplayer.getDefault().notify(msg);
593
            }
681
            }
594
595
        } finally {
682
        } finally {
596
            // Finishes "atomic" undo redo action for special undo redo manager of open support.
683
            // Finishes "atomic" undo redo action for special undo redo manager of open support.
597
            obj.getOpenSupport().atomicUndoRedoFlag = null;
684
//            obj.getOpenSupport().atomicUndoRedoFlag = null;
685
            structure.getOpenSupport().atomicUndoRedoFlag = null;
598
686
599
            selectionUpdateDisabled = false;
687
            selectionUpdateDisabled = false;
600
        }
688
        }
Lines 608-614 Link Here
608
            PropertiesRequestProcessor.getInstance().post(new Runnable() {
696
            PropertiesRequestProcessor.getInstance().post(new Runnable() {
609
                public void run() {
697
                public void run() {
610
                    // Find indexes.
698
                    // Find indexes.
611
                    int rowIndex = obj.getBundleStructure().getKeyIndexByName(key);
699
                    int rowIndex = structure.getKeyIndexByName(key);
612
                    
700
                    
613
                    if((rowIndex != -1)) {
701
                    if((rowIndex != -1)) {
614
                        final int row = rowIndex;
702
                        final int row = rowIndex;
Lines 677-689 Link Here
677
        private static final String SORT_ASC_ICON = ICON_PKG + "columnSortedAsc.gif";   //NOI18N
765
        private static final String SORT_ASC_ICON = ICON_PKG + "columnSortedAsc.gif";   //NOI18N
678
        private static final String SORT_DESC_ICON = ICON_PKG + "columnSortedDesc.gif"; //NOI18N
766
        private static final String SORT_DESC_ICON = ICON_PKG + "columnSortedDesc.gif"; //NOI18N
679
767
680
        private final PropertiesDataObject propDataObj;
768
        private final BundleStructure bundleStructure;
681
        private final TableCellRenderer origRenderer;
769
        private final TableCellRenderer origRenderer;
682
        private ImageIcon iconSortAsc, iconSortDesc;
770
        private ImageIcon iconSortAsc, iconSortDesc;
683
        
771
772
        @Deprecated
684
        TableViewHeaderRenderer(PropertiesDataObject propDataObj,
773
        TableViewHeaderRenderer(PropertiesDataObject propDataObj,
685
                                TableCellRenderer origRenderer) {
774
                                TableCellRenderer origRenderer) {
686
            this.propDataObj = propDataObj;
775
            bundleStructure = propDataObj.getBundleStructure();
776
            this.origRenderer = origRenderer;
777
        }
778
779
        TableViewHeaderRenderer(BundleStructure bundleStructure,
780
                                TableCellRenderer origRenderer) {
781
            this.bundleStructure = bundleStructure;
687
            this.origRenderer = origRenderer;
782
            this.origRenderer = origRenderer;
688
        }
783
        }
689
784
Lines 698-704 Link Here
698
793
699
            if (comp instanceof JLabel) {
794
            if (comp instanceof JLabel) {
700
                JLabel label = (JLabel) comp;
795
                JLabel label = (JLabel) comp;
701
                BundleStructure bundleStruct = propDataObj.getBundleStructure();
796
                BundleStructure bundleStruct = bundleStructure;
702
                int sortIndex = table.convertColumnIndexToView(
797
                int sortIndex = table.convertColumnIndexToView(
703
                                        bundleStruct.getSortIndex());
798
                                        bundleStruct.getSortIndex());
704
                if (column == sortIndex) {
799
                if (column == sortIndex) {
Lines 1003-1011 Link Here
1003
        }
1098
        }
1004
        
1099
        
1005
        private void documentModified() {
1100
        private void documentModified() {
1006
            obj.setModified(true);
1101
            ((PropertiesTableModel)table.getModel()).getFileEntry(table.getEditingColumn()).getDataObject().setModified(true);
1102
//            obj.setModified(true);
1007
        }
1103
        }
1008
        
1104
        
1009
    }
1105
    }
1010
    
1106
1011
}
1107
}
(-)a/properties/src/org/netbeans/modules/properties/BundleStructure.java (-14 / +39 lines)
Lines 44-49 Link Here
44
44
45
import java.beans.PropertyChangeEvent;
45
import java.beans.PropertyChangeEvent;
46
import java.beans.PropertyChangeListener;
46
import java.beans.PropertyChangeListener;
47
import java.io.Serializable;
47
import java.util.List;
48
import java.util.List;
48
import java.util.ArrayList;
49
import java.util.ArrayList;
49
import java.util.Collections;
50
import java.util.Collections;
Lines 51-56 Link Here
51
import java.util.Iterator;
52
import java.util.Iterator;
52
import java.util.Map;
53
import java.util.Map;
53
import java.util.TreeMap;
54
import java.util.TreeMap;
55
import org.openide.filesystems.FileObject;
54
import org.openide.loaders.MultiDataObject.Entry;
56
import org.openide.loaders.MultiDataObject.Entry;
55
import org.openide.util.WeakListeners;
57
import org.openide.util.WeakListeners;
56
58
Lines 69-75 Link Here
69
 * @author Petr Jiricka
71
 * @author Petr Jiricka
70
 */
72
 */
71
public class BundleStructure {
73
public class BundleStructure {
72
    
74
73
    /**
75
    /**
74
     * <code>PropertiesDataObject</code> whose structure is described
76
     * <code>PropertiesDataObject</code> whose structure is described
75
     * by this object
77
     * by this object
Lines 109-115 Link Here
109
111
110
    /** listens to changes on the underlying <code>PropertyDataObject</code> */
112
    /** listens to changes on the underlying <code>PropertyDataObject</code> */
111
    private PropertyChangeListener propListener;
113
    private PropertyChangeListener propListener;
112
    
114
115
    protected BundleStructure() {
116
        obj = null;
117
    }
113
    /**
118
    /**
114
     * Creates a new instance describing a given
119
     * Creates a new instance describing a given
115
     * <code>PropertiesDataObject</code>.
120
     * <code>PropertiesDataObject</code>.
Lines 543-548 Link Here
543
        return comparator.isAscending();
548
        return comparator.isAscending();
544
    }
549
    }
545
550
551
    PropertiesOpen getOpenSupport() {
552
        throw new UnsupportedOperationException("Not yet implemented");
553
    }
554
546
    /**
555
    /**
547
     * Builds (or rebuilds) a sorted list of entries of the underlying
556
     * Builds (or rebuilds) a sorted list of entries of the underlying
548
     * <code>PropertiesDataObject<code> and a sorted list of keys gathered
557
     * <code>PropertiesDataObject<code> and a sorted list of keys gathered
Lines 551-557 Link Here
551
     * @see  #entries
560
     * @see  #entries
552
     * @see  #keyList
561
     * @see  #keyList
553
     */
562
     */
554
    private void updateEntries() {
563
    void updateEntries() {
555
        Map<String,PropertiesFileEntry> tm = new TreeMap<String,PropertiesFileEntry>(
564
        Map<String,PropertiesFileEntry> tm = new TreeMap<String,PropertiesFileEntry>(
556
                PropertiesDataObject.getSecondaryFilesComparator());
565
                PropertiesDataObject.getSecondaryFilesComparator());
557
        for (Entry entry : obj.secondaryEntries()) {
566
        for (Entry entry : obj.secondaryEntries()) {
Lines 577-583 Link Here
577
     *
586
     *
578
     * @see  #keyList
587
     * @see  #keyList
579
     */
588
     */
580
    private synchronized void buildKeySet() {
589
    protected synchronized void buildKeySet() {
581
        List<String> keyList = new ArrayList<String>() {
590
        List<String> keyList = new ArrayList<String>() {
582
            public boolean equals(Object obj) {
591
            public boolean equals(Object obj) {
583
                if (!(obj instanceof ArrayList)) {
592
                if (!(obj instanceof ArrayList)) {
Lines 602-617 Link Here
602
        int entriesCount = getEntryCount();
611
        int entriesCount = getEntryCount();
603
        for (int index = 0; index < entriesCount; index++) {
612
        for (int index = 0; index < entriesCount; index++) {
604
            PropertiesFileEntry entry = getNthEntry(index);
613
            PropertiesFileEntry entry = getNthEntry(index);
605
            PropertiesStructure ps = entry.getHandler().getStructure();
614
            if (entry != null) {
606
            if (ps != null) {
615
                PropertiesStructure ps = entry.getHandler().getStructure();
607
                for (Iterator<Element.ItemElem> it = ps.allItems(); it.hasNext(); ) {
616
                if (ps != null) {
608
                    Element.ItemElem item = it.next();
617
                    for (Iterator<Element.ItemElem> it = ps.allItems(); it.hasNext(); ) {
609
                    if (item == null) {
618
                        Element.ItemElem item = it.next();
610
                        continue;
619
                        if (item == null) {
611
                    }
620
                            continue;
612
                    String key = item.getKey();
621
                        }
613
                    if (key != null && !(keyList.contains(key))) {
622
                        String key = item.getKey();
614
                        keyList.add(item.getKey());
623
                        if (key != null && !(keyList.contains(key))) {
624
                            keyList.add(item.getKey());
625
                        }
615
                    }
626
                    }
616
                }
627
                }
617
            }
628
            }
Lines 676-681 Link Here
676
     * @see  #removePropertyBundleListener
687
     * @see  #removePropertyBundleListener
677
     */
688
     */
678
    public void addPropertyBundleListener(PropertyBundleListener l) {
689
    public void addPropertyBundleListener(PropertyBundleListener l) {
690
        if (propBundleSupport == null) propBundleSupport = new PropertyBundleSupport(this);
679
        propBundleSupport.addPropertyBundleListener(l);
691
        propBundleSupport.addPropertyBundleListener(l);
680
    }
692
    }
681
693
Lines 707-712 Link Here
707
        );
719
        );
708
    }
720
    }
709
721
722
    void notifyOneFileChanged(FileObject file) {
723
        // PENDING - events should be finer
724
        // find out whether global key table has changed and fire a change
725
        // according to that
726
        List oldKeyList = keyList;
727
728
        buildKeySet();
729
        if (!keyList.equals(oldKeyList)) {
730
            propBundleSupport.fireBundleDataChanged();
731
        } else {
732
            propBundleSupport.fireFileChanged(file.getName());
733
        }
734
    }
710
    /**
735
    /**
711
     * Notifies registered listeners of a change in a single file entry.
736
     * Notifies registered listeners of a change in a single file entry.
712
     * Depending whether a list of keys has changed, either an event
737
     * Depending whether a list of keys has changed, either an event
(-)a/properties/src/org/netbeans/modules/properties/MultiBundleStructure.java (+291 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2008 Sun Microsystems, Inc.
38
 */
39
package org.netbeans.modules.properties;
40
41
import java.io.Serializable;
42
import java.util.ArrayList;
43
import java.util.Arrays;
44
import java.util.HashSet;
45
import java.util.List;
46
import java.util.Locale;
47
import java.util.Set;
48
import org.openide.filesystems.FileObject;
49
import org.openide.loaders.DataObject;
50
import org.openide.loaders.DataObjectNotFoundException;
51
import org.openide.util.Exceptions;
52
53
/**
54
 *
55
 * @author alexeybutenko
56
 */
57
class MultiBundleStructure extends BundleStructure implements Serializable {
58
59
    private transient FileObject[] files;
60
    private transient PropertiesFileEntry primaryEntry;
61
    private String baseName;
62
63
    /** Generated Serialized Version UID. */
64
    static final long serialVersionUID = 7501232754255253334L;
65
66
    private transient PropertiesOpen openSupport;
67
    /** Lock used for synchronization of <code>openSupport</code> instance creation */
68
    private final transient Object OPEN_SUPPORT_LOCK = new Object();
69
70
71
    protected MultiBundleStructure() {
72
//        super();
73
//        files = null;
74
//        primaryEntry = null;
75
//        baseName = null;
76
    }
77
78
    public MultiBundleStructure(PropertiesDataObject obj) {
79
//        super(obj);
80
        this.obj = obj;
81
        baseName = Util.getBaseName(obj.getName());
82
    }
83
84
    /**
85
     * Find entries according to PropertiesDataObject
86
     *
87
     */
88
    private void findEntries() {
89
        try {
90
            if (obj == null) return;
91
            if (!obj.isValid()) {
92
                if (files.length == 1) {
93
                    primaryEntry = null;
94
                    obj = null;
95
                    files = null;
96
                    return;
97
                }
98
            } else {
99
                obj = Util.findPrimaryDataObject(obj);
100
                primaryEntry = (PropertiesFileEntry) obj.getPrimaryEntry();
101
            }
102
            FileObject primary = primaryEntry.getFile();
103
            FileObject parent = primary.getParent();
104
            List<FileObject> listFileObjects = new ArrayList<FileObject>();
105
            String fName;
106
            FileObject oldCandidate;
107
            for (FileObject file : parent.getChildren()) {
108
                fName = file.getName();
109
                if (fName.equals(baseName) && file.isValid()) {
110
                    listFileObjects.add(0,file);
111
                }
112
                if (fName.indexOf(baseName) != -1) {
113
                    int index = fName.indexOf(PropertiesDataLoader.PRB_SEPARATOR_CHAR);
114
                    if (index == baseName.length()) {
115
                        oldCandidate = null;
116
                        while (index != -1) {
117
                            FileObject candidate = file;
118
                            if (candidate != null && isValidLocaleSuffix(fName.substring(index)) && oldCandidate == null && file.isValid()) {
119
                                listFileObjects.add(candidate);
120
                                oldCandidate = candidate;
121
                            }
122
                            index = fName.indexOf(PropertiesDataLoader.PRB_SEPARATOR_CHAR, index + 1);
123
                        }
124
                    }
125
                }
126
            }
127
            files = new FileObject[listFileObjects.size()];
128
            int index = 0;
129
            for (FileObject file : listFileObjects) {
130
                files[index++] = file;
131
            }
132
            primaryEntry = getNthEntry(0);
133
            obj = (PropertiesDataObject) primaryEntry.getDataObject();
134
        } catch (DataObjectNotFoundException ex) {
135
            Exceptions.printStackTrace(ex);
136
        }
137
    }
138
139
    void updateEntries() {
140
        findEntries();
141
        if (files != null) {
142
            buildKeySet();
143
        }
144
    }
145
146
    @Override
147
    public PropertiesFileEntry getNthEntry(int index) {
148
        if (files == null) {
149
            return super.getNthEntry(index);
150
//            notifyEntriesNotInitialized();
151
        }
152
        if (index >= 0 && index < files.length) {
153
            try {
154
                return (PropertiesFileEntry) ((PropertiesDataObject) DataObject.find(files[index])).getPrimaryEntry();
155
            } catch (DataObjectNotFoundException ex) {
156
                Exceptions.printStackTrace(ex);
157
                return null;
158
            }
159
        } else {
160
            return null;
161
        }
162
    }
163
164
    /**
165
     * Retrieves an index of a file entry representing the given file.
166
     *
167
     * @param  fileName  simple name (without path and extension) of the
168
     *                   primary or secondary file
169
     * @return  index of the entry representing a file with the given filename;
170
     *          or <code>-1</code> if no such entry is found
171
     * @exception  java.lang.IllegalStateException
172
     *             if the list of entries has not been initialized yet
173
     * @see  #getEntryByFileName
174
     */
175
    @Override
176
    public int getEntryIndexByFileName(String fileName) {
177
        if (files == null) {
178
            notifyEntriesNotInitialized();
179
        }
180
        for (int i = 0; i < getEntryCount(); i++) {
181
            if (files[i].getName().equals(fileName)) {
182
                return i;
183
            }
184
        }
185
        return -1;
186
    }
187
188
    /**
189
     * Retrieves a file entry representing the given file
190
     *
191
     * @param  fileName  simple name (excl. path, incl. extension) of the
192
     *                   primary or secondary file
193
     * @return  entry representing the given file;
194
     *          or <code>null</code> if not such entry is found
195
     * @exception  java.lang.IllegalStateException
196
     *             if the list of entries has not been initialized yet
197
     * @see  #getEntryIndexByFileName
198
     */
199
    @Override
200
    public PropertiesFileEntry getEntryByFileName(String fileName) {
201
        int index = getEntryIndexByFileName(fileName);
202
        try {
203
            return (index == -1) ? null : (PropertiesFileEntry) ((PropertiesDataObject) DataObject.find(files[index])).getPrimaryEntry();
204
        } catch (DataObjectNotFoundException ex) {
205
            Exceptions.printStackTrace(ex);
206
            return null;
207
        }
208
    }
209
210
    /**
211
     * Retrieves number of file entries.
212
     *
213
     * @return  number of file entries
214
     * @exception  java.lang.IllegalStateException
215
     *             if the list of entries has not been initialized yet
216
     */
217
    @Override
218
    public int getEntryCount() {
219
        if (files == null) {
220
            return 0;//super.getEntryCount();
221
//            notifyEntriesNotInitialized();
222
        }
223
        return files.length;
224
    }
225
226
    /**
227
     * Throws a runtime exception with a message that the entries
228
     * have not been initialized yet.
229
     *
230
     * @exception  java.lang.IllegalStateException  thrown always
231
     * @see  #updateEntries
232
     */
233
    private void notifyEntriesNotInitialized() {
234
        throw new IllegalStateException(
235
                "Resource Bundles: Entries not initialized");           //NOI18N
236
    }
237
238
    private static boolean isValidLocaleSuffix(String s) {
239
        // first char is _
240
        int n = s.length();
241
        String s1;
242
        // check first suffix - language (two chars)
243
        if (n == 3 || (n > 3 && s.charAt(3) == PropertiesDataLoader.PRB_SEPARATOR_CHAR)) {
244
            s1 = s.substring(1, 3).toLowerCase();
245
        // language must be followed by a valid country suffix or no suffix
246
        } else {
247
            return false;
248
        }
249
        // check second suffix - country (two chars)
250
        String s2;
251
        if (n == 3) {
252
            s2 = null;
253
        } else if (n == 6 || (n > 6 && s.charAt(6) == PropertiesDataLoader.PRB_SEPARATOR_CHAR)) {
254
            s2 = s.substring(4, 6).toUpperCase();
255
        // country may be followed by whatever additional suffix
256
        } else {
257
            return false;
258
        }
259
260
        Set<String> knownLanguages = new HashSet<String>(Arrays.asList(Locale.getISOLanguages()));
261
        if (!knownLanguages.contains(s1)) {
262
            return false;
263
        }
264
265
        if (s2 != null) {
266
            Set<String> knownCountries = new HashSet<String>(Arrays.asList(Locale.getISOCountries()));
267
            if (!knownCountries.contains(s2)) {
268
                return false;
269
            }
270
        }
271
        return true;
272
    }
273
    @Override
274
    public PropertiesOpen getOpenSupport() {
275
        synchronized (OPEN_SUPPORT_LOCK) {
276
            if (openSupport == null) {
277
                openSupport = new PropertiesOpen(this);
278
            }
279
            return openSupport;
280
        }
281
    }
282
283
    @Override
284
    public int getKeyCount() {
285
        try {
286
            return super.getKeyCount();
287
        } catch (IllegalStateException ie) {
288
            return 0;
289
        }
290
    }
291
}
(-)a/properties/src/org/netbeans/modules/properties/PropertiesDataLoader.java (-7 / +12 lines)
Lines 87-92 Link Here
87
    /** */
87
    /** */
88
    private static Set<String> knownCountries;
88
    private static Set<String> knownCountries;
89
89
90
    /** */
91
    private static boolean nestedView = false;
92
90
    /** Creates new PropertiesDataLoader. */
93
    /** Creates new PropertiesDataLoader. */
91
    public PropertiesDataLoader() {
94
    public PropertiesDataLoader() {
92
        super("org.netbeans.modules.properties.PropertiesDataObject"); // NOI18N
95
        super("org.netbeans.modules.properties.PropertiesDataObject"); // NOI18N
Lines 153-166 Link Here
153
             * corresponding to an existing file
156
             * corresponding to an existing file
154
             */
157
             */
155
            String fName = fo.getName();
158
            String fName = fo.getName();
156
            int index = fName.indexOf(PRB_SEPARATOR_CHAR);
159
            if (nestedView) {
157
            while (index != -1) {
160
                int index = fName.indexOf(PRB_SEPARATOR_CHAR);
158
                FileObject candidate = fo.getParent().getFileObject(
161
                while (index != -1) {
159
                        fName.substring(0, index), fo.getExt());
162
                    FileObject candidate = fo.getParent().getFileObject(
160
                if (candidate != null && isValidLocaleSuffix(fName.substring(index))) {
163
                            fName.substring(0, index), fo.getExt());
161
                    return candidate;
164
                    if (candidate != null && isValidLocaleSuffix(fName.substring(index))) {
165
                        return candidate;
166
                    }
167
                    index = fName.indexOf(PRB_SEPARATOR_CHAR, index + 1);
162
                }
168
                }
163
                index = fName.indexOf(PRB_SEPARATOR_CHAR, index + 1);
164
            }
169
            }
165
            return fo;
170
            return fo;
166
        } else {
171
        } else {
(-)a/properties/src/org/netbeans/modules/properties/PropertiesDataNode.java (-7 / +6 lines)
Lines 60-66 Link Here
60
import org.openide.loaders.DataFolder;
60
import org.openide.loaders.DataFolder;
61
import org.openide.loaders.DataNode;
61
import org.openide.loaders.DataNode;
62
import org.openide.loaders.DataObject;
62
import org.openide.loaders.DataObject;
63
import org.openide.loaders.FileEntry;
64
import org.openide.nodes.Children;
63
import org.openide.nodes.Children;
65
import org.openide.nodes.Node;
64
import org.openide.nodes.Node;
66
import org.openide.nodes.NodeTransfer;
65
import org.openide.nodes.NodeTransfer;
Lines 103-109 Link Here
103
    public PropertiesDataNode(DataObject dataObject, Children children) {
102
    public PropertiesDataNode(DataObject dataObject, Children children) {
104
        super(dataObject, children);
103
        super(dataObject, children);
105
        setIconBaseWithExtension("org/netbeans/modules/properties/propertiesObject.png"); // NOI18N
104
        setIconBaseWithExtension("org/netbeans/modules/properties/propertiesObject.png"); // NOI18N
106
        
107
        dataObjectListener = new NameUpdater();
105
        dataObjectListener = new NameUpdater();
108
        dataObject.addPropertyChangeListener(
106
        dataObject.addPropertyChangeListener(
109
                WeakListeners.propertyChange(dataObjectListener, dataObject));
107
                WeakListeners.propertyChange(dataObjectListener, dataObject));
Lines 321-334 Link Here
321
    } // End of NewLocaleType class.
319
    } // End of NewLocaleType class.
322
320
323
    private static boolean containsLocale(PropertiesDataObject propertiesDataObject, Locale locale) {
321
    private static boolean containsLocale(PropertiesDataObject propertiesDataObject, Locale locale) {
324
        FileObject file = propertiesDataObject.getPrimaryFile();
322
        FileObject file = propertiesDataObject.getBundleStructure().getNthEntry(0).getFile();
323
//        FileObject file = propertiesDataObject.getPrimaryFile();
325
        String newName = file.getName() + PropertiesDataLoader.PRB_SEPARATOR_CHAR + locale;
324
        String newName = file.getName() + PropertiesDataLoader.PRB_SEPARATOR_CHAR + locale;
326
        Iterator it = propertiesDataObject.secondaryEntries().iterator();
325
        BundleStructure structure = propertiesDataObject.getBundleStructure();
327
        while (it.hasNext()) {
326
        for (int i = 0; i<structure.getEntryCount();i++) {
328
            FileObject f = ((FileEntry)it.next()).getFile();
327
            FileObject f = structure.getNthEntry(i).getFile();
329
            if (newName.startsWith(f.getName()) && f.getName().length() > file.getName().length())
328
            if (newName.startsWith(f.getName()) && f.getName().length() > file.getName().length())
330
                file = f;
329
                file = f;
331
        }        
330
        }
332
        return file.getName().equals(newName);
331
        return file.getName().equals(newName);
333
    }
332
    }
334
}
333
}
(-)a/properties/src/org/netbeans/modules/properties/PropertiesDataObject.java (-44 / +67 lines)
Lines 38-47 Link Here
38
 * Version 2 license, then the option applies only if the new code is
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
39
 * made subject to such option by the copyright holder.
40
 */
40
 */
41
42
43
package org.netbeans.modules.properties;
41
package org.netbeans.modules.properties;
44
45
42
46
import java.beans.PropertyChangeEvent;
43
import java.beans.PropertyChangeEvent;
47
import java.beans.PropertyChangeListener;
44
import java.beans.PropertyChangeListener;
Lines 60-69 Link Here
60
import org.openide.loaders.DataNode;
57
import org.openide.loaders.DataNode;
61
import org.openide.loaders.DataObject;
58
import org.openide.loaders.DataObject;
62
import org.openide.loaders.DataObjectExistsException;
59
import org.openide.loaders.DataObjectExistsException;
60
import org.openide.loaders.DataObjectNotFoundException;
63
import org.openide.loaders.MultiDataObject;
61
import org.openide.loaders.MultiDataObject;
64
import org.openide.nodes.Children;
62
import org.openide.nodes.Children;
65
import org.openide.nodes.CookieSet;
63
import org.openide.nodes.CookieSet;
66
import org.openide.nodes.Node;
64
import org.openide.nodes.Node;
65
import org.openide.util.Exceptions;
67
import org.openide.util.Lookup;
66
import org.openide.util.Lookup;
68
import org.openide.util.WeakListeners;
67
import org.openide.util.WeakListeners;
69
import static java.util.logging.Level.FINER;
68
import static java.util.logging.Level.FINER;
Lines 79-90 Link Here
79
78
80
    /** Generated Serialized Version UID. */
79
    /** Generated Serialized Version UID. */
81
    static final long serialVersionUID = 4795737295255253334L;
80
    static final long serialVersionUID = 4795737295255253334L;
82
    
81
83
    static final Logger LOG = Logger.getLogger(PropertiesDataObject.class.getName());
82
    static final Logger LOG = Logger.getLogger(PropertiesDataObject.class.getName());
84
83
85
    /** Structural view of the dataobject */
84
    /** Structural view of the dataobject */
86
    private transient BundleStructure bundleStructure;
85
    private transient BundleStructure bundleStructure;
87
    
86
88
    /** Open support for this data object. Provides editable table view on bundle. */
87
    /** Open support for this data object. Provides editable table view on bundle. */
89
    private transient PropertiesOpen openSupport;
88
    private transient PropertiesOpen openSupport;
90
89
Lines 94-100 Link Here
94
    // Hack due having lock on secondaries, can't override handleCopy, handleMove at all.
93
    // Hack due having lock on secondaries, can't override handleCopy, handleMove at all.
95
    /** Suffix used by copying/moving dataObject. */
94
    /** Suffix used by copying/moving dataObject. */
96
    private transient String pasteSuffix;
95
    private transient String pasteSuffix;
97
    
96
98
    /** */
97
    /** */
99
    private Lookup lookup;
98
    private Lookup lookup;
100
99
Lines 110-116 Link Here
110
     *              for the specified file
109
     *              for the specified file
111
     */
110
     */
112
    public PropertiesDataObject(final FileObject primaryFile,
111
    public PropertiesDataObject(final FileObject primaryFile,
113
                                final PropertiesDataLoader loader)
112
            final PropertiesDataLoader loader)
114
            throws DataObjectExistsException {
113
            throws DataObjectExistsException {
115
        super(primaryFile, loader);
114
        super(primaryFile, loader);
116
        // use editor support
115
        // use editor support
Lines 122-133 Link Here
122
    PropertiesEncoding getEncoding() {
121
    PropertiesEncoding getEncoding() {
123
        return ((PropertiesDataLoader) getLoader()).getEncoding();
122
        return ((PropertiesDataLoader) getLoader()).getEncoding();
124
    }
123
    }
125
    
124
126
    @Override
125
    @Override
127
    public Lookup getLookup() {
126
    public Lookup getLookup() {
128
        return getCookieSet().getLookup();
127
        return getCookieSet().getLookup();
129
    }
128
    }
130
    
129
131
    /** Initializes the object. Used by construction and deserialized. */
130
    /** Initializes the object. Used by construction and deserialized. */
132
    private void initialize() {
131
    private void initialize() {
133
        bundleStructure = null;
132
        bundleStructure = null;
Lines 154-160 Link Here
154
    CookieSet getCookieSet0() {
153
    CookieSet getCookieSet0() {
155
        return getCookieSet();
154
        return getCookieSet();
156
    }
155
    }
157
    
156
158
    /** Copies primary and secondary files to new folder.
157
    /** Copies primary and secondary files to new folder.
159
     * Overrides superclass method.
158
     * Overrides superclass method.
160
     * @param df the new folder
159
     * @param df the new folder
Lines 175-181 Link Here
175
            pasteSuffix = null;
174
            pasteSuffix = null;
176
        }
175
        }
177
    }
176
    }
178
    
177
179
    /** Moves primary and secondary files to a new folder.
178
    /** Moves primary and secondary files to a new folder.
180
     * Overrides superclass method.
179
     * Overrides superclass method.
181
     * @param df the new folder
180
     * @param df the new folder
Lines 197-209 Link Here
197
196
198
        try {
197
        try {
199
            pasteSuffix = createPasteSuffix(df);
198
            pasteSuffix = createPasteSuffix(df);
200
        
199
201
            return super.handleMove(df);
200
            return super.handleMove(df);
202
        } finally {
201
        } finally {
203
            pasteSuffix = null;
202
            pasteSuffix = null;
204
        }
203
        }
205
    }
204
    }
206
    
205
207
    /** Gets suffix used by entries by copying/moving. */
206
    /** Gets suffix used by entries by copying/moving. */
208
    String getPasteSuffix() {
207
    String getPasteSuffix() {
209
        return pasteSuffix;
208
        return pasteSuffix;
Lines 215-221 Link Here
215
    void removeSecondaryEntry2(Entry fe) {
214
    void removeSecondaryEntry2(Entry fe) {
216
        if (LOG.isLoggable(FINER)) {
215
        if (LOG.isLoggable(FINER)) {
217
            LOG.finer("removeSecondaryEntry2(Entry "                    //NOI18N
216
            LOG.finer("removeSecondaryEntry2(Entry "                    //NOI18N
218
                      + FileUtil.getFileDisplayName(fe.getFile()) + ')');
217
                    + FileUtil.getFileDisplayName(fe.getFile()) + ')');
219
        }
218
        }
220
        removeSecondaryEntry (fe);
219
        removeSecondaryEntry (fe);
221
    }
220
    }
Lines 226-251 Link Here
226
        String basicName = getPrimaryFile().getName();
225
        String basicName = getPrimaryFile().getName();
227
226
228
        DataObject[] children = folder.getChildren();
227
        DataObject[] children = folder.getChildren();
229
        
228
230
        
229
231
        // Repeat until there is not such file name.
230
        // Repeat until there is not such file name.
232
        for(int i = 0; ; i++) {
231
        for(int i = 0; ; i++) {
233
            String newName;
232
            String newName;
234
            
233
235
            if (i == 0) {
234
            if (i == 0) {
236
                newName = basicName;
235
                newName = basicName;
237
            } else {
236
            } else {
238
                newName = basicName + i;
237
                newName = basicName + i;
239
            }
238
            }
240
            boolean exist = false;
239
            boolean exist = false;
241
            
240
242
            for(int j = 0; j < children.length; j++) {
241
            for(int j = 0; j < children.length; j++) {
243
                if(children[j] instanceof PropertiesDataObject && newName.equals(children[j].getName())) {
242
                if(children[j] instanceof PropertiesDataObject && newName.equals(children[j].getName())) {
244
                    exist = true;
243
                    exist = true;
245
                    break;
244
                    break;
246
                }
245
                }
247
            }
246
            }
248
                
247
249
            if(!exist) {
248
            if(!exist) {
250
                if (i == 0) {
249
                if (i == 0) {
251
                    return ""; // NOI18N
250
                    return ""; // NOI18N
Lines 258-270 Link Here
258
257
259
    /** Returns open support. It's used by all subentries as open support too. */
258
    /** Returns open support. It's used by all subentries as open support too. */
260
    public PropertiesOpen getOpenSupport() {
259
    public PropertiesOpen getOpenSupport() {
261
        synchronized(OPEN_SUPPORT_LOCK) {
260
//        synchronized (OPEN_SUPPORT_LOCK) {
262
            if(openSupport == null) {
261
            return ((MultiBundleStructure)getBundleStructure()).getOpenSupport();
263
                openSupport = new PropertiesOpen(this);
262
//            PropertiesDataObject dataObject = this;
264
            }
263
//            try {
265
264
//                dataObject = Util.findPrimaryDataObject(this);
266
            return openSupport;
265
//            } catch (DataObjectNotFoundException ex) {
267
        }
266
//                Exceptions.printStackTrace(ex);
267
//            }
268
//            if (this == dataObject) {
269
//                    if (openSupport == null) {
270
//                        openSupport = new PropertiesOpen(this);
271
//                    }
272
//
273
//                    return openSupport;
274
//            } else {
275
//                return dataObject.getOpenSupport();
276
//            }
277
//        }
268
    }
278
    }
269
279
270
    /** Updates modification status of this dataobject from its entries. */
280
    /** Updates modification status of this dataobject from its entries. */
Lines 294-300 Link Here
294
     *
304
     *
295
     * @return the node representation for this data object
305
     * @return the node representation for this data object
296
     * @see DataNode
306
     * @see DataNode
297
     */                                                           
307
     */
298
    @Override
308
    @Override
299
    protected Node createNodeDelegate () {
309
    protected Node createNodeDelegate () {
300
        return new PropertiesDataNode(this);
310
        return new PropertiesDataNode(this);
Lines 304-318 Link Here
304
        return new PropertiesChildren();
314
        return new PropertiesChildren();
305
    }
315
    }
306
316
317
    //TODO XXX Now it is always false
307
    boolean isMultiLocale() {
318
    boolean isMultiLocale() {
308
        return secondaryEntries().size() > 0;
319
        return secondaryEntries().size() > 0;
309
    }
320
    }
310
321
311
    /** Returns a structural view of this data object */
322
    /** Returns a structural view of this data object */
312
    public BundleStructure getBundleStructure() {
323
    public BundleStructure getBundleStructure() {
313
        if (bundleStructure == null)
324
        PropertiesDataObject dataObject = null;
314
            bundleStructure = new BundleStructure(this);
325
        try {
315
        return bundleStructure;
326
            dataObject = Util.findPrimaryDataObject(this);
327
        } catch (DataObjectNotFoundException ex) {
328
            Exceptions.printStackTrace(ex);
329
        }
330
        if (this == dataObject) {
331
            if (bundleStructure == null) {
332
                bundleStructure = new MultiBundleStructure(this);
333
                ((MultiBundleStructure)bundleStructure).updateEntries();
334
            }
335
            return bundleStructure;
336
        } else {
337
            return dataObject.getBundleStructure();
338
        }
316
    }
339
    }
317
340
318
    /** Comparator used for ordering secondary files, works over file names */
341
    /** Comparator used for ordering secondary files, works over file names */
Lines 326-339 Link Here
326
        LOG.finer("fireNameChange()");                                  //NOI18N
349
        LOG.finer("fireNameChange()");                                  //NOI18N
327
        firePropertyChange(PROP_NAME, null, null);
350
        firePropertyChange(PROP_NAME, null, null);
328
    }
351
    }
329
    
352
330
    /** Deserialization. */
353
    /** Deserialization. */
331
    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
354
    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
332
        in.defaultReadObject();
355
        in.defaultReadObject();
333
        initialize();
356
        initialize();
334
    }
357
    }
335
358
336
    
359
337
    /** Children of this <code>PropertiesDataObject</code>. */
360
    /** Children of this <code>PropertiesDataObject</code>. */
338
    private class PropertiesChildren extends Children.Keys<String> {
361
    private class PropertiesChildren extends Children.Keys<String> {
339
362
Lines 341-353 Link Here
341
        private PropertyChangeListener propertyListener = null;
364
        private PropertyChangeListener propertyListener = null;
342
        private PropertyChangeListener weakPropListener = null;
365
        private PropertyChangeListener weakPropListener = null;
343
366
344
        
367
345
        /** Constructor.*/
368
        /** Constructor.*/
346
        PropertiesChildren() {
369
        PropertiesChildren() {
347
            super();
370
            super();
348
        }
371
        }
349
372
350
        
373
351
        /** Sets all keys in the correct order */
374
        /** Sets all keys in the correct order */
352
        protected void mySetKeys() {
375
        protected void mySetKeys() {
353
            TreeSet<String> newKeys = new TreeSet<String>(new Comparator<String>() {
376
            TreeSet<String> newKeys = new TreeSet<String>(new Comparator<String>() {
Lines 366-372 Link Here
366
            });
389
            });
367
390
368
            newKeys.add(getPrimaryEntry().getFile().getName());
391
            newKeys.add(getPrimaryEntry().getFile().getName());
369
            
392
370
            for (Entry entry : secondaryEntries()) {
393
            for (Entry entry : secondaryEntries()) {
371
                newKeys.add(entry.getFile().getName());
394
                newKeys.add(entry.getFile().getName());
372
            }
395
            }
Lines 379-392 Link Here
379
        @Override
402
        @Override
380
        protected void addNotify () {
403
        protected void addNotify () {
381
            mySetKeys();
404
            mySetKeys();
382
            
405
383
            // listener
406
            // listener
384
            if(propertyListener == null) {
407
            if(propertyListener == null) {
385
                propertyListener = new PropertyChangeListener () {
408
                propertyListener = new PropertyChangeListener () {
386
                    public void propertyChange(PropertyChangeEvent evt) {
409
                    public void propertyChange(PropertyChangeEvent evt) {
387
                        if(PROP_FILES.equals(evt.getPropertyName())) {
410
                        if(PROP_FILES.equals(evt.getPropertyName())) {
388
                            if (isMultiLocale()) {
411
                            if (isMultiLocale()) {
389
                            mySetKeys();
412
                                mySetKeys();
390
                            } else {
413
                            } else {
391
                                // These children are only used for two or more locales.
414
                                // These children are only used for two or more locales.
392
                                // If only default locale is left, disconnect the listener.
415
                                // If only default locale is left, disconnect the listener.
Lines 395-405 Link Here
395
                                if (propertyListener != null) {
418
                                if (propertyListener != null) {
396
                                    PropertiesDataObject.this.removePropertyChangeListener(weakPropListener);
419
                                    PropertiesDataObject.this.removePropertyChangeListener(weakPropListener);
397
                                    propertyListener = null;
420
                                    propertyListener = null;
421
                                }
422
                            }
398
                        }
423
                        }
399
                    }
424
                    }
400
                        }
425
                };
401
                    }
402
                }; 
403
                weakPropListener = WeakListeners.propertyChange(propertyListener, PropertiesDataObject.this);
426
                weakPropListener = WeakListeners.propertyChange(propertyListener, PropertiesDataObject.this);
404
                PropertiesDataObject.this.addPropertyChangeListener(weakPropListener);
427
                PropertiesDataObject.this.addPropertyChangeListener(weakPropListener);
405
            }
428
            }
Lines 419-438 Link Here
419
            if (entryName == null) {
442
            if (entryName == null) {
420
                return null;
443
                return null;
421
            }
444
            }
422
            
445
423
            PropertiesFileEntry entry = (PropertiesFileEntry)getPrimaryEntry();
446
            PropertiesFileEntry entry = (PropertiesFileEntry)getPrimaryEntry();
424
            
447
425
            if(entryName.equals(entry.getFile().getName())) {
448
            if(entryName.equals(entry.getFile().getName())) {
426
                return new Node[] {entry.getNodeDelegate()};
449
                return new Node[] {entry.getNodeDelegate()};
427
            }
450
            }
428
            for(Iterator<Entry> it = secondaryEntries().iterator();it.hasNext();) {
451
            for(Iterator<Entry> it = secondaryEntries().iterator();it.hasNext();) {
429
                entry = (PropertiesFileEntry)it.next();
452
                entry = (PropertiesFileEntry)it.next();
430
                
453
431
                if (entryName.equals(entry.getFile().getName())) {
454
                if (entryName.equals(entry.getFile().getName())) {
432
                    return new Node[] {entry.getNodeDelegate()};
455
                    return new Node[] {entry.getNodeDelegate()};
433
                }
456
                }
434
            }
457
            }
435
                
458
436
            return null;
459
            return null;
437
        }
460
        }
438
461
(-)a/properties/src/org/netbeans/modules/properties/PropertiesOpen.java (-93 / +295 lines)
Lines 57-64 Link Here
57
import java.io.ObjectInput;
57
import java.io.ObjectInput;
58
import java.io.ObjectOutput;
58
import java.io.ObjectOutput;
59
import java.io.Serializable;
59
import java.io.Serializable;
60
import java.util.ArrayList;
60
import java.util.Enumeration;
61
import java.util.Enumeration;
62
import java.util.HashMap;
61
import java.util.Iterator;
63
import java.util.Iterator;
64
import java.util.List;
62
import javax.swing.Action;
65
import javax.swing.Action;
63
import javax.swing.event.ChangeListener;
66
import javax.swing.event.ChangeListener;
64
import javax.swing.JPanel;
67
import javax.swing.JPanel;
Lines 91-97 Link Here
91
import org.openide.util.actions.SystemAction;
94
import org.openide.util.actions.SystemAction;
92
import org.openide.windows.CloneableOpenSupport;
95
import org.openide.windows.CloneableOpenSupport;
93
import org.openide.windows.CloneableTopComponent;
96
import org.openide.windows.CloneableTopComponent;
94
import org.openide.util.Utilities;
95
import org.openide.DialogDescriptor;
97
import org.openide.DialogDescriptor;
96
import org.openide.filesystems.FileUtil;
98
import org.openide.filesystems.FileUtil;
97
99
Lines 105-112 Link Here
105
                            implements OpenCookie, CloseCookie {
107
                            implements OpenCookie, CloseCookie {
106
108
107
    /** Main properties dataobject */
109
    /** Main properties dataobject */
110
    @Deprecated
108
    PropertiesDataObject propDataObject;
111
    PropertiesDataObject propDataObject;
109
    
112
113
114
    private List<PropertiesDataObject> dataObjectList;
115
116
    private BundleStructure bundleStructure;
110
    /** Listener for modificationc on dataobject, adding and removing save cookie */
117
    /** Listener for modificationc on dataobject, adding and removing save cookie */
111
    PropertyChangeListener modifL;
118
    PropertyChangeListener modifL;
112
119
Lines 118-133 Link Here
118
    
125
    
119
126
120
    /** Constructor */
127
    /** Constructor */
128
    @Deprecated
121
    public PropertiesOpen(PropertiesDataObject propDataObject) {
129
    public PropertiesOpen(PropertiesDataObject propDataObject) {
122
        super(new Environment(propDataObject));
130
        super(new Environment(propDataObject));
123
        
131
        
124
        this.propDataObject = propDataObject;
132
        this.propDataObject = propDataObject;
125
        
133
126
        this.propDataObject.addPropertyChangeListener(WeakListeners.propertyChange(modifL = 
134
        //PENDING Add Listeners for all DataObject from this OpenSupport
135
        this.propDataObject.addPropertyChangeListener(WeakListeners.propertyChange(modifL =
127
            new ModifiedListener(), this.propDataObject));
136
            new ModifiedListener(), this.propDataObject));
128
    }
137
    }
129
138
139
    public PropertiesOpen(BundleStructure structure) {
140
        super(new Environment(structure));
130
141
142
        this.bundleStructure = structure;
143
        addModifiedListeners();
144
    }
145
146
    private void addModifiedListeners() {
147
        BundleStructure structure = bundleStructure;
148
        dataObjectList = new ArrayList<PropertiesDataObject>();
149
        PropertiesDataObject dataObject;
150
        modifL = new ModifiedListener();
151
        for (int i=0;i<structure.getEntryCount();i++) {
152
            dataObject = (PropertiesDataObject) structure.getNthEntry(i).getDataObject();
153
            dataObject.addPropertyChangeListener(WeakListeners.propertyChange(modifL, dataObject));
154
            dataObjectList.add(dataObject);
155
        }
156
    }
157
158
    protected void addDataObject(PropertiesDataObject dataObject) {
159
        dataObject.removePropertyChangeListener(WeakListeners.propertyChange(modifL, dataObject));
160
        dataObject.addPropertyChangeListener(WeakListeners.propertyChange(modifL, dataObject));
161
        env = new Environment(bundleStructure);
162
        PropertiesCloneableTopComponent topComp = (PropertiesCloneableTopComponent) allEditors.getArbitraryComponent();
163
        if (topComp != null) {
164
            topComp.dataObjectAdded(dataObject);
165
        }
166
        dataObjectList.add(dataObject);
167
}
131
    /** 
168
    /** 
132
     * Tests whether all data is saved, and if not, prompts the user to save.
169
     * Tests whether all data is saved, and if not, prompts the user to save.
133
     *
170
     *
Lines 135-142 Link Here
135
     */
172
     */
136
    @Override
173
    @Override
137
    protected boolean canClose() {
174
    protected boolean canClose() {
138
        SaveCookie saveCookie = propDataObject.getCookie(SaveCookie.class);
175
        PropertiesDataObject dataObject;
139
        if (saveCookie == null) {
176
        SaveCookie saveCookie = null;
177
        HashMap<SaveCookie,PropertiesDataObject> map = new HashMap<SaveCookie,PropertiesDataObject>();
178
        for (int i=0;i<bundleStructure.getEntryCount();i++) {
179
            dataObject = (PropertiesDataObject) bundleStructure.getNthEntry(i).getDataObject();
180
            saveCookie = dataObject.getCookie(SaveCookie.class);
181
            //Need to find all saveCookie
182
            if (saveCookie != null) map.put(saveCookie, dataObject);
183
        }
184
        if (map.isEmpty()) {
140
            return true;
185
            return true;
141
        }
186
        }
142
        stopEditing();
187
        stopEditing();
Lines 149-155 Link Here
149
                                           "CTL_Question");         //NOI18N
194
                                           "CTL_Question");         //NOI18N
150
        String question = NbBundle.getMessage(PropertiesOpen.class,
195
        String question = NbBundle.getMessage(PropertiesOpen.class,
151
                                              "MSG_SaveFile",       //NOI18N
196
                                              "MSG_SaveFile",       //NOI18N
152
                                              propDataObject.getName());
197
                                              bundleStructure.getNthEntry(0).getName());
153
        String optionSave = NbBundle.getMessage(PropertiesOpen.class,
198
        String optionSave = NbBundle.getMessage(PropertiesOpen.class,
154
                                                "CTL_Save");        //NOI18N
199
                                                "CTL_Save");        //NOI18N
155
        String optionDiscard = NbBundle.getMessage(PropertiesOpen.class,
200
        String optionDiscard = NbBundle.getMessage(PropertiesOpen.class,
Lines 171-185 Link Here
171
        /* Save the file if the answer was "Save": */
216
        /* Save the file if the answer was "Save": */
172
        if (answer == optionSave) {
217
        if (answer == optionSave) {
173
            try {
218
            try {
174
                saveCookie.save();
219
                for (SaveCookie save : map.keySet()) {
175
                propDataObject.updateModificationStatus();
220
                    save.save();
221
                    map.get(save).updateModificationStatus();
222
                }
176
            }
223
            }
177
            catch (IOException e) {
224
            catch (IOException e) {
178
                ErrorManager.getDefault().notify(e);
225
                ErrorManager.getDefault().notify(e);
179
                return false;
226
                return false;
180
            }
227
            }
181
        }
228
        }
182
        propDataObject.updateModificationStatus();
229
        dataObject = null;
230
        for (int i=0;i<bundleStructure.getEntryCount();i++) {
231
            dataObject = (PropertiesDataObject) bundleStructure.getNthEntry(i).getDataObject();
232
            dataObject.updateModificationStatus();
233
        }
183
234
184
        return (answer == optionSave || answer == optionDiscard);
235
        return (answer == optionSave || answer == optionDiscard);
185
    }
236
    }
Lines 215-221 Link Here
215
     * @return the cloneable top component for this support
266
     * @return the cloneable top component for this support
216
     */
267
     */
217
    protected CloneableTopComponent createCloneableTopComponent() {
268
    protected CloneableTopComponent createCloneableTopComponent() {
218
        return new PropertiesCloneableTopComponent(propDataObject);
269
//        return new PropertiesCloneableTopComponent(propDataObject);
270
        return new PropertiesCloneableTopComponent(bundleStructure);
219
    }
271
    }
220
272
221
    /**
273
    /**
Lines 225-232 Link Here
225
     */
277
     */
226
    protected String messageOpening() {
278
    protected String messageOpening() {
227
        return NbBundle.getMessage(PropertiesOpen.class, "LBL_ObjectOpen", // NOI18N
279
        return NbBundle.getMessage(PropertiesOpen.class, "LBL_ObjectOpen", // NOI18N
228
            propDataObject.getName(),
280
            bundleStructure.getNthEntry(0).getName(),
229
            propDataObject.getPrimaryFile().toString()
281
            bundleStructure.getNthEntry(0).getFile().toString()
230
        );
282
        );
231
    }
283
    }
232
284
Lines 249-263 Link Here
249
        if (undoRedoManager != null) {
301
        if (undoRedoManager != null) {
250
            return undoRedoManager;
302
            return undoRedoManager;
251
        } else {
303
        } else {
252
            return new CompoundUndoRedoManager(propDataObject);
304
            return new CompoundUndoRedoManager(bundleStructure);
253
        }
305
        }
254
    }
306
    }
255
307
256
    /** Helper method. Closes documents. */
308
    /** Helper method. Closes documents. */
257
    private synchronized void closeDocuments() {
309
    private synchronized void closeDocuments() {
258
        closeEntry((PropertiesFileEntry)propDataObject.getPrimaryEntry());
310
        BundleStructure structure = bundleStructure;
259
        for (Iterator it = propDataObject.secondaryEntries().iterator(); it.hasNext(); ) {
311
        for (int i = 0; i< structure.getEntryCount(); i++) {
260
            closeEntry((PropertiesFileEntry)it.next());
312
            closeEntry(structure.getNthEntry(i));
261
        }
313
        }
262
    }
314
    }
263
315
Lines 278-284 Link Here
278
        }
330
        }
279
    }
331
    }
280
332
281
    /** 
333
    /**
282
     * Helper method. Should be called only if the object has SaveCookie
334
     * Helper method. Should be called only if the object has SaveCookie
283
     * @return true if closing this editor whithout saving would result in loss of data
335
     * @return true if closing this editor whithout saving would result in loss of data
284
     *  because al least one of the modified files is not open in the code editor
336
     *  because al least one of the modified files is not open in the code editor
Lines 286-300 Link Here
286
    private boolean shouldAskSave() {
338
    private boolean shouldAskSave() {
287
        // for each entry : if there is a SaveCookie and no open editor component, return true.
339
        // for each entry : if there is a SaveCookie and no open editor component, return true.
288
        // if passed for all entries, return false
340
        // if passed for all entries, return false
289
        PropertiesFileEntry entry = (PropertiesFileEntry)propDataObject.getPrimaryEntry();
341
        BundleStructure structure = bundleStructure;
290
        SaveCookie savec = entry.getCookie(SaveCookie.class);
342
        PropertiesFileEntry entry;
291
        
343
        SaveCookie savec;
292
        if ((savec != null) && !entry.getPropertiesEditor().hasOpenedEditorComponent()) {
344
        for (int i = 0; i < structure.getEntryCount(); i++) {
293
            return true;
345
            entry = structure.getNthEntry(i);
294
        }
295
296
        for (Iterator it = propDataObject.secondaryEntries().iterator(); it.hasNext(); ) {
297
            entry = (PropertiesFileEntry)it.next();
298
            savec = entry.getCookie(SaveCookie.class);
346
            savec = entry.getCookie(SaveCookie.class);
299
            if ((savec != null) && !entry.getPropertiesEditor().hasOpenedEditorComponent()) {
347
            if ((savec != null) && !entry.getPropertiesEditor().hasOpenedEditorComponent()) {
300
                return true;
348
                return true;
Lines 303-309 Link Here
303
        return false;
351
        return false;
304
    }
352
    }
305
353
306
    
354
307
    /** Environment that connects the open support together with {@code DataObject}. */
355
    /** Environment that connects the open support together with {@code DataObject}. */
308
    private static class Environment implements CloneableOpenSupport.Env, Serializable,
356
    private static class Environment implements CloneableOpenSupport.Env, Serializable,
309
        PropertyChangeListener, VetoableChangeListener {
357
        PropertyChangeListener, VetoableChangeListener {
Lines 312-318 Link Here
312
        static final long serialVersionUID = -1934890789745432531L;
360
        static final long serialVersionUID = -1934890789745432531L;
313
        
361
        
314
        /** Object to serialize and be connected to. */
362
        /** Object to serialize and be connected to. */
363
        @Deprecated
315
        private DataObject dataObject;
364
        private DataObject dataObject;
365
366
        private BundleStructure bundleStructure;
316
        
367
        
317
        /** Support for firing of property changes. */
368
        /** Support for firing of property changes. */
318
        private transient PropertyChangeSupport propSupp;
369
        private transient PropertyChangeSupport propSupp;
Lines 327-339 Link Here
327
         * are also rethrown to own listeners.
378
         * are also rethrown to own listeners.
328
         * @param dataObject data object to be attached to
379
         * @param dataObject data object to be attached to
329
         */
380
         */
381
        @Deprecated
330
        public Environment(PropertiesDataObject dataObject) {
382
        public Environment(PropertiesDataObject dataObject) {
331
            this.dataObject = dataObject;
383
            this.dataObject = dataObject;
332
            dataObject.addPropertyChangeListener(WeakListeners.propertyChange(this, dataObject));
384
            dataObject.addPropertyChangeListener(WeakListeners.propertyChange(this, dataObject));
333
            dataObject.addVetoableChangeListener(WeakListeners.vetoableChange(this, dataObject));
385
            dataObject.addVetoableChangeListener(WeakListeners.vetoableChange(this, dataObject));
334
        }
386
        }
335
387
336
        
388
        public Environment(BundleStructure structure) {
389
            this.bundleStructure = structure;
390
            dataObject = bundleStructure.getNthEntry(0).getDataObject();
391
            addListeners();
392
        }
393
394
395
        private void addListeners() {
396
            BundleStructure structure = bundleStructure;
397
            PropertiesDataObject dataObj;
398
            for(int i=0;i<structure.getEntryCount();i++) {
399
                dataObj = (PropertiesDataObject) structure.getNthEntry(i).getDataObject();
400
                dataObj.addPropertyChangeListener(WeakListeners.propertyChange(this, dataObj));
401
                dataObj.addVetoableChangeListener(WeakListeners.vetoableChange(this, dataObj));
402
            }
403
404
        }
337
        /** Implements {@code CloneableOpenSupport.Env} interface. Adds property listener. */
405
        /** Implements {@code CloneableOpenSupport.Env} interface. Adds property listener. */
338
        public void addPropertyChangeListener(PropertyChangeListener l) {
406
        public void addPropertyChangeListener(PropertyChangeListener l) {
339
            prop().addPropertyChangeListener(l);
407
            prop().addPropertyChangeListener(l);
Lines 354-370 Link Here
354
            veto().removeVetoableChangeListener(l);
422
            veto().removeVetoableChangeListener(l);
355
        }
423
        }
356
424
357
        /** 
425
        /**
358
         * Implements {@code CloneableOpenSupport} interface.
426
         * Implements {@code CloneableOpenSupport} interface.
359
         * Method that allows environment to find its cloneable open support.
427
         * Method that allows environment to find its cloneable open support.
360
         * @return the support or null if the environemnt is not in valid 
428
         * @return the support or null if the environemnt is not in valid 
361
         * state and the CloneableOpenSupport cannot be found for associated
429
         * state and the CloneableOpenSupport cannot be found for associated
362
         * data object
430
         * data object
363
         */
431
         */
432
        @Deprecated
433
        //TODO PENDING Called from super class need to preserve
364
        public CloneableOpenSupport findCloneableOpenSupport() {
434
        public CloneableOpenSupport findCloneableOpenSupport() {
435
            return (CloneableOpenSupport) dataObject.getCookie(OpenCookie.class);
436
        }
437
438
        public CloneableOpenSupport findCloneableOpenSupport(PropertiesDataObject dataObject) {
365
            return (CloneableOpenSupport)dataObject.getCookie(OpenCookie.class);
439
            return (CloneableOpenSupport)dataObject.getCookie(OpenCookie.class);
366
        }
440
        }
367
        
441
368
        /** 
442
        /** 
369
         * Implements {@code CloneableOpenSupport.Env} interface.
443
         * Implements {@code CloneableOpenSupport.Env} interface.
370
         * Test whether the support is in valid state or not.
444
         * Test whether the support is in valid state or not.
Lines 372-380 Link Here
372
         * referenced to does not exist anymore.
446
         * referenced to does not exist anymore.
373
         * @return true or false depending on its state
447
         * @return true or false depending on its state
374
         */
448
         */
449
        @Deprecated
375
        public boolean isValid() {
450
        public boolean isValid() {
376
            return dataObject.isValid();
451
            return dataObject.isValid();
377
        }
452
        }
453
454
        public boolean isValid(PropertiesDataObject dataObject) {
455
            return dataObject.isValid();
456
        }
457
378
        
458
        
379
        /**
459
        /**
380
         * Implements {@code CloneableOpenSupport.Env} interface. 
460
         * Implements {@code CloneableOpenSupport.Env} interface. 
Lines 382-387 Link Here
382
         * @return true if the object is modified
462
         * @return true if the object is modified
383
         */
463
         */
384
        public boolean isModified() {
464
        public boolean isModified() {
465
            //if one dataObject is modified assume that everything modified
466
            for (int i=0; i < bundleStructure.getEntryCount();i++) {
467
                if (bundleStructure.getNthEntry(i).getDataObject().isModified()) {
468
                    return true;
469
                }
470
            }
471
            return false;
472
        }
473
474
        public boolean isModified(PropertiesDataObject dataObject) {
385
            return dataObject.isModified();
475
            return dataObject.isModified();
386
        }
476
        }
387
477
Lines 392-406 Link Here
392
         *   (for example when the file is readonly), when such exception
482
         *   (for example when the file is readonly), when such exception
393
         *   is the support should discard all previous changes
483
         *   is the support should discard all previous changes
394
         */
484
         */
485
        @Deprecated
395
        public void markModified() throws java.io.IOException {
486
        public void markModified() throws java.io.IOException {
396
            dataObject.setModified(true);
487
            dataObject.setModified(true);
397
        }
488
        }
398
        
489
490
        public void markModified(PropertiesDataObject dataObject) throws java.io.IOException {
491
            dataObject.setModified(true);
492
        }
399
        /** 
493
        /** 
400
         * Implements {@code CloneableOpenSupport.Env} interface.
494
         * Implements {@code CloneableOpenSupport.Env} interface.
401
         * Reverse method that can be called to make the environment unmodified.
495
         * Reverse method that can be called to make the environment unmodified.
402
         */
496
         */
497
        @Deprecated
403
        public void unmarkModified() {
498
        public void unmarkModified() {
499
            dataObject.setModified(false);
500
        }
501
502
        public void unmarkModified(PropertiesDataObject dataObject) {
404
            dataObject.setModified(false);
503
            dataObject.setModified(false);
405
        }
504
        }
406
        
505
        
Lines 410-419 Link Here
410
         */
509
         */
411
        public void propertyChange(PropertyChangeEvent evt) {
510
        public void propertyChange(PropertyChangeEvent evt) {
412
            if(DataObject.PROP_MODIFIED.equals(evt.getPropertyName())) {
511
            if(DataObject.PROP_MODIFIED.equals(evt.getPropertyName())) {
413
                if(dataObject.isModified()) {
512
                PropertiesDataObject dataObj = null;
414
                    dataObject.addVetoableChangeListener(this);
513
                if (evt.getSource() instanceof PropertiesDataObject) {
415
                } else {
514
                    dataObj = (PropertiesDataObject) evt.getSource();
416
                    dataObject.removeVetoableChangeListener(this);
515
                }
516
                if (dataObj!=null) {
517
                    if(dataObj.isModified()) {
518
                        dataObj.addVetoableChangeListener(this);
519
                    } else {
520
                        dataObj.removeVetoableChangeListener(this);
521
                    }
417
                }
522
                }
418
            } else if(DataObject.PROP_VALID.equals(evt.getPropertyName ())) { 
523
            } else if(DataObject.PROP_VALID.equals(evt.getPropertyName ())) { 
419
                // We will handle the object invalidation here.
524
                // We will handle the object invalidation here.
Lines 422-436 Link Here
422
                    return;
527
                    return;
423
                }
528
                }
424
529
530
                PropertiesDataObject dataObj = null;
531
                if (evt.getSource() instanceof PropertiesDataObject) {
532
                    dataObj = (PropertiesDataObject) evt.getSource();
533
                }
534
                if (dataObj != null) {
535
                    bundleStructure.updateEntries();
536
                    bundleStructure.notifyOneFileChanged(dataObj.getPrimaryFile());
537
                    if (bundleStructure.getEntryCount() == 0) {
425
                // Loosing validity.
538
                // Loosing validity.
426
                PropertiesOpen support = (PropertiesOpen)findCloneableOpenSupport();
539
//                PropertiesOpen support = (PropertiesOpen)findCloneableOpenSupport();
427
                if(support != null) {
540
                        PropertiesOpen support = (PropertiesOpen)findCloneableOpenSupport(dataObj);
541
                        if(support != null ) {
428
                    
542
                    
429
                    // Mark the object as not being modified, so nobody
543
                            // Mark the object as not being modified, so nobody
430
                    // will ask for save.
544
                            // will ask for save.
431
                    unmarkModified();
545
                            unmarkModified((PropertiesDataObject) evt.getSource());
432
                    
546
                    
433
                    support.close(false);
547
                            support.close(false);
548
                        }
549
                    }
434
                }
550
                }
435
            } else {
551
            } else {
436
                firePropertyChange (
552
                firePropertyChange (
Lines 496-515 Link Here
496
    /** Inner class. Listens to modifications and updates save cookie. */
612
    /** Inner class. Listens to modifications and updates save cookie. */
497
    private final class ModifiedListener implements SaveCookie, PropertyChangeListener {
613
    private final class ModifiedListener implements SaveCookie, PropertyChangeListener {
498
614
615
499
        /** Gives notification that the DataObject was changed.
616
        /** Gives notification that the DataObject was changed.
500
        * @param ev PropertyChangeEvent
617
        * @param ev PropertyChangeEvent
501
        */
618
        */
502
        public void propertyChange(PropertyChangeEvent evt) {
619
        public void propertyChange(PropertyChangeEvent evt) {
503
            // Data object changed, reset the UndoRedo manager.
620
            // Data object changed, reset the UndoRedo manager.
504
            if (evt.getSource().equals(propDataObject)) {
621
            if (DataObject.PROP_MODIFIED.equals(evt.getPropertyName())) {
505
                ((CompoundUndoRedoManager) PropertiesOpen.this.getUndoRedo()).reset(propDataObject);
622
                if (evt.getSource() instanceof  PropertiesDataObject) {
506
            }
623
                    PropertiesDataObject dataObject = (PropertiesDataObject) evt.getSource();
507
624
                    if(bundleStructure.getEntryByFileName(dataObject.getName())!=null) {
508
            if ((evt.getSource() == propDataObject) && (DataObject.PROP_MODIFIED.equals(evt.getPropertyName()))) {
625
                        ((CompoundUndoRedoManager) PropertiesOpen.this.getUndoRedo()).reset(bundleStructure);
509
                if (((Boolean)evt.getNewValue()).booleanValue()) {
626
                            if (((Boolean)evt.getNewValue()).booleanValue()) {
510
                    addSaveCookie();
627
                                addSaveCookie(dataObject);
511
                } else {
628
                            } else {
512
                    removeSaveCookie();
629
                                removeSaveCookie(dataObject);
630
                            }
631
                     }
513
                }
632
                }
514
            }
633
            }
515
        }
634
        }
Lines 538-551 Link Here
538
        * @exception IOException on I/O error
657
        * @exception IOException on I/O error
539
        */
658
        */
540
        public void saveDocument() throws IOException {
659
        public void saveDocument() throws IOException {
541
            PropertiesFileEntry pfe = (PropertiesFileEntry)propDataObject.getPrimaryEntry();
660
            BundleStructure structure = bundleStructure;
542
            SaveCookie save = pfe.getCookie(SaveCookie.class);
661
            SaveCookie save;
543
            if (save != null) {
662
            for (int i=0; i<structure.getEntryCount();i++) {
544
                save.save();
663
                save = structure.getNthEntry(i).getCookie(SaveCookie.class);
545
            }
546
547
            for (Iterator it = propDataObject.secondaryEntries().iterator(); it.hasNext();) {
548
                save = ((PropertiesFileEntry) it.next()).getCookie(SaveCookie.class);
549
                if (save != null) {
664
                if (save != null) {
550
                    save.save();
665
                    save.save();
551
                }
666
                }
Lines 553-566 Link Here
553
        }
668
        }
554
669
555
        /** Adds save cookie to the dataobject. */
670
        /** Adds save cookie to the dataobject. */
671
        @Deprecated
556
        private void addSaveCookie() {
672
        private void addSaveCookie() {
673
            if(propDataObject.getCookie(SaveCookie.class) == null) {
674
                propDataObject.getCookieSet0().add(this);
675
            }
676
        }
677
678
        private void addSaveCookie(PropertiesDataObject propDataObject) {
557
            if(propDataObject.getCookie(SaveCookie.class) == null) {
679
            if(propDataObject.getCookie(SaveCookie.class) == null) {
558
                propDataObject.getCookieSet0().add(this);
680
                propDataObject.getCookieSet0().add(this);
559
            }
681
            }
560
        }
682
        }
561
        
683
        
562
        /** Removes save cookie from the dataobject. */
684
        /** Removes save cookie from the dataobject. */
685
        @Deprecated
563
        private void removeSaveCookie() {
686
        private void removeSaveCookie() {
687
            if(propDataObject.getCookie(SaveCookie.class) == this) {
688
                propDataObject.getCookieSet0().remove(this);
689
            }
690
        }
691
692
        private void removeSaveCookie(PropertiesDataObject propDataObject) {
564
            if(propDataObject.getCookie(SaveCookie.class) == this) {
693
            if(propDataObject.getCookie(SaveCookie.class) == this) {
565
                propDataObject.getCookieSet0().remove(this);
694
                propDataObject.getCookieSet0().remove(this);
566
            }
695
            }
Lines 597-603 Link Here
597
            final PropertiesCloneableTopComponent editor = (PropertiesCloneableTopComponent)PropertiesOpen.super.openCloneableTopComponent();
726
            final PropertiesCloneableTopComponent editor = (PropertiesCloneableTopComponent)PropertiesOpen.super.openCloneableTopComponent();
598
            editor.requestActive();
727
            editor.requestActive();
599
            
728
            
600
            BundleStructure bs = propDataObject.getBundleStructure();
729
            BundleStructure bs = bundleStructure;
730
            bs.updateEntries();
601
            // Find indexes.
731
            // Find indexes.
602
            int entryIndex = bs.getEntryIndexByFileName(entry.getFile().getName());
732
            int entryIndex = bs.getEntryIndexByFileName(entry.getFile().getName());
603
            int rowIndex   = bs.getKeyIndexByName(key);
733
            int rowIndex   = bs.getKeyIndexByName(key);
Lines 618-625 Link Here
618
                        }
748
                        }
619
749
620
                        // Update selection & edit.
750
                        // Update selection & edit.
621
                        table.getColumnModel().getSelectionModel().setSelectionInterval(row, column);
751
//XXX This caused to open properties for editing with wrong values
622
                        table.getSelectionModel().setSelectionInterval(row, column);
752
//                        table.getColumnModel().getSelectionModel().setSelectionInterval(row, column);
753
//                        table.getSelectionModel().setSelectionInterval(row, column);
623
754
624
                        table.editCellAt(row, column);
755
                        table.editCellAt(row, column);
625
                    }
756
                    }
Lines 633-644 Link Here
633
    public static class PropertiesCloneableTopComponent extends CloneableTopComponent {
764
    public static class PropertiesCloneableTopComponent extends CloneableTopComponent {
634
765
635
        /** Reference to underlying {@code PropertiesDataObject}. */
766
        /** Reference to underlying {@code PropertiesDataObject}. */
767
        @Deprecated
636
        private PropertiesDataObject propDataObject;
768
        private PropertiesDataObject propDataObject;
637
        
769
770
        private PropertiesDataObject[] dataObjecs;
638
        /** Listener for changes on {@code propDataObject} name and cookie properties.
771
        /** Listener for changes on {@code propDataObject} name and cookie properties.
639
         * Changes display name of components accordingly. */
772
         * Changes display name of components accordingly. */
640
        private transient PropertyChangeListener dataObjectListener;
773
        private transient PropertyChangeListener dataObjectListener;
641
        
774
775
        private transient static HashMap<PropertiesDataObject,PropertyChangeListener> weakListeners;
776
642
        /** Generated serial version UID. */
777
        /** Generated serial version UID. */
643
        static final long serialVersionUID =2836248291419024296L;
778
        static final long serialVersionUID =2836248291419024296L;
644
        
779
        
Lines 649-660 Link Here
649
        
784
        
650
        /** Constructor.
785
        /** Constructor.
651
        * @param propDataObject data object we belong to */
786
        * @param propDataObject data object we belong to */
787
        @Deprecated
652
        public PropertiesCloneableTopComponent (PropertiesDataObject propDataObject) {
788
        public PropertiesCloneableTopComponent (PropertiesDataObject propDataObject) {
653
            this.propDataObject  = propDataObject;
789
            this.propDataObject  = propDataObject;
654
790
655
            initialize();
791
            initialize();
656
        }
792
        }
657
793
794
        private MultiBundleStructure bundleStructure;
795
796
        public PropertiesCloneableTopComponent(BundleStructure structure) {
797
            this.bundleStructure = (MultiBundleStructure) structure;
798
            propDataObject = (PropertiesDataObject) bundleStructure.getNthEntry(0).getDataObject();
799
            dataObjecs = new PropertiesDataObject[bundleStructure.getEntryCount()];
800
            for (int i=0; i<bundleStructure.getEntryCount();i++) {
801
                dataObjecs[i] = (PropertiesDataObject) bundleStructure.getNthEntry(i).getDataObject();
802
            }
803
            weakListeners = new HashMap<PropertiesDataObject, PropertyChangeListener>();
804
            initialize();
805
        }
658
        /**
806
        /**
659
         */
807
         */
660
        @Override
808
        @Override
Lines 681-694 Link Here
681
        private void initialize() {
829
        private void initialize() {
682
            initComponents();
830
            initComponents();
683
            setupActions();
831
            setupActions();
684
            setActivatedNodes(new Node[] {propDataObject.getNodeDelegate()});
832
            BundleStructure structure = bundleStructure;
833
            PropertiesDataObject dataObject;
685
834
835
            Node[] node = new Node[structure.getEntryCount()];
686
            dataObjectListener = new NameUpdater();
836
            dataObjectListener = new NameUpdater();
687
            propDataObject.addPropertyChangeListener(
837
688
                    WeakListeners.propertyChange(dataObjectListener,
838
            for( int i=0; i<structure.getEntryCount();i++) {
689
                                                 propDataObject));
839
                    dataObject = dataObjecs[i];//(PropertiesDataObject) structure.getNthEntry(i).getDataObject();
840
                    node[i] = dataObject.getNodeDelegate();
841
                    weakListeners.put(dataObject,WeakListeners.propertyChange(dataObjectListener, dataObject));
842
                    dataObject.addPropertyChangeListener(weakListeners.get(dataObject));
843
            }
690
            
844
            
845
            setActivatedNodes(node);
846
691
            updateName();
847
            updateName();
848
        }
849
850
        /**
851
         * Called from PropertiesOpen when new DataObject added
852
         * @param dataObject to add listener to
853
         */
854
        protected void dataObjectAdded(PropertiesDataObject dataObject) {
855
            dataObject.removePropertyChangeListener(WeakListeners.propertyChange(dataObjectListener, dataObject));
856
            dataObject.addPropertyChangeListener(WeakListeners.propertyChange(dataObjectListener, dataObject));
692
        }
857
        }
693
        
858
        
694
        /* Based on class DataNode.PropL. */
859
        /* Based on class DataNode.PropL. */
Lines 710-716 Link Here
710
            
875
            
711
            /** */
876
            /** */
712
            private final int action;
877
            private final int action;
713
            
878
714
            /**
879
            /**
715
             */
880
             */
716
            NameUpdater() {
881
            NameUpdater() {
Lines 730-736 Link Here
730
                    previous.removeFileStatusListener(weakL);
895
                    previous.removeFileStatusListener(weakL);
731
                }
896
                }
732
                try {
897
                try {
733
                    previous = propDataObject.getPrimaryFile().getFileSystem();
898
                    previous = bundleStructure.getNthEntry(0).getFile().getFileSystem();
734
                    if (weakL == null) {
899
                    if (weakL == null) {
735
                        weakL = org.openide.filesystems.FileUtil
900
                        weakL = org.openide.filesystems.FileUtil
736
                                .weakFileStatusListener(this, previous);
901
                                .weakFileStatusListener(this, previous);
Lines 750-757 Link Here
750
                }
915
                }
751
                
916
                
752
                boolean thisChanged = false;
917
                boolean thisChanged = false;
753
                for (FileObject fo : propDataObject.files()) {
918
                for (int i=0;i<bundleStructure.getEntryCount();i++) {
754
                    if (ev.hasChanged(fo)) {
919
                    if(ev.hasChanged(bundleStructure.getNthEntry(i).getFile())) {
755
                        thisChanged = true;
920
                        thisChanged = true;
756
                        break;
921
                        break;
757
                    }
922
                    }
Lines 765-771 Link Here
765
            /**
930
            /**
766
             */
931
             */
767
            public void propertyChange(PropertyChangeEvent e) {
932
            public void propertyChange(PropertyChangeEvent e) {
768
                if (!propDataObject.isValid()) {
933
                //PENDING Add correct propDataObject
934
                if (bundleStructure.getEntryCount() == 0) {return;}
935
                if (!bundleStructure.getNthEntry(0).getDataObject().isValid()) {
769
                    return;
936
                    return;
770
                }
937
                }
771
                
938
                
Lines 819-825 Link Here
819
        private void updateName() {
986
        private void updateName() {
820
            assert EventQueue.isDispatchThread();
987
            assert EventQueue.isDispatchThread();
821
            
988
            
822
            final String name = propDataObject.getName();
989
            final String name = bundleStructure.getNthEntry(0).getName();
823
            final String displayName = displayName();
990
            final String displayName = displayName();
824
            final String htmlDisplayName = htmlDisplayName();
991
            final String htmlDisplayName = htmlDisplayName();
825
            final String toolTip = messageToolTip();
992
            final String toolTip = messageToolTip();
Lines 853-860 Link Here
853
        /**
1020
        /**
854
         */
1021
         */
855
        private String addModifiedInfo(String name) {
1022
        private String addModifiedInfo(String name) {
856
            boolean modified
1023
            boolean modified = false;
857
                    = propDataObject.getCookie(SaveCookie.class) != null;
1024
            for (int i=0;i<bundleStructure.getEntryCount();i++) {
1025
                if(bundleStructure.getNthEntry(i).getDataObject().getCookie(SaveCookie.class) != null) {
1026
                    modified = true;
1027
                    break;
1028
                }
1029
            }
858
            int version = modified ? 1 : 3;
1030
            int version = modified ? 1 : 3;
859
            return NbBundle.getMessage(PropertiesCloneableTopComponent.class,
1031
            return NbBundle.getMessage(PropertiesCloneableTopComponent.class,
860
                                       "LBL_EditorName",                //NOI18N
1032
                                       "LBL_EditorName",                //NOI18N
Lines 869-875 Link Here
869
         * @see  #htmlDisplayName
1041
         * @see  #htmlDisplayName
870
         */
1042
         */
871
        private String displayName() {
1043
        private String displayName() {
872
            String nameBase = propDataObject.getNodeDelegate().getDisplayName();
1044
            String nameBase = bundleStructure.getNthEntry(0).getDataObject().getNodeDelegate().getDisplayName();
873
            return addModifiedInfo(nameBase);
1045
            return addModifiedInfo(nameBase);
874
        }
1046
        }
875
        
1047
        
Lines 880-886 Link Here
880
         * @see  #displayName()
1052
         * @see  #displayName()
881
         */
1053
         */
882
        private String htmlDisplayName() {
1054
        private String htmlDisplayName() {
883
            final Node node = propDataObject.getNodeDelegate();
1055
            final Node node = bundleStructure.getNthEntry(0).getDataObject().getNodeDelegate();
884
            String displayName = node.getHtmlDisplayName();
1056
            String displayName = node.getHtmlDisplayName();
885
            if (displayName != null) {
1057
            if (displayName != null) {
886
                if (!displayName.startsWith("<html>")) {                //NOI18N
1058
                if (!displayName.startsWith("<html>")) {                //NOI18N
Lines 894-915 Link Here
894
        
1066
        
895
        /** Gets string for tooltip. */
1067
        /** Gets string for tooltip. */
896
        private String messageToolTip() {
1068
        private String messageToolTip() {
897
            FileObject fo = propDataObject.getPrimaryFile();
1069
            FileObject fo = bundleStructure.getNthEntry(0).getFile();
898
            return FileUtil.getFileDisplayName(fo);
1070
            return FileUtil.getFileDisplayName(fo);
899
        }
1071
        }
900
        
1072
        
901
        /** 
1073
        /**
1074
         * 
902
         * Overrides superclass method. When closing last view, also close the document.
1075
         * Overrides superclass method. When closing last view, also close the document.
903
         * @return {@code true} if close succeeded
1076
         * @return {@code true} if close succeeded
904
         */
1077
         */
905
        @Override
1078
        @Override
906
        protected boolean closeLast () {
1079
        protected boolean closeLast () {
907
            if (!propDataObject.getOpenSupport().canClose ()) {
1080
            if (!bundleStructure.getOpenSupport().canClose ()) {
908
                // if we cannot close the last window
1081
                // if we cannot close the last window
909
                return false;
1082
                return false;
910
            }
1083
            }
911
            propDataObject.getOpenSupport().closeDocuments();
1084
            bundleStructure.getOpenSupport().closeDocuments();
912
1085
            PropertyChangeListener l;
1086
            for (PropertiesDataObject dataObject:dataObjecs) {
1087
                l = weakListeners.get(dataObject);
1088
                if (l!=null) {
1089
                    dataObject.removePropertyChangeListener(l);
1090
                    weakListeners.remove(l);
1091
                }
1092
            }
913
            return true;
1093
            return true;
914
        }
1094
        }
915
1095
Lines 920-926 Link Here
920
         */
1100
         */
921
        @Override
1101
        @Override
922
        protected CloneableTopComponent createClonedObject () {
1102
        protected CloneableTopComponent createClonedObject () {
923
            return new PropertiesCloneableTopComponent(propDataObject);
1103
            return new PropertiesCloneableTopComponent(bundleStructure);
924
        }
1104
        }
925
1105
926
        /** Gets {@code Icon}. */
1106
        /** Gets {@code Icon}. */
Lines 950-956 Link Here
950
         */
1130
         */
951
        @Override
1131
        @Override
952
        public UndoRedo getUndoRedo () {
1132
        public UndoRedo getUndoRedo () {
953
            return propDataObject.getOpenSupport().getUndoRedo();
1133
            return  bundleStructure.getOpenSupport().getUndoRedo();
954
        }
1134
        }
955
1135
956
        /** Inits the subcomponents. Sets layout for this top component and adds {@code BundleEditPanel} to it. 
1136
        /** Inits the subcomponents. Sets layout for this top component and adds {@code BundleEditPanel} to it. 
Lines 964-970 Link Here
964
            c.weightx = 1.0;
1144
            c.weightx = 1.0;
965
            c.weighty = 1.0;
1145
            c.weighty = 1.0;
966
            c.gridwidth = GridBagConstraints.REMAINDER;
1146
            c.gridwidth = GridBagConstraints.REMAINDER;
967
            JPanel panel = new BundleEditPanel(propDataObject, new PropertiesTableModel(propDataObject.getBundleStructure()));
1147
            JPanel panel = new BundleEditPanel(bundleStructure, new PropertiesTableModel(bundleStructure));
968
            gridbag.setConstraints(panel, c);
1148
            gridbag.setConstraints(panel, c);
969
            add(panel);
1149
            add(panel);
970
        }
1150
        }
Lines 973-979 Link Here
973
         *  is not valid.
1153
         *  is not valid.
974
         */
1154
         */
975
        private boolean discard () {
1155
        private boolean discard () {
976
            return propDataObject == null;
1156
            return bundleStructure == null;
977
        }
1157
        }
978
        
1158
        
979
1159
Lines 985-991 Link Here
985
        @Override
1165
        @Override
986
        public void writeExternal (ObjectOutput out) throws IOException {
1166
        public void writeExternal (ObjectOutput out) throws IOException {
987
            super.writeExternal(out);
1167
            super.writeExternal(out);
988
            out.writeObject(propDataObject);
1168
            out.writeObject(bundleStructure.getNthEntry(0).getDataObject());
989
        }
1169
        }
990
1170
991
        /** 
1171
        /** 
Lines 998-1004 Link Here
998
            super.readExternal(in);
1178
            super.readExternal(in);
999
1179
1000
            propDataObject = (PropertiesDataObject)in.readObject();
1180
            propDataObject = (PropertiesDataObject)in.readObject();
1001
            
1181
            bundleStructure = (MultiBundleStructure) propDataObject.getBundleStructure();
1182
            dataObjecs = new PropertiesDataObject[bundleStructure.getEntryCount()];
1183
            for (int i=0;i<bundleStructure.getEntryCount();i++) {
1184
                dataObjecs[i] = (PropertiesDataObject) bundleStructure.getNthEntry(i).getDataObject();
1185
            }
1186
            weakListeners = new HashMap<PropertiesDataObject, PropertyChangeListener>();
1002
            initialize();
1187
            initialize();
1003
        }
1188
        }
1004
    } // End of nested class PropertiesCloneableTopComponent.
1189
    } // End of nested class PropertiesCloneableTopComponent.
Lines 1017-1038 Link Here
1017
        // Constructor
1202
        // Constructor
1018
        
1203
        
1019
        /** Collects all UndoRedo managers from all editor support of all entries. */
1204
        /** Collects all UndoRedo managers from all editor support of all entries. */
1205
        @Deprecated
1020
        public CompoundUndoRedoManager(PropertiesDataObject obj) {
1206
        public CompoundUndoRedoManager(PropertiesDataObject obj) {
1021
            init(obj);
1207
            init(obj);
1022
        }
1208
        }
1209
        public CompoundUndoRedoManager(BundleStructure structure) {
1210
            init(structure);
1211
        }
1023
1212
1024
        /** Initialize set of managers. */
1213
        /** Initialize set of managers. */
1214
        @Deprecated
1025
        private void init(PropertiesDataObject obj) {
1215
        private void init(PropertiesDataObject obj) {
1026
            managers.add( ((PropertiesFileEntry)obj.getPrimaryEntry()).getPropertiesEditor().getUndoRedoManager());
1216
            BundleStructure structure = obj.getBundleStructure();
1027
            for (Iterator it = obj.secondaryEntries().iterator(); it.hasNext(); ) {
1217
            for(int i=0; i< structure.getEntryCount(); i++) {
1028
                managers.add( ((PropertiesFileEntry)it.next()).getPropertiesEditor().getUndoRedoManager() );
1218
                managers.add(structure.getNthEntry(i).getPropertiesEditor().getUndoRedoManager());
1029
            } 
1219
            }
1220
        }
1221
1222
        private void init(BundleStructure structure) {
1223
            for(int i=0; i< structure.getEntryCount(); i++) {
1224
                managers.add(structure.getNthEntry(i).getPropertiesEditor().getUndoRedoManager());
1225
            }
1030
        }
1226
        }
1031
1227
1032
        /** Resets the managers. Used when data object has changed. */
1228
        /** Resets the managers. Used when data object has changed. */
1229
        @Deprecated
1033
        public synchronized void reset(PropertiesDataObject obj) {
1230
        public synchronized void reset(PropertiesDataObject obj) {
1034
            managers.clear();
1231
            managers.clear();
1035
            init(obj);
1232
            init(obj);
1233
        }
1234
1235
        public synchronized void reset(BundleStructure structure) {
1236
            managers.clear();
1237
            init(structure);
1036
        }
1238
        }
1037
1239
1038
        /** Gets manager which undo edit comes to play.*/
1240
        /** Gets manager which undo edit comes to play.*/
(-)a/properties/src/org/netbeans/modules/properties/PropertiesTableCellEditor.java (-1 / +1 lines)
Lines 160-166 Link Here
160
        public void setValue(Object x) {
160
        public void setValue(Object x) {
161
            // PENDING - due to a compiler error explicitly do "super" code instead of calling super
161
            // PENDING - due to a compiler error explicitly do "super" code instead of calling super
162
            this.value = x;
162
            this.value = x;
163
            //super.setValue(x);
163
//            super.setValue(x);
164
            PropertiesTableModel.StringPair sp = (PropertiesTableModel.StringPair)x;
164
            PropertiesTableModel.StringPair sp = (PropertiesTableModel.StringPair)x;
165
165
166
            // set values as they deserve
166
            // set values as they deserve
(-)a/properties/src/org/netbeans/modules/properties/PropertiesTableModel.java (-6 / +16 lines)
Lines 284-289 Link Here
284
        fireTableChanged(new TableModelEvent(this, 0, getRowCount() - 1, columnModelIndex));
284
        fireTableChanged(new TableModelEvent(this, 0, getRowCount() - 1, columnModelIndex));
285
    }
285
    }
286
286
287
    /**
288
     * Get FileEntry  according to column in Table View
289
     * @param column
290
     * @return
291
     */
292
    PropertiesFileEntry getFileEntry(int column) {
293
        return structure.getNthEntry(column-1);
294
    }
287
    /** Overrides superclass method. */
295
    /** Overrides superclass method. */
288
    @Override
296
    @Override
289
    public String toString() {
297
    public String toString() {
Lines 364-371 Link Here
364
                // Note: Normal way would be use the next commented out rows, which should do in effect
372
                // Note: Normal way would be use the next commented out rows, which should do in effect
365
                // the same thing like reseting the model, but it doesn't, therefore we reset the model directly.
373
                // the same thing like reseting the model, but it doesn't, therefore we reset the model directly.
366
                
374
                
367
                //cancelEditingInTables(getDefaultCancelSelector());
375
                cancelEditingInTables(getDefaultCancelSelector());
368
                //fireTableStructureChanged(); 
376
                fireTableStructureChanged(); 
369
377
370
                Object[] list = PropertiesTableModel.super.listenerList.getListenerList();
378
                Object[] list = PropertiesTableModel.super.listenerList.getListenerList();
371
                for(int i = 0; i < list.length; i++) {
379
                for(int i = 0; i < list.length; i++) {
Lines 396-404 Link Here
396
            } else if(changeType == PropertyBundleEvent.CHANGE_FILE) {
404
            } else if(changeType == PropertyBundleEvent.CHANGE_FILE) {
397
                // File changed.
405
                // File changed.
398
                final int index = structure.getEntryIndexByFileName(evt.getEntryName());
406
                final int index = structure.getEntryIndexByFileName(evt.getEntryName());
407
                //This mean file deleted
399
                if (index == -1) {
408
                if (index == -1) {
400
                    if (Boolean.getBoolean("netbeans.debug.exceptions")) // NOI18N
409
                    fireTableStructureChanged();
401
                        (new Exception("Changed file not found")).printStackTrace(); // NOI18N
410
//                    if (Boolean.getBoolean("netbeans.debug.exceptions")) // NOI18N
411
//                        (new Exception("Changed file not found")).printStackTrace(); // NOI18N
402
                    return;
412
                    return;
403
                }
413
                }
404
                
414
                
Lines 409-416 Link Here
409
                        return (column == index + 1);
419
                        return (column == index + 1);
410
                    }
420
                    }
411
                });
421
                });
412
                
422
//                fireTableColumnChanged(index + 1);
413
                fireTableColumnChanged(index + 1);
423
                  fireTableStructureChanged();
414
            } else if(changeType == PropertyBundleEvent.CHANGE_ITEM) {
424
            } else if(changeType == PropertyBundleEvent.CHANGE_ITEM) {
415
                // one item changed
425
                // one item changed
416
                final int index2 = structure.getEntryIndexByFileName(evt.getEntryName());
426
                final int index2 = structure.getEntryIndexByFileName(evt.getEntryName());
(-)a/properties/src/org/netbeans/modules/properties/Util.java (-8 / +142 lines)
Lines 45-50 Link Here
45
45
46
import java.io.IOException;
46
import java.io.IOException;
47
import java.text.MessageFormat;
47
import java.text.MessageFormat;
48
import java.util.Arrays;
49
import java.util.HashSet;
48
import java.util.Locale;
50
import java.util.Locale;
49
import org.openide.DialogDisplayer;
51
import org.openide.DialogDisplayer;
50
import org.openide.NotifyDescriptor;
52
import org.openide.NotifyDescriptor;
Lines 52-59 Link Here
52
import org.openide.filesystems.FileObject;
54
import org.openide.filesystems.FileObject;
53
import org.openide.filesystems.FileSystem;
55
import org.openide.filesystems.FileSystem;
54
import org.openide.filesystems.FileUtil;
56
import org.openide.filesystems.FileUtil;
57
import org.openide.filesystems.Repository;
55
import org.openide.loaders.DataFolder;
58
import org.openide.loaders.DataFolder;
56
import org.openide.loaders.DataObject;
59
import org.openide.loaders.DataObject;
60
import org.openide.loaders.DataObjectNotFoundException;
57
import org.openide.loaders.FileEntry;
61
import org.openide.loaders.FileEntry;
58
62
59
import org.openide.loaders.MultiDataObject;
63
import org.openide.loaders.MultiDataObject;
Lines 147-160 Link Here
147
     * @see  #getVariant
151
     * @see  #getVariant
148
     */
152
     */
149
    public static String getLocaleSuffix(MultiDataObject.Entry fe) {
153
    public static String getLocaleSuffix(MultiDataObject.Entry fe) {
150
        MultiDataObject.Entry pe = fe.getDataObject().getPrimaryEntry();
154
        FileObject fo = fe.getFile();
151
        if (fe == pe) {
155
        String fName = fo.getName();
152
            return "";                                                  //NOI18N
156
        int index = fName.indexOf(PRB_SEPARATOR_CHAR);
157
        FileObject po = fo;
158
        while (index != -1) {
159
            FileObject candidate = fo.getParent().getFileObject(
160
                    fName.substring(0, index), fo.getExt());
161
            if (candidate != null && isValidLocaleSuffix(fName.substring(index))) {
162
                po = candidate;
163
            }
164
            index = fName.indexOf(PRB_SEPARATOR_CHAR, index + 1);
153
        }
165
        }
154
        String myName   = fe.getFile().getName();
166
        if (fo == po) {
155
        String baseName = pe.getFile().getName();
167
            return "";
168
        }
169
        String myName   = fo.getName();
170
        String baseName = po.getName();
156
        assert myName.startsWith(baseName);
171
        assert myName.startsWith(baseName);
157
        return myName.substring(baseName.length());
172
        return myName.substring(baseName.length());
173
//        MultiDataObject.Entry pe = fe.getDataObject().getPrimaryEntry();
174
//        if (fe == pe) {
175
//            return "";                                                  //NOI18N
176
//        }
177
//        String myName   = fe.getFile().getName();
178
//        String baseName = pe.getFile().getName();
179
//        assert myName.startsWith(baseName);
180
//        return myName.substring(baseName.length());
181
    }
182
183
    private static boolean isValidLocaleSuffix(String s) {
184
        // first char is _
185
        int n = s.length();
186
        String s1;
187
        // check first suffix - language (two chars)
188
        if (n == 3 || (n > 3 && s.charAt(3) == PropertiesDataLoader.PRB_SEPARATOR_CHAR)) {
189
            s1 = s.substring(1, 3).toLowerCase();
190
            // language must be followed by a valid country suffix or no suffix
191
        } else {
192
            return false;
193
        }
194
        // check second suffix - country (two chars)
195
        String s2;
196
        if (n == 3) {
197
            s2 = null;
198
        } else if (n == 6 || (n > 6 && s.charAt(6) == PropertiesDataLoader.PRB_SEPARATOR_CHAR)) {
199
            s2 = s.substring(4, 6).toUpperCase();
200
            // country may be followed by whatever additional suffix
201
        } else {
202
            return false;
203
        }
204
205
        HashSet<String> knownLanguages = new HashSet<String>(Arrays.asList(Locale.getISOLanguages()));
206
        if (!knownLanguages.contains(s1)) {
207
            return false;
208
        }
209
210
        if (s2 != null) {
211
            HashSet<String> knownCountries = new HashSet<String>(Arrays.asList(Locale.getISOCountries()));
212
            if (!knownCountries.contains(s2)) {
213
                return false;
214
            }
215
        }
216
        return true;
158
    }
217
    }
159
218
160
    /**
219
    /**
Lines 384-395 Link Here
384
            folder = FileUtil.createFolder(folder, folderPath);
443
            folder = FileUtil.createFolder(folder, folderPath);
385
            fileName = fileName.substring(idx + 1);
444
            fileName = fileName.substring(idx + 1);
386
        }
445
        }
387
        FileObject templateFO = FileUtil.getConfigFile("Templates/Other/properties.properties"); // NOI18N
446
        FileSystem defaultFS = Repository.getDefault().getDefaultFileSystem();
447
        FileObject templateFO = defaultFS.findResource("Templates/Other/properties.properties"); // NOI18N
388
        DataObject template = DataObject.find(templateFO);
448
        DataObject template = DataObject.find(templateFO);
389
        return (PropertiesDataObject)
449
        return (PropertiesDataObject)
390
               template.createFromTemplate(DataFolder.findFolder(folder), fileName);
450
               template.createFromTemplate(DataFolder.findFolder(folder), fileName);
391
    }
451
    }
392
452
453
    /**
454
     * Create new DataObject with requested locale and notify that new locale was added
455
     * @param propertiesDataObject DataObject to add locale
456
     * @param locale
457
     * @param copyInitialContent
458
     */
393
    public static void createLocaleFile(PropertiesDataObject propertiesDataObject,
459
    public static void createLocaleFile(PropertiesDataObject propertiesDataObject,
394
                                        String locale,
460
                                        String locale,
395
                                        boolean copyInitialContent)
461
                                        boolean copyInitialContent)
Lines 402-409 Link Here
402
            }
468
            }
403
469
404
            if(propertiesDataObject != null) {
470
            if(propertiesDataObject != null) {
405
                FileObject file = propertiesDataObject.getPrimaryFile();
471
//                FileObject file = propertiesDataObject.getPrimaryFile();
406
                final String newName = file.getName() + PropertiesDataLoader.PRB_SEPARATOR_CHAR + locale;
472
                FileObject file = propertiesDataObject.getBundleStructure().getNthEntry(0).getFile();
473
                //Default locale may be deleted
474
                final String newName = getBaseName(file.getName()) + PropertiesDataLoader.PRB_SEPARATOR_CHAR + locale;
407
                final FileObject folder = file.getParent();
475
                final FileObject folder = file.getParent();
408
//                                    final PropertiesEditorSupport editor = (PropertiesEditorSupport)propertiesDataObject.getCookie(PropertiesEditorSupport.class);
476
//                                    final PropertiesEditorSupport editor = (PropertiesEditorSupport)propertiesDataObject.getCookie(PropertiesEditorSupport.class);
409
                java.util.Iterator it = propertiesDataObject.secondaryEntries().iterator();
477
                java.util.Iterator it = propertiesDataObject.secondaryEntries().iterator();
Lines 428-433 Link Here
428
                                templateFile.copy(folder, newName, PropertiesDataLoader.PROPERTIES_EXTENSION);
496
                                templateFile.copy(folder, newName, PropertiesDataLoader.PROPERTIES_EXTENSION);
429
                            }
497
                            }
430
                        });
498
                        });
499
                        //update entries in BundleStructure
500
                        propertiesDataObject.getBundleStructure().updateEntries();
501
                        //find just created DataObject
502
                        PropertiesDataObject dataObject = (PropertiesDataObject) DataObject.find(folder.getFileObject(newName, PropertiesDataLoader.PROPERTIES_EXTENSION));
503
                        //Add it to OpenSupport
504
                        propertiesDataObject.getOpenSupport().addDataObject(dataObject);
505
                        //Notify BundleStructure that one file changed
506
                        propertiesDataObject.getBundleStructure().notifyOneFileChanged(folder.getFileObject(newName, PropertiesDataLoader.PROPERTIES_EXTENSION));
507
//                        propertiesDataObject.getBundleStructure().notifyFileAdded(folder.getFileObject(newName, PropertiesDataLoader.PROPERTIES_EXTENSION));
431
                    }
508
                    }
432
                } else {
509
                } else {
433
                    // Create an empty file - creating from template via DataObject
510
                    // Create an empty file - creating from template via DataObject
Lines 443-446 Link Here
443
            notifyError(locale);
520
            notifyError(locale);
444
        }
521
        }
445
    }
522
    }
523
524
    /**
525
     *
526
     * @param obj DataObject
527
     * @return DataObject which represent default locale
528
     *          In case when default locale is absent it will return first found locale as primary,
529
     *          which has the same base name
530
     * @throws org.openide.loaders.DataObjectNotFoundException
531
     */
532
    static PropertiesDataObject findPrimaryDataObject(PropertiesDataObject obj) throws DataObjectNotFoundException {
533
        FileObject primary = obj.getPrimaryFile();
534
        assert primary != null : "Object " + obj + " cannot have null primary file"; // NOI18N
535
        String fName;
536
        fName = primary.getName();
537
        String baseName = getBaseName(fName);
538
        FileObject parent = primary.getParent();
539
        int index = fName.indexOf(PropertiesDataLoader.PRB_SEPARATOR_CHAR);
540
        while (index != -1) {
541
            FileObject candidate = parent.getFileObject(
542
                    fName.substring(0, index), primary.getExt());
543
            if (candidate != null && isValidLocaleSuffix(fName.substring(index))) {
544
                return (PropertiesDataObject) DataObject.find(candidate);
545
            } else if (candidate == null){
546
                for (FileObject file : parent.getChildren()) {
547
                    if (file.getName().indexOf(baseName) != -1) {
548
                        if (isValidLocaleSuffix(file.getName().substring(index))) {
549
                            return (PropertiesDataObject) DataObject.find(file);
550
                        }
551
                    }
552
                }
553
            }
554
            index = fName.indexOf(PropertiesDataLoader.PRB_SEPARATOR_CHAR, index + 1);
555
        }
556
        return obj;
557
    }
558
559
//    static BundleStructure findBundleStructure(PropertiesDataObject dataObject) {
560
//
561
//    }
562
563
    /**
564
     * @param name file name
565
     * @return Base name for this locale
566
     */
567
    static String getBaseName(String name) {
568
        String baseName = null;
569
        int index = name.indexOf(PropertiesDataLoader.PRB_SEPARATOR_CHAR);
570
        while (index != -1) {
571
            baseName = name.substring(0, index);
572
            if (baseName != null && isValidLocaleSuffix(name.substring(index))) {
573
                return baseName;
574
            }
575
            index = name.indexOf(PropertiesDataLoader.PRB_SEPARATOR_CHAR, index + 1);
576
        }
577
        return name;
578
    }
579
446
}
580
}

Return to bug 48263