Cet article "Calendrier de l'Avent DeNA IP Platform Division 2017" Ceci est l'article du 19ème jour.
Dans mon équipe, tous les ingénieurs côté serveur codent à l'aide d'IntelliJ IDEA. Récemment, je me suis soudainement demandé "Comment créer un plug-in IntelliJ IDEA?", Et pendant mes études, j'ai essayé de créer quelque chose comme une mascotte de bureau qui apparaît sur l'IDE, alors j'aimerais résumer le flux.
Lorsque vous démarrez l'IDE, d'étranges créatures apparaîtront. Au fur et à mesure que vous codez, les valeurs d'expérience (Exp) s'accumulent. (Je voulais ajouter une fonction qui prend en charge le codage un peu plus, mais ce n'est pas grave)
IntelliJ IDEA est requis pour créer un plug-in. (L'édition communautaire est également acceptable) Il semble qu'il sera plus facile de déboguer pendant le développement du plug si le code source d'IntelliJ IDEA Community Edition est également supprimé, mais je ne l'ai pas utilisé cette fois. La procédure détaillée est décrite dans le Document officiel, je vais donc l'omettre.
[Fichier> Nouveau projet> Plugin de plateforme IntelliJ> Suivant] sur IntelliJ IDEA Donnez au nom du projet un nom approprié. (Cette fois, c'est Nunyu)
Les trois types de composants suivants sont à la base du plug-in.
Cette fois, je veux que la mascotte apparaisse tout le temps dans les projets lorsque l'EDI démarre, donc je vais la créer avec le composant de niveau Application. Vous pouvez en créer un nouveau en cliquant avec le bouton droit sur le panneau Projet et en sélectionnant [Nouveau> Plugin DevKit> Composant d'application]. Le nom du composant est "Nunyu".
En fait, le plug-in fonctionne maintenant sur l'IDE! Processus d'initialisation des composants Déconnectons-nous et exécutons-le avec ʻinitComponent`.
src/Nunyu.java
import com.intellij.openapi.diagnostic.Logger;
...
@Override
public void initComponent() {
Logger.getInstance(Nunyu.class).info("Nunyu");
}
...
Pour l'exécuter, sélectionnez [Exécuter> Déboguer] dans le menu. Ensuite, un autre IntelliJ IDEA sera lancé et le plug-in s'y exécutera. Et vous pouvez voir qu'il y a un message dans la console de débogage.
Laissez le composant hériter de JWindow
pour afficher la fenêtre lors de l'initialisation et rendre l'image. Il s'agit de "Swing".
src/Nunyu.java
import com.intellij.openapi.components.ApplicationComponent;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Nunyu extends JWindow implements ApplicationComponent {
private Image image;
private ImagePanel imagePanel;
public Nunyu() {
}
@Override
public void initComponent() {
initWindow();
makeDraggable();
}
public void initWindow() {
image = Toolkit.getDefaultToolkit().getImage(getClass().getResource("/images/nunyu-alpha.png "));
setSize(100, 100);
setAlwaysOnTop(true);
setBackground(new Color(1, 0, 0, 0));
imagePanel = new ImagePanel();
add(imagePanel);
setVisible(true);
}
public void makeDraggable() {
final Point startPos = new Point();
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
startPos.setLocation(e.getPoint());
}
});
addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
setLocation(e.getXOnScreen() - startPos.x, e.getYOnScreen() - startPos.y);
}
});
}
public class ImagePanel extends JPanel {
public ImagePanel() {
setOpaque(false);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
}
@Override
public void disposeComponent() {
// TODO: insert component disposal logic here
}
@Override
@NotNull
public String getComponentName() {
return "Nunyu";
}
}
setBackground (new Color (0, 0, 0, 0))
pour rendre la fenêtre transparente.
--Préparez le PNG transparent dans resources / images / nunyu-alpha.png
et réglez-le sur setOpaque (false)
et rendez-le.
--Je veux que vous l'affichez toujours en haut, donc setAlwaysOnTop (true)
--Je veux pouvoir faire glisser la mascotte, alors regardez l'événement de la souris et implémentez-le un peu makeDraggable ()
Maintenant, lorsque vous l'exécutez, vous verrez les mascottes que vous pouvez faire glisser!
À ce rythme, même si l'EDI perd le focus, la mascotte restera affichée en haut et ne disparaîtra pas. C'est ennuyant. Ainsi, lorsque l'EDI perd le focus, j'ajouterai un processus pour effacer la mascotte en même temps.
src/Nunyu.java
@Override
public void initComponent() {
initWindow();
setupFocusEvent();
}
...
public void setupFocusEvent() {
WindowManager.getInstance().addListener(new WindowManagerListener() {
@Override
public void frameCreated(IdeFrame frame) {
WindowManager.getInstance().getFrame(frame.getProject()).addWindowFocusListener(new WindowFocusListener() {
@Override
public void windowGainedFocus(WindowEvent e) {
setVisible(true);
}
@Override
public void windowLostFocus(WindowEvent e) {
if (e.getOppositeWindow() == null) {
setVisible(false);
}
}
});
}
@Override
public void beforeFrameReleased(IdeFrame frame) {
}
});
}
Ajoutez un écouteur WindowManagerListener
et ajoutez un WindowFocusListener
à cette fenêtre chaque fois qu'une image est créée sur l'EDI. Dans cet écouteur, implémentez windowGainedFocus
, qui se déclenche lorsque la fenêtre obtient le focus, et windowLostFocus
, qui se déclenche lorsque la fenêtre perd le focus.
Je veux afficher la mascotte lorsque la fenêtre de l'EDI obtient le focus, donc je peux appeler setVisible (true)
. Inversement, si vous perdez le focus, vous pouvez utiliser ʻe.getOppositeWindow () pour obtenir la fenêtre qui sera le prochain focus, mais si c'est
null, l'EDI n'aura pas le focus, donc
setVisible Appel (faux) `.
Maintenant, la prochaine fois que je coderai dans l'éditeur, j'essaierai de donner une valeur à l'expérience de la mascotte. Cela nécessite des frappes de l'éditeur de hook, mais étendons ʻeditorTypedHandler` pour y parvenir.
src/MyTypedHandler.java
import com.intellij.codeInsight.editorActions.AutoFormatTypedHandler;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.TypedActionHandler;
import org.jetbrains.annotations.NotNull;
public class MyTypedHandler extends AutoFormatTypedHandler {
public MyTypedHandler(TypedActionHandler originalHandler) {
super(originalHandler);
}
@Override
public void execute(@NotNull Editor editor, char charTyped, @NotNull DataContext dataContext) {
super.execute(editor, charTyped, dataContext);
Logger.getInstance(Nunyu.class).info("Typed: " + charTyped);
}
}
resources/META-INF/plugin.xml
...
<extensions defaultExtensionNs="com.intellij">
<editorTypedHandler implementationClass="MyTypedHandler"/>
</extensions>
...
Lorsqu'un caractère est saisi dans l'éditeur, ʻexecute () est appelé. Essayez de sortir la touche enfoncée dans le journal en appelant
super.execute ()telle quelle pour ne pas changer le comportement par défaut. Essayez de l'exécuter maintenant et modifiez quelque chose sur l'EDI qui se lance. Vous pouvez voir que la clé que vous avez saisie apparaît dans le journal d'informations. Voici comment accrocher cette clé, mais il semble que [il y a aussi un moyen d'utiliser
TypedHandlerDelegate`](https://qiita.com/shiraji/items/5a7a1654dc7b6da20a60), mais quand je l'ai essayé, je l'ai essayé dans l'IDE. Lorsque la fenêtre contextuelle de saisie semi-automatique est sortie, il semblait que l'événement ne se reproduirait pas, donc cela n'a pas fonctionné. (Honnêtement, je ne sais pas quelle est la bonne réponse.)
Même si je peux donner l'expérience de la mascotte, il est triste qu'elle soit réinitialisée lorsque l'EDI est redémarré. Alors, rendons possible de rendre permanente la valeur d'expérience donnée ensuite.
Utilisez PersistentStateComponent
pour conserver les données dans le plug-in.
src/MyService.java
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
@State(
name = "MyService",
storages = {
@Storage("nunyu.xml"),
}
)
class MyService implements PersistentStateComponent<MyService.State> {
static class State {
public Integer exp = 0;
}
State myState;
public MyService() {
this.myState = new State();
}
public State getState() {
return myState;
}
public void loadState(State state) {
myState = state;
}
public static MyService getInstance() {
return ServiceManager.getService(MyService.class);
}
}
J'ai implémenté une boîte qui a simplement l'entier ʻexp. Vous pouvez définir la destination à conserver avec l'annotation
@ State`.
N'oubliez pas non plus de mentionner dans plugin.xml
pour utiliser ce service.
resources/META-INF/plugin.xml
...
<extensions defaultExtensionNs="com.intellij">
<applicationService serviceInterface="MyService" serviceImplementation="MyService"/>
</extensions>
...
Enregistrez-vous en tant que ʻapplicationServicecar il sera utilisé par les composants au niveau de l'application. Notez qu'il existe d'autres
projectService`, etc.
Tout d'abord, commençons par afficher la valeur d'expérience à l'écran.
Réécrivez la méthode paintComponent ()
de la classe ʻImagePanel pour afficher le
ʻexp de
MyService. Préparez également la méthode
repaint ()` afin de pouvoir redessiner à chaque fois que la valeur d'expérience augmente.
src/Nunyu.java
...
public void repaint() {
imagePanel.repaint();
}
...
public class ImagePanel extends JPanel {
...
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
g.drawString("Exp. " + MyService.getInstance().myState.exp, 0, 10);
}
}
...
Ensuite, écrivez un processus pour augmenter la valeur d'expérience au moment de la saisie clé et du redessiner.
src/MyService.java
...
public void increment() {
myState.exp++;
}
...
src/MyTypedHandler.java
...
@Override
public void execute(@NotNull Editor editor, char charTyped, @NotNull DataContext dataContext) {
super.execute(editor, charTyped, dataContext);
ServiceManager.getService(MyService.class).increment();
ApplicationManager.getApplication().getComponent(Nunyu.class).repaint();
}
...
C'est tout. Au fur et à mesure que vous codez, votre expérience augmentera régulièrement!
Au fait, j'ai créé un plug-in qui ne servait à rien (rires), mais en procédant par essais et erreurs, j'ai en quelque sorte compris quelque chose comme comment créer un plug-in. Il était assez difficile de trouver des informations dans les documents, et je n'ai rien trouvé du genre "Que dois-je faire quand je veux faire quelque chose comme ça?!", Et même une si simple était très difficile. Il existe de nombreux plug-ins sur le marché, vous pouvez donc y rechercher du code utile, ou Rechercher dans la communauté. community & topic = 20036979 & utf8 =% E2% 9C% 93) et vous pouvez ou non trouver les informations que vous recherchez! Cet article était la fin d'une lutte, mais si vous avez des suggestions, veuillez commenter.
Recommended Posts