org.openide.text.CloneableEditorSupport Java Examples

The following examples show how to use org.openide.text.CloneableEditorSupport. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: CssRenameRefactoringPlugin.java    From netbeans with Apache License 2.0 6 votes vote down vote up
private void refactorElement(ModificationResult modificationResult, CssElementContext.Editor context, CssIndex index) {
    //type selector: div
    //we do refactor only elements in the current css file, and even this is questionable if makes much sense
    Node element = context.getElement();
    String elementImage = element.image().toString();

    CssFileModel model = CssFileModel.create(context.getParserResult());
    List<Difference> diffs = new ArrayList<>();
    CloneableEditorSupport editor = GsfUtilities.findCloneableEditorSupport(context.getFileObject());
    for (Entry entry : model.getHtmlElements()) {
        if (entry.isValidInSourceDocument() && elementImage.equals(entry.getName())) {
            diffs.add(new Difference(Difference.Kind.CHANGE,
                    editor.createPositionRef(entry.getDocumentRange().getStart(), Bias.Forward),
                    editor.createPositionRef(entry.getDocumentRange().getEnd(), Bias.Backward),
                    entry.getName(),
                    refactoring.getNewName(),
                    NbBundle.getMessage(CssRenameRefactoringPlugin.class, "MSG_Rename_Selector"))); //NOI18N
        }
    }
    if (!diffs.isEmpty()) {
        modificationResult.addDifferences(context.getFileObject(), diffs);
    }

}
 
Example #2
Source File: InstantRenamePerformer.java    From netbeans with Apache License 2.0 6 votes vote down vote up
private synchronized void release() {
    if (target == null) {
        //already released
        return ;
    }
    sendUndoableEdit(doc, CloneableEditorSupport.END_COMMIT_GROUP);
    target.putClientProperty("NetBeansEditor.navigateBoundaries", null); // NOI18N
    target.putClientProperty(InstantRenamePerformer.class, null);
    if (doc instanceof BaseDocument) {
        ((BaseDocument) doc).setPostModificationDocumentListener(null);
    }
    target.removeKeyListener(this);
    target = null;

    region = null;
    attribs = null;
    
    requestRepaint();

    doc = null;
}
 
Example #3
Source File: JspSyntaxSupport.java    From netbeans with Apache License 2.0 6 votes vote down vote up
@Override
protected SyntaxSupport createSyntaxSupport(Class syntaxSupportClass) {
    SyntaxSupport support = super.createSyntaxSupport(syntaxSupportClass);
    if (support != null)
        return support;

    EditorKit kit;
    // try the content language support
    kit = CloneableEditorSupport.getEditorKit("text/html"); //NOI18N
    if (kit instanceof BaseKit) {
        support = ((BaseKit)kit).createSyntaxSupport(getDocument());
        if (support != null)
            return support;
    }
    // try the scripting language support
    kit = CloneableEditorSupport.getEditorKit("text/x-java"); //NOI18N
    if (kit instanceof BaseKit) {
        support = ((BaseKit)kit).createSyntaxSupport(getDocument());
        if (support != null)
            return support;
    }
    return null;
}
 
Example #4
Source File: Utilities.java    From netbeans with Apache License 2.0 6 votes vote down vote up
public static List<PositionBounds> prepareSpansFor(FileObject file, Iterable<? extends int[]> spans) {
    List<PositionBounds> result = new ArrayList<PositionBounds>();

    try {
        DataObject d = DataObject.find(file);
        EditorCookie ec = d.getLookup().lookup(EditorCookie.class);
        CloneableEditorSupport ces = (CloneableEditorSupport) ec;

        result = new LinkedList<PositionBounds>();

        for (int[] span : spans) {
            PositionRef start = ces.createPositionRef(span[0], Bias.Forward);
            PositionRef end = ces.createPositionRef(span[1], Bias.Forward);

            result.add(new PositionBounds(start, end));
        }
    } catch (DataObjectNotFoundException ex) {
        Exceptions.printStackTrace(ex);
    }

    return result;
}
 
