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/src/org/netbeans/modules/properties/BundleEditPanel.form (-1 / +5 lines)
Lines 1-11 Link Here
1
<?xml version="1.0" encoding="UTF-8" ?>
1
<?xml version="1.0" encoding="UTF-8" ?>
2
2
3
<Form version="1.0" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
3
<Form version="1.2" maxVersion="1.2" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
4
  <Properties>
4
  <Properties>
5
    <Property name="focusCycleRoot" type="boolean" value="true"/>
5
    <Property name="focusCycleRoot" type="boolean" value="true"/>
6
  </Properties>
6
  </Properties>
7
  <AuxValues>
7
  <AuxValues>
8
    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
9
    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
10
    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
8
    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
11
    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
12
    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
9
    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
13
    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
10
    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
14
    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
11
    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
15
    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
(-)a/properties/src/org/netbeans/modules/properties/BundleEditPanel.java (-21 / +117 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 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
244
        table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
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
    } // End of constructor.
171
    
256
    
172
    /** Stops editing if editing is in run. */
257
    /** Stops editing if editing is in run. */
173
    protected void stopEditing() {
258
    protected void stopEditing() {
Lines 229-235 Link Here
229
                    if (ex == null) {
314
                    if (ex == null) {
230
                        return;
315
                        return;
231
                    } 
316
                    } 
232
                    String [] keys = obj.getBundleStructure().getKeys();
317
                    String [] keys = structure.getKeys();
233
                    int idx;
318
                    int idx;
234
                    for (idx = 0; idx < keys.length; idx++) {
319
                    for (idx = 0; idx < keys.length; idx++) {
235
                        String key = keys[idx];
320
                        String key = keys[idx];
Lines 248-254 Link Here
248
        }
333
        }
249
        
334
        
250
        lastSelectedColumn = column;
335
        lastSelectedColumn = column;
251
        BundleStructure structure = obj.getBundleStructure();
336
//        BundleStructure structure = obj.getBundleStructure();
252
        removeButton.setEnabled((row >= 0) && (!structure.isReadOnly()));
337
        removeButton.setEnabled((row >= 0) && (!structure.isReadOnly()));
253
        String value;
338
        String value;
254
        String comment;
339
        String comment;
Lines 281-294 Link Here
281
    }
366
    }
282
    
367
    
283
    private void updateAddButton() {
368
    private void updateAddButton() {
284
        addButton.setEnabled(!obj.getBundleStructure().isReadOnly());
369
        addButton.setEnabled(!structure.isReadOnly());
285
    }
370
    }
286
    
371
    
287
    /** Returns the main table with all values */
372
    /** Returns the main table with all values */
288
    public JTable getTable() {
373
    public JTable getTable() {
289
        return table;
374
        return table;
290
    }
375
    }
291
    
292
    
376
    
293
    /** Initializes <code>settings</code> variable. */
377
    /** Initializes <code>settings</code> variable. */
