/*
* Copyright 2015 Igor Maznitsa.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.igormaznitsa.ideamindmap.editor;
import com.igormaznitsa.ideamindmap.facet.MindMapFacet;
import com.igormaznitsa.ideamindmap.utils.IdeaUtils;
import com.igormaznitsa.ideamindmap.utils.SelectIn;
import com.igormaznitsa.ideamindmap.utils.SwingUtils;
import com.igormaznitsa.meta.annotation.MustNotContainNull;
import com.igormaznitsa.mindmap.ide.commons.DnDUtils;
import com.igormaznitsa.mindmap.model.*;
import com.igormaznitsa.mindmap.model.logger.Logger;
import com.igormaznitsa.mindmap.model.logger.LoggerFactory;
import com.igormaznitsa.mindmap.swing.panel.DialogProvider;
import com.igormaznitsa.mindmap.swing.panel.MMDTopicsTransferable;
import com.igormaznitsa.mindmap.swing.panel.MindMapListener;
import com.igormaznitsa.mindmap.swing.panel.MindMapPanel;
import com.igormaznitsa.mindmap.swing.panel.ui.AbstractElement;
import com.igormaznitsa.mindmap.swing.panel.utils.KeyEventType;
import com.igormaznitsa.mindmap.swing.panel.utils.MindMapUtils;
import com.igormaznitsa.mindmap.swing.panel.utils.Utils;
import com.intellij.codeHighlighting.BackgroundEditorHighlighter;
import com.intellij.ide.CopyProvider;
import com.intellij.ide.CutProvider;
import com.intellij.ide.DataManager;
import com.intellij.ide.PasteProvider;
import com.intellij.ide.dnd.DnDDragStartBean;
import com.intellij.ide.dnd.TransferableWrapper;
import com.intellij.ide.structureView.StructureViewBuilder;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.event.DocumentAdapter;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.event.DocumentListener;
import com.intellij.openapi.fileEditor.*;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.xml.ui.Committable;
import com.intellij.util.xml.ui.UndoHelper;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.*;
import java.awt.event.*;
import java.awt.geom.Rectangle2D;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.StringReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ResourceBundle;
import static com.igormaznitsa.ideamindmap.utils.SwingUtils.safeSwing;
import static com.igormaznitsa.mindmap.swing.panel.StandardTopicAttribute.doesContainOnlyStandardAttributes;
import static com.igormaznitsa.mindmap.swing.panel.utils.Utils.assertSwingDispatchThread;
public class MindMapDocumentEditor implements AdjustmentListener, DocumentsEditor, MindMapController, MindMapListener, DropTargetListener, Committable, DataProvider, CopyProvider, CutProvider, PasteProvider {
private static final long serialVersionUID = -8185230144865144686L;
private static final Logger LOGGER = LoggerFactory.getLogger(MindMapDocumentEditor.class);
private static final ResourceBundle BUNDLE = java.util.ResourceBundle.getBundle("/i18n/Bundle");
private static final String FILELINK_ATTR_OPEN_IN_SYSTEM = "useSystem"; //NOI18N
private final JScrollPane mainScrollPane;
private final MindMapPanel mindMapPanel;
private final Project project;
private final VirtualFile file;
private final Document[] documents;
private boolean dragAcceptableType = false;
private final MindMapPanelControllerImpl panelController;
private final UndoHelper undoHelper;
private boolean firstLayouting = true;
private final DocumentListener documentListener;
public MindMapDocumentEditor(final Project project, final VirtualFile file) {
this.project = project;
this.file = file;
this.panelController = new MindMapPanelControllerImpl(this);
this.mindMapPanel = new MindMapPanel(panelController);
this.mindMapPanel.putTmpObject("project", project);
this.mindMapPanel.putTmpObject("editor", this);
this.mindMapPanel.addMindMapListener(this);
this.mainScrollPane = new JScrollPane(this.mindMapPanel); // NB! JBScrollPane sometime doesn't show scrollbars so that it replaced by swing panel
this.mainScrollPane.setWheelScrollingEnabled(true);
this.mainScrollPane.setAutoscrolls(true);
this.mindMapPanel.addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
mainScrollPane.getViewport().revalidate();
}
});
final Document document = FileDocumentManager.getInstance().getDocument(this.file);
this.documents = new Document[]{document};
this.mindMapPanel.setDropTarget(new DropTarget(this.mindMapPanel, this));
loadMindMapFromDocument();
this.undoHelper = new UndoHelper(this.project, this);
this.undoHelper.addWatchedDocument(getDocument());
this.documentListener = new DocumentAdapter() {
@Override
public void documentChanged(DocumentEvent e) {
loadMindMapFromDocument();
}
};
this.getDocument().addDocumentListener(this.documentListener);
DataManager.registerDataProvider(this.mainScrollPane, this);
this.mainScrollPane.getHorizontalScrollBar().addAdjustmentListener(this);
this.mainScrollPane.getVerticalScrollBar().addAdjustmentListener(this);
}
@Override
public void adjustmentValueChanged(AdjustmentEvent e) {
this.mindMapPanel.repaint();
}
@Override
public void onComponentElementsLayouted(@Nonnull final MindMapPanel mindMapPanel, @Nonnull final Graphics2D graphics2D) {
if (this.firstLayouting) {
this.firstLayouting = false;
centreToRoot();
}
}
public void centreToRoot() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
final Topic root = mindMapPanel.getModel().getRoot();
if (root != null) {
mindMapPanel.updateElementsAndSizeForCurrentGraphics(true, false);
topicToCentre(root);
}
}
});
}
@Override
public void onTopicCollapsatorClick(@Nonnull final MindMapPanel source, @Nonnull final Topic topic, final boolean beforeAction) {
if (!beforeAction) {
this.mindMapPanel.getModel().resetPayload();
topicToCentre(topic);
}
}
public void topicToCentre(@Nullable Topic topic) {
assertSwingDispatchThread();
if (topic != null) {
AbstractElement element = (AbstractElement) topic.getPayload();
if (element == null && this.mindMapPanel.updateElementsAndSizeForCurrentGraphics(true, true)) {
topic = this.mindMapPanel.getModel().findForPositionPath(topic.getPositionPath());
if (topic != null) {
element = (AbstractElement) topic.getPayload();
this.mainScrollPane.getViewport().doLayout();
}
}
if (element != null) {
final Rectangle2D bounds = element.getBounds();
final Dimension viewPortSize = mainScrollPane.getViewport().getExtentSize();
final int x = Math.max(0, (int) Math.round(bounds.getX() - (viewPortSize.getWidth() - bounds.getWidth()) / 2));
final int y = Math.max(0, (int) Math.round(bounds.getY() - (viewPortSize.getHeight() - bounds.getHeight()) / 2));
mainScrollPane.getViewport().setViewPosition(new Point(x, y));
}
}
}
@Nullable
public Document getDocument() {
return this.documents[0];
}
private void saveMindMapToDocument() {
if (!this.mindMapPanel.isDisposed()) {
final MindMap model = this.mindMapPanel.getModel();
final Document document = getDocument();
if (document != null && model != null) {
IdeaUtils.executeWriteAction(getProject(), document, new Runnable() {
@Override
public void run() {
document.setText(model.packToString());
}
});
}
}
}
private void loadMindMapFromDocument() {
final MindMapDocumentEditor editorIstance = this;
SwingUtils.safeSwing(new Runnable() {
@Override
public void run() {
final Document document = getDocument();
if (document != null) {
IdeaUtils.executeReadAction(getProject(), getDocument(), new Runnable() {
@Override
public void run() {
final String documentText = document.getText();
safeSwing(new Runnable() {
@Override
public void run() {
if (!mindMapPanel.isDisposed()) {
try {
mindMapPanel.setModel(new MindMap(editorIstance, new StringReader(documentText)));
} catch (Exception ex) {
LOGGER.error("Can't parse MindMap text", ex);
editorIstance.mindMapPanel.setErrorText("Can't parse mind map content");
}
}
}
});
}
});
CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() {
@Override
public void run() {
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
public void run() {
final String documentText = document.getText();
safeSwing(new Runnable() {
@Override
public void run() {
if (!mindMapPanel.isDisposed()) {
try {
mindMapPanel.setModel(new MindMap(editorIstance, new StringReader(documentText)));
} catch (Exception ex) {
LOGGER.error("Can't parse MindMap text", ex);
editorIstance.mindMapPanel.setErrorText("Can't parse mind map content");
}
}
}
});
}
});
}
}, null, null, document);
}
}
});
}
@Override
public Document[] getDocuments() {
return this.documents;
}
@Nonnull
@Override
public JComponent getComponent() {
return this.mainScrollPane;
}
@Nullable
@Override
public JComponent getPreferredFocusedComponent() {
return this.mainScrollPane;
}
@Nonnull
@Override
public String getName() {
return "nb-mm-editor";
}
@Nonnull
@Override
public FileEditorState getState(@Nonnull FileEditorStateLevel fileEditorStateLevel) {
return MindMapFileEditorState.DUMMY;
}
@Override
public void setState(@Nonnull FileEditorState fileEditorState) {
}
@Override
public boolean isModified() {
return FileDocumentManager.getInstance().isFileModified(this.file);
}
@Override
public boolean isValid() {
return true;
}
@Override
public void selectNotify() {
}
@Override
public void deselectNotify() {
}
@Override
public void addPropertyChangeListener(@Nonnull PropertyChangeListener propertyChangeListener) {
}
@Override
public void removePropertyChangeListener(@Nonnull PropertyChangeListener propertyChangeListener) {
}
@Nullable
@Override
public BackgroundEditorHighlighter getBackgroundHighlighter() {
return null;
}
@Nullable
@Override
public FileEditorLocation getCurrentLocation() {
return null;
}
@Nullable
@Override
public StructureViewBuilder getStructureViewBuilder() {
return null;
}
@Override
public void dispose() {
try {
this.mindMapPanel.dispose();
}finally {
this.getDocument().removeDocumentListener(this.documentListener);
DataManager.removeDataProvider(this.mainScrollPane);
}
}
@Nullable
@Override
public <T> T getUserData(@Nonnull Key<T> key) {
return null;
}
@Override
public <T> void putUserData(@Nonnull Key<T> key, @Nullable T t) {
}
@Override
public void onNonConsumedKeyEvent(@Nonnull final MindMapPanel source, @Nonnull final KeyEvent e, @Nonnull final KeyEventType type) {
if (type == KeyEventType.PRESSED && e.getModifiers() == 0 && (e.getKeyCode() == KeyEvent.VK_UP
|| e.getKeyCode() == KeyEvent.VK_LEFT
|| e.getKeyCode() == KeyEvent.VK_RIGHT
|| e.getKeyCode() == KeyEvent.VK_DOWN)) {
e.consume();
}
}
@Override
public boolean canBeDeletedSilently(@Nonnull MindMap mindMap, @Nonnull Topic topic) {
return topic.getText().isEmpty() && topic.getExtras().isEmpty() && doesContainOnlyStandardAttributes(topic);
}
@Override
public void onMindMapModelChanged(@Nonnull final MindMapPanel mindMapPanel) {
saveMindMapToDocument();
}
@Override
public void onMindMapModelRealigned(@Nonnull MindMapPanel mindMapPanel, @Nonnull Dimension dimension) {
this.mainScrollPane.getViewport().revalidate();
}
@Override
public void onScaledByMouse(@Nonnull final MindMapPanel source, @Nonnull final Point mousePoint, final double oldScale, final double newScale, final boolean beforeAction) {
if (!beforeAction && Double.compare(oldScale, newScale) != 0) {
final JViewport viewport = this.mainScrollPane.getViewport();
final Point viewPos = viewport.getViewPosition();
final int dx = mousePoint.x - viewPos.x;
final int dy = mousePoint.y - viewPos.y;
final double scaleRelation = newScale / oldScale;
final int newMouseX = (int) (Math.round(mousePoint.x * scaleRelation));
final int newMouseY = (int) (Math.round(mousePoint.y * scaleRelation));
viewport.doLayout();
viewport.setViewPosition(new Point(Math.max(0, newMouseX - dx), Math.max(0, newMouseY - dy)));
}
}
@Override
public void onEnsureVisibilityOfTopic(@Nonnull MindMapPanel mindMapPanel, @Nonnull final Topic topic) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
if (topic == null) {
return;
}
final AbstractElement element = (AbstractElement) topic.getPayload();
if (element == null) {
return;
}
final Rectangle2D orig = element.getBounds();
if (orig == null) {
return;
}
final int GAP = 30;
final Rectangle bounds = orig.getBounds();
bounds.setLocation(Math.max(0, bounds.x - GAP), Math.max(0, bounds.y - GAP));
bounds.setSize(bounds.width + GAP * 2, bounds.height + GAP * 2);
final JViewport viewport = mainScrollPane.getViewport();
final Rectangle visible = viewport.getViewRect();
if (visible.contains(bounds)) {
return;
}
bounds.setLocation(bounds.x - visible.x, bounds.y - visible.y);
viewport.scrollRectToVisible(bounds);
}
});
}
@Nullable
public VirtualFile findRootFolderForEditedFile() {
final Module module = IdeaUtils.findModuleForFile(this.project, this.file);
final VirtualFile rootFolder;
if (module == null) {
rootFolder = this.project.getBaseDir();
} else {
rootFolder = IdeaUtils.findPotentialRootFolderForModule(module);
}
return rootFolder;
}
@Override
public void onClickOnExtra(@Nonnull final MindMapPanel source, final int modifiers, final int clicks, @Nonnull final Topic topic, @Nonnull final Extra<?> extra) {
if (clicks > 1) {
switch (extra.getType()) {
case FILE: {
final MMapURI fileURI = (MMapURI) extra.getValue();
final boolean flagOpenFileLinkInSystemViewer = Boolean.parseBoolean(fileURI.getParameters().getProperty(FILELINK_ATTR_OPEN_IN_SYSTEM, "false"));
final VirtualFile rootFolder = findRootFolderForEditedFile();
final VirtualFile theFile = LocalFileSystem.getInstance().findFileByIoFile(fileURI.asFile(IdeaUtils.vfile2iofile(rootFolder)));
if (theFile == null) {
// file not found
LOGGER.warn("Can't find FileObject for " + fileURI);
getDialogProvider().msgError(String.format(BUNDLE.getString("MMDGraphEditor.onClickExtra.errorCanfFindFile"), fileURI.toString()));
} else if (VfsUtilCore.isAncestor(rootFolder, theFile, false)) {
// inside project
if (flagOpenFileLinkInSystemViewer) {
SelectIn.SYSTEM.open(this, theFile);
} else {
SelectIn.IDE.open(this, theFile);
}
} else {
// outside project
if (flagOpenFileLinkInSystemViewer) {
SelectIn.SYSTEM.open(this, theFile);
} else {
SelectIn.IDE.open(this, theFile);
}
}
}
break;
case LINK: {
final MMapURI uri = ((ExtraLink) extra).getValue();
if (!IdeaUtils.browseURI(uri.asURI(), isUseInsideBrowser())) { //NOI18N
getDialogProvider().msgError(String.format(BUNDLE.getString("MMDGraphEditor.onClickOnExtra.msgCantBrowse"), uri.toString()));
}
}
break;
case NOTE: {
editTextForTopic(topic);
}
break;
case TOPIC: {
final Topic theTopic = this.mindMapPanel.getModel().findTopicForLink((ExtraTopic) extra);
if (theTopic == null) {
// not presented
getDialogProvider().msgWarn(BUNDLE.getString("MMDGraphEditor.onClickOnExtra.msgCantFindTopic"));
} else {
// detected
this.mindMapPanel.focusTo(theTopic);
}
}
break;
default:
throw new Error("Unexpected type " + extra);
}
}
}
@Nullable
public final MindMapFacet findFacet() {
return MindMapFacet.getInstance(IdeaUtils.findModuleForFile(this.project, this.file));
}
boolean isUseInsideBrowser() {
final MindMapFacet facet = findFacet();
return facet != null && facet.getConfiguration().isUseInsideBrowser();
}
boolean isMakeRelativePath() {
final MindMapFacet facet = findFacet();
return facet == null || facet.getConfiguration().isMakeRelativePath();
}
@Override
public void onChangedSelection(@Nonnull final MindMapPanel mindMapPanel, @Nonnull @MustNotContainNull final Topic[] topics) {
}
public DialogProvider getDialogProvider() {
return this.panelController.getDialogProvider();
}
@Override
public boolean allowedRemovingOfTopics(@Nonnull final MindMapPanel mindMapPanel, @Nonnull @MustNotContainNull final Topic[] topics) {
boolean topicsNotImportant = true;
for (final Topic t : topics) {
topicsNotImportant &= t.canBeLost();
if (!topicsNotImportant) {
break;
}
}
final boolean result;
if (topicsNotImportant) {
result = true;
} else {
result = this.getDialogProvider().msgConfirmYesNo(BUNDLE.getString("MMDGraphEditor.allowedRemovingOfTopics,title"),
String.format(BUNDLE.getString("MMDGraphEditor.allowedRemovingOfTopics.message"), topics.length));
}
return result;
}
private void editTextForTopic(final Topic topic) {
final ExtraNote note = (ExtraNote) topic.getExtras().get(Extra.ExtraType.NOTE);
final String result;
if (note == null) {
// create new
result = IdeaUtils
.editText(this.project, String.format(BUNDLE.getString("MMDGraphEditor.editTextForTopic.dlfAddNoteTitle"), Utils.makeShortTextVersion(topic.getText(), 16)), ""); //NOI18N
} else {
// edit
result = IdeaUtils
.editText(this.project, String.format(BUNDLE.getString("MMDGraphEditor.editTextForTopic.dlgEditNoteTitle"), Utils.makeShortTextVersion(topic.getText(), 16)),
note.getValue());
}
if (result != null) {
if (result.isEmpty()) {
topic.removeExtra(Extra.ExtraType.NOTE);
} else {
topic.setExtra(new ExtraNote(result));
}
this.mindMapPanel.invalidate();
this.mindMapPanel.repaint();
onMindMapModelChanged(this.mindMapPanel);
}
this.mainScrollPane.requestFocus();
}
@Override
public void commit() {
loadMindMapFromDocument();
}
@Override
public void reset() {
loadMindMapFromDocument();
}
@Override
public void dragEnter(DropTargetDragEvent dtde) {
this.dragAcceptableType = DnDUtils.isFileOrLinkOrText(dtde);
if (!this.dragAcceptableType) {
dtde.rejectDrag();
}
}
@Override
public void dragOver(DropTargetDragEvent dtde) {
if (acceptOrRejectDragging(dtde)) {
dtde.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
} else {
dtde.rejectDrag();
}
}
@Override
public void dropActionChanged(DropTargetDragEvent dtde) {
}
@Override
public void dragExit(DropTargetEvent dte) {
}
@SuppressWarnings("unchecked")
@Nullable
private File extractDropFile(@Nonnull final DropTargetDropEvent dtde) throws Exception {
try {
java.util.List<File> files = null;
final Object objectToDrop = dtde.getTransferable().getTransferData(DataFlavor.javaFileListFlavor);
if (objectToDrop instanceof DnDDragStartBean) {
final Object wrapper = ((DnDDragStartBean) objectToDrop).getAttachedObject();
if (wrapper instanceof TransferableWrapper) {
files = ((TransferableWrapper) wrapper).asFileList();
}
} else if (objectToDrop instanceof java.util.List) {
files = (java.util.List<File>) objectToDrop;
}
return files == null || files.isEmpty() ? null : files.get(0);
} catch (UnsupportedFlavorException ex) {
return null;
}
}
@SuppressWarnings("unchecked")
@Override
public void drop(final DropTargetDropEvent dtde) {
dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
File dropFile = null;
String extractedLink;
String extractedText = null;
URI decodedLink = null;
try {
dropFile = extractDropFile(dtde);
extractedLink = DnDUtils.extractDropLink(dtde);
extractedText = DnDUtils.extractDropNote(dtde);
decodedLink = null;
if (extractedLink != null) {
try {
decodedLink = new URI(extractedLink);
} catch (final URISyntaxException ex) {
decodedLink = null;
}
}
dtde.dropComplete(true);
} catch (Exception ex) {
LOGGER.error("Can't complete DnD operation for error", ex);
dtde.dropComplete(false);
}
final AbstractElement element = this.mindMapPanel.findTopicUnderPoint(dtde.getLocation());
if (dropFile != null) {
decodedLink = DnDUtils.extractUrlLinkFromFile(dropFile);
if (decodedLink == null) {
addFileToElement(dropFile, element);
} else {
addURItoElement(decodedLink, element);
}
} else if (decodedLink != null) {
addURItoElement(decodedLink, element);
} else if (extractedText != null) {
addNoteToElement(extractedText, element);
}
}
private void addURItoElement(@Nonnull final URI uri, @Nullable final AbstractElement element) {
if (element != null) {
final Topic topic = element.getModel();
final MMapURI mmapUri = new MMapURI(uri);
if (topic.getExtras().containsKey(Extra.ExtraType.LINK)) {
if (!getDialogProvider().msgConfirmOkCancel(BUNDLE.getString("MMDGraphEditor.addDataObjectLinkToElement.confirmTitle"), BUNDLE.getString("MMDGraphEditor.addDataObjectLinkToElement.confirmMsg"))) {
return;
}
}
topic.setExtra(new ExtraLink(mmapUri));
this.mindMapPanel.invalidate();
this.mindMapPanel.repaint();
onMindMapModelChanged(this.mindMapPanel);
}
}
private void addNoteToElement(@Nonnull final String text, @Nullable final AbstractElement element) {
if (element != null) {
final Topic topic = element.getModel();
if (topic.getExtras().containsKey(Extra.ExtraType.NOTE)) {
if (!getDialogProvider().msgConfirmOkCancel(BUNDLE.getString("MMDGraphEditor.addDataObjectTextToElement.confirmTitle"), BUNDLE.getString("MMDGraphEditor.addDataObjectTextToElement.confirmMsg"))) {
return;
}
}
topic.setExtra(new ExtraNote(text));
this.mindMapPanel.invalidate();
this.mindMapPanel.repaint();
onMindMapModelChanged(this.mindMapPanel);
}
}
private void addFileToElement(final File file, final AbstractElement element) {
if (element != null) {
final Topic topic = element.getModel();
final VirtualFile theFile = VfsUtil.findFileByIoFile(file, true);
if (theFile != null) {
final File rootFolder = IdeaUtils.vfile2iofile(findRootFolderForEditedFile());
final File theFileIo = IdeaUtils.vfile2iofile(theFile);
final MMapURI theURI = isMakeRelativePath() ?
new MMapURI(rootFolder, theFileIo, null) :
new MMapURI(null, theFileIo, null); //NOI18N
if (topic.getExtras().containsKey(Extra.ExtraType.FILE)) {
if (!getDialogProvider()
.msgConfirmOkCancel(BUNDLE.getString("MMDGraphEditor.addDataObjectToElement.confirmTitle"), BUNDLE.getString("MMDGraphEditor.addDataObjectToElement.confirmMsg"))) {
return;
}
}
topic.setExtra(new ExtraFile(theURI));
this.mindMapPanel.invalidate();
this.mindMapPanel.repaint();
onMindMapModelChanged(this.mindMapPanel);
} else {
LOGGER.warn("Can't find VirtualFile for " + file);
}
}
}
protected boolean acceptOrRejectDragging(final DropTargetDragEvent dtde) {
final int dropAction = dtde.getDropAction();
boolean result = false;
if (this.dragAcceptableType && (dropAction & DnDConstants.ACTION_COPY_OR_MOVE) != 0 && this.mindMapPanel.findTopicUnderPoint(dtde.getLocation()) != null) {
result = true;
}
return result;
}
public MindMapPanel getMindMapPanel() {
return this.mindMapPanel;
}
public Project getProject() {
return this.project;
}
public void refreshConfiguration() {
this.mindMapPanel.refreshConfiguration();
this.mindMapPanel.revalidate();
this.mindMapPanel.repaint();
}
@org.jetbrains.annotations.Nullable
@Override
public Object getData(@NonNls String s) {
if (PlatformDataKeys.COPY_PROVIDER.is(s) || PlatformDataKeys.CUT_PROVIDER.is(s) || PlatformDataKeys.PASTE_PROVIDER.is(s)) {
return this;
}
return null;
}
@Override
public void performCopy(@NotNull DataContext dataContext) {
this.mindMapPanel.copyTopicsToClipboard(false, MindMapUtils.removeSuccessorsAndDuplications(this.mindMapPanel.getSelectedTopics()));
}
@Override
public boolean isCopyEnabled(@NotNull DataContext dataContext) {
return this.mindMapPanel.hasSelectedTopics();
}
@Override
public boolean isCopyVisible(@NotNull DataContext dataContext) {
return true;
}
@Override
public void performCut(@NotNull DataContext dataContext) {
this.mindMapPanel.copyTopicsToClipboard(true, MindMapUtils.removeSuccessorsAndDuplications(this.mindMapPanel.getSelectedTopics()));
}
@Override
public boolean isCutEnabled(@NotNull DataContext dataContext) {
return this.mindMapPanel.hasSelectedTopics();
}
@Override
public boolean isCutVisible(@NotNull DataContext dataContext) {
return true;
}
@Override
public void performPaste(@NotNull DataContext dataContext) {
this.mindMapPanel.pasteTopicsFromClipboard();
}
@Override
public boolean isPastePossible(@NotNull DataContext dataContext) {
return isPasteEnabled(dataContext);
}
@Override
public boolean isPasteEnabled(@NotNull DataContext dataContext) {
boolean result = false;
if (this.mindMapPanel.hasSelectedTopics()) {
result = Toolkit.getDefaultToolkit().getSystemClipboard().isDataFlavorAvailable(MMDTopicsTransferable.MMD_DATA_FLAVOR);
}
return result;
}
}