Example #5
Source File: AbbrevDetection.java    From netbeans with Apache License 2.0 6 votes vote down vote up
private static boolean expand(CodeTemplateManagerOperation op, JTextComponent component, int abbrevStartOffset, CharSequence abbrev) {
    op.waitLoaded();
    CodeTemplate ct = op.findByAbbreviation(abbrev.toString());
    if (ct != null) {
        if (accept(ct, CodeTemplateManagerOperation.getTemplateFilters(component, abbrevStartOffset))) {
            Document doc = component.getDocument();
            sendUndoableEdit(doc, CloneableEditorSupport.BEGIN_COMMIT_GROUP);
            try {
                // Remove the abbrev text
                doc.remove(abbrevStartOffset, abbrev.length());
                ct.insert(component);
            } catch (BadLocationException ble) {
            } finally {
                sendUndoableEdit(doc, CloneableEditorSupport.END_COMMIT_GROUP);
            }
            return true;
        }
    }
    return false;
}
 
Example #6
Source File: AbstractRefactoringElement.java    From netbeans with Apache License 2.0 6 votes vote down vote up
public PositionBounds getPosition() {
    try {
        DataObject dobj = DataObject.find(getParentFile());
        if (dobj != null) {
            EditorCookie.Observable obs = (EditorCookie.Observable)dobj.getCookie(EditorCookie.Observable.class);
            if (obs != null && obs instanceof CloneableEditorSupport) {
                CloneableEditorSupport supp = (CloneableEditorSupport)obs;

                if (loc == null) {
                    loc = location();
                }
            PositionBounds bounds = new PositionBounds(
                    supp.createPositionRef(loc[0], Position.Bias.Forward),
                    supp.createPositionRef(Math.max(loc[0], loc[1]), Position.Bias.Forward)
                    );
            
            return bounds;
        }
        }
    } catch (DataObjectNotFoundException ex) {
        ex.printStackTrace();
    }
    return null;
}
 
Example #7
Source File: HintsControllerImpl.java    From netbeans with Apache License 2.0 6 votes vote down vote up
public static PositionBounds linePart(FileObject file, int start, int end) {
    try {
        DataObject od = DataObject.find(file);
        
        if (od == null)
            return null;
        
        EditorCookie ec = od.getCookie(EditorCookie.class);
        
        if (!(ec instanceof CloneableEditorSupport)) {
            return null;
        }
        
        final CloneableEditorSupport ces = (CloneableEditorSupport) ec;
        
        checkOffsetsAndLog(start, end);
        
        return new PositionBounds(ces.createPositionRef(start, Position.Bias.Forward), ces.createPositionRef(end, Position.Bias.Backward));
    } catch (IOException e) {
        LOG.log(Level.INFO, null, e);
        return null;
    }
}
 
Example #8
Source File: MultiViewCloneableTopComponentTest.java    From netbeans with Apache License 2.0 6 votes vote down vote up
public void testSourceViewMarker() throws Exception {
    MVElem elem1 = new MVElem();
    MVElem elem2 = new MVElem();
    MVElem elem3 = new SourceMVElem();
    MultiViewDescription desc1 = new MVDesc("desc1", null, 0, elem1);
    MultiViewDescription desc2 = new MVDesc("desc2", null, 0, elem2);
    MultiViewDescription desc3 = new SourceMVDesc("desc3", null, 0, elem3);
    MultiViewDescription[] descs = new MultiViewDescription[] { desc1, desc2, desc3 };
    CloneableTopComponent tc = MultiViewFactory.createCloneableMultiView(descs, desc1);
    
    tc.open();
    tc.requestActive();
    
    CloneableEditorSupport.Pane pane = (CloneableEditorSupport.Pane)tc;
    JEditorPane editor = pane.getEditorPane();
    assertNotNull(editor);
    
    MultiViewHandler hand = MultiViews.findMultiViewHandler(tc);
    assertFalse(desc3.equals(Accessor.DEFAULT.extractDescription(hand.getSelectedPerspective())));
    
}
 
Example #9
Source File: CPRenameRefactoringPlugin.java    From netbeans with Apache License 2.0 6 votes vote down vote up
private void refactorElements(ModificationResult modificationResult, RefactoringElementContext context, Collection<RefactoringElement> elementsToRename, String renameMsg) throws IOException, ParseException {
    Map<FileObject, List<Difference>> file2diffs = new HashMap<>();
    for (RefactoringElement re : elementsToRename) {
        CloneableEditorSupport editor = GsfUtilities.findCloneableEditorSupport(re.getFile());

        Difference diff = new Difference(Difference.Kind.CHANGE,
                editor.createPositionRef(re.getRange().getStart(), Bias.Forward),
                editor.createPositionRef(re.getRange().getEnd(), Bias.Backward),
                re.getName(),
                refactoring.getNewName(),
                renameMsg);

        List<Difference> diffs = file2diffs.get(re.getFile());
        if (diffs == null) {
            diffs = new ArrayList<>();
            file2diffs.put(re.getFile(), diffs);
        }
        diffs.add(diff);
    }

    for (Entry<FileObject, List<Difference>> entry : file2diffs.entrySet()) {
        modificationResult.addDifferences(entry.getKey(), entry.getValue());
    }
}
 