294
    private void initSettings() {
378
    private void initSettings() {
Lines 511-520 Link Here
511
        if (DialogDisplayer.getDefault().notify(msg).equals(NotifyDescriptor.OK_OPTION)) {
595
        if (DialogDisplayer.getDefault().notify(msg).equals(NotifyDescriptor.OK_OPTION)) {
512
            try {
596
            try {
513
                // Starts "atomic" acion for special undo redo manager of open support.
597
                // Starts "atomic" acion for special undo redo manager of open support.
514
                obj.getOpenSupport().atomicUndoRedoFlag = new Object();
598
//                TODO XXX
599
//                obj.getOpenSupport().atomicUndoRedoFlag = new Object();
515
                
600
                
516
                for (int i=0; i < obj.getBundleStructure().getEntryCount(); i++) {
601
                for (int i=0; i < structure.getEntryCount(); i++) {
517
                    PropertiesFileEntry entry = obj.getBundleStructure().getNthEntry(i);
602
                    PropertiesFileEntry entry = structure.getNthEntry(i);
518
                    if (entry != null) {
603
                    if (entry != null) {
519
                        PropertiesStructure ps = entry.getHandler().getStructure();
604
                        PropertiesStructure ps = entry.getHandler().getStructure();
520
                        if (ps != null) {
605
                        if (ps != null) {
Lines 524-530 Link Here
524
                }
609
                }
525
            } finally {
610
            } finally {
526
                // finishes "atomic" undo redo action for special undo redo manager of open support
611
                // finishes "atomic" undo redo action for special undo redo manager of open support
527
                obj.getOpenSupport().atomicUndoRedoFlag = null;
612
//                TODO XXX
613
//                obj.getOpenSupport().atomicUndoRedoFlag = null;
528
            }
614
            }
529
        }
615
        }
530
    }//GEN-LAST:event_removeButtonActionPerformed
616
    }//GEN-LAST:event_removeButtonActionPerformed
Lines 563-573 Link Here
563
            selectionUpdateDisabled = true;
649
            selectionUpdateDisabled = true;
564
650
565
            // Starts "atomic" acion for special undo redo manager of open support.
651
            // Starts "atomic" acion for special undo redo manager of open support.
566
            obj.getOpenSupport().atomicUndoRedoFlag = new Object();
652
//                TODO XXX
653
//            obj.getOpenSupport().atomicUndoRedoFlag = new Object();
567
            
654
            
568
            // add key to all entries
655
            // add key to all entries
569
            for (int i=0; i < obj.getBundleStructure().getEntryCount(); i++) {
656
            for (int i=0; i < structure.getEntryCount(); i++) {
570
                PropertiesFileEntry entry = obj.getBundleStructure().getNthEntry(i);
657
                PropertiesFileEntry entry = structure.getNthEntry(i);
571
                
658
                
572
                if (entry != null && !entry.getHandler().getStructure().addItem(key, value, comment)) {
659
                if (entry != null && !entry.getHandler().getStructure().addItem(key, value, comment)) {
573
                    NotifyDescriptor.Message msg = new NotifyDescriptor.Message(
660
                    NotifyDescriptor.Message msg = new NotifyDescriptor.Message(
Lines 586-592 Link Here
586
            }
673
            }
587
        } finally {
674
        } finally {
588
            // Finishes "atomic" undo redo action for special undo redo manager of open support.
675
            // Finishes "atomic" undo redo action for special undo redo manager of open support.
589
            obj.getOpenSupport().atomicUndoRedoFlag = null;
676
//                TODO XXX
677
//            obj.getOpenSupport().atomicUndoRedoFlag = null;
590
678
591
            selectionUpdateDisabled = false;
679
            selectionUpdateDisabled = false;
592
        }
680
        }
Lines 600-606 Link Here
600
            PropertiesRequestProcessor.getInstance().post(new Runnable() {
688
            PropertiesRequestProcessor.getInstance().post(new Runnable() {
601
                public void run() {
689
                public void run() {
602
                    // Find indexes.
690
                    // Find indexes.
603
                    int rowIndex = obj.getBundleStructure().getKeyIndexByName(key);
691
                    int rowIndex = structure.getKeyIndexByName(key);
604
                    
692
                    
605
                    if((rowIndex != -1)) {
693
                    if((rowIndex != -1)) {
606
                        final int row = rowIndex;
694
                        final int row = rowIndex;
Lines 669-681 Link Here
669
        private static final String SORT_ASC_ICON = ICON_PKG + "columnSortedAsc.gif";   //NOI18N
757
        private static final String SORT_ASC_ICON = ICON_PKG + "columnSortedAsc.gif";   //NOI18N
670
        private static final String SORT_DESC_ICON = ICON_PKG + "columnSortedDesc.gif"; //NOI18N
758
        private static final String SORT_DESC_ICON = ICON_PKG + "columnSortedDesc.gif"; //NOI18N
671
759
672
        private final PropertiesDataObject propDataObj;
760
        private final BundleStructure bundleStructure;
673
        private final TableCellRenderer origRenderer;
761
        private final TableCellRenderer origRenderer;
674
        private ImageIcon iconSortAsc, iconSortDesc;
762
        private ImageIcon iconSortAsc, iconSortDesc;
675
        
763
764
        @Deprecated
676
        TableViewHeaderRenderer(PropertiesDataObject propDataObj,
765
        TableViewHeaderRenderer(PropertiesDataObject propDataObj,
677
                                TableCellRenderer origRenderer) {
766
                                TableCellRenderer origRenderer) {
678
            this.propDataObj = propDataObj;
767
            bundleStructure = propDataObj.getBundleStructure();
768
            this.origRenderer = origRenderer;
769
        }
770
771
        TableViewHeaderRenderer(BundleStructure bundleStructure,
772
                                TableCellRenderer origRenderer) {
773
            this.bundleStructure = bundleStructure;
679
            this.origRenderer = origRenderer;
774
            this.origRenderer = origRenderer;
680
        }
775
        }
681
776
Lines 690-696 Link Here
690
785
691
            if (comp instanceof JLabel) {
786
            if (comp instanceof JLabel) {
692
                JLabel label = (JLabel) comp;
787
                JLabel label = (JLabel) comp;
693
                BundleStructure bundleStruct = propDataObj.getBundleStructure();
788
                BundleStructure bundleStruct = bundleStructure;
694
                int sortIndex = table.convertColumnIndexToView(
789
                int sortIndex = table.convertColumnIndexToView(
695
                                        bundleStruct.getSortIndex());
790
                                        bundleStruct.getSortIndex());
696
                if (column == sortIndex) {
791
                if (column == sortIndex) {
Lines 995-1001 Link Here
995
        }
1090
        }
996
        
1091
        
997
        private void documentModified() {
1092
        private void documentModified() {
998
            obj.setModified(true);
1093
            ((PropertiesTableModel)table.getModel()).getFileEntry(table.getEditingColumn()).getDataObject().setModified(true);
1094
//            obj.setModified(true);
999
        }
1095
        }
1000
        
1096
        
1001
    }
1097
    }
(-)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 (+292 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
     *
86
     * TODO XXX PENDING Check it out
87
     *
88
     */
89
    private void findEntries() {
90
        try {
91
            if (obj == null) return;
92
            if (!obj.isValid()) {
93
                if (files.length == 1) {
94
                    primaryEntry = null;
95
                    obj = null;
96
                    files = null;
97
                    return;
98
                }
99
            } else {
100
                obj = Util.findPrimaryDataObject(obj);
101
                primaryEntry = (PropertiesFileEntry) obj.getPrimaryEntry();
102
            }
103
            FileObject primary = primaryEntry.getFile();
104
            FileObject parent = primary.getParent();
105
            List<FileObject> listFileObjects = new ArrayList<FileObject>();
106
            String fName;
107
            FileObject oldCandidate;
108
            for (FileObject file : parent.getChildren()) {
109
                fName = file.getName();
110
                if (fName.equals(baseName) && file.isValid()) {
111
                    listFileObjects.add(0,file);
112
                }
113
                if (fName.indexOf(baseName) != -1) {
114
                    int index = fName.indexOf(PropertiesDataLoader.PRB_SEPARATOR_CHAR);
115
                    if (index == baseName.length()) {
116
                        oldCandidate = null;
117
                        while (index != -1) {
118
                            FileObject candidate = file;
119
                            if (candidate != null && isValidLocaleSuffix(fName.substring(index)) && oldCandidate == null && file.isValid()) {
120
                                listFileObjects.add(candidate);
121
                                oldCandidate = candidate;
122
                            }
123
                            index = fName.indexOf(PropertiesDataLoader.PRB_SEPARATOR_CHAR, index + 1);
124
                        }
125
                    }
126
                }
127
            }
128
            files = new FileObject[listFileObjects.size()];
129
            int index = 0;
130
            for (FileObject file : listFileObjects) {
131
                files[index++] = file;
132
            }
133
            primaryEntry = getNthEntry(0);
134
            obj = (PropertiesDataObject) primaryEntry.getDataObject();
135
        } catch (DataObjectNotFoundException ex) {
136
            Exceptions.printStackTrace(ex);
137
        }
138
    }
139
140
    void updateEntries() {
141
        findEntries();
142
        if (files != null) {
143
            buildKeySet();
144
        }
145
    }
146
147
    @Override
148
    public PropertiesFileEntry getNthEntry(int index) {
149
        if (files == null) {
150
            return super.getNthEntry(index);
151
//            notifyEntriesNotInitialized();
152
        }
153
        if (index >= 0 && index < files.length) {
154
            try {
155
                return (PropertiesFileEntry) ((PropertiesDataObject) DataObject.find(files[index])).getPrimaryEntry();
156
            } catch (DataObjectNotFoundException ex) {
157
                Exceptions.printStackTrace(ex);
158
                return null;
159
            }
160
        } else {
161
            return null;
162
        }
163
    }
164
165
    /**
166
     * Retrieves an index of a file entry representing the given file.
167
     *
168
     * @param  fileName  simple name (without path and extension) of the
169
     *                   primary or secondary file
170
     * @return  index of the entry representing a file with the given filename;
171
     *          or <code>-1</code> if no such entry is found
172
     * @exception  java.lang.IllegalStateException
173
     *             if the list of entries has not been initialized yet
174
     * @see  #getEntryByFileName
175
     */
176
    @Override
177
    public int getEntryIndexByFileName(String fileName) {
178
        if (files == null) {
179
            notifyEntriesNotInitialized();
180
        }
181
        for (int i = 0; i < getEntryCount(); i++) {
182
            if (files[i].getName().equals(fileName)) {
183
                return i;
184
            }
185
        }
186
        return -1;
187
    }
188
189
    /**
190
     * Retrieves a file entry representing the given file
191
     *
192
     * @param  fileName  simple name (excl. path, incl. extension) of the
193
     *                   primary or secondary file
194
     * @return  entry representing the given file;
195
     *          or <code>null</code> if not such entry is found
196
     * @exception  java.lang.IllegalStateException
197
     *             if the list of entries has not been initialized yet
198
     * @see  #getEntryIndexByFileName
199
     */
200
    @Override
201
    public PropertiesFileEntry getEntryByFileName(String fileName) {
202
        int index = getEntryIndexByFileName(fileName);
203
        try {
204
            return (index == -1) ? null : (PropertiesFileEntry) ((PropertiesDataObject) DataObject.find(files[index])).getPrimaryEntry();
205
        } catch (DataObjectNotFoundException ex) {
206
            Exceptions.printStackTrace(ex);
207
            return null;
208
        }
209
    }
210
211
    /**
212
     * Retrieves number of file entries.
213
     *
214
     * @return  number of file entries
215
     * @exception  java.lang.IllegalStateException
216
     *             if the list of entries has not been initialized yet
217
     */
218
    @Override
219
    public int getEntryCount() {
220
        if (files == null) {
221
            return 0;//super.getEntryCount();
222
//            notifyEntriesNotInitialized();
223
        }
224
        return files.length;
225
    }
226
227
    /**
228
     * Throws a runtime exception with a message that the entries
229
     * have not been initialized yet.
230
     *
231
     * @exception  java.lang.IllegalStateException  thrown always
232
     * @see  #updateEntries
233
     */
234
    private void notifyEntriesNotInitialized() {
235
        throw new IllegalStateException(
236
                "Resource Bundles: Entries not initialized");           //NOI18N
237
    }
238
239
    private static boolean isValidLocaleSuffix(String s) {
240
        // first char is _
241
        int n = s.length();
242
        String s1;
243
        // check first suffix - language (two chars)
244
        if (n == 3 || (n > 3 && s.charAt(3) == PropertiesDataLoader.PRB_SEPARATOR_CHAR)) {
245
            s1 = s.substring(1, 3).toLowerCase();
246
        // language must be followed by a valid country suffix or no suffix
247
        } else {
248
            return false;
249
        }
250
        // check second suffix - country (two chars)
251
        String s2;
252
        if (n == 3) {
253
            s2 = null;
254
        } else if (n == 6 || (n > 6 && s.charAt(6) == PropertiesDataLoader.PRB_SEPARATOR_CHAR)) {
255
            s2 = s.substring(4, 6).toUpperCase();
256
        // country may be followed by whatever additional suffix
257
        } else {
258
            return false;
259
        }
260
261
        Set<String> knownLanguages = new HashSet<String>(Arrays.asList(Locale.getISOLanguages()));
262
        if (!knownLanguages.contains(s1)) {
263
            return false;
264
        }
265
266
        if (s2 != null) {
267
            Set<String> knownCountries = new HashSet<String>(Arrays.asList(Locale.getISOCountries()));
268
            if (!knownCountries.contains(s2)) {
269
                return false;
270
            }
271
        }
272
        return true;
273
    }
274
    @Override
275
    public PropertiesOpen getOpenSupport() {
276
        synchronized (OPEN_SUPPORT_LOCK) {
277
            if (openSupport == null) {
278
                openSupport = new PropertiesOpen(this);
279
            }
280
            return openSupport;
281
        }
282
    }
283
284
    @Override
285
    public int getKeyCount() {
286
        try {
287
            return super.getKeyCount();
288
        } catch (IllegalStateException ie) {
289
            return 0;
290
        }
291
    }
292
}
(-)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 (-91 / +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
                //TODO XXX PENDING Check it
531
                PropertiesDataObject dataObject = null;
532
                if (evt.getSource() instanceof PropertiesDataObject) {
533
                    dataObject = (PropertiesDataObject) evt.getSource();
534
                }
535
                if (dataObject != null) {
536
                    bundleStructure.updateEntries();
537
                    bundleStructure.notifyOneFileChanged(dataObject.getPrimaryFile());
538
                    if (bundleStructure.getEntryCount() == 0) {
425
                // Loosing validity.
539
                // Loosing validity.
426
                PropertiesOpen support = (PropertiesOpen)findCloneableOpenSupport();
540
//                PropertiesOpen support = (PropertiesOpen)findCloneableOpenSupport();
427
                if(support != null) {
541
                        PropertiesOpen support = (PropertiesOpen)findCloneableOpenSupport(dataObject);
542
                        if(support != null ) {
428
                    
543
                    
429
                    // Mark the object as not being modified, so nobody
544
                            // Mark the object as not being modified, so nobody
430
                    // will ask for save.
545
                            // will ask for save.
431
                    unmarkModified();
546
                            unmarkModified((PropertiesDataObject) evt.getSource());
432
                    
547
                    
433
                    support.close(false);
548
                            support.close(false);
549
                        }
550
                    }
434
                }
551
                }
435
            } else {
552
            } else {
436
                firePropertyChange (
553
                firePropertyChange (
Lines 496-515 Link Here
496
    /** Inner class. Listens to modifications and updates save cookie. */
613
    /** Inner class. Listens to modifications and updates save cookie. */
497
    private final class ModifiedListener implements SaveCookie, PropertyChangeListener {
614
    private final class ModifiedListener implements SaveCookie, PropertyChangeListener {
498
615
616
499
        /** Gives notification that the DataObject was changed.
617
        /** Gives notification that the DataObject was changed.
500
        * @param ev PropertyChangeEvent
618
        * @param ev PropertyChangeEvent
501
        */
619
        */
502
        public void propertyChange(PropertyChangeEvent evt) {
620
        public void propertyChange(PropertyChangeEvent evt) {
503
            // Data object changed, reset the UndoRedo manager.
621
            // Data object changed, reset the UndoRedo manager.
504
            if (evt.getSource().equals(propDataObject)) {
622
            if (DataObject.PROP_MODIFIED.equals(evt.getPropertyName())) {
505
                ((CompoundUndoRedoManager) PropertiesOpen.this.getUndoRedo()).reset(propDataObject);
623
                if (evt.getSource() instanceof  PropertiesDataObject) {
506
            }
624
                    PropertiesDataObject dataObject = (PropertiesDataObject) evt.getSource();
507
625
                    if(bundleStructure.getEntryByFileName(dataObject.getName())!=null) {
508
            if ((evt.getSource() == propDataObject) && (DataObject.PROP_MODIFIED.equals(evt.getPropertyName()))) {
626
                        ((CompoundUndoRedoManager) PropertiesOpen.this.getUndoRedo()).reset(bundleStructure);
509
                if (((Boolean)evt.getNewValue()).booleanValue()) {
627
                            if (((Boolean)evt.getNewValue()).booleanValue()) {
510
                    addSaveCookie();
628
                                addSaveCookie(dataObject);
511
                } else {
629
                            } else {
512
                    removeSaveCookie();
630
                                removeSaveCookie(dataObject);
631
                            }
632
                     }
513
                }
633
                }
514
            }
634
            }
515
        }
635
        }
Lines 538-551 Link Here
538
        * @exception IOException on I/O error
658
        * @exception IOException on I/O error
539
        */
659
        */
540
        public void saveDocument() throws IOException {
660
        public void saveDocument() throws IOException {
541
            PropertiesFileEntry pfe = (PropertiesFileEntry)propDataObject.getPrimaryEntry();
661
            BundleStructure structure = bundleStructure;
542
            SaveCookie save = pfe.getCookie(SaveCookie.class);
662
            SaveCookie save;
543
            if (save != null) {
663
            for (int i=0; i<structure.getEntryCount();i++) {
544
                save.save();
664
                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) {
665
                if (save != null) {
550
                    save.save();
666
                    save.save();
551
                }
667
                }
Lines 553-566 Link Here
553
        }
669
        }
554
670
555
        /** Adds save cookie to the dataobject. */
671
        /** Adds save cookie to the dataobject. */
672
        @Deprecated
556
        private void addSaveCookie() {
673
        private void addSaveCookie() {
674
            if(propDataObject.getCookie(SaveCookie.class) == null) {
675
                propDataObject.getCookieSet0().add(this);
676
            }
677
        }
678
679
        private void addSaveCookie(PropertiesDataObject propDataObject) {
557
            if(propDataObject.getCookie(SaveCookie.class) == null) {
680
            if(propDataObject.getCookie(SaveCookie.class) == null) {
558
                propDataObject.getCookieSet0().add(this);
681
                propDataObject.getCookieSet0().add(this);
559
            }
682
            }
560
        }
683
        }
561
        
684
        
562
        /** Removes save cookie from the dataobject. */
685
        /** Removes save cookie from the dataobject. */
686
        @Deprecated
563
        private void removeSaveCookie() {
687
        private void removeSaveCookie() {
688
            if(propDataObject.getCookie(SaveCookie.class) == this) {
689
                propDataObject.getCookieSet0().remove(this);
690
            }
691
        }
692
693
        private void removeSaveCookie(PropertiesDataObject propDataObject) {
564
            if(propDataObject.getCookie(SaveCookie.class) == this) {
694
            if(propDataObject.getCookie(SaveCookie.class) == this) {
565
                propDataObject.getCookieSet0().remove(this);
695
                propDataObject.getCookieSet0().remove(this);
566
            }
696
            }
Lines 597-603 Link Here
597
            final PropertiesCloneableTopComponent editor = (PropertiesCloneableTopComponent)PropertiesOpen.super.openCloneableTopComponent();
727
            final PropertiesCloneableTopComponent editor = (PropertiesCloneableTopComponent)PropertiesOpen.super.openCloneableTopComponent();
598
            editor.requestActive();
728
            editor.requestActive();
599
            
729
            
600
            BundleStructure bs = propDataObject.getBundleStructure();
730
            BundleStructure bs = bundleStructure;
731
            bs.updateEntries();
601
            // Find indexes.
732
            // Find indexes.
602
            int entryIndex = bs.getEntryIndexByFileName(entry.getFile().getName());
733
            int entryIndex = bs.getEntryIndexByFileName(entry.getFile().getName());
603
            int rowIndex   = bs.getKeyIndexByName(key);
734
            int rowIndex   = bs.getKeyIndexByName(key);
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
            //TODO XXX PENDING Probable need to add activated Nodes
833
            BundleStructure structure = bundleStructure;
834
            PropertiesDataObject dataObject;
685
835
836
            Node[] node = new Node[structure.getEntryCount()];
686
            dataObjectListener = new NameUpdater();
837
            dataObjectListener = new NameUpdater();
687
            propDataObject.addPropertyChangeListener(
838
688
                    WeakListeners.propertyChange(dataObjectListener,
839
            for( int i=0; i<structure.getEntryCount();i++) {
689
                                                 propDataObject));
840
                    dataObject = dataObjecs[i];//(PropertiesDataObject) structure.getNthEntry(i).getDataObject();
841
                    node[i] = dataObject.getNodeDelegate();
842
                    weakListeners.put(dataObject,WeakListeners.propertyChange(dataObjectListener, dataObject));
843
                    dataObject.addPropertyChangeListener(weakListeners.get(dataObject));
844
            }
690
            
845
            
846
            setActivatedNodes(node);
847
691
            updateName();
848
            updateName();
849
        }
850
851
        /**
852
         * Called from PropertiesOpen when new DataObject added
853
         * @param dataObject to add listener to
854
         */
855
        protected void dataObjectAdded(PropertiesDataObject dataObject) {
856
            dataObject.removePropertyChangeListener(WeakListeners.propertyChange(dataObjectListener, dataObject));
857
            dataObject.addPropertyChangeListener(WeakListeners.propertyChange(dataObjectListener, dataObject));
692
        }
858
        }
693
        
859
        
694
        /* Based on class DataNode.PropL. */
860
        /* Based on class DataNode.PropL. */
Lines 710-716 Link Here
710
            
876
            
711
            /** */
877
            /** */
712
            private final int action;
878
            private final int action;
713
            
879
714
            /**
880
            /**
715
             */
881
             */
716
            NameUpdater() {
882
            NameUpdater() {
Lines 730-736 Link Here
730
                    previous.removeFileStatusListener(weakL);
896
                    previous.removeFileStatusListener(weakL);
731
                }
897
                }
732
                try {
898
                try {
733
                    previous = propDataObject.getPrimaryFile().getFileSystem();
899
                    previous = bundleStructure.getNthEntry(0).getFile().getFileSystem();
734
                    if (weakL == null) {
900
                    if (weakL == null) {
735
                        weakL = org.openide.filesystems.FileUtil
901
                        weakL = org.openide.filesystems.FileUtil
736
                                .weakFileStatusListener(this, previous);
902
                                .weakFileStatusListener(this, previous);
Lines 750-757 Link Here
750
                }
916
                }
751
                
917
                
752
                boolean thisChanged = false;
918
                boolean thisChanged = false;
753
                for (FileObject fo : propDataObject.files()) {
919
                //PENDING Check it
754
                    if (ev.hasChanged(fo)) {
920
                for (int i=0;i<bundleStructure.getEntryCount();i++) {
921
                    if(ev.hasChanged(bundleStructure.getNthEntry(i).getFile())) {
755
                        thisChanged = true;
922
                        thisChanged = true;
756
                        break;
923
                        break;
757
                    }
924
                    }
Lines 765-771 Link Here
765
            /**
932
            /**
766
             */
933
             */
767
            public void propertyChange(PropertyChangeEvent e) {
934
            public void propertyChange(PropertyChangeEvent e) {
768
                if (!propDataObject.isValid()) {
935
                //PENDING Add correct propDataObject
936
                if (bundleStructure.getEntryCount() == 0) {return;}
937
                if (!bundleStructure.getNthEntry(0).getDataObject().isValid()) {
769
                    return;
938
                    return;
770
                }
939
                }
771
                
940
                
Lines 819-825 Link Here
819
        private void updateName() {
988
        private void updateName() {
820
            assert EventQueue.isDispatchThread();
989
            assert EventQueue.isDispatchThread();
821
            
990
            
822
            final String name = propDataObject.getName();
991
            final String name = bundleStructure.getNthEntry(0).getName();
823
            final String displayName = displayName();
992
            final String displayName = displayName();
824
            final String htmlDisplayName = htmlDisplayName();
993
            final String htmlDisplayName = htmlDisplayName();
825
            final String toolTip = messageToolTip();
994
            final String toolTip = messageToolTip();
Lines 853-860 Link Here
853
        /**
1022
        /**
854
         */
1023
         */
855
        private String addModifiedInfo(String name) {
1024
        private String addModifiedInfo(String name) {
856
            boolean modified
1025
            boolean modified = false;
857
                    = propDataObject.getCookie(SaveCookie.class) != null;
1026
            for (int i=0;i<bundleStructure.getEntryCount();i++) {
1027
                if(bundleStructure.getNthEntry(i).getDataObject().getCookie(SaveCookie.class) != null) {
1028
                    modified = true;
1029
                    break;
1030
                }
1031
            }
858
            int version = modified ? 1 : 3;
1032
            int version = modified ? 1 : 3;
859
            return NbBundle.getMessage(PropertiesCloneableTopComponent.class,
1033
            return NbBundle.getMessage(PropertiesCloneableTopComponent.class,
860
                                       "LBL_EditorName",                //NOI18N
1034
                                       "LBL_EditorName",                //NOI18N
Lines 869-875 Link Here
869
         * @see  #htmlDisplayName
1043
         * @see  #htmlDisplayName
870
         */
1044
         */
871
        private String displayName() {
1045
        private String displayName() {
872
            String nameBase = propDataObject.getNodeDelegate().getDisplayName();
1046
            String nameBase = bundleStructure.getNthEntry(0).getDataObject().getNodeDelegate().getDisplayName();
873
            return addModifiedInfo(nameBase);
1047
            return addModifiedInfo(nameBase);
874
        }
1048
        }
875
        
1049
        
Lines 880-886 Link Here
880
         * @see  #displayName()
1054
         * @see  #displayName()
881
         */
1055
         */
882
        private String htmlDisplayName() {
1056
        private String htmlDisplayName() {
883
            final Node node = propDataObject.getNodeDelegate();
1057
            final Node node = bundleStructure.getNthEntry(0).getDataObject().getNodeDelegate();
884
            String displayName = node.getHtmlDisplayName();
1058
            String displayName = node.getHtmlDisplayName();
885
            if (displayName != null) {
1059
            if (displayName != null) {
886
                if (!displayName.startsWith("<html>")) {                //NOI18N
1060
                if (!displayName.startsWith("<html>")) {                //NOI18N
Lines 894-915 Link Here
894
        
1068
        
895
        /** Gets string for tooltip. */
1069
        /** Gets string for tooltip. */
896
        private String messageToolTip() {
1070
        private String messageToolTip() {
897
            FileObject fo = propDataObject.getPrimaryFile();
1071
            FileObject fo = bundleStructure.getNthEntry(0).getFile();
898
            return FileUtil.getFileDisplayName(fo);
1072
            return FileUtil.getFileDisplayName(fo);
899
        }
1073
        }
900
        
1074
        
901
        /** 
1075
        /**
1076
         * 
902
         * Overrides superclass method. When closing last view, also close the document.
1077
         * Overrides superclass method. When closing last view, also close the document.
903
         * @return {@code true} if close succeeded
1078
         * @return {@code true} if close succeeded
904
         */
1079
         */
905
        @Override
1080
        @Override
906
        protected boolean closeLast () {
1081
        protected boolean closeLast () {
907
            if (!propDataObject.getOpenSupport().canClose ()) {
1082
            if (!bundleStructure.getOpenSupport().canClose ()) {
908
                // if we cannot close the last window
1083
                // if we cannot close the last window
909
                return false;
1084
                return false;
910
            }
1085
            }
911
            propDataObject.getOpenSupport().closeDocuments();
1086
            bundleStructure.getOpenSupport().closeDocuments();
912
1087
            PropertyChangeListener l;
1088
            for (PropertiesDataObject dataObject:dataObjecs) {
1089
                l = weakListeners.get(dataObject);
1090
                if (l!=null) {
1091
                    dataObject.removePropertyChangeListener(l);
1092
                    weakListeners.remove(l);
1093
                }
1094
            }
913
            return true;
1095
            return true;
914
        }
1096
        }
915
1097
Lines 920-926 Link Here
920
         */
1102
         */
921
        @Override
1103
        @Override
922
        protected CloneableTopComponent createClonedObject () {
1104
        protected CloneableTopComponent createClonedObject () {
923
            return new PropertiesCloneableTopComponent(propDataObject);
1105
            return new PropertiesCloneableTopComponent(bundleStructure);
924
        }
1106
        }
925
1107
926
        /** Gets {@code Icon}. */
1108
        /** Gets {@code Icon}. */
Lines 950-956 Link Here
950
         */
1132
         */
951
        @Override
1133
        @Override
952
        public UndoRedo getUndoRedo () {
1134
        public UndoRedo getUndoRedo () {
953
            return propDataObject.getOpenSupport().getUndoRedo();
1135
            return  bundleStructure.getOpenSupport().getUndoRedo();
954
        }
1136
        }
955
1137
956
        /** Inits the subcomponents. Sets layout for this top component and adds {@code BundleEditPanel} to it. 
1138
        /** 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;
1146
            c.weightx = 1.0;
965
            c.weighty = 1.0;
1147
            c.weighty = 1.0;
966
            c.gridwidth = GridBagConstraints.REMAINDER;
1148
            c.gridwidth = GridBagConstraints.REMAINDER;
967
            JPanel panel = new BundleEditPanel(propDataObject, new PropertiesTableModel(propDataObject.getBundleStructure()));
1149
            JPanel panel = new BundleEditPanel(bundleStructure, new PropertiesTableModel(bundleStructure));
968
            gridbag.setConstraints(panel, c);
1150
            gridbag.setConstraints(panel, c);
969
            add(panel);
1151
            add(panel);
970
        }
1152
        }
Lines 973-979 Link Here
973
         *  is not valid.
1155
         *  is not valid.
974
         */
1156
         */
975
        private boolean discard () {
1157
        private boolean discard () {
976
            return propDataObject == null;
1158
            return bundleStructure == null;
977
        }
1159
        }
978
        
1160
        
979
1161
Lines 985-991 Link Here
985
        @Override
1167
        @Override
986
        public void writeExternal (ObjectOutput out) throws IOException {
1168
        public void writeExternal (ObjectOutput out) throws IOException {
987
            super.writeExternal(out);
1169
            super.writeExternal(out);
988
            out.writeObject(propDataObject);
1170
            out.writeObject(bundleStructure.getNthEntry(0).getDataObject());
989
        }
1171
        }
990
1172
991
        /** 
1173
        /** 
Lines 998-1004 Link Here
998
            super.readExternal(in);
1180
            super.readExternal(in);
999
1181
1000
            propDataObject = (PropertiesDataObject)in.readObject();
1182
            propDataObject = (PropertiesDataObject)in.readObject();
1001
            
1183
            bundleStructure = (MultiBundleStructure) propDataObject.getBundleStructure();
1184
            dataObjecs = new PropertiesDataObject[bundleStructure.getEntryCount()];
1185
            for (int i=0;i<bundleStructure.getEntryCount();i++) {
1186
                dataObjecs[i] = (PropertiesDataObject) bundleStructure.getNthEntry(i).getDataObject();
1187
            }
1188
            weakListeners = new HashMap<PropertiesDataObject, PropertyChangeListener>();
1002
            initialize();
1189
            initialize();
1003
        }
1190
        }
1004
    } // End of nested class PropertiesCloneableTopComponent.
1191
    } // End of nested class PropertiesCloneableTopComponent.
Lines 1017-1038 Link Here
1017
        // Constructor
1204
        // Constructor
1018
        
1205
        
1019
        /** Collects all UndoRedo managers from all editor support of all entries. */
1206
        /** Collects all UndoRedo managers from all editor support of all entries. */
1207
        @Deprecated
1020
        public CompoundUndoRedoManager(PropertiesDataObject obj) {
1208
        public CompoundUndoRedoManager(PropertiesDataObject obj) {
1021
            init(obj);
1209
            init(obj);
1022
        }
1210
        }
1211
        public CompoundUndoRedoManager(BundleStructure structure) {
1212
            init(structure);
1213
        }
1023
1214
1024
        /** Initialize set of managers. */
1215
        /** Initialize set of managers. */
1216
        @Deprecated
1025
        private void init(PropertiesDataObject obj) {
1217
        private void init(PropertiesDataObject obj) {
1026
            managers.add( ((PropertiesFileEntry)obj.getPrimaryEntry()).getPropertiesEditor().getUndoRedoManager());
1218
            BundleStructure structure = obj.getBundleStructure();
1027
            for (Iterator it = obj.secondaryEntries().iterator(); it.hasNext(); ) {
1219
            for(int i=0; i< structure.getEntryCount(); i++) {
1028
                managers.add( ((PropertiesFileEntry)it.next()).getPropertiesEditor().getUndoRedoManager() );
1220
                managers.add(structure.getNthEntry(i).getPropertiesEditor().getUndoRedoManager());
1029
            } 
1221
            }
1222
        }
1223
1224
        private void init(BundleStructure structure) {
1225
            for(int i=0; i< structure.getEntryCount(); i++) {
1226
                managers.add(structure.getNthEntry(i).getPropertiesEditor().getUndoRedoManager());
1227
            }
1030
        }
1228
        }
1031
1229
1032
        /** Resets the managers. Used when data object has changed. */
1230
        /** Resets the managers. Used when data object has changed. */
1231
        @Deprecated
1033
        public synchronized void reset(PropertiesDataObject obj) {
1232
        public synchronized void reset(PropertiesDataObject obj) {
1034
            managers.clear();
1233
            managers.clear();
1035
            init(obj);
1234
            init(obj);
1235
        }
1236
1237
        public synchronized void reset(BundleStructure structure) {
1238
            managers.clear();
1239
            init(structure);
1036
        }
1240
        }
1037
1241
1038
        /** Gets manager which undo edit comes to play.*/
1242
        /** Gets manager which undo edit comes to play.*/
(-)a/properties/src/org/netbeans/modules/properties/PropertiesTableModel.java (-6 / +18 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
     * XXX Check it out.
290
     * @param column
291
     * @return
292
     */
293
    PropertiesFileEntry getFileEntry(int column) {
294
        return structure.getNthEntry(column-1);
295
    }
287
    /** Overrides superclass method. */
296
    /** Overrides superclass method. */
288
    @Override
297
    @Override
289
    public String toString() {
298
    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
373
                // 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.
374
                // the same thing like reseting the model, but it doesn't, therefore we reset the model directly.
366
                
375
                
367
                //cancelEditingInTables(getDefaultCancelSelector());
376
                cancelEditingInTables(getDefaultCancelSelector());
368
                //fireTableStructureChanged(); 
377
                fireTableStructureChanged(); 
369
378
370
                Object[] list = PropertiesTableModel.super.listenerList.getListenerList();
379
                Object[] list = PropertiesTableModel.super.listenerList.getListenerList();
371
                for(int i = 0; i < list.length; i++) {
380
                for(int i = 0; i < list.length; i++) {
Lines 396-404 Link Here
396
            } else if(changeType == PropertyBundleEvent.CHANGE_FILE) {
405
            } else if(changeType == PropertyBundleEvent.CHANGE_FILE) {
397
                // File changed.
406
                // File changed.
398
                final int index = structure.getEntryIndexByFileName(evt.getEntryName());
407
                final int index = structure.getEntryIndexByFileName(evt.getEntryName());
408
                //This mean file deleted
399
                if (index == -1) {
409
                if (index == -1) {
400
                    if (Boolean.getBoolean("netbeans.debug.exceptions")) // NOI18N
410
                    fireTableStructureChanged();
401
                        (new Exception("Changed file not found")).printStackTrace(); // NOI18N
411
//                    if (Boolean.getBoolean("netbeans.debug.exceptions")) // NOI18N
412
//                        (new Exception("Changed file not found")).printStackTrace(); // NOI18N
402
                    return;
413
                    return;
403
                }
414
                }
404
                
415
                
Lines 409-416 Link Here
409
                        return (column == index + 1);
420
                        return (column == index + 1);
410
                    }
421
                    }
411
                });
422
                });
412
                
423
//TODO XXX PENDING
413
                fireTableColumnChanged(index + 1);
424
//                fireTableColumnChanged(index + 1);
425
                  fireTableStructureChanged();
414
            } else if(changeType == PropertyBundleEvent.CHANGE_ITEM) {
426
            } else if(changeType == PropertyBundleEvent.CHANGE_ITEM) {
415
                // one item changed
427
                // one item changed
416
                final int index2 = structure.getEntryIndexByFileName(evt.getEntryName());
428
                final int index2 = structure.getEntryIndexByFileName(evt.getEntryName());
(-)a/properties/src/org/netbeans/modules/properties/Util.java (-7 / +139 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 55-60 Link Here
55
import org.openide.filesystems.Repository;
57
import org.openide.filesystems.Repository;
56
import org.openide.loaders.DataFolder;
58
import org.openide.loaders.DataFolder;
57
import org.openide.loaders.DataObject;
59
import org.openide.loaders.DataObject;
60
import org.openide.loaders.DataObjectNotFoundException;
58
import org.openide.loaders.FileEntry;
61
import org.openide.loaders.FileEntry;
59
62
60
import org.openide.loaders.MultiDataObject;
63
import org.openide.loaders.MultiDataObject;
Lines 148-161 Link Here
148
     * @see  #getVariant
151
     * @see  #getVariant
149
     */
152
     */
150
    public static String getLocaleSuffix(MultiDataObject.Entry fe) {
153
    public static String getLocaleSuffix(MultiDataObject.Entry fe) {
151
        MultiDataObject.Entry pe = fe.getDataObject().getPrimaryEntry();
154
        FileObject fo = fe.getFile();
152
        if (fe == pe) {
155
        String fName = fo.getName();
153
            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);
154
        }
165
        }
155
        String myName   = fe.getFile().getName();
166
        if (fo == po) {
156
        String baseName = pe.getFile().getName();
167
            return "";
168
        }
169
        String myName   = fo.getName();
170
        String baseName = po.getName();
157
        assert myName.startsWith(baseName);
171
        assert myName.startsWith(baseName);
158
        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;
159
    }
217
    }
160
218
161
    /**
219
    /**
Lines 392-397 Link Here
392
               template.createFromTemplate(DataFolder.findFolder(folder), fileName);
450
               template.createFromTemplate(DataFolder.findFolder(folder), fileName);
393
    }
451
    }
394
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
     */
395
    public static void createLocaleFile(PropertiesDataObject propertiesDataObject,
459
    public static void createLocaleFile(PropertiesDataObject propertiesDataObject,
396
                                        String locale,
460
                                        String locale,
397
                                        boolean copyInitialContent)
461
                                        boolean copyInitialContent)
Lines 404-411 Link Here
404
            }
468
            }
405
469
406
            if(propertiesDataObject != null) {
470
            if(propertiesDataObject != null) {
407
                FileObject file = propertiesDataObject.getPrimaryFile();
471
//                FileObject file = propertiesDataObject.getPrimaryFile();
408
                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;
409
                final FileObject folder = file.getParent();
475
                final FileObject folder = file.getParent();
410
//                                    final PropertiesEditorSupport editor = (PropertiesEditorSupport)propertiesDataObject.getCookie(PropertiesEditorSupport.class);
476
//                                    final PropertiesEditorSupport editor = (PropertiesEditorSupport)propertiesDataObject.getCookie(PropertiesEditorSupport.class);
411
                java.util.Iterator it = propertiesDataObject.secondaryEntries().iterator();
477
                java.util.Iterator it = propertiesDataObject.secondaryEntries().iterator();
Lines 430-435 Link Here
430
                                templateFile.copy(folder, newName, PropertiesDataLoader.PROPERTIES_EXTENSION);
496
                                templateFile.copy(folder, newName, PropertiesDataLoader.PROPERTIES_EXTENSION);
431
                            }
497
                            }
432
                        });
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));
433
                    }
508
                    }
434
                } else {
509
                } else {
435
                    // Create an empty file - creating from template via DataObject
510
                    // Create an empty file - creating from template via DataObject
Lines 445-448 Link Here
445
            notifyError(locale);
520
            notifyError(locale);
446
        }
521
        }
447
    }
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
448
}
580
}

Return to bug 48263