PageRenderTime 47ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/src/fwt/java/Fwt.java

https://bitbucket.org/bedlaczech/fan-1.0
Java | 463 lines | 328 code | 43 blank | 92 comment | 61 complexity | 6aef8a1b380b45fc67b5954273fb4c2f MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. //
  2. // Copyright (c) 2008, Brian Frank and Andy Frank
  3. // Licensed under the Academic Free License version 3.0
  4. //
  5. // History:
  6. // 12 Jun 08 Brian Frank Creation
  7. //
  8. package fan.fwt;
  9. import java.io.*;
  10. import java.lang.reflect.Method;
  11. import java.util.*;
  12. import fan.sys.*;
  13. import fan.concurrent.*;
  14. import fan.sys.List;
  15. import org.eclipse.swt.*;
  16. import org.eclipse.swt.graphics.Color;
  17. import org.eclipse.swt.graphics.Cursor;
  18. import org.eclipse.swt.graphics.Font;
  19. import org.eclipse.swt.graphics.GC;
  20. import org.eclipse.swt.graphics.Image;
  21. import org.eclipse.swt.widgets.*;
  22. import org.eclipse.swt.widgets.Display;
  23. import org.eclipse.swt.widgets.Monitor;
  24. /**
  25. * Fwt manages the display resources.
  26. */
  27. public class Fwt
  28. {
  29. //////////////////////////////////////////////////////////////////////////
  30. // Lookup
  31. //////////////////////////////////////////////////////////////////////////
  32. /**
  33. * Get the Fwt for the current thread.
  34. */
  35. public static Fwt get()
  36. {
  37. return (Fwt)threadlocal.get();
  38. }
  39. /**
  40. * Get the main UI thread display.
  41. */
  42. public static Fwt main()
  43. {
  44. if (mainFwt == null) throw new IllegalStateException("Main UI thread not running");
  45. return mainFwt;
  46. }
  47. private static volatile Fwt mainFwt;
  48. private static ThreadLocal threadlocal = new ThreadLocal()
  49. {
  50. protected Object initialValue()
  51. {
  52. Fwt fwt = new Fwt();
  53. Actor.locals().set("gfx.env", FwtEnv.make());
  54. if (mainFwt == null) mainFwt = fwt;
  55. return fwt;
  56. }
  57. };
  58. private Fwt() {}
  59. //////////////////////////////////////////////////////////////////////////
  60. // Display
  61. //////////////////////////////////////////////////////////////////////////
  62. public void mainEventLoop(Shell shell)
  63. {
  64. eventLoop(shell);
  65. display.dispose();
  66. disposeAllColors();
  67. disposeAllFonts();
  68. disposeAllCursors();
  69. disposeAllImages();
  70. disposeScratchGC();
  71. }
  72. public void eventLoop(Shell shell)
  73. {
  74. while (!shell.isDisposed())
  75. {
  76. try
  77. {
  78. if (!display.readAndDispatch())
  79. display.sleep();
  80. }
  81. catch (Throwable e)
  82. {
  83. e.printStackTrace();
  84. }
  85. }
  86. }
  87. //////////////////////////////////////////////////////////////////////////
  88. // Color
  89. //////////////////////////////////////////////////////////////////////////
  90. /**
  91. * Map a Fan Color to an SWT color.
  92. */
  93. public Color color(fan.gfx.Color c)
  94. {
  95. if (c == null) return null;
  96. Color x = (Color)colors.get(c.argb);
  97. if (x == null)
  98. {
  99. int argb = (int)c.argb;
  100. x = new Color(display, (argb >> 16) & 0xff, (argb >> 8) & 0xff, argb & 0xff);
  101. colors.put(c.argb, x);
  102. }
  103. return x;
  104. }
  105. /**
  106. * Dispose the SWT color for the Fan Color.
  107. */
  108. public void dispose(fan.gfx.Color c)
  109. {
  110. if (c == null) return;
  111. Color x = (Color)colors.get(c.argb);
  112. if (x != null)
  113. {
  114. x.dispose();
  115. colors.remove(c.argb);
  116. }
  117. }
  118. /**
  119. * Dispose all cached colors.
  120. */
  121. public void disposeAllColors()
  122. {
  123. Iterator it = (Iterator)colors.values().iterator();
  124. while (it.hasNext()) ((Color)it.next()).dispose();
  125. colors.clear();
  126. }
  127. //////////////////////////////////////////////////////////////////////////
  128. // Font
  129. //////////////////////////////////////////////////////////////////////////
  130. /**
  131. * Map a Fan Font to an SWT Font.
  132. */
  133. public Font font(fan.gfx.Font f)
  134. {
  135. if (f == null) return null;
  136. Font x = (Font)fonts.get(f);
  137. if (x == null)
  138. {
  139. int style = SWT.NORMAL;
  140. if (f.bold) style |= SWT.BOLD;
  141. if (f.italic) style |= SWT.ITALIC;
  142. x = new Font(display, f.name, (int)f.size, style);
  143. fonts.put(f, x);
  144. }
  145. return x;
  146. }
  147. /**
  148. * Dispose the SWT font for the Fan Font.
  149. */
  150. public void dispose(fan.gfx.Font f)
  151. {
  152. if (f == null) return;
  153. Font x = (Font)fonts.get(f);
  154. if (x != null)
  155. {
  156. x.dispose();
  157. fonts.remove(f);
  158. }
  159. }
  160. /**
  161. * Dispose all cached fonts.
  162. */
  163. public void disposeAllFonts()
  164. {
  165. Iterator it = (Iterator)fonts.values().iterator();
  166. while (it.hasNext()) ((Font)it.next()).dispose();
  167. fonts.clear();
  168. }
  169. //////////////////////////////////////////////////////////////////////////
  170. // Cursor
  171. //////////////////////////////////////////////////////////////////////////
  172. /**
  173. * Map a Fan Cursor to a SWT Cursor.
  174. */
  175. public Cursor cursor(fan.fwt.Cursor c)
  176. {
  177. if (c == null) return null;
  178. Cursor swtCursor = (Cursor)cursors.get(c);
  179. if (swtCursor == null)
  180. {
  181. if (c.image != null)
  182. {
  183. Image swtImage = image(c.image);
  184. swtCursor = new Cursor(display, swtImage.getImageData(), (int)c.x, (int)c.y);
  185. }
  186. else
  187. {
  188. swtCursor = new Cursor(display, cursorStyle(c));
  189. }
  190. cursors.put(c, swtCursor);
  191. }
  192. return swtCursor;
  193. }
  194. /**
  195. * Return SWT style of Fan cursor
  196. */
  197. public int cursorStyle(fan.fwt.Cursor c)
  198. {
  199. if (cursorStyles == null)
  200. {
  201. cursorStyles = new HashMap();
  202. cursorStyles.put(fan.fwt.Cursor.defVal, SWT.CURSOR_ARROW);
  203. cursorStyles.put(fan.fwt.Cursor.pointer, SWT.CURSOR_HAND);
  204. cursorStyles.put(fan.fwt.Cursor.text, SWT.CURSOR_IBEAM);
  205. cursorStyles.put(fan.fwt.Cursor.crosshair, SWT.CURSOR_CROSS);
  206. cursorStyles.put(fan.fwt.Cursor.wait, SWT.CURSOR_WAIT);
  207. cursorStyles.put(fan.fwt.Cursor.help, SWT.CURSOR_HELP);
  208. cursorStyles.put(fan.fwt.Cursor.progress, SWT.CURSOR_APPSTARTING);
  209. cursorStyles.put(fan.fwt.Cursor.move, SWT.CURSOR_SIZEALL);
  210. cursorStyles.put(fan.fwt.Cursor.notAllowed, SWT.CURSOR_NO);
  211. cursorStyles.put(fan.fwt.Cursor.nResize, SWT.CURSOR_SIZEN);
  212. cursorStyles.put(fan.fwt.Cursor.sResize, SWT.CURSOR_SIZES);
  213. cursorStyles.put(fan.fwt.Cursor.wResize, SWT.CURSOR_SIZEW);
  214. cursorStyles.put(fan.fwt.Cursor.eResize, SWT.CURSOR_SIZEE);
  215. cursorStyles.put(fan.fwt.Cursor.swResize, SWT.CURSOR_SIZESW);
  216. cursorStyles.put(fan.fwt.Cursor.seResize, SWT.CURSOR_SIZESE);
  217. cursorStyles.put(fan.fwt.Cursor.nwResize, SWT.CURSOR_SIZENW);
  218. cursorStyles.put(fan.fwt.Cursor.neResize, SWT.CURSOR_SIZENE);
  219. }
  220. return (Integer)cursorStyles.get(c);
  221. }
  222. /**
  223. * Dispose the SWT cursor for the Fan Cursor.
  224. */
  225. public void dispose(fan.fwt.Cursor c)
  226. {
  227. if (c == null) return;
  228. Cursor x = (Cursor)cursors.get(c);
  229. if (x != null)
  230. {
  231. x.dispose();
  232. cursors.remove(c);
  233. }
  234. }
  235. /**
  236. * Dispose all cached cursors.
  237. */
  238. public void disposeAllCursors()
  239. {
  240. Iterator it = (Iterator)cursors.values().iterator();
  241. while (it.hasNext()) ((Cursor)it.next()).dispose();
  242. cursors.clear();
  243. }
  244. //////////////////////////////////////////////////////////////////////////
  245. // Images
  246. //////////////////////////////////////////////////////////////////////////
  247. /**
  248. * Map a Fan Image to an SWT Image.
  249. */
  250. public Image image(fan.gfx.Image i)
  251. {
  252. if (i == null) return null;
  253. Image x = (Image)images.get(i.uri);
  254. if (x == null)
  255. {
  256. if (i.file == null)
  257. {
  258. System.out.println("ERROR: image has no file: " + i);
  259. return null;
  260. }
  261. InputStream in = SysInStream.java(i.file.in());
  262. try
  263. {
  264. x = new Image(display, in);
  265. images.put(i.uri, x);
  266. }
  267. catch (Exception e)
  268. {
  269. System.out.println("ERROR: Cannot load image: " + i);
  270. e.printStackTrace();
  271. return null;
  272. }
  273. finally
  274. {
  275. try { in.close(); } catch (Exception e) {}
  276. }
  277. }
  278. return x;
  279. }
  280. /**
  281. * Dispose the SWT image for the Fan Image.
  282. */
  283. public void dispose(fan.gfx.Image i)
  284. {
  285. if (i == null) return;
  286. Image x = (Image)images.get(i.uri);
  287. if (x != null)
  288. {
  289. x.dispose();
  290. images.remove(i.uri);
  291. }
  292. }
  293. /**
  294. * Dispose all cached images.
  295. */
  296. public void disposeAllImages()
  297. {
  298. Iterator it = (Iterator)images.values().iterator();
  299. while (it.hasNext()) ((Image)it.next()).dispose();
  300. images.clear();
  301. }
  302. //////////////////////////////////////////////////////////////////////////
  303. // Scratch GC
  304. //////////////////////////////////////////////////////////////////////////
  305. /**
  306. * SWT makes it extremely paintful to work with font metrics,
  307. * so we use a scratch GC to do font metrics conveniently.
  308. */
  309. public GC scratchGC()
  310. {
  311. if (scratchGC == null) scratchGC = new GC(display);
  312. return scratchGC;
  313. }
  314. /**
  315. * Dispose the scratchGC if we've allocated one.
  316. */
  317. void disposeScratchGC()
  318. {
  319. if (scratchGC != null)
  320. {
  321. scratchGC.dispose();
  322. scratchGC = null;
  323. }
  324. }
  325. //////////////////////////////////////////////////////////////////////////
  326. // Monitors
  327. //////////////////////////////////////////////////////////////////////////
  328. public List monitors()
  329. {
  330. if (monitors == null)
  331. {
  332. Monitor[] m = display.getMonitors();
  333. Monitor pm = display.getPrimaryMonitor();
  334. List acc = new List(Type.find("fwt::Monitor"));
  335. for (int i=0; i<m.length; ++i)
  336. {
  337. fan.fwt.Monitor f = MonitorPeer.make(m[i]);
  338. acc.add(f);
  339. if (pm.equals(m[i])) primaryMonitor = f;
  340. }
  341. monitors = acc.ro();
  342. }
  343. return monitors;
  344. }
  345. public fan.fwt.Monitor primaryMonitor()
  346. {
  347. if (primaryMonitor == null) monitors();
  348. return primaryMonitor;
  349. }
  350. //////////////////////////////////////////////////////////////////////////
  351. // Platform
  352. //////////////////////////////////////////////////////////////////////////
  353. public static boolean isWindows() { return Env.cur().os().equals("win32"); }
  354. public static boolean isMac() { return Env.cur().os().equals("macosx"); }
  355. public static int os(String name)
  356. {
  357. try
  358. {
  359. Class c = Class.forName("org.eclipse.swt.internal." + SWT.getPlatform() + ".OS");
  360. return c.getField(name).getInt(null);
  361. }
  362. catch (Exception e)
  363. {
  364. e.printStackTrace();
  365. return 0;
  366. }
  367. }
  368. public static int osGet(Control w, int k)
  369. {
  370. try
  371. {
  372. Class c = Class.forName("org.eclipse.swt.internal." + SWT.getPlatform() + ".OS");
  373. Method m = c.getMethod("GetWindowLong", new Class[] { int.class, int.class });
  374. int h = osHandle(w);
  375. return ((Integer)m.invoke(null, new Object[] {h, new Integer(k)})).intValue();
  376. }
  377. catch (Exception e)
  378. {
  379. e.printStackTrace();
  380. return 0;
  381. }
  382. }
  383. public static void osSet(Control w, int k, int v)
  384. {
  385. try
  386. {
  387. Class c = Class.forName("org.eclipse.swt.internal." + SWT.getPlatform() + ".OS");
  388. Method m = c.getMethod("SetWindowLong", new Class[] { int.class, int.class, int.class });
  389. int h = osHandle(w);
  390. m.invoke(null, new Object[] {h, new Integer(k), new Integer(v)});
  391. }
  392. catch (Exception e)
  393. {
  394. e.printStackTrace();
  395. }
  396. }
  397. public static int osHandle(Control w)
  398. {
  399. try
  400. {
  401. return w.getClass().getField("handle").getInt(w);
  402. }
  403. catch (Exception e)
  404. {
  405. return 0;
  406. }
  407. }
  408. //////////////////////////////////////////////////////////////////////////
  409. // Fields
  410. //////////////////////////////////////////////////////////////////////////
  411. Display display = Display.getCurrent() == null ? new Display() : Display.getCurrent(); // SWT display
  412. HashMap colors = new HashMap(); // Int rgb -> Color
  413. HashMap fonts = new HashMap(); // fwt::Font -> Font
  414. HashMap images = new HashMap(); // Uri -> Image
  415. HashMap cursors = new HashMap(); // fwt::Cursor -> Cursor
  416. HashMap cursorStyles; // fwt::Cursor -> Integer
  417. GC scratchGC;
  418. List monitors;
  419. fan.fwt.Monitor primaryMonitor;
  420. }