2
$\begingroup$

I have tried modifying KeyEventTranslations.tr with code:

Item[KeyEvent["r", Modifiers -> {Control}], 
    FrontEndExecute @ Module[
      {p ,ret},
      DialogInput[{
        ListPicker[Dynamic[p],{"one", "two"}], 
        DefaultButton[DialogReturn[ret = p]]
      }]
    ],
    MenuEvaluator -> Automatic, Method -> "Queued"
],

but it complains that

DialogInput is not currently supported within preemptive evaluations

whenever I call the keyboard shortcut.

$\endgroup$
3
  • $\begingroup$ Maybe you could prompt a MessageDialog first and from there run whatever you want. $\endgroup$
    – Kuba
    Apr 11, 2016 at 7:58
  • $\begingroup$ Thanks, however unluckily MessageDialog doesn't wait for input like DialogInput does. $\endgroup$
    – Ranza
    Apr 11, 2016 at 8:43
  • $\begingroup$ Yes, I know but it can be some kind of intermediate step with a short message about what is going to happen and a "Queued" button to run your initial procedure. $\endgroup$
    – Kuba
    Apr 11, 2016 at 8:45

1 Answer 1

4
$\begingroup$

You can't run Kernel Blocking Dialogs on the preemptive link. But you can prompt other dialogs. And we can abuse that to run a procedure containing Input[], DialogInput[] or some system dialogs.

The trick is to run your code inside an asynchronous initialization of the regular dialog:

MessageDialog[
   DynamicModule[{},
      1,
      Initialization :> (
         NotebookClose @ EvaluationNotebook[];

         (*put here a custom procedure*)

       ),
       SynchronousInitialization -> False
   ],
   Visible -> False
]

This regular invisible dialog is closed automatically by itself.

We can test it with Button as by default it uses preemptive link, just like procedures assigned to keyboard shortcuts.

Normally you wouldn't be able to run this procedure from there:

 procedure[] := Module[{test}, test = Input[];  Print[test]];

 Button["test", procedure[]]

Input::nprmtv: Input is not currently supported within preemptive evaluations. >> (after click)

But with this workaround it works:

Button["test", 
 MessageDialog[
  DynamicModule[{}, 1, 
   Initialization :> (NotebookClose@EvaluationNotebook[];
     procedure[]), SynchronousInitialization -> False], 
  Visible -> False]
]
$\endgroup$
5
  • $\begingroup$ That's a really creative idea, but it doesn't solve my problem :/ I want to be able to use the return value of this Dialog box in another function which shouldn't run before the Dialog box is closed. $\endgroup$
    – Ranza
    Apr 11, 2016 at 11:16
  • $\begingroup$ @Ranza The point is that instead of my Module you can use whatever you want, if your procedure contains another dialogs, doesn't matter, it should work. Everything except the Module is just a wrapper here. $\endgroup$
    – Kuba
    Apr 11, 2016 at 11:18
  • $\begingroup$ Stupid me! Indeed you're right, thank you a thousand-fold! $\endgroup$
    – Ranza
    Apr 11, 2016 at 11:37
  • $\begingroup$ Very clever. This is really useful for things like auto-asking for a file name on a "MouseEntered" event or similar, too. One thing to beware of is that you really need to ask for Evaluation* before the MessageDialog pops up and adding it with With or something. I was just using this to auto-replace a label with a file name and ran into just that issue. $\endgroup$
    – b3m2a1
    Dec 9, 2016 at 5:58
  • 1
    $\begingroup$ @MB1965 Thanks. Yes, many solutions are really tricks so one has to always be careful :) $\endgroup$
    – Kuba
    Dec 9, 2016 at 9:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.