GraphicalEditorに限らずですが、FileEditorを自作している時は、Editorで表示しているファイルが削除された時、名前を変更された時のイベントを拾って整合性を合わせてあげる必要があります。
ファイルを削除された時。→ EditorをCloseする必要がある。
ファイルの名前が変わった時。→ Editorの名前をファイル名にしているのであれば、変更する必要がある。
これらのイベントの取得は、IResourceChangeListenerを使ってリソースの変更のタイミングを取得するのですが、このリスナーを追加する場所は Workspaceです。
ResourcesPlugin.getWorkspace().addResourceChangeListener(new MyResourceChangeLisnter());
ということで、自分のEditor以外でのリソース変更のタイミングも飛んでくるようになります。
ここで! AIR GEARで不具合が発生していました(涙)
GraphicalEditorではAdobeAIRのMXMLファイルの内容を表示しているのですが、MXMLファイルを編集するのは、その他のEditor(TextEditorとかXMLEditorとか)もアリ。
その他のEditorで変更された場合、表示中のGraphicalEditorの表示も最新にする必要があるので、このResourceChangeLisnterで受け取ったタイミングで、どのファイルが変更されたか?を確認せずに「ファイルの内容を読込みしてGUIを生成し直す」という処理を入れちゃってた。
元のソース
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public void resourceChanged(final IResourceChangeEvent event) { | |
if (event.getType() == IResourceChangeEvent.POST_CHANGE) { | |
Display.getDefault().asyncExec(new Runnable() { | |
public void run() { | |
IFile file = ((IFileEditorInput) input).getFile(); | |
if (!file.exists()) { | |
// ファイル名が変更されていたら、EditorをCloseする | |
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); | |
page.closeEditor(VisualMXMLEditor.this, false); | |
} else { | |
if (!getPartName().equals(file.getName())) { | |
//ファイル名が変わっていたらEditorPartの名前も変更する | |
setPartName(file.getName()); | |
} | |
// GraphicalEditorをファイルの情報から読込み直し | |
refreshGraphicalEditor(); | |
} | |
} | |
}); | |
} | |
} |
どのファイルのリソースが修正されたか? は IResourceChangeEventのgetDelta()に含まれているようです。
ということで、修正後のソース。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public void resourceChanged(final IResourceChangeEvent event) { | |
if (event.getType() == IResourceChangeEvent.POST_CHANGE) { | |
IResourceDelta rootDelta = event.getDelta(); | |
final IEditorInput input = getEditorInput(); | |
IFile file = ((IFileEditorInput) input).getFile(); | |
IPath filePath = file.getFullPath(); | |
IResourceDelta targetDelta = rootDelta.findMember(filePath); | |
if (targetDelta != null) { | |
Display.getDefault().asyncExec(new Runnable() { | |
public void run() { | |
IFile file = ((IFileEditorInput) input).getFile(); | |
if (!file.exists()) { | |
// ファイル名が変更されていたら、EditorをCloseする | |
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); | |
page.closeEditor(VisualMXMLEditor.this, false); | |
} else { | |
if (!getPartName().equals(file.getName())) { | |
//ファイル名が変わっていたらEditorPartの名前も変更する | |
setPartName(file.getName()); | |
} | |
// GraphicalEditorをファイルの情報から読込み直し | |
refreshGraphicalViewer(); | |
} | |
} | |
}); | |
} | |
} | |
} |
ですが、このままではファイル名が変更された時には、Editorが終了してしまう様子。
ファイル名の変更=ファイルの移動としてちゃんとチェックをしてあげないとダメみたい。
で、再度変更ソース。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public void resourceChanged(final IResourceChangeEvent event) { | |
if (event.getType() != IResourceChangeEvent.POST_CHANGE | |
|| !(getEditorInput() instanceof IFileEditorInput)) { | |
return; | |
} | |
IResourceDelta rootDelta = event.getDelta(); | |
IFile file = ((IFileEditorInput) getEditorInput()).getFile(); | |
IPath filePath = file.getFullPath(); | |
IResourceDelta delta = rootDelta.findMember(filePath); | |
if (delta == null) { | |
return; | |
} | |
Runnable changeRunnable = null; | |
if (delta.getKind() == IResourceDelta.REMOVED) { | |
if ((IResourceDelta.MOVED_TO & delta.getFlags()) != 0) { | |
IPath path = delta.getMovedToPath(); | |
final IFile newFile = delta.getResource().getWorkspace().getRoot().getFile(path); | |
if (newFile != null) { | |
changeRunnable = new Runnable() { | |
public void run() { | |
setInput(new FileEditorInput(newFile)); | |
setPartName(getEditorInput().getName()); | |
} | |
}; | |
} | |
} else { | |
changeRunnable = new Runnable() { | |
public void run() { | |
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); | |
page.closeEditor(VisualMXMLEditor.this, false); | |
} | |
}; | |
} | |
} else if (delta.getKind() == IResourceDelta.CHANGED) { | |
changeRunnable = new Runnable() { | |
public void run() { | |
refreshGraphicalViewer(); | |
} | |
}; | |
} | |
if (changeRunnable != null) { | |
getSite().getShell().getDisplay().asyncExec(changeRunnable); | |
} | |
} |
これで何となく動いているようだ。
ファイルをフォルダ移動した時、Eclipse本体のWindowタイトルに表示されるファイルパスが移動先のものにならない...というのを除いて。
んー まぁそこは...今度みます。。