atom feed8 messages in net.java.dev.rococoa.usersRe: rococoa video player
FromSent OnAttachments
Greg KellumDec 18, 2009 12:27 pm 
Duncan McGregorDec 18, 2009 1:03 pm 
Greg KellumDec 18, 2009 1:24 pm 
Harald KuhrDec 21, 2009 5:06 am 
Andrew ThompsonDec 21, 2009 8:01 pm 
Brian SchliningDec 21, 2009 9:09 pm 
Harald KuhrDec 22, 2009 5:26 am 
Harald KuhrDec 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,

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.