| From | Sent On | Attachments |
|---|---|---|
| Greg Kellum | Dec 18, 2009 12:27 pm | |
| Duncan McGregor | Dec 18, 2009 1:03 pm | |
| Greg Kellum | Dec 18, 2009 1:24 pm | |
| Harald Kuhr | Dec 21, 2009 5:06 am | |
| Andrew Thompson | Dec 21, 2009 8:01 pm | |
| Brian Schlining | Dec 21, 2009 9:09 pm | |
| Harald Kuhr | Dec 22, 2009 5:26 am | |
| Harald Kuhr | Dec 22, 2009 5:33 am |
| Subject: | Re: rococoa video player | |
|---|---|---|
| From: | Harald Kuhr (hara...@gmail.com) | |
| Date: | Dec 22, 2009 5:26:39 am | |
| List: | net.java.dev.rococoa.users | |
Okay,
I'm away on christmas holidays now, so I haven't had time to clean it up, but here's the main parts of the interesting code (the example shows a modal NSOpen/NSavePanel, but I guess any blocking Cocoa call could be made).
This code is clearly full of hacks, like the reflective invocation of the package protected pumpEvents and the timer. But until there are better solutions out there, it works for me.. ;-)
Here goes:
private final ExecutorService executor = Executors.newSingleThreadExecutor();
...
// NOTE: This method should be called on the EDT, and will block until the user has made a selection/dismissed the dialog private int runDialog(final JFileChooser chooser, final Component parent, final Dialog.ModalityType pModality, final NSSavePanel pSave) { final Window window = getWindowAncestor(parent);
try { final Future<Integer> future = executor.submit(new Callable<Integer>() { public Integer call() throws Exception {
// -- blocking AppKit call ahead -- // Shows a sheet or full dialog depending on dialog modality if (pModality == Dialog.ModalityType.DOCUMENT_MODAL) { ModalDelegate delegate = new ModalDelegate(); NSObject proxy = Rococoa.proxy(delegate); pSave.beginSheet( chooser.getCurrentDirectory(), chooser.getSelectedFile(), window, proxy.id(), Foundation.selector("panelDidEnd:returnCode:"), null );
return delegate.getResult(); } else { return pSave.runModal(chooser.getCurrentDirectory(), chooser.getSelectedFile()); } // -- done blocking AppKit call --
} });
// NOTE: The event pump seems to stall the EDT until new events occurs, so we'll keep it alive with a timer... // It will simply fire no-op events every 100ms until we're done. Timer timer = new Timer(100, null); timer.setRepeats(true);
// Block until dialog is done try { timer.start();
new EventPump(new Conditional() { public boolean evaluate() { return !future.isDone(); } }).start(); } catch (Exception e) { throw new RuntimeException(e); } finally { timer.stop(); }
// The future should now be done, so just return the result return future.get(); } catch (InterruptedException e) { throw new RuntimeException(e); } catch (ExecutionException e) { throw new RuntimeException(e); } }
...
// Pretty much the same interface as java.awt.Conditional static interface Conditional { boolean evaluate(); }
// Adapted from
http://www.jroller.com/santhosh/entry/are_you_missing_maximize_button
// @author Santhosh Kumar T - sant...@in.fiorano.com
static class EventPump {
private final Conditional conditional;
final InvocationHandler conditionalHandler = new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return conditional.evaluate(); } };
public EventPump(final Conditional conditional) { this.conditional = conditional; }
// The reflection calls in this method should be // replaced once Sun provides a public API to pump events. public void start() throws Exception { Class conditionalClass = Class.forName("java.awt.Conditional");
Object conditional = Proxy.newProxyInstance( conditionalClass.getClassLoader(), new Class[]{conditionalClass}, conditionalHandler );
Method pumpMethod = Class .forName ("java.awt.EventDispatchThread").getDeclaredMethod("pumpEvents", conditionalClass); pumpMethod.setAccessible(true);
// NOTE: Current thread must be the EDT pumpMethod.invoke(Thread.currentThread(), conditional); } }
Best regards,
-- Harald K
On 22. des.. 2009, at 06.10, Brian Schlining wrote:
Me too.
I'd like to see that code.
On Dec 21, 2009, at 8:06 AM, Harald Kuhr wrote:
I might submit my code for inclusion with Rococoa one day if anyone's interested. And of course always call back to Swing using SwingUtilities.invokeLater.





