package tufts.macosx;
import com.apple.cocoa.foundation.*;
import com.apple.cocoa.application.*;
import java.awt.*;
public class Screen
{
private static NSWindow sFullScreen;
public static void goBlack() {
goBlack(getFullScreenWindow());
}
public static void goBlack(NSWindow w) {
w.setAlphaValue(1);
w.orderFrontRegardless();
//w.orderFront(w);
}
public static void goClear() {
getFullScreenWindow().setAlphaValue(0);
}
public static void fadeToBlack() {
NSWindow w = getFullScreenWindow();
w.setAlphaValue(0);
w.orderFront(w);
cycleAlpha(0, 1);
}
public static void fadeFromBlack() {
fadeFromBlack(getFullScreenWindow());
}
public static void fadeFromBlack(NSWindow w) {
goBlack(w);
cycleAlpha(w, 1, 0);
//w.close(); bus-eror!
}
private static void cycleAlpha(float start, float end) {
cycleAlpha(getFullScreenWindow(), start, end, 32);
}
private static void cycleAlpha(NSWindow w, float start, float end) {
cycleAlpha(w, start, end, 32);
}
private static void cycleAlpha(NSWindow w, float start, float end, final int steps) {
System.out.println("cycleAlpha " + start + " -> " + end + " in " + steps + " steps");
float alpha;
float delta = end - start;
float inc = delta / steps;
for (int i = 0; i < steps; i++) {
alpha = start + inc * i;
w.setAlphaValue(alpha);
//System.out.println("alpha=" + alpha);
//try { Thread.sleep(10); } catch (Exception e) {} // give CPU a break
}
// if end value isn't 0, and you don't manuall close the window,
// it will grab all mouse events, locking out everything below it!
w.setAlphaValue(end);
System.out.println("cycleAlpha complete");
}
private static NSWindow getFullScreenWindow() {
if (sFullScreen == null) {
Dimension screen = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
sFullScreen = new NSWindow(new NSRect(0,0,screen.width,screen.height),
0,
NSWindow.Buffered,
true);
sFullScreen.setBackgroundColor(NSColor.blackColor());
//sFullScreen.setBackgroundColor(NSColor.redColor());
sFullScreen.setLevel(NSWindow.ScreenSaverWindowLevel); // this allows it over the mac menu bar
sFullScreen.setTitle("X");
}
return sFullScreen;
}
private static void showColorPicker() {
//NSColorPanel cp = new NSColorPanel();
NSColorPanel cp = NSColorPanel.sharedColorPanel();
cp.setShowsAlpha(true);
cp.orderFront(cp);
}
public static NSWindow getMainWindow() {
return NSApplication.sharedApplication().mainWindow();
}
public static NSMenu getMainMenu() {
return NSApplication.sharedApplication().mainMenu();
}
private static NSMenu firstMenu = null;
private static NSMenu cloneMenu = null;
public static void dumpMainMenu() {
NSMenu m = getMainMenu();
dumpMenu(m);
/*
if (firstMenu == null) {
firstMenu = m;
try {
cloneMenu = (NSMenu) m.clone();
dumpMenu(cloneMenu);
} catch (Exception ex) {
System.err.println(ex);
}
NSApplication.sharedApplication().setMainMenu(cloneMenu);
}
*/
//if (m != firstMenu)
//NSApplication.sharedApplication().setMainMenu(cloneMenu);
}
public static void dumpMenu(NSMenu m) {
System.out.println("Mac Main Menu: " + m + " visible="+m.menuBarVisible() + " hash=" + m.hashCode());
}
private static NSWindow MainWindow = null;
private static NSWindow FullWindow = null;
public static void keepWindowsOnTop() {
keepWindowsOnTop(null, false);
}
/** This method make's sure any visible windows are made as
* children of the application main window, which keeps them
* on top of it. As a side effect, this functionality on the
* mac also moves the windows along with the main window
* @param ensureWindow is for a window that may be in the
* process of showing, and thus claim's not to be visible
* yet, even tho it is. We make sure to process any window
* with this title even it claims not to be visible.
*
* Not that making a window a child also brings it to the
* front, if it's NOT already at the front, java will have
* no idea the window is visible, and it won't be pretty.
*
* This code is very specific to the frame title used in VUE.
*/
public static void keepWindowsOnTop(String ensuredWindow, boolean fullScreen) {
//dumpWindows();
NSApplication a = NSApplication.sharedApplication();
NSArray windows = a.windows();
NSWindow w;
// note that the only way at moment we can recognize the
// main vue frame & full screen window is by title,
// so be sure not to create any titles that start with
// the below checked strings. (getMainWindow() is
// returning a different object that the main vue frame)
if (true ||MainWindow == null || FullWindow == null) {
for (int i = 0; i < windows.count(); i++) {
w = (NSWindow) windows.objectAtIndex(i);
if (w.title().startsWith("VUE-FULL-WORKING"))
FullWindow = w;
else if (w.title().startsWith("VUE:"))
MainWindow = w;
}
}
for (int i = 0; i < windows.count(); i++) {
w = (NSWindow) windows.objectAtIndex(i);
if (w == MainWindow || w == FullWindow || w.title().startsWith("OLD-"))
continue;
// Ordering also forces the window visible! (and doesn't tell java, of course)
// Even when checking if visible mac java impl is putting other frames them right back
// behind as soon as the main frame gets activated...
//if (w != MainWindow && MainWindow != null && w.isVisible()) {
// todo: would be nice to bring forward the "Toolbar" from a dragged JToolBar,
// but when we go full screen, it appears invisible (prob because it's a dialog
// child of the vue frame, and it went invisible with it...) We can do this,
// but VUE will have to help us specifically.
if ((ensuredWindow != null && ensuredWindow.equals(w.title())) ||
(w.isVisible() && w.title().length() > 1))
{
if (fullScreen && FullWindow != null) {
System.out.println("ADDING AS CHILD OF FULL-SCREEN: #" + i + " [" + w.title() + "]");
FullWindow.addChildWindow(w, NSWindow.Above);
} else {
System.out.println("ADDING AS CHILD OF MAIN-WINDOW: #" + i + " [" + w.title() + "]");
MainWindow.addChildWindow(w, NSWindow.Above);
}
//w.orderFront(w); // causes some flashing
}
//if (w != MainWindow && MainWindow != null && w.isVisible())
// w.orderWindow(NSWindow.Above, MainWindow.windowNumber());
// Anothing above default level puts window over other apps
//if (!w.title().startsWith("VUE"))
//w.setLevel(NSWindow.FloatingWindowLevel);
//w.setLevel(NSWindow.StatusWindowLevel);
//w.setAlphaValue(0.75f);
//w.orderFront(w);
}
// Having seen the below once, we're nulling just in case.
// ObjCJava FATAL:
// jobjc_lookupObjCObject(): returning garbage collected java ref for objc object of class NSWindow
// ObjCJava Exit
w = null;
a = null;
windows = null;
}
public static void dumpWindows() {
NSApplication a = NSApplication.sharedApplication();
NSArray windows = a.windows();
for (int i = 0; i < windows.count(); i++) {
NSWindow w = (NSWindow) windows.objectAtIndex(i);
System.out.println("Window #" + (i>9?"":" ") + i + ": "
+ " visible=" + w.isVisible() + (w.isVisible()?" ":"")
+ " [" + w.title() + "]\t"
+ w
//+ " level=[" + w.level() + "] "
//+ " " + w.getClass() // always NSWindow
+ " frame=" + w.frame()
+ " NSView=" + w.contentView()
//+ " " w.contentView().getClass() // is always NSView
);
}
}
public static void makeMainInvisible() {
getMainWindow().setAlphaValue(0);
}
public static boolean isMainInvisible() {
return getMainWindow().alphaValue() == 0;
}
public static void fadeUpMainWindow() {
cycleAlpha(getMainWindow(), 0, 1);
}
public static void setMainAlpha(float alpha) {
getMainWindow().setAlphaValue(alpha);
}
public static void main(String args[])
{
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);
main.setBackgroundColor(NSColor.redColor());
main.setAlphaValue(0.5f);
fadeFromBlack();
//try { Thread.sleep(5000); } catch (Exception e) {}
}
public static void x_main(String args[])
{
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) {
nsw.setAlphaValue((float)alpha);
//try { sleep(10); } catch (Exception e) {} // give CPU a break
}
System.out.println("alpha="+(float)alpha);
for (alpha = 1; alpha >= 0; alpha -= 0.02) {
if (alpha < 0.01)
alpha = 0;
nsw.setAlphaValue((float)alpha);
//try { sleep(10); } catch (Exception e) {}
}
System.out.println("alpha="+(float)alpha);
if (!cycle)
return;
}
}
}.start();
}
}