package tufts.macosx; import com.apple.cocoa.foundation.*; import com.apple.cocoa.application.*; import com.apple.eawt.*; import java.awt.*; import java.net.*; // NOTE: This will ONLY compile on Mac OS X (or, technically, anywhere // you have the com.apple.cocoa.* class files available). It is for // generating a library to be put in the lib dir so VUE can build on // any platform. // Scott Fraize 2005-03-27 /** * Mac OSX Test Code * @version $Revision: 1.6 $ / $Date: 2008-05-27 23:55:58 $ / $Author: sfraize $ */ public class MacTest extends MacOSX { public static void main(String args[]) { MacOSX.DEBUG = true; tufts.vue.gui.GUI.parseArgs(args); tufts.vue.gui.GUI.init(); //test_fadeScreen(); test_colorPicker(args); //test_movie(args); //test_macPanel(args); } // Okay, NSMovieView is just broken crap. Doesn't even work in // an NSPanel, never mind a CocoaComponent. Need to use // the quicktime.* classes -- see PlayMovie demo in QTJavaDemos. static void test_movie(String args[]) { URL u = null; try { u = new URL(args[0]); } catch (Throwable e) { e.printStackTrace(); } final URL url = u; NSMovie movie = new NSMovie(url, false); out("got movie " + movie + " url=" + movie.URL()); final NSMovieView movieView = new NSMovieView(); movieView.setMovie(movie); out("got movie view " + movieView); String viewStr = movieView.toString(); String viewHex = viewStr.substring(viewStr.indexOf("0x")+2, viewStr.length() - 1); out("got movie hashCode " + movieView.hashCode()); out("got movie view hex " + viewHex); final long viewPtr = Long.parseLong(viewHex, 16); out("got movie view ptr " + viewPtr); NSSize movieSize = movieView.sizeForMagnification(1.0F); final Dimension csize = movieSize.toAWTDimension(); //movieView.showController(false, false); movieView.setEditable(false); // changes controller to simpler/standard movieView.setPlaysSelectionOnly(false); // can't see effect //movieView.setPlaysEveryFrame(true); // won't even start, or stops after shorter bursts //movieView.setRate(0.5F); out("got movie size " + csize); out("got movie rate " + movieView.rate()); out("isControllerVisible=" + movieView.isControllerVisible()); //Canvas movieCanvas = new quicktime.app.display.QTCanvas() { // apparenly ONLY java 1.3!!! //Canvas movieCanvas = new quicktime.app.view.QTJavaCocoaCanvas() { // not accessable Canvas movieCanvas = new CocoaComponent() { { out("constructed " + this); } public int createNSView() { // doesn't get called, but just in case return (int) createNSViewLong(); } public void addNotify() { out("addNotify " + this); super.addNotify(); } protected void processEvent(AWTEvent e) { out("processEvent " + e); super.processEvent(e); } // if this doesn't return something, createNSView will be called public long createNSViewLong() { long ptr = viewPtr; out("createNSViewLong returns " + ptr); return ptr; } public void paint(Graphics g) { out("paint"); super.paint(g); } public void update(Graphics g) { out("update"); super.update(g); } public java.awt.Dimension getMaximumSize() { return csize; } public java.awt.Dimension getMinimumSize() { return csize; } public java.awt.Dimension getPreferredSize() { return csize; } }; out("got canvas " + movieCanvas); //NSWindow main = NSApplication.sharedApplication().mainWindow(); //out("NSApplication.mainWindow="+main); Frame frame = new Frame("Movie: " + url) { { setBackground(Color.orange); setLayout(new FlowLayout()); add(new Label("Movie: " + url)); } public void paint(Graphics g) { out("frame paint"); super.paint(g); } public void update(Graphics g) { out("frame update"); super.update(g); } protected void processEvent(AWTEvent e) { out("frame processEvent " + e); super.processEvent(e); } }; if (true) { frame.add(movieCanvas); } else { // Wow: NSMovieView doesn't even work in a real NSPanel NSPanel p = new MacPanel(true); p.setTitle("Movie: " + url); p.setContentView(movieView); p.orderFrontRegardless(); KEEP.add(p); } frame.pack(); frame.show(); //NSWindow main = NSApplication.sharedApplication().mainWindow(); //out("NSApplication.mainWindow="+main); KEEP.add(movie); KEEP.add(movieView); KEEP.add(movieCanvas); // So I bet this would work fine in an NSPanel. // It doesn't seem to like being in a java Frame. dumpWindows(); //movieView.start(null); } static void test_colorPicker(String args[]) { DEBUG=true; showColorPicker(); try { Thread.sleep(5000); } catch (Exception e) {} /* Frame w = new Frame("invisible"); fadeToBlack(); if (args.length > 0) w.show(); // leaves us in AWT event loop at end of main instead of exiting //goBlack(); showColorPicker(); NSOpenPanel.openPanel().orderFront(null); try { Thread.sleep(500); } catch (Exception e) {} NSWindow main = NSApplication.sharedApplication().mainWindow(); System.out.println("mainWindow="+main); if (main == null) { System.out.println("COULDN'T FIND MAIN WINDOW!"); } else { main.setBackgroundColor(NSColor.redColor()); main.setAlphaValue(0.5f); } fadeFromBlack(); //try { Thread.sleep(5000); } catch (Exception e) {} */ } static void test_fadeScreen() { System.out.println("MacTest - Cocoa application & foundation classes"); Frame w = new Frame("Hello"); // if we don't create a Java frame or window of some kind first, we get the following // error (note that we don't even have to show it): /* Exception in thread "main" NSInternalInconsistencyException: Error (1002) creating CGSWindow at com.apple.cocoa.application.NSWindow.orderFrontRegardless(Native Method) at MacTest.main(MacTest.java:22) */ final NSWindow nsw = new NSWindow(new NSRect(0,0,1600,1024), //NSWindow.TitledWindowMask + //NSWindow.ClosableWindowMask + //NSWindow.ResizableWindowMask + //NSWindow.MiniaturizableWindowMask + //NSWindow.TexturedBackgroundWindowMask + 0, NSWindow.Buffered, true); //nsw.center(); nsw.setTitle("My Apple Window"); //nsw.setAlphaValue(0.75f); //nsw.setBackgroundColor(NSColor.brownColor()); nsw.setBackgroundColor(NSColor.blackColor()); //nsw.setShowsResizeIndicator(true); nsw.setLevel(NSWindow.ScreenSaverWindowLevel); // this allows it over the mac menu bar nsw.setAlphaValue(0); nsw.orderFront(nsw); //nsw.orderFrontRegardless(); //nsw.display(); System.out.println("NSWindow=" + nsw); new Thread() { public void run() { // note that the mac conveniently does not return from the setAlphaValue // until it's been set and rendered onto the screen. (So this is too // fast for a small window w/out big delay, but if you maximize it, it's // smooth). final boolean cycle = false; boolean black = false; while (true) { if (cycle) { if (black) nsw.setBackgroundColor(NSColor.whiteColor()); else nsw.setBackgroundColor(NSColor.blackColor()); nsw.setAlphaValue(0); nsw.display(); // must call display for a background color change to take effect black = !black; } // for max effect, especially when fading to full white, take into // account that brightness sensitivity is non-linear -- e.g., // fade to white ramps too fast in the beginning. double alpha; for (alpha = 0.1; alpha <= 1; alpha += 0.02) { out("alpha="+(float)alpha); nsw.setAlphaValue((float)alpha); try { sleep(10); } catch (Exception e) {} // give CPU a break } out("alpha="+(float)alpha); for (alpha = 1; alpha >= 0; alpha -= 0.02) { if (alpha < 0.01) alpha = 0; out("alpha="+(float)alpha); nsw.setAlphaValue((float)alpha); try { sleep(10); } catch (Exception e) {} } if (!cycle) return; } } }.start(); } //private static NSPanel NSPanelDontGarbageCollectMe; private static java.util.Collection KEEP = new java.util.ArrayList(); // array of object to not GC public static class NoticeListener { //private static NSSelector selector = new NSSelector("notice", new Class[] { new String().getClass() }); private static NSSelector selector = new NSSelector("notice", new Class[] { NSNotification.class }); public static NSSelector getSelector() { return selector; //return new NSSelector("notice", new Class[] { new String().getClass() }); } public static void addObserver(Object toWatch) { addObserver(toWatch, null); } public static void addObserver(Object toWatch, String message) { System.err.println("Adding observer of " + toWatch + " for messages: " + message); Object listener = new NoticeListener(); KEEP.add(listener); NSNotificationCenter.defaultCenter().addObserver(listener, getSelector(), message, toWatch); //NSNotificationCenter.defaultCenter().addObserver(null, getSelector(), null, toWatch); //System.err.println("Added observer of " + toWatch); } public void notice(NSNotification n) { if (!n.name().equals(NSWindow.WindowDidUpdateNotification)) System.out.println(n); } public static void test() { try { System.out.println("NSSelector: " + selector); //selector.invoke(new NoticeListener(), new Object[] { "test message" }); selector.invoke(new NoticeListener(), new Object[] { new NSNotification("TestNotice", "AnObject") }); } catch (Exception e) { e.printStackTrace(); System.exit(0); } } } public static class MacPanel extends NSPanel { public Panel awtPanel; private Window awtWindow; private static int cnt = 0; MacPanel(boolean textured) { super(new NSRect(100*cnt,100*cnt, 200,100), NSWindow.TitledWindowMask + NSWindow.ClosableWindowMask + //NSWindow.MiniaturizableWindowMask + // apparently not allowed w/UtilityWindows NSWindow.ResizableWindowMask + (textured ? NSWindow.TexturedBackgroundWindowMask : 0) + //NSWindow.UnifiedTitleAndToolbarWindowMask + // kills all deco on utility NSPanel.UtilityWindowMask + 0, NSWindow.Buffered, true); cnt++; NSButton close = standardWindowButton(NSWindow.CloseButton); NSButton iconify = standardWindowButton(NSWindow.MiniaturizeButton); NSButton zoom = standardWindowButton(NSWindow.ZoomButton); if (textured) { if (false) { // tends to lead to Bus Error / Seg Fault // maybe if we tried after construction? // Anyway to get the view to repack so // doesn't have empty space left over? iconify.removeFromSuperview(); zoom.removeFromSuperview(); } else { iconify.setHidden(true); zoom.setHidden(true); } return; } setBackgroundColor(NSColor.brownColor().colorWithAlphaComponent(0.5f)); //setAlphaValue(0.5f); setOpaque(false); //System.out.println("got button " + b + " w/image " + b.image()); setIgnoresMouseEvents(false); setAcceptsMouseMovedEvents(true); awtWindow = tufts.vue.gui.DockWindow.getTestWindow(); NSWindow awtNS = getWindow(awtWindow); awtNS.setOpaque(false); awtNS.setBackgroundColor(NSColor.whiteColor().colorWithAlphaComponent(0.02f)); //awtNS.setBackgroundColor(NSColor.brownColor().colorWithAlphaComponent(0.0f)); if (true) { awtWindow = null; // detach from the movement stuff awtNS.setHasShadow(true); awtNS.setLevel(NSWindow.ScreenSaverWindowLevel); } else { //awtNS.setPreservesContentDuringLiveResize(true); // does nothing for AWT //awtNS.setAlphaValue(0.5f); awtNS.setHasShadow(false); addChildWindow(awtNS, NSWindow.Above); } } public void test(int msg) { System.out.println("test " + msg); } public void test(String msg) { System.out.println("test " + msg); } public void testInvoke() { NSSelector method1 = new NSSelector("test", new Class[] {int.class}); NSSelector method2 = new NSSelector("test", new Class[] {new String().getClass()}); NSSelector method3 = new NSSelector("windowNotice", new Class[] { new String().getClass() }); // using "String.class" to define arg list gets us a wierd mac exception try { method1.invoke(this, new Object[] { new Integer(3) }); method2.invoke(this, new Object[] { "foo" }); method3.invoke(this, new Object[] { "hello notification" }); } catch (Exception e) { e.printStackTrace(); } System.exit(0); } public void sendEvent(com.apple.cocoa.application.NSEvent e) { System.out.println(e); super.sendEvent(e); } public void postEvent(com.apple.cocoa.application.NSEvent e, boolean tv) { System.out.println("post " + e + " " + tv); super.postEvent(e, tv); } public void setFrame(com.apple.cocoa.foundation.NSRect rect, boolean display, boolean animate) { System.out.println(rect); super.setFrame(rect, display, animate); // not seeing } public void setFrame(final com.apple.cocoa.foundation.NSRect r, boolean display) { System.out.println("setFrame " + r + " display=" + display); super.setFrame(r, display); if (awtPanel != null) { awtPanel.setLocation(0,0); awtPanel.setSize((int)r.width()-10, (int)r.height()-20); } else if (awtWindow != null) { // Must sync with AWT or java crashes in no time tufts.vue.VUE.invokeAfterAWT(new Runnable() { public void run() { awtWindow.setLocation((int)r.x(), (int)r.y()); awtWindow.setSize((int)r.width()-10, (int)r.height()-20); } }); } } public void setContentSize(com.apple.cocoa.foundation.NSSize size) { System.out.println(size); super.setContentSize(size); } } public static void test_macPanel(String args[]) { NoticeListener.test(); System.out.println("MacTest - Cocoa application & foundation classes"); tufts.vue.DEBUG.DOCK = true; tufts.vue.DEBUG.BOXES = true; /* javax.swing.JFrame frame = new javax.swing.JFrame("Swing Frame"); javax.swing.JPanel panel = new javax.swing.JPanel(); panel.add(new javax.swing.JLabel("Label")); panel.add(new javax.swing.JButton(new tufts.vue.VueAction("Action"))); frame.getContentPane().add(panel); frame.setSize(200,100); frame.show(); */ // Well, we can get AWT panels & components actually responding, // laying out, clicking, etc, inside an NSWindow, but not Swing components. // Actually, we can get a JButton to be placed & repsond to clicks, but it won't paint... Frame frame = new Frame("AWT Frame"); final Panel panel = new Panel(); //final javax.swing.JPanel panel = new javax.swing.JPanel(); panel.add(new Label("Label")); panel.setBackground(java.awt.Color.red); Button button = new Button("Button"); button.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent e) { System.out.println("actionPerformed: " + e); panel.setLocation(panel.getX() + 1, panel.getY() + 1); panel.setSize(panel.getWidth() + 1, panel.getHeight() + 1); panel.layout(); } }); panel.add(button); panel.add(new javax.swing.JButton(new tufts.vue.VueAction("Action"))); frame.add(panel); frame.setSize(200,100); frame.show(); // if we don't create a Java frame or window of some kind first, we get the following // error (note that we don't even have to show the frame): /* Exception in thread "main" NSInternalInconsistencyException: Error (1002) creating CGSWindow at com.apple.cocoa.application.NSWindow.orderFrontRegardless(Native Method) at MacTest.main(MacTest.java:22) */ final NSWindow nsw = new NSWindow(new NSRect(100,100,200,100), NSWindow.TitledWindowMask + NSWindow.ClosableWindowMask + NSWindow.ResizableWindowMask + NSWindow.UnifiedTitleAndToolbarWindowMask + //NSWindow.MiniaturizableWindowMask + //NSWindow.TexturedBackgroundWindowMask + 0, NSWindow.Buffered, true); nsw.center(); nsw.setTitle("An NSWindow"); //nsw.setBackgroundColor(NSColor.brownColor()); //nsw.setBackgroundColor(NSColor.blackColor()); //nsw.setShowsResizeIndicator(true); //nsw.orderFront(nsw); nsw.display(); nsw.orderFrontRegardless(); MacPanel p = new MacPanel(false); NoticeListener.addObserver(p, null); //p.testInvoke(); //p.setBackgroundColor(NSColor.brownColor()); p.setTitle("An NSPanel"); p.setShowsResizeIndicator(true); p.display(); p.orderFrontRegardless(); MacPanel textured = new MacPanel(true); textured.setTitle("NSPanel Textured"); textured.orderFrontRegardless(); //NSButton b = textured.standardWindowButton(NSWindow.CloseButton); //System.out.println("got button " + b + " w/image " + b.image()); System.out.println("\n"); dumpWindows(); NSWindow frameWin = getWindow(frame); NSView frameView = frameWin.contentView(); System.out.println("got NSView " + frameView); if (false) { frameWin.setContentView(null); p.setContentView(frameView); frame.hide(); } p.makeKeyWindow(); dumpWindows(); KEEP.add(p); KEEP.add(textured); //NSPanelDontGarbageCollectMe = p; // This prevent's GC. I think since main is exiting, these ref's are being GC'd, which // eventually closes out any NSWindows w/out a non-stack pointer (e.g., there's no // AWT like system that keeps references to everything). } }