Example #10
Source File: BackupFacility2.java    From netbeans with Apache License 2.0 6 votes vote down vote up
private void storeChecksum(long l) throws IOException {
    BackupEntry backup = map.get(l);
    if(backup.orig == null) { // Find fileobject for newly created file
        backup.orig = FileUtil.toFileObject(backup.origFile);
        backup.origFile = null;
    }
    FileObject fo = backup.orig;
    if (!fo.isValid()) {
        //deleted
        backup.checkSum = new byte[16];
        Arrays.fill(backup.checkSum, (byte)0);
        return;
    }
    DataObject dob = DataObject.find(fo);
    if (dob != null) {
        CloneableEditorSupport ces = dob.getLookup().lookup(CloneableEditorSupport.class);
        final BaseDocument doc = (BaseDocument) ces.getDocument();
        if (doc !=null && doc.isAtomicLock()) {
            //workaround to avoid deadlock
            return;
        }
    }
    LOG.log(Level.FINE, "Storing MD5 for {0}", backup.orig);
    backup.checkSum = getMD5(getInputStream(backup.orig));
    LOG.log(Level.FINE, "MD5 is: {0}", MD5toString(backup.checkSum));
}
 
Example #11
Source File: EditorSanityTest.java    From netbeans with Apache License 2.0 6 votes vote down vote up
public void testPlainEditorKits() {
    // VIS: JEditorPane when constructed contains javax.swing.JEditorPane$PlainEditorKit
    // and calling JEP.setContenetType("text/plain") has no effect. IMO this is probably
    // a defect in JDK, becuase JEP should always honour its EditorKit registry.
    JEditorPane pane = new JEditorPane();
    pane.setEditorKit(new DefaultEditorKit() {
        public @Override String getContentType() {
            return "text/whatever";
        }
    });
    setContentTypeInAwt(pane, "text/plain");
    
    // Test JDK kit
    EditorKit kitFromJdk = pane.getEditorKit();
    assertNotNull("Can't find JDK kit for text/plain", kitFromJdk);
    assertEquals("The kit for text/plain should not be from JDK", 
        "org.netbeans.modules.editor.plain.PlainKit", kitFromJdk.getClass().getName());

    // Test Netbeans kit
    EditorKit kitFromNb = CloneableEditorSupport.getEditorKit("text/plain");
    assertNotNull("Can't find Nb kit for text/plain", kitFromNb);
    assertEquals("Wrong Nb kit for text/plain", 
        "org.netbeans.modules.editor.plain.PlainKit", kitFromNb.getClass().getName());
}
 
Example #12
Source File: CPActionsImplementationProvider.java    From netbeans with Apache License 2.0 5 votes vote down vote up
private static boolean isFromEditor(EditorCookie ec) {
    if (ec != null && ec.getOpenedPanes() != null) {
        TopComponent activetc = TopComponent.getRegistry().getActivated();
        if (activetc instanceof CloneableEditorSupport.Pane) {
            return true;
        }
    }
    return false;
}
 
Example #13
Source File: LaunchedProjectOpener.java    From netbeans with Apache License 2.0 5 votes vote down vote up
private boolean closeCloneableEditor(JShellEnvironment env) {
    FileObject consoleDoc = env.getConsoleFile();
    CloneableEditorSupport editor = consoleDoc.getLookup().lookup(CloneableEditorSupport.class);
    if (editor == null || editor.getOpenedPanes() == null) {
        return false;
    }
    return editor.close();
}
 
