11package de .adito .aditoweb .nbm .nodejs .impl .runconfig ;
22
33import de .adito .aditoweb .nbm .nbide .nbaditointerface .javascript .node .*;
4+ import de .adito .aditoweb .nbm .nodejs .impl .NodeJSScriptExitHook ;
45import de .adito .aditoweb .nbm .nodejs .impl .actions .io .*;
56import de .adito .nbm .runconfig .api .*;
67import de .adito .nbm .runconfig .spi .IActiveConfigComponentProvider ;
1213import org .jetbrains .annotations .NotNull ;
1314import org .netbeans .api .progress .ProgressHandle ;
1415import org .netbeans .api .project .*;
16+ import org .netbeans .core .output2 .adito .InputOutputExt ;
17+ import org .openide .*;
18+ import org .openide .util .*;
1519import org .openide .windows .*;
1620
1721import javax .swing .*;
22+ import java .beans .PropertyChangeListener ;
1823import java .io .*;
1924import java .nio .charset .StandardCharsets ;
2025import java .nio .file .Paths ;
2126import java .util .*;
22- import java .util .concurrent .CompletableFuture ;
27+ import java .util .concurrent .* ;
2328
2429/**
2530 * RunConfig to execute a single nodejs script
2833 */
2934class NodeJSScriptRunConfig implements IRunConfig
3035{
31-
3236 private final Project project ;
3337 private final INodeJSEnvironment environment ;
3438 private final String scriptName ;
@@ -86,6 +90,12 @@ public void executeAsnyc(@NotNull ProgressHandle pProgressHandle)
8690 }
8791 }
8892
93+ @ NbBundle .Messages ({
94+ "LBL_ScriptCloseTerminateTitle=NodeJS script is still running..." ,
95+ "LBL_ScriptCloseTerminateMessage=Do you want to terminate the NodeJS script?" ,
96+ "LBL_ScriptCloseTerminateTerminateBtn=Terminate" ,
97+ "LBL_ScriptCloseTerminateDetachBtn=Detach" ,
98+ })
8999 private void run (@ NotNull InputOutput pIo , @ NotNull INodeJSExecutor pExecutor , @ NotNull Subject <Optional <CompletableFuture <Integer >>> pSubject )
90100 {
91101 try
@@ -107,7 +117,34 @@ private void run(@NotNull InputOutput pIo, @NotNull INodeJSExecutor pExecutor, @
107117 String npmScript = Paths .get (environment .getPath ().getParent (), "node_modules" , "npm" , "bin" , "npm-cli.js" ).toString ();
108118 CompletableFuture <Integer > future = pExecutor .executeAsync (environment , INodeJSExecBase .node (), out , err , null , npmScript , "run" , scriptName );
109119 pSubject .onNext (Optional .of (future ));
110- future .whenComplete ((pExit , pEx ) -> pSubject .onNext (Optional .of (future )));
120+
121+ PropertyChangeListener ioListener = evt -> {
122+ // also remove, if the script is not stopped
123+ NodeJSScriptExitHook .remove (future );
124+
125+ // no cancel option, because the closing of the output window can not be aborted here
126+ NotifyDescriptor descriptor = new NotifyDescriptor .Confirmation (
127+ Bundle .LBL_ScriptCloseTerminateMessage (),
128+ Bundle .LBL_ScriptCloseTerminateTitle ());
129+ descriptor .setOptions (new String []{
130+ Bundle .LBL_ScriptCloseTerminateTerminateBtn (),
131+ Bundle .LBL_ScriptCloseTerminateDetachBtn (),
132+ });
133+ Object selected = DialogDisplayer .getDefault ().notify (descriptor );
134+ if (Bundle .LBL_ScriptCloseTerminateTerminateBtn ().equals (selected ))
135+ future .cancel (false );
136+ };
137+ if (pIo instanceof InputOutputExt )
138+ ((InputOutputExt ) pIo ).addPropertyChangeListener (ioListener );
139+
140+ future .whenComplete ((pExit , pEx ) -> {
141+ if (pIo instanceof InputOutputExt )
142+ ((InputOutputExt ) pIo ).removePropertyChangeListener (ioListener );
143+
144+ NodeJSScriptExitHook .remove (future );
145+ pSubject .onNext (Optional .of (future ));
146+ });
147+ NodeJSScriptExitHook .add (future );
111148 }
112149 catch (IOException pEx )
113150 {
0 commit comments