/* * Copyright 2019 The Chromium Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ package io.flutter.editor; /* * Copyright 2019 The Chromium Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ import com.intellij.openapi.Disposable; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.editor.Caret; import com.intellij.openapi.editor.EditorFactory; import com.intellij.openapi.editor.event.*; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; import java.awt.*; /** * Service that tracks the visible area and Carat selection of an editor. * <p> * This class provides a {@link EditorPositionService.Listener} that notifies consumers when * the editor changes position or carat selection. */ public class EditorPositionService extends EditorEventServiceBase<EditorPositionService.Listener> implements Disposable { public interface Listener { void updateVisibleArea(Rectangle newRectangle); void onVisibleChanged(); default void updateSelected(Caret carat) { } } private final VisibleAreaListener visibleAreaListener; private final EditorEventMulticaster eventMulticaster; public EditorPositionService(Project project) { super(project); eventMulticaster = EditorFactory.getInstance().getEventMulticaster(); visibleAreaListener = (VisibleAreaEvent event) -> { invokeAll(listener -> listener.updateVisibleArea(event.getNewRectangle()), event.getEditor()); }; eventMulticaster.addVisibleAreaListener(visibleAreaListener); eventMulticaster.addCaretListener(new CaretListener() { @Override public void caretPositionChanged(@NotNull CaretEvent e) { invokeAll(listener -> listener.updateSelected(e.getCaret()), e.getEditor()); } }, this); // TODO(jacobr): listen for when editors are disposed? } @NotNull public static EditorPositionService getInstance(@NotNull final Project project) { return ServiceManager.getService(project, EditorPositionService.class); } public void addListener(EditorEx editor, @NotNull Listener listener, Disposable disposable) { super.addListener(editor, listener, disposable); // Notify the listener of the current state. listener.updateVisibleArea(editor.getScrollingModel().getVisibleArea()); final Caret carat = editor.getCaretModel().getPrimaryCaret(); if (carat.isValid()) { listener.updateSelected(carat); } } @Override public void dispose() { eventMulticaster.removeVisibleAreaListener(visibleAreaListener); super.dispose(); } }