Example #14
Source File: MultiViewCloneableTopComponent.java    From netbeans with Apache License 2.0 5 votes vote down vote up
private MultiViewElement findPaneElement() {
    MultiViewElement el = peer.model.getActiveElement(false);
    if (el != null && el.getVisualRepresentation() instanceof CloneableEditorSupport.Pane) {
        return el;
    }
    // now try a best guess.. iterate the already created elements and check if any of
    // them is a Pane
    Collection col = peer.model.getCreatedElements();
    Iterator<MultiViewElement> it = col.iterator();
    while (it.hasNext()) {
        el = it.next();
        if (el.getVisualRepresentation() instanceof CloneableEditorSupport.Pane) {
            // fingers crossed and hope for the best... could result in bad results once
            // we have multiple editors in the multiview component.
            return el;
        }
    }
    
    MultiViewDescription[] descs = peer.model.getDescriptions();
    for (MultiViewDescription desc : descs) {
        if (isSourceView(desc)) {
            el = peer.model.getElementForDescription(desc);
            if (el.getVisualRepresentation() instanceof CloneableEditorSupport.Pane) {
                return el;
            } else {
                Logger.getLogger(getClass().getName()).info("MultiViewDescription " + desc.getDisplayName() + "(" + desc.getClass() + 
                        ") claimed to contain sources, but it's MutliViewElement.getVisualRepresentation() didn't return a valid CloeanbleEditorSupport.Pane instance.");
            }
        }
    }
    // hopeless case, don't try to create new elements. it's users responsibility to
    // switch to the editor element before getEditorPane() 
    return null;
}
 
Example #15
Source File: HtmlActionsImplementationProvider.java    From netbeans with Apache License 2.0 5 votes vote down vote up
private static boolean isFromEditor(final EditorCookie ec) {
    return Mutex.EVENT.readAccess(new Mutex.Action<Boolean>() {
        @Override
        public Boolean run() {
            if (ec != null && ec.getOpenedPanes() != null) {
                TopComponent activetc = TopComponent.getRegistry().getActivated();
                if (activetc instanceof CloneableEditorSupport.Pane) {
                    return true;
                }
            }
            return false;
        }
    });
}
 
Example #16
Source File: EditorSanityTest.java    From netbeans with Apache License 2.0 5 votes vote down vote up
public void testHTMLEditorKits() {
    JEditorPane pane = new JEditorPane();
    setContentTypeInAwt(pane, "text/html");
    
    // Test JDK kit
    EditorKit kitFromJdk = pane.getEditorKit();
    assertNotNull("Can't find JDK kit for text/html", kitFromJdk);
    assertTrue("Wrong JDK kit for text/html", kitFromJdk instanceof HTMLEditorKit);

    // Check that org.netbeans.modules.html.editor is available
    boolean htmlPresent = false;
    Collection<? extends ModuleInfo> modules = Lookup.getDefault().lookupAll(ModuleInfo.class);
    for(ModuleInfo info : modules) {
        if (info.getCodeNameBase().equals("org.netbeans.modules.html.editor")) {
            htmlPresent = true;
            break;
        }
    }

    if (htmlPresent) {
        // Test Netbeans kit
        EditorKit kitFromNb = CloneableEditorSupport.getEditorKit("text/html");
        assertNotNull("Can't find Nb kit for text/html", kitFromNb);
        assertEquals("Wrong Nb kit for text/html",
            "org.netbeans.modules.html.editor.api.HtmlKit", kitFromNb.getClass().getName());
    } else {
        log("Module org.netbeans.modules.html.editor not present, skipping HTMLKit test...");
    }
}
 
Example #17
Source File: EditableDiffView.java    From netbeans with Apache License 2.0 5 votes vote down vote up
private void repairTextUI (JEditorPane pane) {
    TextUI ui = pane.getUI();
    if (!(ui instanceof BaseTextUI)) {
        // use plain editor
        pane.setEditorKit(CloneableEditorSupport.getEditorKit(CONTENT_TYPE_PLAIN)); //NOI18N
    }
}
 
