|
| 1 | +/* |
| 2 | + * Copyright 2024 JetBrains s.r.o. |
| 3 | + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| 4 | + * |
| 5 | + * This code is free software; you can redistribute it and/or modify it |
| 6 | + * under the terms of the GNU General Public License version 2 only, as |
| 7 | + * published by the Free Software Foundation. Oracle designates this |
| 8 | + * particular file as subject to the "Classpath" exception as provided |
| 9 | + * by Oracle in the LICENSE file that accompanied this code. |
| 10 | + * |
| 11 | + * This code is distributed in the hope that it will be useful, but WITHOUT |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| 14 | + * version 2 for more details (a copy is included in the LICENSE file that |
| 15 | + * accompanied this code). |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU General Public License version |
| 18 | + * 2 along with this work; if not, write to the Free Software Foundation, |
| 19 | + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| 20 | + * |
| 21 | + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| 22 | + * or visit www.oracle.com if you need additional information or have any |
| 23 | + * questions. |
| 24 | + */ |
| 25 | + |
| 26 | +package com.jetbrains; |
| 27 | + |
| 28 | +/** |
| 29 | + * This is a JBR API for text-input related functionality for applications that implement custom text components. |
| 30 | + * <p> |
| 31 | + * Suppose an application implements a custom text component called {@code CustomTextComponent}, that |
| 32 | + * doesn't inherit from {@link java.awt.TextComponent} or {@link javax.swing.text.JTextComponent}. |
| 33 | + * For this component to work correctly, the application needs to handle certain events that are missing from |
| 34 | + * the Java specification. |
| 35 | + * <p> |
| 36 | + * To do this, the application should add an event listener for the events provided by this API. |
| 37 | + * This is best done at application startup time, since the event listener is global, and not per-component. |
| 38 | + * For example, this would be a proper way to implement this event handler for {@code CustomTextComponent}: |
| 39 | + * |
| 40 | + * <pre> |
| 41 | + * {@code |
| 42 | + * var textInput = JBR.getTextInput(); |
| 43 | + * if (textInput != null) { |
| 44 | + * textInput.setGlobalEventListener(new TextInput.EventListener() { |
| 45 | + * @Override |
| 46 | + * public void handleSelectTextRangeEvent(TextInput.SelectTextRangeEvent event) { |
| 47 | + * if (event.getSource() instanceof CustomTextComponent) { |
| 48 | + * ((CustomTextComponent)event.getSource()).select(event.getBegin(), event.getBegin() + event.getLength()); |
| 49 | + * } |
| 50 | + * } |
| 51 | + * }); |
| 52 | + * } |
| 53 | + * } |
| 54 | + * </pre> |
| 55 | + * This assumes that {@code CustomTextComponent} has a method called {@code select}, that selects a text range, |
| 56 | + * similar to the {@link java.awt.TextComponent#select(int, int)} and {@link javax.swing.text.JTextComponent#select(int, int)}. |
| 57 | + * See {@link TextInput.SelectTextRangeEvent} for more information. |
| 58 | + */ |
| 59 | +@Service |
| 60 | +@Provided |
| 61 | +public interface TextInput { |
| 62 | + /** |
| 63 | + * Custom text components that do not extend {@link java.awt.TextComponent} or {@link javax.swing.text.JTextComponent} |
| 64 | + * should subscribe to this event. When receiving it, they should select the text range of UTF-16 code units starting |
| 65 | + * at index {@param begin} of length {@param length}. |
| 66 | + * <p> |
| 67 | + * It is expected, that {@link java.awt.event.KeyEvent#KEY_TYPED}, or |
| 68 | + * {@link java.awt.event.InputMethodEvent} events will immediately follow. They will insert new text in place of the |
| 69 | + * old text pointed to by this event's range. |
| 70 | + */ |
| 71 | + @Provided |
| 72 | + interface SelectTextRangeEvent { |
| 73 | + /** |
| 74 | + * Returns an AWT component that is the target of this event |
| 75 | + * @return an AWT component that is the target of this event |
| 76 | + */ |
| 77 | + Object getSource(); |
| 78 | + |
| 79 | + /** |
| 80 | + * Returns first UTF-16 code unit index of the replacement range |
| 81 | + * @return first UTF-16 code unit index of the replacement range |
| 82 | + */ |
| 83 | + int getBegin(); |
| 84 | + |
| 85 | + /** |
| 86 | + * Returns length of the replacement range in UTF-16 code units |
| 87 | + * @return length of the replacement range in UTF-16 code units |
| 88 | + */ |
| 89 | + int getLength(); |
| 90 | + } |
| 91 | + |
| 92 | + /** |
| 93 | + * Event listener interface for all events supported by this API. |
| 94 | + */ |
| 95 | + @Provides |
| 96 | + interface EventListener { |
| 97 | + /** |
| 98 | + * Handles the {@link SelectTextRangeEvent}. |
| 99 | + * <p> |
| 100 | + * Custom text components that do not extend {@link java.awt.TextComponent} or {@link javax.swing.text.JTextComponent} |
| 101 | + * should subscribe to this event. When receiving it, they should select the text range of UTF-16 code units starting |
| 102 | + * at index {@param begin} of length {@param length}. |
| 103 | + * <p> |
| 104 | + * It is expected, that {@link java.awt.event.KeyEvent#KEY_TYPED}, or |
| 105 | + * {@link java.awt.event.InputMethodEvent} events will immediately follow. They will insert new text in place of the |
| 106 | + * old text pointed to by this event's range. |
| 107 | + * |
| 108 | + * @param event the {@link SelectTextRangeEvent} object |
| 109 | + */ |
| 110 | + void handleSelectTextRangeEvent(SelectTextRangeEvent event); |
| 111 | + } |
| 112 | + |
| 113 | + /** |
| 114 | + * Sets the global event listener for text input/IME related events. |
| 115 | + * This should ideally be called once on the application startup. |
| 116 | + * Passing null will remove the listener. |
| 117 | + * The listener will only be called on the event dispatch thread (EDT). |
| 118 | + * |
| 119 | + * @param listener listener |
| 120 | + */ |
| 121 | + void setGlobalEventListener(EventListener listener); |
| 122 | +} |
0 commit comments