Delete 193 bunch files
This commit is contained in:
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* 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 org.jetbrains.kotlin.idea.actions
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnAction
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys
|
||||
import com.intellij.openapi.wm.ToolWindowAnchor
|
||||
import com.intellij.openapi.wm.ToolWindowManager
|
||||
import com.intellij.ui.content.ContentFactory
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.idea.KotlinIcons
|
||||
import org.jetbrains.kotlin.idea.internal.KotlinBytecodeToolWindow
|
||||
|
||||
class ShowKotlinBytecodeAction : AnAction() {
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val project = e.project ?: return
|
||||
val toolWindowManager = ToolWindowManager.getInstance(project)
|
||||
var toolWindow = toolWindowManager.getToolWindow(TOOLWINDOW_ID)
|
||||
if (toolWindow == null) {
|
||||
toolWindow = toolWindowManager.registerToolWindow(TOOLWINDOW_ID, false, ToolWindowAnchor.RIGHT)
|
||||
toolWindow.icon = KotlinIcons.SMALL_LOGO_13
|
||||
|
||||
val contentManager = toolWindow.contentManager
|
||||
val contentFactory = ContentFactory.SERVICE.getInstance()
|
||||
contentManager.addContent(contentFactory.createContent(KotlinBytecodeToolWindow(project, toolWindow), "", false))
|
||||
}
|
||||
toolWindow.activate(null)
|
||||
}
|
||||
|
||||
override fun update(e: AnActionEvent) {
|
||||
val file = e.getData(CommonDataKeys.PSI_FILE)
|
||||
e.presentation.isEnabled = e.project != null && file?.fileType == KotlinFileType.INSTANCE
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TOOLWINDOW_ID = "Kotlin Bytecode"
|
||||
}
|
||||
}
|
||||
-284
@@ -1,284 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* 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 org.jetbrains.kotlin.idea.scratch.output
|
||||
|
||||
import com.intellij.execution.filters.OpenFileHyperlinkInfo
|
||||
import com.intellij.execution.impl.ConsoleViewImpl
|
||||
import com.intellij.execution.runners.ExecutionUtil
|
||||
import com.intellij.execution.ui.ConsoleViewContentType
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.TransactionGuard
|
||||
import com.intellij.openapi.command.WriteCommandAction
|
||||
import com.intellij.openapi.editor.ex.EditorEx
|
||||
import com.intellij.openapi.fileTypes.PlainTextFileType
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.wm.ToolWindow
|
||||
import com.intellij.openapi.wm.ToolWindowAnchor
|
||||
import com.intellij.openapi.wm.ToolWindowFactory
|
||||
import com.intellij.openapi.wm.ToolWindowManager
|
||||
import com.intellij.psi.PsiFile
|
||||
import org.jetbrains.kotlin.idea.scratch.ScratchExpression
|
||||
import org.jetbrains.kotlin.idea.scratch.ScratchFile
|
||||
import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||
|
||||
/**
|
||||
* Method to retrieve shared instance of scratches ToolWindow output handler.
|
||||
*
|
||||
* [releaseToolWindowHandler] must be called for every output handler received from this method.
|
||||
*
|
||||
* Can be called from EDT only.
|
||||
*
|
||||
* @return new toolWindow output handler if one does not exist, otherwise returns the existing one. When application in test mode,
|
||||
* returns [TestOutputHandler].
|
||||
*/
|
||||
fun requestToolWindowHandler(): ScratchOutputHandler {
|
||||
return if (ApplicationManager.getApplication().isUnitTestMode) {
|
||||
TestOutputHandler
|
||||
} else {
|
||||
ScratchToolWindowHandlerKeeper.requestOutputHandler()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be called once with the output handler received from the [requestToolWindowHandler] call.
|
||||
*
|
||||
* When release is called for every request, the output handler is actually disposed.
|
||||
*
|
||||
* When application in test mode, does nothing.
|
||||
*
|
||||
* Can be called from EDT only.
|
||||
*/
|
||||
fun releaseToolWindowHandler(scratchOutputHandler: ScratchOutputHandler) {
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode) {
|
||||
ScratchToolWindowHandlerKeeper.releaseOutputHandler(scratchOutputHandler)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements logic of shared pointer for the toolWindow output handler.
|
||||
*
|
||||
* Not thread safe! Can be used only from the EDT.
|
||||
*/
|
||||
private object ScratchToolWindowHandlerKeeper {
|
||||
private var toolWindowHandler: ScratchOutputHandler? = null
|
||||
private var toolWindowDisposable = Disposer.newDisposable()
|
||||
private var counter = 0
|
||||
|
||||
fun requestOutputHandler(): ScratchOutputHandler {
|
||||
if (counter == 0) {
|
||||
toolWindowHandler = ToolWindowScratchOutputHandler(toolWindowDisposable)
|
||||
}
|
||||
|
||||
counter += 1
|
||||
return toolWindowHandler!!
|
||||
}
|
||||
|
||||
fun releaseOutputHandler(scratchOutputHandler: ScratchOutputHandler) {
|
||||
require(counter > 0) { "Counter is $counter, nothing to release!" }
|
||||
require(toolWindowHandler === scratchOutputHandler) { "$scratchOutputHandler differs from stored $toolWindowHandler" }
|
||||
|
||||
counter -= 1
|
||||
if (counter == 0) {
|
||||
Disposer.dispose(toolWindowDisposable)
|
||||
toolWindowDisposable = Disposer.newDisposable()
|
||||
toolWindowHandler = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ToolWindowScratchOutputHandler(private val parentDisposable: Disposable) : ScratchOutputHandlerAdapter() {
|
||||
|
||||
override fun handle(file: ScratchFile, expression: ScratchExpression, output: ScratchOutput) {
|
||||
printToConsole(file) {
|
||||
val psiFile = file.getPsiFile()
|
||||
if (psiFile != null) {
|
||||
printHyperlink(
|
||||
getLineInfo(psiFile, expression),
|
||||
OpenFileHyperlinkInfo(
|
||||
project,
|
||||
psiFile.virtualFile,
|
||||
expression.lineStart,
|
||||
),
|
||||
)
|
||||
print(" ", ConsoleViewContentType.NORMAL_OUTPUT)
|
||||
}
|
||||
print(output.text, output.type.convert())
|
||||
}
|
||||
}
|
||||
|
||||
override fun error(file: ScratchFile, message: String) {
|
||||
printToConsole(file) {
|
||||
print(message, ConsoleViewContentType.ERROR_OUTPUT)
|
||||
}
|
||||
}
|
||||
|
||||
private fun printToConsole(file: ScratchFile, print: ConsoleViewImpl.() -> Unit) {
|
||||
ApplicationManager.getApplication().invokeLater {
|
||||
val project = file.project.takeIf { !it.isDisposed } ?: return@invokeLater
|
||||
|
||||
val toolWindow = getToolWindow(project) ?: createToolWindow(file)
|
||||
|
||||
val contents = toolWindow.contentManager.contents
|
||||
for (content in contents) {
|
||||
val component = content.component
|
||||
if (component is ConsoleViewImpl) {
|
||||
component.print()
|
||||
component.print("\n", ConsoleViewContentType.NORMAL_OUTPUT)
|
||||
}
|
||||
}
|
||||
|
||||
toolWindow.setAvailable(true, null)
|
||||
|
||||
if (!file.options.isInteractiveMode) {
|
||||
toolWindow.show(null)
|
||||
}
|
||||
|
||||
toolWindow.icon = ExecutionUtil.getLiveIndicator(scratchIcon())
|
||||
}
|
||||
}
|
||||
|
||||
override fun clear(file: ScratchFile) {
|
||||
ApplicationManager.getApplication().invokeLater {
|
||||
val toolWindow = getToolWindow(file.project) ?: return@invokeLater
|
||||
val contents = toolWindow.contentManager.contents
|
||||
for (content in contents) {
|
||||
val component = content.component
|
||||
if (component is ConsoleViewImpl) {
|
||||
component.clear()
|
||||
}
|
||||
}
|
||||
|
||||
if (!file.options.isInteractiveMode) {
|
||||
toolWindow.hide(null)
|
||||
}
|
||||
|
||||
toolWindow.icon = scratchIcon()
|
||||
}
|
||||
}
|
||||
|
||||
private fun ScratchOutputType.convert() = when (this) {
|
||||
ScratchOutputType.OUTPUT -> ConsoleViewContentType.SYSTEM_OUTPUT
|
||||
ScratchOutputType.RESULT -> ConsoleViewContentType.NORMAL_OUTPUT
|
||||
ScratchOutputType.ERROR -> ConsoleViewContentType.ERROR_OUTPUT
|
||||
}
|
||||
|
||||
private fun getToolWindow(project: Project): ToolWindow? {
|
||||
val toolWindowManager = ToolWindowManager.getInstance(project)
|
||||
return toolWindowManager.getToolWindow(ScratchToolWindowFactory.ID)
|
||||
}
|
||||
|
||||
private fun createToolWindow(file: ScratchFile): ToolWindow {
|
||||
val project = file.project
|
||||
val toolWindowManager = ToolWindowManager.getInstance(project)
|
||||
toolWindowManager.registerToolWindow(ScratchToolWindowFactory.ID, true, ToolWindowAnchor.BOTTOM)
|
||||
val window = toolWindowManager.getToolWindow(ScratchToolWindowFactory.ID)
|
||||
ScratchToolWindowFactory().createToolWindowContent(project, window)
|
||||
|
||||
Disposer.register(
|
||||
parentDisposable,
|
||||
Disposable {
|
||||
toolWindowManager.unregisterToolWindow(ScratchToolWindowFactory.ID)
|
||||
},
|
||||
)
|
||||
|
||||
return window
|
||||
}
|
||||
}
|
||||
|
||||
private fun scratchIcon() = PlainTextFileType.INSTANCE.icon
|
||||
|
||||
private fun getLineInfo(psiFile: PsiFile, expression: ScratchExpression) =
|
||||
"${psiFile.name}:${expression.lineStart + 1}"
|
||||
|
||||
private class ScratchToolWindowFactory : ToolWindowFactory {
|
||||
companion object {
|
||||
const val ID = "Scratch Output"
|
||||
}
|
||||
|
||||
override fun createToolWindowContent(project: Project, toolWindow: ToolWindow) {
|
||||
val consoleView = ConsoleViewImpl(project, true)
|
||||
toolWindow.isToHideOnEmptyContent = true
|
||||
toolWindow.icon = scratchIcon()
|
||||
toolWindow.hide(null)
|
||||
|
||||
val contentManager = toolWindow.contentManager
|
||||
val content = contentManager.factory.createContent(consoleView.component, null, false)
|
||||
contentManager.addContent(content)
|
||||
val editor = consoleView.editor
|
||||
if (editor is EditorEx) {
|
||||
editor.isRendererMode = true
|
||||
}
|
||||
|
||||
Disposer.register(project, consoleView)
|
||||
}
|
||||
}
|
||||
|
||||
private object TestOutputHandler : ScratchOutputHandlerAdapter() {
|
||||
private val errors = arrayListOf<String>()
|
||||
private val inlays = arrayListOf<Pair<ScratchExpression, String>>()
|
||||
|
||||
override fun handle(file: ScratchFile, expression: ScratchExpression, output: ScratchOutput) {
|
||||
inlays.add(expression to output.text)
|
||||
}
|
||||
|
||||
override fun error(file: ScratchFile, message: String) {
|
||||
errors.add(message)
|
||||
}
|
||||
|
||||
override fun onFinish(file: ScratchFile) {
|
||||
TransactionGuard.submitTransaction(
|
||||
file.project,
|
||||
Runnable {
|
||||
val psiFile = file.getPsiFile()
|
||||
?: error(
|
||||
"PsiFile cannot be found for scratch to render inlays in tests:\n" +
|
||||
"project.isDisposed = ${file.project.isDisposed}\n" +
|
||||
"inlays = ${inlays.joinToString { it.second }}\n" +
|
||||
"errors = ${errors.joinToString()}",
|
||||
)
|
||||
|
||||
if (inlays.isNotEmpty()) {
|
||||
testPrint(
|
||||
psiFile,
|
||||
inlays.map { (expression, text) ->
|
||||
"/** ${getLineInfo(psiFile, expression)} $text */"
|
||||
},
|
||||
)
|
||||
inlays.clear()
|
||||
}
|
||||
|
||||
if (errors.isNotEmpty()) {
|
||||
testPrint(psiFile, listOf(errors.joinToString(prefix = "/** ", postfix = " */")))
|
||||
errors.clear()
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private fun testPrint(file: PsiFile, comments: List<String>) {
|
||||
WriteCommandAction.runWriteCommandAction(file.project) {
|
||||
for (comment in comments) {
|
||||
file.addAfter(
|
||||
KtPsiFactory(file.project).createComment(comment),
|
||||
file.lastChild,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-487
@@ -1,487 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.scratch.ui;
|
||||
|
||||
|
||||
import com.intellij.codeHighlighting.BackgroundEditorHighlighter;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.structureView.StructureViewBuilder;
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.editor.ex.EditorGutterComponentEx;
|
||||
import com.intellij.openapi.fileEditor.*;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.UserDataHolderBase;
|
||||
import com.intellij.openapi.wm.IdeFocusManager;
|
||||
import com.intellij.ui.JBSplitter;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.idea.KotlinJvmBundle;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Two panel editor with three states: Editor, Preview and Editor with Preview.
|
||||
* Based on SplitFileEditor by Valentin Fondaratov
|
||||
* <p/>
|
||||
* <b>NOTE:</b> This class is a copy of {@link com.intellij.openapi.fileEditor.TextEditorWithPreview} from the most recent intellij-community
|
||||
* repository. We cannot use bundled version of this class because it doesn't yet have customization methods
|
||||
* (namely {@link TextEditorWithPreview#createLeftToolbarActionGroup()}).
|
||||
* <p/>
|
||||
* {@link SplitEditorToolbar} is also copied from the platform.
|
||||
* <p/>
|
||||
* This class also may have some minimal customizations to allow tracking when its layout have been changed. In the future we hope to
|
||||
* remove this copied class entirely and to use the bundled version.
|
||||
*/
|
||||
public class TextEditorWithPreview extends UserDataHolderBase implements FileEditor {
|
||||
protected final TextEditor myEditor;
|
||||
protected final FileEditor myPreview;
|
||||
@NotNull
|
||||
private final MyListenersMultimap myListenersGenerator = new MyListenersMultimap();
|
||||
private Layout myLayout;
|
||||
private JComponent myComponent;
|
||||
private SplitEditorToolbar myToolbarWrapper;
|
||||
private final String myName;
|
||||
|
||||
public TextEditorWithPreview(@NotNull TextEditor editor, @NotNull FileEditor preview, @NotNull String editorName) {
|
||||
myEditor = editor;
|
||||
myPreview = preview;
|
||||
myName = editorName;
|
||||
}
|
||||
|
||||
public TextEditorWithPreview(@NotNull TextEditor editor, @NotNull FileEditor preview) {
|
||||
this(editor, preview, "TextEditorWithPreview");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BackgroundEditorHighlighter getBackgroundHighlighter() {
|
||||
return myEditor.getBackgroundHighlighter();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public FileEditorLocation getCurrentLocation() {
|
||||
return myEditor.getCurrentLocation();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public StructureViewBuilder getStructureViewBuilder() {
|
||||
return myEditor.getStructureViewBuilder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
Disposer.dispose(myEditor);
|
||||
Disposer.dispose(myPreview);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectNotify() {
|
||||
myEditor.selectNotify();
|
||||
myPreview.selectNotify();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deselectNotify() {
|
||||
myEditor.deselectNotify();
|
||||
myPreview.deselectNotify();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JComponent getComponent() {
|
||||
if (myComponent == null) {
|
||||
final JBSplitter splitter = new JBSplitter(false, 0.5f, 0.15f, 0.85f);
|
||||
splitter.setSplitterProportionKey(getSplitterProportionKey());
|
||||
splitter.setFirstComponent(myEditor.getComponent());
|
||||
splitter.setSecondComponent(myPreview.getComponent());
|
||||
splitter.setDividerWidth(3);
|
||||
|
||||
myToolbarWrapper = createMarkdownToolbarWrapper(splitter);
|
||||
Disposer.register(this, myToolbarWrapper);
|
||||
|
||||
if (myLayout == null) {
|
||||
String lastUsed = PropertiesComponent.getInstance().getValue(getLayoutPropertyName());
|
||||
setLayout(Layout.fromName(lastUsed, Layout.SHOW_EDITOR_AND_PREVIEW));
|
||||
}
|
||||
adjustEditorsVisibility();
|
||||
|
||||
myComponent = JBUI.Panels.simplePanel(splitter).addToTop(myToolbarWrapper);
|
||||
}
|
||||
return myComponent;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private SplitEditorToolbar createMarkdownToolbarWrapper (@NotNull JComponent targetComponentForActions) {
|
||||
final ActionToolbar leftToolbar = createToolbar();
|
||||
if (leftToolbar != null) {
|
||||
leftToolbar.setTargetComponent(targetComponentForActions);
|
||||
leftToolbar.setReservePlaceAutoPopupIcon(false);
|
||||
}
|
||||
|
||||
final ActionToolbar rightToolbar = createRightToolbar();
|
||||
rightToolbar.setTargetComponent(targetComponentForActions);
|
||||
rightToolbar.setReservePlaceAutoPopupIcon(false);
|
||||
|
||||
return new SplitEditorToolbar(leftToolbar, rightToolbar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setState(@NotNull FileEditorState state) {
|
||||
if (state instanceof MyFileEditorState) {
|
||||
final MyFileEditorState compositeState = (MyFileEditorState)state;
|
||||
if (compositeState.getFirstState() != null) {
|
||||
myEditor.setState(compositeState.getFirstState());
|
||||
}
|
||||
if (compositeState.getSecondState() != null) {
|
||||
myPreview.setState(compositeState.getSecondState());
|
||||
}
|
||||
if (compositeState.getSplitLayout() != null) {
|
||||
setLayout(compositeState.getSplitLayout());
|
||||
invalidateLayout();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void adjustEditorsVisibility() {
|
||||
myEditor.getComponent().setVisible(myLayout == Layout.SHOW_EDITOR || myLayout == Layout.SHOW_EDITOR_AND_PREVIEW);
|
||||
myPreview.getComponent().setVisible(myLayout == Layout.SHOW_PREVIEW || myLayout == Layout.SHOW_EDITOR_AND_PREVIEW);
|
||||
}
|
||||
|
||||
private void invalidateLayout() {
|
||||
adjustEditorsVisibility();
|
||||
myToolbarWrapper.refresh();
|
||||
myComponent.repaint();
|
||||
|
||||
final JComponent focusComponent = getPreferredFocusedComponent();
|
||||
if (focusComponent != null) {
|
||||
IdeFocusManager.findInstanceByComponent(focusComponent).requestFocus(focusComponent, true);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected String getSplitterProportionKey() {
|
||||
return "TextEditorWithPreview.SplitterProportionKey";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JComponent getPreferredFocusedComponent() {
|
||||
switch (myLayout) {
|
||||
case SHOW_EDITOR_AND_PREVIEW:
|
||||
case SHOW_EDITOR:
|
||||
return myEditor.getPreferredFocusedComponent();
|
||||
case SHOW_PREVIEW:
|
||||
return myPreview.getPreferredFocusedComponent();
|
||||
default:
|
||||
throw new IllegalStateException(myLayout.myName);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FileEditorState getState(@NotNull FileEditorStateLevel level) {
|
||||
return new MyFileEditorState(myLayout, myEditor.getState(level), myPreview.getState(level));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPropertyChangeListener(@NotNull PropertyChangeListener listener) {
|
||||
myEditor.addPropertyChangeListener(listener);
|
||||
myPreview.addPropertyChangeListener(listener);
|
||||
|
||||
final DoublingEventListenerDelegate delegate = myListenersGenerator.addListenerAndGetDelegate(listener);
|
||||
myEditor.addPropertyChangeListener(delegate);
|
||||
myPreview.addPropertyChangeListener(delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePropertyChangeListener(@NotNull PropertyChangeListener listener) {
|
||||
myEditor.removePropertyChangeListener(listener);
|
||||
myPreview.removePropertyChangeListener(listener);
|
||||
|
||||
final DoublingEventListenerDelegate delegate = myListenersGenerator.removeListenerAndGetDelegate(listener);
|
||||
if (delegate != null) {
|
||||
myEditor.removePropertyChangeListener(delegate);
|
||||
myPreview.removePropertyChangeListener(delegate);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public TextEditor getTextEditor() {
|
||||
return myEditor;
|
||||
}
|
||||
|
||||
public Layout getLayout() {
|
||||
return myLayout;
|
||||
}
|
||||
|
||||
protected void setLayout(@NotNull Layout layout) {
|
||||
myLayout = layout;
|
||||
}
|
||||
|
||||
static class MyFileEditorState implements FileEditorState {
|
||||
private final Layout mySplitLayout;
|
||||
private final FileEditorState myFirstState;
|
||||
private final FileEditorState mySecondState;
|
||||
|
||||
MyFileEditorState(Layout layout, FileEditorState firstState, FileEditorState secondState) {
|
||||
mySplitLayout = layout;
|
||||
myFirstState = firstState;
|
||||
mySecondState = secondState;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Layout getSplitLayout() {
|
||||
return mySplitLayout;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public FileEditorState getFirstState() {
|
||||
return myFirstState;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public FileEditorState getSecondState() {
|
||||
return mySecondState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeMergedWith(FileEditorState otherState, FileEditorStateLevel level) {
|
||||
return otherState instanceof MyFileEditorState
|
||||
&& (myFirstState == null || myFirstState.canBeMergedWith(((MyFileEditorState)otherState).myFirstState, level))
|
||||
&& (mySecondState == null || mySecondState.canBeMergedWith(((MyFileEditorState)otherState).mySecondState, level));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isModified() {
|
||||
return myEditor.isModified() || myPreview.isModified();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return myEditor.isValid() && myPreview.isValid();
|
||||
}
|
||||
|
||||
private class DoublingEventListenerDelegate implements PropertyChangeListener {
|
||||
@NotNull
|
||||
private final PropertyChangeListener myDelegate;
|
||||
|
||||
private DoublingEventListenerDelegate(@NotNull PropertyChangeListener delegate) {
|
||||
myDelegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
myDelegate.propertyChange(
|
||||
new PropertyChangeEvent(TextEditorWithPreview.this, evt.getPropertyName(), evt.getOldValue(), evt.getNewValue()));
|
||||
}
|
||||
}
|
||||
|
||||
private class MyListenersMultimap {
|
||||
private final Map<PropertyChangeListener, Pair<Integer, DoublingEventListenerDelegate>> myMap = new HashMap<>();
|
||||
|
||||
@NotNull
|
||||
public DoublingEventListenerDelegate addListenerAndGetDelegate(@NotNull PropertyChangeListener listener) {
|
||||
if (!myMap.containsKey(listener)) {
|
||||
myMap.put(listener, Pair.create(1, new DoublingEventListenerDelegate(listener)));
|
||||
}
|
||||
else {
|
||||
final Pair<Integer, DoublingEventListenerDelegate> oldPair = myMap.get(listener);
|
||||
myMap.put(listener, Pair.create(oldPair.getFirst() + 1, oldPair.getSecond()));
|
||||
}
|
||||
|
||||
return myMap.get(listener).getSecond();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public DoublingEventListenerDelegate removeListenerAndGetDelegate(@NotNull PropertyChangeListener listener) {
|
||||
final Pair<Integer, DoublingEventListenerDelegate> oldPair = myMap.get(listener);
|
||||
if (oldPair == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (oldPair.getFirst() == 1) {
|
||||
myMap.remove(listener);
|
||||
}
|
||||
else {
|
||||
myMap.put(listener, Pair.create(oldPair.getFirst() - 1, oldPair.getSecond()));
|
||||
}
|
||||
return oldPair.getSecond();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected ActionToolbar createToolbar() {
|
||||
ActionGroup actionGroup = createLeftToolbarActionGroup();
|
||||
if (actionGroup != null) {
|
||||
return ActionManager.getInstance().createActionToolbar("TextEditorWithPreview", actionGroup, true);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected ActionGroup createLeftToolbarActionGroup() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private ActionToolbar createRightToolbar() {
|
||||
final ActionGroup viewActions = createViewActionGroup();
|
||||
final ActionGroup group = createRightToolbarActionGroup();
|
||||
final ActionGroup rightToolbarActions = group == null
|
||||
? viewActions
|
||||
: new DefaultActionGroup(group, Separator.create(), viewActions);
|
||||
return ActionManager.getInstance().createActionToolbar("TextEditorWithPreview", rightToolbarActions, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected ActionGroup createViewActionGroup() {
|
||||
return new DefaultActionGroup(
|
||||
getShowEditorAction(),
|
||||
getShowEditorAndPreviewAction(),
|
||||
getShowPreviewAction()
|
||||
);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected ActionGroup createRightToolbarActionGroup() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected ToggleAction getShowEditorAction() {
|
||||
return new ChangeViewModeAction(Layout.SHOW_EDITOR);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected ToggleAction getShowPreviewAction() {
|
||||
return new ChangeViewModeAction(Layout.SHOW_PREVIEW);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected ToggleAction getShowEditorAndPreviewAction() {
|
||||
return new ChangeViewModeAction(Layout.SHOW_EDITOR_AND_PREVIEW);
|
||||
}
|
||||
|
||||
public enum Layout {
|
||||
SHOW_EDITOR(KotlinJvmBundle.message("editor.editor.only"), AllIcons.General.LayoutEditorOnly),
|
||||
SHOW_PREVIEW(KotlinJvmBundle.message("editor.preview.only"), AllIcons.General.LayoutPreviewOnly),
|
||||
SHOW_EDITOR_AND_PREVIEW(KotlinJvmBundle.message("editor.editor.and.preview"), AllIcons.General.LayoutEditorPreview);
|
||||
|
||||
private final String myName;
|
||||
private final Icon myIcon;
|
||||
|
||||
Layout(String name, Icon icon) {
|
||||
myName = name;
|
||||
myIcon = icon;
|
||||
}
|
||||
|
||||
public static Layout fromName(String name, Layout defaultValue) {
|
||||
for (Layout layout : Layout.values()) {
|
||||
if (layout.myName.equals(name)) {
|
||||
return layout;
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
public Icon getIcon() {
|
||||
return myIcon;
|
||||
}
|
||||
}
|
||||
|
||||
private class ChangeViewModeAction extends ToggleAction implements DumbAware {
|
||||
private final Layout myActionLayout;
|
||||
|
||||
ChangeViewModeAction(Layout layout) {
|
||||
super(layout.getName(), layout.getName(), layout.getIcon());
|
||||
myActionLayout = layout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSelected(@NotNull AnActionEvent e) {
|
||||
return myLayout == myActionLayout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(@NotNull AnActionEvent e, boolean state) {
|
||||
if (state) {
|
||||
setLayout(myActionLayout);
|
||||
PropertiesComponent.getInstance().setValue(getLayoutPropertyName(), myLayout.myName, Layout.SHOW_EDITOR_AND_PREVIEW.myName);
|
||||
adjustEditorsVisibility();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String getLayoutPropertyName() {
|
||||
return myName + "Layout";
|
||||
}
|
||||
}
|
||||
|
||||
class SplitEditorToolbar extends JPanel implements Disposable {
|
||||
|
||||
private final ActionToolbar myRightToolbar;
|
||||
|
||||
public SplitEditorToolbar(@Nullable ActionToolbar leftToolbar, @NotNull ActionToolbar rightToolbar) {
|
||||
super(new GridBagLayout());
|
||||
myRightToolbar = rightToolbar;
|
||||
|
||||
if (leftToolbar != null) {
|
||||
add(leftToolbar.getComponent());
|
||||
}
|
||||
|
||||
final JPanel centerPanel = new JPanel(new BorderLayout());
|
||||
add(centerPanel, new GridBagConstraints(2, 0, 1, 1, 1.0, 1.0,
|
||||
GridBagConstraints.CENTER, GridBagConstraints.BOTH, JBUI.emptyInsets(), 0, 0));
|
||||
|
||||
add(myRightToolbar.getComponent());
|
||||
|
||||
setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, UIUtil.CONTRAST_BORDER_COLOR));
|
||||
|
||||
if (leftToolbar != null) leftToolbar.updateActionsImmediately();
|
||||
rightToolbar.updateActionsImmediately();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@ApiStatus.ScheduledForRemoval
|
||||
public void addGutterToTrack(@NotNull EditorGutterComponentEx gutterComponentEx) {}
|
||||
|
||||
public void refresh() {
|
||||
myRightToolbar.updateActionsImmediately();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@ApiStatus.ScheduledForRemoval
|
||||
@Override
|
||||
public void dispose() {}
|
||||
}
|
||||
Reference in New Issue
Block a user