Example #18
Source File: MultiViewEditorElementTest.java    From netbeans with Apache License 2.0 5 votes vote down vote up
public void testLookupProvidersAreConsistent() throws Exception {
    InstanceContent ic = new InstanceContent();
    Lookup context = new AbstractLookup(ic);

    CloneableEditorSupport ces = createSupport(context);
    ic.add(ces);
    ic.add(10);

    final CloneableTopComponent tc = MultiViews.createCloneableMultiView("text/plaintest", new LP(context));
    final CloneableEditorSupport.Pane p = (CloneableEditorSupport.Pane) tc;
    EventQueue.invokeAndWait(new Runnable() {
        @Override
        public void run() {
            tc.open();
            tc.requestActive();
            p.updateName();
        }
    });

    assertNull("No icon yet", tc.getIcon());
    MultiViewHandler handler = MultiViews.findMultiViewHandler(tc);
    final MultiViewPerspective[] one = handler.getPerspectives();
    assertEquals("Two elements only" + Arrays.asList(one), 2, handler.getPerspectives().length);
    assertEquals("First one is source", "source", one[0].preferredID());
    assertEquals("Second one is also source", "source", one[1].preferredID());
    handler.requestVisible(one[0]);
    
    List<Lookup.Provider> arr = new ArrayList<Provider>();
    findProviders(tc, arr);
    assertEquals("Two providers: " + arr, 2, arr.size());

    assertSame("Both return same lookup", arr.get(0).getLookup(), arr.get(1).getLookup());
}
 
Example #19
Source File: RefactoringUtils.java    From netbeans with Apache License 2.0 5 votes vote down vote up
public static boolean isFromEditor(EditorCookie ec) {
    if (ec != null && ec.getOpenedPanes() != null) {
        TopComponent activetc = TopComponent.getRegistry().getActivated();
        if (activetc instanceof CloneableEditorSupport.Pane) {
            return true;
        }
    }
    return false;
}
 
Example #20
Source File: SQLEditorSupport.java    From netbeans with Apache License 2.0 5 votes vote down vote up
@Override
protected Pane createPane() {
    Pane pane;
    if(getDataObject().getPrimaryFile().toURL().toExternalForm().startsWith("nbfs://")) {
        pane = new SQLCloneableEditor(Lookups.fixed(this, getDataObject()));
    } else {
        pane = (CloneableEditorSupport.Pane) MultiViews.createCloneableMultiView(
            SQLDataLoader.SQL_MIME_TYPE, getDataObject());
    }
    return pane;
}
 
Example #21
Source File: GsfDataObject.java    From netbeans with Apache License 2.0 5 votes vote down vote up
@Override
protected Pane createPane() {
    if(language.useMultiview()) {
        return (CloneableEditorSupport.Pane) MultiViews.createCloneableMultiView(language.getMimeType(), getDataObject());
    } else {
        return super.createPane();
    }
}
 
Example #22
Source File: JSFEditorUtilities.java    From netbeans with Apache License 2.0 5 votes vote down vote up
/**
 * Method that allows to find its
 * CloneableEditorSupport from given DataObject
 * @return the support or null if the CloneableEditorSupport 
 * was not found
 * This method is hot fix for issue #53309
 * this methd was copy/pasted from OpenSupport.Env class
 * @param dob an instance of DataObject
 */
public static CloneableEditorSupport findCloneableEditorSupport(DataObject dob) {
    Node.Cookie obj = dob.getCookie(org.openide.cookies.OpenCookie.class);
    if (obj instanceof CloneableEditorSupport) {
        return (CloneableEditorSupport)obj;
    }
    obj = dob.getCookie(org.openide.cookies.EditorCookie.class);
    if (obj instanceof CloneableEditorSupport) {
        return (CloneableEditorSupport)obj;
    }
    return null;
}
 
Example #23
Source File: PositionBoundsResolver.java    From netbeans with Apache License 2.0 5 votes vote down vote up
private CloneableEditorSupport findCloneableEditorSupport() {
    Node.Cookie obj = dataObject.getCookie(org.openide.cookies.OpenCookie.class);
    if (obj instanceof CloneableEditorSupport) {
        return (CloneableEditorSupport)obj;
    }
    obj = dataObject.getCookie(org.openide.cookies.EditorCookie.class);
    if (obj instanceof CloneableEditorSupport) {
        return (CloneableEditorSupport)obj;
    }
    return null;
}
 
Example #24
Source File: ModelItem.java    From netbeans with Apache License 2.0 5 votes vote down vote up
public void updatePostDataPane(JEditorPane pane, boolean rawData) {
    if (hasPostData()) {
        if (rawData) {
            pane.setEditorKit(CloneableEditorSupport.getEditorKit("text/plain"));
            pane.setText(getPostData());
        } else {
            String contentType = stripDownContentType(getRequestHeaders());
            reformatAndUseRightEditor(pane, getPostData(), contentType);
        }
    }
}
 
Example #25
Source File: BuildActionsCustomizer.java    From netbeans with Apache License 2.0 5 votes vote down vote up
/**
 * Creates new form BuildActionsCustomizer
 */
public BuildActionsCustomizer(Project project) {
    this.project = project;
    initComponents();
    actionRegistry = new CustomActionRegistrationSupport(project);
    lsActions.setCellRenderer(new MyListCellRenderer());
    tfLabel.getDocument().addDocumentListener(applyListener);
    EditorKit kit = CloneableEditorSupport.getEditorKit(GradleCliEditorKit.MIME_TYPE);
    taArgs.setEditorKit(kit);
    taArgs.getDocument().putProperty(Document.StreamDescriptionProperty, project);
    taArgs.getDocument().addDocumentListener(applyListener);
    initDefaultModels();
    comboReady = true;
}
 
Example #26
Source File: GradleExecutorOptionsPanel.java    From netbeans with Apache License 2.0 5 votes vote down vote up
/**
 * Creates new form GradleExecutorOptionsPanel
 */
public GradleExecutorOptionsPanel(Project project) {
    this.project = project;
    initComponents();
    EditorKit kit = CloneableEditorSupport.getEditorKit(GradleCliEditorKit.MIME_TYPE);
    epCLI.setEditorKit(kit);
    if (project != null) {
        epCLI.getDocument().putProperty(Document.StreamDescriptionProperty, project);
    } else {
        tfRememberAs.setEnabled(false);
        lbRememberAs.setEnabled(false);
    }
    epCLI.requestFocus();
}
 
Example #27
Source File: GroovyProjectUtil.java    From netbeans with Apache License 2.0 5 votes vote down vote up
public static CloneableEditorSupport findCloneableEditorSupport(DataObject dob) {
    Object obj = dob.getLookup().lookup(OpenCookie.class);
    if (obj instanceof CloneableEditorSupport) {
        return (CloneableEditorSupport)obj;
    }
    obj = dob.getLookup().lookup(EditorCookie.class);
    if (obj instanceof CloneableEditorSupport) {
        return (CloneableEditorSupport)obj;
    }
    return null;
}
 
Example #28
Source File: FindUsagesElement.java    From netbeans with Apache License 2.0 5 votes vote down vote up
@Override
public PositionBounds getPosition() {
    OffsetRange range = ASTUtils.getRange(usageElement.getNode(), doc);
    if (range == OffsetRange.NONE) {
        return null;
    }

    CloneableEditorSupport ces = GroovyProjectUtil.findCloneableEditorSupport(usageElement.getFileObject());
    PositionRef ref1 = ces.createPositionRef(range.getStart(), Position.Bias.Forward);
    PositionRef ref2 = ces.createPositionRef(range.getEnd(), Position.Bias.Forward);
    return new PositionBounds(ref1, ref2);
}
 
Example #29
Source File: FolderActionsImplementationProvider.java    From netbeans with Apache License 2.0 5 votes vote down vote up
private static boolean isFromEditor(final EditorCookie ec) {
    return Mutex.EVENT.readAccess(new Action<Boolean>() {
        @Override
        public Boolean run() {
            if (ec != null && ec.getOpenedPanes() != null) {
                TopComponent activetc = TopComponent.getRegistry().getActivated();
                if (activetc instanceof CloneableEditorSupport.Pane) {
                    return true;
                }
            }
            return false;
        }
    });
}
 
Example #30
Source File: PropertiesEditorSupport.java    From netbeans with Apache License 2.0 5 votes vote down vote up
@Messages({
    "MSG_SaveModified=File {0} is modified. Save?"
})
@Override
public CloseOperationState canCloseElement() {
    final CloneableEditorSupport sup = getLookup().lookup(CloneableEditorSupport.class);
    Enumeration en = getReference().getComponents();
    if (en.hasMoreElements()) {
        en.nextElement();
        if (en.hasMoreElements()) {
            // at least two is OK
            return CloseOperationState.STATE_OK;
        }
    }
    
    PropertiesDataObject dataObject = getDataObject();
    if (dataObject.isModified()) {
        AbstractAction save = new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                try {
                    sup.saveDocument();
                } catch (IOException ex) {
                    Exceptions.printStackTrace(ex);
                }
            }
        };
        save.putValue(Action.LONG_DESCRIPTION, Bundle.MSG_SaveModified(FileUtil.getFileDisplayName(dataObject.getPrimaryFile())));
        return MultiViewFactory.createUnsafeCloseState("editor", save, null);
    } 
    return CloseOperationState.STATE_OK;
}